home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume23 / rc / part01 / exec.c < prev    next >
C/C++ Source or Header  |  1991-10-18  |  3KB  |  125 lines

  1. /*
  2.    exec.c: exec() takes an argument list and does the appropriate thing
  3.    (calls a builtin, calls a function, etc.)
  4. */
  5.  
  6. #include <signal.h>
  7. #include <errno.h>
  8. #include "rc.h"
  9. #include "utils.h"
  10. #include "exec.h"
  11. #include "status.h"
  12. #include "hash.h"
  13. #include "builtins.h"
  14. #include "footobar.h"
  15. #include "jbwrap.h"
  16. #include "except.h"
  17. #include "redir.h"
  18. #include "wait.h"
  19.  
  20. void exec(List *s, boolean parent) {
  21.     char **av, **ev;
  22.     int pid, stat;
  23.     builtin_t *b;
  24.     char *path = NULL;
  25.     void (*handler)(int);
  26.     boolean forked, saw_exec, saw_builtin;
  27.  
  28.     av = list2array(s, dashex);
  29.     ev = makeenv();
  30.     saw_builtin = saw_exec = FALSE;
  31.  
  32.     do {
  33.         if (*av == NULL    || isabsolute(*av))
  34.             b = NULL;
  35.         else if (!saw_builtin && fnlookup(*av) != NULL)
  36.             b = funcall;
  37.         else
  38.             b = isbuiltin(*av);
  39.  
  40.         saw_builtin = FALSE; /* a builtin applies only to the immmediately following command, e.g., builtin exec echo hi */
  41.  
  42.         if (b == b_exec) {
  43.             av++;
  44.             saw_exec = TRUE;
  45.             parent = FALSE;
  46.         } else if (b == b_builtin) {
  47.             av++;
  48.             saw_builtin = TRUE;
  49.         }
  50.     } while (b == b_exec || b == b_builtin);
  51.  
  52.     if (*av == NULL && saw_exec) { /* do redirs and return on a null exec */
  53.         doredirs();
  54.         return;
  55.     }
  56.  
  57.     if (b == NULL) {
  58.         path = which(*av, TRUE);
  59.         if (path == NULL && *av != NULL) { /* perform null commands for redirections */
  60.             set(FALSE);
  61.             redirq = NULL;
  62.             empty_fifoq();
  63.             if (parent)
  64.                 return;
  65.             rc_exit(1);
  66.         }
  67.     }
  68.  
  69.     /* if parent & the redirq is nonnull, builtin or not it has to fork. */
  70.  
  71.     if (parent && (b == NULL || redirq != NULL)) {
  72.         pid = rc_fork();
  73.         forked = TRUE;
  74.     } else {
  75.         pid = 0;
  76.         forked = FALSE;
  77.     }
  78.  
  79.     switch (pid) {
  80.     case -1:
  81.         uerror("fork");
  82.         rc_error(NULL);
  83.         /* NOTREACHED */
  84.     case 0:
  85.         if (forked)
  86.             setsigdefaults();
  87.         doredirs();
  88.  
  89.         /* null commands performed for redirections */
  90.         if (*av == NULL || b != NULL) {
  91.             if (b != NULL)
  92.                 b(av);
  93.             empty_fifoq();
  94.             if (!forked && parent)
  95.                 return;
  96.             rc_exit(getstatus());
  97.         }
  98. #ifdef NOEXECVE
  99.         my_execve(path, (const char **) av, (const char **) ev); /* bogus, huh? */
  100. #else
  101.         execve(path, (const char **) av, (const char **) ev);
  102. #endif
  103. #ifdef DEFAULTINTERP
  104.         if (errno == ENOEXEC) {
  105.             *av = path;
  106.             *--av = DEFAULTINTERP;
  107.             execve(*av, (const char **) av, (const char **) ev);
  108.         }
  109. #endif
  110.         uerror(*av);
  111.         rc_exit(1);
  112.         /* NOTREACHED */
  113.     default:
  114.         if ((handler = signal(SIGINT, SIG_IGN)) != sig)
  115.             signal(SIGINT, handler); /* don't ignore interrupts in noninteractive mode */
  116.         rc_wait4(pid, &stat);
  117.         signal(SIGINT, handler);
  118.         redirq = NULL;
  119.         empty_fifoq();
  120.         setstatus(stat);
  121.         if (stat == SIGINT || stat == SIGQUIT) /* interrupted? let the handler deal with it. */
  122.             rc_raise(ERROR);
  123.     }
  124. }
  125.