#include #include #include #include #include #include int main(int argc, char* argv[]); void print_time(); void print_time() { struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); printf("%d\n", tv.tv_usec); } int main(int argc, char* argv[]) { const char* verbose_flag = "-v"; int verbose = 0; int arg_str_index = 0; if (argc == 1) { verbose = 0; arg_str_index = 0; } else if (argc == 2) { if (strcmp(argv[1], verbose_flag) == 0) { verbose = 1; arg_str_index = 0; } else { verbose = 0; arg_str_index = 1; } } else if (argc == 3 && (strcmp(argv[1], verbose_flag) == 0)) { verbose = 1; arg_str_index = 2; } else { fprintf(stderr, " Usage: %s [%s] [msg_word]\n", argv[0], verbose_flag); exit(EXIT_FAILURE); } // setup one-way pipe as a file descriptor: // index 0 is read, index 1 is write enum { READ_END, WRITE_END }; int fd[2]; int p = pipe(fd); if (p == -1) { perror("Pipe not created."); exit(EXIT_FAILURE); } // create a child process // fork returns twice: // 1. in the parent (return value the child's PID) // 2. in the child (return value 0) pid_t fork_ret = fork(); if (fork_ret == -1) { perror("Couldn't fork."); exit(EXIT_FAILURE); } else if (fork_ret == 0) { /* THE CHILD */ if (verbose) { printf(" This is the child.\n"); } close(fd[WRITE_END]); // child won't write anyone anyway // read from the pipe's read end // one char at a time into c; // for each read, write c to stdout // finish with newline char c; if (verbose) { while (read(fd[READ_END], &c, 1) > 0) { write(STDOUT_FILENO, &c, 1); } write(STDOUT_FILENO, "\n", 1); } else { while (read(fd[READ_END], &c, 1) > 0) ; } close(fd[READ_END]); // child done reading print_time(); exit(EXIT_SUCCESS); } else { /* THE PARENT */ if (verbose) { printf(" Parent speaking: child has PID %d.\n", fork_ret); } close(fd[READ_END]); // parent won't read anything // write the first argument passed at invocation // or, if none, write a simple greeting char* s = (arg_str_index ? argv[arg_str_index] : "Message: Hi"); print_time(); write(fd[WRITE_END], s, strlen(s)); close(fd[WRITE_END]); // parent done writing wait(NULL); // parent will wait for the child to terminate exit(EXIT_SUCCESS); } return 0; }