home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume25 / pdksh / part05 < prev    next >
Text File  |  1991-11-12  |  56KB  |  2,815 lines

  1. Newsgroups: comp.sources.misc
  2. From: sjg@zen.void.oz.au (Simon J. Gerraty)
  3. Subject:  v25i051:  pdksh - Public Domain Korn Shell, v4, Part05/09
  4. Message-ID: <1991Nov13.031141.16071@sparky.imd.sterling.com>
  5. X-Md4-Signature: caab833c4db7863094df7fd7ea6c1d2f
  6. Date: Wed, 13 Nov 1991 03:11:41 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: sjg@zen.void.oz.au (Simon J. Gerraty)
  10. Posting-number: Volume 25, Issue 51
  11. Archive-name: pdksh/part05
  12. Environment: UNIX
  13.  
  14. #! /bin/sh
  15. # into a shell via "sh file" or similar.  To overwrite existing files,
  16. # type "sh file -c".
  17. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  18. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  19. # Contents:  sh/c_sh.c sh/c_test.c sh/edit.c sh/history.c sh/main.c
  20. #   sh/tree.c std/stdc/stdio.c
  21. # Wrapped by kent@sparky on Tue Nov 12 20:44:33 1991
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 5 (of 9)."'
  25. if test -f 'sh/c_sh.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'sh/c_sh.c'\"
  27. else
  28.   echo shar: Extracting \"'sh/c_sh.c'\" \(8560 characters\)
  29.   sed "s/^X//" >'sh/c_sh.c' <<'END_OF_FILE'
  30. X/*
  31. X * built-in Bourne commands
  32. X */
  33. X
  34. X#ifndef lint
  35. Xstatic char *RCSid = "Id: /u/egisin/sh/src/RCS/c_sh.c,v 3.1 88/11/03 09:14:31 egisin Exp $";
  36. Xstatic char *sccs_id = "@(#)c_sh.c    1.3 91/11/09 15:35:24 (sjg)";
  37. X#endif
  38. X
  39. X#include <stddef.h>
  40. X#include <stdio.h>
  41. X#include <string.h>
  42. X#include <errno.h>
  43. X#include <signal.h>
  44. X#include <setjmp.h>
  45. X#include <sys/times.h>
  46. X#include <unistd.h>        /* getcwd */
  47. X#include "sh.h"
  48. X#include "lex.h"
  49. X#include "tree.h"
  50. X#include "table.h"
  51. X
  52. Xstatic    char *clocktos();
  53. X
  54. Xint
  55. Xc_label(wp)
  56. X    char **wp;
  57. X{
  58. X    return 0;
  59. X}
  60. X
  61. Xint
  62. Xc_shift(wp)
  63. X    register char **wp;
  64. X{
  65. X    register struct block *l = e.loc;
  66. X    register int n;
  67. X
  68. X    n = wp[1] ? evaluate(wp[1]) : 1;
  69. X    if (l->argc < n) {
  70. X        errorf("nothing to shift\n");
  71. X        return (1);
  72. X    }
  73. X    l->argv[n] = l->argv[0];
  74. X    l->argv += n;
  75. X    l->argc -= n;
  76. X    return 0;
  77. X}
  78. X
  79. Xint
  80. Xc_umask(wp)
  81. X    register char **wp;
  82. X{
  83. X    register int i;
  84. X    register char *cp;
  85. X
  86. X    if ((cp = wp[1]) == NULL) {
  87. X        i = umask(0);
  88. X        umask(i);
  89. X        printf("%#3.3o\n", i);    /* should this be shell output? */
  90. X    } else {
  91. X        for (i = 0; *cp>='0' && *cp<='7'; cp++)
  92. X            i = i*8 + (*cp-'0');
  93. X        umask(i);
  94. X    }
  95. X    return 0;
  96. X}
  97. X
  98. Xint
  99. Xc_dot(wp)
  100. X    char **wp;
  101. X{
  102. X    char *file, *cp;
  103. X
  104. X    if ((cp = wp[1]) == NULL)
  105. X        return 0;
  106. X    file = search(cp, path, 0);
  107. X    if (file == NULL)
  108. X        errorf("%s: not found\n", cp);
  109. X    if (include(file))
  110. X        return exstat;
  111. X    return -1;
  112. X}
  113. X
  114. Xint
  115. Xc_wait(wp)
  116. X    char **wp;
  117. X{
  118. X    register char *cp;
  119. X
  120. X    wp++;
  121. X    cp = *wp;
  122. X    if (cp == NULL) cp = "%";
  123. X    /* todo: print status ? */
  124. X    return waitfor(j_lookup(cp));
  125. X}
  126. X
  127. Xint
  128. Xc_read(wp)
  129. X    register char **wp;
  130. X{
  131. X    register int c = 0;
  132. X    FILE *f = stdin;
  133. X    int expand = 1;
  134. X    register char *cp;
  135. X
  136. X    for (wp++; (cp = *wp) != NULL && *cp++ == '-'; wp++) {
  137. X        while (*cp) switch (*cp++) {
  138. X          case 'e':
  139. X            expand = 1;
  140. X            break;
  141. X          case 'r':
  142. X            expand = 0;
  143. X            break;
  144. X          case 'u':
  145. X            if (!digit(*cp) || (f = shf[*cp++-'0']) == NULL)
  146. X                errorf("bad -u argument\n");
  147. X            break;
  148. X        }
  149. X    }
  150. X
  151. X    if (*wp == NULL)
  152. X        errorf("missing name\n");
  153. X    if ((cp = strchr(*wp, '?')) != NULL) {
  154. X        *cp = 0;
  155. X        if (flag[FTALKING]) {
  156. X            shellf("%s ", cp+1);
  157. X            fflush(shlout);
  158. X        }
  159. X    }
  160. X
  161. X    for (; *wp != NULL; wp++) {
  162. X        for (cp = line; cp <= line+LINE; ) {
  163. X            if (c == '\n')
  164. X                break;
  165. X            c = getc(f);
  166. X            if (c == EOF)
  167. X                return 1;
  168. X            if (expand && c == '\\') {
  169. X                c = getc(f);
  170. X                if (c == '\n')
  171. X                    c = 0;
  172. X                else
  173. X                    *cp++ = c;
  174. X                continue;
  175. X            }
  176. X            if (c == '\n' || wp[1] && ctype(c, C_IFS))
  177. X                break;
  178. X            *cp++ = c;
  179. X        }
  180. X        *cp = 0;
  181. X        setstr(global(*wp), line);
  182. X    }
  183. X    return 0;
  184. X}
  185. X
  186. Xint
  187. Xc_eval(wp)
  188. X    register char **wp;
  189. X{
  190. X    register struct source *s;
  191. X
  192. X    s = pushs(SWORDS);
  193. X    s->u.strv = wp+1;
  194. X    return shell(s);
  195. X}
  196. X
  197. Xvoid setsig ARGS((struct trap *p, handler_t f));
  198. X
  199. Xint
  200. Xc_trap(wp)
  201. X    register char **wp;
  202. X{
  203. X    int i;
  204. X    char *s;
  205. X    register struct trap *p;
  206. X
  207. X    wp++;
  208. X    if (*wp == NULL) {
  209. X        for (p = sigtraps, i = SIGNALS; --i >= 0; p++) {
  210. X            if (p->trap != NULL)
  211. X                shellf("%s: %s\n", p->name, p->trap);
  212. X        }
  213. X        return 0;
  214. X    }
  215. X
  216. X    s = (gettrap(*wp) == NULL) ? *wp++ : NULL; /* get command */
  217. X    if (s != NULL && s[0] == '-' && s[1] == '\0')
  218. X        s = NULL;
  219. X
  220. X    /* set/clear traps */
  221. X    while (*wp != NULL) {
  222. X        p = gettrap(*wp++);
  223. X        if (p == NULL)
  224. X            errorf("trap: bad signal %s\n", wp[-1]);
  225. X        if (p->trap != NULL)
  226. X            afree((Void*)p->trap, APERM);
  227. X        p->trap = NULL;
  228. X        if (s != NULL) {
  229. X            if (strlen(s) != 0) {
  230. X                p->trap = strsave(s, APERM);
  231. X                setsig(p, trapsig);
  232. X            } else
  233. X                setsig(p, (handler_t)SIG_IGN);
  234. X        } else
  235. X            /* todo: restore to orginal value */
  236. X            setsig(p,
  237. X               (p->signal==SIGINT || p->signal==SIGQUIT) && flag[FTALKING]
  238. X               ? (handler_t)SIG_IGN : (handler_t)SIG_DFL);
  239. X    }
  240. X    return 0;
  241. X}
  242. X
  243. Xvoid
  244. Xsetsig(p, f)
  245. X    register struct trap *p;
  246. X    void (*f)();
  247. X{
  248. X    if (p->signal == 0)
  249. X        return;
  250. X    if (signal(p->signal, SIG_IGN) != SIG_IGN || p->ourtrap) {
  251. X        p->ourtrap = 1;
  252. X        signal(p->signal, f);
  253. X    }
  254. X}
  255. X
  256. Xint
  257. Xc_return(wp)
  258. X    char **wp;
  259. X{
  260. X    wp++;
  261. X    if (*wp != NULL)
  262. X        exstat = getn(*wp);
  263. X    quitenv();        /* pop E_TCOM */
  264. X    while (e.type == E_LOOP || e.type == E_EXEC)
  265. X        quitenv();
  266. X    if (e.type == E_FUNC)
  267. X        longjmp(e.jbuf, 1);
  268. X    leave(exstat);
  269. X}
  270. X
  271. Xint
  272. Xc_brkcont(wp)
  273. X    register char **wp;
  274. X{
  275. X    int quit;
  276. X
  277. X    quit = wp[1] == NULL ? 1 : getn(wp[1]);
  278. X    quitenv();        /* pop E_TCOM */
  279. X    while (e.type == E_LOOP || e.type == E_EXEC) {
  280. X        if (e.type == E_LOOP && --quit <= 0)
  281. X            longjmp(e.jbuf, (*wp[0] == 'b') ? LBREAK : LCONTIN);
  282. X        quitenv();
  283. X    }
  284. X    errorf("cannot %s\n", wp[0]);
  285. X}
  286. X
  287. X
  288. X/* 91-05-27 <sjg>
  289. X * we are supposed to not exit first try
  290. X * if there are stopped jobs.
  291. X */
  292. Xint
  293. Xc_exit(wp)
  294. X    char **wp;
  295. X{
  296. X    register char *cp;
  297. X    static int extry = 0;
  298. X    
  299. X#ifdef JOBS
  300. X    if (extry++ == 0)
  301. X    {
  302. X      if (flag[FMONITOR] && j_stopped()) /* todo: only once */
  303. X      {
  304. X        errorf("There are stopped jobs\n");
  305. X        return 1;
  306. X      }
  307. X    }
  308. X#endif
  309. X    e.oenv = NULL;
  310. X    if ((cp = wp[1]) != NULL)
  311. X        exstat = getn(cp);
  312. X    leave(exstat);
  313. X}
  314. X
  315. Xint
  316. Xc_set(wp)
  317. X    register char **wp;
  318. X{
  319. X    struct block *l = e.loc;
  320. X    register struct tbl *vp, **p;
  321. X    register char **owp = wp;
  322. X    register char *cp;
  323. X    int old_fmonitor = flag[FMONITOR];
  324. X
  325. X    if ((cp = *++wp) == NULL) {
  326. X        static char * Const args [] = {"set", "-", NULL};
  327. X        extern int c_typeset ARGS((char **args));
  328. X        return c_typeset(args);
  329. X    }
  330. X    
  331. X    for (; (cp = *wp) != NULL && (*cp == '-' || *cp == '+');) {
  332. X        int i, n = *cp++ == '-'; /* set or clear flag */
  333. X        wp++;
  334. X        if (*cp == '\0') {
  335. X            if (n)
  336. X                flag[FXTRACE] = flag[FVERBOSE] = 0;
  337. X            break;
  338. X        }
  339. X        if (*cp == '-')
  340. X            goto setargs;
  341. X        for (; *cp != '\0'; cp++)
  342. X            if (*cp == 'o') {
  343. X                if (*wp == NULL) {
  344. X                    printoptions();
  345. X                    return 0;
  346. X                }
  347. X                i = option(*wp++);
  348. X                if (i == 0)
  349. X                    shellf("%s: unknown option\n", *--wp);
  350. X                flag[i] = n;
  351. X                if (i == FEMACS && n)
  352. X                    flag[FVI] = 0;
  353. X                else if (i == FVI && n)
  354. X                    flag[FEMACS] = 0;
  355. X            } else if (*cp>='a' && *cp<='z')
  356. X                flag[FLAG(*cp)] = n;
  357. X            else
  358. X                errorf("%c: bad flag\n", *cp);
  359. X        if (flag[FTALKING])
  360. X            flag[FERREXIT] = 0;
  361. X    }
  362. X
  363. X#ifdef JOBS
  364. X    if (old_fmonitor != flag[FMONITOR])
  365. X        j_change();
  366. X#endif
  367. X
  368. X    /* set $# and $* */
  369. X    if (*wp != NULL) {
  370. X      setargs:
  371. X        owp = --wp;
  372. X        wp[0] = l->argv[0]; /* save $0 */
  373. X        while (*++wp != NULL)
  374. X            *wp = strsave(*wp, &l->area);
  375. X        l->argc = wp - owp - 1;
  376. X        l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area);
  377. X        for (wp = l->argv; (*wp++ = *owp++) != NULL; )
  378. X            ;
  379. X        resetopts();
  380. X    }
  381. X    return 0;
  382. X}
  383. X
  384. Xint
  385. Xc_unset(wp)
  386. X    register char **wp;
  387. X{
  388. X    register char *id;
  389. X    int flagf = 0;
  390. X
  391. X    for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
  392. X        if (*++id == 'f')
  393. X            flagf++;
  394. X    for (; (id = *wp) != NULL; wp++)
  395. X        if (!flagf) {    /* unset variable */
  396. X            unset(global(id));
  397. X        } else {    /* unset function */
  398. X            define(id, (struct op *)NULL);
  399. X        }
  400. X    return 0;
  401. X}
  402. X
  403. Xint
  404. Xc_ulimit(wp)
  405. X    register char **wp;
  406. X{
  407. X    extern int do_ulimit();
  408. X
  409. X    return do_ulimit(wp[1], wp[2]);
  410. X}
  411. X
  412. Xint
  413. Xc_times(wp)
  414. X    char **wp;
  415. X{
  416. X    struct tms all;
  417. X
  418. X    (void) times(&all);
  419. X    printf("Shell: ");
  420. X    printf("%8s user ", clocktos(all.tms_utime));
  421. X    printf("%8s system\n", clocktos(all.tms_stime));
  422. X    printf("Kids:  ");
  423. X    printf("%8s user ", clocktos(all.tms_cutime));
  424. X    printf("%8s system\n", clocktos(all.tms_cstime));
  425. X
  426. X    return 0;
  427. X}
  428. X
  429. X/*
  430. X * time pipeline (really a statement, not a built-in comman)
  431. X */
  432. Xint
  433. Xtimex(t, f)
  434. X    struct op *t;
  435. X    int f;
  436. X{
  437. X    int rv;
  438. X    struct tms t0, t1;
  439. X    clock_t t0t, t1t;
  440. X    extern clock_t j_utime, j_stime; /* computed by j_wait */
  441. X
  442. X    j_utime = j_stime = 0;
  443. X    t0t = times(&t0);
  444. X    rv = execute(t->left, f);
  445. X    t1t = times(&t1);
  446. X
  447. X    shellf("%8s real ", clocktos(t1t - t0t));
  448. X    shellf("%8s user ",
  449. X           clocktos(t1.tms_utime - t0.tms_utime + j_utime));
  450. X    shellf("%8s system ",
  451. X           clocktos(t1.tms_stime - t0.tms_stime + j_stime));
  452. X    shellf("\n");
  453. X
  454. X    return rv;
  455. X}
  456. X
  457. Xstatic char *
  458. Xclocktos(t)
  459. X    clock_t t;
  460. X{
  461. X    static char temp[20];
  462. X    register int i;
  463. X    register char *cp = temp + sizeof(temp);
  464. X
  465. X#if CLK_TCK != 100        /* convert to 1/100'ths */
  466. X    t = (t < 1000000000/CLK_TCK) ?
  467. X        (t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
  468. X#endif
  469. X
  470. X    *--cp = '\0';
  471. X    *--cp = 's';
  472. X    for (i = -2; i <= 0 || t > 0; i++) {
  473. X        if (i == 0)
  474. X            *--cp = '.';
  475. X        *--cp = '0' + (char)(t%10);
  476. X        t /= 10;
  477. X    }
  478. X    return cp;
  479. X}
  480. X
  481. X/* dummy function, special case in comexec() */
  482. Xint
  483. Xc_exec(wp)
  484. X    char ** wp;
  485. X{
  486. X    return 0;
  487. X}
  488. X
  489. X/* dummy function, special case in comexec() */
  490. Xint
  491. Xc_builtin(wp)
  492. X    char ** wp;
  493. X{
  494. X    return 0;
  495. X}
  496. X
  497. Xextern    int c_test();        /* in test.c */
  498. X
  499. XConst struct builtin shbuiltins [] = {
  500. X    {"=:", c_label},
  501. X    {"=.", c_dot},
  502. X    {"[", c_test},
  503. X    {"=builtin", c_builtin},
  504. X    {"=exec", c_exec},
  505. X    {"=shift", c_shift},
  506. X    {"=wait", c_wait},
  507. X    {"read", c_read},
  508. X    {"=eval", c_eval},
  509. X    {"=trap", c_trap},
  510. X    {"=break", c_brkcont},
  511. X    {"=continue", c_brkcont},
  512. X    {"=exit", c_exit},
  513. X    {"=return", c_return},
  514. X    {"=set", c_set},
  515. X    {"unset", c_unset},
  516. X    {"umask", c_umask},
  517. X    {"test", c_test},
  518. X    {"=times", c_times},
  519. X    {"ulimit", c_ulimit},
  520. X    {NULL, NULL}
  521. X};
  522. X
  523. END_OF_FILE
  524.   if test 8560 -ne `wc -c <'sh/c_sh.c'`; then
  525.     echo shar: \"'sh/c_sh.c'\" unpacked with wrong size!
  526.   fi
  527.   # end of 'sh/c_sh.c'
  528. fi
  529. if test -f 'sh/c_test.c' -a "${1}" != "-c" ; then 
  530.   echo shar: Will not clobber existing file \"'sh/c_test.c'\"
  531. else
  532.   echo shar: Extracting \"'sh/c_test.c'\" \(7284 characters\)
  533.   sed "s/^X//" >'sh/c_test.c' <<'END_OF_FILE'
  534. X/*
  535. X * test(1); version 7-like  --  author Erik Baalbergen
  536. X * modified by Eric Gisin to be used as built-in.
  537. X * modified by Arnold Robbins to add SVR3 compatibility
  538. X * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
  539. X */
  540. X
  541. Xstatic char *RCSid = "$Id: c_test.c,v 3.3 89/03/27 15:47:25 egisin Exp $";
  542. X
  543. X#include <stddef.h>
  544. X#include <string.h>
  545. X#include <signal.h>
  546. X#include <errno.h>
  547. X#include <setjmp.h>
  548. X#include <sys/types.h>
  549. X#include <sys/stat.h>
  550. X#include "sh.h"
  551. X
  552. X/* test(1) accepts the following grammar:
  553. X    oexpr    ::= aexpr | aexpr "-o" oexpr ;
  554. X    aexpr    ::= nexpr | nexpr "-a" aexpr ;
  555. X    nexpr    ::= primary ! "!" primary
  556. X    primary    ::= unary-operator operand
  557. X        | operand binary-operator operand
  558. X        | operand
  559. X        | "(" oexpr ")"
  560. X        ;
  561. X    unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
  562. X        "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
  563. X
  564. X    binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
  565. X            "-nt"|"-ot"|"-ef";
  566. X    operand ::= <any legal UNIX file name>
  567. X*/
  568. X
  569. X#define EOI    0
  570. X#define FILRD    1
  571. X#define FILWR    2
  572. X#define FILREG    3
  573. X#define FILID    4
  574. X#define FILGZ    5
  575. X#define FILTT    6
  576. X#define STZER    7
  577. X#define STNZE    8
  578. X#define STEQL    9
  579. X#define STNEQ    10
  580. X#define INTEQ    11
  581. X#define INTNE    12
  582. X#define INTGE    13
  583. X#define INTGT    14
  584. X#define INTLE    15
  585. X#define INTLT    16
  586. X#define UNOT    17
  587. X#define BAND    18
  588. X#define BOR    19
  589. X#define LPAREN    20
  590. X#define RPAREN    21
  591. X#define OPERAND    22
  592. X#define FILEX    23
  593. X#define FILCDEV    24
  594. X#define FILBDEV    25
  595. X#define FILFIFO    26
  596. X#define FILSETU    27
  597. X#define FILSETG    28
  598. X#define FILSTCK    29
  599. X#define FILSYM    30
  600. X#define FILNT    31
  601. X#define FILOT    32
  602. X#define FILEQ    33
  603. X#define FILSOCK    34
  604. X#define    FILUID    35
  605. X#define    FILGID    36
  606. X#define    OPTION    37
  607. X
  608. X#define UNOP    1
  609. X#define BINOP    2
  610. X#define BUNOP    3
  611. X#define BBINOP    4
  612. X#define PAREN    5
  613. X
  614. Xstruct t_op {
  615. X    char *op_text;
  616. X    short op_num, op_type;
  617. X} Const ops [] = {
  618. X    {"-r",    FILRD,    UNOP},
  619. X    {"-w",    FILWR,    UNOP},
  620. X    {"-x",    FILEX,    UNOP},
  621. X    {"-f",    FILREG,    UNOP},
  622. X    {"-d",    FILID,    UNOP},
  623. X    {"-c",    FILCDEV,UNOP},
  624. X    {"-b",    FILBDEV,UNOP},
  625. X    {"-p",    FILFIFO,UNOP},
  626. X    {"-u",    FILSETU,UNOP},
  627. X    {"-g",    FILSETG,UNOP},
  628. X    {"-k",    FILSTCK,UNOP},
  629. X    {"-s",    FILGZ,    UNOP},
  630. X    {"-t",    FILTT,    UNOP},
  631. X    {"-z",    STZER,    UNOP},
  632. X    {"-n",    STNZE,    UNOP},
  633. X#if 0                /* conficts with binary -o */
  634. X    {"-o",    OPTION,    UNOP},
  635. X#endif
  636. X    {"-U",    FILUID,    UNOP},
  637. X    {"-G",    FILGID,    UNOP},
  638. X    {"-L",    FILSYM,    UNOP},
  639. X    {"-S",    FILSOCK,UNOP},
  640. X    {"=",    STEQL,    BINOP},
  641. X    {"!=",    STNEQ,    BINOP},
  642. X    {"-eq",    INTEQ,    BINOP},
  643. X    {"-ne",    INTNE,    BINOP},
  644. X    {"-ge",    INTGE,    BINOP},
  645. X    {"-gt",    INTGT,    BINOP},
  646. X    {"-le",    INTLE,    BINOP},
  647. X    {"-lt",    INTLT,    BINOP},
  648. X    {"-nt",    FILNT,    BINOP},
  649. X    {"-ot",    FILOT,    BINOP},
  650. X    {"-ef",    FILEQ,    BINOP},
  651. X    {"!",    UNOT,    BUNOP},
  652. X    {"-a",    BAND,    BBINOP},
  653. X    {"-o",    BOR,    BBINOP},
  654. X    {"(",    LPAREN,    PAREN},
  655. X    {")",    RPAREN,    PAREN},
  656. X    {0,    0,    0}
  657. X};
  658. X
  659. Xchar **t_wp;
  660. Xstruct t_op Const *t_wp_op;
  661. X
  662. Xstatic void syntax();
  663. X
  664. Xint
  665. Xc_test(wp)
  666. X    char **wp;
  667. X{
  668. X    int    res;
  669. X
  670. X    t_wp = wp+1;
  671. X    if (strcmp(wp[0], "[") == 0) {
  672. X        while (*wp != NULL)
  673. X            wp++;
  674. X        if (strcmp(*--wp, "]") != 0)
  675. X            errorf("[: missing ]\n");
  676. X        *wp = NULL;
  677. X    }
  678. X    res = *t_wp == NULL || !oexpr(t_lex(*t_wp));
  679. X
  680. X    if (*t_wp != NULL && *++t_wp != NULL)
  681. X        syntax(*t_wp, "unknown operand");
  682. X
  683. X    return res;
  684. X}
  685. X
  686. Xstatic void
  687. Xsyntax(op, msg)
  688. X    char    *op;
  689. X    char    *msg;
  690. X{
  691. X    if (op && *op)
  692. X        errorf("test: %s: %s\n", op, msg);
  693. X    else
  694. X        errorf("test: %s\n", msg);
  695. X}
  696. X
  697. Xoexpr(n)
  698. X{
  699. X    int res;
  700. X
  701. X    res = aexpr(n);
  702. X    if (t_lex(*++t_wp) == BOR)
  703. X        return oexpr(t_lex(*++t_wp)) || res;
  704. X    t_wp--;
  705. X    return res;
  706. X}
  707. X
  708. Xaexpr(n)
  709. X{
  710. X    int res;
  711. X
  712. X    res = nexpr(n);
  713. X    if (t_lex(*++t_wp) == BAND)
  714. X        return aexpr(t_lex(*++t_wp)) && res;
  715. X    t_wp--;
  716. X    return res;
  717. X}
  718. X
  719. Xnexpr(n)
  720. X    int n;            /* token */
  721. X{
  722. X    if (n == UNOT)
  723. X        return !nexpr(t_lex(*++t_wp));
  724. X    return primary(n);
  725. X}
  726. X
  727. Xprimary(n)
  728. X    int n;            /* token */
  729. X{
  730. X    register char *opnd1, *opnd2;
  731. X    int res;
  732. X
  733. X    if (n == EOI)
  734. X        syntax(NULL, "argument expected");
  735. X    if (n == LPAREN) {
  736. X        res = oexpr(t_lex(*++t_wp));
  737. X        if (t_lex(*++t_wp) != RPAREN)
  738. X            syntax(NULL, "closing paren expected");
  739. X        return res;
  740. X    }
  741. X    if (t_wp_op && t_wp_op->op_type == UNOP) {
  742. X        /* unary expression */
  743. X        if (*++t_wp == NULL && n != FILTT)
  744. X            syntax(t_wp_op->op_text, "argument expected");
  745. X        switch (n) {
  746. X          case OPTION:
  747. X            return flag[option(*t_wp)];
  748. X          case STZER:
  749. X            return strlen(*t_wp) == 0;
  750. X          case STNZE:
  751. X            return strlen(*t_wp) != 0;
  752. X          case FILTT:
  753. X            if (!digit(**t_wp))
  754. X                return filstat("0", n);
  755. X          default:    /* all other FIL* */
  756. X            return filstat(*t_wp, n);
  757. X        }
  758. X    }
  759. X    opnd1 = *t_wp;
  760. X    (void) t_lex(*++t_wp);
  761. X    if (t_wp_op && t_wp_op->op_type == BINOP) {
  762. X        struct t_op Const *op = t_wp_op;
  763. X
  764. X        if ((opnd2 = *++t_wp) == (char *)0)
  765. X            syntax(op->op_text, "argument expected");
  766. X        
  767. X        switch (op->op_num) {
  768. X        case STEQL:
  769. X            return strcmp(opnd1, opnd2) == 0;
  770. X        case STNEQ:
  771. X            return strcmp(opnd1, opnd2) != 0;
  772. X        case INTEQ:
  773. X            return evaluate(opnd1) == evaluate(opnd2);
  774. X        case INTNE:
  775. X            return evaluate(opnd1) != evaluate(opnd2);
  776. X        case INTGE:
  777. X            return evaluate(opnd1) >= evaluate(opnd2);
  778. X        case INTGT:
  779. X            return evaluate(opnd1) > evaluate(opnd2);
  780. X        case INTLE:
  781. X            return evaluate(opnd1) <= evaluate(opnd2);
  782. X        case INTLT:
  783. X            return evaluate(opnd1) < evaluate(opnd2);
  784. X        case FILNT:
  785. X            return newerf (opnd1, opnd2);
  786. X        case FILOT:
  787. X            return olderf (opnd1, opnd2);
  788. X        case FILEQ:
  789. X            return equalf (opnd1, opnd2);
  790. X        }
  791. X    }
  792. X    t_wp--;
  793. X    return strlen(opnd1) > 0;
  794. X}
  795. X
  796. Xfilstat(nm, mode)
  797. X    char *nm;
  798. X{
  799. X    struct stat s;
  800. X    
  801. X    switch (mode) {
  802. X    case FILRD:
  803. X        return eaccess(nm, 4) == 0;
  804. X    case FILWR:
  805. X        return eaccess(nm, 2) == 0;
  806. X    case FILEX:
  807. X        return eaccess(nm, 1) == 0;
  808. X    case FILREG:
  809. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG;
  810. X    case FILID:
  811. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR;
  812. X    case FILCDEV:
  813. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFCHR;
  814. X    case FILBDEV:
  815. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFBLK;
  816. X    case FILFIFO:
  817. X#ifdef S_IFIFO
  818. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFIFO;
  819. X#else
  820. X        return 0;
  821. X#endif
  822. X    case FILSETU:
  823. X        return stat(nm, &s) == 0 && (s.st_mode & S_ISUID) == S_ISUID;
  824. X    case FILSETG:
  825. X        return stat(nm, &s) == 0 && (s.st_mode & S_ISGID) == S_ISGID;
  826. X    case FILSTCK:
  827. X        return stat(nm, &s) == 0 && (s.st_mode & S_ISVTX) == S_ISVTX;
  828. X    case FILGZ:
  829. X        return stat(nm, &s) == 0 && s.st_size > 0L;
  830. X    case FILTT:
  831. X        return isatty(getn(nm));
  832. X      case FILUID:
  833. X        return stat(nm, &s) == 0 && s.st_uid == geteuid();
  834. X      case FILGID:
  835. X        return stat(nm, &s) == 0 && s.st_gid == getegid();
  836. X#ifdef S_IFLNK
  837. X    case FILSYM:
  838. X        return lstat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFLNK;
  839. X#endif
  840. X#ifdef S_IFSOCK
  841. X    case FILSOCK:
  842. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFSOCK;
  843. X#endif
  844. X      default:
  845. X        return 1;
  846. X    }
  847. X}
  848. X
  849. Xint
  850. Xt_lex(s)
  851. X    register char *s;
  852. X{
  853. X    register struct t_op Const *op = ops;
  854. X
  855. X    if (s == 0) {
  856. X        t_wp_op = (struct t_op *)0;
  857. X        return EOI;
  858. X    }
  859. X    while (op->op_text) {
  860. X        if (strcmp(s, op->op_text) == 0) {
  861. X            t_wp_op = op;
  862. X            return op->op_num;
  863. X        }
  864. X        op++;
  865. X    }
  866. X    t_wp_op = (struct t_op *)0;
  867. X    return OPERAND;
  868. X}
  869. X
  870. Xnewerf (f1, f2)
  871. Xchar *f1, *f2;
  872. X{
  873. X    struct stat b1, b2;
  874. X
  875. X    return (stat (f1, &b1) == 0 &&
  876. X        stat (f2, &b2) == 0 &&
  877. X        b1.st_mtime > b2.st_mtime);
  878. X}
  879. X
  880. Xolderf (f1, f2)
  881. Xchar *f1, *f2;
  882. X{
  883. X    struct stat b1, b2;
  884. X
  885. X    return (stat (f1, &b1) == 0 &&
  886. X        stat (f2, &b2) == 0 &&
  887. X        b1.st_mtime < b2.st_mtime);
  888. X}
  889. X
  890. Xequalf (f1, f2)
  891. Xchar *f1, *f2;
  892. X{
  893. X    struct stat b1, b2;
  894. X
  895. X    return (stat (f1, &b1) == 0 &&
  896. X        stat (f2, &b2) == 0 &&
  897. X        b1.st_dev == b2.st_dev &&
  898. X        b1.st_ino == b2.st_ino);
  899. X}
  900. X
  901. END_OF_FILE
  902.   if test 7284 -ne `wc -c <'sh/c_test.c'`; then
  903.     echo shar: \"'sh/c_test.c'\" unpacked with wrong size!
  904.   fi
  905.   # end of 'sh/c_test.c'
  906. fi
  907. if test -f 'sh/edit.c' -a "${1}" != "-c" ; then 
  908.   echo shar: Will not clobber existing file \"'sh/edit.c'\"
  909. else
  910.   echo shar: Extracting \"'sh/edit.c'\" \(7903 characters\)
  911.   sed "s/^X//" >'sh/edit.c' <<'END_OF_FILE'
  912. X/*
  913. X * Command line editing - common code
  914. X */
  915. X
  916. X#include "config.h"
  917. X#if defined(EMACS) || defined(VI)
  918. X
  919. X#ifndef lint
  920. Xstatic char *RCSid = "$Id: edit.c,v 3.2 89/03/27 15:47:34 egisin Exp $";
  921. Xstatic char *sccs_id = "@(#)edit.c    1.4 91/11/09 15:35:07 (sjg)";
  922. X#endif
  923. X
  924. X#include <stddef.h>
  925. X#include <stdlib.h>
  926. X#include <string.h>
  927. X#include <stdio.h>
  928. X#include <unistd.h>
  929. X#include <signal.h>
  930. X#include <fcntl.h>
  931. X#include <errno.h>
  932. X#include <setjmp.h>
  933. X#include "sh.h"
  934. X#include "lex.h"
  935. X#include "tty.h"
  936. X#define EXTERN
  937. X#include "edit.h"
  938. X#undef EXTERN
  939. X
  940. X#ifdef _CRAY2
  941. Xextern unsigned    sleep();
  942. X#endif
  943. X
  944. X#if 0
  945. Xint    x_do_init = 1;        /* set up tty modes */
  946. Xint    x_cols = 80;        /* todo: $COLUMNS */
  947. Xint    ed_erase = -1, ed_kill = -1, ed_werase = -1, ed_intr = -1, ed_quit = -1;
  948. X#endif
  949. X
  950. Xstatic int    x_noecho = 0;
  951. X
  952. X/*
  953. X * read an edited command line
  954. X */
  955. Xint
  956. Xx_read(fd, buf, len)
  957. X    int fd;            /* not used */
  958. X    char *buf;
  959. X    size_t len;
  960. X{
  961. X  static int setup_done = 0;
  962. X    char    c;
  963. X    int    i;
  964. X
  965. X  if (setup_done != 42)
  966. X  {
  967. X    setup_done = 42;        /* these get done once only */
  968. X    x_do_init = 1;
  969. X    x_cols = 80;
  970. X    x_col = 0;
  971. X    ed_erase = -1, ed_kill = -1, ed_werase = -1, ed_intr = -1, ed_quit = -1;
  972. X    x_adj_ok = 1;
  973. X    x_adj_done = 0;
  974. X  }
  975. X    if (x_do_init)
  976. X        x_init();
  977. X
  978. X    if (x_noecho)
  979. X        return(read(ttyfd, buf, len));
  980. X
  981. X    (void)x_mode(TRUE);
  982. X#ifdef EMACS
  983. X    if (flag[FEMACS])
  984. X        i = x_emacs(buf, len);
  985. X    else
  986. X#endif
  987. X#ifdef VI
  988. X    if (flag[FVI])
  989. X        i = x_vi(buf, len);
  990. X    else
  991. X#endif
  992. X        i = -1;        /* internal error */
  993. X    (void) x_mode(FALSE);
  994. X    /* XXX -- doesn't get them all */
  995. X    if (i > 4 && strncmp(buf, "stty", 4) == 0)
  996. X        x_do_init = 1;
  997. X    if (i < 0 && errno == EINTR)
  998. X        trapsig(SIGINT);
  999. X    return i;
  1000. X}
  1001. X
  1002. X/* tty I/O */
  1003. X
  1004. Xint
  1005. Xx_getc()
  1006. X{
  1007. X    char c;
  1008. X
  1009. X    if (read(ttyfd, &c, 1) != 1)
  1010. X        return -1;
  1011. X    return c & 0x7F;
  1012. X}
  1013. X
  1014. Xvoid
  1015. Xx_flush()
  1016. X{
  1017. X    fflush(stdout);
  1018. X}
  1019. X
  1020. X
  1021. X/* NAME:
  1022. X *      x_adjust - redraw the line adjusting starting point etc.
  1023. X *
  1024. X * DESCRIPTION:
  1025. X *      This function is called when we have exceeded the bounds 
  1026. X *      of the edit window.  It increments x_adj_done so that 
  1027. X *      functions like x_ins and x_delete know that we have been 
  1028. X *      called and can skip the x_bs() stuff which has already 
  1029. X *      been done by x_redraw.
  1030. X *
  1031. X * RETURN VALUE:
  1032. X *      None
  1033. X */
  1034. X
  1035. Xvoid
  1036. Xx_adjust()
  1037. X{
  1038. X  x_adj_done++;            /* flag the fact that we were called. */
  1039. X  /*
  1040. X   * we had a promblem if the prompt length > x_cols / 2
  1041. X   */
  1042. X  if ((xbp = xcp - (x_displen / 2)) < xbuf)
  1043. X    xbp = xbuf;
  1044. X  xlp_valid = FALSE;
  1045. X  x_redraw(x_cols);
  1046. X  x_flush();
  1047. X}
  1048. X
  1049. Xvoid
  1050. Xx_putc(c)
  1051. X    int c;
  1052. X{
  1053. X  if (c == '\r' || c == '\n')
  1054. X    x_col = 0;
  1055. X  if (x_col < x_cols)
  1056. X  {
  1057. X    putc(c, stdout);
  1058. X    switch(c)
  1059. X    {
  1060. X    case BEL:
  1061. X      break;
  1062. X    case '\r':
  1063. X    case '\n':
  1064. X    break;
  1065. X    case '\b':
  1066. X      x_col--;
  1067. X      break;
  1068. X    default:
  1069. X      x_col++;
  1070. X      break;
  1071. X    }
  1072. X  }
  1073. X  if (x_adj_ok && (x_col < 0 || x_col >= (x_cols - 2)))
  1074. X  {
  1075. X    x_adjust();
  1076. X  }
  1077. X}
  1078. X
  1079. X#ifdef DEBUG
  1080. Xint
  1081. Xx_debug_info()
  1082. X{
  1083. X  x_flush();
  1084. X  printf("\nksh debug:\n");
  1085. X  printf("\tx_col == %d,\t\tx_cols == %d,\tx_displen == %d\n",
  1086. X     x_col, x_cols, x_displen);
  1087. X  printf("\txcp == 0x%lx,\txep == 0x%lx\n", (long) xcp, (long) xep);
  1088. X  printf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf);
  1089. X  printf("\txlp == 0x%lx\n", (long) xlp);
  1090. X  printf("\txlp == 0x%lx\n", (long) x_lastcp());
  1091. X  printf("\n");
  1092. X  x_redraw(-1);
  1093. X  return 0;
  1094. X}
  1095. X#endif
  1096. X
  1097. Xvoid
  1098. Xx_puts(s)
  1099. X    register char *s;
  1100. X{
  1101. X  register int    adj = x_adj_done;
  1102. X
  1103. X  while (*s && adj == x_adj_done)
  1104. X    x_putc(*s++);
  1105. X}
  1106. X
  1107. X#ifdef _BSD
  1108. Xstatic    struct sgttyb cb, cborig;
  1109. X#ifdef TIOCGATC
  1110. Xstatic struct ttychars lchars, lcharsorig;
  1111. X#else
  1112. Xstatic struct tchars tchars, tcharsorig;
  1113. Xstatic struct ltchars ltchars, ltcharsorig;
  1114. X#endif
  1115. X#else
  1116. Xstatic    struct termio cb, cborig;
  1117. X#endif
  1118. X
  1119. X/* initialize editing mode */
  1120. Xvoid
  1121. Xx_init()
  1122. X{
  1123. X    x_do_init = 0;
  1124. X#ifdef _BSD
  1125. X    (void)ioctl(ttyfd, TIOCGETP, &cborig);
  1126. X    if ((cborig.sg_flags & ECHO) == 0)
  1127. X        x_noecho = 1;
  1128. X    cb = cborig;
  1129. X    ed_erase = cb.sg_erase;
  1130. X    ed_kill = cb.sg_kill;
  1131. X    cb.sg_flags &= ~ECHO;
  1132. X    cb.sg_flags |= CBREAK;
  1133. X#ifdef TIOCGATC
  1134. X    (void)ioctl(ttyfd, TIOCGATC, &lcharsorig);
  1135. X    lchars = lcharsorig;
  1136. X    ed_werase = lchars.tc_werasc;
  1137. X    lchars.tc_suspc = -1;
  1138. X    lchars.tc_dsuspc = -1;
  1139. X    lchars.tc_lnextc = -1;
  1140. X    lchars.tc_statc = -1;
  1141. X    lchars.tc_intrc = -1;
  1142. X    lchars.tc_quitc = -1;
  1143. X    lchars.tc_rprntc = -1;
  1144. X#else
  1145. X    (void)ioctl(ttyfd, TIOCGETC, &tcharsorig);
  1146. X    (void)ioctl(ttyfd, TIOCGLTC, <charsorig);
  1147. X    tchars = tcharsorig;
  1148. X    ltchars = ltcharsorig;
  1149. X    ed_werase = ltchars.t_werasc;
  1150. X    ltchars = ltcharsorig;
  1151. X    ltchars.t_suspc = -1;
  1152. X    ltchars.t_dsuspc = -1;
  1153. X    ltchars.t_lnextc = -1;
  1154. X    tchars.t_intrc = -1;
  1155. X    tchars.t_quitc = -1;
  1156. X    ltchars.t_rprntc = -1;
  1157. X#endif
  1158. X#else /* !_BSD */
  1159. X    (void)ioctl(ttyfd, TCGETA, &cborig);
  1160. X    if ((cborig.c_lflag & ECHO) == 0)
  1161. X        x_noecho = 1;
  1162. X    cb = cborig;
  1163. X    ed_erase = cb.c_cc[VERASE]; /* TODO */
  1164. X    ed_kill = cb.c_cc[VKILL]; /* TODO */
  1165. X    ed_intr = cb.c_cc[VINTR];
  1166. X    ed_quit = cb.c_cc[VQUIT];
  1167. X#ifdef _CRAY2        /* brain-damaged terminal handler */
  1168. X    cb.c_lflag &= ~(ICANON|ECHO);
  1169. X    /* rely on print routine to map '\n' to CR,LF */
  1170. X#else
  1171. X    cb.c_iflag &= ~(INLCR|ICRNL);
  1172. X#ifdef _BSD_SYSV    /* need to force CBREAK instead of RAW (need CRMOD on output) */
  1173. X    cb.c_lflag &= ~(ICANON|ECHO);
  1174. X#else
  1175. X#ifdef SWTCH    /* need CBREAK to handle swtch char */
  1176. X    cb.c_lflag &= ~(ICANON|ECHO);
  1177. X    cb.c_lflag |= ISIG;
  1178. X    cb.c_cc[VINTR] = 0377;
  1179. X    cb.c_cc[VQUIT] = 0377;
  1180. X#else
  1181. X    cb.c_lflag &= ~(ISIG|ICANON|ECHO);
  1182. X#endif
  1183. X#endif
  1184. X    cb.c_cc[VTIME] = 0;
  1185. X    cb.c_cc[VMIN] = 1;
  1186. X#endif    /* _CRAY2 */
  1187. X#endif
  1188. X#ifdef EMACS
  1189. X    x_emacs_keys(ed_erase, ed_kill, ed_werase, ed_intr, ed_quit);
  1190. X#endif
  1191. X}
  1192. X
  1193. Xstatic    bool_t    x_cur_mode = FALSE;
  1194. X
  1195. X/* set/clear tty cbreak mode */
  1196. X
  1197. X#ifdef _BSD
  1198. Xbool_t
  1199. Xx_mode(onoff)
  1200. X    bool_t    onoff;
  1201. X{
  1202. X    bool_t    prev;
  1203. X
  1204. X    if (x_cur_mode == onoff) return x_cur_mode;
  1205. X    prev = x_cur_mode;
  1206. X    x_cur_mode = onoff;
  1207. X    if (onoff)  {
  1208. X        (void)ioctl(ttyfd, TIOCSETN, &cb);
  1209. X#ifdef TIOCGATC
  1210. X        (void)ioctl(ttyfd, TIOCSATC, &lchars);
  1211. X#else
  1212. X        (void)ioctl(ttyfd, TIOCSETC, &tchars);
  1213. X        (void)ioctl(ttyfd, TIOCSLTC, <chars);
  1214. X#endif
  1215. X    }
  1216. X    else {
  1217. X        (void)ioctl(ttyfd, TIOCSETN, &cborig);
  1218. X#ifdef TIOCGATC
  1219. X        (void)ioctl(ttyfd, TIOCSATC, &lcharsorig);
  1220. X#else
  1221. X        (void)ioctl(ttyfd, TIOCSETC, &tcharsorig);
  1222. X        (void)ioctl(ttyfd, TIOCSLTC, <charsorig);
  1223. X#endif
  1224. X    }
  1225. X    return prev;
  1226. X}
  1227. X
  1228. X#else    /* !_BSD */
  1229. X
  1230. Xbool_t
  1231. Xx_mode(onoff)
  1232. Xbool_t    onoff;
  1233. X{
  1234. X    bool_t    prev;
  1235. X
  1236. X    if (x_cur_mode == onoff) return x_cur_mode;
  1237. X    prev = x_cur_mode;
  1238. X    x_cur_mode = onoff;
  1239. X
  1240. X    if (onoff)  {
  1241. X#ifndef TCSETAW                /* e.g. Cray-2 */
  1242. X        /* first wait for output to drain */
  1243. X#ifdef TCSBRK
  1244. X        (void)ioctl(ttyfd, TCSBRK, 1);
  1245. X#else    /* the following kludge is minimally intrusive, but sometimes fails */
  1246. X        (void)sleep((unsigned)1);    /* fake it */
  1247. X#endif
  1248. X#endif
  1249. X#if defined(_BSD_SYSV) || !defined(TCSETAW)
  1250. X/* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
  1251. X        (void)ioctl(ttyfd, TCSETA, &cb);
  1252. X#else
  1253. X        (void)ioctl(ttyfd, TCSETAW, &cb);
  1254. X#endif
  1255. X    }
  1256. X    else {
  1257. X#ifndef TCSETAW                /* e.g. Cray-2 */
  1258. X        /* first wait for output to drain */
  1259. X#ifdef TCSBRK
  1260. X        (void)ioctl(ttyfd, TCSBRK, 1);
  1261. X#else
  1262. X/* doesn't seem to be necessary when leaving xmode */
  1263. X/*        (void)sleep((unsigned)1);    /* fake it */
  1264. X#endif
  1265. X#endif
  1266. X#if defined(_BSD_SYSV) || !defined(TCSETAW)
  1267. X/* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
  1268. X        (void)ioctl(ttyfd, TCSETA, &cborig);
  1269. X#else
  1270. X        (void)ioctl(ttyfd, TCSETAW, &cborig);
  1271. X#endif
  1272. X    }
  1273. X    return prev;
  1274. X}
  1275. X#endif    /* _BSD */
  1276. X
  1277. X
  1278. X/* NAME:
  1279. X *      promptlen - calculate the length of PS1 etc.
  1280. X *
  1281. X * DESCRIPTION:
  1282. X *      This function is based on a fix from guy@demon.co.uk
  1283. X *      It fixes a bug in that if PS1 contains '!', the length 
  1284. X *      given by strlen() is probably wrong.
  1285. X *
  1286. X * RETURN VALUE:
  1287. X *      length
  1288. X */
  1289. Xint
  1290. Xpromptlen(cp)
  1291. X  register char  *cp;
  1292. X{
  1293. X  register int count = 0;
  1294. X
  1295. X  while (*cp)
  1296. X  {
  1297. X    if ( *cp++ != '!' )
  1298. X      count++;
  1299. X    else
  1300. X      if ( *cp == '!' )
  1301. X      {
  1302. X    cp++;
  1303. X    count++;
  1304. X      }
  1305. X      else
  1306. X      {
  1307. X    register int i = source->line;
  1308. X
  1309. X    do
  1310. X    {
  1311. X      count ++;
  1312. X    }
  1313. X    while( ( i /= 10 ) > 0 );
  1314. X      }
  1315. X  }
  1316. X  return count;
  1317. X}
  1318. X
  1319. X#endif
  1320. END_OF_FILE
  1321.   if test 7903 -ne `wc -c <'sh/edit.c'`; then
  1322.     echo shar: \"'sh/edit.c'\" unpacked with wrong size!
  1323.   fi
  1324.   # end of 'sh/edit.c'
  1325. fi
  1326. if test -f 'sh/history.c' -a "${1}" != "-c" ; then 
  1327.   echo shar: Will not clobber existing file \"'sh/history.c'\"
  1328. else
  1329.   echo shar: Extracting \"'sh/history.c'\" \(7391 characters\)
  1330.   sed "s/^X//" >'sh/history.c' <<'END_OF_FILE'
  1331. X/*
  1332. X * command history
  1333. X *
  1334. X * only implements in-memory history.
  1335. X */
  1336. X
  1337. Xstatic char *RCSid = "$Id: history.c,v 3.3 89/01/27 00:08:27 egisin Exp $";
  1338. X
  1339. X#include <stddef.h>
  1340. X#include <stdio.h>
  1341. X#include <string.h>
  1342. X#include <errno.h>
  1343. X#include <setjmp.h>
  1344. X#include "sh.h"
  1345. X#include "lex.h"
  1346. X
  1347. Xchar   *histrpl();
  1348. Xchar  **current;
  1349. Xint    curpos;
  1350. X
  1351. Xc_fc(wp)
  1352. X    register char **wp;
  1353. X{
  1354. X    register char *id;
  1355. X    FILE *f;
  1356. X    struct temp *tf;
  1357. X    register char **hp;
  1358. X    char **hbeg, **hend;
  1359. X    char *p, *cmd = NULL;
  1360. X    int lflag = 0, nflag = 0, sflag = 0, rflag = 0, gflag = 0;
  1361. X    int done = 0;
  1362. X    void histbackup();
  1363. X
  1364. X    for (wp++; (id = *wp) != NULL && *id++ == '-' && !done; wp++)
  1365. X        while (*id && !done) {
  1366. X            switch (*id++) {
  1367. X              case 'l':
  1368. X                lflag++;
  1369. X                break;
  1370. X              case 'n':
  1371. X                nflag++;
  1372. X                break;
  1373. X              case 'r':
  1374. X                rflag++;
  1375. X                break;
  1376. X              case 'g':
  1377. X                gflag++;
  1378. X                break;
  1379. X              case 'e':
  1380. X                if (++wp && (p = *wp)) {
  1381. X                    if (p[0] == '-' && !p[1]) {
  1382. X                        sflag++;
  1383. X                    } else {
  1384. X                        cmd = alloc((size_t)(strlen(p)+4),ATEMP);
  1385. X                        strcpy(cmd, p);
  1386. X                        strcat(cmd, " $_");
  1387. X                    }
  1388. X                } else
  1389. X                    errorf("argument expected\n");
  1390. X                id = "";
  1391. X                break;
  1392. X              default:
  1393. X                wp--;
  1394. X                done++;
  1395. X                break;
  1396. X            }
  1397. X        }
  1398. X
  1399. X    if (sflag) {
  1400. X        char *pat = NULL, *rep = NULL;
  1401. X
  1402. X        hp = histptr - 1;
  1403. X        while ((id = *wp++) != NULL) {
  1404. X            /* todo: multiple substitutions */
  1405. X            if ((p = strchr(id, '=')) != NULL) {
  1406. X                pat = id;
  1407. X                rep = p;
  1408. X                *rep++ = '\0';
  1409. X            } else
  1410. X                hp = histget(id);
  1411. X        }
  1412. X
  1413. X        if (hp == NULL || hp < history)
  1414. X            errorf("cannot find history\n");
  1415. X        if (pat == NULL)
  1416. X            strcpy(line, *hp);
  1417. X        else
  1418. X            histrpl(*hp, pat, rep, gflag);
  1419. X        histbackup();
  1420. X        histsave(line); 
  1421. X        histpush--; 
  1422. X        line[0] = '\0';
  1423. X        return 0;
  1424. X    }
  1425. X
  1426. X    if (*wp != NULL) {
  1427. X        hbeg = histget(*wp++); /* first */
  1428. X        if (*wp != NULL)
  1429. X            hend = histget(*wp++); /* last */
  1430. X        else if (lflag)
  1431. X            hend = histptr;
  1432. X        else
  1433. X            hend = hbeg;
  1434. X    } else {
  1435. X        if (lflag)
  1436. X            hbeg = histptr - 16, hend = histptr;
  1437. X        else
  1438. X            hbeg = hend = histptr - 1;
  1439. X        if (hbeg < history)
  1440. X            hbeg = history;
  1441. X    }
  1442. X    if (hbeg == NULL || hend == NULL)
  1443. X        errorf("can't find history\n");
  1444. X
  1445. X    if (lflag)
  1446. X        f = stdout;
  1447. X    else {
  1448. X        nflag++;
  1449. X        tf = maketemp(ATEMP);
  1450. X        tf->next = e.temps; e.temps = tf;
  1451. X        f = fopen(tf->name, "w");
  1452. X        if (f == NULL)
  1453. X            errorf("cannot create temp file %s", tf->name);
  1454. X        setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
  1455. X    }
  1456. X
  1457. X    for (hp = (rflag ? hend : hbeg); rflag ? (hp >= hbeg) : (hp <= hend);
  1458. X          rflag ? hp-- : hp++) {
  1459. X        if (!nflag)
  1460. X            fprintf(f, "%3d: ", source->line - (int)(histptr-hp));
  1461. X        fprintf(f, "%s\n", *hp);
  1462. X    }
  1463. X
  1464. X    if (lflag)
  1465. X        return 0;
  1466. X    else
  1467. X        fclose(f);
  1468. X
  1469. X    setstr(local("_"), tf->name);
  1470. X    if (cmd) {
  1471. X        command(cmd); /* edit temp file */
  1472. X        afree(cmd, ATEMP);
  1473. X    } else
  1474. X        command("${FCEDIT:-/bin/ed} $_");
  1475. X
  1476. X    f = fopen(tf->name, "r");
  1477. X    if (f == NULL)
  1478. X        errorf("cannot open temp file %s\n", tf->name);
  1479. X    setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
  1480. X    /* we push the editted lines onto the history list */
  1481. X    while (fgets(line, sizeof(line), f) != NULL) {
  1482. X        histsave(line); 
  1483. X        histpush--; 
  1484. X    }
  1485. X    line[0] = '\0';
  1486. X    fclose(f);
  1487. X
  1488. X    return 0;
  1489. X}
  1490. X
  1491. X/******************************/
  1492. X/* Back up over last histsave */
  1493. X/******************************/
  1494. Xvoid
  1495. Xhistbackup()
  1496. X{
  1497. X    static int last_line = -1;
  1498. X
  1499. X    if (histptr > history && last_line != source->line) { 
  1500. X        source->line--;
  1501. X        afree((Void*)*histptr, APERM);
  1502. X        histptr--;
  1503. X        last_line = source->line;
  1504. X    }
  1505. X}
  1506. X
  1507. X/*
  1508. X * save command in history
  1509. X */
  1510. Xvoid
  1511. Xhistsave(cmd)
  1512. X    char *cmd;
  1513. X{
  1514. X    register char **hp = histptr;
  1515. X    char *cp;
  1516. X
  1517. X    if (++hp >= history + HISTORY) { /* remove oldest command */
  1518. X        afree((Void*)*history, APERM);
  1519. X        for (hp = history; hp < history + HISTORY - 1; hp++)
  1520. X            hp[0] = hp[1];
  1521. X    }
  1522. X    *hp = strsave(cmd, APERM);
  1523. X    if ((cp = strchr(*hp, '\n')) != NULL)
  1524. X        *cp = '\0';
  1525. X    histptr = hp;
  1526. X}
  1527. X
  1528. X/*
  1529. X * get pointer to history given pattern
  1530. X * pattern is a number or string
  1531. X */
  1532. Xchar **
  1533. Xhistget(str)
  1534. X    char *str;
  1535. X{
  1536. X    register char **hp = NULL;
  1537. X
  1538. X    if (*str == '-')
  1539. X        hp = histptr + getn(str);
  1540. X    else
  1541. X    if (digit(*str))
  1542. X        hp = histptr + (getn(str) - source->line);
  1543. X    else 
  1544. X    if (*str == '?') {    /* unanchored match */
  1545. X        for (hp = histptr-1; hp >= history; hp--)
  1546. X            if (strstr(*hp, str+1) != NULL)
  1547. X                break;
  1548. X    } else {        /* anchored match */
  1549. X        for (hp = histptr; hp >= history; hp--)
  1550. X            if (strncmp(*hp, str, strlen(str)) == 0)
  1551. X                break;
  1552. X    }
  1553. X
  1554. X    return (history <= hp && hp <= histptr) ? hp : NULL;
  1555. X}
  1556. X
  1557. Xchar *
  1558. Xhistrpl(s, pat, rep, global)
  1559. X    char *s;
  1560. X    char *pat, *rep;
  1561. X    int global;
  1562. X{
  1563. X    char *s1, *p, *last = NULL;
  1564. X    int len = strlen(pat);
  1565. X
  1566. X    if (strlen(s) - strlen(pat) + strlen(rep) >= LINE)
  1567. X        errorf("substitution too long\n");
  1568. X    line[0] = '\0';
  1569. X    p = line;
  1570. X    while (s1 = strstr(s, pat)) {
  1571. X        strncpy(p, s, s1 - s);        /* first part */
  1572. X        strcpy(p + (s1 - s), rep);    /* replacement */
  1573. X        s = s1 + len;
  1574. X        last = s1;
  1575. X        p = strchr(p, 0);
  1576. X        if (!global)
  1577. X            s = "";
  1578. X    }
  1579. X    if (last)
  1580. X        strcpy(p, last + len);        /* last part */
  1581. X    else
  1582. X        errorf("substitution failed\n");
  1583. X    return line;
  1584. X}
  1585. X
  1586. X#if 0
  1587. X
  1588. X/* History file management routines (by DPK@BRL) */
  1589. X
  1590. Xvoid
  1591. Xhist_init()
  1592. X{
  1593. X    register struct namnod *n;
  1594. X    int fd;
  1595. X
  1596. X    if (hist_fd >= 0 || (flags&oneflg))
  1597. X        return;
  1598. X    if ((n = findnam(histname)) == (struct namnod *)0
  1599. X     || n->namval == (char *)0)
  1600. X        return;
  1601. X    if ((fd = open(n->namval, O_RDWR)) >= 0) {
  1602. X        hist_load(fd);
  1603. X        (void)fcntl(fd, F_SETFL, O_APPEND);
  1604. X    }
  1605. X    hist_fd = fd;
  1606. X}
  1607. X
  1608. Xvoid
  1609. Xhist_finish()
  1610. X{
  1611. X    if (hist_fd >= 0)
  1612. X        (void)close(hist_fd);
  1613. X    hist_fd = -1;
  1614. X}
  1615. X
  1616. Xvoid
  1617. Xhist_record(buf, len)
  1618. Xchar    *buf;
  1619. Xint    len;
  1620. X{
  1621. X    if (hist_fd >= 0)
  1622. X        (void)write(hist_fd, buf, (unsigned)len);
  1623. X}
  1624. X
  1625. Xvoid
  1626. Xhist_load(fd)
  1627. Xint    fd;
  1628. X{
  1629. X    extern long    lseek();
  1630. X    struct stat sb;
  1631. X    char *x;
  1632. X    register char *cmdp, *end;
  1633. X    register int    len;
  1634. X    register int    i;
  1635. X
  1636. X    if (fstat(fd, &sb) < 0 || sb.st_size <= 0)
  1637. X        return;
  1638. X    if (x = alloc((unsigned)(sb.st_size+1))) {
  1639. X        (void)lseek(fd, 0L, 0);
  1640. X        if ((len = read(fd, x, (unsigned)sb.st_size)) <= 0) {
  1641. X            free((struct blk *)x);
  1642. X            return;
  1643. X        }
  1644. X        x[len] = 0;
  1645. X        end = x;
  1646. X        for (;;) {
  1647. X            while(*end == NL)
  1648. X                end++;        /* Skip NL */
  1649. X            if (*end == 0)
  1650. X                break;
  1651. X            cmdp = end;
  1652. X            while(*end && *end != NL)
  1653. X                end++;    /* Goto NL */
  1654. X            if (*end == 0)
  1655. X                break;
  1656. X            if ((len = (end - cmdp)) < 2)
  1657. X                continue;
  1658. X            if (len >= BUFSIZ)
  1659. X                len = BUFSIZ - 1;        /* Protection */
  1660. X            i = curhist % NHISTORY;
  1661. X            if(histbuf[i])
  1662. X                free((struct blk *)histbuf[i]);
  1663. X            histbuf[i] = alloc((unsigned)(len+1));
  1664. X            (void)strncpy(histbuf[i], cmdp, len);
  1665. X            histbuf[i][len] = 0;
  1666. X            curhist++;
  1667. X            histpc=curhist;
  1668. X        }
  1669. X        free((struct blk *)x);
  1670. X    }
  1671. X    return;
  1672. X}
  1673. X
  1674. X#endif
  1675. X
  1676. X/*
  1677. X * Return the current position.
  1678. X */
  1679. Xchar **
  1680. Xhistpos()
  1681. X{
  1682. X    return current;
  1683. X}
  1684. X
  1685. Xint
  1686. XhistN()
  1687. X{
  1688. X    return curpos;
  1689. X}
  1690. X
  1691. Xint
  1692. Xhistnum(n)
  1693. X{
  1694. X    int    last = histptr - history;
  1695. X
  1696. X    if (n < 0 || n >= last) {
  1697. X        current = histptr;
  1698. X        curpos = last;
  1699. X        return last;
  1700. X    }  else {
  1701. X        current = &history[n];
  1702. X        curpos = n;
  1703. X        return n;
  1704. X    }
  1705. X}
  1706. X
  1707. X/*
  1708. X * This will become unecessary if histget is modified to allow
  1709. X * searching from positions other than the end, and in either 
  1710. X * direction.
  1711. X */
  1712. Xchar *
  1713. Xfindhist(start, fwd, str)
  1714. X    int    start;
  1715. X    int    fwd;
  1716. X    char     *str;
  1717. X{
  1718. X    char     **hp = NULL;
  1719. X    int     pos = start;
  1720. X    char     *line, *last;
  1721. X
  1722. X    /* XXX check that we are valid after this */
  1723. X    if (fwd)
  1724. X        pos++;
  1725. X    else
  1726. X        pos--;
  1727. X    histnum(pos);
  1728. X    line = *histpos();
  1729. X    do {
  1730. X        last = line;
  1731. X        if (strstr(line, str) != 0) {
  1732. X            /* keep position current */
  1733. X            return (line);
  1734. X        }
  1735. X        if (fwd)
  1736. X            pos++;
  1737. X        else
  1738. X            pos--;
  1739. X        histnum(pos);
  1740. X        line = *histpos();
  1741. X    } while (line && *line && line != last && pos>0);
  1742. X
  1743. X    histnum(start);
  1744. X    if (pos <= 0)
  1745. X        return (char*)-1; /* TODO */
  1746. X    return NULL;
  1747. X}
  1748. END_OF_FILE
  1749.   if test 7391 -ne `wc -c <'sh/history.c'`; then
  1750.     echo shar: \"'sh/history.c'\" unpacked with wrong size!
  1751.   fi
  1752.   # end of 'sh/history.c'
  1753. fi
  1754. if test -f 'sh/main.c' -a "${1}" != "-c" ; then 
  1755.   echo shar: Will not clobber existing file \"'sh/main.c'\"
  1756. else
  1757.   echo shar: Extracting \"'sh/main.c'\" \(8586 characters\)
  1758.   sed "s/^X//" >'sh/main.c' <<'END_OF_FILE'
  1759. X/*
  1760. X * startup, main loop, enviroments and error handling
  1761. X */
  1762. X
  1763. X#ifndef lint
  1764. Xstatic char *RCSid = "$Id: main.c,v 3.3 89/03/27 15:51:39 egisin Exp $";
  1765. Xstatic char *sccs_id = "@(#)main.c    1.3 91/11/09 15:34:27 (sjg)";
  1766. X#endif
  1767. X
  1768. X#define    Extern                /* define Externs in sh.h */
  1769. X
  1770. X#include <stddef.h>
  1771. X#include <stdlib.h>
  1772. X#include <stdio.h>
  1773. X#include <string.h>
  1774. X#include <unistd.h>
  1775. X#include <fcntl.h>
  1776. X#include <signal.h>
  1777. X#include <errno.h>
  1778. X#include <setjmp.h>
  1779. X#include <time.h>
  1780. X#include "sh.h"
  1781. X#include "lex.h"
  1782. X#include "tree.h"
  1783. X#include "table.h"
  1784. X
  1785. X/*
  1786. X * global data
  1787. X */
  1788. X
  1789. XArea    aperm;
  1790. X
  1791. Xstatic    void    reclaim ARGS((void));
  1792. X
  1793. X/*
  1794. X * shell initialization
  1795. X */
  1796. X
  1797. Xstatic    char    initifs [] = "IFS= \t\n"; /* must be R/W */
  1798. X
  1799. Xstatic    Const    char   initsubs [] = 
  1800. X#ifdef sun                /* sun's don't have a real /bin */
  1801. X  "${SHELL:=/bin/sh} ${PATH:=/usr/bin:/usr/ucb:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${MAILCHECK:=600}";
  1802. X#else
  1803. X  "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${MAILCHECK:=600}";
  1804. X#endif
  1805. X
  1806. Xstatic    Const    char *initcoms [] = {
  1807. X    "cd", ".", NULL,        /* set up $PWD */
  1808. X    "typeset", "-x", "SHELL", "PATH", "HOME", NULL,
  1809. X    "typeset", "-r", "PWD", "OLDPWD", NULL,
  1810. X    "typeset", "-i", "SECONDS=0", "OPTIND=1", NULL,
  1811. X    "alias",
  1812. X      "integer=typeset -i", "pwd=print -r \"$PWD\"",
  1813. X      "history=fc -l", "r=fc -e -", "nohup=nohup ",
  1814. X      "login=exec login", "newgrp=exec newgrp",
  1815. X      "type=whence -v", "functions=typeset -f",
  1816. X      "echo=print", "true=:", "false=let", "[=\\[", NULL,
  1817. X    NULL
  1818. X};
  1819. X
  1820. X#ifdef USE_TRACE
  1821. X/*
  1822. X * use SIGUSR1 to bump up Trace_level
  1823. X * use SIGUSR2 to clear Trace_level
  1824. X */
  1825. Xvoid
  1826. Xset_TraceLev(sig)
  1827. X  int sig;
  1828. X{
  1829. X  switch(sig)
  1830. X  {
  1831. X  case SIGUSR1:
  1832. X    Trace_level++;
  1833. X    break;
  1834. X  case SIGUSR2:
  1835. X    Trace_level = 0;
  1836. X    break;
  1837. X  }
  1838. X  if (sig > 0)
  1839. X    (void) signal(sig, set_TraceLev);
  1840. X  return;
  1841. X}
  1842. X#endif
  1843. X
  1844. Xmain(argc, argv, envp)
  1845. X    int argc;
  1846. X    register char **argv;
  1847. X    char **envp;
  1848. X{
  1849. X    register int i;
  1850. X    register char *arg;
  1851. X    int cflag = 0, qflag = 0, fflag = 0;
  1852. X    char *name;
  1853. X    register Source *s;
  1854. X    register struct block *l = &globals;
  1855. X    register char **wp0, **wp;
  1856. X    extern char ksh_version [];
  1857. X    extern time_t time();
  1858. X
  1859. X    ainit(&aperm);        /* initialize permanent Area */
  1860. X
  1861. X    /* set up base enviroment */
  1862. X    e.type = E_NONE;
  1863. X    ainit(&e.area);
  1864. X    e.loc = l;
  1865. X    e.savefd = NULL;
  1866. X    e.oenv = NULL;
  1867. X
  1868. X    initctypes();
  1869. X
  1870. X    /* open file streams for fd's 0,1,2 */
  1871. X    fopenshf(0);    fopenshf(1);    fopenshf(2);
  1872. X
  1873. X    /* set up variable and command dictionaries */
  1874. X    newblock();        /* set up global l->vars and l->funs */
  1875. X    tinit(&commands, APERM);
  1876. X    tinit(&builtins, APERM);
  1877. X    tinit(&lexicals, APERM);
  1878. X    tinit(&homedirs, APERM);
  1879. X
  1880. X    /* import enviroment */
  1881. X    if (envp != NULL)
  1882. X        for (wp = envp; *wp != NULL; wp++)
  1883. X            import(*wp);
  1884. X
  1885. X    kshpid = getpid();
  1886. X    typeset(initifs, 0, 0);    /* for security */
  1887. X    typeset(ksh_version, 0, 0); /* RDONLY */
  1888. X
  1889. X#ifdef USE_TRACE
  1890. X    (void) signal(SIGUSR1, set_TraceLev);
  1891. X    (void) signal(SIGUSR2, set_TraceLev);
  1892. X    _TRACE(0, ("Traces enabled.")); /* allow _TRACE to setup */
  1893. X#endif
  1894. X
  1895. X    /* define shell keywords */
  1896. X    keywords();
  1897. X
  1898. X    /* define built-in commands */
  1899. X    for (i = 0; shbuiltins[i].name != NULL; i++)
  1900. X        builtin(shbuiltins[i].name, shbuiltins[i].func);
  1901. X    for (i = 0; kshbuiltins[i].name != NULL; i++)
  1902. X        builtin(kshbuiltins[i].name, kshbuiltins[i].func);
  1903. X
  1904. X    /* assign default shell variable values */
  1905. X    substitute(initsubs, 0);
  1906. X    setint(typeset("PPID", INTEGER, 0), (long) getppid());
  1907. X    typeset("PPID", RDONLY, 0);
  1908. X    setint(typeset("RANDOM", INTEGER, 0), (long) time((time_t *)0));
  1909. X    /* execute initialization statements */
  1910. X    for (wp0 = (char**) initcoms; *wp0 != NULL; wp0 = wp+1) {
  1911. X        /* copy because the alias initializers are readonly */
  1912. X        for (wp = wp0; *wp != NULL; wp++)
  1913. X            *wp = strsave(*wp, ATEMP);
  1914. X        shcomexec(wp0);
  1915. X    }
  1916. X    afreeall(ATEMP);
  1917. X
  1918. X    if (geteuid() == 0)
  1919. X        setstr(global("PS1"), "# ");
  1920. X
  1921. X    s = pushs(SFILE);
  1922. X    s->u.file = stdin;
  1923. X    cflag = 0;
  1924. X    name = *argv++;
  1925. X
  1926. X    /* what a bloody mess */
  1927. X    if (--argc >= 1) {
  1928. X        if (argv[0][0] == '-' && argv[0][1] != '\0') {
  1929. X            for (arg = argv[0]+1; *arg; arg++)
  1930. X                switch (*arg) {
  1931. X                  case 'c':
  1932. X                    cflag = 1;
  1933. X                    if (--argc > 0) {
  1934. X                        s->type = SSTRING;
  1935. X                        s->str = *++argv;
  1936. X                    }
  1937. X                    break;
  1938. X    
  1939. X                  case 'q':
  1940. X                    qflag = 1;
  1941. X                    break;
  1942. X
  1943. X                  default:
  1944. X                    if (*arg>='a' && *arg<='z')
  1945. X                        flag[FLAG(*arg)]++;
  1946. X                }
  1947. X        } else {
  1948. X            argv--;
  1949. X            argc++;
  1950. X        }
  1951. X        if (s->type == SFILE && --argc > 0 && !flag[FSTDIN]) {
  1952. X            if ((s->u.file = fopen(*++argv, "r")) == NULL)
  1953. X                errorf("%s: cannot open\n", *argv);
  1954. X            fflag = 1;
  1955. X            s->file = name = *argv;
  1956. X            argc--;
  1957. X            fileno(s->u.file) = savefd(fileno(s->u.file));
  1958. X            setvbuf(s->u.file, (char *)NULL, _IOFBF, BUFSIZ);
  1959. X        }
  1960. X    }
  1961. X
  1962. X    if (s->type == SFILE) {
  1963. X        if (fileno(s->u.file) == 0)
  1964. X            flag[FSTDIN] = 1;
  1965. X        if (isatty(0) && isatty(1) && !cflag && !fflag)
  1966. X            flag[FTALKING] = 1;
  1967. X        if (flag[FTALKING] && flag[FSTDIN])
  1968. X            s->type = STTY;
  1969. X    }
  1970. X    if (s->type == STTY) {
  1971. X        ttyfd = fcntl(0, F_DUPFD, FDBASE);
  1972. X        (void) fcntl(ttyfd, F_SETFD, FD_CLEXEC);
  1973. X#ifdef EMACS
  1974. X        x_init_emacs();
  1975. X#endif
  1976. X    }
  1977. X
  1978. X    /* initialize job control */
  1979. X    j_init();
  1980. X
  1981. X    if (!qflag)
  1982. X        ignoresig(SIGQUIT);
  1983. X
  1984. X    l->argv = argv;
  1985. X    l->argc = argc;
  1986. X    l->argv[0] = name;
  1987. X    resetopts();
  1988. X
  1989. X    if (name[0] == '-') {
  1990. X        flag[FTALKING] = 1;
  1991. X        (void) include("/etc/profile");
  1992. X        (void) include(".profile");
  1993. X    }
  1994. X
  1995. X    /* include $ENV */
  1996. X    arg = substitute(strval(global("ENV")), DOTILDE);
  1997. X    if (*arg != '\0')
  1998. X        (void) include(arg);
  1999. X
  2000. X    if (flag[FTALKING]) {
  2001. X        signal(SIGTERM, trapsig);
  2002. X        ignoresig(SIGINT);
  2003. X    } else
  2004. X        flag[FHASHALL] = 1;
  2005. X
  2006. X#ifdef JOBS            /* todo: could go before includes? */
  2007. X    if (s->type == STTY) {
  2008. X        flag[FMONITOR] = 1;
  2009. X        j_change();
  2010. X    }
  2011. X#endif
  2012. X
  2013. X    argc = shell(s);
  2014. X    leave(argc);
  2015. X}
  2016. X
  2017. Xint
  2018. Xinclude(name)
  2019. X    register char *name;
  2020. X{
  2021. X    register FILE *f;
  2022. X    register Source *s;
  2023. X
  2024. X    if (strcmp(name, "-") != 0) {
  2025. X        f = fopen(name, "r");
  2026. X        if (f == NULL)
  2027. X            return 0;
  2028. X        /* todo: the savefd doesn't get popped */
  2029. X        fileno(f) = savefd(fileno(f)); /* questionable */
  2030. X        setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
  2031. X    } else
  2032. X        f = stdin;
  2033. X    s = pushs(SFILE);
  2034. X    s->u.file = f;
  2035. X    s->file = name;
  2036. X    /*return*/ shell(s);
  2037. X    if (f != stdin)
  2038. X        fclose(f);
  2039. X    return 1;
  2040. X}
  2041. X
  2042. Xint
  2043. Xcommand(comm)
  2044. X    register char *comm;
  2045. X{
  2046. X    register Source *s;
  2047. X
  2048. X    s = pushs(SSTRING);
  2049. X    s->str = comm;
  2050. X    return shell(s);
  2051. X}
  2052. X
  2053. X/*
  2054. X * run the commands from the input source, returning status.
  2055. X */
  2056. Xint
  2057. Xshell(s)
  2058. X    Source *s;        /* input source */
  2059. X{
  2060. X    struct op *t;
  2061. X    Volatile int attempts = 13;
  2062. X    Volatile int wastty;
  2063. X    Volatile int reading = 0;
  2064. X    extern void mcheck();
  2065. X
  2066. X    newenv(E_PARSE);
  2067. X    e.interactive = 1;
  2068. X    exstat = 0;
  2069. X    if (setjmp(e.jbuf)) {
  2070. X        /*shellf("<unwind>");*/
  2071. X        if (trap)    /* pending SIGINT */
  2072. X            shellf("\n");
  2073. X        if (reading && s->type == STTY && s->line)
  2074. X            s->line--;
  2075. X        sigtraps[SIGINT].set = 0;
  2076. X    }
  2077. X
  2078. X    while (1) {
  2079. X        if (trap)
  2080. X            runtraps();
  2081. X        if (flag[FTALKING])
  2082. X            signal(SIGINT, trapsig);
  2083. X
  2084. X        if (s->next == NULL)
  2085. X            s->echo = flag[FVERBOSE];
  2086. X
  2087. X        j_notify();
  2088. X
  2089. X        if ((wastty = (s->type == STTY)) || s->type == SHIST) {
  2090. X            prompt = substitute(strval(global("PS1")), 0);
  2091. X            mcheck();
  2092. X        }
  2093. X
  2094. X        reading = 1;
  2095. X        t = compile(s);
  2096. X        reading = 0;
  2097. X        j_reap();
  2098. X        if (t != NULL && t->type == TEOF)
  2099. X            if (wastty && flag[FIGNEOF] && --attempts > 0) {
  2100. X                shellf("Use `exit'\n");
  2101. X                s->type = STTY;
  2102. X                continue;
  2103. X            }
  2104. X            else
  2105. X                break;
  2106. X        flushshf(2);    /* flush -v output */
  2107. X
  2108. X        if (!flag[FNOEXEC] || s->type == STTY)
  2109. X            execute(t, 0);
  2110. X
  2111. X        reclaim();
  2112. X    }
  2113. X  Error:
  2114. X    quitenv();
  2115. X    return exstat;
  2116. X}
  2117. X
  2118. Xvoid
  2119. Xleave(rv)
  2120. X    int rv;
  2121. X{
  2122. X    if (e.type == E_TCOM && e.oenv != NULL)    /* exec'd command */
  2123. X        unwind();
  2124. X    runtrap(&sigtraps[0]);
  2125. X    j_exit();
  2126. X    exit(rv);
  2127. X    /* NOTREACHED */
  2128. X}
  2129. X
  2130. Xerror()
  2131. X{
  2132. X    if (flag[FERREXIT] || !flag[FTALKING])
  2133. X        leave(1);
  2134. X    unwind();
  2135. X}
  2136. X
  2137. X/* return to closest error handler or shell(), exit if none found */
  2138. Xunwind()
  2139. X{
  2140. X    while (1)
  2141. X        switch (e.type) {
  2142. X          case E_NONE:
  2143. X            leave(1);
  2144. X            /* NOTREACHED */
  2145. X          case E_PARSE:
  2146. X            longjmp(e.jbuf, 1);
  2147. X            /* NOTREACHED */
  2148. X          case E_ERRH:
  2149. X            longjmp(e.jbuf, 1);
  2150. X            /* NOTREACHED */
  2151. X          default:
  2152. X            quitenv();
  2153. X            break;
  2154. X        }
  2155. X}
  2156. X
  2157. Xnewenv(type)
  2158. X{
  2159. X    register struct env *ep;
  2160. X
  2161. X    ep = (struct env *) alloc(sizeof(*ep), ATEMP);
  2162. X    *ep = e;
  2163. X    ainit(&e.area);
  2164. X    e.type = type;
  2165. X    e.oenv = ep;
  2166. X    e.savefd = NULL;
  2167. X    e.temps = NULL;
  2168. X}
  2169. X
  2170. Xquitenv()
  2171. X{
  2172. X    register struct env *ep;
  2173. X    register int fd;
  2174. X
  2175. X    if ((ep = e.oenv) == NULL)
  2176. X        exit(exstat);    /* exit child */
  2177. X    if (e.loc != ep->loc)
  2178. X        popblock();
  2179. X    if (e.savefd != NULL)
  2180. X        for (fd = 0; fd < NUFILE; fd++)
  2181. X            restfd(fd, e.savefd[fd]);
  2182. X    reclaim();
  2183. X    e = *ep;
  2184. X}
  2185. X
  2186. X/* remove temp files and free ATEMP Area */
  2187. Xstatic void
  2188. Xreclaim()
  2189. X{
  2190. X    register struct temp *tp;
  2191. X
  2192. X    for (tp = e.temps; tp != NULL; tp = tp->next)
  2193. X        remove(tp->name);
  2194. X    e.temps = NULL;
  2195. X    afreeall(&e.area);
  2196. X}
  2197. X
  2198. Xvoid
  2199. Xaerror(ap, msg)
  2200. X    Area *ap;
  2201. X    Const char *msg;
  2202. X{
  2203. X    errorf("alloc internal error: %s\n", msg);
  2204. X}
  2205. X
  2206. END_OF_FILE
  2207.   if test 8586 -ne `wc -c <'sh/main.c'`; then
  2208.     echo shar: \"'sh/main.c'\" unpacked with wrong size!
  2209.   fi
  2210.   # end of 'sh/main.c'
  2211. fi
  2212. if test -f 'sh/tree.c' -a "${1}" != "-c" ; then 
  2213.   echo shar: Will not clobber existing file \"'sh/tree.c'\"
  2214. else
  2215.   echo shar: Extracting \"'sh/tree.c'\" \(9120 characters\)
  2216.   sed "s/^X//" >'sh/tree.c' <<'END_OF_FILE'
  2217. X/*
  2218. X * command tree climbing
  2219. X */
  2220. X
  2221. Xstatic char *RCSid = "$Id: tree.c,v 3.2 89/03/27 15:52:13 egisin Exp $";
  2222. X
  2223. X#include <stddef.h>
  2224. X#include <string.h>
  2225. X#include <stdio.h>
  2226. X#include <errno.h>
  2227. X#include <setjmp.h>
  2228. X#include <varargs.h>
  2229. X#include "sh.h"
  2230. X#include "tree.h"
  2231. X
  2232. X#define    FSTRING    (FILE*)NULL
  2233. X
  2234. Xstatic    int    tputc ARGS((int c, FILE *f));
  2235. Xstatic    void    tputC ARGS((int c, FILE *f));
  2236. Xstatic    void    tputS ARGS((char *wp, FILE *f));
  2237. X
  2238. X/*
  2239. X * print a command tree
  2240. X */
  2241. X
  2242. Xvoid
  2243. Xptree(t, f)
  2244. X    register struct op *t;
  2245. X    register FILE *f;
  2246. X{
  2247. X    register char **w;
  2248. X    struct ioword **ioact;
  2249. X    struct op *t1;
  2250. X
  2251. X Chain:
  2252. X    if (t == NULL)
  2253. X        return;
  2254. X    switch (t->type) {
  2255. X      case TCOM:
  2256. X        for (w = t->vars; *w != NULL; )
  2257. X            fptreef(f, "%S ", *w++);
  2258. X        for (w = t->args; *w != NULL; )
  2259. X            fptreef(f, "%S ", *w++);
  2260. X        break;
  2261. X      case TEXEC:
  2262. X        t = t->left;
  2263. X        goto Chain;
  2264. X      case TPAREN:
  2265. X        fptreef(f, "(%T)", t->left);
  2266. X        break;
  2267. X      case TPIPE:
  2268. X        fptreef(f, "%T| ", t->left);
  2269. X        t = t->right;
  2270. X        goto Chain;
  2271. X      case TLIST:
  2272. X        fptreef(f, "%T", t->left);
  2273. X        fptreef(f, "%;");
  2274. X        t = t->right;
  2275. X        goto Chain;
  2276. X      case TOR:
  2277. X      case TAND:
  2278. X        fptreef(f, "%T", t->left);
  2279. X        fptreef(f, "%s %T", (t->type==TOR) ? "||" : "&&", t->right);
  2280. X        break;
  2281. X      case TFOR:
  2282. X        fptreef(f, "for %s ", t->str);
  2283. X        if (t->vars != NULL) {
  2284. X            fptreef(f, "in ");
  2285. X            for (w = t->vars; *w; )
  2286. X                fptreef(f, "%S ", *w++);
  2287. X            fptreef(f, "%;");
  2288. X        }
  2289. X        fptreef(f, "do %T", t->left);
  2290. X        fptreef(f, "%;done ");
  2291. X        break;
  2292. X      case TCASE:
  2293. X        fptreef(f, "case %S in%;", t->str);
  2294. X        for (t1 = t->left; t1 != NULL; t1 = t1->right) {
  2295. X            fptreef(f, "(");
  2296. X            for (w = t1->vars; *w != NULL; w++) {
  2297. X                fptreef(f, "%S", *w);
  2298. X                fptreef(f, "%c", (w[1] != NULL) ? '|' : ')');
  2299. X            }
  2300. X            fptreef(f, " %T;;%;", t1->left);
  2301. X        }
  2302. X        fptreef(f, "esac ");
  2303. X        break;
  2304. X      case TIF:
  2305. X        fptreef(f, "if %T", t->left);
  2306. X        fptreef(f, "%;");
  2307. X        t = t->right;
  2308. X        if (t->left != NULL) {
  2309. X            fptreef(f, "then %T", t->left);
  2310. X            fptreef(f, "%;");
  2311. X        }
  2312. X        if (t->right != NULL) {
  2313. X            fptreef(f, "else %T", t->right);
  2314. X            fptreef(f, "%;");
  2315. X        }
  2316. X        fptreef(f, "fi ");
  2317. X        break;
  2318. X      case TWHILE:
  2319. X      case TUNTIL:
  2320. X        fptreef(f, "%s %T",
  2321. X            (t->type==TWHILE) ? "while" : "until",
  2322. X            t->left);
  2323. X        fptreef(f, "%;do %T", t->right);
  2324. X        fptreef(f, "%;done ");
  2325. X        break;
  2326. X      case TBRACE:
  2327. X        fptreef(f, "{%;%T", t->left);
  2328. X        fptreef(f, "%;} ");
  2329. X        break;
  2330. X      case TASYNC:
  2331. X        fptreef(f, "%T&", t->left);
  2332. X        break;
  2333. X      case TFUNCT:
  2334. X        fptreef(f, "function %s %T", t->str, t->left);
  2335. X        break;
  2336. X      case TTIME:
  2337. X        fptreef(f, "time %T", t->left);
  2338. X        break;
  2339. X      default:
  2340. X        fptreef(f, "<botch>");
  2341. X        break;
  2342. X    }
  2343. X    if ((ioact = t->ioact) != NULL)
  2344. X        while (*ioact != NULL)
  2345. X            pioact(f, *ioact++);
  2346. X}
  2347. X
  2348. Xpioact(f, iop)
  2349. X    register FILE *f;
  2350. X    register struct ioword *iop;
  2351. X{
  2352. X    register int flag = iop->flag;
  2353. X    if (iop->unit > 1)
  2354. X        fptreef(f, "%c", '0' + iop->unit );
  2355. X
  2356. X    switch(flag&IOTYPE) {
  2357. X    case IOREAD:
  2358. X        fptreef(f, "< ");
  2359. X        break;
  2360. X    case IOHERE:
  2361. X        if (flag&IOSKIP)
  2362. X            fptreef(f, "<<- ");
  2363. X        else
  2364. X            fptreef(f, "<< ");
  2365. X        if (!(flag&IOEVAL))
  2366. X            fptreef(f, "'");
  2367. X        break;
  2368. X    case IOCAT:
  2369. X        fptreef(f, ">> ");
  2370. X        break;
  2371. X    case IOWRITE:
  2372. X        if (flag&IOCLOB)
  2373. X            fptreef(f, ">! ");
  2374. X        else
  2375. X            fptreef(f, "> ");
  2376. X        break;
  2377. X    case IODUP:            /* Needs help */
  2378. X        if (iop->unit == 0)
  2379. X            fptreef(f, "<&");
  2380. X        else
  2381. X            fptreef(f, ">&");
  2382. X        break;
  2383. X    }
  2384. X
  2385. X    if ((flag&IOTYPE) == IOHERE) {
  2386. X        if (flag&IOEVAL)
  2387. X            fptreef(f, "%s ", iop->name);
  2388. X        else
  2389. X            fptreef(f, "%s' ", iop->name);
  2390. X    } else {
  2391. X        fptreef(f, "%S ", iop->name);
  2392. X    }
  2393. X}
  2394. X
  2395. X
  2396. X/*
  2397. X * variants of fputc, fputs for ptreef and snptreef
  2398. X */
  2399. X
  2400. Xstatic    char   *snpf_s;        /* snptreef string */
  2401. Xstatic    int    snpf_n;        /* snptreef length */
  2402. X
  2403. Xstatic int
  2404. Xtputc(c, f)
  2405. X    int c;
  2406. X    register FILE *f;
  2407. X{
  2408. X    if (f != NULL)
  2409. X        putc(c, f);
  2410. X    else
  2411. X        if (--snpf_n >= 0)
  2412. X            *snpf_s++ = c;
  2413. X    return c;
  2414. X}
  2415. X
  2416. Xstatic void
  2417. XtputC(c, f)
  2418. X    register int c;
  2419. X    register FILE *f;
  2420. X{
  2421. X    if ((c&0x60) == 0) {        /* C0|C1 */
  2422. X        tputc((c&0x80) ? '$' : '^', f);
  2423. X        tputc((c&0x7F|0x40), f);
  2424. X    } else if ((c&0x7F) == 0x7F) {    /* DEL */
  2425. X        tputc((c&0x80) ? '$' : '^', f);
  2426. X        tputc('?', f);
  2427. X    } else
  2428. X        tputc(c, f);
  2429. X}
  2430. X
  2431. Xstatic void
  2432. XtputS(wp, f)
  2433. X    register char *wp;
  2434. X    register FILE *f;
  2435. X{
  2436. X    register int c, quoted=0;
  2437. X
  2438. X    while (1)
  2439. X        switch ((c = *wp++)) {
  2440. X          case EOS:
  2441. X            return;
  2442. X          case CHAR:
  2443. X            tputC(*wp++, f);
  2444. X            break;
  2445. X          case QCHAR:
  2446. X            if (!quoted)
  2447. X                tputc('\\', f);
  2448. X            tputC(*wp++, f);
  2449. X            break;
  2450. X          case OQUOTE:
  2451. X              quoted = 1;
  2452. X            tputc('"', f);
  2453. X            break;
  2454. X          case CQUOTE:
  2455. X            quoted = 0;
  2456. X            tputc('"', f);
  2457. X            break;
  2458. X          case OSUBST:
  2459. X            tputc('$', f);
  2460. X            tputc('{', f);
  2461. X            while ((c = *wp++) != 0)
  2462. X                tputc(c, f);
  2463. X            if (*wp != CSUBST)
  2464. X                tputC(*wp++, f);
  2465. X            break;
  2466. X          case CSUBST:
  2467. X            tputc('}', f);
  2468. X            break;
  2469. X          case COMSUB:
  2470. X            tputc('$', f);
  2471. X            tputc('(', f);
  2472. X            while (*wp != 0)
  2473. X                tputC(*wp++, f);
  2474. X            tputc(')', f);
  2475. X            break;
  2476. X        }
  2477. X}
  2478. X
  2479. X/* TODO: use varargs properly */
  2480. X
  2481. X/* VARARGS */ int
  2482. Xfptreef(f, va_alist) va_dcl
  2483. X    register FILE *f;
  2484. X{
  2485. X    va_list va;
  2486. X    char *fmt;
  2487. X
  2488. X    va_start(va);
  2489. X    fmt = va_arg(va, char *);
  2490. X    vfptreef(f, fmt, va);
  2491. X    va_end(va);
  2492. X    return 0;
  2493. X}
  2494. X
  2495. X/* VARARGS */ int
  2496. Xsnptreef(s, n, va_alist) va_dcl
  2497. X    char *s;
  2498. X    int n;
  2499. X{
  2500. X    va_list va;
  2501. X    char *fmt;
  2502. X
  2503. X    snpf_s = s;
  2504. X    snpf_n = n;
  2505. X    va_start(va);
  2506. X    fmt = va_arg(va, char *);
  2507. X    vfptreef(FSTRING, fmt, va);
  2508. X    tputc('\0', FSTRING);
  2509. X    va_end(va);
  2510. X    return 0;
  2511. X}
  2512. X
  2513. Xvfptreef(f, fmt, va)
  2514. X    register FILE *f;
  2515. X    register char *fmt;
  2516. X    register va_list va;
  2517. X{
  2518. X    register int c;
  2519. X
  2520. X    while ((c = *fmt++))
  2521. X        if (c == '%') {
  2522. X        register long n;
  2523. X        register char *p;
  2524. X        int neg;
  2525. X
  2526. X        switch ((c = *fmt++)) {
  2527. X          case 'c':
  2528. X            tputc(va_arg(va, int), f);
  2529. X            break;
  2530. X          case 's':
  2531. X            p = va_arg(va, char *);
  2532. X            while (*p)
  2533. X                tputc(*p++, f);
  2534. X            break;
  2535. X          case 'S':    /* word */
  2536. X            p = va_arg(va, char *);
  2537. X            tputS(p, f);
  2538. X            break;
  2539. X          case 'd': case 'u': /* decimal */
  2540. X            n = (c == 'd') ? va_arg(va, int) : va_arg(va, unsigned int);
  2541. X            neg = c=='d' && n<0;
  2542. X            p = ulton((neg) ? -n : n, 10);
  2543. X            if (neg)
  2544. X                *--p = '-';
  2545. X            while (*p)
  2546. X                tputc(*p++, f);
  2547. X            break;
  2548. X          case 'T':    /* format tree */
  2549. X            ptree(va_arg(va, struct op *), f);
  2550. X            break;
  2551. X          case ';':    /* newline or ; */
  2552. X            p = (f == FSTRING) ? "; " : "\n";
  2553. X            while (*p)
  2554. X                tputc(*p++, f);
  2555. X            break;
  2556. X          default:
  2557. X            tputc(c, f);
  2558. X            break;
  2559. X        }
  2560. X        } else
  2561. X        tputc(c, f);
  2562. X}
  2563. X
  2564. X/*
  2565. X * copy tree (for function definition)
  2566. X */
  2567. X
  2568. Xstatic    struct ioword **iocopy();
  2569. X
  2570. Xstruct op *
  2571. Xtcopy(t, ap)
  2572. X    register struct op *t;
  2573. X    Area *ap;
  2574. X{
  2575. X    register struct op *r;
  2576. X    register char **tw, **rw;
  2577. X
  2578. X    if (t == NULL)
  2579. X        return NULL;
  2580. X
  2581. X    r = (struct op *) alloc(sizeof(struct op), ap);
  2582. X
  2583. X    r->type = t->type;
  2584. X
  2585. X    /* this will copy function and for identifiers quite accidently */
  2586. X    r->str = (t->str == NULL) ? NULL : wdcopy(t->str, ap);
  2587. X
  2588. X    if (t->vars == NULL)
  2589. X        r->vars = NULL;
  2590. X    else {
  2591. X        for (tw = t->vars; *tw++ != NULL; )
  2592. X            ;
  2593. X        rw = r->vars = (char **)
  2594. X            alloc((int)(tw - t->vars) * sizeof(*tw), ap);
  2595. X        for (tw = t->vars; *tw != NULL; )
  2596. X            *rw++ = wdcopy(*tw++, ap);
  2597. X        *rw = NULL;
  2598. X    }
  2599. X
  2600. X    if (t->args == NULL)
  2601. X        r->args = NULL;
  2602. X    else {
  2603. X        for (tw = t->args; *tw++ != NULL; )
  2604. X            ;
  2605. X        rw = r->args = (char **)
  2606. X            alloc((int)(tw - t->args) * sizeof(*tw), ap);
  2607. X        for (tw = t->args; *tw != NULL; )
  2608. X            *rw++ = wdcopy(*tw++, ap);
  2609. X        *rw = NULL;
  2610. X    }
  2611. X
  2612. X    r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
  2613. X
  2614. X    r->left = tcopy(t->left, ap);
  2615. X    r->right = tcopy(t->right, ap);
  2616. X
  2617. X    return r;
  2618. X}
  2619. X
  2620. Xchar *
  2621. Xwdcopy(wp, ap)
  2622. X    char *wp;
  2623. X    Area *ap;
  2624. X{
  2625. X    size_t len = wdscan(wp, EOS) - wp;
  2626. X    return memcpy(alloc(len, ap), wp, len);
  2627. X}
  2628. X
  2629. X/* return the position of prefix c in wp plus 1 */
  2630. Xchar *
  2631. Xwdscan(wp, c)
  2632. X    register char *wp;
  2633. X    register int c;
  2634. X{
  2635. X    register int nest = 0;
  2636. X
  2637. X    while (1)
  2638. X        switch (*wp++) {
  2639. X          case EOS:
  2640. X            return wp;
  2641. X          case CHAR:
  2642. X          case QCHAR:
  2643. X            wp++;
  2644. X            break;
  2645. X          case OQUOTE:
  2646. X          case CQUOTE:
  2647. X            break;
  2648. X          case OSUBST:
  2649. X            nest++;
  2650. X            while (*wp++ != 0)
  2651. X                ;
  2652. X            if (*wp != CSUBST)
  2653. X                wp++;
  2654. X            break;
  2655. X          case CSUBST:
  2656. X            if (c == CSUBST && nest == 0)
  2657. X                return wp;
  2658. X            nest--;
  2659. X            break;
  2660. X          case COMSUB:
  2661. X            while (*wp++ != 0)
  2662. X                ;
  2663. X            break;
  2664. X        }
  2665. X}
  2666. X
  2667. Xstatic    struct ioword **
  2668. Xiocopy(iow, ap)
  2669. X    register struct ioword **iow;
  2670. X    Area *ap;
  2671. X{
  2672. X    register struct ioword **ior;
  2673. X    register int i;
  2674. X
  2675. X    for (ior = iow; *ior++ != NULL; )
  2676. X        ;
  2677. X    ior = (struct ioword **) alloc((int)(ior - iow) * sizeof(*ior), ap);
  2678. X
  2679. X    for (i = 0; iow[i] != NULL; i++) {
  2680. X        register struct ioword *p, *q;
  2681. X
  2682. X        p = iow[i];
  2683. X        q = (struct ioword *) alloc(sizeof(*p), ap);
  2684. X        ior[i] = q;
  2685. X        *q = *p;
  2686. X        if (p->name != NULL)
  2687. X            q->name = wdcopy(p->name, ap);
  2688. X    }
  2689. X    ior[i] = NULL;
  2690. X
  2691. X    return ior;
  2692. X}
  2693. X
  2694. X/*
  2695. X * free tree (for function definition)
  2696. X */
  2697. X
  2698. Xstatic    void iofree();
  2699. X
  2700. Xvoid
  2701. Xtfree(t, ap)
  2702. X    register struct op *t;
  2703. X    Area *ap;
  2704. X{
  2705. X    register char **w;
  2706. X
  2707. X    if (t == NULL)
  2708. X        return;
  2709. X
  2710. X    if (t->str != NULL)
  2711. X        afree((Void*)t->str, ap);
  2712. X
  2713. X    if (t->vars != NULL) {
  2714. X        for (w = t->vars; *w != NULL; w++)
  2715. X            afree((Void*)*w, ap);
  2716. X        afree((Void*)t->vars, ap);
  2717. X    }
  2718. X
  2719. X    if (t->args != NULL) {
  2720. X        for (w = t->args; *w != NULL; w++)
  2721. X            afree((Void*)*w, ap);
  2722. X        afree((Void*)t->args, ap);
  2723. X    }
  2724. X
  2725. X    if (t->ioact != NULL)
  2726. X        iofree(t->ioact, ap);
  2727. X
  2728. X    tfree(t->left, ap);
  2729. X    tfree(t->right, ap);
  2730. X
  2731. X    afree((Void*)t, ap);
  2732. X}
  2733. X
  2734. Xstatic    void
  2735. Xiofree(iow, ap)
  2736. X    struct ioword **iow;
  2737. X    Area *ap;
  2738. X{
  2739. X    register struct ioword **iop;
  2740. X    register struct ioword *p;
  2741. X
  2742. X    for (iop = iow; (p = *iop++) != NULL; ) {
  2743. X        if (p->name != NULL)
  2744. X            afree((Void*)p->name, ap);
  2745. X        afree((Void*)p, ap);
  2746. X    }
  2747. X}
  2748. X
  2749. END_OF_FILE
  2750.   if test 9120 -ne `wc -c <'sh/tree.c'`; then
  2751.     echo shar: \"'sh/tree.c'\" unpacked with wrong size!
  2752.   fi
  2753.   # end of 'sh/tree.c'
  2754. fi
  2755. if test -f 'std/stdc/stdio.c' -a "${1}" != "-c" ; then 
  2756.   echo shar: Will not clobber existing file \"'std/stdc/stdio.c'\"
  2757. else
  2758.   echo shar: Extracting \"'std/stdc/stdio.c'\" \(301 characters\)
  2759.   sed "s/^X//" >'std/stdc/stdio.c' <<'END_OF_FILE'
  2760. X/*
  2761. X * Emulation of misc. ANSI C stdio functions
  2762. X */
  2763. X
  2764. X/* $Header */
  2765. X
  2766. X#include <stdio.h>
  2767. X
  2768. X#if 1
  2769. Xint
  2770. Xremove(name)
  2771. X    Const char *name;
  2772. X{
  2773. X    return unlink(name);
  2774. X}
  2775. X#endif
  2776. X
  2777. X#if _V7
  2778. Xint
  2779. Xrename(oname, nname)
  2780. X    Const char *oname, *nname;
  2781. X{
  2782. X    return link(oname, nname) == 0 && unlink(oname) == 0 ? 0 : -1;
  2783. X}
  2784. X#endif
  2785. X
  2786. END_OF_FILE
  2787.   if test 301 -ne `wc -c <'std/stdc/stdio.c'`; then
  2788.     echo shar: \"'std/stdc/stdio.c'\" unpacked with wrong size!
  2789.   fi
  2790.   # end of 'std/stdc/stdio.c'
  2791. fi
  2792. echo shar: End of archive 5 \(of 9\).
  2793. cp /dev/null ark5isdone
  2794. MISSING=""
  2795. for I in 1 2 3 4 5 6 7 8 9 ; do
  2796.     if test ! -f ark${I}isdone ; then
  2797.     MISSING="${MISSING} ${I}"
  2798.     fi
  2799. done
  2800. if test "${MISSING}" = "" ; then
  2801.     echo You have unpacked all 9 archives.
  2802.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2803. else
  2804.     echo You still must unpack the following archives:
  2805.     echo "        " ${MISSING}
  2806. fi
  2807. exit 0
  2808. exit 0 # Just in case...
  2809. -- 
  2810. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2811. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2812. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2813. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2814.