home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / pdksh-src.lha / src / amiga / pdksh / sh / c_ksh.c < prev    next >
C/C++ Source or Header  |  1993-12-01  |  12KB  |  598 lines

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