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_ksh.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  12KB  |  616 lines

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