#include #include #include #include #include #include #include #include #include #define MAX_PATH 2048// Maximal full path length we support #define MAX_COMMANDS 8 #define MAX_COMMAND_LENGTH 48 int main (int argc, char **argv) { int i = 0; int j = 0; int k = 0; //test only int fork_num = 0; int status; char file_name[MAX_PATH]; char file_path[MAX_PATH + 1]; FILE* cmd_file; struct stat file_stat; char *cmd_hldr;//[MAX_COMMAND_LENGTH]; char *cmd_ary[MAX_COMMANDS]; //add another dimension here for each arg char *delimiter = " "; pid_t childpid; char *cmd_to_fork[MAX_COMMAND_LENGTH]; int totalpipeid[16];//Stores the ids of the pipes //check if there is enough arguements (a filename and nothing more) if (argc != 2) { fprintf(stderr, "invalid number of arguments, please supply a filename\n"); perror("Error"); exit(1); } strcpy(file_name, argv[1]); strcpy(file_path, "./"); strcat(file_path, file_name); // obtain file status if (stat(file_path, &file_stat) == -1) { // error getting stat fprintf(stderr, "%s cannot be read properly (cannot get stat)\n", file_name); perror ("Error"); exit(1); } //check if the filename names a regular file if(S_ISREG(file_stat.st_mode)) { //printf("'%s' is regular file at '%s'\n", file_name, file_path); cmd_file = fopen(file_path, "r"); //make sure file opens ok if (!cmd_file) { fprintf(stderr, "Failed opening file %s for reading \n", file_path); perror ("Error"); exit(1); } cmd_hldr = malloc(MAX_COMMAND_LENGTH); //loop to read each command from the file, into cmd_ary while((fgets(cmd_hldr, MAX_COMMAND_LENGTH, cmd_file)) != NULL) { if(fork_num > 7) { fprintf(stderr, "File contains too many commands, will only perform the first %d\n", MAX_COMMANDS); perror ("Error:"); break; } //unessecary, don't need to remove newline from command strings /*for(i = 0; i < MAX_COMMAND_LENGTH;i++) { //printf("char %d of command %d is %c\n", i, fork_num, cmd_hldr[i]); if (cmd_hldr[i] == "\n") { cmd_hldr[i] = " "; //cmd_hldr[i+1] = " "; break; } }*/ cmd_ary[fork_num] = malloc(strlen(cmd_hldr) + 1); strcpy(cmd_ary[fork_num], cmd_hldr); //printf("command number %d is %s\n", fork_num, cmd_ary[fork_num]); fork_num++; } if (fclose(cmd_file) == -1) { fprintf(stderr, "unable to close [%s]\n", file_path); perror("Error"); exit(1); } } //file named by filename is not a regular file, quit else { fprintf(stderr, "%s is not a regular file\n", file_name); perror("Error"); exit(1); } /************************************* * file is open now, next read * commands one by one, forking them * to seperate processes ************************************/ //In case there is only a single command if (fork_num == 1) { childpid = fork(); int j = 0; if (childpid == 0) { //Store the program name for execution cmd_hldr = strtok(cmd_ary[i], delimiter); char program_name[strlen(cmd_hldr)]; strcpy(program_name,cmd_hldr); printf("program name is %s\n",cmd_hldr); //Store the arguments for the program while (( cmd_hldr = strtok(NULL, delimiter)) != NULL) { j++; cmd_to_fork[j] = malloc(strlen(cmd_hldr) + 1); strcpy(cmd_to_fork[j], cmd_hldr); printf("Arg %d of command [%s] is [%s]\n", j, program_name, cmd_to_fork[j]); } execvp(program_name, cmd_to_fork); perror("I could not call exec for some reason"); return 0; } wait(&status); if (WIFEXITED(status) != 1) { perror("Failure to Exit safely"); } return 1; } //Build up an array of pipeids /*typedef int* my_type; my_type pipeids[fork_num]; int t; for (t =0; t < 1; t++) { int pipenum[2]; if (pipe(pipenum) == -1) { perror("Failure of pipe"); } pipeids[t] = pipenum; }*/ //Iterate over all the commands for(i = 0; i < fork_num; i++) { //printf("executing command number %d which is %s\n", i, cmd_ary[i]); int j = 0; //Store the program name for execution cmd_hldr = strtok(cmd_ary[i], delimiter); char program_name[strlen(cmd_hldr)]; strcpy(program_name,cmd_hldr); //printf("program name is %s\n",cmd_hldr); //Store the arguments for the program while (( cmd_hldr = strtok(NULL, delimiter)) != NULL) { j++; cmd_to_fork[j] = malloc(strlen(cmd_hldr) + 1); strcpy(cmd_to_fork[j], cmd_hldr); //printf("Arg %d of command [%s] is [%s]\n", j, program_name, cmd_to_fork[j]); } int pipeid[2]; if (pipe(pipeid) == -1) { perror("Piping failed"); } //Initial Case if (i == 0) { fprintf(stderr,"Initial case i = %d and command = [%s]\n", i,program_name ); childpid = fork(); if (childpid ==0 ){ if (dup2(pipeid[1],1) == -1) { perror("Failed at initial redirect"); } else if (close(pipeid[1]) == -1) { perror("Failed to close pipe"); } else { if (execvp(program_name,cmd_to_fork) == -1) { perror("Failure calling initial executable"); } } return 0; } wait(&status); if (WIFEXITED(status) != 1) { perror("child exit error"); } close(pipeid[1]); } //Middle Case if (i < fork_num-1) {//i is NOT the last command fprintf(stderr,"Middle case i = %d and command = [%s]\n", i,program_name ); childpid = fork(); if (childpid == 0 ) { if ((dup2(pipeid[0], 0) == -1 ) || (dup2(pipeid[1],1)==-1)) perror("Failed to redirect stdin of sort"); else if ((close(pipeid[0]) == -1) || (close(pipeid[1]) == -1) ) { perror("failed at closing"); } else { if (execvp(program_name,cmd_to_fork) == -1) { perror("Failure calling Middle executable"); } } return 1; } wait(&status); if (WIFEXITED(status) != 1) { perror("child exit error"); } close(pipeid[0]); close(pipeid[1]); } else { if (i == fork_num-1) { //End Case childpid = fork(); fprintf(stderr,"End case i = %d and command = [%s]\n", i,program_name ); if (childpid==0) { if (dup2(pipeid[0] , 0) == -1) { perror("Failed to redirect stdout of sort"); } else if (close(pipeid[0]) == -1) { perror("failed at closing"); } else { if (execvp(program_name,cmd_to_fork) == -1) { perror("Failure calling Final executable"); } } return 1; } wait(&status); if (WIFEXITED(status) != 1) { perror("child exit error"); } close(pipeid[0]); } } } return 1; }