Prerequisite: Write a program to query the user for two input lines. Each input line must be a unix command with arguments allowed. For example, input 1 may be ls -l , and input 2 may be more . Then the program will create a channel and two child processes. The first child process will run the command specified in the first input. It will be output to the pipe instead of the standard output. The second child process will run the command specified in the second input. It will accept its input from the pipe, not from standard input. The parent process will wait until his two children are finished, then all this will happen again. Execution stops when the โ@โ character is entered as the first command. Here is the code I have:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> int main(){ /* Program Termination Symbol */ const char terminate = '@'; /* String delimiter */ const char delimiter = ' '; /* Pipe file ID */ int fileID[2]; /* Parent ID */ int pid1, pid2; /* String token */ char * token, * token2; /* User input */ char * user_input, line[100]; user_input = (char *) malloc(100); /* Unix Commands */ char * command1[10], *command2[10]; for (int i=0; i<10; i++) { command1[i] = (char *)malloc(100*sizeof(char)); command2[i] = (char *)malloc(100*sizeof(char)); } /* Begin main program logic */ printf("Please enter the first command: \n"); user_input = gets(line); while (user_input[0] != terminate) { token = (char *) malloc(100*sizeof(char)); for (int i=0; i<10; i++) { if (i == 0) { token = strtok(user_input, &delimiter); } else { token = strtok(NULL, &delimiter); } if (token != NULL) { strcpy(command1[i], token); } else { command1[i] = 0; } } printf("Please enter the second command: \n"); user_input = gets(line); token2 = (char *) malloc(100*sizeof(char)); for (int i=0; i<10; i++) { if (i == 0) { token2 = strtok(user_input, &delimiter); } else { token2 = strtok(NULL, &delimiter); } if (token2 != NULL) { strcpy(command2[i], token2); } else { command2[i] = 0; } } /* Pipe and execute user commands */ /* Create pipe */ pipe(fileID); /* Create child processes */ pid1 = fork(); if (pid1 != 0) { pid2 = fork(); } /* First child process */ if (pid1 == 0) { dup2(fileID[1], 1); execvp(command1[0], command1); } /* Second child process */ if (pid2 == 0) { dup2(fileID[0], 0); execvp(command2[0], command2); } /* Wait for children to terminate */ wait(&pid1); wait(&pid2); /* Repeat */ printf("Please enter the first command: \n"); user_input = gets(line); } return 0; }
The problem I am facing is related to my expectations. If I have one and the other that makes sense for me (one wait for one child), then the program freezes after the first channel is completed. If I delete the second wait, the program will start the cycle again, but will not accept keyboard input except input, and will issue segfault. So, with both expectations, entry and exit ...
Please enter the first command: ls Please enter the second command: more Pipe Pipe.c Pipe.c~
... and then it blocks. If I remove the second wait, the input / output will be ...
Please enter the first command: ls Please enter the second command: more Pipe Pipe.c Pipe.c~ Please enter the first command: (I hit enter, nothing else will work) Segmentation fault
Anyone have any suggestions? This is clearly related to the expectation of two processes, but I do not understand how to handle this.
This program is now 100% functional - thank you very much for your help, everyone! Stack overflow was one of the best resources on the Internet. Thank you so much for taking the time to look at my code and give me your suggestions.