1: /*
   2:  * Copyright (c) 1988 The Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * This code is derived from software written by Ken Arnold and
   6:  * published in UNIX Review, Vol. 6, No. 8.
   7:  *
   8:  * Redistribution and use in source and binary forms are permitted
   9:  * provided that the above copyright notice and this paragraph are
  10:  * duplicated in all such forms and that any documentation,
  11:  * advertising materials, and other materials related to such
  12:  * distribution and use acknowledge that the software was developed
  13:  * by the University of California, Berkeley.  The name of the
  14:  * University may not be used to endorse or promote products derived
  15:  * from this software without specific prior written permission.
  16:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19:  *
  20:  */
  21: 
  22: /* this came out of the ftpd sources; it's been modified to avoid the
  23:  * globbing stuff since we don't need it.  also execvp instead of execv.
  24:  */
  25: 
  26: #if !defined(lint) && defined(DOSCCS)
  27: static char sccsid[] = "@(#)popen.c	5.7.2 (2.11BSD) 1999/08/05";
  28: #endif
  29: 
  30: #include "cron.h"
  31: #include <errno.h>
  32: #include <sys/signal.h>
  33: 
  34: #define WANT_GLOBBING 0
  35: 
  36: /*
  37:  * Special version of popen which avoids call to shell.  This insures noone
  38:  * may create a pipe to a hidden program as a side effect of a list or dir
  39:  * command.
  40:  */
  41: static PID_T *pids;
  42: static int fds;
  43: 
  44: FILE *
  45: cron_popen(program, type)
  46:     char *program, *type;
  47: {
  48:     register char *cp;
  49:     FILE *iop;
  50:     int argc, pdes[2];
  51:     PID_T pid;
  52:     char *argv[100];
  53: #if WANT_GLOBBING
  54:     char **pop, *vv[2];
  55:     int gargc;
  56:     char *gargv[1000];
  57:     extern char **glob(), **copyblk();
  58: #endif
  59: 
  60:     if (*type != 'r' && *type != 'w' || type[1])
  61:         return(NULL);
  62: 
  63:     if (!pids) {
  64:         if ((fds = getdtablesize()) <= 0)
  65:             return(NULL);
  66:         if (!(pids = (PID_T *)malloc((u_int)(fds * sizeof(PID_T)))))
  67:             return(NULL);
  68:         bzero((char *)pids, fds * sizeof(PID_T));
  69:     }
  70:     if (pipe(pdes) < 0)
  71:         return(NULL);
  72: 
  73:     /* break up string into pieces */
  74:     for (argc = 0, cp = program;; cp = NULL)
  75:         if (!(argv[argc++] = strtok(cp, " \t\n")))
  76:             break;
  77: 
  78: #if WANT_GLOBBING
  79:     /* glob each piece */
  80:     gargv[0] = argv[0];
  81:     for (gargc = argc = 1; argv[argc]; argc++) {
  82:         if (!(pop = glob(argv[argc]))) {    /* globbing failed */
  83:             vv[0] = argv[argc];
  84:             vv[1] = NULL;
  85:             pop = copyblk(vv);
  86:         }
  87:         argv[argc] = (char *)pop;       /* save to free later */
  88:         while (*pop && gargc < 1000)
  89:             gargv[gargc++] = *pop++;
  90:     }
  91:     gargv[gargc] = NULL;
  92: #endif
  93: 
  94:     iop = NULL;
  95:     switch(pid = vfork()) {
  96:     case -1:            /* error */
  97:         (void)close(pdes[0]);
  98:         (void)close(pdes[1]);
  99:         goto pfree;
 100:         /* NOTREACHED */
 101:     case 0:             /* child */
 102:         if (*type == 'r') {
 103:             if (pdes[1] != 1) {
 104:                 dup2(pdes[1], 1);
 105:                 dup2(pdes[1], 2);   /* stderr, too! */
 106:                 (void)close(pdes[1]);
 107:             }
 108:             (void)close(pdes[0]);
 109:         } else {
 110:             if (pdes[0] != 0) {
 111:                 dup2(pdes[0], 0);
 112:                 (void)close(pdes[0]);
 113:             }
 114:             (void)close(pdes[1]);
 115:         }
 116: #if WANT_GLOBBING
 117:         execvp(gargv[0], gargv);
 118: #else
 119:         execvp(argv[0], argv);
 120: #endif
 121:         _exit(1);
 122:     }
 123:     /* parent; assume fdopen can't fail...  */
 124:     if (*type == 'r') {
 125:         iop = fdopen(pdes[0], type);
 126:         (void)close(pdes[1]);
 127:     } else {
 128:         iop = fdopen(pdes[1], type);
 129:         (void)close(pdes[0]);
 130:     }
 131:     pids[fileno(iop)] = pid;
 132: 
 133: pfree:
 134: #if WANT_GLOBBING
 135:     for (argc = 1; argv[argc] != NULL; argc++) {
 136: /*		blkfree((char **)argv[argc]);	*/
 137:         free((char *)argv[argc]);
 138:     }
 139: #endif
 140:     return(iop);
 141: }
 142: 
 143: int
 144: cron_pclose(iop)
 145:     FILE *iop;
 146: {
 147:     register int fdes;
 148:     sigset_t omask, nmask;
 149:     WAIT_T stat_loc;
 150:     register PID_T pid;
 151: 
 152:     /*
 153: 	 * pclose returns -1 if stream is not associated with a
 154: 	 * `popened' command, or, if already `pclosed'.
 155: 	 */
 156:     if (pids == 0 || pids[fdes = fileno(iop)] == 0)
 157:         return(-1);
 158:     (void)fclose(iop);
 159:     sigemptyset(&nmask);
 160:     sigaddset(&nmask, SIGINT);
 161:     sigaddset(&nmask, SIGQUIT);
 162:     sigaddset(&nmask, SIGHUP);
 163:     sigprocmask(SIG_BLOCK, &nmask, &omask);
 164:     do  {
 165:         pid = waitpid(pids[fdes], &stat_loc, NULL);
 166:         } while (pid == -1 && errno == EINTR);
 167:     (void)sigprocmask(SIG_SETMASK, &omask, NULL);
 168:     pids[fdes] = 0;
 169:     return (pid == -1 ? -1 : WEXITSTATUS(stat_loc));
 170: }

Defined functions

cron_pclose defined in line 143; never used
cron_popen defined in line 44; used 1 times

Defined variables

fds defined in line 42; used 3 times
sccsid defined in line 27; never used

Defined macros

WANT_GLOBBING defined in line 34; used 4 times
Last modified: 1999-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3535
Valid CSS Valid XHTML 1.0 Strict