home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / pdksh-4.9-src.tgz / tar.out / contrib / pdksh / sh / c_sh.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  507 lines

  1. /*
  2.  * built-in Bourne commands
  3.  */
  4.  
  5. #ifndef lint
  6. static char *RCSid = "$Id: c_sh.c,v 1.4 93/05/05 21:16:16 sjg Exp $";
  7. #endif
  8.  
  9. #include "stdh.h"
  10. #include <errno.h>
  11. #include <signal.h>
  12. #include <setjmp.h>
  13. #include <sys/times.h>
  14. #include <unistd.h>        /* getcwd */
  15. #include <limits.h>
  16. #include "sh.h"
  17.  
  18. static char *   clocktos    ARGS((clock_t t));
  19.  
  20. #ifndef CLK_TCK
  21. #define CLK_TCK 60            /* 60HZ */
  22. #endif
  23.  
  24. int
  25. c_label(wp)
  26.     char **wp;
  27. {
  28.     return 0;
  29. }
  30.  
  31. int
  32. c_shift(wp)
  33.     register char **wp;
  34. {
  35.     register struct block *l = e.loc;
  36.     register int n;
  37.  
  38.     n = wp[1] ? evaluate(wp[1]) : 1;
  39.     if (l->argc < n) {
  40.         errorf("nothing to shift\n");
  41.         return (1);
  42.     }
  43.     l->argv[n] = l->argv[0];
  44.     l->argv += n;
  45.     l->argc -= n;
  46.     return 0;
  47. }
  48.  
  49. int
  50. c_umask(wp)
  51.     register char **wp;
  52. {
  53.     register int i;
  54.     register char *cp;
  55.  
  56.     if ((cp = wp[1]) == NULL) {
  57.         i = umask(0);
  58.         umask(i);
  59.         printf("%#3.3o\n", i);    /* should this be shell output? */
  60.     } else {
  61.         for (i = 0; *cp>='0' && *cp<='7'; cp++)
  62.             i = i*8 + (*cp-'0');
  63.         umask(i);
  64.     }
  65.     return 0;
  66. }
  67.  
  68. int
  69. c_dot(wp)
  70.     char **wp;
  71. {
  72.     char *file, *cp;
  73.  
  74.     if ((cp = wp[1]) == NULL)
  75.         return 0;
  76.     file = search(cp, path, 0);
  77.     if (file == NULL)
  78.         errorf("sh: %s: not found\n", cp);
  79.     if (include(file))
  80.         return exstat;
  81.     return -1;
  82. }
  83.  
  84. int
  85. c_wait(wp)
  86.     char **wp;
  87. {
  88.     register char *cp;
  89.  
  90.     wp++;
  91.     cp = *wp;
  92.     if (cp == NULL) cp = "%";
  93.     /* todo: print status ? */
  94.     return waitfor(j_lookup(cp));
  95. }
  96.  
  97. int
  98. c_read(wp)
  99.     register char **wp;
  100. {
  101.     register int c = 0;
  102.     FILE *f = stdin;
  103.     int expand = 1;
  104.     register char *cp;
  105.  
  106.     for (wp++; (cp = *wp) != NULL && *cp++ == '-'; wp++) {
  107.         while (*cp) switch (*cp++) {
  108.           case 'e':
  109.             expand = 1;
  110.             break;
  111.           case 'r':
  112.             expand = 0;
  113.             break;
  114.           case 'u':
  115.             if (!digit(*cp) || (f = shf[*cp++-'0']) == NULL)
  116.                 errorf("bad -u argument\n");
  117.             break;
  118.         }
  119.     }
  120.  
  121.     if (*wp == NULL)
  122.         errorf("missing name\n");
  123.     if ((cp = strchr(*wp, '?')) != NULL) {
  124.         *cp = 0;
  125.         if (flag[FTALKING]) {
  126.             shellf("%s ", cp+1);
  127.             fflush(shlout);
  128.         }
  129.     }
  130.  
  131.     for (; *wp != NULL; wp++) {
  132.         for (cp = line; cp <= line+LINE; ) {
  133.             if (c == '\n')
  134.                 break;
  135.             c = getc(f);
  136.             if (c == EOF)
  137.                 return 1;
  138.             if (expand && c == '\\') {
  139.                 c = getc(f);
  140.                 if (c == '\n')
  141.                     c = 0;
  142.                 else
  143.                     *cp++ = c;
  144.                 continue;
  145.             }
  146.             if (c == '\n' || (wp[1] && ctype(c, C_IFS)))
  147.                 break;
  148.             *cp++ = c;
  149.         }
  150.         *cp = 0;
  151.         setstr(global(*wp), line);
  152.     }
  153.     return 0;
  154. }
  155.  
  156. int
  157. c_eval(wp)
  158.     register char **wp;
  159. {
  160.     register struct source *s;
  161.  
  162.     s = pushs(SWORDS);
  163.     s->u.strv = wp+1;
  164.     return shell(s);
  165. }
  166.  
  167. void setsig ARGS((struct trap *p, handler_t f));
  168.  
  169. int
  170. c_trap(wp)
  171.     register char **wp;
  172. {
  173.     int i;
  174.     char *s;
  175.     register struct trap *p;
  176.  
  177.     wp++;
  178.     if (*wp == NULL) {
  179.         for (p = sigtraps, i = SIGNALS; --i >= 0; p++) {
  180.             if (p->trap != NULL)
  181.                 shellf("%s: %s\n", p->name, p->trap);
  182.         }
  183.         return 0;
  184.     }
  185.  
  186.     s = (gettrap(*wp) == NULL) ? *wp++ : NULL; /* get command */
  187.     if (s != NULL && s[0] == '-' && s[1] == '\0')
  188.         s = NULL;
  189.  
  190.     /* set/clear traps */
  191.     while (*wp != NULL) {
  192.         p = gettrap(*wp++);
  193.         if (p == NULL)
  194.             errorf("trap: bad signal %s\n", wp[-1]);
  195.         if (p->trap != NULL)
  196.             afree((void*)p->trap, APERM);
  197.         p->trap = NULL;
  198.         if (s != NULL) {
  199.             if (strlen(s) != 0) {
  200.                 p->trap = strsave(s, APERM);
  201.                 setsig(p, trapsig);
  202.             } else
  203.                 setsig(p, (handler_t)SIG_IGN);
  204.         } else
  205.             /* todo: restore to orginal value */
  206.             setsig(p,
  207.                (p->signal==SIGINT || p->signal==SIGQUIT) && flag[FTALKING]
  208.                ? (handler_t)SIG_IGN : (handler_t)SIG_DFL);
  209.     }
  210.     return 0;
  211. }
  212.  
  213. void
  214. setsig(p, f)
  215.     register struct trap *p;
  216.     void (*f)();
  217. {
  218.   if (p->signal == 0)
  219.     return;
  220. #ifdef USE_SIGACT
  221.   sigaction(p->signal, &Sigact_ign, &Sigact);
  222.   if (Sigact.sa_handler != SIG_IGN || p->ourtrap)
  223.   {
  224.     p->ourtrap = 1;
  225.     Sigact.sa_handler = f;
  226.     sigaction(p->signal, &Sigact, NULL);
  227.     sigemptyset(&Sigact.sa_mask);
  228.     Sigact.sa_flags = 0;
  229.   }
  230. #else
  231.   if (signal(p->signal, SIG_IGN) != SIG_IGN || p->ourtrap)
  232.   {
  233.     p->ourtrap = 1;
  234.     signal(p->signal, f);
  235.   }
  236. #endif
  237. }
  238.  
  239. int
  240. c_return(wp)
  241.     char **wp;
  242. {
  243.     wp++;
  244.     if (*wp != NULL)
  245.         exstat = getn(*wp);
  246.     quitenv();        /* pop E_TCOM */
  247.     while (e.type == E_LOOP || e.type == E_EXEC)
  248.         quitenv();
  249.     if (e.type == E_FUNC)
  250.         longjmp(e.jbuf, 1);
  251.     leave(exstat);
  252. }
  253.  
  254. int
  255. c_brkcont(wp)
  256.     register char **wp;
  257. {
  258.     int quit;
  259.     char ch;
  260.  
  261.     quit = wp[1] == NULL ? 1 : getn(wp[1]);
  262.     ch = *wp[0];
  263.     quitenv();        /* pop E_TCOM */
  264.     while (e.type == E_LOOP || e.type == E_EXEC) {
  265.         if (e.type == E_LOOP && --quit <= 0)
  266.             longjmp(e.jbuf, (ch == 'b') ? LBREAK : LCONTIN);
  267.         quitenv();
  268.     }
  269.     errorf("cannot %s\n", wp[0]);
  270. }
  271.  
  272.  
  273. /* 91-05-27 <sjg>
  274.  * we are supposed to not exit first try
  275.  * if there are stopped jobs.
  276.  */
  277. int
  278. c_exit(wp)
  279.     char **wp;
  280. {
  281.     register char *cp;
  282.     static int extry = 0;
  283.     
  284. #ifdef JOBS
  285.     if (extry++ == 0)
  286.     {
  287.       if (flag[FMONITOR] && j_stopped()) /* todo: only once */
  288.       {
  289.         errorf("There are stopped jobs\n");
  290.         return 1;
  291.       }
  292.     }
  293. #endif
  294.     e.oenv = NULL;
  295.     if ((cp = wp[1]) != NULL)
  296.         exstat = getn(cp);
  297.     leave(exstat);
  298. }
  299.  
  300. int
  301. c_set(wp)
  302.     register char **wp;
  303. {
  304.     struct block *l = e.loc;
  305.     register char **owp = wp;
  306.     register char *cp;
  307.     int old_fmonitor = flag[FMONITOR];
  308.  
  309.     if ((cp = *++wp) == NULL) {
  310.         static char * const args [] = {"set", "-", NULL};
  311.         extern int c_typeset ARGS((char **args));
  312.         return c_typeset((char **)args);
  313.     }
  314.     
  315.     for (; (cp = *wp) != NULL && (*cp == '-' || *cp == '+');) {
  316.         int i, n = *cp++ == '-'; /* set or clear flag */
  317.         wp++;
  318.         if (*cp == '\0') {
  319.             if (n)
  320.                 flag[FXTRACE] = flag[FVERBOSE] = 0;
  321.             break;
  322.         }
  323.         if (*cp == '-')
  324.             goto setargs;
  325.         for (; *cp != '\0'; cp++)
  326.             if (*cp == 'o') {
  327.                 if (*wp == NULL) {
  328.                     printoptions();
  329.                     return 0;
  330.                 }
  331.                 i = option(*wp++);
  332.                 if (i == 0)
  333.                     shellf("%s: unknown option\n", *--wp);
  334.                 flag[i] = n;
  335.                 if (i == FEMACS && n)
  336.                     flag[FVI] = 0;
  337.                 else if (i == FVI && n)
  338.                     flag[FEMACS] = 0;
  339.             } else if (*cp>='a' && *cp<='z')
  340.                 flag[FLAG(*cp)] = n;
  341.             else
  342.                 errorf("%c: bad flag\n", *cp);
  343.         if (flag[FTALKING])
  344.             flag[FERREXIT] = 0;
  345.     }
  346.  
  347. #ifdef JOBS
  348.     if (old_fmonitor != flag[FMONITOR])
  349.         j_change();
  350. #endif
  351.  
  352.     /* set $# and $* */
  353.     if (*wp != NULL) {
  354.       setargs:
  355.         owp = --wp;
  356.         wp[0] = l->argv[0]; /* save $0 */
  357.         while (*++wp != NULL)
  358.             *wp = strsave(*wp, &l->area);
  359.         l->argc = wp - owp - 1;
  360.         l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area);
  361.         for (wp = l->argv; (*wp++ = *owp++) != NULL; )
  362.             ;
  363.         resetopts();
  364.     }
  365.     return 0;
  366. }
  367.  
  368. int
  369. c_unset(wp)
  370.     register char **wp;
  371. {
  372.     register char *id;
  373.     int flagf = 0;
  374.  
  375.     for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
  376.         if (*++id == 'f')
  377.             flagf++;
  378.     for (; (id = *wp) != NULL; wp++)
  379.         if (!flagf) {    /* unset variable */
  380.             unset(global(id));
  381.         } else {    /* unset function */
  382.             define(id, (struct op *)NULL);
  383.         }
  384.     return 0;
  385. }
  386.  
  387. int
  388. c_ulimit(wp)
  389.     register char **wp;
  390. {
  391.     extern int do_ulimit();
  392.  
  393.     return do_ulimit(wp[1], wp[2]);
  394. }
  395.  
  396. int
  397. c_times(wp)
  398.     char **wp;
  399. {
  400.     struct tms all;
  401.  
  402.     (void) times(&all);
  403.     printf("Shell: ");
  404.     printf("%8s user ", clocktos(all.tms_utime));
  405.     printf("%8s system\n", clocktos(all.tms_stime));
  406.     printf("Kids:  ");
  407.     printf("%8s user ", clocktos(all.tms_cutime));
  408.     printf("%8s system\n", clocktos(all.tms_cstime));
  409.  
  410.     return 0;
  411. }
  412.  
  413. /*
  414.  * time pipeline (really a statement, not a built-in comman)
  415.  */
  416. int
  417. timex(t, f)
  418.     struct op *t;
  419.     int f;
  420. {
  421.     int rv;
  422.     struct tms t0, t1;
  423.     clock_t t0t, t1t;
  424.     extern clock_t j_utime, j_stime; /* computed by j_wait */
  425.  
  426.     j_utime = j_stime = 0;
  427.     t0t = times(&t0);
  428.     rv = execute(t->left, f);
  429.     t1t = times(&t1);
  430.  
  431.     shellf("%8s real ", clocktos(t1t - t0t));
  432.     shellf("%8s user ",
  433.            clocktos(t1.tms_utime - t0.tms_utime + j_utime));
  434.     shellf("%8s system ",
  435.            clocktos(t1.tms_stime - t0.tms_stime + j_stime));
  436.     shellf("\n");
  437.  
  438.     return rv;
  439. }
  440.  
  441. static char *
  442. clocktos(t)
  443.     clock_t t;
  444. {
  445.     static char temp[20];
  446.     register int i;
  447.     register char *cp = temp + sizeof(temp);
  448.  
  449.     /* CLK_TCK may actually be a _sysconf() function call */
  450.     if (CLK_TCK != 100)    /* convert to 1/100'ths */
  451.       t = (t < 1000000000/CLK_TCK) ?
  452.         (t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
  453.  
  454.     *--cp = '\0';
  455.     *--cp = 's';
  456.     for (i = -2; i <= 0 || t > 0; i++) {
  457.         if (i == 0)
  458.             *--cp = '.';
  459.         *--cp = '0' + (char)(t%10);
  460.         t /= 10;
  461.     }
  462.     return cp;
  463. }
  464.  
  465. /* dummy function, special case in comexec() */
  466. int
  467. c_exec(wp)
  468.     char ** wp;
  469. {
  470.     return 0;
  471. }
  472.  
  473. /* dummy function, special case in comexec() */
  474. int
  475. c_builtin(wp)
  476.     char ** wp;
  477. {
  478.     return 0;
  479. }
  480.  
  481. extern    int c_test();        /* in test.c */
  482.  
  483. const struct builtin shbuiltins [] = {
  484.     {"=:", c_label},
  485.     {"=.", c_dot},
  486.     {"[", c_test},
  487.     {"=builtin", c_builtin},
  488.     {"=exec", c_exec},
  489.     {"=shift", c_shift},
  490.     {"=wait", c_wait},
  491.     {"read", c_read},
  492.     {"=eval", c_eval},
  493.     {"=trap", c_trap},
  494.     {"=break", c_brkcont},
  495.     {"=continue", c_brkcont},
  496.     {"=exit", c_exit},
  497.     {"=return", c_return},
  498.     {"=set", c_set},
  499.     {"unset", c_unset},
  500.     {"umask", c_umask},
  501.     {"test", c_test},
  502.     {"=times", c_times},
  503.     {"ulimit", c_ulimit},
  504.     {NULL, NULL}
  505. };
  506.  
  507.