home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2270 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  38.9 KB

  1. From: netnews@netcom.UUCP (USENET Administration)
  2. Newsgroups: alt.sources
  3. Subject: Public Domain Korn Shell - Part.05 of 7
  4. Message-ID: <18610@netcom.UUCP>
  5. Date: 12 Dec 90 11:38:04 GMT
  6.  
  7. #!/bin/sh
  8. # This is part 05 of ksh-pd
  9. # ============= src/c_ksh.c ==============
  10. if test ! -d 'src'; then
  11.     echo 'x - creating directory src'
  12.     mkdir 'src'
  13. fi
  14. if test -f 'src/c_ksh.c' -a X"$1" != X"-c"; then
  15.     echo 'x - skipping src/c_ksh.c (File already exists)'
  16. else
  17. echo 'x - extracting src/c_ksh.c (Text)'
  18. sed 's/^X//' << 'SHAR_EOF' > 'src/c_ksh.c' &&
  19. X/*
  20. X * built-in Korn commands: c_*
  21. X */
  22. X
  23. Xstatic char *RCSid = "$Id: c_ksh.c,v 3.2 89/01/23 10:57:38 egisin Exp $";
  24. X
  25. X#include <stddef.h>
  26. X#include <stdio.h>
  27. X#include <string.h>
  28. X#include <errno.h>
  29. X#include <setjmp.h>
  30. X#include "sh.h"
  31. X#include "table.h"
  32. X
  33. Xint
  34. Xc_hash(wp)
  35. X    register char **wp;
  36. X{
  37. X    register int i;
  38. X    register struct tbl *tp, **p;
  39. X
  40. X    wp++;
  41. X    if (*wp == NULL) {
  42. X        for (p = tsort(&commands); (tp = *p++) != NULL; )
  43. X            if ((tp->flag&ISSET))
  44. X                printf("%s\n", tp->val.s);
  45. X        return 0;
  46. X    }
  47. X
  48. X    if (strcmp(*wp, "-r") == 0)
  49. X        flushcom(1);
  50. X    while (*wp != NULL)
  51. X        findcom(*wp++, 1);
  52. X    return 0;
  53. X}
  54. X
  55. Xint
  56. Xc_print(wp)
  57. X    register char **wp;
  58. X{
  59. X    int nl = 1;
  60. X    int expand = 1;
  61. X    FILE *f = stdout;
  62. X
  63. X    for (wp++; *wp != NULL && **wp == '-'; wp++) {
  64. X        register char *s = *wp + 1;
  65. X        if (*s == '\0') {
  66. X            wp++;
  67. X            break;
  68. X        }
  69. X        while (*s) switch (*s++) {
  70. X          case 'n':
  71. X            nl = 0;
  72. X            break;
  73. X          case 'e':
  74. X            expand = 1;
  75. X            break;
  76. X          case 'r':
  77. X            expand = 0;
  78. X            break;
  79. X          case 'u':
  80. X            if (!digit(*s) || (f = shf[*s++-'0']) == NULL)
  81. X                errorf("bad -u argument\n");
  82. X            break;
  83. X        }
  84. X    }
  85. X
  86. X    while (*wp != NULL) {
  87. X        register char *s = *wp;
  88. X        register int c;
  89. X        while ((c = *s++) != '\0')
  90. X            if (expand && c == '\\') {
  91. X                switch ((c = *s++)) {
  92. X                case 'b': c = '\b'; break;
  93. X                case 'c': nl = 0; continue; /* AT&T brain damage */
  94. X                case 'f': c = '\f'; break;
  95. X                case 'n': c = '\n'; break;
  96. X                case 'r': c = '\r'; break;
  97. X                case 't': c = '\t'; break;
  98. X                case 'v': c = 0x0B; break;
  99. X                case '0': case '1': case '2': case '3':
  100. X                case '4': case '5': case '6': case '7':
  101. X                    c = c - '0';
  102. X                    if (*s >= '0' && *s <= '7')
  103. X                        c = 8*c + *s++ - '0';
  104. X                    if (*s >= '0' && *s <= '7')
  105. X                        c = 8*c + *s++ - '0';
  106. X                    break;
  107. X                case '\\': break;
  108. X                default:
  109. X                    putc('\\', f);
  110. X                }
  111. X                putc(c, f);
  112. X            } else
  113. X                putc(c, f);
  114. X        if (*++wp != NULL)
  115. X            putc(' ', f);
  116. X    }
  117. X    if (nl)
  118. X        putc('\n', f);
  119. X    return 0;
  120. X}
  121. X
  122. X/* todo: handle case where id is both lexical and command */
  123. Xint
  124. Xc_whence(wp)
  125. X    register char **wp;
  126. X{
  127. X    register struct tbl *tp;
  128. X    char *id;
  129. X    int vflag = 0;
  130. X
  131. X    for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
  132. X        if (id[1] == 'v')
  133. X            vflag = 1;
  134. X
  135. X    while ((id = *wp++) != NULL) {
  136. X        tp = tsearch(&lexicals, id, hash(id));
  137. X        if (tp == NULL)
  138. X            tp = findcom(id, 1);
  139. X        if (vflag)
  140. X            switch ((tp == NULL) ? CNONE : tp->type) {
  141. X              case CNONE:
  142. X                printf("%s is unknown\n", id);
  143. X                break;
  144. X              case CSHELL:
  145. X                printf("%s is a shell builtin\n", id);
  146. X                break;
  147. X              case CFUNC:
  148. X                printf("%s is a function\n", id);
  149. X                fptreef(stdout, "function %s %T\n", id, tp->val.t);
  150. X                break;
  151. X              case CEXEC:
  152. X                printf("%s is %s\n", id,
  153. X                       (tp->flag&ISSET) ? tp->val.s : "unknown");
  154. X                break;
  155. X              case CALIAS:
  156. X                printf("%s is the alias '%s'\n", id, tp->val.s);
  157. X                break;
  158. X              case CKEYWD:
  159. X                printf("%s is a shell keyword\n", id);
  160. X                break;
  161. X              default:
  162. X                printf("%s is *GOK*\n", id);
  163. X                break;
  164. X            }
  165. X        else
  166. X            switch ((tp == NULL) ? CNONE : tp->type) {
  167. X              case CNONE:
  168. X                printf("\n");
  169. X                break;
  170. X              case CSHELL:
  171. X                printf("builtin %s\n", id);
  172. X                break;
  173. X              case CFUNC:
  174. X                printf("%s\n", id);
  175. X                break;
  176. X              case CEXEC:
  177. X                printf("%s\n", (tp->flag&ISSET) ? tp->val.s : id);
  178. X                break;
  179. X              case CALIAS:
  180. X                printf("%s\n", tp->val.s);
  181. X                break;
  182. X              case CKEYWD:
  183. X                printf("%s\n", id);
  184. X                break;
  185. X              default:
  186. X                printf("*GOK*\n");
  187. X                break;
  188. X            }
  189. X    }
  190. X    return 0;
  191. X}
  192. X
  193. X/* typeset, export, and readonly */
  194. Xint
  195. Xc_typeset(wp)
  196. X    register char **wp;
  197. X{
  198. X    register char *id;
  199. X    struct block *l = e.loc;
  200. X    register struct tbl *vp, **p;
  201. X    int fset = 0, fclr = 0;
  202. X    int thing = 0, func = 0, local = 0;
  203. X
  204. X    switch (**wp) {
  205. X      case 'e':        /* export */
  206. X        fset |= EXPORT;
  207. X        break;
  208. X      case 'r':        /* readonly */
  209. X        fset |= RDONLY;
  210. X        break;
  211. X      case 't':        /* typeset */
  212. X        local = 1;
  213. X        break;
  214. X    }
  215. X
  216. X    for (wp++; (id = *wp) != NULL && (*id == '-' || *id == '+'); wp++) {
  217. X        int flag = 0;
  218. X        thing = *id;
  219. X        while (*++id != '\0') switch (*id) {
  220. X          case 'f':
  221. X            flag |= FUNCT;
  222. X            func = 1;
  223. X            break;
  224. X          case 'i':
  225. X            flag |= INTEGER;
  226. X            break;
  227. X          case 'r':
  228. X            flag |= RDONLY;
  229. X            break;
  230. X          case 'x':
  231. X            flag |= EXPORT;
  232. X            break;
  233. X          case 't':
  234. X            flag |= TRACE;
  235. X            break;
  236. X          default:
  237. X            errorf("unknown flag -%c\n", *id);
  238. X        }
  239. X        if (flag != 0) { /* + or - with options */
  240. X            if (thing == '-')
  241. X                fset |= flag;
  242. X            else
  243. X                fclr |= flag;
  244. X            thing = 0;
  245. X        }
  246. X    }
  247. X
  248. X    /* list variables and attributes */
  249. X    if (*wp == NULL) {
  250. X        for (l = e.loc; l != NULL; l = l->next) {
  251. X            for (p = tsort((func==0) ? &l->vars : &l->funs);
  252. X             (vp = *p++) != NULL; )
  253. X            if ((vp->flag&ISSET))
  254. X                if (thing == 0 && fclr == 0 && fset == 0) {
  255. X                printf("typeset ");
  256. X                if ((vp->flag&INTEGER))
  257. X                    printf("-i ");
  258. X                if ((vp->flag&EXPORT))
  259. X                    printf("-x ");
  260. X                if ((vp->flag&RDONLY))
  261. X                    printf("-r ");
  262. X                if ((vp->flag&TRACE)) 
  263. X                    printf("-t ");
  264. X                printf("%s\n", vp->name);
  265. X                } else
  266. X                if (thing == '+' ||
  267. X                fclr && (vp->flag&fclr) == fclr) {
  268. X                printf("%s\n", vp->name);
  269. X                } else
  270. X                if (thing == '-' ||
  271. X                fset && (vp->flag&fset) == fset) {
  272. X                if (fset&FUNCT)
  273. X                    printf("function %s\n", vp->name);
  274. X                else
  275. X                    printf("%s=%s\n", vp->name, strval(vp));
  276. X                }
  277. X        }
  278. X        return (0);
  279. X    }
  280. X
  281. X    if (local)
  282. X        fset |= LOCAL;
  283. X    for (; *wp != NULL; wp++)
  284. X#if 0
  285. X        if (func) {
  286. X        } else
  287. X#endif
  288. X        if (typeset(*wp, fset, fclr) == NULL)
  289. X            errorf("%s: not identifier\n", *wp);
  290. X    return 0;
  291. X}
  292. X    
  293. Xint
  294. Xc_alias(wp)
  295. X    register char **wp;
  296. X{
  297. X    register struct table *t = &lexicals;
  298. X    register struct tbl *ap, **p;
  299. X    register int i;
  300. X    int rv = 0;
  301. X
  302. X    if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
  303. X        t = &homedirs;
  304. X        wp++;
  305. X    }
  306. X
  307. X    if (*wp == NULL)
  308. X        for (p = tsort(t); (ap = *p++) != NULL; )
  309. X            if (ap->type == CALIAS && (ap->flag&DEFINED))
  310. X                printf("%s='%s'\n", ap->name, ap->val.s);
  311. X
  312. X    for (; *wp != NULL; wp++) {
  313. X        register char *id = *wp;
  314. X        register char *val = strchr(id, '=');
  315. X
  316. X        if (val == NULL) {
  317. X            ap = tsearch(t, id, hash(id));
  318. X            if (ap != NULL && ap->type == CALIAS && (ap->flag&DEFINED))
  319. X                printf("%s='%s'\n", ap->name, ap->val.s);
  320. X            else
  321. X                rv = 1;
  322. X        } else {
  323. X            *val++ = '\0';
  324. X            ap = tenter(t, id, hash(id));
  325. X            if (ap->type == CKEYWD)
  326. X                errorf("cannot alias keyword\n");
  327. X            if ((ap->flag&ALLOC)) {
  328. X                afree((Void*)ap->val.s, APERM);
  329. X                ap->flag &=~ ALLOC|ISSET;
  330. X            }
  331. X            ap->type = CALIAS;
  332. X            ap->val.s = strsave(val, APERM);
  333. X            ap->flag |= DEFINED|ALLOC|ISSET;
  334. X        }
  335. X    }
  336. X    return rv;
  337. X}
  338. X
  339. Xint
  340. Xc_unalias(wp)
  341. X    register char **wp;
  342. X{
  343. X    register struct table *t = &lexicals;
  344. X    register struct tbl *ap;
  345. X
  346. X    if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
  347. X        t = &homedirs;
  348. X        wp++;
  349. X    }
  350. X
  351. X    for (; *wp != NULL; wp++) {
  352. X        ap = tsearch(t, *wp, hash(*wp));
  353. X        if (ap == NULL || ap->type != CALIAS)
  354. X            continue;
  355. X        if ((ap->flag&ALLOC))
  356. X            afree((Void*)ap->val.s, APERM);
  357. X        ap->flag &=~ DEFINED|ISSET|ALLOC;
  358. X    }
  359. X    return 0;
  360. X}
  361. X
  362. Xint
  363. Xc_let(wp)
  364. X    char **wp;
  365. X{
  366. X    int rv = 1;
  367. X
  368. X    for (wp++; *wp; wp++)
  369. X        rv = evaluate(*wp) == 0;
  370. X    return rv;
  371. X}
  372. X
  373. Xint
  374. Xc_jobs(wp)
  375. X    char **wp;
  376. X{
  377. X    j_jobs();
  378. X    return 0;
  379. X}
  380. X
  381. X#if JOBS
  382. Xint
  383. Xc_fgbg(wp)
  384. X    register char **wp;
  385. X{
  386. X    int bg = strcmp(*wp, "bg") == 0;
  387. X
  388. X    if (!flag[FMONITOR])
  389. X        errorf("Job control not enabled\n");
  390. X    wp++;
  391. X    j_resume(j_lookup((*wp == NULL) ? "%" : *wp), bg);
  392. X    return 0;
  393. X}
  394. X#endif
  395. X
  396. Xint
  397. Xc_kill(wp)
  398. X    register char **wp;
  399. X{
  400. X    register char *cp;
  401. X    int sig = 15;        /* SIGTERM */
  402. X    int rv = 0;
  403. X
  404. X    if (*++wp == NULL)
  405. X        errorf("Usage: kill [-l] [-signal] {pid|job} ...\n");
  406. X    if (strcmp(*wp, "-l") == 0) {
  407. X        register struct trap *p = sigtraps;
  408. X        for (sig = 0; sig < SIGNALS; sig++, p++)
  409. X            if (p->signal)
  410. X                printf("%2d %8s %s\n", p->signal, p->name, p->mess);
  411. X        return 0;
  412. X    }
  413. X
  414. X    for (; (cp = *wp) != NULL; wp++)
  415. X        if (*cp == '-') {
  416. X            struct trap *p;
  417. X            p = gettrap(cp+1);
  418. X            if (p == NULL)
  419. X                errorf("bad signal %s\n", cp+1);
  420. X            sig = p->signal;
  421. X        } else
  422. X        if (digit(*cp)) {
  423. X            if (kill(atoi(cp), sig) < 0) {
  424. X                shellf("%s: %s\n", cp, strerror(errno));
  425. X                rv++;
  426. X            }
  427. X        } else
  428. X        if (*cp == '%')
  429. X            j_kill(j_lookup(cp), sig);
  430. X        else
  431. X            errorf("invalid argument\n");
  432. X    return rv;
  433. X}
  434. X
  435. Xint
  436. Xc_bind(wp)
  437. X    register char **wp;
  438. X{
  439. X    int macro = 0;
  440. X    register char *cp;
  441. X
  442. X    for (wp++; (cp = *wp) != NULL && *cp == '-'; wp++)
  443. X        if (cp[1] == 'm')
  444. X            macro = 1;
  445. X
  446. X    if (*wp == NULL)    /* list all */
  447. X        x_bind((char*)NULL, (char*)NULL, 0);
  448. X
  449. X    for (; *wp != NULL; wp++) {
  450. X        cp = strchr(*wp, '=');
  451. X        if (cp != NULL)
  452. X            *cp++ = 0;
  453. X        x_bind(*wp, cp, macro);
  454. X    }
  455. X
  456. X    return 0;
  457. X}
  458. X
  459. Xextern    c_fc();
  460. Xextern    c_getopts();
  461. X
  462. XConst struct builtin kshbuiltins [] = {
  463. X    {"print", c_print},
  464. X    {"getopts", c_getopts},
  465. X    {"=typeset", c_typeset},
  466. X    {"=export", c_typeset},
  467. X    {"=readonly", c_typeset},
  468. X    {"whence", c_whence},
  469. X    {"alias", c_alias},
  470. X    {"unalias", c_unalias},
  471. X    {"hash", c_hash},
  472. X    {"let", c_let},
  473. X    {"fc", c_fc},
  474. X    {"jobs", c_jobs},
  475. X    {"kill", c_kill},
  476. X#if JOBS
  477. X    {"fg", c_fgbg},
  478. X    {"bg", c_fgbg},
  479. X#endif
  480. X#if EDIT
  481. X    {"bind", c_bind},
  482. X#endif
  483. X    {NULL, NULL}
  484. X};
  485. X
  486. SHAR_EOF
  487. true || echo 'restore of src/c_ksh.c failed'
  488. fi
  489. # ============= src/c_test.c ==============
  490. if test -f 'src/c_test.c' -a X"$1" != X"-c"; then
  491.     echo 'x - skipping src/c_test.c (File already exists)'
  492. else
  493. echo 'x - extracting src/c_test.c (Text)'
  494. sed 's/^X//' << 'SHAR_EOF' > 'src/c_test.c' &&
  495. X/*
  496. X * test(1); version 7-like  --  author Erik Baalbergen
  497. X * modified by Eric Gisin to be used as built-in.
  498. X * modified by Arnold Robbins to add SVR3 compatibility
  499. X * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
  500. X */
  501. X
  502. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/c_test.c,v 3.2 88/12/17 21:39:26 egisin Exp $";
  503. X
  504. X#include <stddef.h>
  505. X#include <string.h>
  506. X#include <signal.h>
  507. X#include <errno.h>
  508. X#include <setjmp.h>
  509. X#include <sys/types.h>
  510. X#include <sys/stat.h>
  511. X#include "sh.h"
  512. X
  513. X/* test(1) accepts the following grammar:
  514. X    oexpr    ::= aexpr | aexpr "-o" oexpr ;
  515. X    aexpr    ::= nexpr | nexpr "-a" aexpr ;
  516. X    nexpr    ::= primary ! "!" primary
  517. X    primary    ::= unary-operator operand
  518. X        | operand binary-operator operand
  519. X        | operand
  520. X        | "(" oexpr ")"
  521. X        ;
  522. X    unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
  523. X        "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
  524. X
  525. X    binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
  526. X            "-nt"|"-ot"|"-ef";
  527. X    operand ::= <any legal UNIX file name>
  528. X*/
  529. X
  530. X#define EOI    0
  531. X#define FILRD    1
  532. X#define FILWR    2
  533. X#define FILREG    3
  534. X#define FILID    4
  535. X#define FILGZ    5
  536. X#define FILTT    6
  537. X#define STZER    7
  538. X#define STNZE    8
  539. X#define STEQL    9
  540. X#define STNEQ    10
  541. X#define INTEQ    11
  542. X#define INTNE    12
  543. X#define INTGE    13
  544. X#define INTGT    14
  545. X#define INTLE    15
  546. X#define INTLT    16
  547. X#define UNOT    17
  548. X#define BAND    18
  549. X#define BOR    19
  550. X#define LPAREN    20
  551. X#define RPAREN    21
  552. X#define OPERAND    22
  553. X#define FILEX    23
  554. X#define FILCDEV    24
  555. X#define FILBDEV    25
  556. X#define FILFIFO    26
  557. X#define FILSETU    27
  558. X#define FILSETG    28
  559. X#define FILSTCK    29
  560. X#define FILSYM    30
  561. X#define FILNT    31
  562. X#define FILOT    32
  563. X#define FILEQ    33
  564. X#define FILSOCK    34
  565. X#define    FILUID    35
  566. X#define    FILGID    36
  567. X#define    OPTION    37
  568. X
  569. X#define UNOP    1
  570. X#define BINOP    2
  571. X#define BUNOP    3
  572. X#define BBINOP    4
  573. X#define PAREN    5
  574. X
  575. Xstruct t_op {
  576. X    char *op_text;
  577. X    short op_num, op_type;
  578. X} Const ops [] = {
  579. X    {"-r",    FILRD,    UNOP},
  580. X    {"-w",    FILWR,    UNOP},
  581. X    {"-x",    FILEX,    UNOP},
  582. X    {"-f",    FILREG,    UNOP},
  583. X    {"-d",    FILID,    UNOP},
  584. X    {"-c",    FILCDEV,UNOP},
  585. X    {"-b",    FILBDEV,UNOP},
  586. X    {"-p",    FILFIFO,UNOP},
  587. X    {"-u",    FILSETU,UNOP},
  588. X    {"-g",    FILSETG,UNOP},
  589. X    {"-k",    FILSTCK,UNOP},
  590. X    {"-s",    FILGZ,    UNOP},
  591. X    {"-t",    FILTT,    UNOP},
  592. X    {"-z",    STZER,    UNOP},
  593. X    {"-n",    STNZE,    UNOP},
  594. X#if 0                /* conficts with binary -o */
  595. X    {"-o",    OPTION,    UNOP},
  596. X#endif
  597. X    {"-U",    FILUID,    UNOP},
  598. X    {"-G",    FILGID,    UNOP},
  599. X    {"-L",    FILSYM,    UNOP},
  600. X    {"-S",    FILSOCK,UNOP},
  601. X    {"=",    STEQL,    BINOP},
  602. X    {"!=",    STNEQ,    BINOP},
  603. X    {"-eq",    INTEQ,    BINOP},
  604. X    {"-ne",    INTNE,    BINOP},
  605. X    {"-ge",    INTGE,    BINOP},
  606. X    {"-gt",    INTGT,    BINOP},
  607. X    {"-le",    INTLE,    BINOP},
  608. X    {"-lt",    INTLT,    BINOP},
  609. X    {"-nt",    FILNT,    BINOP},
  610. X    {"-ot",    FILOT,    BINOP},
  611. X    {"-ef",    FILEQ,    BINOP},
  612. X    {"!",    UNOT,    BUNOP},
  613. X    {"-a",    BAND,    BBINOP},
  614. X    {"-o",    BOR,    BBINOP},
  615. X    {"(",    LPAREN,    PAREN},
  616. X    {")",    RPAREN,    PAREN},
  617. X    {0,    0,    0}
  618. X};
  619. X
  620. Xchar **t_wp;
  621. Xstruct t_op Const *t_wp_op;
  622. X
  623. Xint
  624. Xc_test(wp)
  625. X    char **wp;
  626. X{
  627. X    t_wp = wp+1;
  628. X    if (strcmp(wp[0], "[") == 0) {
  629. X        while (*wp != NULL)
  630. X            wp++;
  631. X        if (strcmp(*--wp, "]") != 0)
  632. X            errorf("[: missing ]\n");
  633. X        *wp = NULL;
  634. X    }
  635. X    return *t_wp == NULL || !oexpr(t_lex(*t_wp));
  636. X}
  637. X
  638. Xstatic
  639. Xsyntax()
  640. X{
  641. X    errorf("test: syntax error\n");
  642. X}
  643. X
  644. Xoexpr(n)
  645. X{
  646. X    int res;
  647. X
  648. X    res = aexpr(n);
  649. X    if (t_lex(*++t_wp) == BOR)
  650. X        return oexpr(t_lex(*++t_wp)) || res;
  651. X    t_wp--;
  652. X    return res;
  653. X}
  654. X
  655. Xaexpr(n)
  656. X{
  657. X    int res;
  658. X
  659. X    res = nexpr(n);
  660. X    if (t_lex(*++t_wp) == BAND)
  661. X        return aexpr(t_lex(*++t_wp)) && res;
  662. X    t_wp--;
  663. X    return res;
  664. X}
  665. X
  666. Xnexpr(n)
  667. X    int n;            /* token */
  668. X{
  669. X    if (n == UNOT)
  670. X        return !nexpr(t_lex(*++t_wp));
  671. X    return primary(n);
  672. X}
  673. X
  674. Xprimary(n)
  675. X    int n;            /* token */
  676. X{
  677. X    register char *opnd1, *opnd2;
  678. X    int res;
  679. X
  680. X    if (n == EOI)
  681. X        syntax();
  682. X    if (n == LPAREN) {
  683. X        res = oexpr(t_lex(*++t_wp));
  684. X        if (t_lex(*++t_wp) != RPAREN)
  685. X            syntax();
  686. X        return res;
  687. X    }
  688. X    if (n == OPERAND) {
  689. X        opnd1 = *t_wp;
  690. X        (void) t_lex(*++t_wp);
  691. X        if (t_wp_op && t_wp_op->op_type == BINOP) {
  692. X            struct t_op Const *op = t_wp_op;
  693. X
  694. X            if ((opnd2 = *++t_wp) == (char *)0)
  695. X                syntax();
  696. X            
  697. X            switch (op->op_num) {
  698. X            case STEQL:
  699. X                return strcmp(opnd1, opnd2) == 0;
  700. X            case STNEQ:
  701. X                return strcmp(opnd1, opnd2) != 0;
  702. X            case INTEQ:
  703. X                return evaluate(opnd1) == evaluate(opnd2);
  704. X            case INTNE:
  705. X                return evaluate(opnd1) != evaluate(opnd2);
  706. X            case INTGE:
  707. X                return evaluate(opnd1) >= evaluate(opnd2);
  708. X            case INTGT:
  709. X                return evaluate(opnd1) > evaluate(opnd2);
  710. X            case INTLE:
  711. X                return evaluate(opnd1) <= evaluate(opnd2);
  712. X            case INTLT:
  713. X                return evaluate(opnd1) < evaluate(opnd2);
  714. X            case FILNT:
  715. X                return newerf (opnd1, opnd2);
  716. X            case FILOT:
  717. X                return olderf (opnd1, opnd2);
  718. X            case FILEQ:
  719. X                return equalf (opnd1, opnd2);
  720. X            }
  721. X        }
  722. X        t_wp--;
  723. X        return strlen(opnd1) > 0;
  724. X    }
  725. X    if (t_wp_op->op_type == UNOP) {
  726. X        /* unary expression */
  727. X        if (*++t_wp == NULL && n != FILTT)
  728. X            syntax();
  729. X        switch (n) {
  730. X          case OPTION:
  731. X            return flag[option(*t_wp)];
  732. X          case STZER:
  733. X            return strlen(*t_wp) == 0;
  734. X          case STNZE:
  735. X            return strlen(*t_wp) != 0;
  736. X          case FILTT:
  737. X            if (!digit(**t_wp))
  738. X                return filstat("0", n);
  739. X          default:    /* all other FIL* */
  740. X            return filstat(*t_wp, n);
  741. X        }
  742. X    }
  743. X    syntax();
  744. X}
  745. X
  746. Xfilstat(nm, mode)
  747. X    char *nm;
  748. X{
  749. X    struct stat s;
  750. X    
  751. X    switch (mode) {
  752. X    case FILRD:
  753. X        return eaccess(nm, 4) == 0;
  754. X    case FILWR:
  755. X        return eaccess(nm, 2) == 0;
  756. X    case FILEX:
  757. X        return eaccess(nm, 1) == 0;
  758. X    case FILREG:
  759. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG;
  760. X    case FILID:
  761. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR;
  762. X    case FILCDEV:
  763. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFCHR;
  764. X    case FILBDEV:
  765. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFBLK;
  766. X    case FILFIFO:
  767. X#ifdef S_IFIFO
  768. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFIFO;
  769. X#else
  770. X        return 0;
  771. X#endif
  772. X    case FILSETU:
  773. X        return stat(nm, &s) == 0 && (s.st_mode & S_ISUID) == S_ISUID;
  774. X    case FILSETG:
  775. X        return stat(nm, &s) == 0 && (s.st_mode & S_ISGID) == S_ISGID;
  776. X    case FILSTCK:
  777. X        return stat(nm, &s) == 0 && (s.st_mode & S_ISVTX) == S_ISVTX;
  778. X    case FILGZ:
  779. X        return stat(nm, &s) == 0 && s.st_size > 0L;
  780. X    case FILTT:
  781. X        return isatty(getn(nm));
  782. X      case FILUID:
  783. X        return stat(nm, &s) == 0 && s.st_uid == geteuid();
  784. X      case FILGID:
  785. X        return stat(nm, &s) == 0 && s.st_gid == getegid();
  786. X#ifdef S_IFLNK
  787. X    case FILSYM:
  788. X        return lstat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFLNK;
  789. X#endif
  790. X#ifdef S_IFSOCK
  791. X    case FILSOCK:
  792. X        return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFSOCK;
  793. X#endif
  794. X      default:
  795. X        return 1;
  796. X    }
  797. X}
  798. X
  799. Xint
  800. Xt_lex(s)
  801. X    register char *s;
  802. X{
  803. X    register struct t_op Const *op = ops;
  804. X
  805. X    if (s == 0)
  806. X        return EOI;
  807. X    while (op->op_text) {
  808. X        if (strcmp(s, op->op_text) == 0) {
  809. X            t_wp_op = op;
  810. X            return op->op_num;
  811. X        }
  812. X        op++;
  813. X    }
  814. X    t_wp_op = (struct t_op *)0;
  815. X    return OPERAND;
  816. X}
  817. X
  818. Xnewerf (f1, f2)
  819. Xchar *f1, *f2;
  820. X{
  821. X    struct stat b1, b2;
  822. X
  823. X    return (stat (f1, &b1) == 0 &&
  824. X        stat (f2, &b2) == 0 &&
  825. X        b1.st_mtime > b2.st_mtime);
  826. X}
  827. X
  828. Xolderf (f1, f2)
  829. Xchar *f1, *f2;
  830. X{
  831. X    struct stat b1, b2;
  832. X
  833. X    return (stat (f1, &b1) == 0 &&
  834. X        stat (f2, &b2) == 0 &&
  835. X        b1.st_mtime < b2.st_mtime);
  836. X}
  837. X
  838. Xequalf (f1, f2)
  839. Xchar *f1, *f2;
  840. X{
  841. X    struct stat b1, b2;
  842. X
  843. X    return (stat (f1, &b1) == 0 &&
  844. X        stat (f2, &b2) == 0 &&
  845. X        b1.st_dev == b2.st_dev &&
  846. X        b1.st_ino == b2.st_ino);
  847. X}
  848. X
  849. SHAR_EOF
  850. true || echo 'restore of src/c_test.c failed'
  851. fi
  852. # ============= src/getopts.c ==============
  853. if test -f 'src/getopts.c' -a X"$1" != X"-c"; then
  854.     echo 'x - skipping src/getopts.c (File already exists)'
  855. else
  856. echo 'x - extracting src/getopts.c (Text)'
  857. sed 's/^X//' << 'SHAR_EOF' > 'src/getopts.c' &&
  858. X/*
  859. X * Reimplementation of SysVr3 sh builtin command "getopts" for S5R2 shell.
  860. X *
  861. X * created by Arnold Robbins
  862. X * modified by Doug Gwyn
  863. X * modified for PD ksh by Eric Gisin
  864. X */
  865. X
  866. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/getopts.c,v 3.2 89/01/14 13:29:26 egisin Exp $";
  867. X
  868. X#include <stddef.h>
  869. X#include <string.h>
  870. X#include <errno.h>
  871. X#include <setjmp.h>
  872. X#include "sh.h"
  873. X#include "table.h"
  874. X
  875. X/*
  876. X * The following is derived from getopt() source placed into the public
  877. X * domain by AT&T (the only time they're known to have done that).
  878. X *
  879. X * It has been modified somewhat to fit into the context of the shell.
  880. X *
  881. X * -D"FASCIST" if you really want to strictly enforce ALL the
  882. X * Command Syntax Standard rules (not recommended).
  883. X */
  884. X
  885. X#define GETOPTEOF    (-1)
  886. X#define ERR(S, C)    shellf("%s%c\n", (S), (C))
  887. X
  888. Xstatic    int    optind;
  889. Xstatic char    *optarg;
  890. Xstatic int    sp;
  891. X
  892. Xstatic int
  893. Xgetopt(argc, argv, opts)
  894. X    int argc;
  895. X    register char **argv, *opts;
  896. X{
  897. X    register int c;
  898. X    register char *cp;
  899. X
  900. X    if (sp == 1)
  901. X        if (optind >= argc ||
  902. X           argv[optind][0] != '-' || argv[optind][1] == '\0')
  903. X            return(GETOPTEOF);
  904. X        else if (strcmp(argv[optind], "--") == 0) {
  905. X            optind++;
  906. X            return(GETOPTEOF);
  907. X        }
  908. X    c = argv[optind][sp];
  909. X    if (c == ':' || (cp=strchr(opts, c)) == NULL) {
  910. X        ERR("illegal option -- ", c);
  911. X        if (argv[optind][++sp] == '\0') {
  912. X            optind++;
  913. X            sp = 1;
  914. X        }
  915. X        optarg = NULL;
  916. X        return('?');
  917. X    }
  918. X    if (*++cp == ':') {
  919. X#if FASCIST
  920. X        if (sp != 1) {
  921. X            ERR("option must not be grouped -- ", c );
  922. X            optind++;
  923. X            sp = 1;
  924. X            optarg = NULL;
  925. X            return('?');
  926. X        } else
  927. X#endif
  928. X        if (argv[optind][sp+1] != '\0') {
  929. X#if FASCIST
  930. X            ERR("option must be followed by whitespace -- ", c );
  931. X            optind++;
  932. X            sp = 1;
  933. X            optarg = NULL;
  934. X            return('?');
  935. X#else
  936. X            optarg = &argv[optind++][sp+1];
  937. X#endif
  938. X        } else if (++optind >= argc) {
  939. X            ERR("option requires an argument -- ", c);
  940. X            sp = 1;
  941. X            optarg = NULL;
  942. X            return('?');
  943. X        } else
  944. X            optarg = argv[optind++];
  945. X        sp = 1;
  946. X    } else {
  947. X        if (argv[optind][++sp] == '\0') {
  948. X            sp = 1;
  949. X            optind++;
  950. X        }
  951. X        optarg = NULL;
  952. X    }
  953. X    return(c);
  954. X}
  955. X
  956. X/*
  957. X * The following were created by Arnold Robbins.
  958. X */
  959. X
  960. X/* resetopts --- magic code for when OPTIND is reset to 1 */
  961. X
  962. Xvoid
  963. Xresetopts ()
  964. X{
  965. X    optind = 1;
  966. X    sp = 1;
  967. X}
  968. X
  969. Xint
  970. Xc_getopts(wp)
  971. X    char **wp;
  972. X{
  973. X    int ret;
  974. X    register int argc;
  975. X    char temp[2];
  976. X    char *optstr;            /* list of options */
  977. X    char *name;            /* variable to get flag val */
  978. X
  979. X    if ((optstr = *++wp) == NULL || (name = *++wp) == NULL)
  980. X        errorf("missing arguments\n");
  981. X
  982. X    for (argc = 1; wp[argc] != NULL; argc++)
  983. X        ;
  984. X
  985. X    if (argc > 1)
  986. X        ret = getopt(argc, wp, optstr);
  987. X    else
  988. X        ret = getopt(e.loc->argc+1, e.loc->argv, optstr);
  989. X
  990. X    /*
  991. X     * set the OPTIND variable in any case, to handle "--" skipping
  992. X     */
  993. X
  994. X    setint(global("OPTIND"), (long)optind);
  995. X
  996. X    if (ret == GETOPTEOF)        /* end of args */
  997. X        return (1);
  998. X
  999. X    /*
  1000. X     * else, got an arg, set the various shell variables
  1001. X     */
  1002. X
  1003. X    if (optarg != NULL)
  1004. X        setstr(global("OPTARG"), optarg);
  1005. X
  1006. X    temp[0] = (char) ret;
  1007. X    temp[1] = '\0';
  1008. X    setstr(global(name), temp);
  1009. X
  1010. X    return (0);
  1011. X}
  1012. X
  1013. SHAR_EOF
  1014. true || echo 'restore of src/getopts.c failed'
  1015. fi
  1016. # ============= src/ulimit.c ==============
  1017. if test -f 'src/ulimit.c' -a X"$1" != X"-c"; then
  1018.     echo 'x - skipping src/ulimit.c (File already exists)'
  1019. else
  1020. echo 'x - extracting src/ulimit.c (Text)'
  1021. sed 's/^X//' << 'SHAR_EOF' > 'src/ulimit.c' &&
  1022. X/*
  1023. X    ulimit -- handle "ulimit" builtin
  1024. X
  1025. X    Eric Gisin, September 1988
  1026. X    Adapted to PD KornShell. Removed AT&T code.
  1027. X
  1028. X    last edit:    06-Jun-1987    D A Gwyn
  1029. X
  1030. X    This started out as the BRL UNIX System V system call emulation
  1031. X    for 4.nBSD, and was later extended by Doug Kingston to handle
  1032. X    the extended 4.nBSD resource limits.  It now includes the code
  1033. X    that was originally under case SYSULIMIT in source file "xec.c".
  1034. X*/
  1035. X
  1036. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/ulimit.c,v 3.1 88/11/03 09:18:11 egisin Exp $";
  1037. X
  1038. X#include <stddef.h>
  1039. X#include <errno.h>
  1040. X#include <signal.h>
  1041. X#include <setjmp.h>
  1042. X#if defined(_BSD) || defined(_BSD_SYSV)
  1043. X#include <sys/time.h>
  1044. X#include <sys/resource.h>
  1045. X#else
  1046. X#define    RLIMIT_FSIZE    2
  1047. X#endif
  1048. X#include "sh.h"
  1049. X
  1050. Xextern    long ulimit();
  1051. X
  1052. Xint
  1053. Xdo_ulimit(a1, a2)
  1054. X    char    *a1, *a2;
  1055. X{
  1056. X    register int    c;
  1057. X    long        i;
  1058. X#if defined(_BSD) || defined(_BSD_SYSV)
  1059. X    struct rlimit    limit;        /* data being gotten/set */
  1060. X    int        softonly = 0;    /* set => soft limit, clear => hard limit */
  1061. X    int        factor = 1024;    /* unit scaling (1K or 1) */
  1062. X#endif
  1063. X    int    command = RLIMIT_FSIZE;
  1064. X
  1065. X    if (a1 && (*a1 == '-'))        /* DAG -- Gould added first test */
  1066. X    {    c = *++a1;        /* DAG */
  1067. X#if defined(_BSD) || defined(_BSD_SYSV)
  1068. X        if (c >= 'A' && c <= 'Z')
  1069. X        {
  1070. X            ++softonly;
  1071. X            c += 'a' - 'A';    /* DAG -- map to lower-case */
  1072. X        }
  1073. X#endif
  1074. X        switch(c)
  1075. X        {
  1076. X#if defined(_BSD) || defined(_BSD_SYSV)
  1077. X            case 'c':
  1078. X                command = RLIMIT_CORE;
  1079. X                break;
  1080. X            case 'd':
  1081. X                command = RLIMIT_DATA;
  1082. X                break;
  1083. X            case 'm':
  1084. X                command = RLIMIT_RSS;
  1085. X                break;
  1086. X            case 's':
  1087. X                command = RLIMIT_STACK;
  1088. X                break;
  1089. X            case 't':
  1090. X                factor = 1;
  1091. X                command = RLIMIT_CPU;
  1092. X                break;
  1093. X#endif    /* _BSD || _BSD_SYSV */
  1094. X            case 'f':
  1095. X                command = RLIMIT_FSIZE;
  1096. X#if _BSD_SYSV
  1097. X                factor = 512;
  1098. X#endif
  1099. X                break;
  1100. X            default:
  1101. X#if _BSD
  1102. X                errorf("Usage: %s [-cdmstf] [limit]\n", "ulimit");
  1103. X#else
  1104. X                errorf("Usage: %s [-f] [limit]\n", "ulimit");
  1105. X#endif
  1106. X        }
  1107. X        a1 = a2;
  1108. X    }
  1109. X    if (a1)
  1110. X    {
  1111. X        i = 0;
  1112. X        while ((c = *a1++) >= '0' && c <= '9')
  1113. X        {
  1114. X            i = (i * 10) + (long)(c - '0');
  1115. X            if (i < 0)
  1116. X                goto Error;
  1117. X        }
  1118. X        if (c || i < 0)
  1119. X            goto Error;
  1120. X    }
  1121. X#if !(defined(_BSD) || defined(_BSD_SYSV))
  1122. X    else
  1123. X    {
  1124. X        i = -1;
  1125. X        command--;
  1126. X    }
  1127. X
  1128. X    if ((i = ulimit(command, i)) < 0L)
  1129. X        goto Error;
  1130. X
  1131. X    if (command != RLIMIT_FSIZE)
  1132. X        shellf("%ld\n", i);
  1133. X#else                    /* DPK -- generalized for 4.nBSD: */
  1134. X    if (getrlimit(command, &limit))
  1135. X        goto Error;    /* errno is already set */
  1136. X
  1137. X    if (a1)
  1138. X    {
  1139. X        limit.rlim_cur = i * factor;
  1140. X
  1141. X        if (!softonly)
  1142. X            limit.rlim_max = limit.rlim_cur;
  1143. X
  1144. X        if (setrlimit(command, &limit))
  1145. X            goto Error;
  1146. X    }
  1147. X    else
  1148. X    {
  1149. X        i = softonly ? limit.rlim_cur : limit.rlim_max;
  1150. X#if _BSD            /* DAG -- System V always prints an integer */
  1151. X        if (i == RLIM_INFINITY)
  1152. X            shellf("unlimited\n");
  1153. X        else
  1154. X#endif
  1155. X            shellf("%ld\n", i/factor);
  1156. X    }
  1157. X#endif    /* _BSD || _BSD_SYSV */
  1158. X    return 0;
  1159. X
  1160. X  Error:
  1161. X    errorf("bad ulimit\n");
  1162. X}
  1163. X
  1164. SHAR_EOF
  1165. true || echo 'restore of src/ulimit.c failed'
  1166. fi
  1167. # ============= src/var.c ==============
  1168. if test -f 'src/var.c' -a X"$1" != X"-c"; then
  1169.     echo 'x - skipping src/var.c (File already exists)'
  1170. else
  1171. echo 'x - extracting src/var.c (Text)'
  1172. sed 's/^X//' << 'SHAR_EOF' > 'src/var.c' &&
  1173. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/var.c,v 3.1 88/11/03 09:18:22 egisin Exp $";
  1174. X
  1175. X#include <stddef.h>
  1176. X#include <string.h>
  1177. X#include <errno.h>
  1178. X#include <setjmp.h>
  1179. X#include <time.h>
  1180. X#include "sh.h"
  1181. X#include "table.h"
  1182. X#include "expand.h"
  1183. X
  1184. X/*
  1185. X * Variables
  1186. X *
  1187. X * WARNING: unreadable code, needs a rewrite
  1188. X *
  1189. X * if (flag&INTEGER), val.i contains integer value, and type contains base.
  1190. X * otherwise, (val.s + type) contains string value.
  1191. X * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting.
  1192. X */
  1193. Xchar    null []    = "";
  1194. Xstatic    struct tbl vtemp;
  1195. Xstatic    void getspec(), setspec();
  1196. Xstatic    void export ARGS((struct tbl *, char *val));
  1197. Xstatic    int special ARGS ((char *name));
  1198. X
  1199. X/*
  1200. X * create a new block for function calls and simple commands
  1201. X * assume caller has allocated and set up e.loc
  1202. X */
  1203. Xvoid
  1204. Xnewblock()
  1205. X{
  1206. X    register struct block *l = e.loc;
  1207. X    static char *empty[] = {""};
  1208. X
  1209. X    ainit(&l->area);
  1210. X    l->argc = 0;
  1211. X    l->argv = empty;
  1212. X    l->exit = l->error = NULL;
  1213. X    tinit(&l->vars, &l->area);
  1214. X    tinit(&l->funs, &l->area);
  1215. X}
  1216. X
  1217. X/*
  1218. X * pop a block handling special variables
  1219. X */
  1220. Xvoid
  1221. Xpopblock()
  1222. X{
  1223. X    register struct block *l = e.loc;
  1224. X    register struct tbl *vp, **vpp = l->vars.tbls;
  1225. X    register int i;
  1226. X
  1227. X    e.loc = l->next;    /* pop block */
  1228. X    for (i = l->vars.size; --i >= 0; )
  1229. X        if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL))
  1230. X            setspec(global(vp->name));
  1231. X    afreeall(&l->area);
  1232. X}
  1233. X
  1234. X/*
  1235. X * Search for variable, if not found create globally.
  1236. X */
  1237. Xstruct tbl *
  1238. Xglobal(n)
  1239. X    register char *n;
  1240. X{
  1241. X    register struct block *l = e.loc;
  1242. X    register struct tbl *vp;
  1243. X    register int c;
  1244. X    unsigned h = hash(n);
  1245. X
  1246. X    c = n[0];
  1247. X    if (digit(c)) {
  1248. X        vp = &vtemp;
  1249. X        lastarea = ATEMP;
  1250. X        vp->flag = (DEFINED|RDONLY);
  1251. X        vp->type = 0;
  1252. X        *vp->name = c;    /* should strncpy */
  1253. X        for (c = 0; digit(*n) && c < 1000; n++)
  1254. X            c = c*10 + *n-'0';
  1255. X        if (c <= l->argc)
  1256. X            setstr(vp, l->argv[c]);
  1257. X        return vp;
  1258. X    } else
  1259. X    if (!letter(c)) {
  1260. X        vp = &vtemp;
  1261. X        lastarea = ATEMP;
  1262. X        vp->flag = (DEFINED|RDONLY);
  1263. X        vp->type = 0;
  1264. X        *vp->name = c;
  1265. X        if (n[1] != '\0')
  1266. X            return vp;
  1267. X        vp->flag |= ISSET|INTEGER;
  1268. X        switch (c) {
  1269. X          case '$':
  1270. X            vp->val.i = getpid();
  1271. X            break;
  1272. X          case '!':
  1273. X            vp->val.i = async;
  1274. X            break;
  1275. X          case '?':
  1276. X            vp->val.i = exstat;
  1277. X            break;
  1278. X          case '#':
  1279. X            vp->val.i = l->argc;
  1280. X            break;
  1281. X          case '-':
  1282. X            vp->flag &= ~ INTEGER;
  1283. X            vp->val.s = getoptions();
  1284. X            break;
  1285. X          default:
  1286. X            vp->flag &= ~(ISSET|INTEGER);
  1287. X        }
  1288. X        return vp;
  1289. X    }
  1290. X    for (l = e.loc; l != NULL; l = l->next) {
  1291. X        vp = tsearch(&l->vars, n, h);
  1292. X        lastarea = &l->area;
  1293. X        if (vp != NULL)
  1294. X            return vp;
  1295. X        if (l->next == NULL)
  1296. X            break;
  1297. X    }
  1298. X    vp = tenter(&l->vars, n, h);
  1299. X    vp->flag |= DEFINED;
  1300. X    if (special(n))
  1301. X        vp->flag |= SPECIAL;
  1302. X    return vp;
  1303. X}
  1304. X
  1305. X/*
  1306. X * Search for local variable, if not found create locally.
  1307. X */
  1308. Xstruct tbl *
  1309. Xlocal(n)
  1310. X    register char *n;
  1311. X{
  1312. X    register struct block *l = e.loc;
  1313. X    register struct tbl *vp;
  1314. X    unsigned h = hash(n);
  1315. X
  1316. X    if (!letter(*n)) {
  1317. X        vp = &vtemp;
  1318. X        lastarea = ATEMP;
  1319. X        vp->flag = (DEFINED|RDONLY);
  1320. X        vp->type = 0;
  1321. X        return vp;
  1322. X    }
  1323. X    vp = tenter(&l->vars, n, h);
  1324. X    lastarea = &l->area;
  1325. X    vp->flag |= DEFINED;
  1326. X    if (special(n))
  1327. X        vp->flag |= SPECIAL;
  1328. X    return vp;
  1329. X}
  1330. X
  1331. X/* get variable string value */
  1332. Xchar *
  1333. Xstrval(vp)
  1334. X    register struct tbl *vp;
  1335. X{
  1336. X    register char *s;
  1337. X    static char strbuf[40];
  1338. X
  1339. X    if ((vp->flag&SPECIAL))
  1340. X        getspec(vp);
  1341. X    if (!(vp->flag&ISSET))
  1342. X        return null;    /* special to dollar() */
  1343. X    if (!(vp->flag&INTEGER))    /* string source */
  1344. X        s = vp->val.s + vp->type;
  1345. X    else {                /* integer source */
  1346. X        register unsigned long n;
  1347. X        register int base;
  1348. X
  1349. X        s = strbuf + sizeof(strbuf);
  1350. X        n = (vp->val.i < 0) ? -vp->val.i : vp->val.i;
  1351. X        base = (vp->type == 0) ? 10 : vp->type;
  1352. X
  1353. X        *--s = '\0';
  1354. X        do {
  1355. X            *--s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[n%base];
  1356. X            n /= base;
  1357. X        } while (n != 0);
  1358. X        /* todo: should we output base# ? */
  1359. X        if (vp->val.i < 0)
  1360. X            *--s = '-';
  1361. X    }
  1362. X    return s;
  1363. X}
  1364. X
  1365. X/* get variable integer value */
  1366. Xlong
  1367. Xintval(vp)
  1368. X    register struct tbl *vp;
  1369. X{
  1370. X    register struct tbl *vq;
  1371. X
  1372. X    if ((vp->flag&SPECIAL))
  1373. X        getspec(vp);
  1374. X    if ((vp->flag&INTEGER))
  1375. X        return vp->val.i;
  1376. X    vq = &vtemp;
  1377. X    vq->flag = (INTEGER);
  1378. X    vq->type = 0;
  1379. X    strint(vq, vp);
  1380. X    return vq->val.i;
  1381. X}
  1382. X
  1383. X/* set variable to string value */
  1384. Xvoid
  1385. Xsetstr(vq, s)
  1386. X    register struct tbl *vq;
  1387. X    char *s;
  1388. X{
  1389. X    if (!(vq->flag&INTEGER)) { /* string dest */
  1390. X        if ((vq->flag&ALLOC))
  1391. X            afree((Void*)vq->val.s, lastarea);
  1392. X        vq->flag &= ~ (ISSET|ALLOC);
  1393. X        vq->type = 0;
  1394. X        if ((vq->flag&EXPORT))
  1395. X            export(vq, s);
  1396. X        else
  1397. X            vq->val.s = strsave(s, lastarea);
  1398. X        vq->flag |= ALLOC;
  1399. X    } else {        /* integer dest */
  1400. X        register struct tbl *vp = &vtemp;    
  1401. X        vp->flag = (DEFINED|ISSET);
  1402. X        vp->type = 0;
  1403. X        vp->val.s = s;
  1404. X        strint(vq, vp);
  1405. X    }
  1406. X    vq->flag |= ISSET;
  1407. X    if ((vq->flag&SPECIAL))
  1408. X        setspec(vq);
  1409. X}
  1410. X    
  1411. X/* convert variable to integer variable */
  1412. Xstruct tbl *
  1413. Xstrint(vq, vp)
  1414. X    register struct tbl *vq, *vp;
  1415. X{
  1416. X    register char *s = vp->val.s + vp->type;
  1417. X    register int c;
  1418. X    int base, neg = 0;
  1419. X    
  1420. X    vq->flag |= INTEGER;
  1421. X    if ((vp->flag&INTEGER)) {
  1422. X        vq->val.i = vp->val.i;
  1423. X        return vq;
  1424. X    }
  1425. X    vq->val.i = 0;
  1426. X    base = 10;
  1427. X    for (c = *s++; c ; c = *s++)
  1428. X        if (c == '-') {
  1429. X            neg++;
  1430. X        } else if (c == '#') {
  1431. X            base = vq->type = vq->val.i;
  1432. X            vq->val.i = 0;
  1433. X        } else if (letnum(c)) {
  1434. X            if ('0' <= c && c <= '9')
  1435. X                c -= '0';
  1436. X            else if ('a' <= c && c <= 'z') /* fuck EBCDIC */
  1437. X                c -= 'a'-10;
  1438. X            else if ('A' <= c && c <= 'Z')
  1439. X                c -= 'A'-10;
  1440. X            vq->val.i = (vq->val.i*base) + c;
  1441. X        } else
  1442. X            break;
  1443. X    if (neg)
  1444. X        vq->val.i = -vq->val.i;
  1445. X    if (vq->type < 2 || vq->type > 36)
  1446. X        vq->type = 0;    /* default base (10) */
  1447. X    return vq;
  1448. X}
  1449. X
  1450. X/* set variable to integer */
  1451. Xvoid
  1452. Xsetint(vq, n)
  1453. X    register struct tbl *vq;
  1454. X    long n;
  1455. X{
  1456. X    if (!(vq->flag&INTEGER)) {
  1457. X        register struct tbl *vp = &vtemp;
  1458. X        vp->flag = (ISSET|INTEGER);
  1459. X        vp->type = 0;
  1460. X        vp->val.i = n;
  1461. X        setstr(vq, strval(vp));    /* ? */
  1462. X    } else
  1463. X        vq->val.i = n;
  1464. X    vq->flag |= ISSET;
  1465. X    if ((vq->flag&SPECIAL))
  1466. X        setspec(vq);
  1467. X}
  1468. X
  1469. X/* set variable from enviroment */
  1470. Ximport(thing)
  1471. X    char *thing;
  1472. X{
  1473. X    register struct tbl *vp;
  1474. X    register char *val;
  1475. X
  1476. X    val = strchr(thing, '=');
  1477. X    if (val == NULL)
  1478. X        return 0;
  1479. X    *val = '\0';
  1480. X    vp = local(thing);
  1481. X    *val++ = '=';
  1482. X    vp->flag |= DEFINED|ISSET|EXPORT;
  1483. X    vp->val.s = thing;
  1484. X    vp->type = val - thing;
  1485. X    if ((vp->flag&SPECIAL))
  1486. X        setspec(vp);
  1487. X    return 1;
  1488. X}
  1489. X
  1490. X/*
  1491. X * make vp->val.s be "name=value" for quick exporting.
  1492. X */
  1493. Xstatic void
  1494. Xexport(vp, val)
  1495. X    register struct tbl *vp;
  1496. X    char *val;
  1497. X{
  1498. X    register char *cp, *xp;
  1499. X    char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
  1500. X
  1501. X    xp = (char*)alloc(strlen(vp->name) + strlen(val) + 2, lastarea);
  1502. X    vp->flag |= ALLOC;
  1503. X    vp->val.s = xp;
  1504. X    for (cp = vp->name; (*xp = *cp++) != '\0'; xp++)
  1505. X        ;
  1506. X    *xp++ = '=';
  1507. X    vp->type = xp - vp->val.s; /* offset to value */
  1508. X    for (cp = val; (*xp++ = *cp++) != '\0'; )
  1509. X        ;
  1510. X    if (op != NULL)
  1511. X        afree((Void*)op, lastarea);
  1512. X}
  1513. X
  1514. X/*
  1515. X * lookup variable (according to (set&LOCAL)),
  1516. X * set its attributes (INTEGER, RDONLY, EXPORT, TRACE),
  1517. X * and optionally set its value if an assignment.
  1518. X */
  1519. Xstruct tbl *
  1520. Xtypeset(var, set, clr)
  1521. X    register char *var;
  1522. X    int clr, set;
  1523. X{
  1524. X    register struct tbl *vp;
  1525. X    register char *val;
  1526. X
  1527. X    /* check for valid variable name, search for value */
  1528. X    val = var;
  1529. X    if (!letter(*val))
  1530. X        return NULL;
  1531. X    for (val++; *val != '\0'; val++)
  1532. X        if (*val == '=')
  1533. X            break;
  1534. X        else if (letnum(*val))
  1535. X            ;
  1536. X        else
  1537. X            return NULL;
  1538. X    if (*val == '=')
  1539. X        *val = '\0';
  1540. X    else
  1541. X        val = NULL;
  1542. X    vp = (set&LOCAL) ? local(var) : global(var);
  1543. X    set &= ~ LOCAL;
  1544. X    if (val != NULL)
  1545. X        *val++ = '=';
  1546. X
  1547. X    if (!(vp->flag&ISSET))
  1548. X        vp->flag = vp->flag & ~clr | set;
  1549. X    else
  1550. X        if (!(vp->flag&INTEGER) && (set&INTEGER)) {
  1551. X        /* string to integer */
  1552. X        vtemp.flag = (ISSET);
  1553. X        vtemp.type = 0;
  1554. X        vtemp.val.s = vp->val.s + vp->type;
  1555. X        if ((vp->flag&ALLOC))
  1556. X            afree((Void*)vp->val.s, lastarea); /* dangerous, used later */
  1557. X        vp->flag &= ~ ALLOC;
  1558. X        vp->flag |= INTEGER;
  1559. X        vp->type = 0;
  1560. X        strint(vp, &vtemp);
  1561. X        } else
  1562. X        if ((clr&INTEGER) && (vp->flag&INTEGER)) {
  1563. X        /* integer to string */
  1564. X        vtemp.val.s = strval(vp);
  1565. X        vp->flag &= ~ INTEGER;
  1566. X        setstr(vp, vtemp.val.s);
  1567. X        }
  1568. X
  1569. X    vp->flag = vp->flag & ~clr | set;
  1570. X
  1571. X    if (val != NULL) {
  1572. X        if ((vp->flag&RDONLY))
  1573. X            errorf("cannot set readonly %s\n", var);
  1574. X        if ((vp->flag&INTEGER))
  1575. X            /* setstr should be able to handle this */
  1576. X            (void)evaluate(var);
  1577. X        else
  1578. X            setstr(vp, val);
  1579. X    }
  1580. X
  1581. X    if ((vp->flag&EXPORT) && !(vp->flag&INTEGER) && vp->type == 0)
  1582. X        export(vp, (vp->flag&ISSET) ? vp->val.s : null);
  1583. X
  1584. X    return vp;
  1585. X}
  1586. X
  1587. Xvoid
  1588. Xunset(vp)
  1589. X    register struct tbl *vp;
  1590. X{
  1591. X    if ((vp->flag&ALLOC))
  1592. X        afree((Void*)vp->val.s, lastarea);
  1593. X    vp->flag &= ~ (ALLOC|ISSET);
  1594. X}
  1595. X
  1596. Xint
  1597. Xisassign(s)
  1598. X    register char *s;
  1599. X{
  1600. X    if (!letter(*s))
  1601. X        return (0);
  1602. X    for (s++; *s != '='; s++)
  1603. X        if (*s == 0 || !letnum(*s))
  1604. X            return (0);
  1605. X    return (1);
  1606. X}
  1607. X
  1608. X/*
  1609. X * Make the exported environment from the exported names in the dictionary.
  1610. X */
  1611. Xchar **
  1612. Xmakenv()
  1613. X{
  1614. X    struct block *l = e.loc;
  1615. X    XPtrV env;
  1616. X    register struct tbl *vp, **vpp;
  1617. X    register int i;
  1618. X
  1619. X    XPinit(env, 64);
  1620. X    for (l = e.loc; l != NULL; l = l->next)
  1621. X        for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; )
  1622. X            if ((vp = *vpp++) != NULL
  1623. X                && (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) {
  1624. X                register struct block *l2;
  1625. X                register struct tbl *vp2;
  1626. X                unsigned h = hash(vp->name);
  1627. X
  1628. X                lastarea = &l->area;
  1629. X
  1630. X                /* unexport any redefined instances */
  1631. X                for (l2 = l->next; l2 != NULL; l2 = l2->next) {
  1632. X                    vp2 = tsearch(&l2->vars, vp->name, h);
  1633. X                    if (vp2 != NULL)
  1634. X                        vp2->flag &= ~ EXPORT;
  1635. X                }
  1636. X                if ((vp->flag&INTEGER)) {
  1637. X                    /* integer to string */
  1638. X                    char *val;
  1639. X                    val = strval(vp);
  1640. X                    vp->flag &= ~ INTEGER;
  1641. X                    setstr(vp, val);
  1642. X                }
  1643. X                XPput(env, vp->val.s);
  1644. X            }
  1645. X    XPput(env, NULL);
  1646. X    return (char **) XPclose(env);
  1647. X}
  1648. X
  1649. X/*
  1650. X * handle special variables with side effects - PATH, SECONDS.
  1651. X */
  1652. X
  1653. Xstatic int
  1654. Xspecial(name)
  1655. X    register char * name;
  1656. X{
  1657. X    if (strcmp("PATH", name) == 0)
  1658. X        return V_PATH;
  1659. X    if (strcmp("IFS", name) == 0)
  1660. X        return V_IFS;
  1661. X    if (strcmp("SECONDS", name) == 0)
  1662. X        return V_SECONDS;
  1663. X    if (strcmp("OPTIND", name) == 0)
  1664. X        return V_OPTIND;
  1665. X    return V_NONE;
  1666. X}
  1667. X
  1668. Xextern    time_t time();
  1669. Xstatic    time_t    seconds;        /* time SECONDS last set */
  1670. X
  1671. Xstatic void
  1672. Xgetspec(vp)
  1673. X    register struct tbl *vp;
  1674. X{
  1675. X    switch (special(vp->name)) {
  1676. X    case V_SECONDS:
  1677. X        vp->flag &= ~ SPECIAL;
  1678. X        setint(vp, time((time_t *)0) - seconds);
  1679. X        vp->flag |= SPECIAL;
  1680. X        break;
  1681. X    }
  1682. X}
  1683. X
  1684. Xstatic void
  1685. Xsetspec(vp)
  1686. X    register struct tbl *vp;
  1687. X{
  1688. X    switch (special(vp->name)) {
  1689. X      case V_PATH:
  1690. X        path = strval(vp);
  1691. X        flushcom(1);    /* clear tracked aliases */
  1692. X        break;
  1693. X      case V_IFS:
  1694. X        setctypes(strval(vp), C_IFS);
  1695. X        break;
  1696. X      case V_SECONDS:
  1697. X        seconds = time((time_t *)0);
  1698. X        break;
  1699. X      case V_OPTIND:
  1700. X        if (intval(vp) == 1)
  1701. X            resetopts();
  1702. X        break;
  1703. X    }
  1704. X}
  1705. X
  1706. SHAR_EOF
  1707. true || echo 'restore of src/var.c failed'
  1708. fi
  1709. # ============= src/table.c ==============
  1710. if test -f 'src/table.c' -a X"$1" != X"-c"; then
  1711.     echo 'x - skipping src/table.c (File already exists)'
  1712. else
  1713. echo 'x - extracting src/table.c (Text)'
  1714. sed 's/^X//' << 'SHAR_EOF' > 'src/table.c' &&
  1715. Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/table.c,v 3.1 88/11/03 09:17:53 egisin Exp $";
  1716. X
  1717. X/*
  1718. X * dynamic hashed associative table for commands and variables
  1719. X */
  1720. X
  1721. X#include <stddef.h>
  1722. X#include <errno.h>
  1723. X#include <setjmp.h>
  1724. X#include "sh.h"
  1725. X#include "table.h"
  1726. X
  1727. X#define    INIT_TBLS    8    /* initial table size (power of 2) */
  1728. X
  1729. Xstatic struct tstate {
  1730. X    int left;
  1731. X    struct tbl **next;
  1732. X} tstate;
  1733. X
  1734. Xstatic void texpand();
  1735. X
  1736. Xunsigned int
  1737. Xhash(n)
  1738. X    register char * n;
  1739. X{
  1740. X    register unsigned int h = 0;
  1741. X
  1742. X    while (*n != '\0')
  1743. X        h = 2*h + *n++;
  1744. X    return h * 32821;    /* scatter bits */
  1745. X}
  1746. X
  1747. X#if 0
  1748. Xphash(s) char *s; {
  1749. X    printf("%2d: %s\n", hash(s)%32, s);
  1750. X}
  1751. X#endif
  1752. X
  1753. Xvoid
  1754. Xtinit(tp, ap)
  1755. X    register struct table *tp;
  1756. X    register Area *ap;
  1757. X{
  1758. X    tp->areap = ap;
  1759. X    tp->size = tp->free = 0;
  1760. X    tp->tbls = NULL;
  1761. X}
  1762. X
  1763. Xstatic void
  1764. Xtexpand(tp, nsize)
  1765. X    register struct table *tp;
  1766. X    int nsize;
  1767. X{
  1768. X    register int i;
  1769. X    register struct tbl *tblp, **p;
  1770. X    register struct tbl **ntblp, **otblp = tp->tbls;
  1771. X    int osize = tp->size;
  1772. X
  1773. X    ntblp = alloc(sizeofN(struct tbl *, nsize), tp->areap);
  1774. X    for (i = 0; i < nsize; i++)
  1775. X        ntblp[i] = NULL;
  1776. X    tp->size = nsize;
  1777. X    tp->free = 8*nsize/10;    /* table can get 80% full */
  1778. X    tp->tbls = ntblp;
  1779. X    if (otblp == NULL)
  1780. X        return;
  1781. X    for (i = 0; i < osize; i++)
  1782. X        if ((tblp = otblp[i]) != NULL)
  1783. X            if ((tblp->flag&DEFINED)) {
  1784. X                for (p = &ntblp[hash(tblp->name) & tp->size-1];
  1785. X                     *p != NULL; p--)
  1786. X                    if (p == ntblp) /* wrap */
  1787. X                        p += tp->size;
  1788. X                *p = tblp;
  1789. X                tp->free--;
  1790. X            } else {
  1791. X                afree((Void*)tblp, tp->areap);
  1792. X            }
  1793. X    afree((Void*)otblp, tp->areap);
  1794. X}
  1795. X
  1796. Xstruct tbl *
  1797. Xtsearch(tp, n, h)
  1798. X    register struct table *tp;    /* table */
  1799. X    register char *n;        /* name to enter */
  1800. X    unsigned int h;            /* hash(n) */
  1801. X{
  1802. X    register struct tbl **pp, *p;
  1803. X
  1804. X    if (tp->size == 0)
  1805. X        return NULL;
  1806. X
  1807. X    /* search for name in hashed table */
  1808. X    for (pp = &tp->tbls[h & tp->size-1]; (p = *pp) != NULL; pp--) {
  1809. X        if (*p->name == *n && strcmp(p->name, n) == 0
  1810. X            && (p->flag&DEFINED))
  1811. X            return p;
  1812. X        if (pp == tp->tbls) /* wrap */
  1813. X            pp += tp->size;
  1814. X    }
  1815. X
  1816. X    return NULL;
  1817. X}
  1818. X
  1819. Xstruct tbl *
  1820. Xtenter(tp, n, h)
  1821. X    register struct table *tp;    /* table */
  1822. X    register char *n;        /* name to enter */
  1823. X    unsigned int h;            /* hash(n) */
  1824. X{
  1825. X    register struct tbl **pp, *p;
  1826. X    register char *cp;
  1827. X
  1828. X    if (tp->size == 0)
  1829. X        texpand(tp, INIT_TBLS);
  1830. X  Search:
  1831. X    /* search for name in hashed table */
  1832. X    for (pp = &tp->tbls[h & tp->size-1]; (p = *pp) != NULL; pp--) {
  1833. X        if (*p->name == *n && strcmp(p->name, n) == 0)
  1834. X            return p;     /* found */
  1835. X        if (pp == tp->tbls) /* wrap */
  1836. X            pp += tp->size;
  1837. X    }
  1838. X
  1839. X    if (tp->free <= 0) {    /* too full */
  1840. X        texpand(tp, 2*tp->size);
  1841. X        goto Search;
  1842. X    }
  1843. X
  1844. X    /* create new tbl entry */
  1845. X    for (cp = n; *cp != '\0'; cp++)
  1846. X        ;
  1847. X    p = (struct tbl *) alloc(offsetof(struct tbl, name[(cp-n)+1]), tp->areap);
  1848. X    p->flag = 0;
  1849. X    p->type = 0;
  1850. X    for (cp = p->name; *n != '\0';)
  1851. X        *cp++ = *n++;
  1852. X    *cp = '\0';
  1853. X
  1854. X    /* enter in tp->tbls */
  1855. X    tp->free--;
  1856. X    *pp = p;
  1857. X    return p;
  1858. X}
  1859. X
  1860. Xvoid
  1861. Xtdelete(p)
  1862. X    register struct tbl *p;
  1863. X{
  1864. X    p->flag = 0;
  1865. X}
  1866. X
  1867. Xvoid
  1868. Xtwalk(tp)
  1869. X    register struct table *tp;
  1870. X{
  1871. X    tstate.left = tp->size;
  1872. X    tstate.next = tp->tbls;
  1873. X}
  1874. X
  1875. Xstruct tbl *
  1876. Xtnext()
  1877. X{
  1878. X    while (--tstate.left >= 0) {
  1879. X        struct tbl *p = *tstate.next++;
  1880. X        if (p != NULL && (p->flag&DEFINED))
  1881. X            return p;
  1882. X    }
  1883. X    return NULL;
  1884. X}
  1885. X
  1886. Xstatic int
  1887. Xtnamecmp(p1, p2)
  1888. X    Void *p1, *p2;
  1889. X{
  1890. X    return strcmp(((struct tbl *)p1)->name, ((struct tbl *)p2)->name);
  1891. X}
  1892. X
  1893. Xstruct tbl **
  1894. Xtsort(tp)
  1895. X    register struct table *tp;
  1896. X{
  1897. X    register int i;
  1898. X    register struct tbl **p, **sp, **dp;
  1899. X
  1900. X    p = (struct tbl **)alloc(sizeofN(struct tbl *, tp->size+1), ATEMP);
  1901. X    sp = tp->tbls;        /* source */
  1902. X    dp = p;            /* dest */
  1903. X    for (i = 0; i < tp->size; i++)
  1904. X        if ((*dp = *sp++) != NULL && ((*dp)->flag&DEFINED))
  1905. X            dp++;
  1906. X    i = dp - p;
  1907. X    qsortp((Void**)p, (size_t)i, tnamecmp);
  1908. X    p[i] = NULL;
  1909. X    return p;
  1910. X}
  1911. X
  1912. SHAR_EOF
  1913. true || echo 'restore of src/table.c failed'
  1914. fi
  1915. true || echo 'restore of src/eval.c failed'
  1916. echo End of part 5, continue with part 6
  1917. exit 0
  1918.