home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume30 / rc / part02 < prev    next >
Encoding:
Text File  |  1992-05-29  |  61.5 KB  |  2,696 lines

  1. Newsgroups: comp.sources.misc
  2. From: byron@archone.tamu.edu (Byron Rakitzis)
  3. Subject:  v30i025:  rc - A Plan 9 shell reimplementation, v1.4, Part02/07
  4. Message-ID: <1992May30.031607.5307@sparky.imd.sterling.com>
  5. X-Md4-Signature: 1766d0bd25c15f101d33191f5df07107
  6. Date: Sat, 30 May 1992 03:16:07 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: byron@archone.tamu.edu (Byron Rakitzis)
  10. Posting-number: Volume 30, Issue 25
  11. Archive-name: rc/part02
  12. Environment: UNIX
  13. Supersedes: rc: Volume 23, Issue 61-66
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  hash.c lex.c open.c rc.1
  22. # Wrapped by kent@sparky on Fri May 29 20:55:23 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 2 (of 7)."'
  26. if test -f 'hash.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'hash.c'\"
  28. else
  29.   echo shar: Extracting \"'hash.c'\" \(6754 characters\)
  30.   sed "s/^X//" >'hash.c' <<'END_OF_FILE'
  31. X/* hash.c: hash table support for functions and variables. */
  32. X
  33. X/*
  34. X   Functions and variables are cached in both internal and external
  35. X   form for performance. Thus a variable which is never "dereferenced"
  36. X   with a $ is passed on to rc's children untouched. This is not so
  37. X   important for variables, but is a big win for functions, where a call
  38. X   to yyparse() is involved.
  39. X*/
  40. X
  41. X#include "rc.h"
  42. X#include "sigmsgs.h"
  43. X
  44. Xstatic bool var_exportable(char *);
  45. Xstatic bool fn_exportable(char *);
  46. Xstatic int hash(char *, int);
  47. Xstatic int find(char *, Htab *, int);
  48. Xstatic void free_fn(Function *);
  49. X
  50. XHtab *fp;
  51. XHtab *vp;
  52. Xstatic int fused, fsize, vused, vsize;
  53. Xstatic char **env;
  54. Xstatic int bozosize;
  55. Xstatic int envsize;
  56. Xstatic bool env_dirty = TRUE;
  57. Xstatic char *dead = "";
  58. X
  59. X#define HASHSIZE 64 /* rc was debugged with HASHSIZE == 2; 64 is about right for normal use */
  60. X
  61. Xextern void inithash() {
  62. X    Htab *fpp, *vpp;
  63. X    int i;
  64. X    fp = ealloc(sizeof(Htab) * HASHSIZE);
  65. X    vp = ealloc(sizeof(Htab) * HASHSIZE);
  66. X    fused = vused = 0;
  67. X    fsize = vsize = HASHSIZE;
  68. X    for (vpp = vp, fpp = fp, i = 0; i < HASHSIZE; i++, vpp++, fpp++)
  69. X        vpp->name = fpp->name = NULL;
  70. X}
  71. X
  72. X#define ADV()   {if ((c = *s++) == '\0') break;}
  73. X
  74. X/* hash function courtesy of paul haahr */
  75. X
  76. Xstatic int hash(char *s, int size) {
  77. X    int c, n = 0;
  78. X    while (1) {
  79. X        ADV();
  80. X        n += (c << 17) ^ (c << 11) ^ (c << 5) ^ (c >> 1);
  81. X        ADV();
  82. X        n ^= (c << 14) + (c << 7) + (c << 4) + c;
  83. X        ADV();
  84. X        n ^= (~c << 11) | ((c << 3) ^ (c >> 1));
  85. X        ADV();
  86. X        n -= (c << 16) | (c << 9) | (c << 2) | (c & 3);
  87. X    }
  88. X    if (n < 0)
  89. X        n = ~n;
  90. X    return n & (size - 1); /* need power of 2 size */
  91. X}
  92. X
  93. Xstatic bool rehash(Htab *ht) {
  94. X    int i, j, size;
  95. X    int newsize, newused;
  96. X    Htab *newhtab;
  97. X    if (ht == fp) {
  98. X        if (fsize > 2 * fused)
  99. X            return FALSE;
  100. X        size = fsize;
  101. X    } else {
  102. X        if (vsize > 2 * vused)
  103. X            return FALSE;
  104. X        size = vsize;
  105. X    }
  106. X    newsize = 2 * size;
  107. X    newhtab = ealloc(newsize * sizeof(Htab));
  108. X    for (i = 0; i < newsize; i++)
  109. X        newhtab[i].name = NULL;
  110. X    for (i = newused = 0; i < size; i++)
  111. X        if (ht[i].name != NULL && ht[i].name != dead) {
  112. X            newused++;
  113. X            j = hash(ht[i].name, newsize);
  114. X            while (newhtab[j].name != NULL) {
  115. X                j++;
  116. X                j &= (newsize - 1);
  117. X            }
  118. X            newhtab[j].name = ht[i].name;
  119. X            newhtab[j].p = ht[i].p;
  120. X        }
  121. X    if (ht == fp) {
  122. X        fused = newused;
  123. X        fp = newhtab;
  124. X        fsize = newsize;
  125. X    } else {
  126. X        vused = newused;
  127. X        vp = newhtab;
  128. X        vsize = newsize;
  129. X    }
  130. X    efree(ht);
  131. X    return TRUE;
  132. X}
  133. X
  134. X#define varfind(s) find(s, vp, vsize)
  135. X#define fnfind(s) find(s, fp, fsize)
  136. X
  137. Xstatic int find(char *s, Htab *ht, int size) {
  138. X    int h = hash(s, size);
  139. X    while (ht[h].name != NULL && !streq(ht[h].name, s)) {
  140. X        h++;
  141. X        h &= size - 1;
  142. X    }
  143. X    return h;
  144. X}
  145. X
  146. Xextern void *lookup(char *s, Htab *ht) {
  147. X    int h = find(s, ht, ht == fp ? fsize : vsize);
  148. X    return (ht[h].name == NULL) ? NULL : ht[h].p;
  149. X}
  150. X
  151. Xextern Function *get_fn_place(char *s) {
  152. X    int h = fnfind(s);
  153. X    env_dirty = TRUE;
  154. X    if (fp[h].name == NULL) {
  155. X        if (rehash(fp))
  156. X            h = fnfind(s);
  157. X        fused++;
  158. X        fp[h].name = ecpy(s);
  159. X        fp[h].p = enew(Function);
  160. X    } else
  161. X        free_fn(fp[h].p);
  162. X    return fp[h].p;
  163. X}
  164. X
  165. Xextern Variable *get_var_place(char *s, bool stack) {
  166. X    Variable *new;
  167. X    int h = varfind(s);
  168. X
  169. X    env_dirty = TRUE;
  170. X
  171. X    if (vp[h].name == NULL) {
  172. X        if (rehash(vp))
  173. X            h = varfind(s);
  174. X        vused++;
  175. X        vp[h].name = ecpy(s);
  176. X        vp[h].p = enew(Variable);
  177. X        ((Variable *)vp[h].p)->n = NULL;
  178. X        return vp[h].p;
  179. X    } else {
  180. X        if (stack) {    /* increase the stack by 1 */
  181. X            new = enew(Variable);
  182. X            new->n = vp[h].p;
  183. X            return vp[h].p = new;
  184. X        } else {    /* trample the top of the stack */
  185. X            new = vp[h].p;
  186. X            efree(new->extdef);
  187. X            listfree(new->def);
  188. X            return new;
  189. X        }
  190. X    }
  191. X}
  192. X
  193. Xextern void delete_fn(char *s) {
  194. X    int h = fnfind(s);
  195. X    if (fp[h].name == NULL)
  196. X        return; /* not found */
  197. X    env_dirty = TRUE;
  198. X    free_fn(fp[h].p);
  199. X    efree(fp[h].p);
  200. X    efree(fp[h].name);
  201. X    if (fp[(h+1)&(fsize-1)].name == NULL) {
  202. X        --fused;
  203. X        fp[h].name = NULL;
  204. X    } else {
  205. X        fp[h].name = dead;
  206. X    }
  207. X}
  208. X
  209. Xextern void delete_var(char *s, bool stack) {
  210. X    int h = varfind(s);
  211. X    Variable *v;
  212. X    if (vp[h].name == NULL)
  213. X        return; /* not found */
  214. X    env_dirty = TRUE;
  215. X    v = vp[h].p;
  216. X    efree(v->extdef);
  217. X    listfree(v->def);
  218. X    if (v->n != NULL) { /* This is the top of a stack */
  219. X        if (stack) { /* pop */
  220. X            vp[h].p = v->n;
  221. X            efree(v);
  222. X        } else { /* else just empty */
  223. X            v->extdef = NULL;
  224. X            v->def = NULL;
  225. X        }
  226. X    } else { /* needs to be removed from the hash table */
  227. X        efree(v);
  228. X        efree(vp[h].name);
  229. X        if (vp[(h+1)&(vsize-1)].name == NULL) {
  230. X            --vused;
  231. X            vp[h].name = NULL;
  232. X        } else {
  233. X            vp[h].name = dead;
  234. X        }
  235. X    }
  236. X}
  237. X
  238. Xstatic void free_fn(Function *f) {
  239. X    treefree(f->def);
  240. X    efree(f->extdef);
  241. X}
  242. X
  243. Xextern void initenv(char **envp) {
  244. X    int n;
  245. X    for (n = 0; envp[n] != NULL; n++)
  246. X        ;
  247. X    n++; /* one for the null terminator */
  248. X    if (n < HASHSIZE)
  249. X        n = HASHSIZE;
  250. X    env = ealloc((envsize = 2 * n) * sizeof (char *));
  251. X    for (; *envp != NULL; envp++)
  252. X        if (strncmp(*envp, "fn_", conststrlen("fn_")) == 0) {
  253. X            if (!dashpee)
  254. X                fnassign_string(*envp);
  255. X        } else {
  256. X            if (!varassign_string(*envp)) /* add to bozo env */
  257. X                env[bozosize++] = *envp;
  258. X        }
  259. X}
  260. X
  261. Xstatic bool var_exportable(char *s) {
  262. X    static char *notforexport[] = {
  263. X        "apid", "pid", "apids", "*", "ifs"
  264. X    };
  265. X    int i;
  266. X    for (i = 0; i < arraysize(notforexport); i++)
  267. X        if (streq(s, notforexport[i]))
  268. X            return FALSE;
  269. X    return TRUE;
  270. X}
  271. X
  272. Xstatic bool fn_exportable(char *s) {
  273. X    int i;
  274. X    if (strncmp(s, "sig", conststrlen("sig")) == 0) { /* small speed hack */
  275. X        for (i = 0; i < NUMOFSIGNALS; i++)
  276. X            if (streq(s, signals[i].name))
  277. X                return FALSE;
  278. X        if (streq(s, "sigexit"))
  279. X            return FALSE;
  280. X    }
  281. X    return TRUE;
  282. X}
  283. X
  284. Xextern char **makeenv() {
  285. X    int ep, i;
  286. X    char *v;
  287. X    if (!env_dirty)
  288. X        return env;
  289. X    env_dirty = FALSE;
  290. X    ep = bozosize;
  291. X    if (vsize + fsize + 1 + bozosize > envsize) {
  292. X        envsize = 2 * (bozosize + vsize + fsize + 1);
  293. X        env = erealloc(env, envsize * sizeof(char *));
  294. X    }
  295. X    for (i = 0; i < vsize; i++) {
  296. X        if (vp[i].name == NULL || vp[i].name == dead || !var_exportable(vp[i].name))
  297. X            continue;
  298. X        v = varlookup_string(vp[i].name);
  299. X        if (v != NULL)
  300. X            env[ep++] = v;
  301. X    }
  302. X    for (i = 0; i < fsize; i++) {
  303. X        if (fp[i].name == NULL || fp[i].name == dead || !fn_exportable(fp[i].name))
  304. X            continue;
  305. X        env[ep++] = fnlookup_string(fp[i].name);
  306. X    }
  307. X    env[ep] = NULL;
  308. X    qsort(env, (SIZE_T) ep, sizeof(char *), starstrcmp);
  309. X    return env;
  310. X}
  311. X
  312. Xextern void whatare_all_vars() {
  313. X    int i;
  314. X    List *s;
  315. X    for (i = 0; i < vsize; i++)
  316. X        if (vp[i].name != NULL && (s = varlookup(vp[i].name)) != NULL)
  317. X            prettyprint_var(1, vp[i].name, s);
  318. X    for (i = 0; i < fsize; i++)
  319. X        if (fp[i].name != NULL && fp[i].name != dead)
  320. X            prettyprint_fn(1, fp[i].name, fnlookup(fp[i].name));
  321. X}
  322. X
  323. X/* fake getenv() for readline() follows: */
  324. X
  325. X#ifdef READLINE
  326. Xextern char *getenv(const char *name) {
  327. X    List *s;
  328. X    if (name == NULL || vp == NULL || (s = varlookup((char *) name)) == NULL)
  329. X        return NULL;
  330. X    return s->w;
  331. X}
  332. X#endif
  333. END_OF_FILE
  334.   if test 6754 -ne `wc -c <'hash.c'`; then
  335.     echo shar: \"'hash.c'\" unpacked with wrong size!
  336.   fi
  337.   # end of 'hash.c'
  338. fi
  339. if test -f 'lex.c' -a "${1}" != "-c" ; then 
  340.   echo shar: Will not clobber existing file \"'lex.c'\"
  341. else
  342.   echo shar: Extracting \"'lex.c'\" \(10427 characters\)
  343.   sed "s/^X//" >'lex.c' <<'END_OF_FILE'
  344. X/* lex.c: rc's lexical analyzer */
  345. X
  346. X#include "rc.h"
  347. X#include "y.tab.h"
  348. X
  349. X/*
  350. X    Special characters (i.e., "non-word") in rc:
  351. X        \t \n # ; & | ^ $ = ~ ` ' { } @ ! ( ) < > \
  352. X
  353. X    The lexical analyzer is fairly straightforward. The only really
  354. X    unclean part concerns backslash continuation and "double
  355. X    backslashes". A backslash followed by a newline is treated as a
  356. X    space, otherwise backslash is not a special characeter (i.e.,
  357. X    it can be part of a word).  This introduces a host of unwanted
  358. X    special cases. In our case, \ cannot be a word character, since
  359. X    we wish to read in all word characters in a tight loop.
  360. X
  361. X    Note: to save the trouble of declaring these arrays with TRUEs
  362. X    and FALSEs, I am assuming that FALSE = 0, TRUE = 1. (and so is
  363. X    it declared in rc.h)
  364. X*/
  365. X
  366. X#define BUFSIZE ((SIZE_T) 1000)    /*    malloc hates power of 2 buffers? */
  367. X#define BUFMAX (8 * BUFSIZE)    /*     How big the buffer can get before we re-allocate the
  368. X                    space at BUFSIZE again. Premature optimization? Maybe.
  369. X                */
  370. X
  371. Xtypedef enum wordstates {
  372. X    NW, RW, KW /* "nonword", "realword", "keyword" */
  373. X} wordstates;
  374. X
  375. Xstatic void getpair(int);
  376. X
  377. Xint lineno;
  378. X
  379. Xconst char nw[] = {
  380. X    1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  381. X    1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
  382. X    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
  383. X    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
  384. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  385. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  386. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  387. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  388. X};
  389. X
  390. Xconst char dnw[] = {
  391. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  392. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
  393. X    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
  394. X    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
  395. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  396. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  397. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  398. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  399. X};
  400. X
  401. Xstatic SIZE_T bufsize = BUFSIZE;
  402. Xstatic char *realbuf = NULL;
  403. Xstatic bool newline = FALSE;
  404. Xstatic bool errset = FALSE;
  405. Xstatic bool prerror = FALSE;
  406. Xstatic wordstates w = NW;
  407. Xstatic int fd_left, fd_right;
  408. X
  409. X#define checkfreecaret {if (w != NW) { w = NW; ugchar(c); return '^'; }}
  410. X
  411. Xenum filedescriptors {
  412. X    UNSET = -9, CLOSED = -1
  413. X};
  414. X
  415. Xextern int yylex() {
  416. X    static bool dollar = FALSE;
  417. X    bool saw_meta = FALSE;
  418. X    int c;
  419. X    SIZE_T i;            /* The purpose of all these local assignments is to    */
  420. X    const char *meta;        /* allow optimizing compilers like gcc to load these    */
  421. X    char *buf = realbuf;        /* values into registers. On a sparc this is a        */
  422. X    YYSTYPE *y = &yylval;        /* win, in code size *and* execution time        */
  423. X    if (errset) {
  424. X        errset = FALSE;
  425. X        return '\n';
  426. X    }
  427. X    /* rc variable-names may contain only alnum, '*' and '_', so use dnw if we are scanning one. */
  428. X    meta = (dollar ? dnw : nw);
  429. X    dollar = FALSE;
  430. X    if (newline) {
  431. X        --lineno; /* slight space optimization; print_prompt2() always increments lineno */
  432. X        print_prompt2();
  433. X        newline = FALSE;
  434. X    }
  435. Xtop:    while ((c = gchar()) == ' ' || c == '\t')
  436. X        w = NW;
  437. X    if (c == EOF)
  438. X        return END;
  439. X    if (!meta[(unsigned char) c]) {    /* it's a word or keyword. */
  440. X        checkfreecaret;
  441. X        w = RW;
  442. X        i = 0;
  443. X    read:    do {
  444. X            buf[i++] = c;
  445. X            if (c == '?' || c == '[' || c == '*')
  446. X                saw_meta = TRUE;
  447. X            if (i >= bufsize)
  448. X                buf = realbuf = erealloc(buf, bufsize *= 2);
  449. X        } while ((c = gchar()) != EOF && !meta[(unsigned char) c]);
  450. X        while (c == '\\') {
  451. X            if ((c = gchar()) == '\n') {
  452. X                print_prompt2();
  453. X                c = ' '; /* Pretend a space was read */
  454. X                break;
  455. X            } else {
  456. X    bs:            if (meta != dnw) { /* all words but varnames may have a bslash */
  457. X                    buf[i++] = '\\';
  458. X                    if (i >= bufsize)
  459. X                        buf = realbuf = erealloc(buf, bufsize *= 2);
  460. X                    if (!meta[(unsigned char) c])
  461. X                        goto read;
  462. X                } else {
  463. X                    ugchar(c);
  464. X                    c = '\\';
  465. X                    break;
  466. X                }
  467. X            }
  468. X        }
  469. X        ugchar(c);
  470. X        buf[i] = '\0';
  471. X        w = KW;
  472. X        if (i == 2) {
  473. X            if (*buf == 'i' && buf[1] == 'f') return IF;
  474. X            if (*buf == 'f' && buf[1] == 'n') return FN;
  475. X            if (*buf == 'i' && buf[1] == 'n') return IN;
  476. X        }
  477. X        if (streq(buf, "for")) return FOR;
  478. X        if (streq(buf, "else")) return ELSE;
  479. X        if (streq(buf, "switch")) return SWITCH;
  480. X        if (streq(buf, "while")) return WHILE;
  481. X        if (streq(buf, "case")) return CASE;
  482. X        w = RW;
  483. X        y->word.w = ncpy(buf);
  484. X        if (saw_meta) {
  485. X            char *r, *s;
  486. X
  487. X            y->word.m = nalloc(strlen(buf) + 1);
  488. X            for (r = buf, s = y->word.m; *r != '\0'; r++, s++)
  489. X                *s = (*r == '?' || *r == '[' || *r == '*');
  490. X        } else {
  491. X            y->word.m = NULL;
  492. X        }
  493. X        return WORD;
  494. X    }
  495. X    if (c == '`' || c == '!' || c == '@' || c == '~' || c == '$' || c == '\'') {
  496. X        checkfreecaret;
  497. X        if (c == '!' || c == '@' || c == '~')
  498. X            w = KW;
  499. X    }
  500. X    switch (c) {
  501. X    case '\0':
  502. X        pr_error("warning: null character ignored");
  503. X        goto top;
  504. X    case '!':
  505. X        return BANG;
  506. X    case '@':
  507. X        return SUBSHELL;
  508. X    case '~':
  509. X        return TWIDDLE;
  510. X    case '`':
  511. X        c = gchar();
  512. X        if (c == '`')
  513. X            return BACKBACK;
  514. X        ugchar(c);
  515. X        return '`';
  516. X    case '$':
  517. X        dollar = TRUE;
  518. X        c = gchar();
  519. X        if (c == '#')
  520. X            return COUNT;
  521. X        if (c == '^')
  522. X            return FLAT;
  523. X        ugchar(c);
  524. X        return '$';
  525. X    case '\'':
  526. X        w = RW;
  527. X        i = 0;
  528. X        do {
  529. X            buf[i++] = c;
  530. X            if (c == '\n')
  531. X                print_prompt2();
  532. X            if (c == EOF) {
  533. X                w = NW;
  534. X                scanerror("eof in quoted string");
  535. X                return HUH;
  536. X            }
  537. X            if (i >= bufsize)
  538. X                buf = realbuf = erealloc(buf, bufsize *= 2);
  539. X        } while ((c = gchar()) != '\'' || (c = gchar()) == '\''); /* quote "'" thus: 'how''s it going?' */
  540. X        ugchar(c);
  541. X        buf[i] = '\0';
  542. X        y->word.w = ncpy(buf);
  543. X        y->word.m = NULL;
  544. X        return WORD;
  545. X    case '\\':
  546. X        if ((c = gchar()) == '\n') {
  547. X            print_prompt2();
  548. X            goto top; /* Pretend it was just another space. */
  549. X        }
  550. X        ugchar(c);
  551. X        c = '\\';
  552. X        checkfreecaret;
  553. X        c = gchar();
  554. X        i = 0;
  555. X        goto bs;
  556. X    case '(':
  557. X        if (w == RW) /* SUB's happen only after real words, not keyowrds, so if () and while () work */
  558. X            c = SUB;
  559. X        w = NW;
  560. X        return c;
  561. X    case '#':
  562. X        while ((c = gchar()) != '\n') /* skip comment until newline */
  563. X            if (c == EOF)
  564. X                return END;
  565. X        /* FALLTHROUGH */
  566. X    case '\n':
  567. X        lineno++;
  568. X        newline = TRUE;
  569. X        /* FALLTHROUGH */
  570. X    case ';':
  571. X    case '^':
  572. X    case ')':
  573. X    case '=':
  574. X    case '{': case '}':
  575. X        w = NW;
  576. X        return c;
  577. X    case '&':
  578. X        w = NW;
  579. X        c = gchar();
  580. X        if (c == '&')
  581. X            return ANDAND;
  582. X        ugchar(c);
  583. X        return '&';
  584. X    case '|':
  585. X        w = NW;
  586. X        c = gchar();
  587. X        if (c == '|')
  588. X            return OROR;
  589. X        getpair(c);
  590. X        if (errset)
  591. X            return HUH;
  592. X        if ((y->pipe.left = fd_left) == UNSET)
  593. X            y->pipe.left = 1;                /* default to fd 1 */
  594. X        if ((y->pipe.right = fd_right) == UNSET)
  595. X            y->pipe.right = 0;                /* default to fd 0 */
  596. X        if (y->pipe.right == CLOSED) {
  597. X            scanerror("expected digit after '='");        /* can't close a pipe */
  598. X            return HUH;
  599. X        }
  600. X        return PIPE;
  601. X    case '>':
  602. X        c = gchar();
  603. X        if (c == '>') {
  604. X            c = gchar();
  605. X            y->redir.type = rAppend;
  606. X        } else
  607. X            y->redir.type = rCreate;
  608. X        y->redir.fd = 1;
  609. X        goto common;
  610. X    case '<':
  611. X        c = gchar();
  612. X        if (c == '<') {
  613. X            c = gchar();
  614. X            if (c == '<') {
  615. X                c = gchar();
  616. X                y->redir.type = rHerestring;
  617. X            } else {
  618. X                y->redir.type = rHeredoc;
  619. X            }
  620. X        } else
  621. X            y->redir.type = rFrom;
  622. X        y->redir.fd = 0;
  623. X    common:
  624. X        w = NW;
  625. X        getpair(c);
  626. X        if (errset)
  627. X            return HUH;
  628. X        if (fd_right == UNSET) { /* redirection, not dup */
  629. X            if (fd_left != UNSET) {
  630. X                y->redir.fd = fd_left;
  631. X                return SREDIR;
  632. X            }
  633. X            return (y->redir.type == rFrom || y->redir.type == rCreate) ? REDIR : SREDIR;
  634. X        } else { /* dup; recast yylval */
  635. X            y->dup.type = y->redir.type;
  636. X            y->dup.left = fd_left;
  637. X            y->dup.right = fd_right;
  638. X            return DUP;
  639. X        }
  640. X    default:
  641. X        w = NW;
  642. X        return c; /* don't know what it is, let yacc barf on it */
  643. X    }
  644. X}
  645. X
  646. Xextern void yyerror(const char *s) {
  647. X    char *tok;
  648. X    if (prerror) { /* don't print "syntax error" if there's a more informative scanerror */
  649. X        prerror = FALSE;
  650. X        return;
  651. X    }
  652. X    if (!interactive) {
  653. X        if (w != NW)
  654. X            tok = realbuf;
  655. X        else if (last == EOF)
  656. X            tok = "eof";
  657. X        else if (last == '\n')
  658. X            tok = "end of line";
  659. X        else
  660. X            tok = nprint((last < 32 || last > 126) ? "(decimal %d)" : "'%c'", last);
  661. X        fprint(2, "line %d: %s near %s\n", lineno - (last == '\n'), s, tok);
  662. X    } else
  663. X        fprint(2, "%s\n", s);
  664. X}
  665. X
  666. Xextern void scanerror(char *s) {
  667. X    flushu(); /* flush upto newline */
  668. X    yyerror(s);
  669. X    errset = prerror = TRUE;
  670. X}
  671. X
  672. Xextern void inityy() {
  673. X    newline = FALSE;
  674. X    w = NW;
  675. X    hq = NULL;
  676. X    /* return memory to the system if the buffer got too large */
  677. X    if (bufsize > BUFMAX && realbuf != NULL) {
  678. X        efree(realbuf);
  679. X        bufsize = BUFSIZE;
  680. X        realbuf = ealloc(bufsize);
  681. X    } else if (realbuf == NULL)
  682. X        realbuf = ealloc(bufsize);
  683. X}
  684. X
  685. Xextern void print_prompt2() {
  686. X    lineno++;
  687. X#ifdef READLINE
  688. X    prompt = prompt2;
  689. X#else
  690. X    if (interactive)
  691. X        fprint(2, "%s", prompt2);
  692. X#endif
  693. X}
  694. X
  695. X/*
  696. X   Scan in a pair of integers for redirections like >[2=1]. CLOSED represents a closed file
  697. X   descriptor (i.e., >[2=]) and UNSET represents an undesignated file descriptor (e.g.,
  698. X   >[2] is represented as (2,UNSET).
  699. X
  700. X   This function makes use of unsigned compares to make range tests in one compare operation.
  701. X*/
  702. X
  703. Xstatic void getpair(int c) {
  704. X    int n;
  705. X    fd_left = fd_right = UNSET;
  706. X    if (c != '[') {
  707. X        ugchar(c);
  708. X        return;
  709. X    }
  710. X    if ((unsigned int) (n = gchar() - '0') > 9) {
  711. X        scanerror("expected digit after '['");
  712. X        return;
  713. X    }
  714. X    while ((unsigned int) (c = gchar() - '0') <= 9)
  715. X        n = n * 10 + c;
  716. X    fd_left = n;
  717. X    c += '0';
  718. X    switch (c) {
  719. X    default:
  720. X        scanerror("expected '=' or ']' after digit");
  721. X        return;
  722. X    case ']':
  723. X        return;
  724. X    case '=':
  725. X        if ((unsigned int) (n = gchar() - '0') > 9) {
  726. X            if (n != ']' - '0') {
  727. X                scanerror("expected digit or ']' after '='");
  728. X                return;
  729. X            }
  730. X            fd_right = CLOSED;
  731. X        } else {
  732. X            while ((unsigned int) (c = gchar() - '0') <= 9)
  733. X                n = n * 10 + c;
  734. X            if (c != ']' - '0') {
  735. X                scanerror("expected ']' after digit");
  736. X                return;
  737. X            }
  738. X            fd_right = n;
  739. X        }
  740. X    }
  741. X}
  742. END_OF_FILE
  743.   if test 10427 -ne `wc -c <'lex.c'`; then
  744.     echo shar: \"'lex.c'\" unpacked with wrong size!
  745.   fi
  746.   # end of 'lex.c'
  747. fi
  748. if test -f 'open.c' -a "${1}" != "-c" ; then 
  749.   echo shar: Will not clobber existing file \"'open.c'\"
  750. else
  751.   echo shar: Extracting \"'open.c'\" \(703 characters\)
  752.   sed "s/^X//" >'open.c' <<'END_OF_FILE'
  753. X/* open.c: to insulate <fcntl.h> from the rest of rc. */
  754. X
  755. X#include <fcntl.h>
  756. X#include "rc.h"
  757. X
  758. X/* prototype for open() follows. comment out if necessary */
  759. X
  760. X/*extern int open(const char *, int,...);*/
  761. X
  762. X/*
  763. X   Opens a file with the necessary flags. Assumes the following
  764. X   declaration for redirtype:
  765. X
  766. X    enum redirtype {
  767. X        rFrom, rCreate, rAppend, rHeredoc, rHerestring
  768. X    };
  769. X*/
  770. X
  771. Xstatic const int mode_masks[] = {
  772. X    /* rFrom */    O_RDONLY,
  773. X    /* rCreate */    O_TRUNC | O_CREAT | O_WRONLY,
  774. X    /* rAppend */    O_APPEND | O_CREAT | O_WRONLY
  775. X};
  776. X
  777. Xextern int rc_open(const char *name, redirtype m) {
  778. X    if ((unsigned) m >= arraysize(mode_masks))
  779. X        panic("bad mode passed to rc_open");
  780. X    return open(name, mode_masks[m], 0666);
  781. X}
  782. END_OF_FILE
  783.   if test 703 -ne `wc -c <'open.c'`; then
  784.     echo shar: \"'open.c'\" unpacked with wrong size!
  785.   fi
  786.   # end of 'open.c'
  787. fi
  788. if test -f 'rc.1' -a "${1}" != "-c" ; then 
  789.   echo shar: Will not clobber existing file \"'rc.1'\"
  790. else
  791.   echo shar: Extracting \"'rc.1'\" \(39683 characters\)
  792.   sed "s/^X//" >'rc.1' <<'END_OF_FILE'
  793. X.\" rc.1
  794. X.\"-------
  795. X.\" Man page portability notes
  796. X.\"
  797. X.\" These are some notes on conventions to maintain for greatest
  798. X.\" portability of this man page to various other versions of
  799. X.\" nroff.
  800. X.\"
  801. X.\" When you want a \ to appear in the output, use \e in the man page.
  802. X.\" (NOTE this comes up in the rc grammar, where to print out '\n' the
  803. X.\" man page must contain '\en'.)
  804. X.\"
  805. X.\" Evidently not all versions of nroff allow the omission of the
  806. X.\" terminal " on a macro argument.  Thus what could be written
  807. X.\"
  808. X.\" .Cr "exec >[2] err.out
  809. X.\"
  810. X.\" in true nroffs must be written
  811. X.\"
  812. X.\" .Cr "exec >[2] err.out"
  813. X.\"
  814. X.\" instead.
  815. X.\"
  816. X.\" Use symbolic font names (e.g. R, I, B) instead of the standard
  817. X.\" font positions 1, 2, 3.  Note that for Xf to work the standard
  818. X.\" font names must be single characters.
  819. X.\"
  820. X.\" Not all man macros have the RS and RE requests (I altered the Ds
  821. X.\" and De macros and the calls to Ds accordingly).
  822. X.\"
  823. X.\" Thanks to Michael Haardt (u31b3hs@cip-s01.informatik.rwth-aachen.de)
  824. X.\" for pointing out these problems.
  825. X.\"
  826. X.\" Note that sentences should end at the end of a line.  nroff and
  827. X.\" troff will supply the correct intersentence spacing, but only if
  828. X.\" the sentences end at the end of a line.  Explicit spaces, if given,
  829. X.\" are apparently honored and the normal intersentence spacing is
  830. X.\" supressed.
  831. X.\"
  832. X.\" DaviD W. Sanderson
  833. X.\"-------
  834. X.\" Dd    distance to space vertically before a "display"
  835. X.\" These are what n/troff use for interparagraph distance
  836. X.\"-------
  837. X.if t .nr Dd .4v
  838. X.if n .nr Dd 1v
  839. X.\"-------
  840. X.\" Ds    begin a display, indented .5 inches from the surrounding text.
  841. X.\"
  842. X.\" Note that uses of Ds and De may NOT be nested.
  843. X.\"-------
  844. X.de Ds
  845. X.\" .RS \\$1
  846. X.sp \\n(Ddu
  847. X.in +0.5i
  848. X.nf
  849. X..
  850. X.\"-------
  851. X.\" De    end a display (no trailing vertical spacing)
  852. X.\"-------
  853. X.de De
  854. X.fi
  855. X.in
  856. X.\" .RE
  857. X..
  858. X.\"-------
  859. X.\" I stole the Xf macro from the -man macros on my machine (originally
  860. X.\" "}S", I renamed it so that it won't conflict).
  861. X.\"-------
  862. X.\" Set Cf to the name of the constant width font.
  863. X.\" It will be "C" or "(CW", typically.
  864. X.\" NOTEZ BIEN the lines defining Cf must have no trailing white space:
  865. X.\"-------
  866. X.if t .ds Cf C
  867. X.if n .ds Cf R
  868. X.\"-------
  869. X.\" Rc - Alternate Roman and Courier
  870. X.\"-------
  871. X.de Rc
  872. X.Xf R \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
  873. X..
  874. X.\"-------
  875. X.\" Ic - Alternate Italic and Courier
  876. X.\"-------
  877. X.de Ic
  878. X.Xf I \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
  879. X..
  880. X.\"-------
  881. X.\" Bc - Alternate Bold and Courier
  882. X.\"-------
  883. X.de Bc
  884. X.Xf B \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
  885. X..
  886. X.\"-------
  887. X.\" Cr - Alternate Courier and Roman
  888. X.\"-------
  889. X.de Cr
  890. X.Xf \\*(Cf R \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
  891. X..
  892. X.\"-------
  893. X.\" Ci - Alternate Courier and Italic
  894. X.\"-------
  895. X.de Ci
  896. X.Xf \\*(Cf I \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
  897. X..
  898. X.\"-------
  899. X.\" Cb - Alternate Courier and Bold
  900. X.\"-------
  901. X.de Cb
  902. X.Xf \\*(Cf B \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
  903. X..
  904. X.\"-------
  905. X.\" Xf - Alternate fonts
  906. X.\"
  907. X.\" \$1 - first font
  908. X.\" \$2 - second font
  909. X.\" \$3 - desired word with embedded font changes, built up by recursion
  910. X.\" \$4 - text for first font
  911. X.\" \$5 - \$9 - remaining args
  912. X.\"
  913. X.\" Every time we are called:
  914. X.\"
  915. X.\" If        there is something in \$4
  916. X.\" then    Call ourself with the fonts switched,
  917. X.\"        with a new word made of the current word (\$3) and \$4
  918. X.\"        rendered in the first font,
  919. X.\"        and with the remaining args following \$4.
  920. X.\" else    We are done recursing.  \$3 holds the desired output
  921. X.\"        word.  We emit \$3, change to Roman font, and restore
  922. X.\"        the point size to the default.
  923. X.\" fi
  924. X.\"
  925. X.\" Use Xi to add a little bit of space after italic text.
  926. X.\"-------
  927. X.de Xf
  928. X.ds Xi
  929. X.\"-------
  930. X.\" I used to test for the italic font both by its font position
  931. X.\" and its name.  Now just test by its name.
  932. X.\"
  933. X.\" .if "\\$1"2" .if !"\\$5"" .ds Xi \^
  934. X.\"-------
  935. X.if "\\$1"I" .if !"\\$5"" .ds Xi \^
  936. X.\"-------
  937. X.\" This is my original code to deal with the recursion.
  938. X.\" Evidently some nroffs can't deal with it.
  939. X.\"-------
  940. X.\" .ie !"\\$4"" \{\
  941. X.\" .    Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
  942. X.\" .\}
  943. X.\" .el \{\\$3
  944. X.\" .    ft R    \" Restore the default font, since we don't know
  945. X.\" .        \" what the last font change was.
  946. X.\" .    ps 10    \" Restore the default point size, since it might
  947. X.\" .        \" have been changed by an argument to this macro.
  948. X.\" .\}
  949. X.\"-------
  950. X.\" Here is more portable (though less pretty) code to deal with
  951. X.\" the recursion.
  952. X.\"-------
  953. X.if !"\\$4"" .Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
  954. X.if "\\$4"" \\$3\fR\s10
  955. X..
  956. X.TH RC 1 "28 April 1991"
  957. X.SH NAME
  958. Xrc \- shell
  959. X.SH SYNOPSIS
  960. X.B rc
  961. X.RB [ \-eixvldnpo ]
  962. X.RB [ \-c
  963. X.IR command ]
  964. X.RI [ arguments ]
  965. X.SH DESCRIPTION
  966. X.I rc
  967. Xis a command interpreter and programming language similar to
  968. X.IR sh (1).
  969. XIt is based on the AT&T Plan 9 shell of the same name.
  970. XThe shell offers a C-like syntax (much more so than the C shell),
  971. Xand a powerful mechanism for manipulating variables.
  972. XIt is reasonably small and reasonably fast,
  973. Xespecially when compared to contemporary shells.
  974. XIts use is intended to be interactive,
  975. Xbut the language lends itself well to scripts.
  976. X.SH OPTIONS
  977. X.TP
  978. X.Cr \-e
  979. XIf the
  980. X.Cr \-e
  981. Xoption is present, then
  982. X.I rc
  983. Xwill exit if the exit status of a command is false (nonzero).
  984. X.I rc
  985. Xwill not exit, however, if a conditional fails, e.g., an
  986. X.Cr if()
  987. Xcommand.
  988. X.TP
  989. X.Cr \-i
  990. XIf the
  991. X.Cr \-i
  992. Xoption is present or if the input to
  993. X.I rc
  994. Xis from a terminal (as determined by
  995. X.IR isatty (3))
  996. Xthen
  997. X.I rc
  998. Xwill be in
  999. X.I interactive
  1000. Xmode.
  1001. XThat is, a prompt (from
  1002. X.Cr $prompt(1)\^ )
  1003. Xwill be printed before an
  1004. Xinput line is taken, and
  1005. X.I rc
  1006. Xwill ignore the signals
  1007. X.Cr SIGINT
  1008. Xand
  1009. X.Cr SIGQUIT .
  1010. X.TP
  1011. X.Cr \-x
  1012. XThis option will make
  1013. X.I rc
  1014. Xprint every command on standard error before it is executed.
  1015. XIt can be useful for debugging
  1016. X.I rc
  1017. Xscripts.
  1018. X.TP
  1019. X.Cr \-v
  1020. XThis option will echo input to
  1021. X.I rc
  1022. Xon standard error as it is read.
  1023. X.TP
  1024. X.Cr \-l
  1025. XIf the
  1026. X.Cr \-l
  1027. Xoption is present, or if
  1028. X.IR rc 's
  1029. X.Cr argv[0][0]
  1030. Xis a dash
  1031. X.Rc ( \- ),
  1032. Xthen
  1033. X.I rc
  1034. Xwill behave as a login shell.
  1035. XThat is, it will try to run commands present in
  1036. X.Cr $home/.rcrc ,
  1037. Xif this file exists, before reading any other input.
  1038. X.TP
  1039. X.Cr \-d
  1040. XThis flag causes
  1041. X.I rc
  1042. Xnot to ignore
  1043. X.Cr SIGQUIT
  1044. Xor
  1045. X.Cr SIGTERM .
  1046. XThus
  1047. X.I rc
  1048. Xcan be made to dump core if sent
  1049. X.Cr SIGQUIT .
  1050. XThis option is only useful for debugging
  1051. X.IR rc .
  1052. X.TP
  1053. X.Cr \-n
  1054. XThis flag causes
  1055. X.I rc
  1056. Xto read its input and parse it, but not to execute any commands.
  1057. XThis is useful for syntax checking on scripts.
  1058. XIf used in combination with the
  1059. X.Cr \-x
  1060. Xoption,
  1061. X.I rc
  1062. Xwill print each command as it is parsed in a form similar to the one
  1063. Xused for exporting functions into the environment.
  1064. X.TP
  1065. X.Cr \-p
  1066. XThis flag prevents
  1067. X.I rc
  1068. Xfrom initializing shell functions from the environment.
  1069. XThis allows
  1070. X.I rc
  1071. Xto run in a protected mode, whereby it becomes more difficult for
  1072. Xan
  1073. X.I rc
  1074. Xscript to be subverted by placing false commands in the environment.
  1075. X(Note that this presence of this option does NOT mean that it is safe to
  1076. Xrun setuid
  1077. X.I rc
  1078. Xscripts; the usual caveats about the setuid bit still apply.)
  1079. X.TP
  1080. X.Cr \-o
  1081. XThis flag prevents the usual practice of trying to open
  1082. X.Cr /dev/null
  1083. Xon file descriptors 0, 1, and 2, if any of those descriptors
  1084. Xare inherited closed.
  1085. X.TP
  1086. X.Cr \-c
  1087. XIf
  1088. X.Cr \-c
  1089. Xis present, commands are executed from the immediately following
  1090. Xargument.
  1091. XAny further arguments to
  1092. X.I rc
  1093. Xare placed in
  1094. X.Cr $* .
  1095. X.PP
  1096. X.SH COMMANDS
  1097. XA simple command is a sequence of words, separated by white space
  1098. X(space and tab) characters that ends with a newline, semicolon
  1099. X.Rc ( ; ),
  1100. Xor ampersand
  1101. X.Rc ( & ).
  1102. XThe first word of a command is the name of that command.
  1103. XIf the name begins with
  1104. X.Cr / ,
  1105. X.Cr ./ ,
  1106. Xor
  1107. X.Cr ../ ,
  1108. Xthen the name is used as an absolute path
  1109. Xname referring to an executable file.
  1110. XOtherwise, the name of the command is looked up in a table
  1111. Xof shell functions, builtin commands,
  1112. Xor as a file in the directories named by
  1113. X.Cr $path .
  1114. X.SS "Background Tasks"
  1115. XA command ending with a
  1116. X.Cr &
  1117. Xis run in the background; that is,
  1118. Xthe shell returns immediately rather than waiting for the command to
  1119. Xcomplete.
  1120. XBackground commands have
  1121. X.Cr /dev/null
  1122. Xconnected to their standard input unless an explicit redirection for
  1123. Xstandard input is used.
  1124. X.SS "Subshells"
  1125. XA command prefixed with an at-sign
  1126. X.Rc ( @ )
  1127. Xis executed in a subshell.
  1128. XThis insulates the parent shell from the effects
  1129. Xof state changing operations such as a
  1130. X.B cd
  1131. Xor a variable assignment.
  1132. XFor example:
  1133. X.Ds
  1134. X.Cr "@ {cd ..; make}"
  1135. X.De
  1136. X.PP
  1137. Xwill run
  1138. X.IR make (1)
  1139. Xin the parent directory
  1140. X.Rc ( .. ),
  1141. Xbut leaves the shell running in the current directory.
  1142. X.SS "Line continuation"
  1143. XA long logical line may be continued over several physical lines by
  1144. Xterminating each line (except the last) with a backslash
  1145. X.Rc ( \e ).
  1146. XThe backslash-newline sequence is treated as a space.
  1147. XA backslash is not otherwise special to
  1148. X.IR rc .
  1149. X(In addition,
  1150. Xinside quotes a backslash loses its special meaning
  1151. Xeven when it is followed by a newline.)
  1152. X.SS Quoting
  1153. X.IR rc
  1154. Xinterprets several characters specially; special characters
  1155. Xautomatically terminate words.
  1156. XThe following characters are special:
  1157. X.Ds
  1158. X.Cr "# ; & | ^ $ = \` ' { } ( ) < >"
  1159. X.De
  1160. X.PP
  1161. XThe single quote
  1162. X.Rc ( ' )
  1163. Xprevents special treatment of any character other than itself.
  1164. XAll characters, including control characters, newlines,
  1165. Xand backslashes between two quote characters are treated as an
  1166. Xuninterpreted string.
  1167. XA quote character itself may be quoted by placing two quotes in a row.
  1168. XThe minimal sequence needed to enter the quote character is
  1169. X.Cr '''' .
  1170. XThe empty string is represented by
  1171. X.Cr '' .
  1172. XThus:
  1173. X.Ds
  1174. X.Cr "echo 'What''s the plan, Stan?'"
  1175. X.De
  1176. X.PP
  1177. Xprints out
  1178. X.Ds
  1179. X.Cr "What's the plan, Stan?"
  1180. X.De
  1181. X.PP
  1182. XThe number sign
  1183. X.Rc ( # )
  1184. Xbegins a comment in
  1185. X.IR rc .
  1186. XAll characters up to but not including the next newline are ignored.
  1187. XNote that backslash continuation does not work inside a comment,
  1188. Xi.e.,
  1189. Xthe backslash is ignored along with everything else.
  1190. X.SS Grouping
  1191. XZero or more commands may be grouped within braces
  1192. X.Rc (`` { ''
  1193. Xand
  1194. X.Rc `` } ''),
  1195. Xand are then treated as one command.
  1196. XBraces do not otherwise define scope;
  1197. Xthey are used only for command grouping.
  1198. XIn particular, be wary of the command:
  1199. X.Ds
  1200. X.Cr "for (i) {"
  1201. X.Cr "    command"
  1202. X.Cr "} | command"
  1203. X.De
  1204. X.PP
  1205. XSince pipe binds tighter than
  1206. X.Cr for ,
  1207. Xthis command does not perform what the user expects it to.
  1208. XInstead, enclose the whole
  1209. X.Cr for
  1210. Xstatement in braces:
  1211. X.Ds
  1212. X.Cr "{for (i) command} | command"
  1213. X.De
  1214. X.PP
  1215. XFortunately,
  1216. X.IR rc 's
  1217. Xgrammar is simple enough that a (confident) user can
  1218. Xunderstand it by examining the skeletal
  1219. X.IR yacc (1)
  1220. Xgrammar
  1221. Xat the end of this man page (see the section entitled
  1222. X.BR GRAMMAR ).
  1223. X.SS "Input and output"
  1224. X.PP
  1225. XThe standard output may be redirected to a file with
  1226. X.Ds
  1227. X.Cr "command > file"
  1228. X.De
  1229. X.PP
  1230. Xand the standard input may be taken from a file with
  1231. X.Ds
  1232. X.Cr "command < file"
  1233. X.De
  1234. X.PP
  1235. XFile descriptors other than 0 and 1 may be specified also.
  1236. XFor example, to redirect standard error to a file, use:
  1237. X.Ds
  1238. X.Cr "command >[2] file"
  1239. X.De
  1240. X.PP
  1241. XIn order to duplicate a file descriptor, use
  1242. X.Ci >[ n = m ]\fR.
  1243. XThus to redirect both standard output and standard error
  1244. Xto the same file, use
  1245. X.Ds
  1246. X.Cr "command > file >[2=1]"
  1247. X.De
  1248. X.PP
  1249. XTo close a file descriptor that may be open, use
  1250. X.Ci >[ n =]\fR.
  1251. XFor example, to
  1252. Xclose file descriptor 7:
  1253. X.Ds
  1254. X.Cr "command >[7=]"
  1255. X.De
  1256. X.PP
  1257. XIn order to place the output of a command at the end of an already
  1258. Xexisting file, use:
  1259. X.Ds
  1260. X.Cr "command >> file"
  1261. X.De
  1262. X.PP
  1263. XIf the file does not exist, then it is created.
  1264. X.PP
  1265. X``Here documents'' are supported as in
  1266. X.I sh
  1267. Xwith the use of
  1268. X.Ds
  1269. X.Cr "command << 'eof-marker'"
  1270. X.De
  1271. X.PP
  1272. XIf the end-of-file marker is enclosed in quotes,
  1273. Xthen no variable substitution occurs inside the here document.
  1274. XOtherwise, every variable is substituted
  1275. Xby its space-separated-list value (see
  1276. X.BR "Flat Lists" ,
  1277. Xbelow),
  1278. Xand if a
  1279. X.Cr ^
  1280. Xcharacter follows a variable name, it is deleted.
  1281. XThis allows the unambiguous use of variables adjacent to text, as in
  1282. X.Ds
  1283. X.Cr $variable^follow
  1284. X.De
  1285. XTo include a literal
  1286. X.Cr $
  1287. Xin a here document when an unquoted end-of-file marker is being used,
  1288. Xenter it as
  1289. X.Cr $$ .
  1290. X.PP
  1291. XAdditionally,
  1292. X.I rc
  1293. Xsupports ``here strings'', which are like here documents,
  1294. Xexcept that input is taken directly from a string on the command line.
  1295. XIts use is illustrated here:
  1296. X.Ds
  1297. X.Cr "cat <<< 'this is a here string' | wc"
  1298. X.De
  1299. X.PP
  1300. X(This feature enables
  1301. X.I rc
  1302. Xto export functions using here documents into the environment;
  1303. Xthe author does not expect users to find this feature useful.)
  1304. X.SS Pipes
  1305. XTwo or more commands may be combined in a pipeline by placing the
  1306. Xvertical bar
  1307. X.Rc ( \||\| )
  1308. Xbetween them.
  1309. XThe standard output (file descriptor 1)
  1310. Xof the command on the left is tied to the standard input (file
  1311. Xdescriptor 0) of the command on the right.
  1312. XThe notation
  1313. X.Ci |[ n = m ]
  1314. Xindicates that file descriptor
  1315. X.I n
  1316. Xof the left process is connected to
  1317. Xfile descriptor
  1318. X.I m
  1319. Xof the right process.
  1320. X.Ci |[ n ]
  1321. Xis a shorthand for
  1322. X.Ci |[ n =0]\fR.
  1323. XAs an example, to pipe the standard error of a command to
  1324. X.IR wc (1),
  1325. Xuse:
  1326. X.Ds
  1327. X.Cr "command |[2] wc"
  1328. X.De
  1329. X.PP
  1330. XThe exit status of a pipeline is considered true if and only if every
  1331. Xcommand in the pipeline exits true.
  1332. X.SS "Commands as Arguments"
  1333. XSome commands, like
  1334. X.IR cmp (1)
  1335. Xor
  1336. X.IR diff (1),
  1337. Xtake their arguments on the command
  1338. Xline, and do not read input from standard input.
  1339. XIt is convenient
  1340. Xsometimes to build nonlinear pipelines so that a command like
  1341. X.I cmp
  1342. Xcan read the output of two other commands at once.
  1343. X.I rc
  1344. Xdoes it like this:
  1345. X.Ds
  1346. X.Cr "cmp <{command} <{command}"
  1347. X.De
  1348. X.PP
  1349. Xcompares the output of the two commands in braces.
  1350. XA note: since this form of
  1351. Xredirection is implemented with some kind of pipe, and since one cannot
  1352. X.IR lseek (2)
  1353. Xon a pipe, commands that use
  1354. X.IR lseek (2)
  1355. Xwill hang.
  1356. XFor example,
  1357. Xmost versions of
  1358. X.IR diff (1)
  1359. Xuse
  1360. X.IR lseek (2)
  1361. Xon their inputs.
  1362. X.PP
  1363. XData can be sent down a pipe to several commands using
  1364. X.IR tee (1)
  1365. Xand the output version of this notation:
  1366. X.Ds
  1367. X.Cr "echo hi there | tee >{sed 's/^/p1 /'} >{sed 's/^/p2 /'}"
  1368. X.De
  1369. X.SH "CONTROL STRUCTURES"
  1370. XThe following may be used for control flow in
  1371. X.IR rc :
  1372. X.SS "If-else Statements"
  1373. X.PD 0
  1374. X.sp
  1375. X.Ci "if (" test ") {"
  1376. X.br
  1377. X.I  "    cmd"
  1378. X.br
  1379. X.TP
  1380. X.Ci "} else " cmd
  1381. XThe
  1382. X.I test
  1383. Xis executed, and if its return status is zero, the first
  1384. Xcommand is executed, otherwise the second is.
  1385. XBraces are not mandatory around the commands.
  1386. XHowever, an
  1387. X.Cr else
  1388. Xstatement is valid only if it
  1389. Xfollows a close-brace on the same line.
  1390. XOtherwise, the
  1391. X.Cr if
  1392. Xis taken to be a simple-if:
  1393. X.Ds
  1394. X.Cr "if (test)"
  1395. X.Cr "    command"
  1396. X.De
  1397. X.PD
  1398. X.SS "While and For Loops"
  1399. X.TP
  1400. X.Ci "while (" test ) " cmd"
  1401. X.I rc
  1402. Xexecutes the
  1403. X.I test
  1404. Xand performs the command as long as the
  1405. X.I test
  1406. Xis true.
  1407. X.TP
  1408. X.Ci "for (" var " in" " list" ) " cmd"
  1409. X.I rc
  1410. Xsets
  1411. X.I var
  1412. Xto each element of
  1413. X.I list
  1414. X(which may contain variables and backquote substitutions) and runs
  1415. X.IR cmd .
  1416. XIf
  1417. X.Rc `` in
  1418. X.IR list ''
  1419. Xis omitted, then
  1420. X.I rc
  1421. Xwill set
  1422. X.I var
  1423. Xto each element of
  1424. X.Cr $*
  1425. X(excluding
  1426. X.Cr $0 ).
  1427. XFor example:
  1428. X.Ds
  1429. X.Cr "for (i in \`{ls -F | grep '\e*$' | sed 's/\e*$//'}) { commands }"
  1430. X.De
  1431. X.TP
  1432. X\&
  1433. Xwill set
  1434. X.Cr $i
  1435. Xto the name of each file in the current directory that is
  1436. Xexecutable.
  1437. X.SS "Switch"
  1438. X.TP
  1439. X.Ci "switch (" list ") { case" " ..." " }"
  1440. X.I rc
  1441. Xlooks inside the braces after a
  1442. X.Cr switch
  1443. Xfor statements beginning with the word
  1444. X.Cr case .
  1445. XIf any of the patterns following
  1446. X.Cr case
  1447. Xmatch the list supplied to
  1448. X.Cr switch ,
  1449. Xthen the commands up until the next
  1450. X.Cr case
  1451. Xstatement are executed.
  1452. XThe metacharacters
  1453. X.Cr "*" ,
  1454. X.Cr [
  1455. Xor
  1456. X.Cr ?
  1457. Xshould not be quoted;
  1458. Xmatching is performed only against the strings in
  1459. X.IR list ,
  1460. Xnot against file names.
  1461. X(Matching for case statements is the same as for the
  1462. X.Cr ~
  1463. Xcommand.)
  1464. X.SS "Logical Operators"
  1465. XThere are a number of operators in
  1466. X.I rc
  1467. Xwhich depend on the exit status of a command.
  1468. X.Ds
  1469. X.Cr "command && command"
  1470. X.De
  1471. X.PP
  1472. Xexecutes the first command and then executes the second command if and only if
  1473. Xthe first command exits with a zero exit status (``true'' in Unix).
  1474. X.Ds
  1475. X.Cr "command || command"
  1476. X.De
  1477. X.PP
  1478. Xexecutes the first command executing the second command if and only if
  1479. Xthe second command exits with a nonzero exit status (``false'' in Unix).
  1480. X.Ds
  1481. X.Cr "! command"
  1482. X.De
  1483. X.PP
  1484. Xnegates the exit status of a command.
  1485. X.SH "PATTERN MATCHING"
  1486. XThere are two forms of pattern matching in
  1487. X.IR rc .
  1488. XOne is traditional shell globbing.
  1489. XThis occurs in matching for file names in argument lists:
  1490. X.Ds
  1491. X.Cr "command argument argument ..."
  1492. X.De
  1493. X.PP
  1494. XWhen the characters
  1495. X.Cr "*" ,
  1496. X.Cr [
  1497. Xor
  1498. X.Cr ?
  1499. Xoccur in an argument or command,
  1500. X.I rc
  1501. Xlooks at the
  1502. Xargument as a pattern for matching against files.
  1503. X(Contrary to the behavior other shells exhibit,
  1504. X.I rc
  1505. Xwill only perform pattern matching if a metacharacter occurs unquoted and
  1506. Xliterally in the input.
  1507. XThus,
  1508. X.Ds
  1509. X.Cr "foo='*'"
  1510. X.Cr "echo $foo"
  1511. X.De
  1512. X.PP
  1513. Xwill always echo just a star.
  1514. XIn order for non-literal metacharacters to be expanded, an
  1515. X.Cr eval
  1516. Xstatement must be used in order to rescan the input.)
  1517. XPattern matching occurs according to the following rules: a
  1518. X.Cr *
  1519. Xmatches any number (including zero) of
  1520. Xcharacters.
  1521. XA
  1522. X.Cr ?
  1523. Xmatches any single character, and a
  1524. X.Cr [
  1525. Xfollowed by a
  1526. Xnumber of characters followed by a
  1527. X.Cr ]
  1528. Xmatches a single character in that
  1529. Xclass.
  1530. XThe rules for character class matching are the same as those for
  1531. X.IR ed (1),
  1532. Xwith the exception that character class negation is achieved
  1533. Xwith the tilde
  1534. X.Rc ( ~ ),
  1535. Xnot the caret
  1536. X.Rc ( ^ ),
  1537. Xsince the caret already means
  1538. Xsomething else in
  1539. X.IR rc .
  1540. X.PP
  1541. X.I rc
  1542. Xalso matches patterns against strings with the
  1543. X.Cr ~
  1544. Xcommand:
  1545. X.Ds
  1546. X.Cr "~ subject pattern pattern ..."
  1547. X.De
  1548. X.PP
  1549. X.Cr ~
  1550. Xsets
  1551. X.Cr $status
  1552. Xto zero if and only if a supplied pattern matches any
  1553. Xsingle element of the subject list.
  1554. XThus
  1555. X.Ds
  1556. X.Cr "~ foo f*"
  1557. X.De
  1558. X.PP
  1559. Xsets status to zero, while
  1560. X.Ds
  1561. X.Cr "~ (bar baz) f*"
  1562. X.De
  1563. X.PP
  1564. Xsets status to one.
  1565. XThe null list is matched by the null list, so
  1566. X.Ds
  1567. X.Cr "~ $foo ()"
  1568. X.De
  1569. X.PP
  1570. Xchecks to see whether
  1571. X.Cr $foo
  1572. Xis empty or not.
  1573. XThis may also be achieved
  1574. Xby the test
  1575. X.Ds
  1576. X.Cr "~ $#foo 0"
  1577. X.De
  1578. X.PP
  1579. XNote that inside a
  1580. X.Cr ~
  1581. Xcommand
  1582. X.I rc
  1583. Xdoes not match patterns against file
  1584. Xnames, so it is not necessary to quote the characters
  1585. X.Cr "*" ,
  1586. X.Cr [
  1587. Xand
  1588. X.Cr "?" .
  1589. XHowever,
  1590. X.I rc
  1591. Xdoes expand the glob the subject against filenames if it contains
  1592. Xmetacharacters.
  1593. XThus, the command
  1594. X.Ds
  1595. X.Cr "~ * ?"
  1596. X.De
  1597. X.PP
  1598. Xreturns true if any of the files in the current directory have a
  1599. Xsingle-character name.
  1600. X(Note that if the
  1601. X.Cr ~
  1602. Xcommand is given a list as its first
  1603. Xargument, then a successful match against any of the elements of that
  1604. Xlist will cause
  1605. X.Cr ~
  1606. Xto return true.
  1607. XFor example:
  1608. X.Ds
  1609. X.Cr "~ (foo goo zoo) z*"
  1610. X.De
  1611. X.PP
  1612. Xis true.)
  1613. X.SH "LISTS AND VARIABLES"
  1614. XThe primary data structure in
  1615. X.IR rc
  1616. Xis the list, which is a sequence of words.
  1617. XParentheses are used to group lists.
  1618. XThe empty list is represented by
  1619. X.Cr "()" .
  1620. XLists have no hierarchical structure;
  1621. Xa list inside another list is expanded so the
  1622. Xouter list contains all the elements of the inner list.
  1623. XThus, the following are all equivalent
  1624. X.Ds
  1625. X.Cr "one two three"
  1626. X
  1627. X.Cr "(one two three)"
  1628. X
  1629. X.Cr "((one) () ((two three)))"
  1630. X.De
  1631. X.PP
  1632. XNote that the null string,
  1633. X.Cr "''" ,
  1634. Xand the null list,
  1635. X.Cr "()" ,
  1636. Xare two very
  1637. Xdifferent things.
  1638. XAssigning the null string to variable is a valid
  1639. Xoperation, but it does not remove its definition.
  1640. XFor example,
  1641. Xif
  1642. X.Cr $a
  1643. Xis set to
  1644. X.Cr "''" ,
  1645. Xthen
  1646. X.Cr "$#a" ,
  1647. Xreturns a 1.
  1648. X.SS "List Concatenation"
  1649. XTwo lists may be joined by the concatenation operator
  1650. X.Rc ( ^ ).
  1651. XA single word is treated as a list of length one, so
  1652. X.Ds
  1653. X.Cr "echo foo^bar"
  1654. X.De
  1655. X.PP
  1656. Xproduces the output
  1657. X.Ds
  1658. X.Cr foobar
  1659. X.De
  1660. X.PP
  1661. XFor lists of more than one element,
  1662. Xconcatenation works according to the following rules:
  1663. Xif the two lists have the same number of elements,
  1664. Xthen concatenation is pairwise:
  1665. X.Ds
  1666. X.Cr "echo (a\- b\- c\-)^(1 2 3)"
  1667. X.De
  1668. X.PP
  1669. Xproduces the output
  1670. X.Ds
  1671. X.Cr "a\-1 b\-2 c\-3"
  1672. X.De
  1673. X.PP
  1674. XOtherwise, one of the lists must have a single element,
  1675. Xand then the concatenation is distributive:
  1676. X.Ds
  1677. X.Cr "cc \-^(O g c) (malloc alloca)^.c"
  1678. X.De
  1679. X.PP
  1680. Xhas the effect of performing the command
  1681. X.Ds
  1682. X.Cr "cc \-O \-g \-c malloc.c alloca.c"
  1683. X.De
  1684. X.SS "Free Carets"
  1685. X.I rc
  1686. Xinserts carets (concatenation operators) for free in certain situations,
  1687. Xin order to save some typing on the user's behalf.
  1688. XFor
  1689. Xexample, the above example could also be typed in as:
  1690. X.Ds
  1691. X.Cr "opts=(O g c) files=(malloc alloca) cc \-$opts $files.c"
  1692. X.De
  1693. X.PP
  1694. X.I rc
  1695. Xtakes care to insert a free-caret between the
  1696. X.Rc `` \- ''
  1697. Xand
  1698. X.Cr "$opts" ,
  1699. Xas well
  1700. Xas between
  1701. X.Cr $files
  1702. Xand
  1703. X.Cr ".c" .
  1704. XThe rule for free carets is as follows:  if
  1705. Xa word or keyword is immediately
  1706. Xfollowed by another word, keyword, dollar-sign or
  1707. Xbackquote, then
  1708. X.I rc
  1709. Xinserts a caret between them.
  1710. X.SS "Variables"
  1711. XA list may be assigned to a variable, using the notation:
  1712. X.Ds
  1713. X.Ic var " = " list
  1714. X.De
  1715. X.PP
  1716. XAny sequence of non-special characters, except a sequence including
  1717. Xonly digits, may be used as a variable name.
  1718. XAll user-defined variables are exported into the environment.
  1719. X.PP
  1720. XThe value of a variable is referenced with the notation:
  1721. X.Ds
  1722. X.Ci $ var
  1723. X.De
  1724. X.PP
  1725. XAny variable which has not been assigned a value returns the null list,
  1726. X.Cr "()" ,
  1727. Xwhen referenced.
  1728. XIn addition, multiple references are allowed:
  1729. X.Ds
  1730. X.Cr a=foo
  1731. X.Cr b=a
  1732. X.Cr "echo $$b"
  1733. X.De
  1734. X.PP
  1735. Xprints
  1736. X.Ds
  1737. X.Cr foo
  1738. X.De
  1739. X.PP
  1740. XA variable's definition may also be removed by
  1741. Xassigning the null list to a variable:
  1742. X.Ds
  1743. X.Ic var =()
  1744. X.De
  1745. X.PP
  1746. XFor ``free careting'' to work correctly,
  1747. X.I rc
  1748. Xmust make certain assumptions
  1749. Xabout what characters may appear in a variable name.
  1750. X.I rc
  1751. Xassumes that a variable name consists only of alphanumeric characters,
  1752. Xunderscore
  1753. X.Rc ( \|_\| )
  1754. Xand star
  1755. X.Rc ( * ).
  1756. XTo reference a variable with other
  1757. Xcharacters in its name, quote the variable name.
  1758. XThus:
  1759. X.Ds
  1760. X.Cr "echo $'we$Ird\Variab!le'"
  1761. X.De
  1762. X.SS "Local Variables"
  1763. XAny number of variable assignments may be made local to a single
  1764. Xcommand by typing:
  1765. X.Ds
  1766. X.Cr "a=foo b=bar ... command"
  1767. X.De
  1768. X.PP
  1769. XThe command may be a compound command, so for example:
  1770. X.Ds
  1771. X.Cr "path=. ifs=() {"
  1772. X.Cr "    " ...
  1773. X.Cr }
  1774. X.De
  1775. X.PP
  1776. Xsets
  1777. X.Cr path
  1778. Xto
  1779. X.Cr .
  1780. Xand removes
  1781. X.Cr ifs
  1782. Xfor the duration of one long compound command.
  1783. X.SS "Variable Subscripts"
  1784. XVariables may be subscripted with the notation
  1785. X.Ds
  1786. X.Ci $var( n )
  1787. X.De
  1788. X.PP
  1789. Xwhere
  1790. X.I n
  1791. Xis a list of integers (origin 1).
  1792. XThe list of subscripts need
  1793. Xnot be in order or even unique.
  1794. XThus, if
  1795. X.Ds
  1796. X.Cr "a=(one two three)"
  1797. X.De
  1798. X.PP
  1799. Xthen
  1800. X.Ds
  1801. X.Cr "echo $a(3 3 3)"
  1802. X.De
  1803. X.PP
  1804. Xprints
  1805. X.Ds
  1806. X.Cr "three three three"
  1807. X.De
  1808. X.PP
  1809. XIf
  1810. X.I n
  1811. Xreferences a nonexistent element, then
  1812. X.Ci $var( n )
  1813. Xreturns the null list.
  1814. XThe notation
  1815. X.Ci "$" n\fR,
  1816. Xwhere
  1817. X.I n
  1818. Xis an integer, is a shorthand for
  1819. X.Ci $*( n )\fR.
  1820. XThus,
  1821. X.IR rc 's
  1822. Xarguments may be referred to as
  1823. X.Cr "$1" ,
  1824. X.Cr "$2" ,
  1825. Xand so on.
  1826. X.PP
  1827. XNote also that the list of subscripts may be given by any of
  1828. X.IR rc 's
  1829. Xlist operations:
  1830. X.Ds
  1831. X.Cr "$var(\`{awk 'BEGIN{for(i=1;i<=10;i++)print i;exit; }'})"
  1832. X.De
  1833. X.PP
  1834. Xreturns the first 10 elements of
  1835. X.Cr $var .
  1836. X.PP
  1837. XTo count the number of elements in a variable, use
  1838. X.Ds
  1839. X.Cr $#var
  1840. X.De
  1841. X.PP
  1842. XThis returns a single-element list, with the number of elements in
  1843. X.Cr $var .
  1844. X.SS "Flat Lists"
  1845. XIn order to create a single-element list from a multi-element list,
  1846. Xwith the components space-separated, use
  1847. X.Ds
  1848. X.Cr $^var
  1849. X.De
  1850. X.PP
  1851. XThis is useful when the normal list concatenation rules need to be
  1852. Xbypassed.
  1853. XFor example, to append a single period at the end of
  1854. X.Cr $path ,
  1855. Xuse:
  1856. X.Ds
  1857. X.Cr "echo $^path."
  1858. X.De
  1859. X.SS "Backquote Substitution"
  1860. XA list may be formed from the output of a command by using backquote
  1861. Xsubstitution:
  1862. X.Ds
  1863. X.Cr "\`{ command }"
  1864. X.De
  1865. X.PP
  1866. Xreturns a list formed from the standard output of the command in braces.
  1867. X.Cr $ifs
  1868. Xis used to split the output into list elements.
  1869. XBy default,
  1870. X.Cr $ifs
  1871. Xhas the value space-tab-newline.
  1872. XThe braces may be omitted if the command is a single word.
  1873. XThus
  1874. X.Cr \`ls
  1875. Xmay be used instead of
  1876. X.Cr "\`{ls}" .
  1877. XThis last feature is useful when defining functions that expand
  1878. Xto useful argument lists.
  1879. XA frequent use is:
  1880. X.Ds
  1881. X.Cr "fn src { echo *.[chy] }"
  1882. X.De
  1883. X.PP
  1884. Xfollowed by
  1885. X.Ds
  1886. X.Cr "wc \`src"
  1887. X.De
  1888. X.PP
  1889. X(This will print out a word-count of all C source files in the current
  1890. Xdirectory.)
  1891. X.PP
  1892. XIn order to override the value of
  1893. X.Cr $ifs
  1894. Xfor a single backquote
  1895. Xsubstitution, use:
  1896. X.Ds
  1897. X.Cr "\`\` (ifs-list) { command }"
  1898. X.De
  1899. X.PP
  1900. X.Cr $ifs
  1901. Xwill be temporarily ignored and the command's output will be split as specified by
  1902. Xthe list following the double backquote.
  1903. XFor example:
  1904. X.Ds
  1905. X.Cr "\`\` ($nl :) {cat /etc/passwd}"
  1906. X.De
  1907. X.PP
  1908. Xsplits up
  1909. X.Cr /etc/passwd
  1910. Xinto fields, assuming that
  1911. X.Cr $nl
  1912. Xcontains a newline
  1913. Xas its value.
  1914. X.SH "SPECIAL VARIABLES"
  1915. XSeveral variables are known to
  1916. X.I rc
  1917. Xand are treated specially.
  1918. X.TP
  1919. X.Cr *
  1920. XThe argument list of
  1921. X.IR rc .
  1922. X.Cr "$1, $2,"
  1923. Xetc. are the same as
  1924. X.Cr $*(1) ,
  1925. X.Cr $*(2) ,
  1926. Xetc.
  1927. XThe variable
  1928. X.Cr $0
  1929. Xholds the value of
  1930. X.Cr argv[0]
  1931. Xwith which
  1932. X.I rc
  1933. Xwas invoked.
  1934. XAdditionally,
  1935. X.Cr $0
  1936. Xis set to the name of a function for the duration of
  1937. Xthe execution of that function, and
  1938. X.Cr $0
  1939. Xis also set to the name of the
  1940. Xfile being interpreted for the duration of a
  1941. X.Cr .
  1942. Xcommand.
  1943. X.TP
  1944. X.Cr apid
  1945. XThe process ID of the last process started in the background.
  1946. X.TP
  1947. X.Cr apids
  1948. XThe process IDs of any background processes which are outstanding
  1949. Xor which have died and have not been waited for yet.
  1950. X.TP
  1951. X.Cr cdpath
  1952. XA list of directories to search for the target of a
  1953. X.B cd
  1954. Xcommand.
  1955. XThe empty string stands for the current directory.
  1956. XNote that if the
  1957. X.Cr $cdpath
  1958. Xvariable does not contain the current directory, then the current
  1959. Xdirectory will not be searched; this allows directory searching to
  1960. Xbegin in a directory other than the current directory.
  1961. XNote also that an assignment to
  1962. X.Cr $cdpath
  1963. Xcauses an automatic assignment to
  1964. X.Cr $CDPATH ,
  1965. Xand vice-versa.
  1966. X.TP
  1967. X.Cr history
  1968. X.Cr $history
  1969. Xcontains the name of a file to which commands are appended as
  1970. X.I rc
  1971. Xreads them.
  1972. XThis facilitates the use of a stand-alone history program
  1973. X(such as
  1974. X.IR history (1))
  1975. Xwhich parses the contents of the history file and presents them to
  1976. X.I rc
  1977. Xfor reinterpretation.
  1978. XIf
  1979. X.Cr $history
  1980. Xis not set, then
  1981. X.I rc
  1982. Xdoes not append commands to any file.
  1983. X.TP
  1984. X.Cr home
  1985. XThe default directory for the builtin
  1986. X.B cd
  1987. Xcommand and is the directory
  1988. Xin which
  1989. X.I rc
  1990. Xlooks to find its initialization file,
  1991. X.Cr .rcrc ,
  1992. Xif
  1993. X.I rc
  1994. Xhas been started up as a login shell.
  1995. XLike
  1996. X.Cr $cdpath
  1997. Xand
  1998. X.Cr $CDPATH ,
  1999. X.Cr $home
  2000. Xand
  2001. X.Cr $HOME
  2002. Xare aliased to each other.
  2003. X.TP
  2004. X.Cr ifs
  2005. XThe internal field separator, used for splitting up the output of
  2006. Xbackquote commands for digestion as a list.
  2007. X.TP
  2008. X.Cr path
  2009. XThis is a list of directories to search in for commands.
  2010. XThe empty string stands for the current directory.
  2011. XNote that like
  2012. X.Cr $cdpath
  2013. Xand
  2014. X.Cr $CDPATH ,
  2015. X.Cr $path
  2016. Xand
  2017. X.Cr $PATH
  2018. Xare aliased to each other.
  2019. XIf
  2020. X.Cr $path
  2021. Xor
  2022. X.Cr $PATH
  2023. Xis not set at startup time,
  2024. X.Cr $path
  2025. Xassumes a default value suitable for your system.
  2026. XThis is typically
  2027. X.Cr "(/usr/ucb /usr/bin /bin .)"
  2028. X.TP
  2029. X.Cr pid
  2030. XThe process ID of the currently running
  2031. X.IR rc .
  2032. X.TP
  2033. X.Cr prompt
  2034. XThis variable holds the two prompts (in list form, of course) that
  2035. X.I rc
  2036. Xprints.
  2037. X.Cr $prompt(1)
  2038. Xis printed before each command is read, and
  2039. X.Cr $prompt(2)
  2040. Xis printed when input is expected to continue on the next
  2041. Xline.
  2042. X.I rc
  2043. Xsets
  2044. X.Cr $prompt
  2045. Xto
  2046. X.Cr "('; ' '')"
  2047. Xby default.
  2048. XThe reason for this is that it enables an
  2049. X.I rc
  2050. Xuser to grab commands from previous lines using a
  2051. Xmouse, and to present them to
  2052. X.I rc
  2053. Xfor re-interpretation; the semicolon
  2054. Xprompt is simply ignored by
  2055. X.IR rc .
  2056. XThe null
  2057. X.Cr $prompt(2)
  2058. Xalso has its
  2059. Xjustification:  an
  2060. X.I rc
  2061. Xscript, when typed interactively, will not leave
  2062. X.Cr $prompt(2) 's
  2063. Xon the screen,
  2064. Xand can therefore be grabbed by a mouse and placed
  2065. Xdirectly into a file for use as a shell script, without further editing
  2066. Xbeing necessary.
  2067. X.TP
  2068. X.Cr prompt " (function)"
  2069. XIf this function is set, then it gets executed every time
  2070. X.I rc
  2071. Xis about to print
  2072. X.Cr "$prompt(1)" .
  2073. X.TP
  2074. X.Cr status
  2075. XThe exit status of the last command.
  2076. XIf the command exited with a numeric value,
  2077. Xthat number is the status.
  2078. XIf the died with a signal,
  2079. Xthe status is the name of that signal; if a core file
  2080. Xwas created, the string
  2081. X.Rc `` +core ''
  2082. Xis appended.
  2083. XThe value of
  2084. X.Cr $status
  2085. Xfor a pipeline is a list, with one entry,
  2086. Xas above, for each process in the pipeline.
  2087. XFor example, the command
  2088. X.Ds
  2089. X.Cr "ls | wc"
  2090. X.De
  2091. X.TP
  2092. X\&
  2093. Xusually sets
  2094. X.Cr $status
  2095. Xto
  2096. X.Cr "(0 0)" .
  2097. X.PP
  2098. XThe values of
  2099. X.Cr "$path" ,
  2100. X.Cr "$cdpath" ,
  2101. Xand
  2102. X.Cr $home
  2103. Xare derived from the environment
  2104. Xvalues of
  2105. X.Cr "$PATH" ,
  2106. X.Cr "$CDPATH" ,
  2107. Xand
  2108. X.Cr "$HOME" .
  2109. XOtherwise, they are derived from
  2110. Xthe environment values of
  2111. X.Cr $path ,
  2112. X.Cr $cdpath
  2113. Xand
  2114. X.Cr $home .
  2115. XThis is for compatibility with other Unix programs, like
  2116. X.IR sh (1).
  2117. X.Cr $PATH
  2118. Xand
  2119. X.Cr $CDPATH
  2120. Xare assumed to be colon-separated lists.
  2121. X.SH FUNCTIONS
  2122. X.I rc
  2123. Xfunctions are identical to
  2124. X.I rc
  2125. Xscripts, except that they are stored
  2126. Xin memory and are automatically exported into the environment.
  2127. XA shell function is declared as:
  2128. X.Ds
  2129. X.Cr "fn name { commands }"
  2130. X.De
  2131. X.PP
  2132. X.I rc
  2133. Xscans the definition until the close-brace, so the function can
  2134. Xspan more than one line.
  2135. XThe function definition may be removed by typing
  2136. X.Ds
  2137. X.Cr "fn name"
  2138. X.De
  2139. X.PP
  2140. X(One or more names may be specified.
  2141. XWith an accompanying definition, all names receive the same definition.
  2142. XThis is sometimes useful
  2143. Xfor assigning the same signal handler to many signals.
  2144. XWithout a definition, all named functions are deleted.)
  2145. XWhen a function is executed,
  2146. X.Cr $*
  2147. Xis set to the arguments to that
  2148. Xfunction for the duration of the command.
  2149. XThus a reasonable definition for
  2150. X.Cr "l" ,
  2151. Xa shorthand for
  2152. X.IR ls (1),
  2153. Xcould be:
  2154. X.Ds
  2155. X.Cr "fn l { ls -FC $* }"
  2156. X.De
  2157. X.PP
  2158. Xbut not
  2159. X.Ds
  2160. X.Cr "fn l { ls -FC }"
  2161. X.De
  2162. X.SH "INTERRUPTS AND SIGNALS"
  2163. X.I rc
  2164. Xrecognizes a number of signals, and allows the user to define shell
  2165. Xfunctions which act as signal handlers.
  2166. X.I rc
  2167. Xby default traps
  2168. X.Cr SIGINT
  2169. Xwhen it is in interactive mode.
  2170. X.Cr SIGQUIT
  2171. Xand
  2172. X.Cr SIGTERM
  2173. Xare ignored, unless
  2174. X.I rc
  2175. Xhas been invoked with the
  2176. X.Cr \-d
  2177. Xflag.
  2178. XHowever, user-defined signal handlers may be written for these and
  2179. Xall other signals.
  2180. XThe way to define a signal handler is to
  2181. Xwrite a function by the name of the signal in lower case.
  2182. XThus:
  2183. X.Ds
  2184. X.Cr "fn sighup { echo hangup; rm /tmp/rc$pid.*; exit }"
  2185. X.De
  2186. X.PP
  2187. XIn addition to Unix signals,
  2188. X.I rc
  2189. Xrecognizes the artificial signal
  2190. X.Cr SIGEXIT
  2191. Xwhich occurs as
  2192. X.I rc
  2193. Xis about to exit.
  2194. X.PP
  2195. XIn order to remove a signal handler's definition,
  2196. Xremove it as though it were a regular function.
  2197. XFor example:
  2198. X.Ds
  2199. X.Cr "fn sigint"
  2200. X.De
  2201. X.PP
  2202. Xreturns the handler of
  2203. X.Cr SIGINT
  2204. Xto the default value.
  2205. XIn order to ignore a signal, set the signal handler's value to
  2206. X.Cr "{}" .
  2207. XThus:
  2208. X.Ds
  2209. X.Cr "fn sigint {}"
  2210. X.De
  2211. X.PP
  2212. Xcauses SIGINT to be ignored by the shell.
  2213. XOnly signals that are being ignored are passed on to programs run by
  2214. X.IR rc ;
  2215. Xsignal functions are not exported.
  2216. X.PP
  2217. XOn System V-based Unix systems,
  2218. X.I rc
  2219. Xwill not allow you to trap
  2220. X.Cr SIGCLD .
  2221. X.SH "BUILTIN COMMANDS"
  2222. XBuiltin commands execute in the context of the shell, but otherwise
  2223. Xbehave exactly like other commands.
  2224. XAlthough
  2225. X.BR ! ,
  2226. X.B ~
  2227. Xand
  2228. X.B @
  2229. Xare not strictly speaking builtin commands,
  2230. Xthey can usually be used as such.
  2231. X.TP
  2232. X\&\fB.\fR [\fB\-i\fR] \fIfile \fR[\fIarg ...\fR]
  2233. XReads
  2234. X.I file
  2235. Xas input to
  2236. X.IR rc
  2237. Xand executes its contents.
  2238. XWith a
  2239. X.Cr \-i
  2240. Xflag, input is interactive.
  2241. XThus from within a shell script,
  2242. X.Ds
  2243. X.Cr ". \-i /dev/tty"
  2244. X.De
  2245. X.TP
  2246. X\&
  2247. Xdoes the ``right'' thing.
  2248. X.TP
  2249. X.B break
  2250. XBreaks from the innermost
  2251. X.Cr for
  2252. Xor
  2253. X.Cr while ,
  2254. Xas in C.
  2255. XIt is an error to invoke
  2256. X.B break
  2257. Xoutside of a loop.
  2258. X(Note that there is no
  2259. X.B break
  2260. Xkeyword between commands in
  2261. X.Cr switch
  2262. Xstatements, unlike C.)
  2263. X.TP
  2264. X\fBbuiltin \fIcommand \fR[\fIarg ...\fR]
  2265. XExecutes the command ignoring any function definition of the
  2266. Xsame name.
  2267. XThis command is present to allow functions with the
  2268. Xsame names as builtins to use the underlying builtin or binary.
  2269. X.TP
  2270. X\fBcd \fR[\fIdirectory\fR]
  2271. XChanges the current directory to
  2272. X.IR directory .
  2273. XThe variable
  2274. X.Cr $cdpath
  2275. Xis searched for possible locations of
  2276. X.IR directory ,
  2277. Xanalogous to the searching of
  2278. X.Cr $path
  2279. Xfor executable files.
  2280. XWith no argument,
  2281. X.B cd
  2282. Xchanges the current directory to
  2283. X.Cr "$home" .
  2284. X.TP
  2285. X\fBecho \fR[\fB\-n\fR] [\fB\-\|\-\fR] [\fIarg ...\fR]
  2286. XPrints its arguments to standard output, terminated by a newline.
  2287. XArguments are separated by spaces.
  2288. XIf the first argument is
  2289. X.Cr "\-n"
  2290. Xno final newline is printed.
  2291. XIf the first argument is
  2292. X.Cr "\-\|\-" ,
  2293. Xthen all other arguments are echoed literally.
  2294. XThis is used for echoing a literal
  2295. X.Cr "\-n" .
  2296. X.TP
  2297. X\fBeval \fR[\fIlist\fR]
  2298. XConcatenates the elements of
  2299. X.I list
  2300. Xwith spaces and feeds the resulting string to
  2301. X.I rc
  2302. Xfor re-scanning.
  2303. XThis is the only time input is rescanned in
  2304. X.IR rc .
  2305. X.TP
  2306. X\fBexec \fR[\fIarg ...\fR]
  2307. XReplaces
  2308. X.I rc
  2309. Xwith the given command.
  2310. XIf the exec contains only redirections,
  2311. Xthen these redirections apply to the current shell
  2312. Xand the shell does not exit.
  2313. XFor example,
  2314. X.Ds
  2315. X.Cr "exec >[2] err.out"
  2316. X.De
  2317. X.TP
  2318. X\&
  2319. Xplaces further output to standard error in the file
  2320. X.IR err.out .
  2321. X.TP
  2322. X\fBexit \fR[\fIstatus\fR]
  2323. XCause the current shell to exit with the given exit
  2324. X.IR status .
  2325. XIf no argument is given, the current value of
  2326. X.Cr $status
  2327. Xis used.
  2328. X.TP
  2329. X\fBlimit \fR[\fB\-h\fR] [\fIresource \fR[\fIvalue\fR]]
  2330. XSimilar to the
  2331. X.IR csh (1)
  2332. X.B limit
  2333. Xbuiltin, this command operates upon the
  2334. XBSD-style limits of a process.
  2335. XThe
  2336. X.Cr \-h
  2337. Xflag displays/alters the hard
  2338. Xlimits.
  2339. XThe resources which can be shown or altered are
  2340. X.BR cputime ,
  2341. X.BR filesize ,
  2342. X.BR datasize ,
  2343. X.BR stacksize ,
  2344. X.B coredumpsize
  2345. Xand
  2346. X.BR memoryuse .
  2347. XFor
  2348. Xexample:
  2349. X.Ds
  2350. X.Cr "limit coredumpsize 0"
  2351. X.De
  2352. X.TP
  2353. X\&
  2354. Xdisables core dumps.
  2355. X.TP
  2356. X.B newpgrp
  2357. XPuts
  2358. X.I rc
  2359. Xinto a new process group.
  2360. XThis builtin is useful for making
  2361. X.I rc
  2362. Xbehave like a job-control shell in a hostile environment.
  2363. XOne example is the NeXT Terminal program, which implicitly assumes
  2364. Xthat each shell it forks will put itself into a new process group.
  2365. X.TP
  2366. X\fBreturn \fR[\fIn\fR]
  2367. XReturns from the current function, with status
  2368. X.IR n ,
  2369. Xwhere
  2370. X.IR n
  2371. Xis a single value or a list of possible exit statuses.
  2372. XThus it is legal to have
  2373. X.Ds
  2374. X.Cr "return (sigpipe 1 2 3)"
  2375. X.De
  2376. X.TP
  2377. X\&
  2378. X(This is commonly used to allow a function to return with the exit status
  2379. Xof a previously executed pipeline of commands.)
  2380. XIf
  2381. X.IR n
  2382. Xis omitted, then
  2383. X.Cr $status
  2384. Xis left unchanged.
  2385. XIt is an error to invoke
  2386. X.B return
  2387. Xwhen not inside a function.
  2388. X.TP
  2389. X\fBshift \fR[\fIn\fR]
  2390. XDeletes
  2391. X.I n
  2392. Xelements from the beginning of
  2393. X.Cr $*
  2394. Xand shifts the other
  2395. Xelements down by
  2396. X.IR n .
  2397. X.I n
  2398. Xdefaults to 1.
  2399. X(Note that
  2400. X.Cr $0
  2401. Xis not affected by
  2402. X.BR shift .)
  2403. X.TP
  2404. X\fBumask \fR[\fImask\fR]
  2405. XSets the current umask (see
  2406. X.IR umask (2))
  2407. Xto the octal
  2408. X.IR mask .
  2409. XIf no argument is present, the current mask value is printed.
  2410. X.TP
  2411. X\fBwait \fR[\fIpid\fR]
  2412. XWaits for the specified
  2413. X.IR pid ,
  2414. Xwhich must have been started by
  2415. X.IR rc .
  2416. XIf no
  2417. X.I pid
  2418. Xis specified,
  2419. X.I rc
  2420. Xwaits for any child process to exit.
  2421. X.TP
  2422. X\fBwhatis \fR[\fB\-s\fR] [\fB\-\|\-\fR] [\fIname ...\fR]
  2423. XPrints a definition of the named objects.
  2424. XFor variables, their values
  2425. Xare printed; for functions, their definitions are; and for executable
  2426. Xfiles, path names are printed.
  2427. XWithout arguments,
  2428. X.B whatis
  2429. Xprints the values of all shell variables and functions.
  2430. XWith a
  2431. X.Cr \-s
  2432. Xargument,
  2433. X.B whatis
  2434. Xalso prints out a list of available signals and their handlers (if any).
  2435. XNote that
  2436. X.B whatis
  2437. Xoutput is suitable for input to
  2438. X.IR rc ;
  2439. Xby saving the output of
  2440. X.B whatis
  2441. Xin a file, it should be possible to recreate the state of
  2442. X.I rc
  2443. Xby sourcing this file with a
  2444. X.Cr .
  2445. Xcommand.
  2446. XAnother note:
  2447. X.Cr "whatis -s > file"
  2448. Xcannot be used to store the state of
  2449. X.IR rc 's
  2450. Xsignal handlers in a file, because builtins with redirections
  2451. Xare run in a subshell, and
  2452. X.I rc
  2453. Xalways restores signal handlers to their default value after a
  2454. X.Cr fork() .
  2455. X.TP
  2456. X\&
  2457. XSince
  2458. X.B whatis
  2459. Xuses
  2460. X.IR getopt (3)
  2461. Xto parse its arguments, you can use the special argument
  2462. X.Cr "\-\|\-"
  2463. Xto terminate its options.
  2464. XThis allows you to use names beginning with a dash, such as
  2465. Xthe
  2466. X.IR history (1)
  2467. Xcommands.
  2468. XFor example,
  2469. X.Ds
  2470. X.Cr "whatis \-\|\- \-p"
  2471. X.De
  2472. X.SH GRAMMAR
  2473. XHere is
  2474. X.IR rc 's
  2475. Xgrammar, edited to remove semantic actions.
  2476. X.Ds
  2477. X.ft \*(Cf
  2478. X%term ANDAND BACKBACK BANG CASE COUNT DUP ELSE END FLAT FN FOR IF IN
  2479. X%term OROR PIPE REDIR SUB SUBSHELL SWITCH TWIDDLE WHILE WORD HUH
  2480. X
  2481. X%left WHILE ')' ELSE
  2482. X%left ANDAND OROR '\en'
  2483. X%left BANG SUBSHELL
  2484. X%left PIPE
  2485. X%right '$'
  2486. X%left SUB
  2487. X
  2488. X%start rc
  2489. X
  2490. X%%
  2491. X
  2492. Xrc: line end
  2493. X    | error end
  2494. X
  2495. Xend: END /* EOF */ | '\en'
  2496. X
  2497. Xcmdsa: cmd ';' | cmd '&'
  2498. X
  2499. Xline: cmd | cmdsa line
  2500. X
  2501. Xbody: cmd | cmdsan body
  2502. X
  2503. Xcmdsan: cmdsa | cmd '\en'
  2504. X
  2505. Xbrace: '{' body '}'
  2506. X
  2507. Xparen: '(' body ')'
  2508. X
  2509. Xassign: first '=' word
  2510. X
  2511. Xepilog: /* empty */ | redir epilog
  2512. X
  2513. Xredir: DUP | REDIR word
  2514. X
  2515. Xcase: CASE words ';' | CASE words '\en'
  2516. X
  2517. Xcbody: cmd | case cbody | cmdsan cbody
  2518. X
  2519. Xiftail: cmd    %prec ELSE
  2520. X    | brace ELSE optnl cmd
  2521. X
  2522. Xcmd    : /* empty */    %prec WHILE
  2523. X    | simple
  2524. X    | brace epilog
  2525. X    | IF paren optnl iftail
  2526. X    | FOR '(' word IN words ')' optnl cmd
  2527. X    | FOR '(' word ')' optnl cmd
  2528. X    | WHILE paren optnl cmd    
  2529. X    | SWITCH '(' word ')' optnl '{' cbody '}'
  2530. X    | TWIDDLE optcaret word words
  2531. X    | cmd ANDAND optnl cmd
  2532. X    | cmd OROR optnl cmd
  2533. X     | cmd PIPE optnl cmd
  2534. X    | redir cmd    %prec BANG
  2535. X    | assign cmd    %prec BANG
  2536. X    | BANG optcaret cmd
  2537. X    | SUBSHELL optcaret cmd
  2538. X    | FN words brace
  2539. X    | FN words
  2540. X
  2541. Xoptcaret: /* empty */ | '^'
  2542. X
  2543. Xsimple: first | simple word | simple redir
  2544. X
  2545. Xfirst: comword | first '^' sword
  2546. X
  2547. Xsword: comword | keyword
  2548. X
  2549. Xword: sword | word '^' sword
  2550. X
  2551. Xcomword: '$' sword
  2552. X    | '$' sword SUB words ')'
  2553. X    | COUNT sword
  2554. X    | FLAT sword
  2555. X    | '`' sword
  2556. X    | '`' brace
  2557. X    | BACKBACK word    brace | BACKBACK word sword
  2558. X    | '(' words ')'
  2559. X    | REDIR brace
  2560. X    | WORD
  2561. X
  2562. Xkeyword: FOR | IN | WHILE | IF | SWITCH
  2563. X    | FN | ELSE | CASE | TWIDDLE | BANG | SUBSHELL
  2564. X
  2565. Xwords: /* empty */ | words word
  2566. X
  2567. Xoptnl: /* empty */ | optnl '\en'
  2568. X.ft R
  2569. X.De
  2570. X.SH FILES
  2571. X.Cr $HOME/.rcrc ,
  2572. X.Cr /tmp/rc* ,
  2573. X.Cr /dev/null
  2574. X.SH CREDITS
  2575. X.I rc
  2576. Xwas written by Byron Rakitzis, with valuable help
  2577. Xfrom Paul Haahr, Hugh Redelmeier and David Sanderson.
  2578. XThe design of this shell has been copied from the
  2579. X.I rc
  2580. Xthat Tom Duff wrote at Bell Labs.
  2581. X.SH BUGS
  2582. XOn systems that support
  2583. X.Cr /dev/fd ,
  2584. X.Cr <{foo}
  2585. Xstyle redirection is implemented that way.
  2586. XHowever, on other systems it is implemented with named pipes,
  2587. Xand it is sometimes
  2588. Xpossible to foil
  2589. X.I rc
  2590. Xinto removing the FIFO it places in
  2591. X.Cr /tmp
  2592. Xprematurely, or it is even possible to cause
  2593. X.I rc
  2594. Xto hang.
  2595. X.PP
  2596. XThe functionality of
  2597. X.B shift
  2598. Xshould be available for variables other than
  2599. X.Cr "$*" .
  2600. X.PP
  2601. X.B echo
  2602. Xis built in only for performance reasons, which is a bad idea.
  2603. X.PP
  2604. XThere should be a way to avoid exporting a variable.
  2605. X.PP
  2606. XThe
  2607. X.Cr $^var
  2608. Xnotation for flattening should allow for using an arbitrary
  2609. Xseparating character, not just space.
  2610. X.PP
  2611. XBug reports should be mailed to
  2612. X.Cr "byron@archone.tamu.edu" .
  2613. X.SH INCOMPATIBILITIES
  2614. XHere is a list of features which distinguish this incarnation of
  2615. X.I rc
  2616. Xfrom the one described in the Bell Labs manual pages:
  2617. X.PP
  2618. XThe treatment of
  2619. X.Cr if - else
  2620. Xis different in the v10
  2621. X.IR rc :
  2622. Xthat version uses an
  2623. X.Cr "if not"
  2624. Xclause which gets executed
  2625. Xif the preceding
  2626. X.Cr if
  2627. Xtest does not succeed.
  2628. X.PP
  2629. XBackquotes are slightly different in v10
  2630. X.IR rc :
  2631. Xa backquote must always be followed by a left-brace.
  2632. XThis restriction is not present for single-word commands in this
  2633. X.IR rc .
  2634. X.PP
  2635. XThe following are all new with this version of
  2636. X.IR rc :
  2637. XThe
  2638. X.Cr \-n
  2639. Xoption,
  2640. Xthe list flattening operator,
  2641. Xhere strings (they facilitate exporting of functions
  2642. Xwith here documents into the environment),
  2643. Xthe
  2644. X.B return
  2645. Xand
  2646. X.B break
  2647. Xkeywords,
  2648. Xthe
  2649. X.B echo
  2650. Xbuiltin,
  2651. Xthe support for the GNU
  2652. X.IR readline (3)
  2653. Xlibrary and
  2654. Xthe support for the
  2655. X.Cr prompt
  2656. Xfunction.
  2657. XThis
  2658. X.I rc
  2659. Xalso sets
  2660. X.Cr $0
  2661. Xto the name of a function being executed/file
  2662. Xbeing sourced.
  2663. X.SH "SEE ALSO"
  2664. X``rc \(em A Shell for Plan 9 and UNIX Systems'',
  2665. XUnix Research System,
  2666. X10th Edition,
  2667. Xvol. 2. (Saunders College Publishing)
  2668. X(This paper is also distributed with this
  2669. X.I rc
  2670. Xin PostScript form.)
  2671. X.PP
  2672. X.IR history (1)
  2673. END_OF_FILE
  2674.   if test 39683 -ne `wc -c <'rc.1'`; then
  2675.     echo shar: \"'rc.1'\" unpacked with wrong size!
  2676.   fi
  2677.   # end of 'rc.1'
  2678. fi
  2679. echo shar: End of archive 2 \(of 7\).
  2680. cp /dev/null ark2isdone
  2681. MISSING=""
  2682. for I in 1 2 3 4 5 6 7 ; do
  2683.     if test ! -f ark${I}isdone ; then
  2684.     MISSING="${MISSING} ${I}"
  2685.     fi
  2686. done
  2687. if test "${MISSING}" = "" ; then
  2688.     echo You have unpacked all 7 archives.
  2689.     rm -f ark[1-9]isdone
  2690. else
  2691.     echo You still must unpack the following archives:
  2692.     echo "        " ${MISSING}
  2693. fi
  2694. exit 0
  2695. exit 0 # Just in case...
  2696.