home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume25 / pdksh / part06 < prev    next >
Encoding:
Text File  |  1991-11-12  |  54.6 KB  |  2,377 lines

  1. Newsgroups: comp.sources.misc
  2. From: sjg@zen.void.oz.au (Simon J. Gerraty)
  3. Subject:  v25i052:  pdksh - Public Domain Korn Shell, v4, Part06/09
  4. Message-ID: <1991Nov13.031201.16173@sparky.imd.sterling.com>
  5. X-Md4-Signature: cc2e0220e22181fc52021675471393dc
  6. Date: Wed, 13 Nov 1991 03:12:01 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 52
  11. Archive-name: pdksh/part06
  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:  ReadMe.jrm sh/ChangeLog sh/alloc.c sh/expr.c sh/mail.c
  20. #   sh/misc.c sh/sh.h sh/table.c sh/ulimit.c std/stdc/vprintf.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 6 (of 9)."'
  25. if test -f 'ReadMe.jrm' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'ReadMe.jrm'\"
  27. else
  28.   echo shar: Extracting \"'ReadMe.jrm'\" \(4951 characters\)
  29.   sed "s/^X//" >'ReadMe.jrm' <<'END_OF_FILE'
  30. XBUILDING THE PD KSH
  31. X===================
  32. X
  33. XAs usual, there are differences between BSD and System V
  34. Xversions.  Ideally, all you have to do is edit the Makefile in
  35. Xthis directory to set the CONFIG macro to the appropriate value.
  36. X(Actually, you may wish to change the CONFIG macro in all
  37. XMakefiles; if you always invoke make(1) from here, CONFIG will
  38. Xbe passed down, but if you invoke make(1) from a subdirectory
  39. Xyou'll want the appropriate definition in that Makefile.)
  40. X
  41. XOf course it's not quite that simple.  You may, however, take
  42. Xsolace in the knowledge that it used to be worse.
  43. X
  44. XThe Compatibility Libraries
  45. X---------------------------
  46. X
  47. XEric Gisin wrote this shell using ANSI C and POSIX as
  48. Xportability guidlines.  Realizing that nobody had a POSIX
  49. Xsystem and almost no one had an ANSI C environment, he provided
  50. Xminimal compatibility libraries.
  51. X
  52. XThere are two libraries, one for POSIX (libposix.a) and one for
  53. XANSI C (libstdc.a).
  54. X
  55. XLibposix.a is pretty simple.  Nothing in it has ever broken on
  56. Xme, so I'd just leave it.  It provides a version of dup2() for
  57. XSystem V systems.
  58. X
  59. XLibstdc.a is a bit hairy.  I recommend looking at the routines
  60. Xprovided and, and editing the std/stdc Makefile and only
  61. Xincluding objects that have routines your system libc.a is
  62. Xlacking.  Various of the provided routines are just plain
  63. Xflaky, but only when they're not really needed.  The other
  64. Xhairy thing he does is craft an ANSI stdio.h from the system
  65. Xsupplied one and one of his own.  Again, it's better than it
  66. Xused to be, but it's still a hack, and you may have to modify
  67. Xit by hand.
  68. X
  69. XYou will also need a POSIX compatible set of directory reading
  70. Xroutines.  System V.3 systems have this in libc.a.  The
  71. Xstd/posix directory provides a something for BSD systems.  I
  72. Xuse a slightly modified version of Doug Gwyn's PD version.
  73. X
  74. X(The ``slightly modified'' is to work around a bug in Gwyn's version.
  75. XThe POSIX routines are documented as returning failure if the file for
  76. Xopendir(3) is not a directory.  Gwyn attempts to open(2) the file, and
  77. Xthen stats it to see if the file is a directory.  However, if the file
  78. Xis a special file, and the open(2) doesn't return, you're screwed.  My
  79. Xchange was to open the file with the O_NDELAY flag, but Gwyn didn't
  80. Xfeel this was portable (true, but I only do it where it works) and
  81. Xthat stat-ing before the open would be too slow (true).  The upshot is
  82. Xif you use his routines unmodified, don't ever do an "ls -l /dev/*/*".)
  83. X
  84. XThe Shell Source
  85. X----------------
  86. X
  87. XThe source for the shell itself is in the sh directory.  There you
  88. Xwill want to edit config.h to determine the configuration options.  Vi
  89. Xmode is in kind of rough shape, but does work.  DIRSTACK routines
  90. Xaren't implemented yet, so again, why bother.  SWTCH is a bit arcane,
  91. Xbut it you use shl(1) and you define EMACS or VI you want to define
  92. Xthis.  JOBS is really only useful on BSD systems.  It might work on
  93. Xsystems that have POSIX job control, but I wouldn't bet on it.
  94. XSHARPBANG is only useful on systems where the exec() family don't
  95. Xhonour the #!/prog/path convention.
  96. X
  97. XThis is where the shell gets built so you may wish to change
  98. Xthe OTHERLIBS macro in the Makefile to point to your POSIX
  99. Xdirectory routines, or to use -lc_s, or whatever.
  100. X
  101. XMiscellaneous
  102. X-------------
  103. X
  104. XThe Makefiles that actually compile things use the macro
  105. XCCOPTS, so you can change it in individual Makefiles or specify
  106. Xit on the command line, eg. "make CCOPTS=-O OTHERLIBS=-lc_s".
  107. XLDOPTS is used in the Makefile where the ksh is actually built.
  108. X
  109. XThe very first time on a new system, do a "make clobber"
  110. X
  111. XGood luck.
  112. X
  113. XDocumentation
  114. X-------------
  115. X
  116. XThe ksh.1 is a man page for the PD ksh, although it lags
  117. Xsomewhat behind the code.  You get what you pay for.
  118. X
  119. XThe ksh88.1 is a man page for AT&T's ksh88 (the latest version)
  120. Xprovided for comparison.
  121. X
  122. XHistory
  123. X-------
  124. X
  125. XMuch of the shell was written by Eric Gisin at the University
  126. Xof Waterloo, using some pieces of other stuff, notably Charles
  127. XForsythe's V7 shell, and some enhancements from the BRL shell.
  128. XHe placed it (in a alpha test state) into the public domain
  129. Xwhile I was at UW.  I snarfed a copy, and got it running on my
  130. XUNIXpc, and later some machines at work.  I sent Gisin some bug
  131. Xreports, but he seems to have lost interest in the project.
  132. XThis may be because he now does some work for MKS, who produce a
  133. Xcommercial version of the ksh for MS-DOS machines, so there may
  134. Xbe a conflict of interest.
  135. X
  136. XSo I gave up on getting future versions, and adopted it.  I've
  137. Xmade some enhancements, and quite a few bug fixes, and various
  138. Xpeople at work have contributed as well.  It remains in the
  139. Xpublic domain, although I imagine the people involved would
  140. Xappreciate leaving their names attached (I'm exempt; I haven't
  141. Xactually included my name anywhere but here).
  142. X
  143. XThe README in the sh directory is Gisin's, and tells a bit of
  144. Xthe story from his point of view.  Note that his compilation
  145. Xinstructions don't really apply anymore.
  146. X
  147. XJohn R. MacMillan
  148. END_OF_FILE
  149.   if test 4951 -ne `wc -c <'ReadMe.jrm'`; then
  150.     echo shar: \"'ReadMe.jrm'\" unpacked with wrong size!
  151.   fi
  152.   # end of 'ReadMe.jrm'
  153. fi
  154. if test -f 'sh/ChangeLog' -a "${1}" != "-c" ; then 
  155.   echo shar: Will not clobber existing file \"'sh/ChangeLog'\"
  156. else
  157.   echo shar: Extracting \"'sh/ChangeLog'\" \(4281 characters\)
  158.   sed "s/^X//" >'sh/ChangeLog' <<'END_OF_FILE'
  159. XSat Nov  9 14:57:30 1991  Simon J. Gerraty  (sjg at zen)
  160. X
  161. X    * Release version 4.1 as a new base line.
  162. X
  163. XThu Nov  7 23:11:25 1991  Simon J. Gerraty  (sjg at zen)
  164. X
  165. X    * John R MacMillan suppied a fix for a bug in yylex() that was the
  166. X    cause of several odd problems such as:
  167. X        $ foo=echo
  168. X        $ $foo bar
  169. X        bar: not found
  170. X        $ pwd
  171. X        $ /local/src/pdksh
  172. X        $ $foo bar
  173. X        bar
  174. X        $
  175. X
  176. XSun Sep 15 23:19:27 1991  Simon J. Gerraty  (sjg at zen)
  177. X
  178. X    * emacs.c:
  179. X    Added function x_lastcp() which returns a pointer to that char in
  180. X    the edit buffer that will be the last displayed on the screen.
  181. X    Thus:
  182. X
  183. X          cp = x_lastcp();
  184. X      while (cp > xcp)
  185. X            x_bs(*--cp);
  186. X    
  187. X    Will correctly position the cursor on the screen (regardless of
  188. X    TABs etc in the buffer).  The previous method got out of sync if
  189. X    there were any TABs to display.
  190. X
  191. XWed Aug  7 11:26:55 1991  Simon J. Gerraty  (sjg at sun0)
  192. X
  193. X    * jobs.c:
  194. X    The Sun SPARCstation 2 was proving extremely unreliable using ksh.
  195. X    After puting traces in jobs.c, it turns out the problem was
  196. X    multiple SIGCHLD events happening too quickly causing the handler
  197. X    to be interupted and thus not recognise the job that it had just
  198. X    reaped was one of its own.  Having done the waitpid(), but not
  199. X    adjusted the job table entry, j_waitj() would loop forever waiting
  200. X    for a job to finnish (that had already done so!)
  201. X    Solution was to have the SIGCHLD handler simply record the events
  202. X    by inrcrementing sigchld_caught.  The actual reaping is now done
  203. X    in a new funtion j_reapchld(), which does what the old signal
  204. X    handler did but blocks SIGCHLD while scanning the job table.
  205. X    j_waitj() calls j_reapchld() when sigchld_caught is non-zero.
  206. X    The SS2 is now much more reliable...
  207. X
  208. X    * trace.c:
  209. X    Added my simple _TRACE facility (used to track the j_waitj
  210. X    problem).  Simply -DUSE_TRACE for it to have effect.  If USE_TRACE
  211. X    is undefined, calls to _TRACE() expand to while(0) which an
  212. X    optimizer will usually remove.  sh.h now includes trace.h
  213. X
  214. XMon Jun 10 10:27:14 1991  Simon J. Gerraty  (sjg at zen)
  215. X
  216. X    * emacs.c:
  217. X    A couple of assignments (xbp = xbuf) were not migrated from the
  218. X    3.2 version.  Caused an anoying bug when retrieving history
  219. X    commands. 
  220. X
  221. XMon May 27 12:50:20 1991  Simon J. Gerraty  (sjg at sun0)
  222. X
  223. X    * added fixes supplied by Mike Jetzer:
  224. X    These relate mainly to vi mode.  See Changes.mlj
  225. X
  226. X    * c_sh.c c_exit():
  227. X    Modified behavior to not imediately exit if there are stopped
  228. X    jobs.  A subsequent exit will kill any jobs left and terminate the
  229. X    shell. 
  230. X
  231. XFri May 24 15:20:10 1991  Simon J. Gerraty  (sjg at sun0)
  232. X
  233. X    * edit.h:
  234. X    Cleaned up prototypes.  Built shell on sun3.
  235. X    While gcc-1.39 builds the ksh ok on the 386i, on the sun3 jobs
  236. X    don't work correctly - any non-builtin command gets stopped and
  237. X    put into the background.  Had same problem with 3.2, using
  238. X    /usr/bin/cc works fine.
  239. X
  240. XThu May 23 13:45:20 1991  Simon J. Gerraty  (sjg at sun0)
  241. X
  242. X    * migrated my 3.2 edit.c changes to the new shell.
  243. X    Affects edit.c, emacs.c
  244. X    Added edit.h which is now included by edit.c,emacs.c and vi.c
  245. X    
  246. X    * vi.c:
  247. X    Fixed handling of '!' in prompt by using pprompt() as in emacs.c
  248. X
  249. X    * std/stdc/vprintf.c:
  250. X    Fixed bug in output of left '0' padded unsigned numbers was
  251. X    always padding with ' ' which left a space in ksh's temp file
  252. X    names.  This prevented fc -l from working.
  253. X
  254. XHere is my 3.2 ChangeLog:
  255. XFri Mar 22 16:50:14 1991  Simon J. Gerraty  (sjg at sun0)
  256. X
  257. X    * edit.c:
  258. X    Added x_set_arg() and x_prev_histword().
  259. X    x_set_arg() handles 'ESC''0-9' type args which are used by word
  260. X    related commands.
  261. X    x_prev_histword() recovers the last (default) or sepcified arg
  262. X    word from the previous command line.  Bound to ESC. and ESC_ to be
  263. X    compatible with real ksh.
  264. X
  265. XTue Feb 26 14:16:17 1991 Simon J. Gerraty  (sjg at zen)
  266. X
  267. X    * edit.c:
  268. X    Changes to handle editing of command lines longer than $COLUMNS in
  269. X    a manner compatible with real ksh.
  270. X
  271. XMon Feb 25 12:20:36 1991 Simon J. Gerraty  (sjg at sun0)
  272. X
  273. X    * var.c,table.h:
  274. X    Implemented $RANDOM
  275. X    Some scripts use [ "$RANDOM" != "$RANDOM" ] to check for ksh. 
  276. X
  277. XWed Feb 20 12:20:36 1991 Simon J. Gerraty  (sjg at sun0)
  278. X
  279. X    Changes so that shell will compile on sun386i.
  280. X
  281. X    * exec.c,main.c,io.c:
  282. X    Handle the case where FD_CLEXEC isn't defined.
  283. X
  284. X    * jobs.c:
  285. X    SunOS has its own ideas about job status etc.
  286. X
  287. X    * tree.c:
  288. X    Fixed conflict between varargs and stdarg.
  289. X
  290. X
  291. X
  292. X
  293. END_OF_FILE
  294.   if test 4281 -ne `wc -c <'sh/ChangeLog'`; then
  295.     echo shar: \"'sh/ChangeLog'\" unpacked with wrong size!
  296.   fi
  297.   # end of 'sh/ChangeLog'
  298. fi
  299. if test -f 'sh/alloc.c' -a "${1}" != "-c" ; then 
  300.   echo shar: Will not clobber existing file \"'sh/alloc.c'\"
  301. else
  302.   echo shar: Extracting \"'sh/alloc.c'\" \(4744 characters\)
  303.   sed "s/^X//" >'sh/alloc.c' <<'END_OF_FILE'
  304. X/*
  305. X * area-based allocation built on malloc/free
  306. X */
  307. X
  308. Xstatic char *RCSid = "$Id";
  309. X
  310. X#include <stddef.h>
  311. X#include <stdlib.h>
  312. X#include <setjmp.h>
  313. X#include "sh.h"
  314. X
  315. X#define    ICELLS    100        /* number of Cells in small Block */
  316. X
  317. Xtypedef union Cell Cell;
  318. Xtypedef struct Block Block;
  319. X
  320. X/*
  321. X * The Cells in a Block are organized as a set of objects.
  322. X * Each object (pointed to by dp) begins with a size in (dp-1)->size,
  323. X * followed with "size" data Cells.  Free objects are
  324. X * linked together via dp->next.
  325. X */
  326. X
  327. Xunion Cell {
  328. X    size_t    size;
  329. X    Cell   *next;
  330. X    struct {int _;} junk;    /* alignment */
  331. X};
  332. X
  333. Xstruct Block {
  334. X    Block  *next;        /* list of Blocks in Area */
  335. X    Cell   *free;        /* object free list */
  336. X    Cell   *last;        /* &b.cell[size] */
  337. X    Cell    cell [1];    /* [size] Cells for allocation */
  338. X};
  339. X
  340. XBlock aempty = {&aempty, aempty.cell, aempty.cell};
  341. X
  342. X/* create empty Area */
  343. XArea *
  344. Xainit(ap)
  345. X    register Area *ap;
  346. X{
  347. X    ap->free = &aempty;
  348. X    return ap;
  349. X}
  350. X
  351. X/* free all object in Area */
  352. Xvoid
  353. Xafreeall(ap)
  354. X    register Area *ap;
  355. X{
  356. X    register Block *bp;
  357. X
  358. X    if (ap->free == NULL || ap->free == &aempty)
  359. X        return;
  360. X    for (bp = ap->free; ; bp = bp->next) {
  361. X        free((Void*)bp);
  362. X        if (bp->next == ap->free)
  363. X            break;
  364. X    }
  365. X    ap->free = &aempty;
  366. X}
  367. X
  368. X/* allocate object from Area */
  369. XVoid *
  370. Xalloc(size, ap)
  371. X    size_t size;
  372. X    register Area *ap;
  373. X{
  374. X    int cells, split;
  375. X    register Block *bp;
  376. X    register Cell *dp, *fp, *fpp;
  377. X
  378. X    if (size <= 0) {
  379. X        aerror(ap, "allocate bad size");
  380. X        return NULL;
  381. X    }
  382. X    cells = (unsigned)(size - 1) / sizeof(Cell) + 1;
  383. X
  384. X    /* find Cell large enough */
  385. X    for (bp = ap->free; ; bp = bp->next) {
  386. X        for (fpp = NULL, fp = bp->free;
  387. X             fp != bp->last; fpp = fp, fp = fpp->next)
  388. X            if ((fp-1)->size >= cells)
  389. X                goto Found;
  390. X
  391. X        /* wrapped around Block list, create new Block */
  392. X        if (bp->next == ap->free) {
  393. X            bp = (Block*) malloc(offsetof(Block, cell[ICELLS + cells]));
  394. X            if (bp == NULL) {
  395. X                aerror(ap, "cannot allocate");
  396. X                return NULL;
  397. X            }
  398. X            if (ap->free == &aempty)
  399. X                bp->next = bp;
  400. X            else {
  401. X                bp->next = ap->free->next;
  402. X                ap->free->next = bp;
  403. X            }
  404. X            bp->last = bp->cell + ICELLS + cells;
  405. X            fp = bp->free = bp->cell + 1; /* initial free list */
  406. X            (fp-1)->size = ICELLS + cells - 1;
  407. X            fp->next = bp->last;
  408. X            fpp = NULL;
  409. X            break;
  410. X        }
  411. X    }
  412. X  Found:
  413. X    ap->free = bp;
  414. X    dp = fp;        /* allocated object */
  415. X    split = (dp-1)->size - cells;
  416. X    if (split < 0)
  417. X        aerror(ap, "allocated object too small");
  418. X    if (--split <= 0) {    /* allocate all */
  419. X        fp = fp->next;
  420. X    } else {        /* allocate head, free tail */
  421. X        (fp-1)->size = cells;
  422. X        fp += cells + 1;
  423. X        (fp-1)->size = split;
  424. X        fp->next = dp->next;
  425. X    }
  426. X    if (fpp == NULL)
  427. X        bp->free = fp;
  428. X    else
  429. X        fpp->next = fp;
  430. X    return (Void*) dp;
  431. X}
  432. X
  433. X/* change size of object -- like realloc */
  434. XVoid *
  435. Xaresize(ptr, size, ap)
  436. X    register Void *ptr;
  437. X    size_t size;
  438. X    Area *ap;
  439. X{
  440. X    int cells;
  441. X    register Cell *dp = (Cell*) ptr;
  442. X
  443. X    if (size <= 0) {
  444. X        aerror(ap, "allocate bad size");
  445. X        return NULL;
  446. X    }
  447. X    cells = (unsigned)(size - 1) / sizeof(Cell) + 1;
  448. X
  449. X    if (dp == NULL || (dp-1)->size < cells) { /* enlarge object */
  450. X        register Cell *np;
  451. X        register int i;
  452. X        Void *optr = ptr;
  453. X
  454. X        ptr = alloc(size, ap);
  455. X        np = (Cell*) ptr;
  456. X        if (dp != NULL)
  457. X            for (i = (dp-1)->size; i--; )
  458. X                *np++ = *dp++;
  459. X        afree(optr, ap);
  460. X    } else {        /* shrink object */
  461. X        int split;
  462. X
  463. X        split = (dp-1)->size - cells;
  464. X        if (--split <= 0) /* cannot split */
  465. X            ;
  466. X        else {        /* shrink head, free tail */
  467. X            (dp-1)->size = cells;
  468. X            dp += cells + 1;
  469. X            (dp-1)->size = split;
  470. X            afree((Void*)dp, ap);
  471. X        }
  472. X    }
  473. X    return (Void*) ptr;
  474. X}
  475. X
  476. Xvoid
  477. Xafree(ptr, ap)
  478. X    Void *ptr;
  479. X    register Area *ap;
  480. X{
  481. X    register Block *bp;
  482. X    register Cell *fp, *fpp;
  483. X    register Cell *dp = (Cell*)ptr;
  484. X
  485. X    /* find Block containing Cell */
  486. X    for (bp = ap->free; ; bp = bp->next) {
  487. X        if (bp->cell <= dp && dp < bp->last)
  488. X            break;
  489. X        if (bp->next == ap->free) {
  490. X            aerror(ap, "freeing with invalid area");
  491. X            return;
  492. X        }
  493. X    }
  494. X
  495. X    /* find position in free list */
  496. X    for (fpp = NULL, fp = bp->free; fp < dp; fpp = fp, fp = fpp->next)
  497. X        ;
  498. X
  499. X    if (fp == dp) {
  500. X        aerror(ap, "freeing free object");
  501. X        return;
  502. X    }
  503. X
  504. X    /* join object with next */
  505. X    if (dp + (dp-1)->size == fp-1) { /* adjacent */
  506. X        (dp-1)->size += (fp-1)->size + 1;
  507. X        dp->next = fp->next;
  508. X    } else            /* non-adjacent */
  509. X        dp->next = fp;
  510. X
  511. X    /* join previous with object */
  512. X    if (fpp == NULL)
  513. X        bp->free = dp;
  514. X    else if (fpp + (fpp-1)->size == dp-1) { /* adjacent */
  515. X        (fpp-1)->size += (dp-1)->size + 1;
  516. X        fpp->next = dp->next;
  517. X    } else            /* non-adjacent */
  518. X        fpp->next = dp;
  519. X}
  520. X
  521. X
  522. X#if TEST_ALLOC
  523. X
  524. XArea a;
  525. X
  526. Xmain(int argc, char **argv) {
  527. X    int i;
  528. X    char *p [9];
  529. X
  530. X    ainit(&a);
  531. X    for (i = 0; i < 9; i++) {
  532. X        p[i] = alloc(124, &a);
  533. X        printf("alloc: %x\n", p[i]);
  534. X    }
  535. X    for (i = 1; i < argc; i++)
  536. X        afree(p[atoi(argv[i])], &a);
  537. X    afreeall(&a);
  538. X    return 0;
  539. X}
  540. X
  541. Xvoid aerror(Area *ap, const char *msg) {
  542. X    abort();
  543. X}
  544. X
  545. X#endif
  546. X
  547. END_OF_FILE
  548.   if test 4744 -ne `wc -c <'sh/alloc.c'`; then
  549.     echo shar: \"'sh/alloc.c'\" unpacked with wrong size!
  550.   fi
  551.   # end of 'sh/alloc.c'
  552. fi
  553. if test -f 'sh/expr.c' -a "${1}" != "-c" ; then 
  554.   echo shar: Will not clobber existing file \"'sh/expr.c'\"
  555. else
  556.   echo shar: Extracting \"'sh/expr.c'\" \(4590 characters\)
  557.   sed "s/^X//" >'sh/expr.c' <<'END_OF_FILE'
  558. X/*
  559. X * Korn expression evaluation
  560. X */
  561. X
  562. Xstatic char *RCSid = "$Id: expr.c,v 3.2 89/03/27 15:50:20 egisin Exp $";
  563. X
  564. X#include <stddef.h>
  565. X#include <errno.h>
  566. X#include <setjmp.h>
  567. X#include "sh.h"
  568. X#include "table.h"
  569. X
  570. X#define    ef    else if        /* fashion statement */
  571. X
  572. X#define    VAR    0x01
  573. X#define    LIT    0x02
  574. X#define    LEQ    0x03
  575. X#define    LNE    0x04
  576. X#define    LLE    0x05
  577. X#define    LGE    0x06
  578. X
  579. Xstatic void token();        /* read next token */
  580. Xstatic Const char *expression;    /* expression being evaluated */
  581. Xstatic Const char *tokp;    /* lexical position */
  582. Xstatic int tok;            /* token from token() */
  583. Xstatic struct tbl *val;        /* value from token() */
  584. X
  585. Xstatic struct tbl *tempvar(), *intvar();
  586. Xstatic struct tbl *asn(), *e6(), *e5(), *e3(), *e2(), *e0();
  587. X
  588. X/*
  589. X * parse and evalute expression
  590. X */
  591. Xvoid
  592. Xevalerr(err)
  593. X    char *err;
  594. X{
  595. X    errorf("%s: %s\n", expression, err);
  596. X}
  597. X
  598. Xlong
  599. Xevaluate(expr)
  600. X    Const char *expr;
  601. X{
  602. X    struct tbl *v;
  603. X
  604. X    expression = tokp = expr;
  605. X    token();
  606. X    v = intvar(asn());
  607. X    if (!(tok == 0))
  608. X        evalerr("bad expression");
  609. X    return v->val.i;
  610. X}
  611. X
  612. Xstatic struct tbl *
  613. Xasn()
  614. X{
  615. X    register struct tbl *vl, *vr;
  616. X
  617. X    vr = vl = e6();
  618. X    if ((tok == '=')) {
  619. X        Area * olastarea = lastarea;
  620. X        token();
  621. X        if ((vl->flag&RDONLY)) /* assign to rvalue */
  622. X            evalerr("bad assignment");
  623. X        vr = intvar(asn());
  624. X        lastarea = olastarea;
  625. X        setint(vl, vr->val.i);
  626. X        if ((vl->flag&INTEGER) && vl->type == 0) /* default base? */
  627. X            vl->type = vr->type;
  628. X    }
  629. X    return vr;
  630. X}
  631. X
  632. Xstatic struct tbl *
  633. Xe6()
  634. X{
  635. X    register struct tbl *vl, *vr;
  636. X
  637. X    vl = e5();
  638. X    while ((tok == LEQ) || (tok == LNE)) {
  639. X        int op = tok;
  640. X        token();
  641. X        vl = intvar(vl);
  642. X        vr = intvar(e5());
  643. X        vl->val.i = vl->val.i == vr->val.i;
  644. X        if (op == LNE)
  645. X            vl->val.i = ! vl->val.i;
  646. X    }
  647. X    return vl;
  648. X}
  649. X
  650. Xstatic struct tbl *
  651. Xe5()
  652. X{
  653. X    register struct tbl *vl, *vr;
  654. X
  655. X    vl = e3();
  656. X    while ((tok == LLE) || (tok == '<') || (tok == '>') || (tok == LGE)) {
  657. X        int op = tok;
  658. X        token();
  659. X        vl = intvar(vl);
  660. X        vr = intvar(e3());
  661. X        if (op == LLE)
  662. X            vl->val.i = vl->val.i <= vr->val.i;
  663. X        ef (op == '<')
  664. X            vl->val.i = vl->val.i < vr->val.i;
  665. X        ef (op == LGE)
  666. X            vl->val.i = vl->val.i >= vr->val.i;
  667. X        ef (op == '>')
  668. X            vl->val.i = vl->val.i > vr->val.i;
  669. X    }
  670. X    return vl;
  671. X}
  672. X
  673. Xstatic struct tbl *
  674. Xe3()
  675. X{
  676. X    register struct tbl *vl, *vr;
  677. X
  678. X    vl = e2();
  679. X    while ((tok == '+') || (tok == '-')) {
  680. X        int op = tok;
  681. X        token();
  682. X        vl = intvar(vl);
  683. X        vr = intvar(e2());
  684. X        if (op == '+')
  685. X            vl->val.i += vr->val.i;
  686. X        ef (op == '-')
  687. X            vl->val.i -= vr->val.i;
  688. X    }
  689. X    return vl;
  690. X}
  691. X
  692. Xstatic struct tbl *
  693. Xe2()
  694. X{
  695. X    register struct tbl *vl, *vr;
  696. X
  697. X    vl = e0();
  698. X    while ((tok == '*') || (tok == '/') || (tok == '%')) {
  699. X        int op = tok;
  700. X        token();
  701. X        vl = intvar(vl);
  702. X        vr = intvar(e0());
  703. X        if (op != '*' && vr->val.i == 0)
  704. X            evalerr("zero divisor");
  705. X        if (op == '*')
  706. X            vl->val.i *= vr->val.i;
  707. X        ef (op == '/')
  708. X            vl->val.i /= vr->val.i;
  709. X        ef (op == '%')
  710. X            vl->val.i %= vr->val.i;
  711. X    }
  712. X    return vl;
  713. X}
  714. X
  715. Xstatic struct tbl *
  716. Xe0()
  717. X{
  718. X    register struct tbl *v;
  719. X
  720. X    if ((tok == '!') || (tok == '-')) {
  721. X        int op = tok;
  722. X        token();
  723. X        v = intvar(e0());
  724. X        if (op == '!')
  725. X            v->val.i = !v->val.i;
  726. X        ef (op == '-')
  727. X            v->val.i = -v->val.i;
  728. X    } else
  729. X    if ((tok == '(')) {
  730. X        token();
  731. X        v = asn();
  732. X        if (!(tok == ')'))
  733. X            evalerr("missing )");
  734. X        token();
  735. X    } else
  736. X    if ((tok == VAR) || (tok == LIT)) {
  737. X        v = val;
  738. X        token();
  739. X    } else
  740. X        evalerr("bad expression");
  741. X    return v;
  742. X}
  743. X
  744. Xstatic void
  745. Xtoken()
  746. X{
  747. X    register char *cp = (char *) tokp;
  748. X    register int c, c2;
  749. X
  750. X    /* skip white space */
  751. X    do c = *cp++;    while (c != '\0' && (c == ' ' || c == '\t'));
  752. X    tokp = cp-1;
  753. X
  754. X    if (letter(c)) {
  755. X        for (; letnum(c); c = *cp++)
  756. X            ;
  757. X        c = *--cp;
  758. X        *cp = 0;
  759. X        val = global(tokp);
  760. X        *cp = c;
  761. X        tok = VAR;
  762. X    } else
  763. X    if (digit(c)) {
  764. X        for (; letnum(c) || c == '#'; c = *cp++)
  765. X            ;
  766. X        c = *--cp;
  767. X        *cp = 0;
  768. X        val = tempvar();
  769. X        setstr(val, tokp);
  770. X        val->flag |= RDONLY;
  771. X        *cp = c;
  772. X        tok = LIT;
  773. X    } else {
  774. X        c2 = *cp++;
  775. X        if (c == '=' && c2 == '=')
  776. X            c = LEQ;
  777. X        ef (c == '!' && c2 == '=')
  778. X            c = LNE;
  779. X        ef (c == '<' && c2 == '=')
  780. X                c = LLE;
  781. X        ef (c == '>' && c2 == '=')
  782. X                c = LGE;
  783. X        else
  784. X            cp--;
  785. X        tok = c;
  786. X    }
  787. X    tokp = cp;
  788. X}
  789. X
  790. Xstatic struct tbl *
  791. Xtempvar()
  792. X{
  793. X    register struct tbl *vp;
  794. X
  795. X    vp = (struct tbl*) alloc(sizeof(struct tbl), ATEMP);
  796. X    lastarea = ATEMP;
  797. X    vp->flag = ISSET|INTEGER;
  798. X    vp->type = 0;
  799. X    vp->name[0] = '\0';
  800. X    return vp;
  801. X}
  802. X
  803. X/* cast (string) variable to temporary integer variable */
  804. Xstatic struct tbl *
  805. Xintvar(vp)
  806. X    register struct tbl *vp;
  807. X{
  808. X    register struct tbl *vq;
  809. X
  810. X    vq = tempvar();
  811. X    vq->type = 10;
  812. X    if (strint(vq, vp) == NULL) {
  813. X        if ((vp->flag&ISSET) && vp->val.s && *(vp->val.s)) {
  814. X            evalerr("bad number");
  815. X        } else {
  816. X            vq->flag |= (ISSET|INTEGER);
  817. X            vq->type = 10;
  818. X            vq->val.i = 0;
  819. X        }
  820. X    }
  821. X    return vq;
  822. X}
  823. X
  824. END_OF_FILE
  825.   if test 4590 -ne `wc -c <'sh/expr.c'`; then
  826.     echo shar: \"'sh/expr.c'\" unpacked with wrong size!
  827.   fi
  828.   # end of 'sh/expr.c'
  829. fi
  830. if test -f 'sh/mail.c' -a "${1}" != "-c" ; then 
  831.   echo shar: Will not clobber existing file \"'sh/mail.c'\"
  832. else
  833.   echo shar: Extracting \"'sh/mail.c'\" \(4237 characters\)
  834.   sed "s/^X//" >'sh/mail.c' <<'END_OF_FILE'
  835. X/*
  836. X * Mailbox checking code by Robert J. Gibson, adapted for PD ksh by
  837. X * John R. MacMillan
  838. X */
  839. X
  840. X#include <stddef.h>
  841. X#include <stdio.h>
  842. X#include <string.h>
  843. X#include <signal.h>
  844. X#include <errno.h>
  845. X#include <setjmp.h>
  846. X#include <sys/types.h>
  847. X#include <sys/stat.h>
  848. X#include "sh.h"
  849. X#include "table.h"
  850. X
  851. XVoid    mcheck();    /* check for new mail */
  852. XVoid    mbset();    /* set $MAIL */
  853. XVoid    mpset();    /* set $MAILPATH */
  854. XVoid    mprint();    /* print a list of mail messages */
  855. X
  856. X#define MBMESSAGE    "you have mail in $_"
  857. X
  858. Xtypedef struct mbox {
  859. X    struct mbox    *mb_next;    /* next mbox in list */
  860. X    char           *mb_path;    /* path to mail file */
  861. X    char           *mb_msg;        /* to announce arrival of new mail */
  862. X    unsigned int    mb_size;    /* size of mail file (bytes) */
  863. X} mbox_t;
  864. X
  865. Xstruct mailmsg {
  866. X    char        *msg;        /* Text of message */
  867. X    struct mailmsg    *next;        /* Next message */
  868. X};
  869. X
  870. X/*
  871. X * $MAILPATH is a linked list of mboxes.  $MAIL is a treated as a
  872. X * special case of $MAILPATH, where the list has only one node.  The
  873. X * same list is used for both since they are exclusive.
  874. X */
  875. X
  876. Xstatic mbox_t  *mplist = NULL;
  877. Xstatic mbox_t  mbox = { NULL, NULL, NULL, 0 };
  878. Xstatic long    mlastchkd = 0;    /* when mail was last checked */
  879. Xstatic struct mailmsg *mmsgs = NULL;    /* Messages to be printed */
  880. Xstatic Void    munset();        /* free mlist and mval */
  881. Xstatic mbox_t  *mballoc();        /* allocate a new mbox */
  882. Xstatic Void    maddmsg();
  883. X
  884. XVoid
  885. Xmcheck()
  886. X{
  887. X    register mbox_t    *mbp;
  888. X    long         now;
  889. X    struct tbl    *vp, mailcheck;
  890. X    struct stat     stbuf;
  891. X
  892. X    vp = global("MAILCHECK");
  893. X    if (!(vp->flag & ISSET) || strint(&mailcheck, vp) == NULL)
  894. X        return;
  895. X
  896. X    if (mlastchkd == 0)
  897. X        mlastchkd = time((long *)0);
  898. X
  899. X    if ((now=time((long *)0)) - mlastchkd >= mailcheck.val.i) {
  900. X        mlastchkd = now;
  901. X        
  902. X        vp = global("MAILPATH");
  903. X        if (vp && (vp->flag & ISSET))
  904. X            mbp = mplist;
  905. X        else if ((vp = global("MAIL")) && (vp->flag & ISSET))
  906. X            mbp = &mbox;
  907. X        else
  908. X            mbp = NULL;
  909. X
  910. X        while (mbp) {
  911. X            if (stat(mbp->mb_path, &stbuf) == 0 &&
  912. X                (stbuf.st_mode & S_IFMT) == S_IFREG) {
  913. X                if (mbp->mb_size < stbuf.st_size)
  914. X                    maddmsg( mbp );
  915. X                mbp->mb_size = stbuf.st_size;
  916. X            } else {
  917. X                /*
  918. X                 * Some mail readers remove the mail
  919. X                 * file if all mail is read.  If file
  920. X                 * does not exist, assume this is the
  921. X                 * case and set size to zero.
  922. X                 */
  923. X                mbp->mb_size = 0;
  924. X            }
  925. X            mbp = mbp->mb_next;
  926. X        }
  927. X    }
  928. X}
  929. X
  930. XVoid
  931. Xmbset(p)
  932. X    register char    *p;
  933. X{
  934. X    struct stat    stbuf;
  935. X
  936. X    if (mbox.mb_msg)
  937. X        afree((Void *)mbox.mb_msg, APERM);
  938. X    mbox.mb_path = p;
  939. X    mbox.mb_msg = NULL;
  940. X    if (stat(p,&stbuf) == 0 && (stbuf.st_mode & S_IFMT) == S_IFREG)
  941. X        mbox.mb_size = stbuf.st_size;
  942. X    else
  943. X        mbox.mb_size = 0;
  944. X}
  945. X
  946. XVoid
  947. Xmpset(mptoparse)
  948. X    register char    *mptoparse;
  949. X{
  950. X    register mbox_t    *mbp;
  951. X    register char    *mpath, *mmsg, *mval;
  952. X
  953. X    munset( mplist );
  954. X    mplist = NULL;
  955. X    mval = strsave(mptoparse, APERM);
  956. X    while (mval) {
  957. X        mpath = mval;
  958. X        if ((mval = strchr(mval, ':')) != NULL) {
  959. X            *mval ='\0', mval++;
  960. X        }
  961. X        if ((mmsg = strchr(mpath, '?')) != NULL) {
  962. X            *mmsg = '\0', mmsg++;
  963. X        }
  964. X        mbp = mballoc(mpath, mmsg);
  965. X        mbp->mb_next = mplist;
  966. X        mplist = mbp;
  967. X    }
  968. X}
  969. X
  970. Xstatic Void
  971. Xmunset(mlist)
  972. Xregister mbox_t    *mlist;
  973. X{
  974. X    register mbox_t    *mbp;
  975. X
  976. X    while (mlist != NULL) {
  977. X        mbp = mlist;
  978. X        mlist = mbp->mb_next;
  979. X        if (!mlist)
  980. X            afree((Void *)mbp->mb_path, APERM);
  981. X        afree((Void *)mbp, APERM);
  982. X    }
  983. X}
  984. X
  985. Xstatic mbox_t *
  986. Xmballoc(p, m)
  987. X    char    *p;
  988. X    char    *m;
  989. X{
  990. X    struct stat    stbuf;
  991. X    register mbox_t    *mbp;
  992. X
  993. X    mbp = (mbox_t *)alloc(sizeof(mbox_t), APERM);
  994. X    mbp->mb_next = NULL;
  995. X    mbp->mb_path = p;
  996. X    mbp->mb_msg = m;
  997. X    if (stat(mbp->mb_path, &stbuf) == 0 &&
  998. X       (stbuf.st_mode & S_IFMT) == S_IFREG) {
  999. X        mbp->mb_size = stbuf.st_size;
  1000. X    } else {
  1001. X        mbp->mb_size = 0;
  1002. X    }
  1003. X    return(mbp);
  1004. X}
  1005. X
  1006. XVoid
  1007. Xmprint()
  1008. X{
  1009. X    struct mailmsg *mm;
  1010. X
  1011. X    while ((mm = mmsgs) != NULL) {
  1012. X        shellf( "%s\n", mm->msg );
  1013. X        fflush(shlout);
  1014. X        afree((Void *)mm->msg, APERM);
  1015. X        mmsgs = mm->next;
  1016. X        afree((Void *)mm, APERM);
  1017. X    }
  1018. X}
  1019. X
  1020. Xstatic Void
  1021. Xmaddmsg( mbp )
  1022. Xmbox_t    *mbp;
  1023. X{
  1024. X    struct mailmsg    *message;
  1025. X    struct tbl    *vp;
  1026. X
  1027. X    message = (struct mailmsg *)alloc(sizeof(struct mailmsg), APERM);
  1028. X    setstr((vp = typeset("_", LOCAL, 0)), mbp->mb_path);
  1029. X
  1030. X    if (mbp->mb_msg)
  1031. X        message->msg = strsave(substitute(mbp->mb_msg,0),APERM);
  1032. X    else
  1033. X        message->msg = strsave(substitute(MBMESSAGE,0),APERM);
  1034. X
  1035. X    unset(vp);
  1036. X    message->next = mmsgs;
  1037. X    mmsgs = message;
  1038. X}
  1039. END_OF_FILE
  1040.   if test 4237 -ne `wc -c <'sh/mail.c'`; then
  1041.     echo shar: \"'sh/mail.c'\" unpacked with wrong size!
  1042.   fi
  1043.   # end of 'sh/mail.c'
  1044. fi
  1045. if test -f 'sh/misc.c' -a "${1}" != "-c" ; then 
  1046.   echo shar: Will not clobber existing file \"'sh/misc.c'\"
  1047. else
  1048.   echo shar: Extracting \"'sh/misc.c'\" \(6802 characters\)
  1049.   sed "s/^X//" >'sh/misc.c' <<'END_OF_FILE'
  1050. X/*
  1051. X * Miscellaneous functions
  1052. X */
  1053. X
  1054. Xstatic char *RCSid = "$Id: misc.c,v 3.2 89/03/27 15:51:44 egisin Exp $";
  1055. X
  1056. X#include <stddef.h>
  1057. X#include <limits.h>
  1058. X#include <string.h>
  1059. X#include <signal.h>
  1060. X#include <errno.h>
  1061. X#include <setjmp.h>
  1062. X#include "sh.h"
  1063. X#include "expand.h"
  1064. X
  1065. Xchar ctypes [UCHAR_MAX+1];    /* type bits for unsigned char */
  1066. X
  1067. X/*
  1068. X * Fast character classes
  1069. X */
  1070. Xvoid
  1071. Xsetctypes(s, t)
  1072. X    register Const char *s;
  1073. X    register int t;
  1074. X{
  1075. X    register int i;
  1076. X
  1077. X    if ((t&C_IFS)) {
  1078. X        for (i = 0; i < UCHAR_MAX+1; i++)
  1079. X            ctypes[i] &=~ C_IFS;
  1080. X        ctypes[0] |= C_IFS; /* include \0 in C_IFS */
  1081. X    }
  1082. X    ctypes[(unsigned char) *s++] |= t;    /* allow leading \0 in string */
  1083. X    while (*s != 0)
  1084. X        ctypes[(unsigned char) *s++] |= t;
  1085. X}
  1086. X
  1087. Xvoid
  1088. Xinitctypes()
  1089. X{
  1090. X    register int c;
  1091. X
  1092. X    for (c = 'a'; c <= 'z'; c++)
  1093. X        ctypes[c] |= C_ALPHA;
  1094. X    for (c = 'A'; c <= 'Z'; c++)
  1095. X        ctypes[c] |= C_ALPHA;
  1096. X    ctypes['_'] |= C_ALPHA;
  1097. X    setctypes("0123456789", C_DIGIT);
  1098. X    setctypes("\0 \t\n|&;<>()", C_LEX1);
  1099. X    setctypes("*@#!$-?", C_VAR1);
  1100. X    setctypes("=-+?#%", C_SUBOP);
  1101. X}
  1102. X
  1103. X/* convert unsigned long to base N string */
  1104. X
  1105. Xchar *
  1106. Xulton(n, base)
  1107. X    register unsigned long n;
  1108. X    int base;
  1109. X{
  1110. X    register char *p;
  1111. X    static char buf [20];
  1112. X
  1113. X    p = &buf[sizeof(buf)];
  1114. X    *--p = '\0';
  1115. X    do {
  1116. X        *--p = "0123456789ABCDEF"[n%base];
  1117. X        n /= base;
  1118. X    } while (n != 0);
  1119. X    return p;
  1120. X}
  1121. X
  1122. Xchar *
  1123. Xstrsave(s, ap)
  1124. X    register char *s;
  1125. X    Area *ap;
  1126. X{
  1127. X    return strcpy((char*) alloc((size_t)strlen(s)+1, ap), s);
  1128. X}
  1129. X
  1130. Xstatic struct option {
  1131. X    char *name;
  1132. X    int flag;
  1133. X} options[] = {
  1134. X    {"allexport",    FEXPORT},
  1135. X    {"bgnice",    FBGNICE},
  1136. X#if defined(EDIT) && defined(EMACS)
  1137. X    {"emacs",    FEMACS},
  1138. X#endif
  1139. X    {"errexit",    FERREXIT},
  1140. X    {"hashall",    FHASHALL},
  1141. X    {"ignoreeof",    FIGNEOF},
  1142. X    {"interactive",    FTALKING},
  1143. X    {"keyword",    FKEYWORD},
  1144. X    {"markdirs",    FMARKDIRS},
  1145. X    {"monitor",    FMONITOR},
  1146. X    {"noexec",    FNOEXEC},
  1147. X    {"noglob",    FNOGLOB},
  1148. X    {"nounset",    FNOUNSET},
  1149. X    {"privileged",    FPRIVILEGED},
  1150. X    {"stdin",    FSTDIN},
  1151. X    {"trackall",    FHASHALL},
  1152. X    {"verbose",    FVERBOSE},
  1153. X#if defined(EDIT) && defined(VI)
  1154. X    {"vi",        FVI},
  1155. X#endif
  1156. X    {"xtrace",    FXTRACE},
  1157. X    {NULL,        0}
  1158. X};    
  1159. X
  1160. X/*
  1161. X * translate -o option into F* constant
  1162. X */
  1163. Xint
  1164. Xoption(n)
  1165. X    Const char *n;
  1166. X{
  1167. X    register struct option *op;
  1168. X
  1169. X    for (op = options; op->name != NULL; op++)
  1170. X        if (strcmp(op->name, n) == 0)
  1171. X            return op->flag;
  1172. X    return 0;
  1173. X}
  1174. X
  1175. Xchar *
  1176. Xgetoptions()
  1177. X{
  1178. X    register int c;
  1179. X    char m [26+1];
  1180. X    register char *cp = m;
  1181. X
  1182. X    for (c = 'a'; c <= 'z'; c++)
  1183. X        if (flag[FLAG(c)])
  1184. X            *cp++ = (char) c;
  1185. X    *cp = 0;
  1186. X    return strsave(m, ATEMP);
  1187. X}
  1188. X
  1189. Xvoid
  1190. Xprintoptions()
  1191. X{
  1192. X    register struct option *op;
  1193. X
  1194. X    for (op = options; op->name != NULL; op++)
  1195. X        if (flag[op->flag])
  1196. X            shellf("%s ", op->name);
  1197. X    shellf("\n");
  1198. X}
  1199. X    
  1200. X/* atoi with error detection */
  1201. X
  1202. Xgetn(as)
  1203. X    char *as;
  1204. X{
  1205. X    register char *s;
  1206. X    register int n;
  1207. X
  1208. X    s = as;
  1209. X    if (*s == '-')
  1210. X        s++;
  1211. X    for (n = 0; digit(*s); s++)
  1212. X        n = (n*10) + (*s-'0');
  1213. X    if (*s)
  1214. X        errorf("%s: bad number\n", as);
  1215. X    return (*as == '-') ? -n : n;
  1216. X}
  1217. X
  1218. X/*
  1219. X * stripped down strerror for kill and exec
  1220. X */
  1221. Xchar *
  1222. Xstrerror(i)
  1223. X    int i;
  1224. X{
  1225. X    switch (i) {
  1226. X      case EINVAL:
  1227. X        return "Invalid argument";
  1228. X      case EACCES:
  1229. X        return "Permission denied";
  1230. X      case ESRCH:
  1231. X        return "No such process";
  1232. X      case EPERM:
  1233. X        return "Not owner";
  1234. X      case ENOENT:
  1235. X        return "No such file or directory";
  1236. X      case ENOTDIR:
  1237. X        return "Not a directory";
  1238. X      case ENOEXEC:
  1239. X        return "Exec format error";
  1240. X      case ENOMEM:
  1241. X        return "Not enough memory";
  1242. X      case E2BIG:
  1243. X        return "Argument list too long";
  1244. X      default:
  1245. X        return "Unknown system error";
  1246. X    }
  1247. X}
  1248. X
  1249. X/* -------- gmatch.c -------- */
  1250. X
  1251. X/*
  1252. X * int gmatch(string, pattern)
  1253. X * char *string, *pattern;
  1254. X *
  1255. X * Match a pattern as in sh(1).
  1256. X * pattern character are prefixed with MAGIC by expand.
  1257. X */
  1258. X
  1259. Xstatic    char    *cclass ARGS((char *, int c));
  1260. X
  1261. Xint
  1262. Xgmatch(s, p)
  1263. X    register char *s, *p;
  1264. X{
  1265. X    register int sc, pc;
  1266. X
  1267. X    if (s == NULL || p == NULL)
  1268. X        return 0;
  1269. X    while ((pc = *p++) != 0) {
  1270. X        sc = *s++;
  1271. X        if (pc ==  MAGIC)
  1272. X            switch (*p++) {
  1273. X              case '[':
  1274. X                if (sc == 0 || (p = cclass(p, sc)) == NULL)
  1275. X                    return (0);
  1276. X                break;
  1277. X
  1278. X              case '?':
  1279. X                if (sc == 0)
  1280. X                    return (0);
  1281. X                break;
  1282. X
  1283. X              case '*':
  1284. X                s--;
  1285. X                do {
  1286. X                    if (*p == '\0' || gmatch(s, p))
  1287. X                        return (1);
  1288. X                } while (*s++ != '\0');
  1289. X                return (0);
  1290. X
  1291. X              default:
  1292. X                if (sc != p[-1])
  1293. X                    return 0;
  1294. X                break;
  1295. X            }
  1296. X        else
  1297. X            if (sc != pc)
  1298. X                return 0;
  1299. X    }
  1300. X    return (*s == 0);
  1301. X}
  1302. X
  1303. Xstatic char *
  1304. Xcclass(p, sub)
  1305. X    register char *p;
  1306. X    register int sub;
  1307. X{
  1308. X    register int c, d, not, found = 0;
  1309. X
  1310. X    if ((not = (*p == MAGIC && *++p == NOT)))
  1311. X        p++;
  1312. X    do {
  1313. X        if (*p == MAGIC)
  1314. X            p++;
  1315. X        if (*p == '\0')
  1316. X            return NULL;
  1317. X        c = *p;
  1318. X        if (p[1] == '-' && p[2] != ']') {
  1319. X            d = p[2];
  1320. X            p++;
  1321. X        } else
  1322. X            d = c;
  1323. X        if (c == sub || c <= sub && sub <= d)
  1324. X            found = 1;
  1325. X    } while (*++p != ']');
  1326. X
  1327. X    return (found != not) ? p+1 : NULL;
  1328. X}
  1329. X
  1330. X/* -------- qsort.c -------- */
  1331. X
  1332. X/*
  1333. X * quick sort of array of generic pointers to objects.
  1334. X */
  1335. X
  1336. Xvoid
  1337. Xqsortp(base, n, f)
  1338. X    Void **base;        /* base address */
  1339. X    size_t n;        /* elements */
  1340. X    int (*f)();        /* compare function */
  1341. X{
  1342. X    qsort1(base, base + n, f);
  1343. X}
  1344. X
  1345. X#define    swap2(a, b)    {\
  1346. X    register Void *t; t = *(a); *(a) = *(b); *(b) = t;\
  1347. X}
  1348. X#define    swap3(a, b, c)    {\
  1349. X    register Void *t; t = *(a); *(a) = *(c); *(c) = *(b); *(b) = t;\
  1350. X}
  1351. X
  1352. Xqsort1(base, lim, f)
  1353. X    Void **base, **lim;
  1354. X    int (*f)();
  1355. X{
  1356. X    register Void **i, **j;
  1357. X    register Void **lptr, **hptr;
  1358. X    size_t n;
  1359. X    int c;
  1360. X
  1361. X  top:
  1362. X    n = (lim - base) / 2;
  1363. X    if (n == 0)
  1364. X        return;
  1365. X    hptr = lptr = base+n;
  1366. X    i = base;
  1367. X    j = lim - 1;
  1368. X
  1369. X    for (;;) {
  1370. X        if (i < lptr) {
  1371. X            if ((c = (*f)(*i, *lptr)) == 0) {
  1372. X                lptr --;
  1373. X                swap2(i, lptr);
  1374. X                continue;
  1375. X            }
  1376. X            if (c < 0) {
  1377. X                i += 1;
  1378. X                continue;
  1379. X            }
  1380. X        }
  1381. X
  1382. X      begin:
  1383. X        if (j > hptr) {
  1384. X            if ((c = (*f)(*hptr, *j)) == 0) {
  1385. X                hptr ++;
  1386. X                swap2(hptr, j);
  1387. X                goto begin;
  1388. X            }
  1389. X            if (c > 0) {
  1390. X                if (i == lptr) {
  1391. X                    hptr ++;
  1392. X                    swap3(i, hptr, j);
  1393. X                    i = lptr += 1;
  1394. X                    goto begin;
  1395. X                }
  1396. X                swap2(i, j);
  1397. X                j -= 1;
  1398. X                i += 1;
  1399. X                continue;
  1400. X            }
  1401. X            j -= 1;
  1402. X            goto begin;
  1403. X        }
  1404. X
  1405. X        if (i == lptr) {
  1406. X            if (lptr-base >= lim-hptr) {
  1407. X                qsort1(hptr+1, lim, f);
  1408. X                lim = lptr;
  1409. X            } else {
  1410. X                qsort1(base, lptr, f);
  1411. X                base = hptr+1;
  1412. X            }
  1413. X            goto top;
  1414. X        }
  1415. X
  1416. X        lptr -= 1;
  1417. X        swap3(j, lptr, i);
  1418. X        j = hptr -= 1;
  1419. X    }
  1420. X}
  1421. X
  1422. Xint
  1423. Xxstrcmp(p1, p2)
  1424. X    Void *p1, *p2;
  1425. X{
  1426. X    return (strcmp((char *)p1, (char *)p2));
  1427. X}
  1428. X
  1429. XVoid
  1430. Xcleanpath(pwd, dir, clean)
  1431. X    char *pwd, *dir, *clean;
  1432. X{
  1433. X    register char  *s, *d, *p;
  1434. X    char *slash = "/";
  1435. X    register int inslash = 0;
  1436. X
  1437. X    d = clean;
  1438. X    if (*dir != '/') {
  1439. X        s = pwd;
  1440. X        while (*d++ = *s++)
  1441. X            ;
  1442. X        *(d - 1) = '/';
  1443. X    }
  1444. X
  1445. X    s = dir;
  1446. X    while (*s) {
  1447. X        if ((*d++ = *s++) == '/' && d > clean + 1) {
  1448. X            if (*(p = d - 2) == '/') {
  1449. X                --d;
  1450. X            } else if (*p == '.') {
  1451. X                if (*--p == '/') {
  1452. X                    d -= 2;
  1453. X                } else if (*p == '.' && *--p == '/') {
  1454. X                    while (p > clean && *--p != '/')
  1455. X                        ;
  1456. X                    d = p + 1;
  1457. X                }
  1458. X            }
  1459. X        }
  1460. X        if (!*s && !inslash && *(s - 1) != '/') {
  1461. X            inslash = 1;
  1462. X            s = slash;
  1463. X        }
  1464. X    }
  1465. X
  1466. X    if (*(d - 1) == '/' && (d - 1) > clean)
  1467. X        d--;
  1468. X    *d = '\0';
  1469. X}
  1470. END_OF_FILE
  1471.   if test 6802 -ne `wc -c <'sh/misc.c'`; then
  1472.     echo shar: \"'sh/misc.c'\" unpacked with wrong size!
  1473.   fi
  1474.   # end of 'sh/misc.c'
  1475. fi
  1476. if test -f 'sh/sh.h' -a "${1}" != "-c" ; then 
  1477.   echo shar: Will not clobber existing file \"'sh/sh.h'\"
  1478. else
  1479.   echo shar: Extracting \"'sh/sh.h'\" \(7087 characters\)
  1480.   sed "s/^X//" >'sh/sh.h' <<'END_OF_FILE'
  1481. X/*
  1482. X * Public Domain Bourne/Korn shell
  1483. X */
  1484. X
  1485. X/* $Id: sh.h,v 3.3 89/03/27 15:46:34 egisin Exp $ */
  1486. X
  1487. X#include "config.h"
  1488. X
  1489. X/* allow for non-Unix linkers. main.c has a "#define Extern " */
  1490. X#ifndef Extern
  1491. X#define    Extern    extern
  1492. X#endif
  1493. X
  1494. X#ifndef SHELL
  1495. X#define    SHELL    "/bin/sh"    /* shell to exec scripts */
  1496. X#endif
  1497. X
  1498. X/* some people object to this use of __STDC__ */
  1499. X#if __STDC__
  1500. X#define    ARGS(args)    args    /* prototype declaration */
  1501. X#define    Void    void        /* generic pointer */
  1502. X#define    Const    const        /* constant data */
  1503. X#define    Volatile volatile    /* you know */
  1504. X#else
  1505. X#define    ARGS(args)    ()    /* K&R declaration */
  1506. X#define    Void    char
  1507. X#define    Const    
  1508. X#define    Volatile 
  1509. X#endif
  1510. X
  1511. X#ifdef _ULTRIX            /* Ultrix 2.x gets dup2 wrong */
  1512. Xint dup2 ARGS ((int, int));
  1513. X/* assumes we don't want dup2 return value */
  1514. X#define    dup2(ofd, nfd) \
  1515. X        (void) ((dup2)(ofd, nfd), fcntl(nfd, F_SETFD, 0))
  1516. X#endif
  1517. X
  1518. X#if defined(EMACS) || defined(VI)
  1519. X#define    EDIT
  1520. X#endif
  1521. X
  1522. Xtypedef int bool_t;
  1523. X#define    FALSE    0
  1524. X#define    TRUE    1
  1525. X
  1526. X#define    sizeofN(type, n) (sizeof(type) * (n))
  1527. X#define    BIT(i)    (1<<(i))    /* define bit in flag */
  1528. X
  1529. X#define    NUFILE    10        /* Number of user-accessible files */
  1530. X#define    FDBASE    10        /* First file usable by Shell */
  1531. X
  1532. X/* you're not going to run setuid shell scripts, are you? */
  1533. X#define    eaccess(path, mode)    access(path, mode)
  1534. X
  1535. X#define    MAGIC    (char)0x80    /* prefix for ~*?[ during expand */
  1536. X#define    NOT    '!'    /* might use ^ */
  1537. X
  1538. X#define    LINE    256        /* input line size */
  1539. X#define    PATH    256        /* pathname size */
  1540. X
  1541. XExtern    int    kshpid;        /* $$, shell pid */
  1542. XExtern    int    exstat;        /* exit status */
  1543. XExtern    int    async;        /* $!, last &'d pid */
  1544. X
  1545. X/*
  1546. X * Area-based allocation built on malloc/free
  1547. X */
  1548. X
  1549. Xtypedef struct Area {
  1550. X    struct Block *free;    /* free list */
  1551. X} Area;
  1552. X
  1553. Xextern    Area    aperm;        /* permanent object space */
  1554. X#define    APERM    &aperm
  1555. X#define    ATEMP    &e.area
  1556. X
  1557. XArea   *ainit ARGS((Area *ap));        /* initialize Area */
  1558. Xvoid    afreeall ARGS((Area *ap));    /* free Area's contents */
  1559. Xvoid    ashrink ARGS((Area *ap));    /* unimplimented */
  1560. Xvoid    aerror ARGS((Area *ap, const char *msg)); /* error handler */
  1561. X
  1562. XVoid   *alloc ARGS((size_t size, Area *ap)); /* alloc object from Area */
  1563. XVoid   *aresize ARGS((Void *ptr, size_t size, Area *ap)); /* shrink object */
  1564. Xvoid    afree ARGS((Void *ptr, Area *ap)); /* free ojbect in Area */
  1565. X
  1566. X/*
  1567. X * parsing & execution environment
  1568. X */
  1569. XExtern    struct    env {
  1570. X    int    type;            /* enviroment type - see below */
  1571. X    Area    area;            /* temporary allocation area */
  1572. X    struct    block *loc;        /* local variables and functions */
  1573. X    short  *savefd;            /* original redirected fd's */
  1574. X    struct    env *oenv;        /* link to previous enviroment */
  1575. X    jmp_buf    jbuf;            /* long jump back to env creator */
  1576. X    int    interactive;        /* fd's 0,1,2 are tty */
  1577. X    struct temp *temps;        /* temp files */
  1578. X} e;
  1579. X
  1580. X#define    E_NONE    0        /* dummy enviroment */
  1581. X#define    E_PARSE    1        /* parsing command # */
  1582. X#define    E_EXEC    2        /* executing command tree */
  1583. X#define    E_LOOP    3        /* executing for/while # */
  1584. X#define    E_TCOM    5        /* executing simple command */
  1585. X#define    E_FUNC    6        /* executing function */
  1586. X#define    E_ERRH    7        /* general error handler # */
  1587. X/* # indicates env has valid jbuf */
  1588. X
  1589. X/*
  1590. X * flags
  1591. X */
  1592. X#define    FEXPORT    FLAG('a')    /* -a: allexport */
  1593. X#define    FERREXIT FLAG('e')    /* -e: errexit (quit on error) */
  1594. X#define    FBGNICE    29        /* bgnice */
  1595. X#define    FEMACS 30        /* emacs command editing */
  1596. X#define    FIGNEOF    27        /* ignoreeof (eof does not exit) */
  1597. X#define    FHASHALL FLAG('h')    /* -h: trackall, hashall */
  1598. X#define    FTALKING FLAG('i')    /* -i: interactive (talking type wireless) */
  1599. X#define    FKEYWORD FLAG('k')    /* -k: keyword (name=value anywhere) */
  1600. X#define    FMARKDIRS 28        /* markdirs */
  1601. X#define    FMONITOR FLAG('m')    /* -m: monitor */
  1602. X#define    FNOEXEC    FLAG('n')    /* -n: noexec */
  1603. X#define    FNOGLOB    FLAG('f')    /* -f: noglob */
  1604. X#define    FPRIVILEGED FLAG('p')    /* -p: privileged */
  1605. X#define    FSTDIN    FLAG('s')    /* -s (invocation): parse stdin */
  1606. X#define    FNOUNSET FLAG('u')    /* -u: nounset (unset vars is error) */
  1607. X#define    FVERBOSE FLAG('v')    /* -v: verbose (echo input) */
  1608. X#define    FVI 31            /* vi command editing */
  1609. X#define    FXTRACE    FLAG('x')    /* -x: (execute) xtrace */
  1610. X
  1611. X#define    FLAG(c)    (1 + c - 'a')    /* map char to flags index */
  1612. X#define    FLAGS    32
  1613. XExtern    char flag [FLAGS];
  1614. Xint    option ARGS((Const char *name));
  1615. Xchar   *getoptions ARGS((void));
  1616. Xvoid    printoptions ARGS((void));
  1617. X
  1618. Xextern    char    null [];    /* null value for variable */
  1619. X
  1620. X/*
  1621. X * other functions
  1622. X */
  1623. Xchar   *search();
  1624. Xstruct tbl *findcom();
  1625. Xchar   *strsave ARGS((char *, Area *));
  1626. Xchar   *ulton ARGS((unsigned long n, int base));
  1627. Xint    xstrcmp();
  1628. Xvoid    qsortp ARGS((void **base, size_t n, int (*compare)(void *, void *)));
  1629. Xlong    evaluate ARGS((Const char *expr));
  1630. Xvoid    resetopts();
  1631. Xvoid    histsave();
  1632. Xvoid    histlist();
  1633. X
  1634. Xvoid    j_init ARGS((void));
  1635. Xvoid    j_exit ARGS((void));
  1636. Xvoid    j_notify ARGS((void));
  1637. Xvoid    j_kill ARGS((int job, int sig));
  1638. X#ifdef JOBS
  1639. Xvoid    j_change ARGS((void));
  1640. Xint    j_resume ARGS((int job, int bg));
  1641. X#endif
  1642. X
  1643. X/*
  1644. X * error handling
  1645. X */
  1646. Xvoid    leave();    /* abort shell (or fail in subshell) */
  1647. X
  1648. X/*
  1649. X * library functions
  1650. X */
  1651. Xtypedef    void (*handler_t)();    /* signal handler */
  1652. X
  1653. X/* temp/here files. the file is removed when the struct is freed */
  1654. Xstruct    temp {
  1655. X    struct    temp * next;
  1656. X    char   *name;
  1657. X};
  1658. Xstruct temp *maketemp ARGS((Area *ap));
  1659. X
  1660. X/*
  1661. X * stdio and our IO routines
  1662. X */
  1663. X
  1664. X#ifdef    BUFSIZ            /* <stdio.h> included? */
  1665. Xextern    FILE *    shf [NUFILE];    /* map shell fd to FILE */
  1666. X#endif
  1667. Xvoid    fopenshf();
  1668. Xvoid    flushshf();
  1669. X
  1670. X#undef    stdin
  1671. X#undef    stdout
  1672. X
  1673. X#define    stdin    shf[0]        /* standard input */
  1674. X#define    stdout    shf[1]        /* standard output */
  1675. X#define    shlout    shf[2]        /* shell output */
  1676. X
  1677. Xint    shellf ARGS((Const char *fmt, ...)); /* fprintf(shlout, ); */
  1678. Xint    errorf ARGS((Const char *fmt, ...)); /* fprintf(shlout, ); error(); */
  1679. X
  1680. X/*
  1681. X * IO control
  1682. X */
  1683. Xextern    int ttyfd;        /* tty fd (original fd 0) */
  1684. X
  1685. Xint    savefd ARGS((int fd));    /* save user fd */
  1686. Xvoid    restfd ARGS((int fd, int ofd));
  1687. Xvoid    openpipe ARGS((int [2]));
  1688. Xvoid    closepipe ARGS((int [2]));;
  1689. X
  1690. X/*
  1691. X * trap handlers
  1692. X */
  1693. Xtypedef struct trap {
  1694. X    int    signal;        /* signal number */
  1695. X    char   *name;        /* short name */
  1696. X    char   *mess;        /* descriptive name */
  1697. X    char   *trap;        /* trap command */
  1698. X    int    Volatile set;    /* trap pending */
  1699. X    int    ourtrap;    /* not ignored (?) */
  1700. X    int    sig_dfl;    /* originally SIG_DFL */
  1701. X} Trap;
  1702. X
  1703. X#ifndef    SIGKILL
  1704. X#include <signal.h>
  1705. X#endif    /* SIGKILL */
  1706. X#ifdef    NSIG
  1707. X#define    SIGNALS    NSIG
  1708. X#else
  1709. X#define    SIGNALS    32
  1710. X#endif    /* NSIG */
  1711. X
  1712. XExtern    int Volatile trap;    /* traps pending? */
  1713. Xextern    Trap    sigtraps[SIGNALS];
  1714. XTrap    *gettrap ARGS((char *)); /* search for struct trap by number or name */
  1715. Xvoid    trapsig ARGS((int sig)); /* trap signal handler */
  1716. X
  1717. X/*
  1718. X * fast character classes
  1719. X */
  1720. X#define    C_ALPHA    0x01        /* a-z_A-Z */
  1721. X#define    C_DIGIT    0x02        /* 0-9 */
  1722. X#define    C_LEX1    0x04        /* \0 \t\n|&;<>() */
  1723. X#define    C_VAR1    0x08        /* *@#!$-? */
  1724. X#define    C_SUBOP    0x40        /* "=-+?#%" */
  1725. X#define    C_IFS    0x80        /* $IFS */
  1726. X
  1727. Xextern    char ctypes [];
  1728. Xvoid    initctypes ARGS((void));
  1729. Xvoid    setctypes ARGS((Const char*, int type));
  1730. X
  1731. X#define    ctype(c, t)    !!(ctypes[(unsigned char)(c)]&(t))
  1732. X#define    letter(c)    ctype(c, C_ALPHA)
  1733. X#define    digit(c)    ctype(c, C_DIGIT)
  1734. X#define    letnum(c)    ctype(c, C_ALPHA|C_DIGIT)
  1735. X
  1736. X/*
  1737. X * 91-07-06 <sjg@sun0>
  1738. X * use my simple debug tracing... 
  1739. X */
  1740. X#include "trace.h"
  1741. X
  1742. END_OF_FILE
  1743.   if test 7087 -ne `wc -c <'sh/sh.h'`; then
  1744.     echo shar: \"'sh/sh.h'\" unpacked with wrong size!
  1745.   fi
  1746.   # end of 'sh/sh.h'
  1747. fi
  1748. if test -f 'sh/table.c' -a "${1}" != "-c" ; then 
  1749.   echo shar: Will not clobber existing file \"'sh/table.c'\"
  1750. else
  1751.   echo shar: Extracting \"'sh/table.c'\" \(3715 characters\)
  1752.   sed "s/^X//" >'sh/table.c' <<'END_OF_FILE'
  1753. Xstatic char *RCSid = "$Id: table.c,v 3.2 89/03/27 15:51:58 egisin Exp $";
  1754. X
  1755. X/*
  1756. X * dynamic hashed associative table for commands and variables
  1757. X */
  1758. X
  1759. X#include <stddef.h>
  1760. X#include <errno.h>
  1761. X#include <setjmp.h>
  1762. X#include "sh.h"
  1763. X#include "table.h"
  1764. X
  1765. X#define    INIT_TBLS    8    /* initial table size (power of 2) */
  1766. X
  1767. Xstatic struct tstate {
  1768. X    int left;
  1769. X    struct tbl **next;
  1770. X} tstate;
  1771. X
  1772. Xstatic void texpand();
  1773. X
  1774. Xunsigned int
  1775. Xhash(n)
  1776. X    register char * n;
  1777. X{
  1778. X    register unsigned int h = 0;
  1779. X
  1780. X    while (*n != '\0')
  1781. X        h = 2*h + *n++;
  1782. X    return h * 32821;    /* scatter bits */
  1783. X}
  1784. X
  1785. X#if 0
  1786. Xphash(s) char *s; {
  1787. X    printf("%2d: %s\n", hash(s)%32, s);
  1788. X}
  1789. X#endif
  1790. X
  1791. Xvoid
  1792. Xtinit(tp, ap)
  1793. X    register struct table *tp;
  1794. X    register Area *ap;
  1795. X{
  1796. X    tp->areap = ap;
  1797. X    tp->size = tp->free = 0;
  1798. X    tp->tbls = NULL;
  1799. X}
  1800. X
  1801. Xstatic void
  1802. Xtexpand(tp, nsize)
  1803. X    register struct table *tp;
  1804. X    int nsize;
  1805. X{
  1806. X    register int i;
  1807. X    register struct tbl *tblp, **p;
  1808. X    register struct tbl **ntblp, **otblp = tp->tbls;
  1809. X    int osize = tp->size;
  1810. X
  1811. X    ntblp = (struct tbl**) alloc(sizeofN(struct tbl *, nsize), tp->areap);
  1812. X    for (i = 0; i < nsize; i++)
  1813. X        ntblp[i] = NULL;
  1814. X    tp->size = nsize;
  1815. X    tp->free = 8*nsize/10;    /* table can get 80% full */
  1816. X    tp->tbls = ntblp;
  1817. X    if (otblp == NULL)
  1818. X        return;
  1819. X    for (i = 0; i < osize; i++)
  1820. X        if ((tblp = otblp[i]) != NULL)
  1821. X            if ((tblp->flag&DEFINED)) {
  1822. X                for (p = &ntblp[hash(tblp->name) & tp->size-1];
  1823. X                     *p != NULL; p--)
  1824. X                    if (p == ntblp) /* wrap */
  1825. X                        p += tp->size;
  1826. X                *p = tblp;
  1827. X                tp->free--;
  1828. X            } else {
  1829. X                afree((Void*)tblp, tp->areap);
  1830. X            }
  1831. X    afree((Void*)otblp, tp->areap);
  1832. X}
  1833. X
  1834. Xstruct tbl *
  1835. Xtsearch(tp, n, h)
  1836. X    register struct table *tp;    /* table */
  1837. X    register char *n;        /* name to enter */
  1838. X    unsigned int h;            /* hash(n) */
  1839. X{
  1840. X    register struct tbl **pp, *p;
  1841. X
  1842. X    if (tp->size == 0)
  1843. X        return NULL;
  1844. X
  1845. X    /* search for name in hashed table */
  1846. X    for (pp = &tp->tbls[h & tp->size-1]; (p = *pp) != NULL; pp--) {
  1847. X        if (*p->name == *n && strcmp(p->name, n) == 0
  1848. X            && (p->flag&DEFINED))
  1849. X            return p;
  1850. X        if (pp == tp->tbls) /* wrap */
  1851. X            pp += tp->size;
  1852. X    }
  1853. X
  1854. X    return NULL;
  1855. X}
  1856. X
  1857. Xstruct tbl *
  1858. Xtenter(tp, n, h)
  1859. X    register struct table *tp;    /* table */
  1860. X    register char *n;        /* name to enter */
  1861. X    unsigned int h;            /* hash(n) */
  1862. X{
  1863. X    register struct tbl **pp, *p;
  1864. X    register char *cp;
  1865. X
  1866. X    if (tp->size == 0)
  1867. X        texpand(tp, INIT_TBLS);
  1868. X  Search:
  1869. X    /* search for name in hashed table */
  1870. X    for (pp = &tp->tbls[h & tp->size-1]; (p = *pp) != NULL; pp--) {
  1871. X        if (*p->name == *n && strcmp(p->name, n) == 0)
  1872. X            return p;     /* found */
  1873. X        if (pp == tp->tbls) /* wrap */
  1874. X            pp += tp->size;
  1875. X    }
  1876. X
  1877. X    if (tp->free <= 0) {    /* too full */
  1878. X        texpand(tp, 2*tp->size);
  1879. X        goto Search;
  1880. X    }
  1881. X
  1882. X    /* create new tbl entry */
  1883. X    for (cp = n; *cp != '\0'; cp++)
  1884. X        ;
  1885. X    p = (struct tbl *) alloc(offsetof(struct tbl, name[(cp-n)+1]), tp->areap);
  1886. X    p->flag = 0;
  1887. X    p->type = 0;
  1888. X    for (cp = p->name; *n != '\0';)
  1889. X        *cp++ = *n++;
  1890. X    *cp = '\0';
  1891. X
  1892. X    /* enter in tp->tbls */
  1893. X    tp->free--;
  1894. X    *pp = p;
  1895. X    return p;
  1896. X}
  1897. X
  1898. Xvoid
  1899. Xtdelete(p)
  1900. X    register struct tbl *p;
  1901. X{
  1902. X    p->flag = 0;
  1903. X}
  1904. X
  1905. Xvoid
  1906. Xtwalk(tp)
  1907. X    register struct table *tp;
  1908. X{
  1909. X    tstate.left = tp->size;
  1910. X    tstate.next = tp->tbls;
  1911. X}
  1912. X
  1913. Xstruct tbl *
  1914. Xtnext()
  1915. X{
  1916. X    while (--tstate.left >= 0) {
  1917. X        struct tbl *p = *tstate.next++;
  1918. X        if (p != NULL && (p->flag&DEFINED))
  1919. X            return p;
  1920. X    }
  1921. X    return NULL;
  1922. X}
  1923. X
  1924. Xstatic int
  1925. Xtnamecmp(p1, p2)
  1926. X    Void *p1, *p2;
  1927. X{
  1928. X    return strcmp(((struct tbl *)p1)->name, ((struct tbl *)p2)->name);
  1929. X}
  1930. X
  1931. Xstruct tbl **
  1932. Xtsort(tp)
  1933. X    register struct table *tp;
  1934. X{
  1935. X    register int i;
  1936. X    register struct tbl **p, **sp, **dp;
  1937. X
  1938. X    p = (struct tbl **)alloc(sizeofN(struct tbl *, tp->size+1), ATEMP);
  1939. X    sp = tp->tbls;        /* source */
  1940. X    dp = p;            /* dest */
  1941. X    for (i = 0; i < tp->size; i++)
  1942. X        if ((*dp = *sp++) != NULL && ((*dp)->flag&DEFINED))
  1943. X            dp++;
  1944. X    i = dp - p;
  1945. X    qsortp((Void**)p, (size_t)i, tnamecmp);
  1946. X    p[i] = NULL;
  1947. X    return p;
  1948. X}
  1949. X
  1950. END_OF_FILE
  1951.   if test 3715 -ne `wc -c <'sh/table.c'`; then
  1952.     echo shar: \"'sh/table.c'\" unpacked with wrong size!
  1953.   fi
  1954.   # end of 'sh/table.c'
  1955. fi
  1956. if test -f 'sh/ulimit.c' -a "${1}" != "-c" ; then 
  1957.   echo shar: Will not clobber existing file \"'sh/ulimit.c'\"
  1958. else
  1959.   echo shar: Extracting \"'sh/ulimit.c'\" \(2799 characters\)
  1960.   sed "s/^X//" >'sh/ulimit.c' <<'END_OF_FILE'
  1961. X/*
  1962. X    ulimit -- handle "ulimit" builtin
  1963. X
  1964. X    Eric Gisin, September 1988
  1965. X    Adapted to PD KornShell. Removed AT&T code.
  1966. X
  1967. X    last edit:    06-Jun-1987    D A Gwyn
  1968. X
  1969. X    This started out as the BRL UNIX System V system call emulation
  1970. X    for 4.nBSD, and was later extended by Doug Kingston to handle
  1971. X    the extended 4.nBSD resource limits.  It now includes the code
  1972. X    that was originally under case SYSULIMIT in source file "xec.c".
  1973. X*/
  1974. X
  1975. Xstatic char *RCSid = "$Id: ulimit.c,v 3.2 89/03/27 15:52:19 egisin Exp $";
  1976. X
  1977. X#include <stddef.h>
  1978. X#include <errno.h>
  1979. X#include <signal.h>
  1980. X#include <setjmp.h>
  1981. X#if defined(_BSD) || defined(_BSD_SYSV)
  1982. X#include <sys/time.h>
  1983. X#include <sys/resource.h>
  1984. X#else
  1985. X#define    RLIMIT_FSIZE    2
  1986. X#endif
  1987. X#include "sh.h"
  1988. X
  1989. Xextern    long ulimit();
  1990. X
  1991. Xint
  1992. Xdo_ulimit(a1, a2)
  1993. X    char    *a1, *a2;
  1994. X{
  1995. X    register int    c;
  1996. X    long        i;
  1997. X#if defined(_BSD) || defined(_BSD_SYSV)
  1998. X    struct rlimit    limit;        /* data being gotten/set */
  1999. X    int        softonly = 0;    /* set => soft limit, clear => hard limit */
  2000. X    int        factor = 1024;    /* unit scaling (1K or 1) */
  2001. X#endif
  2002. X    int    command = RLIMIT_FSIZE;
  2003. X
  2004. X    if (a1 && (*a1 == '-'))        /* DAG -- Gould added first test */
  2005. X    {    c = *++a1;        /* DAG */
  2006. X#if defined(_BSD) || defined(_BSD_SYSV)
  2007. X        if (c >= 'A' && c <= 'Z')
  2008. X        {
  2009. X            ++softonly;
  2010. X            c += 'a' - 'A';    /* DAG -- map to lower-case */
  2011. X        }
  2012. X#endif
  2013. X        switch(c)
  2014. X        {
  2015. X#if defined(_BSD) || defined(_BSD_SYSV)
  2016. X            case 'c':
  2017. X                command = RLIMIT_CORE;
  2018. X                break;
  2019. X            case 'd':
  2020. X                command = RLIMIT_DATA;
  2021. X                break;
  2022. X            case 'm':
  2023. X                command = RLIMIT_RSS;
  2024. X                break;
  2025. X            case 's':
  2026. X                command = RLIMIT_STACK;
  2027. X                break;
  2028. X            case 't':
  2029. X                factor = 1;
  2030. X                command = RLIMIT_CPU;
  2031. X                break;
  2032. X#endif    /* _BSD || _BSD_SYSV */
  2033. X            case 'f':
  2034. X                command = RLIMIT_FSIZE;
  2035. X#if _BSD_SYSV
  2036. X                factor = 512;
  2037. X#endif
  2038. X                break;
  2039. X            default:
  2040. X#if _BSD
  2041. X                errorf("Usage: %s [-cdmstf] [limit]\n", "ulimit");
  2042. X#else
  2043. X                errorf("Usage: %s [-f] [limit]\n", "ulimit");
  2044. X#endif
  2045. X        }
  2046. X        a1 = a2;
  2047. X    }
  2048. X    if (a1)
  2049. X    {
  2050. X        i = 0;
  2051. X        while ((c = *a1++) >= '0' && c <= '9')
  2052. X        {
  2053. X            i = (i * 10) + (long)(c - '0');
  2054. X            if (i < 0)
  2055. X                goto Error;
  2056. X        }
  2057. X        if (c || i < 0)
  2058. X            goto Error;
  2059. X    }
  2060. X#if !(defined(_BSD) || defined(_BSD_SYSV))
  2061. X    else
  2062. X    {
  2063. X        i = -1;
  2064. X        command--;
  2065. X    }
  2066. X
  2067. X    if ((i = ulimit(command, i)) < 0L)
  2068. X        goto Error;
  2069. X
  2070. X    if (command != RLIMIT_FSIZE)
  2071. X        shellf("%ld\n", i);
  2072. X#else                    /* DPK -- generalized for 4.nBSD: */
  2073. X    if (getrlimit(command, &limit))
  2074. X        goto Error;    /* errno is already set */
  2075. X
  2076. X    if (a1)
  2077. X    {
  2078. X        limit.rlim_cur = i * factor;
  2079. X
  2080. X        if (!softonly)
  2081. X            limit.rlim_max = limit.rlim_cur;
  2082. X
  2083. X        if (setrlimit(command, &limit))
  2084. X            goto Error;
  2085. X    }
  2086. X    else
  2087. X    {
  2088. X        i = softonly ? limit.rlim_cur : limit.rlim_max;
  2089. X#if _BSD            /* DAG -- System V always prints an integer */
  2090. X        if (i == RLIM_INFINITY)
  2091. X            shellf("unlimited\n");
  2092. X        else
  2093. X#endif
  2094. X            shellf("%ld\n", i/factor);
  2095. X    }
  2096. X#endif    /* _BSD || _BSD_SYSV */
  2097. X    return 0;
  2098. X
  2099. X  Error:
  2100. X    errorf("bad ulimit\n");
  2101. X}
  2102. X
  2103. END_OF_FILE
  2104.   if test 2799 -ne `wc -c <'sh/ulimit.c'`; then
  2105.     echo shar: \"'sh/ulimit.c'\" unpacked with wrong size!
  2106.   fi
  2107.   # end of 'sh/ulimit.c'
  2108. fi
  2109. if test -f 'std/stdc/vprintf.c' -a "${1}" != "-c" ; then 
  2110.   echo shar: Will not clobber existing file \"'std/stdc/vprintf.c'\"
  2111. else
  2112.   echo shar: Extracting \"'std/stdc/vprintf.c'\" \(4964 characters\)
  2113.   sed "s/^X//" >'std/stdc/vprintf.c' <<'END_OF_FILE'
  2114. X#if __STDC__
  2115. X#include <stdarg.h>
  2116. X#else
  2117. X#include <varargs.h>
  2118. X#endif
  2119. X#include <stdio.h>
  2120. X
  2121. X#define    BUF    40        /* buffer for int -> string conversion */
  2122. X
  2123. Xint
  2124. X#if __STDC__
  2125. Xvprintf(Const char *fmt, va_list va) {
  2126. X#else
  2127. Xvprintf(fmt, va) char *fmt; va_list va; {
  2128. X#endif
  2129. X    return vfprintf(stdout, fmt, va);
  2130. X}
  2131. X
  2132. Xint
  2133. X#if __STDC__
  2134. Xvfprintf(register FILE *f, register Const char *fmt, register va_list va) {
  2135. X#else
  2136. Xvfprintf(f, fmt, va) register FILE *f; register char *fmt; register va_list va; {
  2137. X#endif
  2138. X    register int c;
  2139. X    int pos = 0;            /* todo: implement */
  2140. X
  2141. X    while ((c = *fmt++))
  2142. X        if (c == '%') {
  2143. X        long n;
  2144. X        register unsigned long u;
  2145. X        char buf [BUF+1];
  2146. X        register char *p = buf + BUF;
  2147. X        register enum {
  2148. X            FF_ALT = 0x01, /* #, alternate format */
  2149. X            FF_SHORT = 0x02, /* h, short arg */
  2150. X            FF_LONG = 0x04,    /* l, long arg */
  2151. X            FF_ZERO = 0x08,    /* 0, zero fill */
  2152. X            FF_LEFT = 0x10,    /* -, left adjust */
  2153. X            FF_PREC = 0x20,    /* .*, precision */
  2154. X            FF_NEG = 0x40,    /* signed arg */
  2155. X            FF_PUTS = 0x80,    /* fputs(p, f) */
  2156. X            FF_DEFAULT = 0
  2157. X        } flags = FF_DEFAULT;
  2158. X        int sign = '-';    /* sign: [ +-] */
  2159. X        int width = 0, prec = 0; /* width, precision */
  2160. X
  2161. X        *p = 0;
  2162. X
  2163. X        /* scan flag characters */
  2164. X        for (c = *fmt++; ; c = *fmt++) switch (c) {
  2165. X          case '0':
  2166. X            flags |= FF_ZERO;
  2167. X            break;
  2168. X
  2169. X          case '#':        /* alternate format */
  2170. X            flags |= FF_ALT;
  2171. X            break;
  2172. X
  2173. X          case ' ':        /* blank sign */
  2174. X            sign = ' ';
  2175. X            break;
  2176. X          case '+':        /* +/- sign */
  2177. X            sign = '+';
  2178. X            break;
  2179. X
  2180. X          case '-':        /* left just. */
  2181. X            flags |= FF_LEFT;
  2182. X            break;
  2183. X
  2184. X          default:
  2185. X            goto Frogs;
  2186. X        }
  2187. X      Frogs:
  2188. X
  2189. X        /* scan width */
  2190. X          if (c == '*') {        /* width from arg list */
  2191. X            width = va_arg(va, int);
  2192. X            c = *fmt++;
  2193. X        } else
  2194. X            while ('0' <= c && c <= '9') {
  2195. X                width = width*10 + (c-'0');
  2196. X                c = *fmt++;
  2197. X            }
  2198. X
  2199. X        if (c == '.') {        /* scan precision */
  2200. X            flags |= FF_PREC;
  2201. X            c = *fmt++;
  2202. X            if (c == '*') {    /* precision from arg list */
  2203. X                prec = va_arg(va, int);
  2204. X                c = *fmt++;
  2205. X            } else
  2206. X                while ('0' <= c && c <= '9') {
  2207. X                    prec = prec*10 + (c-'0');
  2208. X                    c = *fmt++;
  2209. X                }
  2210. X        }
  2211. X
  2212. X        /* length modifiers */
  2213. X        if (c == 'h') {
  2214. X            flags |= FF_SHORT;
  2215. X            c = *fmt++;
  2216. X        } else if (c == 'l') {
  2217. X            flags |= FF_LONG;
  2218. X            c = *fmt++;
  2219. X        }
  2220. X
  2221. X        /* do conversion */
  2222. X        switch (c) {
  2223. X          case '%':        /* %% -> % */
  2224. X            putc(c, f);
  2225. X            pos ++;
  2226. X            break;
  2227. X
  2228. X          case 'p':        /* pointer */
  2229. X            *--p = '}';
  2230. X            u = (unsigned long) va_arg(va, Void*);
  2231. X            do {
  2232. X                *--p = "0123456789ABCDEF"[u%16];
  2233. X                u /= 16;
  2234. X            } while (u != 0);
  2235. X            *--p = '{';
  2236. X            flags |= FF_PUTS;
  2237. X            break;
  2238. X
  2239. X          case 'n':        /* save position */
  2240. X            *va_arg(va, int*) = pos;
  2241. X            break;
  2242. X
  2243. X          case 'c':        /* character */
  2244. X            u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
  2245. X              : (flags&&FF_LONG) ? va_arg(va, unsigned long)
  2246. X              : va_arg(va, unsigned int);
  2247. X            *--p = u;
  2248. X            flags |= FF_PUTS;
  2249. X            break;
  2250. X
  2251. X          case 's':        /* string */
  2252. X            p = va_arg(va, char *);
  2253. X            if ((flags&FF_PREC) && strlen(p) > prec) {
  2254. X                pos += prec;
  2255. X                while (--prec >= 0)
  2256. X                    putc(*p++, f);
  2257. X                break;
  2258. X            }
  2259. X            flags |= FF_PUTS;
  2260. X            break;
  2261. X
  2262. X          case 'i': case 'd': case 'u': /* decimal */
  2263. X            if (c != 'u') {    /* signed */
  2264. X                n = (flags&FF_SHORT) ? va_arg(va, short)
  2265. X                  : (flags&&FF_LONG) ? va_arg(va, long)
  2266. X                  : va_arg(va, int);
  2267. X                if (n < 0)
  2268. X                    flags |= FF_NEG;
  2269. X                u = (n < 0) ? -n : n;
  2270. X            } else
  2271. X                u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
  2272. X                  : (flags&&FF_LONG) ? va_arg(va, unsigned long)
  2273. X                  : va_arg(va, unsigned int);
  2274. X            do {
  2275. X                *--p = '0' + u%10;
  2276. X                u /= 10;
  2277. X            } while (u != 0);
  2278. X            prec -= buf+BUF - p;
  2279. X            while (--prec >= 0)
  2280. X                *--p = '0';
  2281. X            if (flags&FF_NEG)
  2282. X                *--p = '-';
  2283. X            else
  2284. X                if (sign != '-')
  2285. X                    *--p = (sign == '+') ? '+' : ' ';
  2286. X            flags |= FF_PUTS;
  2287. X            break;
  2288. X
  2289. X          case 'x': case 'X':    /* hex, Hex */
  2290. X            u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
  2291. X              : (flags&&FF_LONG) ? va_arg(va, unsigned long)
  2292. X              : va_arg(va, unsigned int);
  2293. X            do {
  2294. X                *--p = "0123456789ABCDEF"[u%16];
  2295. X                u /= 16;
  2296. X            } while (u != 0);
  2297. X            prec -= buf+BUF - p;
  2298. X            while (--prec >= 0)
  2299. X                *--p = '0';
  2300. X            if (flags&&FF_ALT)
  2301. X                *--p = 'x', *--p = '0';
  2302. X            flags |= FF_PUTS;
  2303. X            break;
  2304. X
  2305. X          case 'o':        /* octal */
  2306. X            u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
  2307. X              : (flags&&FF_LONG) ? va_arg(va, unsigned long)
  2308. X              : va_arg(va, unsigned int);
  2309. X            do {
  2310. X                *--p = '0' + u%8;
  2311. X                u /= 8;
  2312. X            } while (u != 0);
  2313. X            prec -= buf+BUF - p;
  2314. X            while (--prec >= 0)
  2315. X                *--p = '0';
  2316. X            if (flags&&FF_ALT && *p != '0')
  2317. X                *--p = '0';
  2318. X            flags |= FF_PUTS;
  2319. X            break;
  2320. X
  2321. X          default:        /* todo: error */
  2322. X            putc('%', f);
  2323. X            putc(c, f);
  2324. X            pos += 2;
  2325. X            break;
  2326. X        }
  2327. X
  2328. X        /* copy adjusted string "p" to output */
  2329. X        if (flags&FF_PUTS) {
  2330. X            int len = strlen(p);
  2331. X            int pad = width - len;
  2332. X            if (!(flags&FF_LEFT))
  2333. X                while (--pad >= 0)
  2334. X                    putc((flags&FF_ZERO) ? '0' : ' ', f);
  2335. X            while (*p)
  2336. X                putc(*p++, f);
  2337. X            if ((flags&FF_LEFT))
  2338. X                while (--pad >= 0)
  2339. X                    putc(' ', f);
  2340. X            pos += (len < width) ? width : len;
  2341. X        }
  2342. X        } else {            /* ordinary character */
  2343. X        putc(c, f);
  2344. X        pos ++;
  2345. X        }
  2346. X    return pos;
  2347. X}
  2348. X
  2349. END_OF_FILE
  2350.   if test 4964 -ne `wc -c <'std/stdc/vprintf.c'`; then
  2351.     echo shar: \"'std/stdc/vprintf.c'\" unpacked with wrong size!
  2352.   fi
  2353.   # end of 'std/stdc/vprintf.c'
  2354. fi
  2355. echo shar: End of archive 6 \(of 9\).
  2356. cp /dev/null ark6isdone
  2357. MISSING=""
  2358. for I in 1 2 3 4 5 6 7 8 9 ; do
  2359.     if test ! -f ark${I}isdone ; then
  2360.     MISSING="${MISSING} ${I}"
  2361.     fi
  2362. done
  2363. if test "${MISSING}" = "" ; then
  2364.     echo You have unpacked all 9 archives.
  2365.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2366. else
  2367.     echo You still must unpack the following archives:
  2368.     echo "        " ${MISSING}
  2369. fi
  2370. exit 0
  2371. exit 0 # Just in case...
  2372. -- 
  2373. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2374. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2375. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2376. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2377.