All pastes #945389 Raw Edit

Something

public text v1 · immutable
·published 2008-03-16 22:03 UTC
rendered paste body


#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

#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]);
    }


    //Initial Case
    if (i == 0) {
      perror("I am initial");
      childpid = fork();
      if (childpid ==0 ){
         if (dup2(pipeids[i][1],1) == -1) {
           perror("Failed at initial redirect");
         }
         else if (close(pipeids[i][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(pipeids[i][1]);
      continue;
    }


    childpid = fork();

    //Middle Case

    if (i != fork_num-1) {//i is NOT the last command
      perror("Middle case");
      childpid = fork();

      if (childpid == 0 ) {
         if ((dup2(pipeids[i-1][0], 0) == -1 ) || (dup2(pipeids[i][1],1)==-1))
           perror("Failed to redirect stdin of sort");
         else if ((close(pipeids[i-1][0]) == -1) || (close(pipeids[i][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(pipeids[i-1][0]);
      close(pipeids[i][1]);
      continue;
    }



    //End Case
    childpid = fork();

    perror("End case");
    if (childpid==0) {
      if (dup2(pipeids[i-1][0] , 0) == -1) {
         perror("Failed to redirect stdout of  sort");
      }
      else if (close(pipeids[i-1][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(pipeids[i-1][0]);



  }
  return 1;
}