home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / lib / util / nexec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  4.3 KB  |  199 lines

  1. #include "util.h"
  2. #include "nexec.h"
  3. #include <signal.h>
  4. #ifndef NOFCNTL
  5. #include <fcntl.h>
  6. #endif
  7.  
  8. /*    generic fork/exec procedure, passing re-positioned fd's */
  9.  
  10. /*    Jun 81    D. Crocker    make regfdary loop tmp<=HIGHFD
  11.  *    May 82    D. Crocker    make close of fd tmp<=HIGHFD
  12.  *    Jul 82    D. Crocker    make vax version, to use vfork
  13.  *    Mar 84    D. Kingston    Changed to use _NFILE from stdio.h instead
  14.  *                of HIGHFD. Steve Kille: you don't have
  15.  *                to shorten the array if you have less fds.
  16.  */
  17.  
  18. extern    int    numfds;
  19.  
  20. LOCFUN tryfork();
  21.  
  22. /* VARARGS4 */
  23. #if sparc
  24. #include <varargs.h>
  25. #define MAXARGS 20
  26. nexecl(va_alist)
  27. va_dcl
  28. {
  29.     register    int    i;
  30.             va_list    ap;
  31.             int    proctyp, pgmflags;
  32.             int    *fdarray;
  33.             char    *pgm;
  34.             char    *pgmparm[MAXARGS];
  35.  
  36.     va_start(ap);
  37.     proctyp = va_arg(ap, int);
  38.     pgmflags = va_arg(ap, int);
  39.     fdarray = va_arg(ap, int *);
  40.     pgm = va_arg(ap, char *);
  41.     for (i = 0; i < MAXARGS; ++i) {
  42.         if ((pgmparm[i] = va_arg(ap, char *)) ==(char *)0)
  43.             break;
  44.     }
  45.     va_end(ap);
  46.     return(nexecv(proctyp, pgmflags, fdarray, pgm, pgmparm));
  47. }
  48. #else /* sparc */
  49. #ifdef NO_VARARGS
  50. nexecl(proctyp, pgmflags, fdarray, pgm, pgmparm, a,b,c,d,e,f,g,h,i,j,k,l,m)
  51. #else
  52. nexecl(proctyp, pgmflags, fdarray, pgm, pgmparm)
  53. #endif /* NO_VARARGS */
  54. int proctyp,            /* exec / fork / fork-exec        */
  55. pgmflags,            /* parent wait? disable interrupts?    */
  56. *fdarray;            /* what current fd's go where?        */
  57. char *pgm,            /* what program to exec?        */
  58. *pgmparm;            /* its parameters vector        */
  59. {
  60.     return(nexecv(proctyp, pgmflags, fdarray, pgm, &pgmparm));
  61. }
  62. #endif /* sparc */
  63.  
  64. nexecv(proctyp, pgmflags, fdarray, pgm, pgmparm)
  65. int proctyp,
  66. pgmflags,
  67. *fdarray;
  68. char    *pgm,
  69. *pgmparm[];
  70. {
  71.     register    int    fd;
  72.             int    status;
  73.             int    childid;
  74.     sigtype        (*(osig1))();
  75.     sigtype        (*(osig2))();
  76.     sigtype        (*(osig3))();
  77.  
  78.     if (proctyp != PUREXEC) {
  79.         /* printf("This is a forking call.\n"); */
  80.         childid = tryfork();
  81.         if (childid == -1)
  82.             return(NOTOK);
  83.         /* printf("Successful fork\n"); */
  84.         if (childid != 0) {        /* parent process */
  85.             if (pgmflags & FRKPIGO) { /* disable parent signals */
  86.                 /* printf("Parent to be non-interruptible\n"); */
  87.                 osig1 = signal(SIGHUP, SIG_IGN);
  88.                 osig2 = signal(SIGINT, SIG_IGN);
  89.                 osig3 = signal(SIGQUIT, SIG_IGN);
  90.             }
  91.             if (((proctyp == FRKEXEC) &&(pgmflags & FRKWAIT)) ||
  92.                 proctyp == SPNEXEC) {
  93.                 /* printf("Parent is to wait\n"); */
  94.                 status = pgmwait(childid);
  95.                 if (pgmflags & FRKPIGO) {
  96.                     (void)signal(SIGHUP, osig1);
  97.                     (void)signal(SIGINT, osig2);
  98.                     (void)signal(SIGQUIT, osig3);
  99.                 }
  100.                 return(status);
  101.             }
  102.             return(childid);
  103.         }
  104.         if (proctyp == SPNEXEC) {    /* want it to be a spawn */
  105.             /* printf("This is a spawn\n"); */
  106.             switch(childid = tryfork()) {
  107.             case 0:
  108.                 break;    /* gets to do its thing */
  109.  
  110.             case NOTOK:    /* oops */
  111.                 exit(NOTOK);
  112.  
  113.             default:    /* grandchild: kill middle proc */
  114.                 exit(0);
  115.             }
  116.         }
  117.     }
  118.     if (fdarray) {        /* re-align fd array list */
  119.         /* first do the re-positions */
  120.         for (fd = 0; fd < numfds; fd++) {
  121.             if (fdarray[fd] != CLOSEFD && fdarray[fd] != fd) {
  122. #ifndef NODUP2
  123.                 (void)dup2(fdarray[fd], fd);
  124. #else /* NODUP2 */
  125.                 (void)close(fd);
  126. #ifndef NOFCNTL
  127.                 fcntl(fdarray[fd], F_DUPFD, fd);
  128. #else /* NOFCNTL */
  129.                 {
  130.                     int    dupfd;
  131.  
  132.                     while ((dupfd = dup(fdarray[fd])) < fd && dupfd != -1)
  133.                         ;
  134.                     /* did we get right fd? */
  135.                 }
  136. #endif /* NOFCNTL */
  137. #endif /* NODUP2 */
  138.             }
  139.         }
  140.         for (fd = 0; fd < numfds; fd++)
  141.             if (fdarray[fd] == CLOSEFD) {
  142.                 /* printf("Closing %2d\n", fd); */
  143.                 /* get rid of unwanted ones */
  144.                 (void)close(fd);
  145.             }
  146.     }
  147.  
  148.     if (pgmflags & FRKCIGO) {
  149.         /* printf("Child's interrupts to be disabled\n"); */
  150.         (void)signal(1, SIG_IGN);
  151.         (void)signal(2, SIG_IGN);
  152.         (void)signal(3, SIG_IGN);
  153.     }
  154.  
  155.     /* printf("Execing %s\n", pgm); */
  156.     execv(pgm, pgmparm);
  157.     /* printf("Exec not successful\n"); */
  158.     switch(proctyp) {
  159.     case PUREXEC:
  160.         return(NOTOK);
  161.  
  162.     default:        /* caller can deal with it */
  163.         if (pgmflags & FRKERRR)
  164.             return(NOTOK);
  165.     }
  166.     exit(NOTOK);
  167.     /* NOTREACHED */
  168. }
  169.  
  170. pgmwait(childid)
  171. int childid;            /* process id of child to collect */
  172. {
  173.     int status;
  174.     register int retval;
  175.  
  176.     while ((retval = wait(&status)) != childid)
  177.         if (retval == NOTOK)
  178.             return(NOTOK);
  179.  
  180.     return(gwaitval(status));
  181. }
  182.  
  183.  
  184. LOCFUN
  185. tryfork()
  186. {
  187.     register int childid;
  188.     register int tried;
  189.  
  190.     tried = NUMTRY;
  191.     do {
  192.         if ((childid = fork()) < 0)
  193.             sleep(1);
  194.         else
  195.             return(childid);
  196.     } while (tried--);
  197.     return(childid);
  198. }
  199.