• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/maloc/src/vsh/vpup.c

00001 /*
00002  * ***************************************************************************
00003  * MALOC = < Minimal Abstraction Layer for Object-oriented C >
00004  * Copyright (C) 1994--2008 Michael Holst
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00019  *
00020  * rcsid="$Id: vpup.c,v 1.10 2008/03/12 05:13:58 fetk Exp $"
00021  * ***************************************************************************
00022  */
00023 
00024 /*
00025  * ***************************************************************************
00026  * File:     vpup.c
00027  *
00028  * Purpose:  Handle the following useful features of a shell like bash:
00029  *
00030  *               (1) input/output redirection from/into files
00031  *               (2) pipes of arbitrary length and complexity
00032  *               (3) execv/execvp of the actual user commands
00033  *
00034  * Notes:    These five routines were twisted somewhat from the examples
00035  *           in the book "Practical Unix Programming" by Robbins and Robbins.
00036  *           The five routines are:
00037  *
00038  *               VPUBLIC  Vpup_execCmd
00039  *               VPRIVATE Vpup_makeargv
00040  *               VPRIVATE Vpup_parseDelim
00041  *               VPRIVATE Vpup_reDir
00042  *               VPRIVATE Vpup_connPipe
00043  *
00044  * Author:   Michael Holst
00045  * ***************************************************************************
00046  */
00047 
00048 #include "vsh_p.h"
00049 #include "vpup.h"
00050 
00051 VEMBED(rcsid="$Id: vpup.c,v 1.10 2008/03/12 05:13:58 fetk Exp $")
00052 
00053 /* define VPUP_SHELL 1 */
00054 
00055 #if !defined(HAVE_WINSOCK_H) && defined(VPUP_SHELL)
00056     VPRIVATE int Vpup_makeargv(char *s, const char *delimiters, char ***argvp);
00057     VPRIVATE int Vpup_parseDelim(char *s, char delimiter, char **v);
00058     VPRIVATE int Vpup_reDir(char *infilename, char *outfilename);
00059     VPRIVATE int Vpup_connPipe(char *cmd, int *frontfd, int *backfd);
00060 #endif
00061 
00062 /*
00063  * ***************************************************************************
00064  * Class Vsig: Inlineable methods
00065  * ***************************************************************************
00066  */
00067 #if !defined(VINLINE_MALOC)
00068 
00069 #endif /* if !defined(VINLINE_MALOC) */
00070 /*
00071  * ***************************************************************************
00072  * Class Vsig: Non-inlineable methods
00073  * ***************************************************************************
00074  */
00075 
00076 #if !defined(HAVE_WINSOCK_H) && defined(VPUP_SHELL)
00077 /*
00078  * ***************************************************************************
00079  * Routine:  Vpup_execCmd
00080  *
00081  * Purpose:  Execute a shell command.
00082  *
00083  * Author:   Michael Holst
00084  * ***************************************************************************
00085  */
00086 VPUBLIC void Vpup_execCmd(const char *PR, int argc, char **argv, char *inbuf)
00087 {
00088     char **chargv;
00089     pid_t child_pid;
00090     char *cmd;
00091     char *nextcmd;
00092     int frontfd[2];
00093     int backfd[2];
00094   
00095     frontfd[0] = -1;
00096     frontfd[1] = -1;
00097     backfd[0]  = -1;
00098     backfd[1]  = -1;
00099     child_pid  = 0;
00100 
00101     if ((nextcmd = inbuf) == VNULL) exit(1);
00102 
00103     while (1) {
00104 
00105         cmd = nextcmd;
00106         if (cmd == VNULL) break;
00107 
00108         /* if last in pipeline, do not fork another */
00109         if ((nextcmd = strchr(nextcmd, VPIPE_SYMBOL)) == VNULL) {
00110             backfd[1] = -1;
00111             child_pid = 0;
00112 
00113         /* else fork a child to execute next pipeline command */
00114         } else {
00115             *nextcmd = VNULL_SYMBOL;
00116             nextcmd++;
00117             if (pipe(backfd)== -1) {
00118                 perror(PR);
00119                 exit(1);
00120             } else if ((child_pid = fork()) == -1) {
00121                 perror(PR);
00122                 exit(1);
00123             }
00124         }
00125 
00126         /* the child execs the command */
00127         if (child_pid == 0) {
00128             if (Vpup_connPipe(cmd, frontfd, backfd) == -1) {
00129                 perror(PR);
00130                 exit(1);
00131             } else if (Vpup_makeargv(cmd, VBLANK_STRING, &chargv) > 0) {
00132                 if (execvp(chargv[0], chargv) == -1) {
00133                     perror(PR);
00134                     /* Vnm_system("play sorry.au"); */
00135                 }
00136             }
00137             exit(1);
00138         }
00139 
00140         /* the parent closes front pipe and makes back pipe, front */
00141         close(frontfd[0]);
00142         close(frontfd[1]);
00143         frontfd[0] = backfd[0];
00144         frontfd[1] = backfd[1];
00145     }
00146     close(backfd[0]);
00147     close(backfd[1]);
00148     exit(1);
00149 }
00150 
00151 /*
00152  * ***************************************************************************
00153  * Routine:  Vpup_makeargv
00154  *
00155  * Purpose:  Create a set of tokens from the input buffer.
00156  *
00157  * Author:   Michael Holst
00158  * ***************************************************************************
00159  */
00160 VPRIVATE int Vpup_makeargv(char *s, const char *delimiters, char ***argvp)
00161 {
00162     char         *t;
00163     char         *snew;
00164     int          numtokens;
00165     int          i;
00166     unsigned int size;
00167 
00168     /* snew is real start of string after skipping leading delimiters */
00169     snew = s + strspn(s, delimiters);
00170 
00171     /* try to create space for a copy of snew in t */
00172     if ((t = calloc(strlen(snew) + 1, sizeof(char))) == VNULL) {
00173         *argvp = VNULL;
00174         numtokens = -1;
00175 
00176     /* if space creation successful, parse the string */
00177     } else {
00178 
00179         /* count the number of tokens in snew */
00180         strcpy(t, snew);
00181         if (strtok(t, delimiters) == VNULL)
00182             numtokens = 0;
00183         else
00184             for (numtokens=1; strtok(VNULL,delimiters) != VNULL; numtokens++);  
00185 
00186         /* create an argument array to contain ptrs to tokens */
00187         size = (unsigned int)(numtokens + 1);
00188         if ((*argvp = calloc(size, sizeof(char *))) == VNULL) {
00189             free(t);
00190             numtokens = -1;
00191 
00192         /* if successful, insert pointers to tokens into the array */
00193         } else {
00194             if (numtokens > 0) {
00195                 strcpy(t, snew);
00196                 **argvp = strtok(t, delimiters);
00197                 for (i=1; i<numtokens+1; i++)
00198                    *((*argvp)+i) = strtok(VNULL, delimiters);
00199             } else {
00200                 **argvp = VNULL;
00201                 free(t);
00202             }
00203         }
00204     }   
00205     return numtokens;
00206 }
00207 
00208 /*
00209  * ***************************************************************************
00210  * Routine:  Vpup_parseDelim
00211  *
00212  * Purpose:  buffer.
00213  *
00214  * Author:   Michael Holst
00215  * ***************************************************************************
00216  */
00217 VPRIVATE int Vpup_parseDelim(char *s, char delimiter, char **v)
00218 {
00219     char *p;
00220     char *q;
00221     int offset;
00222     int error = 0;
00223 
00224     /* Find position of the delimiting character */
00225     *v = NULL;
00226     if ((p = strchr(s, delimiter)) != NULL)  {
00227 
00228         /* Split off the token following delimiter */
00229         if ((q = (char *)malloc(strlen(p + 1) + 1)) == NULL)
00230             error = -1;
00231 
00232         else {
00233             strcpy(q, p + 1);
00234             if ((*v = strtok(q, VDELIM_SET)) == NULL) error = -1;
00235             offset = strlen(q);
00236             strcpy(p, p + offset + 1);
00237         } 
00238     }
00239     return error;
00240 }
00241 
00242 /*
00243  * ***************************************************************************
00244  * Routine:  Vpup_reDir
00245  *
00246  * Purpose:  Do a redirection.
00247  *
00248  * Author:   Michael Holst
00249  * ***************************************************************************
00250  */
00251 VPRIVATE int Vpup_reDir(char *infilename, char *outfilename)
00252 {
00253     int indes;
00254     int outdes;
00255 
00256     /* redirect standard in to infilename */
00257     if (infilename != VNULL) {
00258         if ((indes = open(infilename, O_RDONLY, VSTDMODE)) == -1)
00259             return -1;
00260         if (dup2(indes, STDIN_FILENO) == -1) {
00261             close(indes);
00262             return -1;
00263         }  
00264         close(indes);
00265     }
00266 
00267     /* redirect standard out to outfilename */
00268     if (outfilename != VNULL) {
00269         if ((outdes=open(outfilename,O_WRONLY|O_CREAT|O_TRUNC,VSTDMODE))==-1)
00270             return -1;
00271         if (dup2(outdes, STDOUT_FILENO) == -1) {
00272             close(outdes);
00273             return -1;
00274         }
00275         close(outdes);
00276     }   
00277     return 0;
00278 }
00279 
00280 /*
00281  * ***************************************************************************
00282  * Routine:  Vpup_connPipe
00283  *
00284  * Purpose:  Connect up some pipes.
00285  *
00286  * Author:   Michael Holst
00287  * ***************************************************************************
00288  */
00289 VPRIVATE int Vpup_connPipe(char *cmd, int *frontfd, int *backfd)
00290 {
00291     int error = 0;
00292     char *infilename, *outfilename;
00293 
00294     /* look for stdin redirect */
00295     if (Vpup_parseDelim(cmd, VRDIN_SYMBOL, &infilename) == -1)
00296         error = -1;
00297 
00298     /* no redirection allowed at front of pipeline */
00299     else if (infilename != VNULL && frontfd[0] != -1)
00300         error = -1;
00301 
00302     /* look for stdout redirect */
00303     else if (Vpup_parseDelim(cmd, VRDOUT_SYMBOL, &outfilename) == -1)
00304         error = -1;
00305 
00306     /* no redirection allowed at back of pipeline */
00307     else if (outfilename != VNULL && backfd[1] != -1)
00308         error = -1;
00309 
00310     /* do any required redirections */
00311     else if (Vpup_reDir(infilename, outfilename) == -1)
00312         error = -1;
00313 
00314     /* now connect up appropriate pipes */
00315     else { 
00316         if (frontfd[0] != -1) {
00317             if (dup2(frontfd[0], STDIN_FILENO) == -1)
00318             error = -1;
00319         } 
00320         if (backfd[1] != -1) {
00321             if (dup2(backfd[1], STDOUT_FILENO) == -1)
00322                 error = -1;
00323         } 
00324     }
00325 
00326     /* close unneeded file descriptors */
00327     close (frontfd[0]);
00328     close (frontfd[1]);
00329     close (backfd[0]);
00330     close (backfd[1]);
00331     return error;
00332 }
00333 #else
00334 
00335 /*
00336  * ***************************************************************************
00337  * Routine:  Vpup_execCmd
00338  *
00339  * Purpose:  A simple shell command exec.
00340  *
00341  * Author:   Michael Holst
00342  * ***************************************************************************
00343  */
00344 VPUBLIC void Vpup_execCmd(const char *PR, int argc, char **argv, char *inbuf)
00345 {
00346     Vnm_exec(argc,argv);
00347 }
00348 #endif /* if !defined(HAVE_WINSOCK_H) */
00349 

Generated on Wed Oct 20 2010 11:12:15 for APBS by  doxygen 1.7.2