I'm trying to create a simple shell program in C. What I need it to do is provide the user with a prompt in which they can run other local programs. I can do that part fine, using a fork() in which the parent process waits() on the child,and the child execvp()'s the program.
However, if the '&' character is appended to the end of the user's command, I need their program to run in the background, meaning I need the parent to NOT wait on the child process but instead immediately return the prompt to the user, while allowing the background process to continue to run, but not allowing it to display anything on the screen. I just want to be able to check that it still exists via ps command.
I tried to understand the idea behind using fork() to create a child, then have the child fork() again to create a grandchild of sorts, then immediately exit()-ing the child process. i.e., orphan the grandchild. Supposedly this allows the parent to still wait on the child, but since the child effectually ends almost immediately, it's like it doesn't wait at all? Something about zombie madness? I don't know. Several sites I've come across seem to recommend this as a way to run a process in the background.
However, when I try to do this, I get wild things happening with the flow of the program, the 'background' process continues to display input on the screen, and I'm really not sure where to go from here.
This is my implementation of the code, which I'm sure is quite wrong. I'm just wondering if this whole grandchild thing is even the route I need to take,and if so, what's wrong with my code?
36 int main(int argc, char *argv[])
37 {
38 char buffer[512];
39 char *args[16];
40 int background;
41 int *status;
42 size_t arg_ct;
43 pid_t pid;
44
45 while(1)
46 {
47 printf("> ");
48 fgets(buffer, 512, stdin);
49 parse_args(buffer, args, 16, &arg_ct);
50
51 if (arg_ct == 0) continue;
52
53 if (!strcmp(args[0], "exit"))
54 {
55 exit(0);
56 }
57
58 pid = fork(); //here I fork and create a child process
61
62 if (pid && !background) //i.e. if it's the parent process and don't need to run in the background (this is the part that seems to work)
63 {
64 printf("Waiting on child (%d).
", pid);
65 pid = wait(status);
66 printf("Child (%d) finished.
", pid);
67 }
68 else
69 {
70 if (background && pid == 0) { //if it's a child process and i need to run the command in background
71
72 pid = fork(); //fork child and create a grandchild
73 if (pid) exit(0); //exit child and orphan grandchild
74
75 execvp(args[0], args); //orphan execs the command then exits
76 exit(1);
77
78 } else exit(0);
79 }
80 }
81 return 0;
82 }
P.S. To be clear, I need the process that I'm running in the background to never make a sound again, even if it's got an infinite loop of print statements or something. I just want to make sure that it is still running in the background via ps -a or something.
Sorry for the confusing explanation I just don't know how to explain it any better.
Thanks in advance
P.P.S I'll be implementing it so that each subsequent command will determine the boolean value of 'background', sorry for the confusion
See Question&Answers more detail:
os