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_ksh.c < prev    next >
C/C++ Source or Header  |  1993-01-12  |  13KB  |  626 lines

  1. /*
  2.  * built-in Korn commands: c_*
  3.  */
  4.  
  5. #ifndef lint
  6. static char *RCSid = "$Id: c_ksh.c,v 1.3 1992/12/05 13:15:11 sjg Exp $";
  7. #endif
  8.  
  9. #include "stdh.h"
  10. #include <errno.h>
  11. #include <setjmp.h>
  12. #include "sh.h"
  13.  
  14.  
  15. int
  16. c_hash(wp)
  17.     register char **wp;
  18. {
  19.     register struct tbl *tp, **p;
  20.  
  21.     wp++;
  22.     if (*wp == NULL) {
  23.         for (p = tsort(&commands); (tp = *p++) != NULL; )
  24.             if ((tp->flag&ISSET))
  25.                 printf("%s\n", tp->val.s);
  26.         return 0;
  27.     }
  28.  
  29.     if (strcmp(*wp, "-r") == 0)
  30.         flushcom(1);
  31.     while (*wp != NULL)
  32.         findcom(*wp++, 1);
  33.     return 0;
  34. }
  35.  
  36. int
  37. c_cd(wp)
  38.     register char **wp;
  39. {
  40.     char path [PATH];
  41.     char newd [PATH];
  42.     register char *cp;
  43.     register char *dir;
  44.     register char *cdpath;
  45.     register char *rep;
  46.     register char *pwd = NULL, *oldpwd = NULL;
  47.     register int done = 0;
  48.     register int prt = 0;
  49.     register struct tbl *v_pwd = NULL, *v_oldpwd = NULL;
  50.  
  51.     if ((dir = wp[1]) == NULL && (dir = strval(global("HOME"))) == NULL)
  52.         errorf("no home directory");
  53.  
  54.     v_pwd = global("PWD");
  55.     if ((pwd = strval(v_pwd)) == null) {
  56.                 getcwd(path, (size_t)PATH);
  57.         setstr(v_pwd, path);
  58.         pwd = strval(v_pwd);
  59.     }
  60.  
  61.     if (wp[1] != NULL && (rep = wp[2]) != NULL) {
  62.         /*
  63.          * Two arg version: cd pat rep
  64.          */
  65.         if (strlen(pwd) - strlen(dir) + strlen(rep) >= PATH)
  66.             errorf("substitution too long\n");
  67.         cp = strstr(pwd, dir);
  68.         if (cp == NULL)
  69.             errorf("substitution failed\n");
  70.         strncpy(path, pwd, cp - pwd);        /* first part */
  71.         strcpy(path + (cp - pwd), rep);        /* replacement */
  72.         strcat(path, cp + strlen(dir));     /* last part */
  73.         dir = strsave(path, ATEMP);
  74.         prt = 1;
  75.     } else if (dir[0] == '-' && dir[1] == '\0') {
  76.         /*
  77.          * Change to previous dir: cd -
  78.          */
  79.         dir = strval(v_oldpwd = global("OLDPWD"));
  80.         prt = 1;
  81.     }
  82. #ifdef OS2
  83.     if (ISDIRSEP(dir[0]) || 
  84.         (dir[0] == '.' && 
  85.          (dir [1] == 0 || ISDIRSEP(dir[1]) ||
  86.           (dir[1] == '.' && (dir[2] == 0 || ISDIRSEP(dir[2]))))) ||
  87.             (isalpha(dir[0]) && dir[1] == ':') ) {
  88. #else
  89.     if (ISDIRSEP(dir[0]) || 
  90.         (dir[0] == '.' && 
  91.          (dir[1] == 0 || ISDIRSEP(dir[1]) ||
  92.           (dir[1] == '.' && (dir [2] == 0 || ISDIRSEP(dir[2])))))) {
  93. #endif
  94.         /*
  95.          * dir is an explicitly named path, so no CDPATH search
  96.          */
  97.         cleanpath(pwd, dir, newd);
  98.         if (chdir(newd) < 0)
  99.             errorf("%s: bad directory\n", newd);
  100.         else if (prt)
  101.             shellf("%s\n", newd);
  102.         flushcom(0);
  103.     } else {
  104.         /*
  105.          * search CDPATH for dir
  106.          */
  107.         cdpath = strval(global("CDPATH"));
  108.         while ( !done && cdpath != NULL ) {
  109.             cp = path;
  110. #ifdef OS2
  111.             while (*cdpath && *cdpath != ';')
  112. #else
  113.             while (*cdpath && *cdpath != ':')
  114. #endif
  115.                 *cp++ = *cdpath++;
  116.             if (*cdpath == '\0')
  117.                 cdpath = NULL;
  118.             else
  119.                 cdpath++;
  120.             if (prt = (cp > path)) {
  121.                 *cp++ = DIRSEP;
  122.                 (void) strcpy( cp, dir );
  123.                 cp = path;
  124.             } else
  125.                 cp = dir;
  126.  
  127.             cleanpath(pwd, cp, newd);
  128.             if (chdir(newd) == 0)
  129.                 done = 1;
  130.         } while (!done && cdpath != NULL);
  131.         if (!done)
  132.             errorf("%s: bad directory\n", dir);
  133.         if (prt)
  134.             shellf("%s\n", newd);
  135.         flushcom(0);
  136.     }
  137.  
  138.     /*
  139.      * Keep track of OLDPWD and PWD
  140.      */
  141.     oldpwd = pwd;
  142. #ifdef OS2
  143.         getcwd(path, (size_t)PATH);
  144.         pwd = path;
  145. #else
  146.     pwd = newd;
  147. #endif
  148.     if (!v_oldpwd)
  149.         v_oldpwd = global("OLDPWD");
  150.     if (oldpwd && *oldpwd)
  151.         setstr(v_oldpwd, oldpwd);
  152.     else
  153.         unset(v_oldpwd);
  154.     if (*pwd)
  155.         setstr(v_pwd, pwd);
  156.     else
  157.         unset(v_pwd);
  158.  
  159.     return 0;
  160. }
  161.  
  162. int
  163. c_print(wp)
  164.     register char **wp;
  165. {
  166.     int nl = 1;
  167.     int expand = 1;
  168.     FILE *f = stdout;
  169.  
  170.     for (wp++; *wp != NULL && **wp == '-'; wp++) {
  171.         register char *s = *wp + 1;
  172.         if (*s == '\0') {
  173.             wp++;
  174.             break;
  175.         }
  176.         while (*s) switch (*s++) {
  177.           case 'n':
  178.             nl = 0;
  179.             break;
  180.           case 'e':
  181.             expand = 1;
  182.             break;
  183.           case 'r':
  184.             expand = 0;
  185.             break;
  186.           case 'u':
  187.             if (!digit(*s) || (f = shf[*s++-'0']) == NULL)
  188.                 errorf("bad -u argument\n");
  189.             break;
  190.         }
  191.     }
  192.  
  193.     while (*wp != NULL) {
  194.         register char *s = *wp;
  195.         register int c;
  196.         while ((c = *s++) != '\0')
  197.             if (expand && c == '\\') {
  198.                 switch ((c = *s++)) {
  199.                 case 'b': c = '\b'; break;
  200.                 case 'c': nl = 0; continue; /* AT&T brain damage */
  201.                 case 'f': c = '\f'; break;
  202.                 case 'n': c = '\n'; break;
  203.                 case 'r': c = '\r'; break;
  204.                 case 't': c = '\t'; break;
  205.                 case 'v': c = 0x0B; break;
  206.                 case '0': case '1': case '2': case '3':
  207.                 case '4': case '5': case '6': case '7':
  208.                     c = c - '0';
  209.                     if (*s >= '0' && *s <= '7')
  210.                         c = 8*c + *s++ - '0';
  211.                     if (*s >= '0' && *s <= '7')
  212.                         c = 8*c + *s++ - '0';
  213.                     break;
  214.                 case '\\': break;
  215.                 default:
  216.                     putc('\\', f);
  217.                 }
  218.                 putc(c, f);
  219.             } else
  220.                 putc(c, f);
  221.         if (*++wp != NULL)
  222.             putc(' ', f);
  223.     }
  224.     if (nl)
  225.         putc('\n', f);
  226.     return 0;
  227. }
  228.  
  229. /* todo: handle case where id is both lexical and command */
  230. int
  231. c_whence(wp)
  232.     register char **wp;
  233. {
  234.     register struct tbl *tp;
  235.     char *id;
  236.     int vflag = 0;
  237.     int ret = 0;
  238.  
  239.     for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
  240.         if (id[1] == 'v')
  241.             vflag = 1;
  242.  
  243.     while ((id = *wp++) != NULL) {
  244.         tp = tsearch(&lexicals, id, hash(id));
  245.         if (tp == NULL)
  246.             tp = findcom(id, 0);
  247.         if (vflag)
  248.             switch ((tp == NULL) ? CNONE : tp->type) {
  249.               case CNONE:
  250.                 printf("%s is unknown\n", id);
  251.                 ret = 1;
  252.                 break;
  253.               case CSHELL:
  254.                 printf("%s is a shell builtin\n", id);
  255.                 break;
  256.               case CFUNC:
  257.                 printf("%s is a function\n", id);
  258.                 fptreef(stdout, "function %s %T\n", id, tp->val.t);
  259.                 break;
  260.               case CEXEC:
  261.                 printf("%s is %s\n", id,
  262.                        (tp->flag&ISSET) ? tp->val.s : "unknown");
  263.                 if (!(tp->flag&ISSET))
  264.                     ret = 1;
  265.                 break;
  266.               case CALIAS:
  267.                 printf("%s is the alias '%s'\n", id, tp->val.s);
  268.                 break;
  269.               case CKEYWD:
  270.                 printf("%s is a shell keyword\n", id);
  271.                 break;
  272.               default:
  273.                 printf("%s is *GOK*\n", id);
  274.                 break;
  275.             }
  276.         else
  277.             switch ((tp == NULL) ? CNONE : tp->type) {
  278.               case CNONE:
  279.                 printf("\n");
  280.                 ret = 1;
  281.                 break;
  282.               case CSHELL:
  283.                 printf("builtin %s\n", id);
  284.                 break;
  285.               case CFUNC:
  286.                 printf("%s\n", id);
  287.                 break;
  288.               case CEXEC:
  289.                 printf("%s\n", (tp->flag&ISSET) ? tp->val.s : "");
  290.                 if (!(tp->flag&ISSET))
  291.                     ret = 1;
  292.                 break;
  293.               case CALIAS:
  294.                 printf("%s\n", tp->val.s);
  295.                 break;
  296.               case CKEYWD:
  297.                 printf("%s\n", id);
  298.                 break;
  299.               default:
  300.                 printf("*GOK*\n");
  301.                 break;
  302.             }
  303.     }
  304.     return ret;
  305. }
  306.  
  307. /* typeset, export, and readonly */
  308. int
  309. c_typeset(wp)
  310.     register char **wp;
  311. {
  312.     register char *id;
  313.     struct block *l = e.loc;
  314.     register struct tbl *vp, **p;
  315.     int fset = 0, fclr = 0;
  316.     int thing = 0, func = 0, local = 0;
  317.  
  318.     switch (**wp) {
  319.       case 'e':        /* export */
  320.         fset |= EXPORT;
  321.         break;
  322.       case 'r':        /* readonly */
  323.         fset |= RDONLY;
  324.         break;
  325.       case 't':        /* typeset */
  326.         local = 1;
  327.         break;
  328.     }
  329.  
  330.     for (wp++; (id = *wp) != NULL && (*id == '-' || *id == '+'); wp++) {
  331.         int flag = 0;
  332.         thing = *id;
  333.         while (*++id != '\0') switch (*id) {
  334.           case 'f':
  335.             flag |= FUNCT;
  336.             func = 1;
  337.             break;
  338.           case 'i':
  339.             flag |= INTEGER;
  340.             break;
  341.           case 'r':
  342.             flag |= RDONLY;
  343.             break;
  344.           case 'x':
  345.             flag |= EXPORT;
  346.             break;
  347.           case 't':
  348.             flag |= TRACE;
  349.             break;
  350.           default:
  351.             errorf("unknown flag -%c\n", *id);
  352.         }
  353.         if (flag != 0) { /* + or - with options */
  354.             if (thing == '-')
  355.                 fset |= flag;
  356.             else
  357.                 fclr |= flag;
  358.             thing = 0;
  359.         }
  360.     }
  361.  
  362.     /* list variables and attributes */
  363.     if (*wp == NULL) {
  364.         for (l = e.loc; l != NULL; l = l->next) {
  365.             for (p = tsort((func==0) ? &l->vars : &l->funs);
  366.              (vp = *p++) != NULL; )
  367.             if ((vp->flag&ISSET))
  368.                 if (thing == 0 && fclr == 0 && fset == 0) {
  369.                 printf("typeset ");
  370.                 if ((vp->flag&INTEGER))
  371.                     printf("-i ");
  372.                 if ((vp->flag&EXPORT))
  373.                     printf("-x ");
  374.                 if ((vp->flag&RDONLY))
  375.                     printf("-r ");
  376.                 if ((vp->flag&TRACE))
  377.                     printf("-t ");
  378.                 printf("%s\n", vp->name);
  379.                 } else
  380.                 if (thing == '+' ||
  381.                 (fclr && (vp->flag&fclr) == fclr)) {
  382.                 printf("%s\n", vp->name);
  383.                 } else
  384.                 if (thing == '-' ||
  385.                 (fset && (vp->flag&fset) == fset)) {
  386.                 if (fset&FUNCT)
  387.                     printf("function %s\n", vp->name);
  388.                 else
  389.                     printf("%s=%s\n", vp->name, strval(vp));
  390.                 }
  391.         }
  392.         return (0);
  393.     }
  394.  
  395.     if (local)
  396.         fset |= LOCAL;
  397.     for (; *wp != NULL; wp++)
  398. #if 0
  399.         if (func) {
  400.         } else
  401. #endif
  402.         if (typeset(*wp, fset, fclr) == NULL)
  403.             errorf("%s: not identifier\n", *wp);
  404.     return 0;
  405. }
  406.  
  407. int
  408. c_alias(wp)
  409.     register char **wp;
  410. {
  411.     register struct table *t = &lexicals;
  412.     register struct tbl *ap, **p;
  413.     int rv = 0;
  414.  
  415.     if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
  416.         t = &homedirs;
  417.         wp++;
  418.     }
  419.  
  420.     if (*wp == NULL)
  421.         for (p = tsort(t); (ap = *p++) != NULL; )
  422.             if (ap->type == CALIAS && (ap->flag&DEFINED))
  423.                 printf("%s='%s'\n", ap->name, ap->val.s);
  424.  
  425.     for (; *wp != NULL; wp++) {
  426.         register char *id = *wp;
  427.         register char *val = strchr(id, '=');
  428.  
  429.         if (val == NULL) {
  430.             ap = tsearch(t, id, hash(id));
  431.             if (ap != NULL && ap->type == CALIAS && (ap->flag&DEFINED))
  432.                 printf("%s='%s'\n", ap->name, ap->val.s);
  433.             else
  434.                 rv = 1;
  435.         } else {
  436.             *val++ = '\0';
  437.             ap = tenter(t, id, hash(id));
  438.             if (ap->type == CKEYWD)
  439.                 errorf("cannot alias keyword\n");
  440.             if ((ap->flag&ALLOC)) {
  441.                 afree((void*)ap->val.s, APERM);
  442.                 ap->flag &= ~(ALLOC|ISSET);
  443.             }
  444.             ap->type = CALIAS;
  445.             ap->val.s = strsave(val, APERM);
  446.             ap->flag |= DEFINED|ALLOC|ISSET;
  447.         }
  448.     }
  449.     return rv;
  450. }
  451.  
  452. int
  453. c_unalias(wp)
  454.     register char **wp;
  455. {
  456.     register struct table *t = &lexicals;
  457.     register struct tbl *ap;
  458.  
  459.     if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
  460.         t = &homedirs;
  461.         wp++;
  462.     }
  463.  
  464.     for (; *wp != NULL; wp++) {
  465.         ap = tsearch(t, *wp, hash(*wp));
  466.         if (ap == NULL || ap->type != CALIAS)
  467.             continue;
  468.         if ((ap->flag&ALLOC))
  469.             afree((void*)ap->val.s, APERM);
  470.         ap->flag &= ~(DEFINED|ISSET|ALLOC);
  471.     }
  472.     return 0;
  473. }
  474.  
  475. int
  476. c_let(wp)
  477.     char **wp;
  478. {
  479.     int rv = 1;
  480.  
  481.     for (wp++; *wp; wp++)
  482.         rv = evaluate(*wp) == 0;
  483.     return rv;
  484. }
  485.  
  486. int
  487. c_jobs(wp)
  488.     char **wp;
  489. {
  490.     j_jobs();
  491.     return 0;
  492. }
  493.  
  494. #ifdef JOBS
  495. int
  496. c_fgbg(wp)
  497.     register char **wp;
  498. {
  499.     int bg = strcmp(*wp, "bg") == 0;
  500.  
  501.     if (!flag[FMONITOR])
  502.         errorf("Job control not enabled\n");
  503.     wp++;
  504.     j_resume(j_lookup((*wp == NULL) ? "%" : *wp), bg);
  505.     return 0;
  506. }
  507. #endif
  508.  
  509. int
  510. c_kill(wp)
  511.     register char **wp;
  512. {
  513.     register char *cp;
  514.     int sig = 15;        /* SIGTERM */
  515.     int rv = 0;
  516.     int n;
  517.     int gotsig = FALSE;
  518.  
  519.     if (*++wp == NULL)
  520.         errorf("Usage: kill [-l] [-signal] {pid|job} ...\n");
  521.     if (strcmp(*wp, "-l") == 0) {
  522.         register struct trap *p = sigtraps;
  523.         for (sig = 0; sig < SIGNALS; sig++, p++)
  524.             if (p->signal)
  525.                 printf("%2d %8s %s\n", p->signal, p->name, p->mess);
  526.         return 0;
  527.     }
  528.  
  529.     for (; (cp = *wp) != NULL; wp++)
  530.         if (*cp == '-' && gotsig == FALSE && *(wp+1) != NULL) {
  531.             struct trap *p;
  532.             gotsig = FALSE;
  533.             if (digit(*(cp+1))) {
  534.                 if ((n = atoi(cp+1)) < SIGNALS) {
  535.                     sig = n;
  536.                     gotsig = TRUE;
  537.                 } else if (kill(n, sig) < 0) {
  538.                     shellf("%s: %s\n", cp, strerror(errno));
  539.                     rv++;
  540.                 }
  541.             } else {
  542.                 p = gettrap(cp+1);
  543.                 if (p == NULL)
  544.                     errorf("bad signal %s\n", cp+1);
  545.                 sig = p->signal;
  546.                 gotsig = TRUE;
  547.             }
  548.         } else {
  549.             gotsig = FALSE;
  550.             if (digit(*cp) || (*cp == '-' && digit(*(cp+1)))) {
  551.                 if (kill(atoi(cp), sig) < 0) {
  552.                     shellf("%s: %s\n", cp, strerror(errno));
  553.                     rv++;
  554.                 }
  555.             } else
  556.             if (*cp == '%')
  557.                 j_kill(j_lookup(cp), sig);
  558.             else
  559.                 errorf("invalid argument\n");
  560.         }
  561.     return rv;
  562. }
  563.  
  564. #ifdef EMACS
  565. int
  566. c_bind(wp)
  567.     register char **wp;
  568. {
  569.     int macro = 0;
  570.     register char *cp;
  571.  
  572.     for (wp++; (cp = *wp) != NULL && *cp == '-'; wp++)
  573.         if (cp[1] == 'm')
  574.             macro = 1;
  575.  
  576.     if (*wp == NULL)    /* list all */
  577.         x_bind((char*)NULL, (char*)NULL, 0);
  578.  
  579.     for (; *wp != NULL; wp++) {
  580.         cp = strchr(*wp, '=');
  581.         if (cp != NULL)
  582.             *cp++ = 0;
  583.         x_bind(*wp, cp, macro);
  584.     }
  585.  
  586.     return 0;
  587. }
  588.  
  589. int
  590. c_nothing(wp)
  591.     register char **wp;
  592. {
  593.     return 0;
  594. }
  595. #endif
  596.  
  597. extern    c_fc();
  598. extern    c_getopts();
  599.  
  600. const struct builtin kshbuiltins [] = {
  601.     {"cd", c_cd},
  602.     {"print", c_print},
  603.     {"getopts", c_getopts},
  604.     {"=typeset", c_typeset},
  605.     {"=export", c_typeset},
  606.     {"=readonly", c_typeset},
  607.     {"whence", c_whence},
  608.     {"=alias", c_alias},
  609.     {"unalias", c_unalias},
  610.     {"hash", c_hash},
  611.     {"let", c_let},
  612.     {"fc", c_fc},
  613.     {"jobs", c_jobs},
  614.     {"kill", c_kill},
  615.         {"extproc", c_nothing},
  616. #ifdef JOBS
  617.     {"fg", c_fgbg},
  618.     {"bg", c_fgbg},
  619. #endif
  620. #ifdef EMACS
  621.     {"bind", c_bind},
  622. #endif
  623.     {NULL, NULL}
  624. };
  625.  
  626.