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