#include #include #include #include #include #include #include #include typedef struct command { char **argv; int argc; } command; enum{ READ = 0, WRITE = 1, }; int *create_pipefd(int num){ int *pipes = malloc(sizeof *pipes * num * 2); // allocate memory for the pipes if(pipes == NULL){ perror("malloc() failed"); exit(EXIT_FAILURE); } for(size_t i = 0; i < num; i++){ if(pipe(pipes + i*2) == -1){ // create the pipes perror("pipe() failed"); exit(EXIT_FAILURE); } } return pipes; } bool configure_pipes(int *pipefd, int command, int pipe_count){ if(command == 0){ // first command return dup2(pipefd[command*2 + WRITE], STDOUT_FILENO) != -1; }else if(command == pipe_count){ // last command return dup2(pipefd[(command-1)*2 + READ], STDIN_FILENO) != -1; }else { return dup2(pipefd[command*2 + WRITE], STDOUT_FILENO) != -1 && dup2(pipefd[(command-1) * 2 + READ], STDIN_FILENO) != -1; } } int main(){ int pipe_count = 2; int command_count = 3; command *commands = malloc(3 * sizeof(command)); commands[0].argv = malloc(4096 * sizeof *commands[0].argv); commands[1].argv = malloc(4096 * sizeof *commands[1].argv); commands[2].argv = malloc(4096 * sizeof *commands[2].argv); #define BUFFER_SIZE 4096 #define COMMAND_SIZE 512 for(size_t x = 0; x < BUFFER_SIZE; x++){ commands[0].argv[x] = malloc(COMMAND_SIZE*sizeof(char)); // malloc each element of the array seperately memset(commands[0].argv[x], 0, COMMAND_SIZE); // zero out the memory commands[1].argv[x] = malloc(COMMAND_SIZE*sizeof(char)); // malloc each element of the array seperately memset(commands[1].argv[x], 0, COMMAND_SIZE); // zero out the memory commands[2].argv[x] = malloc(COMMAND_SIZE*sizeof(char)); // malloc each element of the array seperately memset(commands[2].argv[x], 0, COMMAND_SIZE); // zero out the memory } memcpy(commands[0].argv[0], "/bin/w", strlen("/bin/w")); commands[0].argv[1] = NULL; commands[0].argc = 1; memcpy(commands[1].argv[0], "/bin/grep", strlen("/bin/grep")); memcpy(commands[1].argv[1], "tty2", strlen("tty2")); commands[1].argv[2] = NULL; commands[1].argc = 2; memcpy(commands[2].argv[0], "/bin/grep", strlen("/bin/grep")); memcpy(commands[2].argv[1], "t", strlen("t")); commands[2].argv[2] = NULL; commands[2].argc = 2; printf("commands[1].argv[1]: %s\n", commands[0].argv[0]); printf("pipe_count 2: %d\n", pipe_count); printf("command_count 2: %d\n", command_count); for (int i = 0; i < command_count; i++) { for(int j = 0; j < commands[i].argc+1; j++){ fprintf(stderr, "commands[%d].argv[%d]: %s\n", i, j, commands[i].argv[j]); } } int* pipes = create_pipefd(pipe_count); for(size_t i = 0; i < command_count; i++){ pid_t child = fork(); switch (child) { case -1: fprintf(stderr, "Failed to fork()"); exit(EXIT_FAILURE); case 0: /* child */ if(configure_pipes(pipes, i, pipe_count) == false){ perror("configure_pipes failed\n"); return 1; } for (size_t j = 0; j < pipe_count; j++) { close(pipes[j*2+READ]); close(pipes[j*2+WRITE]); } free(pipes); if(execvp(commands[i].argv[0], commands[i].argv) != 0){ perror("execvp() failed"); exit(EXIT_FAILURE); } break; default: break; } } }