home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / k / ksh48.zip / sh / c_sh.c < prev    next >
C/C++ Source or Header  |  1992-09-06  |  9KB  |  505 lines

  1. /*
  2.  * built-in Bourne commands
  3.  */
  4.  
  5. #ifndef lint
  6. static char *RCSid = "$Id: c_sh.c,v 1.3 1992/04/25 08:29:52 sjg Exp $";
  7. #endif
  8.  
  9. #include "stdh.h"
  10. #include <errno.h>
  11. #include <signal.h>
  12. #include <setjmp.h>
  13. #include <unistd.h>        /* getcwd */
  14. #include <time.h>
  15. #include <sys/times.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("%03o\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("%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.  
  260.     quit = wp[1] == NULL ? 1 : getn(wp[1]);
  261.     quitenv();        /* pop E_TCOM */
  262.     while (e.type == E_LOOP || e.type == E_EXEC) {
  263.         if (e.type == E_LOOP && --quit <= 0)
  264.             longjmp(e.jbuf, (*wp[0] == 'b') ? LBREAK : LCONTIN);
  265.         quitenv();
  266.     }
  267.     errorf("cannot %s\n", wp[0]);
  268. }
  269.  
  270.  
  271. /* 91-05-27 <sjg>
  272.  * we are supposed to not exit first try
  273.  * if there are stopped jobs.
  274.  */
  275. int
  276. c_exit(wp)
  277.     char **wp;
  278. {
  279.     register char *cp;
  280.     static int extry = 0;
  281.  
  282. #ifdef JOBS
  283.     if (extry++ == 0)
  284.     {
  285.       if (flag[FMONITOR] && j_stopped()) /* todo: only once */
  286.       {
  287.         errorf("There are stopped jobs\n");
  288.         return 1;
  289.       }
  290.     }
  291. #endif
  292.     e.oenv = NULL;
  293.     if ((cp = wp[1]) != NULL)
  294.         exstat = getn(cp);
  295.     leave(exstat);
  296. }
  297.  
  298. int
  299. c_set(wp)
  300.     register char **wp;
  301. {
  302.     struct block *l = e.loc;
  303.     register char **owp = wp;
  304.     register char *cp;
  305.     int old_fmonitor = flag[FMONITOR];
  306.  
  307.     if ((cp = *++wp) == NULL) {
  308.         static char * const args [] = {"set", "-", NULL};
  309.         extern int c_typeset ARGS((char **args));
  310.         return c_typeset(args);
  311.     }
  312.  
  313.     for (; (cp = *wp) != NULL && (*cp == '-' || *cp == '+');) {
  314.         int i, n = *cp++ == '-'; /* set or clear flag */
  315.         wp++;
  316.         if (*cp == '\0') {
  317.             if (n)
  318.                 flag[FXTRACE] = flag[FVERBOSE] = 0;
  319.             break;
  320.         }
  321.         if (*cp == '-')
  322.             goto setargs;
  323.         for (; *cp != '\0'; cp++)
  324.             if (*cp == 'o') {
  325.                 if (*wp == NULL) {
  326.                     printoptions();
  327.                     return 0;
  328.                 }
  329.                 i = option(*wp++);
  330.                 if (i == 0)
  331.                     shellf("%s: unknown option\n", *--wp);
  332.                 flag[i] = n;
  333.                 if (i == FEMACS && n)
  334.                     flag[FVI] = 0;
  335.                 else if (i == FVI && n)
  336.                     flag[FEMACS] = 0;
  337.             } else if (*cp>='a' && *cp<='z')
  338.                 flag[FLAG(*cp)] = n;
  339.             else
  340.                 errorf("%c: bad flag\n", *cp);
  341.         if (flag[FTALKING])
  342.             flag[FERREXIT] = 0;
  343.     }
  344.  
  345. #ifdef JOBS
  346.     if (old_fmonitor != flag[FMONITOR])
  347.         j_change();
  348. #endif
  349.  
  350.     /* set $# and $* */
  351.     if (*wp != NULL) {
  352.       setargs:
  353.         owp = --wp;
  354.         wp[0] = l->argv[0]; /* save $0 */
  355.         while (*++wp != NULL)
  356.             *wp = strsave(*wp, &l->area);
  357.         l->argc = wp - owp - 1;
  358.         l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area);
  359.         for (wp = l->argv; (*wp++ = *owp++) != NULL; )
  360.             ;
  361.         resetopts();
  362.     }
  363.     return 0;
  364. }
  365.  
  366. int
  367. c_unset(wp)
  368.     register char **wp;
  369. {
  370.     register char *id;
  371.     int flagf = 0;
  372.  
  373.     for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
  374.         if (*++id == 'f')
  375.             flagf++;
  376.     for (; (id = *wp) != NULL; wp++)
  377.         if (!flagf) {    /* unset variable */
  378.             unset(global(id));
  379.         } else {    /* unset function */
  380.             define(id, (struct op *)NULL);
  381.         }
  382.     return 0;
  383. }
  384.  
  385. int
  386. c_ulimit(wp)
  387.     register char **wp;
  388. {
  389.     extern int do_ulimit();
  390.  
  391.     return do_ulimit(wp[1], wp[2]);
  392. }
  393.  
  394. int
  395. c_times(wp)
  396.     char **wp;
  397. {
  398.     struct tms all;
  399.  
  400.     (void) times(&all);
  401.     printf("Shell: ");
  402.     printf("%8s user ", clocktos(all.tms_utime));
  403.     printf("%8s system\n", clocktos(all.tms_stime));
  404.     printf("Kids:  ");
  405.     printf("%8s user ", clocktos(all.tms_cutime));
  406.     printf("%8s system\n", clocktos(all.tms_cstime));
  407.  
  408.     return 0;
  409. }
  410.  
  411. /*
  412.  * time pipeline (really a statement, not a built-in comman)
  413.  */
  414. int
  415. timex(t, f)
  416.     struct op *t;
  417.     int f;
  418. {
  419.     int rv;
  420.     struct tms t0, t1;
  421.     clock_t t0t, t1t;
  422.     extern clock_t j_utime, j_stime; /* computed by j_wait */
  423.  
  424.     j_utime = j_stime = 0;
  425.     t0t = times(&t0);
  426.     rv = execute(t->left, f);
  427.     t1t = times(&t1);
  428.  
  429.     shellf("%8s real ", clocktos(t1t - t0t));
  430.     shellf("%8s user ",
  431.            clocktos(t1.tms_utime - t0.tms_utime + j_utime));
  432.     shellf("%8s system ",
  433.            clocktos(t1.tms_stime - t0.tms_stime + j_stime));
  434.     shellf("\n");
  435.  
  436.     return rv;
  437. }
  438.  
  439. static char *
  440. clocktos(t)
  441.     clock_t t;
  442. {
  443.     static char temp[20];
  444.     register int i;
  445.     register char *cp = temp + sizeof(temp);
  446.  
  447. #if CLK_TCK != 100        /* convert to 1/100'ths */
  448.     t = (t < 1000000000/CLK_TCK) ?
  449.         (t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
  450. #endif
  451.  
  452.     *--cp = '\0';
  453.     *--cp = 's';
  454.     for (i = -2; i <= 0 || t > 0; i++) {
  455.         if (i == 0)
  456.             *--cp = '.';
  457.         *--cp = '0' + (char)(t%10);
  458.         t /= 10;
  459.     }
  460.     return cp;
  461. }
  462.  
  463. /* dummy function, special case in comexec() */
  464. int
  465. c_exec(wp)
  466.     char ** wp;
  467. {
  468.     return 0;
  469. }
  470.  
  471. /* dummy function, special case in comexec() */
  472. int
  473. c_builtin(wp)
  474.     char ** wp;
  475. {
  476.     return 0;
  477. }
  478.  
  479. extern    int c_test();        /* in test.c */
  480.  
  481. const struct builtin shbuiltins [] = {
  482.     {"=:", c_label},
  483.     {"=.", c_dot},
  484.     {"[", c_test},
  485.     {"=builtin", c_builtin},
  486.     {"=exec", c_exec},
  487.     {"=shift", c_shift},
  488.     {"=wait", c_wait},
  489.     {"read", c_read},
  490.     {"=eval", c_eval},
  491.     {"=trap", c_trap},
  492.     {"=break", c_brkcont},
  493.     {"=continue", c_brkcont},
  494.     {"=exit", c_exit},
  495.     {"=return", c_return},
  496.     {"=set", c_set},
  497.     {"unset", c_unset},
  498.     {"umask", c_umask},
  499.     {"test", c_test},
  500.     {"=times", c_times},
  501.     {"ulimit", c_ulimit},
  502.     {NULL, NULL}
  503. };
  504.  
  505.