Guest User

ExecCommandList

a guest
Jan 13th, 2014
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.02 KB | None | 0 0
  1. /* License: GPL */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <libgen.h>
  7. #include <signal.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <fcntl.h>
  11. #include <stdbool.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/wait.h>
  15.  
  16. const char * basename_argv0;
  17.  
  18. int ExecCommandWaitChild(pid_t ChildPID) {
  19.   int ChildStatus;
  20.   int status;
  21.   status=waitpid(ChildPID,&ChildStatus,0);
  22.   if (status==-1)
  23.     return (-1);
  24.   if (WIFEXITED(ChildStatus))
  25.     return (WEXITSTATUS(ChildStatus));
  26.   else
  27.     return (-1);
  28. }
  29.  
  30. int ExecCommandWaitChildList(pid_t * ChildPIDList) {
  31.   int ExitStatus;
  32.   ExitStatus=0;
  33.   if (ChildPIDList!=NULL) {
  34.     unsigned int ChildCount;
  35.     int i;
  36.     ChildCount=0;
  37.     for (i=0; ChildPIDList[i]!=-1; i++)
  38.       ChildCount++;
  39.     for (i=ChildCount-1; i>=0; i--) {
  40.       int ChildExitStatus;
  41.       ChildExitStatus=ExecCommandWaitChild(ChildPIDList[i]);
  42.       if (ExitStatus==0 && ChildExitStatus!=0)
  43.     ExitStatus=ChildExitStatus;
  44.     }
  45.     free(ChildPIDList);
  46.   }
  47.   return (ExitStatus);
  48. }
  49.  
  50. int ExecCommandListRedir(const char * const * const * const CommandArgList, char * const FileName) {
  51.   const char * const * CommandArgs;
  52.   int * PipeFDList;
  53.   pid_t * ChildPIDList;
  54.   unsigned int ChildCount;
  55.   int OutFileFD;
  56.   int ExitStatus;
  57.   bool ForegroundProcess;
  58.   long int maxfd;
  59.   int SavedErrNo;
  60.   int status;
  61.   int i;
  62.   if (CommandArgList==NULL)
  63.     return (-1);
  64.   ChildCount=0;
  65.   for (i=0; CommandArgList[i]!=NULL; i++)
  66.     ChildCount++;
  67.   if (ChildCount==0)
  68.     return (-1);
  69. #ifdef DEBUG
  70.   int j;
  71.   fprintf(stderr,"%s: ",__FUNCTION__);
  72.   for (i=0; i<ChildCount; i++) {
  73.     for (j=0; CommandArgList[i][j]!=NULL; j++)
  74.       fprintf(stderr,"%s ",CommandArgList[i][j]);
  75.     if (i<ChildCount-1)
  76.       fprintf(stderr,"| ");
  77.     else
  78.       fprintf(stderr,"> %s\n",FileName);
  79.   }
  80. #endif
  81.   PipeFDList=NULL;
  82.   ChildPIDList=NULL;
  83.   ExitStatus=-1;
  84.   if (FileName!=NULL) {
  85.     OutFileFD=mkstemp(FileName);
  86.     if (OutFileFD==-1)
  87.       goto ExecCommandListRedirExit;
  88.     ForegroundProcess=false;
  89.   }
  90.   else {
  91.     OutFileFD=-1;
  92.     ForegroundProcess=true;
  93.   }
  94.   if (ChildCount>1) {
  95.     PipeFDList=malloc((ChildCount-1)*(2*sizeof(int)));
  96.     if (PipeFDList==NULL)
  97.       goto ExecCommandListRedirExit;
  98.     for (i=0; i<ChildCount-1; i++) {
  99.       PipeFDList[2*i+0]=-1;
  100.       PipeFDList[2*i+1]=-1;
  101.     }
  102.   }
  103.   ChildPIDList=malloc((ChildCount+1)*sizeof(pid_t));
  104.   if (ChildPIDList==NULL)
  105.     goto ExecCommandListRedirExit;
  106.   for (i=0; i<ChildCount+1; i++)
  107.     ChildPIDList[i]=-1;
  108.   maxfd=sysconf(_SC_OPEN_MAX);
  109.   for (i=ChildCount-1; i>=0; i--) {
  110.     if (i>0) {
  111.       status=pipe(&PipeFDList[2*(i-1)]);
  112.       if (status==-1) {
  113.     if (ForegroundProcess==true)
  114.       fprintf(stderr,"%s: pipe creation failed: %s\n",basename_argv0,strerror(errno));
  115.     goto ExecCommandListRedirExit;
  116.       }
  117.     }
  118.     ChildPIDList[i]=fork();
  119.     if (ChildPIDList[i]==0) { /* child */
  120.       struct sigaction sa;
  121.       int fd;
  122.       if (i>0)
  123.     dup2(PipeFDList[2*(i-1)+0],STDIN_FILENO);
  124.       else if (ForegroundProcess==false) {
  125.     fd=open("/dev/null",O_RDONLY);
  126.     if (fd!=-1)
  127.       dup2(fd,STDIN_FILENO);
  128.       }
  129.       if (i<ChildCount-1)
  130.     dup2(PipeFDList[2*i+1],STDOUT_FILENO);
  131.       else if (OutFileFD!=-1)
  132.     dup2(OutFileFD,STDOUT_FILENO);
  133.       for (fd=STDERR_FILENO+1; fd<maxfd; fd++)
  134.     close(fd);
  135.       CommandArgs=CommandArgList[i];
  136.       sa.sa_handler=SIG_DFL;
  137.       sigfillset(&sa.sa_mask);
  138.       sa.sa_flags=0;
  139.       sigaction(SIGINT,&sa,NULL);
  140.       sigaction(SIGTERM,&sa,NULL);
  141.       sigaction(SIGQUIT,&sa,NULL);
  142.       sigaction(SIGPIPE,&sa,NULL);
  143.       execvp(CommandArgs[0],(char * const *)CommandArgs);
  144.       if (ForegroundProcess==true)
  145.     fprintf(stderr,"%s: %s: %s\n",basename_argv0,CommandArgs[0],strerror(errno));
  146.       _exit(127);
  147.     }
  148.     /* parent */
  149.     else if (ChildPIDList[i]==-1) {
  150.       if (ForegroundProcess==true)
  151.     fprintf(stderr,"%s: fork failed: %s\n",basename_argv0,strerror(errno));
  152.       goto ExecCommandListRedirExit;
  153.     }
  154.   }
  155.   ExitStatus=0;
  156. ExecCommandListRedirExit:
  157.   SavedErrNo=errno;
  158.   if (OutFileFD!=-1)
  159.     close(OutFileFD);
  160.   if (PipeFDList!=NULL) {
  161.     for (i=0; i<ChildCount-1; i++) {
  162.       close(PipeFDList[2*i+0]);
  163.       close(PipeFDList[2*i+1]);
  164.     }
  165.     free(PipeFDList);
  166.   }
  167.   ExitStatus=ExecCommandWaitChildList(ChildPIDList);
  168.   errno=SavedErrNo;
  169.   return (ExitStatus);
  170. }
  171.  
  172. FILE * ExecCommandListPipe(const char * const * const * const CommandArgList, pid_t ** ChildPIDListPtr) {
  173.   const char * const * CommandArgs;
  174.   int * PipeFDList;
  175.   pid_t * ChildPIDList;
  176.   unsigned int ChildCount;
  177.   FILE * OutFile;
  178.   long int maxfd;
  179.   int SavedErrNo;
  180.   int status;
  181.   int i;
  182.   *ChildPIDListPtr=NULL;
  183.   if (CommandArgList==NULL)
  184.     return (NULL);
  185.   ChildCount=0;
  186.   for (i=0; CommandArgList[i]!=NULL; i++)
  187.     ChildCount++;
  188.   if (ChildCount==0)
  189.     return (NULL);
  190. #ifdef DEBUG
  191.   int j;
  192.   fprintf(stderr,"%s: ",__FUNCTION__);
  193.   for (i=0; i<ChildCount; i++) {
  194.     for (j=0; CommandArgList[i][j]!=NULL; j++)
  195.       fprintf(stderr,"%s ",CommandArgList[i][j]);
  196.     if (i<ChildCount-1)
  197.       fprintf(stderr,"| ");
  198.     else
  199.       fprintf(stderr,"| %s\n",basename_argv0);
  200.   }
  201. #endif
  202.   OutFile=NULL;
  203.   PipeFDList=malloc(ChildCount*(2*sizeof(int)));
  204.   if (PipeFDList==NULL)
  205.     goto ExecCommandListPipeExit;
  206.   for (i=0; i<ChildCount; i++) {
  207.     PipeFDList[2*i+0]=-1;
  208.     PipeFDList[2*i+1]=-1;
  209.   }
  210.   ChildPIDList=malloc((ChildCount+1)*sizeof(pid_t));
  211.   if (ChildPIDList==NULL)
  212.     goto ExecCommandListPipeExit;
  213.   for (i=0; i<ChildCount+1; i++)
  214.     ChildPIDList[i]=-1;
  215.   *ChildPIDListPtr=ChildPIDList;
  216.   status=pipe(&PipeFDList[2*(ChildCount-1)]);
  217.   if (status==-1)
  218.     goto ExecCommandListPipeExit;
  219.   maxfd=sysconf(_SC_OPEN_MAX);
  220.   for (i=ChildCount-1; i>=0; i--) {
  221.     if (i>0) {
  222.       status=pipe(&PipeFDList[2*(i-1)]);
  223.       if (status==-1)
  224.     goto ExecCommandListPipeExit;
  225.     }
  226.     ChildPIDList[i]=fork();
  227.     if (ChildPIDList[i]==0) { /* child */
  228.       struct sigaction sa;
  229.       int fd;
  230.       if (i>0)
  231.     dup2(PipeFDList[2*(i-1)+0],STDIN_FILENO);
  232.       else {
  233.     fd=open("/dev/null",O_RDONLY);
  234.     if (fd!=-1)
  235.       dup2(fd,STDIN_FILENO);
  236.       }
  237.       dup2(PipeFDList[2*i+1],STDOUT_FILENO);
  238.       for (fd=STDERR_FILENO+1; fd<maxfd; fd++)
  239.     close(fd);
  240.       CommandArgs=CommandArgList[i];
  241.       sa.sa_handler=SIG_DFL;
  242.       sigfillset(&sa.sa_mask);
  243.       sa.sa_flags=0;
  244.       sigaction(SIGINT,&sa,NULL);
  245.       sigaction(SIGTERM,&sa,NULL);
  246.       sigaction(SIGQUIT,&sa,NULL);
  247.       sigaction(SIGPIPE,&sa,NULL);
  248.       execvp(CommandArgs[0],(char * const *)CommandArgs);
  249.       _exit(127);
  250.     }
  251.     /* parent */
  252.     else if (ChildPIDList[i]==-1)
  253.       goto ExecCommandListPipeExit;
  254.   }
  255.   OutFile=fdopen(PipeFDList[2*(ChildCount-1)+0],"r");
  256. ExecCommandListPipeExit:
  257.   SavedErrNo=errno;
  258.   if (PipeFDList!=NULL) {
  259.     for (i=0; i<ChildCount-1; i++) {
  260.       close(PipeFDList[2*i+0]);
  261.       close(PipeFDList[2*i+1]);
  262.     }
  263.     if (OutFile==NULL)
  264.       close(PipeFDList[2*(ChildCount-1)+0]);
  265.     close(PipeFDList[2*(ChildCount-1)+1]);
  266.     free(PipeFDList);
  267.   }
  268.   errno=SavedErrNo;
  269.   return (OutFile);
  270. }
  271.  
  272. int ExecCommandRedir(const char * const * const CommandArgs, char * const FileName) {
  273.   const char * const * CommandArgList[2];
  274.   CommandArgList[0]=CommandArgs;
  275.   CommandArgList[1]=NULL;
  276.   return (ExecCommandListRedir(CommandArgList,FileName));
  277. }
  278.  
  279. FILE * ExecCommandPipe(const char * const * const CommandArgs, pid_t * ChildPID) {
  280.   const char * const * CommandArgList[2];
  281.   pid_t * ChildPIDList;
  282.   FILE * OutFile;
  283.   int SavedErrNo;
  284.   CommandArgList[0]=CommandArgs;
  285.   CommandArgList[1]=NULL;
  286.   OutFile=ExecCommandListPipe(CommandArgList,&ChildPIDList);
  287.   SavedErrNo=errno;
  288.   *ChildPID=ChildPIDList[0];
  289.   errno=SavedErrNo;
  290.   return (OutFile);
  291. }
  292.  
  293. int ExecCommand(const char * const * CommandArgs) {
  294.   int status;
  295.   if (CommandArgs==NULL)
  296.     return (-1);
  297.   status=ExecCommandRedir(CommandArgs,NULL);
  298.   return (status);
  299. }
  300.  
  301. int main(int argc, char * const argv[]) {
  302.   static const char * const Command1Args[]={
  303.     "ls",
  304.     "-l",
  305.     "--si",
  306.     "--color=auto",
  307.     "--show-control-chars",
  308.     "/",
  309.     NULL
  310.   };
  311.   static const char * const Command2Args[]={
  312.     "grep",
  313.     "-i",
  314.     "Jan",
  315.     NULL
  316.   };
  317.   static const char * const Command3Args[]={
  318.     "head",
  319.     "-n",
  320.     "3",
  321.     NULL
  322.   };
  323.   static const char * const * const CommandArgList[]={
  324.     Command1Args,
  325.     Command2Args,
  326.     Command3Args,
  327.     NULL
  328.   };
  329.   FILE * infile;
  330.   pid_t * ChildPIDList;
  331.   pid_t ChildPID;
  332.   int ExitStatus;
  333.   basename_argv0=basename(argv[0]);
  334.  
  335.   /* ls -l --si --color=auto --show-control-chars / | grep -i Jan | head -n 3 | exec */
  336.  
  337.   infile=ExecCommandListPipe(CommandArgList,&ChildPIDList);
  338.   if (infile==NULL) {
  339.     fprintf(stderr,"%s: ExecCommandListPipe: %s\n",basename_argv0,strerror(errno));
  340.     ExitStatus=ExecCommandWaitChildList(ChildPIDList);
  341.     return (ExitStatus);
  342.   }
  343.   while (!feof(infile)) {
  344.     char Buffer[1024];
  345.     char * ptr;
  346.     ptr=fgets(Buffer,sizeof(Buffer),infile);
  347.     if (ptr==NULL) {
  348.       if (feof(infile))
  349.     break;
  350.       else {
  351.     fclose(infile);
  352.     return (2);
  353.       }
  354.     }
  355.     fputs(Buffer,stdout);
  356.   }
  357.   fclose(infile);
  358.   ExitStatus=ExecCommandWaitChildList(ChildPIDList);
  359.   fprintf(stderr,"%s: pipeline exit status: %d\n",basename_argv0,ExitStatus);
  360.  
  361.   /* ls -l --si --color=auto --show-control-chars / | exec */
  362.  
  363.   infile=ExecCommandPipe(Command1Args,&ChildPID);
  364.   if (infile==NULL) {
  365.     fprintf(stderr,"%s: ExecCommandPipe: %s\n",basename_argv0,strerror(errno));
  366.     ExitStatus=ExecCommandWaitChild(ChildPID);
  367.     return (ExitStatus);
  368.   }
  369.   while (!feof(infile)) {
  370.     char Buffer[1024];
  371.     char * ptr;
  372.     ptr=fgets(Buffer,sizeof(Buffer),infile);
  373.     if (ptr==NULL) {
  374.       if (feof(infile))
  375.     break;
  376.       else {
  377.     fclose(infile);
  378.     return (2);
  379.       }
  380.     }
  381.     fputs(Buffer,stdout);
  382.   }
  383.   fclose(infile);
  384.   ExitStatus=ExecCommandWaitChild(ChildPID);
  385.   fprintf(stderr,"%s: command exit status: %d\n",basename_argv0,ExitStatus);
  386.  
  387.   return (0);
  388. }
Advertisement
Add Comment
Please, Sign In to add comment