All pastes #946795 Raw Edit

Miscellany

public text v1 · immutable
·published 2008-03-17 23:12 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>
#include <string.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 = " ";
  int pidarray[MAX_COMMANDS];
  int statusarray[MAX_COMMANDS];

  pid_t childpid; 
  char * forkcommand[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;
      }

            
      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
   ************************************/

  //Gets rid of any \n in the argument array
  for (i = 0; i < fork_num-1; i++){
    char * command = cmd_ary[i];
    int length = strlen(command);
    cmd_ary[i] = strndup(command,length-1);
    printf("Without the ENDL on end = %s\n", cmd_ary[i]);
  }


  //In case there is only a single command
  if (fork_num == 1) {

    int j = 1;
  
    //Store the program name for execution
    cmd_hldr = strtok(cmd_ary[0], delimiter);
    forkcommand[0] = cmd_hldr;

    //Store the arguments for the program
    while (( cmd_hldr = strtok(NULL, delimiter)) != NULL) {
      forkcommand[j]=cmd_hldr;
      j++;
    }

    //Execute the single command
    childpid = fork();
    if (childpid == 0) {
      if (execvp(forkcommand[0],forkcommand)==-1) {
	perror("Exec failed");
      }
      perror("I could not call exec for some reason");
      return 0;
    }

    //Check the wait status
    waitpid(childpid,&status,0);
    if (WIFEXITED(status) != 1) {
      perror("Failure to Exit safely");
    }
    printf("The command [%s] of pid[%d] had a status of [%d]\n", forkcommand[0], childpid, status);
    return 1;
  }



  //Build up an array of pipeids
  typedef int* my_type;
  my_type p[fork_num];

  //DO NOT HAVE A HEART ATTACK AT THIS!
  int pipe1[2],pipe2[2],pipe3[2],pipe4[2], pipe5[2], pipe6[2], pipe7[2], pipe8[2];
  p[0]=pipe1;
  p[1]=pipe2;
  p[2]=pipe3;
  p[3]=pipe4;
  p[4]=pipe5;
  p[5]=pipe6;
  p[6]=pipe7;
  p[7]=pipe8;

  int t;

  //Connect the pipes
  for (t = 0; t < fork_num; t++) {
    if (pipe(p[t])==-1){
      perror("Failure to pipe");
    }
  }



  
  //Iterate over all the commands 
  for(i = 0; i < fork_num; i++) {
    //fprintf(stderr,"executing command number %d which is %s\n", i, cmd_ary[i]);
    
    int j = 1;
    char * cmd_to_fork[MAX_COMMAND_LENGTH];
    
    //Store the program name for execution
    char * cmd = strtok(cmd_ary[i], delimiter);
    cmd_to_fork[0] = malloc(strlen(cmd));
    strcpy(cmd_to_fork[0],cmd);

    //Store the arguments for the program
    while (( cmd = strtok(NULL, delimiter)) != NULL) {
      cmd_to_fork[j] = malloc(strlen(cmd));
      strcpy(cmd_to_fork[j],cmd);
      //fprintf(stderr,"Arg %d of command [%s] is [%s] MAIN\n", j, cmd_to_fork[j], cmd_to_fork[j]);
      j++;
    }

    
    //If the array has leftover arguments, NULLify them
    if (cmd_to_fork[j] != NULL) {
      cmd_to_fork[j] = NULL;
    }


    /*
    j = 0;
    fprintf(stderr,"-----------Command [%s]------------ \n", cmd_to_fork[0]);
    while (cmd_to_fork[j] != NULL) {
      fprintf(stderr,"At location [%d] the value is [%s]\n", j, cmd_to_fork[j]);
      j++;
    }
    */
    

    //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(p[i][1],1) == -1) {
	  perror("Failed at initial redirect");
	}
	else if (close(p[i][1]) == -1) {
	  perror("Failed to close pipe");
	}
	else {
	  if (execvp(cmd_to_fork[0],cmd_to_fork) == -1) {
	    perror("Failure calling initial executable");
	  }
	}
	return 0;
      }
      pidarray[i] = childpid;
      waitpid(childpid,&status,0);
      if (WIFEXITED(status) != 1) {
	perror("child exit error");
      }
      statusarray[i]=status;
      
      close(p[i][1]);
    }




    //Middle Case

    
    else 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(p[i-1][0], 0) == -1 ) || (dup2(p[i][1],1)==-1))
	  perror("Failed to redirect STDIN");
	else if ((close(p[i-1][0]) == -1) || (close(p[i][1]) == -1) ) {
	  perror("Failed at closing");
	}
	else {
	  if (execvp(cmd_to_fork[0],cmd_to_fork) == -1) {
	    perror("Failure calling Middle executable");
	  }
	}
	return 1;
      }
      

      pidarray[i] = childpid;
      waitpid(childpid,&status,0);
      if (WIFEXITED(status) != 1) {
        perror("child exit error");
      }
      statusarray[i]=status;
      close(p[i-1][0]);
      close(p[i][1]);
    }

    else {
      if (i == fork_num-1) {
	//End Case

	//fprintf(stderr,"End case i = %d and command = [%s]\n", i,program_name );
	childpid = fork();
	
	if (childpid==0) {
	  
	  if (dup2(p[i-1][0] , 0) == -1) {
	    perror("Failed to redirect from STDIN");
	  }
	  else if (close(p[i-1][0]) == -1) {
	    perror("Failed at closing");
	  }
	  else {
	    //  	perror("beforeZOMG");
	    if (execvp(cmd_to_fork[0],cmd_to_fork) == -1) {
	      perror("Failure calling Final executable");
	    }
	  }
	  return 1;
	}
	pidarray[i] = childpid;
	waitpid(childpid,&status,0);
	if (WIFEXITED(status) != 1) {
	  perror("child exit error");
	}
	statusarray[i]=status;
	close(p[i-1][0]);
	//	perror("ENDZOMG");
      }
    }

  }
 
  for (i = 0; i < fork_num; i++) {
    printf("The command [%s] of pid[%d] had a status of [%d]\n", strtok(cmd_ary[i], delimiter),pidarray[i],statusarray[i]);
  }

  return 1;
}
//It would print the following three things: process id, command that it executed, and the exit status.