Im currently working on a class work in the Introduction to Operative Systems course, and we are asked to build a simple command interpreter in C. For this interpreter, if we put '&' before a comand we execute it in the background and if we put ';' we execute it as usual (in the foreground). We are using fork and process management functions, so when we are in the parent process, if we typed ';' we simply wait until the child process (executing the comand, for example pwd), and if we put '&' we just dont wait and we break from the switch-case on where we are.
this is the code:
err = get_arguments(buf, n, arg, MAXARG); //if we type & sleep 5 we get the sleep 5 in the arg
id = fork();
switch (id){
case -1:
errore("fork");
break;
case 0: /* child process */
/* execute the command using execvp */
pid = getpid();
pid_parent = getppid();
if(buf[0] == '&') {
printf("-U------- Child: just created (PID %d - Parent PID: %d): now executing'%s ...' in the background...\n",
pid, pid_parent, arg[0]);
} else if(buf[0] == ';') {
printf("-U------- Umea naiz: sortu berria (PID %d - Parent PID: %d): orain '%s ...' exekutatzera aurreko planoan...\n",
pid, pid_parent, arg[0]);
}
execvp(arg[0], arg);
printf("-U------- Child (PID %d): i'm here only if an error has ocurred\n",
pid);
errore("exec");
break;
default: /* parent */
pid_child = id;
pid = getpid();
printf("-G------- Parent (PID %d): child process '%s ...' (PID %d) started \n",
pid, arg[0], pid_child);
if(buf[0] == '&') { // if we want to execute in the background
break; //break and don't wait for the child to stop
} else if(buf[0] == ';') { // if it's in the foreground
/* wait until child finishes */
pid_finished = wait(&status);
if ( pid_finished != pid_child) {
errore("wait");
} else {
if (WIFEXITED(status)){ // get the return code
child_return_code = WEXITSTATUS(status);
printf("-G------- Parent (PID %d): a child process (PID %d) has finished with the %d return code\n",
pid, pid_finished, child_return_code);
}
};
}
break;
}
}
for (n = 0; n < BUFSIZE; n++) buf[n] = '\0';
write(1, "prompt$ ", 9); //write the prompt again
When I write ; pwd for example, it obviously works great. How ever, i want the parent process to know when a child process that has been executed in the background, has finished. And when if happens, print it's id and the return code.
I don't know how to do this, because when execvp is used, the code that comes after it only gets executed when an error happens. So how can I know when this child process has finished in the background?
My code was in spanish so maybe something is spelled wrong, I tried my best.
Thank you so much!