#include #include #include #include #include struct item { char *prog_name; int pid; struct item *next; }; static int check_delimiter(char *arg) { return !strncmp(arg, ";;", 3); } static void fill_in_item(char *arg, int pid, struct item **list) { struct item *tmp_item = malloc(sizeof(struct item)); tmp_item->pid = pid; tmp_item->prog_name = arg; tmp_item->next = *list; *list = tmp_item; } static void make_new_fork(int fd[2], char **begin_pos, struct item **list, int *process_counter) { static int first_process_flag = 0; int pid = fork(); if(pid == -1) { perror("fork error"); exit(1); } if(pid) { fill_in_item(*begin_pos, pid, list); ++*process_counter; } else { /* first process writes to pipeline */ if(first_process_flag == 0) { close(fd[0]); dup2(fd[1], 1); close(fd[1]); /* second process reads */ } else { close(fd[1]); dup2(fd[0], 0); close(fd[0]); } execvp(*begin_pos, begin_pos); perror(*begin_pos); exit(1); } ++first_process_flag; } static char* find_name_by_pid(int pid, struct item *list) { while(list) { if(list->pid == pid) return list->prog_name; list = list->next; } return NULL; } static void clear_list(struct item *list) { struct item *tmp; while(list) { tmp = list; list = list->next; free(tmp); } } int main(int argc, char **argv) { int fd[2]; int status, pid, process_counter; char **begin_pos, **end_pos; struct item *list = NULL; process_counter = 0; pipe(fd); if(argc == 1) { fprintf(stderr, "too few arguments\n"); return 1; } ++argv; for(begin_pos = argv, end_pos = begin_pos + 1; *end_pos != NULL; ) { if(check_delimiter(*end_pos)) { *end_pos = NULL; make_new_fork(fd, begin_pos, &list, &process_counter); begin_pos = end_pos + 1; end_pos = begin_pos + 1; } else ++end_pos; } make_new_fork(fd, begin_pos, &list, &process_counter); close(fd[0]); close(fd[1]); for( ; process_counter; --process_counter) { pid = wait(&status); if(WIFEXITED(status) && WEXITSTATUS(status) == 0) printf("%s\n", find_name_by_pid(pid, list)); } clear_list(list); return 0; }