C exec multi commands - c

i am struggling and your input would be really appreciated. i'm trying to chain arguments to the command line using exec and an array to hold the arguments. the problem comes when I try to chain more than one command. tried using an ";" to separate each command but that does not seem to be working.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>enter code here
int main(){
int proc1 = fork();
char*myargv[16];
myargv[0]="/bin/ls";
myargv[1]="-F;";
myargv[2]="pwd";
myargv[3]=NULL;
if(proc1==0){
execve(myargv[0],myargv,NULL);
exit(1);
}else{
wait(NULL);
printf("This wlways last");
}
return 0;
}

Related

How to enable the usage of fork(), wait() and execv()

I have an assignment to do which requires me to use fork(), wait and execv(). However, every time I try to use them I get an error that they aren't defined. Here is my code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
fork();
printf("Hello world!\n");
return 0;
}
Here is the errors I get:
I would appreciate it if anyone could help.

Reading and writing into the same file using a named pipe in C

More specifically, the program is supposed to emulate the bash command cat file| grep $keyword > file.
What I've done is: In the parent I read every character from the file and format them into lines which I then send to the named pipe, then in the child write the lines containing the keyword into the original file.
However, I receive a segmentation fault error when attempting to read the second character from the original file, which I assume is because the parent is waiting for the child to write in the original file instead of instead of reading the contents of said file.
Any help with the implementation/explanation of why exactly the error occurs would be great.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
char key[20], *c,line[40];
int fd,fd_r,fd_w,fd_fr,fd_fw,counter=0;
int main(){
pid_t pid;
mkfifo("fifo1",0777);
fgets(key,10,stdin);
int k=0;
if ((pid=fork()) < 0)
perror("err_fork");
if(pid){ //PARENT
printf("%d\n",fd_r=open("prog.c",O_RDONLY));
printf("%d\n",fd_fw=open("fifo1",O_WRONLY));
while(read(fd_r,c,1)){
line[k++]=(*c);
while(read(fd_r,c,1) && ((*c)!='\n'))
line[k++]=(*c);
line[k]=0;
write(fd_fw,line,strlen(line)+1);
memset(line,0,sizeof(line));
}
close(fd_r);
close(fd_fw);
}
else{ //CHILD
printf("%d\n",fd_w=open("prog.c",O_WRONLY));
printf("%d\n",fd_fr=open("fifo1",O_RDONLY));
while(read(fd_fr,line,sizeof(line))){
c=strstr(line,key);
if(c)
write(fd_w,line,strlen(line)+1);
}
close(fd_w);
close(fd_fr);
}
unlink("fifo1");
}
You're segfaulting because you're trying to read a byte into c. However, c is an uninitialized global pointer and thus it's equal to NULL. Trying to read data at that location is therefore an invalid use of memory.
What you do instead is declare
char c;
and then
read(fd_r,&c,1)

Set display before indicate path into (execlp)

I need to work with multiple displays in execlp calls (). I'm trying this:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("calling to execlp:\n\n");
execlp("DISPLAY=:0 /usr/bin/qtdisplay","qtdisplay", "-r", NULL);
execlp("DISPLAY=:1 /usr/bin/qtdisplay","qtdisplay", "-r", NULL);
printf("fail!");
exit(0);
}
But this fails, with the following message: execlp: No such file or directory
Is there any way to work with the displays?
Try system() instead, it'll start a new child process and call exec() from there. Also, it handles shell command-line constructs by calling a shell and handing your shell construct to that shell, like this:
system("DISPLAY=:0; /usr/bin/qtdisplay -r");
Also, learn to check return codes from functions like this, and do some sane action (like print an error message):
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int rc;
rc = system("DISPLAY=:0; /usr/bin/qtdisplay -r");
if (rc == -1) {
perror("error starting qtdisplay on :0");
exit(1);
}
rc = system("DISPLAY=:1; /usr/bin/qtdisplay -r");
if (rc == -1) {
perror("error starting qtdisplay on :1");
exit(1);
}
exit(0);
}
If you want these two commands to be run in parallel (not one after the other), you should use command-lines like this:
system("DISPLAY=:0; /usr/bin/qtdisplay -r &");

Unix fifo client to server

I want to use a pair of Unix FIFOs in such manner that:
a client sends to a server a file name and
the server returns to the client: the number of words, lines and bytes from the given file.
Could you please help?
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int nr,s2c,c2s,c,d,e;
char a[20];
c2s=open("fifo1",O_WRONLY);
s2c=open("fifo2",O_RDONLY);
printf("give file name \n");
scanf("%s",a);
nr=strlen(a);
write(c2s,&nr,sizeof(int));
write(c2s,&a,sizeof(nr));
read(s2c,&c,sizeof(int));
read(s2c,&d,sizeof(int));
read(s2c,&e,sizeof(int));
close(c2s);
close(s2c);
return 0;
}
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int nr,s2c,c2s,c,d,e;
char a[20];
FILE* f;
c2s=open("fifo1",O_RDONLY);
s2c=open("fifo2",O_WRONLY);
read(c2s,&nr,sizeof(int));
read(c2s,&a,sizeof(nr));
f=fopen(a,"r");
if(fork()==0)
{
printf("result is: \n");
execl("/usr/bin/wc","wc",c,d,e,NULL);
}
wait(0);
write(s2c,&c,sizeof(int));
write(s2c,&d,sizeof(int));
write(s2c,&e,sizeof(int));
close(c2s);
close(s2c);
printf("\n FINISH \n");
return 0;
}
I have done some improvements but still it doesn't work properly.
In the fork'ed part of the server, redirect the standard input and output of wc with
dup2(c2s, STDIN_FILENO);
dup2(s2c, STDOUT_FILENO);
Then exec it with
execl("/usr/bin/wc", "wc", NULL);
Don't pass the file descriptors as arguments to execl. It expects strings (char const*), not int.
See dup2 in the POSIX standard to understand how this works.
Note that wc writes strings of characters to its output. You are trying to read them as if they are binary numbers. This will lead to confusion - especially as you do not check that the read calls worked correctly.
Actually, general comment - you should check many more of your system calls.
You also have to ensure that your processes do not block when opening the FIFOs. You should be OK; you have the processes open 'fifo1' for reading and writing, and then 'fifo2'. I think that forces a correct order on things.
You only write 4-letter file names correctly on the pipe.

seteuid() not working. Reason?

I'm completely new to C and I use it very rarely. This time i need it for a university project. I have to write a small c app that tests some modifications we made on the Linux kernel (on the scheduler).
Inside the script I'd like to switch to another user to see the distribution of CPU times among the different users. So I start my small C prog with root rights (i.e. with sudo ./myapp). Inside the prog - after I performed some operations which need root rights - I would like to switch back to another uid by calling seteuid(1000) or setuid(1000) where 1000 is the ID of an existing user (the one I used to log on). However the call doesn't seem to have any effect, it doesn't throw any exception neither.
Here's a sample I wrote, just to test the uid switching:
#define _POSIX_SOURCE
#include <pwd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <unistd.h>
#include <string>
#include <time.h>
using namespace std;
int main(int argc, char *argv[])
{
int uid;
struct passwd *p;
if ((p = getpwuid(uid = getuid())) == NULL){
perror("getpwuid() error");
exit(1);
}
printf("***************************************\n");
printf("Executing user: %s (%d)\n", p->pw_name, p->pw_uid);
printf("***************************************\n");
seteuid(1000);
if ((p = getpwuid(uid = getuid())) == NULL){
perror("getpwuid() error");
exit(1);
}
printf("***************************************\n");
printf("Executing user: %s (%d)\n", p->pw_name, p->pw_uid);
printf("***************************************\n");
return 0;
}
Does anyone know why it won't work?? Any help is highly appreciated! Thx
//Edit:
Corrected code as mentioned by chsh
I think it is working just fine, there's just a problem with the logic in the code because you're capturing the value of getuid() into the passwd struct, and then just displaying it twice without retrieving it again after calling seteuid().

Resources