/**************************************************************** * * * CSC209h 200 Summer * * * * Assignment 3 - PartB * * * * Student Name: Jeff Xing * * Student Number: 990555323 * * Instructor: Arthur Tateishi * * * ****************************************************************/ #include #include #include #include #include #include #include #define MAX_LINE 256 #define MAX_ARGS 8192 #define MAX_ARGS_BUF 32768 #define MAX_PIPES 20 #define READ 0 #define WRITE 1 char const *inFile[MAX_PIPES]; char const *outFile[MAX_PIPES]; char *args[MAX_PIPES][MAX_ARGS+1]; char argsbuf[MAX_ARGS_BUF]; char *bufptr; char const *homedir; int numPipe; void reset_args_buf(void) { bufptr = argsbuf; } char * alloc_str(char const *s) { char *p; strcpy(bufptr, s); p = bufptr; bufptr += strlen(bufptr)+1; return(p); } /***************************************************/ /* parse the commands into a two-dimensional array. */ int parse(char *buf) { int i; /* delimiter: space, tab, newline */ static char delims[] = { ' ', '\t', '\n', '\0'} ; char const *s, *p; int n=0; numPipe = 0; /* start with zero */ reset_args_buf(); /* Initially, assume no redirection */ for (i = 0; i < MAX_PIPES; i++) { inFile[i] = NULL; outFile[i] = NULL; } s = strtok(buf, delims); while(s && n < MAX_ARGS) { if (!strcmp(s, "|")){ /* increase row by one. */ args[numPipe][n] = NULL; numPipe++; n = 0; } else if (!strcmp(s, "<")) { if (!(p = strtok(NULL, delims))) return(-1); /* error. no input redir file argument */ inFile[numPipe] = alloc_str(p); } else if (!strcmp(s, ">")) { if (!(p = strtok(NULL, delims))) return(-1); /* error. no output redir file argument */ outFile[numPipe] = alloc_str(p); } else args[numPipe][n++] = alloc_str(s); s = strtok(NULL, delims); } args[numPipe][n] = NULL; return(n); } /*************************************************************/ /* Process the input commands. */ int process(void) { int i, j; int pid; int status; int fd[MAX_PIPES][2]; /* pipe. */ for (i = 0; i < numPipe; i++) pipe(fd[i]); /* fork, dup, exac. */ for (i = 0; i <= numPipe; i++) { pid = fork(); if (pid != 0) /* parent side of fork */ continue; if (i != 0 ) /* duplicate used end to stdin. */ dup2(fd[i-1][READ], 0); if (i != numPipe) /* duplicate used end to stdout. */ dup2(fd[i][WRITE], 1); /* close all the children pipes. */ for (j = 0; j < numPipe; j++) { close(fd[j][READ]); close(fd[j][WRITE]); } if (inFile[i]) { close(fd[i][READ]); fd[i][WRITE] = open(inFile[i], O_RDONLY); if (fd[i][WRITE] == -1) { perror(inFile[i]); exit(-1); } } if (outFile[i]) { close(fd[i][WRITE]); fd[i][READ] = open(outFile[i], O_CREAT|O_WRONLY|O_TRUNC, S_IAMB); if (fd[i][READ] == -1) { perror(outFile[i]); exit(-1); } } execvp(args[i][0], args[i]); perror(args[i][0]); /* error occured on exac */ exit(-1); } /* close all parents pipes */ for (i = 0; i < numPipe; i++) { close(fd[i][READ]); close(fd[i][WRITE]); } /* wait for their children to die. */ for (i = 0; i <= numPipe; i++) wait(&status); return 0; } /****************************************************/ /* Program starts here. */ int main(int argc, char *argv[]) { int ret; char buf[MAX_LINE]; homedir=getenv("HOME"); if (!homedir) homedir="No HOME set!"; /* Read shell input until end-of-file reached */ while(!feof(stdin)) { /* Output prompt. */ printf("pipesh> "); /* Read line of input */ if (fgets(buf, MAX_LINE, stdin) == NULL) continue; /* Call subroutine to parse arguments */ ret = parse(buf); if (ret < 0) { fprintf(stderr, "Syntax error.\n"); continue; /* no command to exec */ } else if (ret == 0) { continue; } /* process built-in commands */ if (!strcmp(args[0][0], "cd")) { char const *dir = args[0][1]; if (!dir) dir = homedir; if (chdir(dir)) perror(dir); continue; } /* process typed-in commands. */ process(); } exit(0); }