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

  1. From: pfalstad@phoenix.Princeton.EDU (Paul John Falstad)
  2. Newsgroups: alt.sources
  3. Subject: zsh - ksh/tcsh-like shell (part 5 of 8)
  4. Message-ID: <4746@idunno.Princeton.EDU>
  5. Date: 14 Dec 90 23:32:05 GMT
  6.  
  7. ---cut here---cut here---cut here---
  8. -{
  9. -list2 l2 = (list2) alloc(sizeof *l2);
  10. -int iter = 0;
  11. -
  12. -    for (;;)
  13. -        {
  14. -        if (peek == BANG)
  15. -            {
  16. -            l2->flags |= PFLAG_NOT;
  17. -            matchit();
  18. -            }
  19. -        else if (peek == TIME)
  20. -            {
  21. -            l2->flags |= PFLAG_TIMED;
  22. -            matchit();
  23. -            }
  24. -        else if (peek == COPROC)
  25. -            {
  26. -            l2->flags |= PFLAG_COPROC;
  27. -            matchit();
  28. -            }
  29. -        else
  30. -            break;
  31. -        iter = 1;
  32. -        }
  33. -    if (!(l2->left = parpline()))
  34. -        {
  35. -        free(l2);
  36. -        if (!errflag && iter)
  37. -            {
  38. -            zerr("parse error: pipeline expected");
  39. -            errflag = 1;
  40. -            }
  41. -        return NULL;
  42. -        }
  43. -    if (peek == DAMPER || peek == DBAR)
  44. -        {
  45. -        l2->type = (peek == DAMPER) ? ANDNEXT : ORNEXT;
  46. -        matchit();
  47. -        while (peek == NEWLIN)
  48. -            matchit();
  49. -        if (!(l2->right = parlist2()))
  50. -            {
  51. -            if (!errflag)
  52. -                {
  53. -                zerr("invalid null command");
  54. -                errflag = 1;
  55. -                }
  56. -            freepline(l2->left);
  57. -            free(l2);
  58. -            return NULL;
  59. -            }
  60. -        }
  61. -    else
  62. -        {
  63. -        l2->type = END;
  64. -        l2->right = NULL;
  65. -        }
  66. -    return l2;
  67. -}
  68. -
  69. -/* parse a pipeline */
  70. -
  71. -pline parpline(void)
  72. -{
  73. -pline p = (pline) alloc(sizeof *p);
  74. -
  75. -    if (!(p->left = parcmd()))
  76. -        {
  77. -        free(p);
  78. -        return NULL;
  79. -        }
  80. -    if (peek == HERR)
  81. -        {
  82. -        freecmd(p->left);
  83. -        free(p);
  84. -        return NULL;
  85. -        }
  86. -    if (peek == BAR || peek == BARAMP)
  87. -        {
  88. -        if (peek == BARAMP)
  89. -            {
  90. -            struct fnode *f;
  91. -
  92. -            f = alloc(sizeof *f);
  93. -            f->type = MERGEOUT;
  94. -            f->fd1 = 2;
  95. -            f->u.fd2 = 1;
  96. -            addnode(p->left->redir,f);
  97. -            }
  98. -        matchit();
  99. -        while (peek == NEWLIN)
  100. -            matchit();
  101. -        p->type = PIPE;
  102. -        if (!(p->right = parpline()))
  103. -            {
  104. -            if (!errflag)
  105. -                {
  106. -                zerr("invalid null command");
  107. -                errflag = 1;
  108. -                }
  109. -            freecmd(p->left);
  110. -            free(p);
  111. -            return NULL;
  112. -            }
  113. -        }
  114. -    else
  115. -        {
  116. -        p->type = END;
  117. -        p->right = NULL;
  118. -        }
  119. -    return p;
  120. -}
  121. -
  122. -/* parse a command */
  123. -
  124. -comm parcmd(void)
  125. -{
  126. -comm c = (comm) alloc(sizeof *c);
  127. -list l;
  128. -char *str;
  129. -int flag,iter = 0;
  130. -
  131. -    incmd = 0;
  132. -    c->left = NULL;
  133. -    c->cmd = NULL;
  134. -    c->args = newtable();
  135. -    c->redir = newtable();
  136. -    c->type = SIMPLE;
  137. -    c->vars = NULL;
  138. -    if (peek == EOF)
  139. -        return NULL;
  140. -foo:
  141. -    switch (peek)
  142. -        {
  143. -        case HERR:
  144. -            return NULL;
  145. -        case ENVSTRING:
  146. -            if (!c->vars)
  147. -                c->vars = newtable(); /* FIX */
  148. -            for (str = tstr; *str != '='; str++);
  149. -            *str++ = '\0';
  150. -            addnode(c->vars,tstr);
  151. -            addnode(c->vars,strdup(str));
  152. -            matchit();
  153. -            goto foo;
  154. -        case FOR:
  155. -            incmd = 1;
  156. -            matchit();
  157. -            if (parfor(c,1))
  158. -                return NULL;
  159. -            break;
  160. -        case SELECT:
  161. -            incmd = 1;
  162. -            matchit();
  163. -            if (parfor(c,0))
  164. -                return NULL;
  165. -            break;
  166. -        case CASE:
  167. -            incmd = 1;
  168. -            matchit();
  169. -            if (parcase(c))
  170. -                return NULL;
  171. -            break;
  172. -        case IF:
  173. -            matchit();
  174. -            if (parif(c))
  175. -                return NULL;
  176. -            break;
  177. -        case WHILE:
  178. -            matchit();
  179. -            if (parwhile(c,0))
  180. -                return NULL;
  181. -            break;
  182. -        case UNTIL:
  183. -            matchit();
  184. -            if (parwhile(c,1))
  185. -                return NULL;
  186. -            break;
  187. -        case REPEAT:
  188. -            incmd = 1;
  189. -            matchit();
  190. -            if (parrepeat(c))
  191. -                return NULL;
  192. -            break;
  193. -        case INPAR:
  194. -            matchit();
  195. -            c->type = SUBSH;
  196. -            if (!(c->left = parlist(1)))
  197. -                {
  198. -                freecmd(c);
  199. -                return NULL;
  200. -                }
  201. -            if (peek != OUTPAR)
  202. -                {
  203. -                freecmd(c);
  204. -                zerr("parse error: '}' expected");
  205. -                return NULL;
  206. -                }
  207. -            matchit();
  208. -            break;
  209. -        case INBRACE:
  210. -            matchit();
  211. -            c->type = CURSH;
  212. -            if (!(c->left = parlist(1)))
  213. -                {
  214. -                freecmd(c);
  215. -                return NULL;
  216. -                }
  217. -            if (peek != OUTBRACE)
  218. -                {
  219. -                freecmd(c);
  220. -                zerr("parse error: '}' expected");
  221. -                return NULL;
  222. -                }
  223. -            matchit();
  224. -            break;
  225. -        case FUNC:
  226. -            matchit();
  227. -            str = tstr;
  228. -            if (peek != STRING && peek != ENVSTRING)
  229. -                {
  230. -                c->cmd = strdup("function");
  231. -                incmd = 1;
  232. -                if (isredir())
  233. -                    goto jump1;
  234. -                else
  235. -                    goto jump2;
  236. -                }
  237. -            do    
  238. -                matchit();
  239. -            while (peek == NEWLIN);
  240. -            if (peek != INBRACE)
  241. -                {
  242. -                freecmd(c);
  243. -                zerr("parse error: '{' expected");
  244. -                return NULL;
  245. -                }
  246. -            matchit();
  247. -            flag = peek == OUTBRACE;
  248. -            if (!(l = parlist(1)))
  249. -                {
  250. -                freecmd(c);
  251. -                return NULL;
  252. -                }
  253. -            if (peek != OUTBRACE)
  254. -                {
  255. -                freelist(l);
  256. -                freecmd(c);
  257. -                zerr("parse error: '}' expected");
  258. -                return NULL;
  259. -                }
  260. -            matchit();
  261. -            settrap(str,flag);
  262. -            addhnode(str,l,shfunchtab,freeshfunc);
  263. -            c->cmd = strdup("");
  264. -            c->type = SIMPLE;
  265. -            break;
  266. -        case EXEC:
  267. -            c->flags |= CFLAG_EXEC;
  268. -            matchit();
  269. -            iter = 1;
  270. -            goto foo;
  271. -        case COMMAND:
  272. -            c->flags |= CFLAG_COMMAND;
  273. -            matchit();
  274. -            iter = 1;
  275. -            goto foo;
  276. -        default:
  277. -jump1:
  278. -            if (isredir())
  279. -                {
  280. -                if (parredir(c))
  281. -                    {
  282. -                    freecmd(c);
  283. -                    return NULL;
  284. -                    }
  285. -                goto foo;
  286. -                }
  287. -            if (!(peek == STRING || peek == ENVSTRING))
  288. -                {
  289. -                if (full(c->redir))
  290. -                    {
  291. -                    c->cmd = strdup("cat");
  292. -                    return c;
  293. -                    }
  294. -                if (c->vars)
  295. -                    {
  296. -                    c->cmd = strdup("");
  297. -                    return c;
  298. -                    }
  299. -                free(c->args);
  300. -                free(c->redir);
  301. -                free(c);
  302. -                if (iter && !errflag)
  303. -                    {
  304. -                    errflag = 1;
  305. -                    zerr("parse error: command expected");
  306. -                    }
  307. -                return NULL;
  308. -                }
  309. -jump2:
  310. -            while (peek == STRING || peek == ENVSTRING || isredir())
  311. -                if (isredir())
  312. -                    {
  313. -                    if (parredir(c))
  314. -                        {
  315. -                        freecmd(c);
  316. -                        return NULL;
  317. -                        }
  318. -                    }
  319. -                else
  320. -                    {
  321. -                    if (tstr[0] == Inpar && tstr[1] == Outpar && !tstr[2])
  322. -                        {
  323. -                        free(tstr);
  324. -                        incmd = 0;
  325. -                        matchit();
  326. -                        if (full(c->args))
  327. -                            {
  328. -                            zerr("illegal function definition");
  329. -                            freecmd(c);
  330. -                            return NULL;
  331. -                            }
  332. -                        while (peek == NEWLIN)
  333. -                            matchit();
  334. -                        if (peek != INBRACE)
  335. -                            {
  336. -                            freecmd(c);
  337. -                            zerr("parse error: '{' expected");
  338. -                            return NULL;
  339. -                            }
  340. -                        matchit();
  341. -                        flag = peek == OUTBRACE;
  342. -                        if (!(l = parlist(1)))
  343. -                            {
  344. -                            freecmd(c);
  345. -                            return NULL;
  346. -                            }
  347. -                        if (peek != OUTBRACE)
  348. -                            {
  349. -                            freelist(l);
  350. -                            freecmd(c);
  351. -                            zerr("parse error: '}' expected");
  352. -                            return NULL;
  353. -                            }
  354. -                        matchit();
  355. -                        settrap(c->cmd,flag);
  356. -                        addhnode(c->cmd,l,shfunchtab,freeshfunc);
  357. -                        c->cmd = strdup("");
  358. -                        c->type = SIMPLE;
  359. -                        incmd = 0;
  360. -                        return c;
  361. -                        }
  362. -                    if (peek == ENVSTRING && (!incmd || opts[KEYWORD] == OPT_SET))
  363. -                        {
  364. -                        if (!c->vars)
  365. -                            c->vars = newtable(); /* FIX */
  366. -                        for (str = tstr; *str != '='; str++);
  367. -                        *str++ = '\0';
  368. -                        addnode(c->vars,tstr);
  369. -                        addnode(c->vars,strdup(str));
  370. -                        }
  371. -                    else if (c->cmd)
  372. -                        addnode(c->args,tstr);
  373. -                    else
  374. -                        {
  375. -                        c->cmd = tstr;
  376. -                        incmd = 1;
  377. -                        }
  378. -                    matchit();
  379. -                    }
  380. -            break;
  381. -        }
  382. -    while (isredir())
  383. -        if (parredir(c))
  384. -            {
  385. -            freecmd(c);
  386. -            return NULL;
  387. -            }
  388. -    incmd = 0;
  389. -    if (peek == HERR)
  390. -        {
  391. -        freecmd(c);
  392. -        return NULL;
  393. -        }
  394. -    return c;
  395. -}
  396. -
  397. -/* != 0 if peek is a redirection operator */
  398. -
  399. -int isredir(void)
  400. -{
  401. -    return (peek >= OUTANG && peek <= DOUTANGAMPBANG);
  402. -}
  403. -
  404. -/* get fd associated with str */
  405. -
  406. -int getfdstr(char *s)
  407. -{
  408. -    if (s[1])
  409. -        return -1;
  410. -    if (isdigit(*s))
  411. -        return *s-'0';
  412. -    if (*s == 'p')
  413. -        return -2;
  414. -    return -1;
  415. -}
  416. -
  417. -int parredir(comm c)
  418. -{
  419. -struct fnode *fn = (struct fnode *) alloc(sizeof *fn);
  420. -int pk = peek,ic = incmd,mrg2 = 0;
  421. -
  422. -    fn->type = peek-OUTANG+WRITE;
  423. -    if (peek == OUTANGAMP)
  424. -        fn->type = MERGEOUT;
  425. -    if (peekfd != -1)
  426. -        fn->fd1 = peekfd;
  427. -    else if (peek <= DOUTANGBANG || peek >= OUTANGAMP)
  428. -        fn->fd1 = 1;
  429. -    else
  430. -        fn->fd1 = 0;
  431. -    incmd = 1;
  432. -    matchit();
  433. -    incmd = ic;
  434. -    if (peek != STRING)
  435. -        {
  436. -        zerr("parse error: filename expected");
  437. -        return 1;
  438. -        }
  439. -    
  440. -    if ((*tstr == Inang || *tstr == Outang) && tstr[1] == Inpar)
  441. -        {
  442. -        if (fn->type == WRITE)
  443. -            fn->type = OUTPIPE;
  444. -        else if (fn->type == READ)
  445. -            fn->type = INPIPE;
  446. -        else
  447. -            {
  448. -            zerr("parse error: bad process redirection");
  449. -            return 1;
  450. -            }
  451. -        fn->u.name = tstr;
  452. -        }
  453. -    else if (fn->type == HEREDOC)
  454. -        fn->u.fd2 = gethere(tstr);
  455. -    else if (pk >= OUTANGAMP && getfdstr(tstr) == -1)
  456. -        {
  457. -        mrg2 = 1;
  458. -        fn->u.name = tstr;
  459. -        fn->type = pk-OUTANGAMP;
  460. -        }
  461. -    else if (pk > OUTANGAMPBANG)
  462. -        {
  463. -        zerr("parse error: filename expected");
  464. -        return 1;
  465. -        }
  466. -    else if (pk == OUTANGAMPBANG)
  467. -        {
  468. -        struct fnode *fe = alloc(sizeof *fe);
  469. -
  470. -        fe->fd1 = fn->fd1;
  471. -        fe->type = CLOSE;
  472. -        addnode(c->redir,fe);
  473. -        fn->u.fd2 = getfdstr(tstr);
  474. -        if (fn->u.fd2 == -2)
  475. -            fn->u.fd2 = spout;
  476. -        fn->type = MERGEOUT;
  477. -        }
  478. -    else if (fn->type == MERGE || fn->type == MERGEOUT)
  479. -        {
  480. -        if (*tstr == '-')
  481. -            fn->type = CLOSE;
  482. -        else
  483. -            {
  484. -            fn->u.fd2 = getfdstr(tstr);
  485. -            if (fn->u.fd2 == -2)
  486. -                fn->u.fd2 = (pk == OUTANGAMP) ? spout : spin;
  487. -            }
  488. -        }
  489. -    else
  490. -        fn->u.name = tstr;
  491. -    addnode(c->redir,fn);
  492. -    if (mrg2)
  493. -        {
  494. -        struct fnode *fe = alloc(sizeof *fe);
  495. -
  496. -        fe->fd1 = 2;
  497. -        fe->u.fd2 = fn->fd1;
  498. -        fe->type = MERGEOUT;
  499. -        addnode(c->redir,fe);
  500. -        }
  501. -    matchit();
  502. -    return 0;
  503. -}
  504. -
  505. End of parse.c
  506. echo parse.pro 1>&2
  507. sed 's/^-//' >parse.pro <<'End of parse.pro'
  508. -list parlist(int nest);
  509. -list parlist1(int nest);
  510. -list2 parlist2(void);
  511. -pline parpline(void);
  512. -comm parcmd(void);
  513. -int isredir(void);
  514. -int getfdstr(char *s);
  515. -int parredir(comm c);
  516. End of parse.pro
  517. echo subst.c 1>&2
  518. sed 's/^-//' >subst.c <<'End of subst.c'
  519. -/*
  520. -
  521. -    subst.c - various substitution
  522. -
  523. -    This file is part of zsh, the Z shell.
  524. -
  525. -   zsh is free software; no one can prevent you from reading the source
  526. -   code, or giving it to someone else.
  527. -   This file is copyrighted under the GNU General Public License, which
  528. -   can be found in the file called COPYING.
  529. -
  530. -   Copyright (C) 1990 Paul Falstad
  531. -
  532. -   zsh is distributed in the hope that it will be useful, but
  533. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  534. -   responsibility to anyone for the consequences of using it or for
  535. -   whether it serves any particular purpose or works at all, unless he
  536. -   says so in writing.  Refer to the GNU General Public License
  537. -   for full details.
  538. -
  539. -   Everyone is granted permission to copy, modify and redistribute
  540. -   zsh, but only under the conditions described in the GNU General Public
  541. -   License.   A copy of this license is supposed to have been given to you
  542. -   along with zsh so you can know your rights and responsibilities.
  543. -   It should be in a file named COPYING.
  544. -
  545. -   Among other things, the copyright notice and this notice must be
  546. -   preserved on all copies.
  547. -
  548. -*/
  549. -
  550. -#include "zsh.h"
  551. -#include "funcs.h"
  552. -#include <pwd.h>
  553. -#define MAXPATHLEN 1024
  554. -
  555. -#define magicerr() { if (magic) putc('\n',stderr); }
  556. -
  557. -/* do substitutions before fork */
  558. -
  559. -void prefork(table list)
  560. -{
  561. -Node node = list->first;
  562. -
  563. -    while (node)
  564. -        {
  565. -        char *str,*str3;
  566. -        
  567. -        str = str3 = node->dat;
  568. -        if (!magic && str[1] == Inpar && (*str == Inang ||
  569. -                *str == Outang || *str == Equals))
  570. -            {
  571. -            if (*str == Inang)
  572. -                node->dat = getoutproc(str+2);        /* <(...) */
  573. -            else if (*str == Equals)
  574. -                node->dat = getoutputfile(str+2);    /* =(...) */
  575. -            else
  576. -                node->dat = getinproc(str+2);            /* >(...) */
  577. -            free(str);
  578. -            if (!node->dat)
  579. -                {
  580. -                zerr("parse error in process substitution");
  581. -                errflag = 1;
  582. -                return;
  583. -                }
  584. -            }
  585. -        else while (*str)
  586. -            {
  587. -            if (*str == String || *str == Qstring)
  588. -                if (str[1] != Inpar)
  589. -                    if (str[1] == '*' || str[1] == Star)
  590. -                        parminsall(list,&node,&str,&str3);    /* $* */
  591. -                    else if (str[1] == Inbrack)
  592. -                        {
  593. -                        arithsuber((void **) &str,&str3);    /* $[...] */
  594. -                        if (magic)
  595. -                            magic = 2;
  596. -                        node->dat = str3;
  597. -                        }
  598. -                    else
  599. -                        {
  600. -                        parmsuber(str,&str3);        /* $foo */
  601. -                        node->dat = str = str3;
  602. -                        if (errflag)
  603. -                            return;
  604. -                        continue;
  605. -                        }
  606. -            str++;
  607. -            if (errflag)
  608. -                return;
  609. -            }
  610. -        node = node->next;
  611. -        }
  612. -}
  613. -
  614. -void postfork(table list,int globstat)
  615. -{
  616. -Node node = list->first;
  617. -int glb = 1;
  618. -
  619. -    if (isset(NOGLOBOPT) || globstat != GLOB)
  620. -        glb = 0;
  621. -    while (node)
  622. -        {
  623. -        char *str,*str3;
  624. -        
  625. -        str = str3 = node->dat;
  626. -        while (*str)
  627. -            {
  628. -            if (((*str == String || *str == Qstring) && str[1] == Inpar) ||
  629. -                    *str == Tick || *str == Qtick)
  630. -                comminsall(list,&node,&str,&str3);    /* `...`,$(...) */
  631. -            str++;
  632. -            if (errflag)
  633. -                return;
  634. -            }
  635. -        
  636. -        /* now we remove the Nulargs tokens if this is not a null
  637. -            arguments.  The lexical analyzer throws these in so that
  638. -            zsh will not look at this:
  639. -
  640. -            $PA"TH"
  641. -
  642. -            and expand it to $PATH.  But after parameter substitution
  643. -            these are only a nuisance, so we remove them. */
  644. -
  645. -        if (*(char *) node->dat)
  646. -            remnulargs(node->dat);
  647. -        
  648. -        if (unset(IGNOREBRACES))
  649. -            while (hasbraces(node->dat))
  650. -                xpandbraces(list,&node);
  651. -        filesub(&node->dat);
  652. -        if (errflag)
  653. -            return;
  654. -        if (glb)
  655. -            {
  656. -            if (haswilds(node->dat))
  657. -                glob(list,&node);
  658. -            if (errflag)
  659. -                return;
  660. -            }
  661. -        else if (globstat == MOSTGLOB && *(char *) node->dat != '-')
  662. -            glb = 1;
  663. -        node = node->next;
  664. -        }
  665. -}
  666. -
  667. -/* strdup, but returns "Nularg" if this is a null string */
  668. -
  669. -void *nstrdup(void *s)
  670. -{
  671. -char *t = s,u[] = {Nularg,'\0'};
  672. -
  673. -    if (!*t)
  674. -        return strdup(u);
  675. -    return strdup(t);
  676. -}
  677. -
  678. -/* $* */
  679. -
  680. -void parminsall(table l,Node *nn,char **aptr,char **bptr)
  681. -{
  682. -char *str3 = *aptr,*str = *bptr;
  683. -Node n = *nn,where = n->last;
  684. -table pl;
  685. -
  686. -    if (magic)
  687. -        magic = 2;
  688. -    *str3 = '\0';
  689. -    str3 += 2;
  690. -    remnode(l,n);
  691. -    pl = duptable(pparms,nstrdup);
  692. -    free(getnode(pl));
  693. -    if (pl->first)    /* if $# > 1 */
  694. -        {
  695. -        char *ptr;
  696. -        Node tmp;
  697. -
  698. -        ptr = pl->first->dat;
  699. -        pl->first->dat = dyncat(str,ptr);
  700. -        free(ptr);
  701. -        ptr = pl->last->dat;
  702. -        *bptr = pl->last->dat = dyncat(ptr,str3);
  703. -        *aptr = *bptr+strlen(str)+strlen(ptr)-1;
  704. -        free(ptr);
  705. -        tmp = where->next;
  706. -        where->next = pl->first;
  707. -        pl->last->next = tmp;
  708. -        pl->first->last = where;
  709. -        if (tmp)
  710. -            tmp->last = pl->last;
  711. -        else
  712. -            l->last = pl->last;
  713. -        *nn = pl->last;
  714. -        }
  715. -    else    /* just remove the $* */
  716. -        {
  717. -        insnode(l,where,*bptr = dyncat(str,str3));
  718. -        *nn = where->next;
  719. -        *aptr = *bptr+strlen(str)-1;
  720. -        }
  721. -}
  722. -
  723. -char *dynread(char stop)
  724. -{
  725. -int bsiz = 256,ct = 0,c;
  726. -char *buf = zalloc(bsiz),*ptr;
  727. -    ptr = buf;
  728. -    while ((c = hgetc()) != stop)
  729. -        {
  730. -        *ptr++ = c;
  731. -        if (++ct == bsiz)
  732. -            {
  733. -            buf = realloc(buf,bsiz *= 2);
  734. -            ptr = buf+ct;
  735. -            }
  736. -        }
  737. -    *ptr = 0;
  738. -    return buf;
  739. -}
  740. -
  741. -int filesub(void **namptr)
  742. -{
  743. -char *str = *namptr,*cnam;
  744. -
  745. -    if (*str == Tilde && str[1] != '=')
  746. -        {
  747. -        if (str[1] == '+')
  748. -            {
  749. -            char *foo = strdup(cwd),*t = str;    /* ~+ */
  750. -
  751. -            str+=2;
  752. -            modify((void **) &foo,&str);
  753. -            *namptr = dyncat(cwd,str);
  754. -            free(foo);
  755. -            free(t);
  756. -            return 1;
  757. -            }
  758. -        else if (str[1] == '-')            /* ~- */
  759. -            {
  760. -            char *foo,*t = str;
  761. -
  762. -            if (cnam = getparm("OLDPWD"))
  763. -                foo = cnam;
  764. -            else
  765. -                foo = cwd;
  766. -            str += 2;
  767. -            foo = strdup(foo);
  768. -            modify((void **) &foo,&str);
  769. -            *namptr = dyncat(foo,str);
  770. -            free(t);
  771. -            free(foo);
  772. -            return 1;
  773. -            }
  774. -        if (isalpha(str[1]))        /* ~foo */
  775. -            {
  776. -            char *ptr,*home;
  777. -            for (ptr = ++str; *ptr && !istok(*ptr) && (isalnum(*ptr) || *ptr == '-'); ptr++)
  778. -                if (*ptr == '-')
  779. -                    *ptr = '-';
  780. -            if (!(home = gethome(str,ptr-str)))
  781. -                {
  782. -                if (magic)
  783. -                    home = completehome(str,ptr-str);
  784. -                if (!home)
  785. -                    {
  786. -                    magicerr();
  787. -                    zerr("user not found: %l",ptr-str,str);
  788. -                    errflag = 1;
  789. -                    return 0;
  790. -                    }
  791. -                }
  792. -            modify((void **) &home,&ptr);
  793. -            *namptr = dyncat(home,ptr);
  794. -            free(home);
  795. -            free(str-1);
  796. -            return 1;
  797. -            }
  798. -        else if (str[1] == '/')    /* ~/foo */
  799. -            {
  800. -            *namptr = dyncat(home,str+1);
  801. -            free(str);
  802. -            return 1;
  803. -            }
  804. -        else if (!str[1])        /* ~ by itself */
  805. -            {
  806. -            free(str);
  807. -            *namptr = strdup(home);
  808. -            return 1;
  809. -            }
  810. -        }
  811. -    if (*str == Equals && !istok(str[1]) && (isalnum(str[1]) || str[1] == '-'))
  812. -        {
  813. -        char *ptr,*s,*ds;
  814. -        int val;
  815. -        
  816. -        untokenize(str);
  817. -        if (isalpha(str[1]))        /* =foo */
  818. -            {
  819. -            struct chnode *chn;
  820. -            struct anode *t;
  821. -            char sav,*pp;
  822. -            for (pp = str+1; *pp && *pp != ':'; pp++);
  823. -            sav = *pp;
  824. -            *pp = '\0';
  825. -            if ((t = gethnode(str+1,alhtab)) && t->cmd)
  826. -                if (t->cmd >= 0)
  827. -                    cnam = strdup(t->text);
  828. -                else
  829. -                    {
  830. -                    magicerr();
  831. -                    zerr("%s: shell reserved word",str+1);
  832. -                    errflag = 1;
  833. -                    return 0;
  834. -                    }
  835. -             else if (chn = gethnode(str+1,chtab))
  836. -                if (chn->type != BUILTIN)
  837. -                    cnam = strdup(chn->u.nam);
  838. -                else
  839. -                    {
  840. -                    magicerr();
  841. -                    zerr("%s: shell built-in command",str+1);
  842. -                    errflag = 1;
  843. -                    return 0;
  844. -                    }
  845. -            else if (!(cnam = findcmd(str+1)))
  846. -                {
  847. -                magicerr();
  848. -                zerr("%s not found",str+1);
  849. -                errflag = 1;
  850. -                return 0;
  851. -                }
  852. -            *namptr = cnam;
  853. -            if ((*pp = sav) == ':')
  854. -                {
  855. -                modify(namptr,&pp);
  856. -                s = *namptr;
  857. -                *namptr = dyncat(*namptr,pp);
  858. -                free(s);
  859. -                }
  860. -            free(str);
  861. -            return 1;
  862. -            }
  863. -        if (str[1] == '-')     /* =- */
  864. -            {
  865. -            val = -1;
  866. -            ptr = str+2;
  867. -            }
  868. -        else
  869. -            val = strtol(str+1,&ptr,10);    /* =# */
  870. -        ds = dstackent(val);
  871. -        if (!ds)
  872. -            return 1;
  873. -        s = strdup(ds);
  874. -        modify((void **) &s,&ptr);
  875. -        *namptr = dyncat(s,ptr);
  876. -        free(s);
  877. -        free(str);
  878. -        return 1;
  879. -        }
  880. -    return 0;
  881. -}
  882. -
  883. -/* get a user's directory */
  884. -
  885. -char *gethome(char *user,int len)
  886. -{
  887. -char sav,*str;
  888. -struct passwd *pw;
  889. -    sav = user[len];
  890. -    user[len] = '\0';
  891. -    if (!(pw = getpwnam(user)))
  892. -        {
  893. -        user[len] = sav;
  894. -        return NULL;
  895. -        }
  896. -    str = xsymlink(pw->pw_dir);
  897. -    user[len] = sav;
  898. -    return str;
  899. -}
  900. -
  901. -/* complete a user and try to get his home directory */
  902. -
  903. -char *completehome(char *user,int len)
  904. -{
  905. -FILE *in;
  906. -char buf[MAXPATHLEN],*str;
  907. -
  908. -    sprintf(buf,"%s/.zfriends",getparm("HOME"));
  909. -    if (!(in = fopen(buf,"r")))
  910. -        return NULL;
  911. -    while (fgetline(buf,MAXPATHLEN,in))
  912. -        if (!strncmp(user,buf,len))
  913. -            if (str = gethome(buf,strlen(buf)))
  914. -                {
  915. -                fclose(in);
  916. -                return str;
  917. -                }
  918. -    fclose(in);
  919. -    return NULL;
  920. -}
  921. -
  922. -/* get the value of the parameter specified by the first len
  923. -    characters of s */
  924. -
  925. -char *getsparmval(char *s,int len)
  926. -{
  927. -char sav = s[len];
  928. -char *val;
  929. -char buf[50];
  930. -int t0;
  931. -
  932. -    if (len == 1 && (istok(*s) || !isalnum(*s)))
  933. -        switch(*s)
  934. -            {
  935. -            case Pound:
  936. -            case '#':
  937. -                sprintf(buf,"%d",ppcount());
  938. -                return strdup(buf);
  939. -            case '-':
  940. -                for (val = buf, t0 = ' '; t0 <= 'z'; t0++)
  941. -                    if (opts[t0] == OPT_SET)
  942. -                        *val++ = t0;
  943. -                *val = '\0';
  944. -                return strdup(buf);
  945. -            case '?':
  946. -            case Quest:
  947. -                sprintf(buf,"%d",lastval);
  948. -                return strdup(buf);
  949. -            case '$':
  950. -            case String:
  951. -                sprintf(buf,"%d",procnum);
  952. -                return strdup(buf);
  953. -            case '!':
  954. -                sprintf(buf,"%d",proclast);
  955. -                return strdup(buf);
  956. -            default:
  957. -                return NULL;
  958. -            }
  959. -    s[len] = '\0';
  960. -    if (isdigit(*s))
  961. -        {
  962. -        int num;
  963. -        Node node;
  964. -        
  965. -        num = atoi(s);
  966. -        s[len] = sav;
  967. -        for (node = pparms->first; node && num; num--,node = node->next);
  968. -        return (node) ? strdup(node->dat) : NULL;
  969. -        }
  970. -    val = getparm(s);
  971. -    s[len] = sav;
  972. -    return (val) ? strdup(val) : NULL;
  973. -}
  974. -
  975. -/* set the parameter associated with the first len characters of s
  976. -    to v. */
  977. -
  978. -void setparml(char *s,int len,char *v)
  979. -{
  980. -char c;
  981. -    c = s[len];
  982. -    s[len] = 0;
  983. -    if (isdigit(*s))
  984. -        {
  985. -        int num;
  986. -        Node node;
  987. -        
  988. -        num = atoi(s);
  989. -        for (node = pparms->first; node && num; num--,node = node->next);
  990. -        if (node)
  991. -            {
  992. -            free(node->dat);
  993. -            node->dat = v;
  994. -            }
  995. -        else
  996. -            {
  997. -            while (num--)
  998. -                addnode(pparms,strdup(""));
  999. -            addnode(pparms,v);
  1000. -            }
  1001. -        }
  1002. -    else
  1003. -        setparm(strdup(s),v,0,0);
  1004. -    s[len] = c;
  1005. -}
  1006. -
  1007. -/* `...`, $(...) */
  1008. -
  1009. -void comminsall(table l,Node *nn,char **aptr,char **bptr)
  1010. -{
  1011. -char *str3 = *aptr,*str = *bptr,*str2;
  1012. -Node n = *nn,where = n->last;
  1013. -table pl;
  1014. -int s31 = (*str3 == Qtick || *str3 == Qstring);
  1015. -
  1016. -    if (magic) magic = 2;
  1017. -    if (*str3 == Tick || *str3 == Qtick)
  1018. -        {
  1019. -        *str3 = '\0';
  1020. -        for (str2 = ++str3; *str3 != Tick && *str3 != Qtick; str3++);
  1021. -        *str3++ = '\0';
  1022. -        }
  1023. -    else
  1024. -        {
  1025. -        *str3++ = '\0';
  1026. -        for (str2 = ++str3; *str3 != Outpar; str3++);
  1027. -        *str3++ = '\0';
  1028. -        }
  1029. -    remnode(l,n);
  1030. -    if (!(pl = getoutput(str2,s31)))
  1031. -        {
  1032. -        magicerr();
  1033. -        zerr("parse error in command substitution");
  1034. -        errflag = 1;
  1035. -        return;
  1036. -        }
  1037. -    if (pl->first)
  1038. -        {
  1039. -        char *ptr;
  1040. -        Node tmp;
  1041. -
  1042. -        ptr = pl->first->dat;
  1043. -        pl->first->dat = dyncat(str,ptr);
  1044. -        free(ptr);
  1045. -        ptr = pl->last->dat;
  1046. -        *bptr = pl->last->dat = dyncat(ptr,str3);
  1047. -        *aptr = *bptr+strlen(str)+strlen(ptr)-1;
  1048. -        free(ptr);
  1049. -        tmp = where->next;
  1050. -        where->next = pl->first;
  1051. -        pl->last->next = tmp;
  1052. -        pl->first->last = where;
  1053. -        if (tmp)
  1054. -            tmp->last = pl->last;
  1055. -        else
  1056. -            l->last = pl->last;
  1057. -        /* free(tmp); */
  1058. -        *nn = pl->last;
  1059. -        free(pl);
  1060. -        }
  1061. -    else
  1062. -        {
  1063. -        insnode(l,where,*bptr = dyncat(str,str3));
  1064. -        *nn = where->next;
  1065. -        *aptr = *bptr+strlen(str)-1;
  1066. -        }
  1067. -}
  1068. -
  1069. -/* do simple parameter substitution */
  1070. -
  1071. -/*
  1072. -    consider an argument like this:
  1073. -
  1074. -    abcde${fgh:-ijk}lmnop
  1075. -
  1076. -    aptr will point to the $.
  1077. -    *bptr,ostr will point to the a.
  1078. -    t will point to the f.
  1079. -    u will point to the i.
  1080. -    s will point to the l (eventually).
  1081. -*/
  1082. -
  1083. -void parmsuber(char *aptr,char **bptr)
  1084. -{
  1085. -char *s = aptr,*t,*u,*val,*ostr = *bptr;
  1086. -int brs;            /* != 0 means ${...}, otherwise $... */
  1087. -int vlen;        /* the length of the name of the parameter */
  1088. -int colf;        /* != 0 means we found a colon after the name */
  1089. -int doub = 0;    /* != 0 means we have %%, not %, or ##, not # */
  1090. -
  1091. -    /* first, remove the $ so *bptr is pointing to a null-terminated
  1092. -        string containing the stuff before the $.  Then check for braces,
  1093. -        and get the parameter name and value, if any. */
  1094. -
  1095. -    *s++ = '\0';
  1096. -    if (brs = (*s == '{' || *s == Inbrace))
  1097. -        s++;
  1098. -    t = s;
  1099. -    if (istok(*s) || !isalnum(*s))
  1100. -        {
  1101. -        val = getsparmval(t,vlen = 1);
  1102. -        if (!val)
  1103. -            {
  1104. -            *(char *) aptr = '$';
  1105. -            if (brs)
  1106. -                s[-1] = '{';
  1107. -            return;
  1108. -            }
  1109. -        s++;
  1110. -        }
  1111. -    else
  1112. -        {
  1113. -        while (!istok(*s) && (isalnum(*s) || *s == '_'))
  1114. -            s++;
  1115. -        val = getsparmval(t,vlen = s-t);
  1116. -        }
  1117. -
  1118. -    /* val can still be NULL at this point. */
  1119. -
  1120. -    if (colf = *s == ':')
  1121. -        s++;
  1122. -    
  1123. -    /* check for ${..?...} or ${..=..} or one of those.  Only works
  1124. -        if the name is in braces. */
  1125. -
  1126. -    if (brs && (*s == '-' || *s == '=' || *s == '?' || *s == '+' || *s == '#' ||
  1127. -            *s == '%' || *s == Quest || *s == Pound))
  1128. -        {
  1129. -        if (*s == s[1])
  1130. -            {
  1131. -            s++;
  1132. -            doub = 1;
  1133. -            }
  1134. -        u = ++s;
  1135. -        if (brs)
  1136. -            while (*s != '}' && *s != Outbrace)
  1137. -                s++;
  1138. -        else
  1139. -            {
  1140. -            while (*s++);
  1141. -            s--;
  1142. -            }
  1143. -        *s = '\0';
  1144. -        switch (u[-1])
  1145. -            {
  1146. -            case '-':
  1147. -                if (!val || (colf && !*val))
  1148. -                    val = strdup(u);
  1149. -                break;
  1150. -            case '=':
  1151. -                if (!val || (colf && !*val))
  1152. -                    setparml(t,vlen,val = strdup(u));
  1153. -                break;
  1154. -            case '?':
  1155. -            case Quest:
  1156. -                if (!val || (colf && !*val))
  1157. -                    {
  1158. -                    magicerr();
  1159. -                    zerr("%s",(*u) ? u : "parameter not set");
  1160. -                    if (!interact)
  1161. -                        exit(1);
  1162. -                    else
  1163. -                        errflag = 1;
  1164. -                    return;
  1165. -                    }
  1166. -                break;
  1167. -            case '+':
  1168. -                if (!val || (colf && !*val))
  1169. -                    val = strdup("");
  1170. -                else
  1171. -                    val = strdup(u);
  1172. -                break;
  1173. -            case '#':
  1174. -            case Pound:
  1175. -                if (!val)
  1176. -                    val = strdup("");
  1177. -                getmatch(&val,u,doub);
  1178. -                break;
  1179. -            case '%':
  1180. -                if (!val)
  1181. -                    val = strdup("");
  1182. -                getmatch(&val,u,doub+2);
  1183. -                break;
  1184. -            }
  1185. -        }
  1186. -    else        /* no ${...=...} or anything, but possible modifiers. */
  1187. -        {
  1188. -        if (!val)
  1189. -            {
  1190. -            if (isset(NOUNSET))
  1191. -                {
  1192. -                zerr("parameter not set: %l",vlen,t);
  1193. -                errflag = 1;
  1194. -                return;
  1195. -                }
  1196. -            val = strdup("");
  1197. -            }
  1198. -        if (colf)
  1199. -            {
  1200. -            s--;
  1201. -            modify((void **) &val,&s);        /* do modifiers */
  1202. -            }
  1203. -        if (brs)
  1204. -            {
  1205. -            if (*s != '}' && *s != Outbrace)
  1206. -                {
  1207. -                zerr("closing brace expected");
  1208. -                errflag = 1;
  1209. -                return;
  1210. -                }
  1211. -            s++;
  1212. -            }
  1213. -        }
  1214. -    if (errflag)
  1215. -        {
  1216. -        free(ostr);
  1217. -        return;
  1218. -        }
  1219. -    *bptr = zalloc((char *) aptr-(*bptr)+strlen(val)+strlen(s)+1);
  1220. -    strcpy(*bptr,ostr);
  1221. -    strcat(*bptr,val);
  1222. -    strcat(*bptr,s);
  1223. -    free(ostr);
  1224. -    if (magic)
  1225. -        magic = 2;
  1226. -}
  1227. -
  1228. -/* arithmetic substitution */
  1229. -
  1230. -void arithsuber(void **aptr,char **bptr)
  1231. -{
  1232. -char *s = *aptr,*t,buf[16];
  1233. -long v;
  1234. -
  1235. -    *s = '\0';
  1236. -    for (; *s != Outbrack; s++);
  1237. -    *s++ = '\0';
  1238. -    v = matheval(*aptr+2);
  1239. -    sprintf(buf,"%ld",v);
  1240. -    t = zalloc(strlen(*bptr)+strlen(buf)+strlen(s)+1);
  1241. -    strcpy(t,*bptr);
  1242. -    strcat(t,buf);
  1243. -    strcat(t,s);
  1244. -    free(*bptr);
  1245. -    *bptr = t;
  1246. -}
  1247. -
  1248. -void modify(void **str,char **ptr)
  1249. -{
  1250. -char *ptr1,*ptr2,*ptr3,del,*lptr;
  1251. -int gbal;
  1252. -    while (**ptr == ':')
  1253. -        {
  1254. -        lptr = *ptr;
  1255. -        (*ptr)++;
  1256. -        gbal = 0;
  1257. -here:
  1258. -        switch(*(*ptr)++)
  1259. -            {
  1260. -            case 'h':
  1261. -                while (remtpath(str) && gbal);
  1262. -                break;
  1263. -            case 'r':
  1264. -                while (remtext(str) && gbal);
  1265. -                break;
  1266. -            case 'e':
  1267. -                while (rembutext(str) && gbal);
  1268. -                break;
  1269. -            case 't':
  1270. -                while (remlpaths(str) && gbal);
  1271. -                break;
  1272. -            case 's':
  1273. -                if (last)
  1274. -                    free(last);
  1275. -                if (rast)
  1276. -                    free(rast);
  1277. -                ptr1 = *ptr;
  1278. -                del = *ptr1++;
  1279. -                for (ptr2 = ptr1; *ptr2 != del && *ptr2; ptr2++);
  1280. -                if (!*ptr2)
  1281. -                    {
  1282. -                    magicerr();
  1283. -                    zerr("bad subtitution");
  1284. -                    errflag = 1;
  1285. -                    return;
  1286. -                    }
  1287. -                *ptr2++ = '\0';
  1288. -                for (ptr3 = ptr2; *ptr3 != del && *ptr3; ptr3++);
  1289. -                if (*ptr3)
  1290. -                    *ptr3++ = '\0';
  1291. -                last = strdup(ptr1);
  1292. -                rast = strdup(ptr2);
  1293. -                *ptr = ptr3;
  1294. -            case '&':
  1295. -                if (last && rast)
  1296. -                    subststr(str,last,rast,gbal);
  1297. -                break;
  1298. -            case 'g':
  1299. -                gbal = 1;
  1300. -                goto here;
  1301. -            default:
  1302. -                *ptr = lptr;
  1303. -                return;
  1304. -            }
  1305. -        }
  1306. -}
  1307. -
  1308. -/* get a directory stack entry */
  1309. -
  1310. -char *dstackent(int val)
  1311. -{
  1312. -Node node;
  1313. -    if ((val < 0 && !dirstack->first) || !val--)
  1314. -        return cwd;
  1315. -    if (val < 0)
  1316. -        node = dirstack->last;
  1317. -    else
  1318. -        for (node = dirstack->first; node && val; val--,node = node->next);
  1319. -    if (!node)
  1320. -        {
  1321. -        magicerr();
  1322. -        zerr("not enough dir stack entries.");
  1323. -        errflag = 1;
  1324. -        return NULL;
  1325. -        }
  1326. -    return node->dat;
  1327. -}
  1328. -void execshfunc(comm comm)
  1329. -{
  1330. -table tab,oldlocals;
  1331. -Node n;
  1332. -char *s;
  1333. -
  1334. -    tab = pparms;
  1335. -    oldlocals = locallist;
  1336. -    locallist = newtable();
  1337. -    for (n = tab->first; n; n = n->next);
  1338. -    pparms = comm->args;
  1339. -    runlist(comm->left);
  1340. -    retflag = 0;
  1341. -    comm->left = NULL;
  1342. -    pparms = tab;
  1343. -    while (s = getnode(locallist))
  1344. -        {
  1345. -        void *z = remhnode(s,parmhtab);
  1346. -        if (z)
  1347. -            freepm(z);
  1348. -        }
  1349. -    free(locallist);
  1350. -    locallist = oldlocals;
  1351. -}
  1352. -
  1353. -/* make an alias hash table node */
  1354. -
  1355. -struct anode *mkanode(char *txt,int cmflag)
  1356. -{
  1357. -struct anode *ptr = (void *) alloc(sizeof(struct anode));
  1358. -
  1359. -    ptr->text  = txt;
  1360. -    ptr->cmd = cmflag;
  1361. -    ptr->inuse = 0;
  1362. -    return ptr;
  1363. -}
  1364. -
  1365. -/* perform TAB substitution */
  1366. -
  1367. -char *docompsubs(char *str,int *i)
  1368. -{
  1369. -table fake,curt = curtab;
  1370. -char *s,*t;
  1371. -int ct = 0;
  1372. -
  1373. -    for (s = str; *s; s++)
  1374. -        for (t = tokens; *t; t++)
  1375. -            if (*s == *t)
  1376. -                {
  1377. -                *s = (t-tokens)+Pound;
  1378. -                break;
  1379. -                }
  1380. -    curtab = NULL;
  1381. -    magic = 1;
  1382. -    fake = newtable();
  1383. -    addnode(fake,str);
  1384. -    prefork(fake);
  1385. -    if (!errflag)
  1386. -        postfork(fake,GLOB);
  1387. -    if (fake->first && fake->first->next)
  1388. -        ct = 1;
  1389. -    t = s = buildline(fake);
  1390. -    free(fake);
  1391. -    rl_prep_terminal();
  1392. -    if (errflag)
  1393. -        {
  1394. -        rl_on_new_line();
  1395. -        rl_redisplay();
  1396. -        errflag = 0;
  1397. -        magic = 0;
  1398. -        curtab = curt;
  1399. -        *i = 0;
  1400. -        return NULL;
  1401. -        }
  1402. -    *i = (magic == 2) + ct;
  1403. -    magic = 0;
  1404. -    curtab = curt;
  1405. -    untokenize(s);
  1406. -    return s;
  1407. -}
  1408. -
  1409. -/* perform substitution on the command name */
  1410. -
  1411. -void docmdsubs(char **str)
  1412. -{
  1413. -table fake;
  1414. -char *s = strdup(*str);
  1415. -
  1416. -    fake = newtable();
  1417. -    addnode(fake,*str);
  1418. -    prefork(fake);
  1419. -    if (!errflag) postfork(fake,GLOB);
  1420. -    if (errflag)
  1421. -        {
  1422. -        free(fake);
  1423. -        free(s);
  1424. -        return;
  1425. -        }
  1426. -    if (fake->first && fake->first->next)
  1427. -        {
  1428. -        zerr("%s: ambiguous",s);
  1429. -        errflag = 1;
  1430. -        free(fake);
  1431. -        free(s);
  1432. -        return;
  1433. -        }
  1434. -    *str = getnode(fake);
  1435. -    free(s);
  1436. -    free(fake);
  1437. -}
  1438. -
  1439. -/* perform substitution on the variables */
  1440. -
  1441. -void dovarsubs(char **str)
  1442. -{
  1443. -table fake;
  1444. -char *s;
  1445. -
  1446. -    fake = newtable();
  1447. -    addnode(fake,*str);
  1448. -    prefork(fake);
  1449. -    if (!errflag) postfork(fake,GLOB);
  1450. -    if (errflag)
  1451. -        return;
  1452. -    s = buildline(fake);
  1453. -    untokenize(s);
  1454. -    *str = s;
  1455. -    free(fake);
  1456. -}
  1457. -
  1458. End of subst.c
  1459. echo subst.pro 1>&2
  1460. sed 's/^-//' >subst.pro <<'End of subst.pro'
  1461. -void prefork(table list);
  1462. -void postfork(table list,int globstat);
  1463. -void *nstrdup(void *s);
  1464. -void parminsall(table l,Node *nn,char **aptr,char **bptr);
  1465. -char *dynread(char stop);
  1466. -int filesub(void **namptr);
  1467. -char *gethome(char *user,int len);
  1468. -char *completehome(char *user,int len);
  1469. -char *getsparmval(char *s,int len);
  1470. -void setparml(char *s,int len,char *v);
  1471. -void comminsall(table l,Node *nn,char **aptr,char **bptr);
  1472. -void parmsuber(char *aptr,char **bptr);
  1473. -void arithsuber(void **aptr,char **bptr);
  1474. -void modify(void **str,char **ptr);
  1475. -char *dstackent(int val);
  1476. -void execshfunc(comm comm);
  1477. -struct anode *mkanode(char *txt,int cmflag);
  1478. -char *docompsubs(char *str,int *i);
  1479. -void docmdsubs(char **str);
  1480. -void dovarsubs(char **str);
  1481. End of subst.pro
  1482. echo table.c 1>&2
  1483. sed 's/^-//' >table.c <<'End of table.c'
  1484. -/*
  1485. -
  1486. -    table.c - linked list and hash table management
  1487. -
  1488. -    This file is part of zsh, the Z shell.
  1489. -
  1490. -   zsh is free software; no one can prevent you from reading the source
  1491. -   code, or giving it to someone else.
  1492. -   This file is copyrighted under the GNU General Public License, which
  1493. -   can be found in the file called COPYING.
  1494. -
  1495. -   Copyright (C) 1990 Paul Falstad
  1496. -
  1497. -   zsh is distributed in the hope that it will be useful, but
  1498. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  1499. -   responsibility to anyone for the consequences of using it or for
  1500. -   whether it serves any particular purpose or works at all, unless he
  1501. -   says so in writing.  Refer to the GNU General Public License
  1502. -   for full details.
  1503. -
  1504. -   Everyone is granted permission to copy, modify and redistribute
  1505. -   zsh, but only under the conditions described in the GNU General Public
  1506. -   License.   A copy of this license is supposed to have been given to you
  1507. -   along with zsh so you can know your rights and responsibilities.
  1508. -   It should be in a file named COPYING.
  1509. -
  1510. -   Among other things, the copyright notice and this notice must be
  1511. -   preserved on all copies.
  1512. -
  1513. -*/
  1514. -
  1515. -#include "zsh.h"
  1516. -#include "funcs.h"
  1517. -
  1518. -/* get an empty linked list header */
  1519. -
  1520. -table newtable()
  1521. -{
  1522. -table list;
  1523. -    list = alloc(sizeof(*list));
  1524. -    list->first = 0;
  1525. -    list->last = (Node) list;
  1526. -    return list;
  1527. -}
  1528. -
  1529. -/* get an empty hash table */
  1530. -
  1531. -htable newhtable(int size)
  1532. -{
  1533. -htable ret;
  1534. -    ret = alloc(sizeof(struct xhtab));
  1535. -    ret->hsize = size;
  1536. -    ret->nodes = alloc(size*sizeof(struct hnode *));
  1537. -    return ret;
  1538. -}
  1539. -/* Peter Weinberger's hash function */
  1540. -
  1541. -int hasher(char *s)
  1542. -{
  1543. -unsigned hash = 0,g;
  1544. -    for (; *s; s++)
  1545. -        {
  1546. -        hash = (hash << 4) + *s;
  1547. -        if (g = hash & 0xf0000000)
  1548. -            {
  1549. -            hash ^= g;
  1550. -            hash ^= g >> 24;
  1551. -            }
  1552. -        }
  1553. -    return hash;
  1554. -}
  1555. -
  1556. -/* add a node to a hash table */
  1557. -
  1558. -void addhnode(char *nam,void *dat,htable ht,void (*freefunc)(void *))
  1559. -{
  1560. -int hval = hasher(nam) % ht->hsize;
  1561. -struct hnode *hp = ht->nodes[hval],*hn;
  1562. -    for (; hp; hp = hp->hchain)
  1563. -        if (!strcmp(hp->nam,nam))
  1564. -            {
  1565. -            freefunc(hp->dat);
  1566. -            hp->dat = dat;
  1567. -            free(nam);
  1568. -            return;
  1569. -            }
  1570. -    hn = (void *) alloc(sizeof(struct hnode));
  1571. -    hn->nam = nam;
  1572. -    hn->dat = dat;
  1573. -    hn->hchain = ht->nodes[hval];
  1574. -    ht->nodes[hval] = hn;
  1575. -    if (++ht->ct == ht->hsize*4)
  1576. -        expandhtab(ht);
  1577. -}
  1578. -
  1579. -/* expand hash tables when they get too many entries */
  1580. -
  1581. -void expandhtab(htable ht)
  1582. -{
  1583. -struct hnode *hp,**arr,**ha,*hn;
  1584. -int osize = ht->hsize,nsize = osize*8;
  1585. -
  1586. -    ht->hsize = nsize;
  1587. -    arr = ht->nodes;
  1588. -    ht->nodes = alloc(nsize*sizeof(struct hnode *));
  1589. -    for (ha = arr; osize; osize--,ha++)
  1590. -        for (hn = *ha; hn; )
  1591. -            {
  1592. -            addhnode(hn->nam,hn->dat,ht,NULL);
  1593. -            hp = hn->hchain;
  1594. -            free(hn);
  1595. -            hn = hp;
  1596. -            }
  1597. -    free(arr);
  1598. -}
  1599. -
  1600. -/* get an entry in a hash table */
  1601. -
  1602. -void *gethnode(char *nam,htable ht)
  1603. -{
  1604. -int hval = hasher(nam) % ht->hsize;
  1605. -struct hnode *hn = ht->nodes[hval];
  1606. -    for (; hn; hn = hn->hchain)
  1607. -        if (!strcmp(hn->nam,nam))
  1608. -            return hn->dat;
  1609. -    return NULL;
  1610. -}
  1611. -void freehtab(htable ht,void (*freefunc)(void *))
  1612. -{
  1613. -int val;
  1614. -struct hnode *hn,**hptr = &ht->nodes[0],*next;
  1615. -    for (val = ht->hsize; val; val--,hptr++)
  1616. -        for (hn = *hptr; hn; )
  1617. -            {
  1618. -            next = hn->hchain;
  1619. -            freefunc(hn);
  1620. -            hn = next;
  1621. -            }
  1622. -}
  1623. -
  1624. -/* remove a hash table entry and return a pointer to it */
  1625. -
  1626. -void *remhnode(char *nam,htable ht)
  1627. -{
  1628. -int hval = hasher(nam) % ht->hsize;
  1629. -struct hnode *hn = ht->nodes[hval],*hp;
  1630. -void *dat;
  1631. -
  1632. -    if (!hn)
  1633. -        return NULL;
  1634. -    if (!strcmp(hn->nam,nam))
  1635. -        {
  1636. -        ht->nodes[hval] = hn->hchain;
  1637. -        dat = hn->dat;
  1638. -        free(hn->nam);
  1639. -        free(hn);
  1640. -        ht->ct--;
  1641. -        return dat;
  1642. -        }
  1643. -    for (hp = hn, hn = hn->hchain; hn; hn = (hp = hn)->hchain)
  1644. -        if (!strcmp(hn->nam,nam))
  1645. -            {
  1646. -            hp->hchain = hn->hchain;
  1647. -            dat = hn->dat;
  1648. -            free(hn->nam);
  1649. -            free(hn);
  1650. -            ht->ct--;
  1651. -            return dat;
  1652. -            }
  1653. -    return NULL;
  1654. -}
  1655. -void *zalloc(int l)
  1656. -{
  1657. -void *z;
  1658. -    if (!(z = malloc(l)))
  1659. -        {
  1660. -        zerr("fatal error: out of memory: restarting");
  1661. -        execl(MYSELF,"zsh","-f",(void *) 0);
  1662. -        exit(1);
  1663. -        }
  1664. -    return z;
  1665. -}
  1666. -
  1667. -void *alloc(int l)
  1668. -{
  1669. -void *z;
  1670. -    if (!(z = calloc(l,1)))
  1671. -        {
  1672. -        zerr("fatal error: out of memory: restarting");
  1673. -        execl(MYSELF,"zsh","-f",(void *) 0);
  1674. -        exit(1);
  1675. -        }
  1676. -    return z;
  1677. -}
  1678. -
  1679. -/* add a node to the end of a linked list */
  1680. -
  1681. -void addnode(table list,void *str)
  1682. -{
  1683. -    insnode(list,list->last,str);
  1684. -}
  1685. -
  1686. -/* insert a node in a linked list after 'last' */
  1687. -
  1688. -void insnode(table list,Node last,void *dat)
  1689. -{
  1690. -Node tmp;
  1691. -    tmp = last->next;
  1692. -    last->next = alloc(sizeof(*tmp));
  1693. -    last->next->last = last;
  1694. -    last->next->dat = dat;
  1695. -    last->next->next = tmp;
  1696. -    if (tmp)
  1697. -        tmp->last = last->next;
  1698. -    else
  1699. -        list->last = last->next;
  1700. -}
  1701. -
  1702. -/* remove a node from a linked list */
  1703. -
  1704. -void *remnode(table list,Node nd)
  1705. -{
  1706. -void *dat;
  1707. -
  1708. -    nd->last->next = nd->next;
  1709. -    if (nd->next)
  1710. -        nd->next->last = nd->last;
  1711. -    else
  1712. -        list->last = nd->last;
  1713. -    free(nd);
  1714. -    dat = nd->dat;
  1715. -    return dat;
  1716. -}
  1717. -
  1718. -/* delete a character in a string */
  1719. -
  1720. -void chuck(char *str)
  1721. -{
  1722. -    while (str[0] = str[1])
  1723. -        str++;
  1724. -}
  1725. -
  1726. -/* get a node in a linked list */
  1727. -
  1728. -void *getnode(table list)
  1729. -{
  1730. -void *dat;
  1731. -Node node = list->first;
  1732. -    if (!node)
  1733. -        return NULL;
  1734. -    dat = node->dat;
  1735. -    list->first = node->next;
  1736. -    if (node->next)
  1737. -        node->next->last = (Node) list;
  1738. -    else
  1739. -        list->last = (Node) list;
  1740. -    free(node);
  1741. -    return dat;
  1742. -}
  1743. -
  1744. -/* != 0 if the linked list has at least one entry */
  1745. -
  1746. -int full(table list)
  1747. -{
  1748. -    return list->first != NULL;
  1749. -}
  1750. -void freetable(table tab,void (*freefunc)(void *))
  1751. -{
  1752. -Node node = tab->first,next;
  1753. -    while (node)
  1754. -        {
  1755. -        next = node->next;
  1756. -        freefunc(node);
  1757. -        node = next;
  1758. -        }
  1759. -    free(tab);
  1760. -}
  1761. -char *strdup(char *str)
  1762. -{
  1763. -char *ret = zalloc(strlen(str)+1);
  1764. -    strcpy(ret,str);
  1765. -    return ret;
  1766. -}
  1767. -
  1768. -#ifndef STRSTR
  1769. -const char *strstr(const char *s,const char *t)
  1770. -{
  1771. -const char *p1,*p2;
  1772. -    for (; *s; s++)
  1773. -        {
  1774. -        for (p1 = s, p2 = t; *p2; p1++,p2++)
  1775. -            if (*p1 != *p2)
  1776. -                break;
  1777. -        if (!*p2)
  1778. -             return (char *) s;
  1779. -        }
  1780. -    return NULL;
  1781. -}
  1782. -#endif
  1783. -
  1784. End of table.c
  1785. echo table.pro 1>&2
  1786. sed 's/^-//' >table.pro <<'End of table.pro'
  1787. -table newtable();
  1788. -htable newhtable(int size);
  1789. -int hasher(char *s) /* copied from Programming in C++, p14 */;
  1790. -void addhnode(char *nam,void *dat,htable ht,void (*freefunc)(void *));
  1791. -void expandhtab(htable ht);
  1792. -void *gethnode(char *nam,htable ht);
  1793. -void freehtab(htable ht,void (*freefunc)(void *));
  1794. -void *remhnode(char *nam,htable ht);
  1795. -void *zalloc(int l);
  1796. -void *alloc(int l);
  1797. -void addnode(table list,void *str);
  1798. -void insnode(table list,Node last,void *dat);
  1799. -void *remnode(table list,Node nd);
  1800. -void chuck(char *str);
  1801. -void *getnode(table list);
  1802. -int full(table list);
  1803. -void freetable(table tab,void (*freefunc)(void *));
  1804. -char *strdup(char *str);
  1805. -/*const char *strstr(const char *s,const char *t); */
  1806. End of table.pro
  1807. echo test.c 1>&2
  1808. sed 's/^-//' >test.c <<'End of test.c'
  1809. -/*
  1810. -
  1811. -    test.c - the test builtin
  1812. -
  1813. -    This file is part of zsh, the Z shell.
  1814. -
  1815. -   zsh is free software; no one can prevent you from reading the source
  1816. -   code, or giving it to someone else.
  1817. -   This file is copyrighted under the GNU General Public License, which
  1818. -   can be found in the file called COPYING.
  1819. -
  1820. -   Copyright (C) 1990 Paul Falstad
  1821. -
  1822. -   zsh is distributed in the hope that it will be useful, but
  1823. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  1824. -   responsibility to anyone for the consequences of using it or for
  1825. -   whether it serves any particular purpose or works at all, unless he
  1826. -   says so in writing.  Refer to the GNU General Public License
  1827. -   for full details.
  1828. -
  1829. -   Everyone is granted permission to copy, modify and redistribute
  1830. -   zsh, but only under the conditions described in the GNU General Public
  1831. -   License.   A copy of this license is supposed to have been given to you
  1832. -   along with zsh so you can know your rights and responsibilities.
  1833. -   It should be in a file named COPYING.
  1834. -
  1835. -   Among other things, the copyright notice and this notice must be
  1836. -   preserved on all copies.
  1837. -
  1838. -*/
  1839. -
  1840. -#include "zsh.h"
  1841. -
  1842. -#ifndef F_OK
  1843. -#define F_OK 00
  1844. -#define R_OK 04
  1845. -#define W_OK 02
  1846. -#define X_OK 01
  1847. -#endif
  1848. -
  1849. -#include "test.pro"
  1850. -#include "table.pro"
  1851. -
  1852. -static char **arg;
  1853. -static int efg;
  1854. -
  1855. -void die(char *str)
  1856. -{
  1857. -    if (!efg)
  1858. -        zerrnam("test",str);
  1859. -    efg = 1;
  1860. -}
  1861. -
  1862. -int test(comm comm)
  1863. -{
  1864. -Node n;
  1865. -int t0;
  1866. -char **av,**ap;
  1867. -
  1868. -    for (n = comm->args->first, t0 = 0; n; n = n->next,t0++);
  1869. -    ap = av = (char **) zalloc((sizeof(char *))*(t0+1));
  1870. -    for (n = comm->args->first; n; n = n->next)
  1871. -        *ap++ = n->dat;
  1872. -    *ap = NULL;
  1873. -    t0 = testmain(av);
  1874. -    free(av);
  1875. -    return t0;
  1876. -}
  1877. -
  1878. -int testmain(char **argv)
  1879. -{
  1880. -int ret,isbrack;
  1881. -    
  1882. -    efg = 0;
  1883. -    arg = argv+1;
  1884. -    ret = testexpr();
  1885. -    if (efg)
  1886. -        return 1;
  1887. -    isbrack = !strcmp(*argv,"[");
  1888. -    if (isbrack)
  1889. -        {
  1890. -        if (*arg && !strcmp(*arg,"]") && !arg[1])
  1891. -            return !ret;
  1892. -        }
  1893. -    else
  1894. -        if (!*arg)
  1895. -            return !ret;
  1896. -    die("bad test format");
  1897. -    return 1;
  1898. -}
  1899. -
  1900. -int testexpr(void)
  1901. -{
  1902. -int ret = testexpr2(),ret2;
  1903. -
  1904. -    if (*arg && !strcmp(*arg,"-o"))
  1905. -        {
  1906. -        arg++;
  1907. -        ret2 = testexpr2();
  1908. -        if (efg)
  1909. -            return 0;
  1910. -        ret = ret || ret2;
  1911. -        }
  1912. -    return ret;
  1913. -}
  1914. -
  1915. -int testexpr2(void)
  1916. -{
  1917. -int ret = testexpr3(),ret2;
  1918. -
  1919. -    if (*arg && !strcmp(*arg,"-a"))
  1920. -        {
  1921. -        arg++;
  1922. -        ret2 = testexpr2();
  1923. -        if (efg)
  1924. -            return 0;
  1925. -        ret = ret && ret2;
  1926. -        }
  1927. -    return ret;
  1928. -}
  1929. -
  1930. -int testexpr3(void)
  1931. -{
  1932. -    if (*arg && !strcmp(*arg,"!"))
  1933. -        {
  1934. -        arg++;
  1935. -        return !testexpr3();
  1936. -        }
  1937. -    return testexpr4();
  1938. -}
  1939. -
  1940. -int testexpr4(void)
  1941. -{
  1942. -int ret,t0,t1;
  1943. -struct stat *st;
  1944. -char buf[16],*op;
  1945. -
  1946. -    if (!*arg)
  1947. -        {
  1948. -        die("expression expected");
  1949. -        return 0;
  1950. -        }
  1951. -    if (!strcmp(*arg,"("))
  1952. -        {
  1953. -        arg++;
  1954. -        ret = testexpr();
  1955. -        if (!*arg || strcmp(*arg,")"))
  1956. -            {
  1957. -            die("')' expected");
  1958. -            return 0;
  1959. -            }
  1960. -        arg++;
  1961. -        return ret;
  1962. -        }
  1963. -    if (**arg == '-' && !(*arg)[2])
  1964. -        {
  1965. -        switch((*arg++)[1])
  1966. -            {
  1967. -            case 'a': return(doaccess(F_OK));
  1968. -            case 'b': return(S_ISBLK(dostat()));
  1969. -            case 'c': return(S_ISCHR(dostat()));
  1970. -            case 'd': return(S_ISDIR(dostat()));
  1971. -            case 'f': return(S_ISREG(dostat()));
  1972. -            case 'g': return(!!(dostat() & S_ISGID));
  1973. -            case 'k': return(!!(dostat() & S_ISVTX));
  1974. -            case 'L': return(S_ISLNK(dostat()));
  1975. -            case 'p': return(S_ISFIFO(dostat()));
  1976. -            case 'r': return(doaccess(R_OK));
  1977. -            case 's': return((st = getstat()) && !!(st->st_size));
  1978. -            case 'S': return(S_ISSOCK(dostat()));
  1979. -            case 'u': return(!!(dostat() & S_ISUID));
  1980. -            case 'w': return(doaccess(W_OK));
  1981. -            case 'x': return(doaccess(X_OK));
  1982. -            case 'O': return((st = getstat()) && st->st_uid == geteuid());
  1983. -            case 'G': return((st = getstat()) && st->st_gid == getegid());
  1984. -            case 't': {
  1985. -                int t0 = 1;
  1986. -
  1987. -                if (*arg && isdigit(**arg))
  1988. -                    t0 = atoi(*arg++);
  1989. -                return isatty(t0);
  1990. -                }
  1991. -            case 'z':
  1992. -                if (!*arg)
  1993. -                    {
  1994. -                    die("string expected");
  1995. -                    return 0;
  1996. -                    }
  1997. -                return !strlen(*arg++);
  1998. -            case 'n':
  1999. -                if (!*arg)
  2000. -                    {
  2001. -                    die("string expected");
  2002. -                    return 0;
  2003. -                    }
  2004. -                return !!strlen(*arg++);
  2005. -            case 'l':
  2006. -                sprintf(buf,"%d",strlen(*arg));
  2007. -                *arg = buf;
  2008. -                break;
  2009. -            }
  2010. -        }
  2011. -    if (!arg[1] || !strcmp(arg[1],"-o") || !strcmp(arg[1],"-a") ||
  2012. -            !strcmp(arg[1],"]") || !strcmp(arg[1],")"))
  2013. -        return(!!strlen(*arg++));
  2014. -    if (!arg[2])
  2015. -        {
  2016. -        die("bad expression");
  2017. -        return 0;
  2018. -        }
  2019. -    if (!strcmp(arg[1],"-nt"))
  2020. -        {
  2021. -        time_t a;
  2022. -
  2023. -        if (!(st = getstat()))
  2024. -            {
  2025. -            arg += 2;
  2026. -            return 0;
  2027. -            }
  2028. -        a = st->st_mtime;
  2029. -        arg++;
  2030. -        if (!(st = getstat()))
  2031. -            {
  2032. -            arg += 2;
  2033. -            return 0;
  2034. -            }
  2035. -        return a > st->st_mtime;
  2036. -        }
  2037. -    if (!strcmp(arg[1],"-ot"))
  2038. -        {
  2039. -        time_t a;
  2040. -
  2041. -        if (!(st = getstat()))
  2042. -            {
  2043. -            arg += 2;
  2044. -            return 0;
  2045. -            }
  2046. -        a = st->st_mtime;
  2047. -        arg++;
  2048. -        if (!(st = getstat()))
  2049. -            {
  2050. -            arg += 2;
  2051. -            return 0;
  2052. -            }
  2053. -        return a < st->st_mtime;
  2054. -        }
  2055. -    if (!strcmp(arg[1],"-ef"))
  2056. -        {
  2057. -        dev_t d;
  2058. -        ino_t i;
  2059. -
  2060. -        if (!(st = getstat()))
  2061. -            {
  2062. -            arg += 2;
  2063. -            return 0;
  2064. -            }
  2065. -        d = st->st_dev;
  2066. -        i = st->st_ino;
  2067. -        arg++;
  2068. -        if (!(st = getstat()))
  2069. -            {
  2070. -            arg += 2;
  2071. -            return 0;
  2072. -            }
  2073. -        return d == st->st_dev && i == st->st_ino;
  2074. -        }
  2075. -    if (!strcmp(arg[1],"~="))
  2076. -        {
  2077. -        arg += 3;
  2078. -        return patmatch(arg[-3],arg[-1]);
  2079. -        }
  2080. -    if (!strcmp(arg[1],"="))
  2081. -        {
  2082. -        arg += 3;
  2083. -        return !strcmp(arg[-3],arg[-1]);
  2084. -        }
  2085. -    if (!strcmp(arg[1],"!="))
  2086. -        {
  2087. -        arg += 3;
  2088. -        return !!strcmp(arg[-3],arg[-1]);
  2089. -        }
  2090. -    t0 = atoi(arg[0]);
  2091. -    op = arg[1];
  2092. -    arg += 2;
  2093. -    if (!strcmp(*arg,"-l"))
  2094. -        {
  2095. -        if (!arg[1])
  2096. -            {
  2097. -            die("string expected");
  2098. -            return 0;
  2099. -            }
  2100. -        t1 = strlen(arg[1]);
  2101. -        arg += 2;
  2102. -        }
  2103. -    else
  2104. -        t1 = atoi(*arg++);
  2105. -    if (!strcmp(op,"-eq"))
  2106. -        return t0 == t1;
  2107. -    if (!strcmp(op,"-ne"))
  2108. -        return t0 != t1;
  2109. -    if (!strcmp(op,"-lt"))
  2110. -        return t0 < t1;
  2111. -    if (!strcmp(op,"-le"))
  2112. -        return t0 <= t1;
  2113. -    if (!strcmp(op,"-gt"))
  2114. -        return t0 > t1;
  2115. -    if (!strcmp(op,"-ge"))
  2116. -        return t0 >= t1;
  2117. -    if (!efg)
  2118. -        zerrnam("test","unrecognized operator: %s",op);
  2119. -    efg = 1;
  2120. -    return 0;
  2121. -}
  2122. -
  2123. -int doaccess(int c)
  2124. -{
  2125. -    if (!*arg)
  2126. -        {
  2127. -        die("filename expected");
  2128. -        return 0;
  2129. -        }
  2130. -    return !access(*arg++,c);
  2131. -}
  2132. -
  2133. -struct stat *getstat(void)
  2134. -{
  2135. -static struct stat st;
  2136. -
  2137. -    if (!*arg)
  2138. -        {
  2139. -        die("filename expected");
  2140. -        return NULL;
  2141. -        }
  2142. -    if (!strncmp(*arg,"/dev/fd/",8))
  2143. -        {
  2144. -        if (fstat(atoi((*arg++)+8),&st))
  2145. -            return NULL;
  2146. -        }
  2147. -    else if (lstat(*arg++,&st))
  2148. -        return NULL;
  2149. -    return &st;
  2150. -}
  2151. -
  2152. -unsigned short dostat(void)
  2153. -{
  2154. -struct stat *st;
  2155. -
  2156. -    if (!(st = getstat()))
  2157. -        return 0;
  2158. -    return st->st_mode;
  2159. -}
  2160. -
  2161. End of test.c
  2162. echo test.pro 1>&2
  2163. sed 's/^-//' >test.pro <<'End of test.pro'
  2164. -void die(char *str);
  2165. -int test(comm comm);
  2166. -int testmain(char **argv);
  2167. -int testexpr(void);
  2168. -int testexpr2(void);
  2169. -int testexpr3(void);
  2170. -int testexpr4(void);
  2171. -int doaccess(int c);
  2172. -struct stat *getstat(void);
  2173. -unsigned short dostat(void);
  2174. End of test.pro
  2175. echo utils.c 1>&2
  2176. sed 's/^-//' >utils.c <<'End of utils.c'
  2177. -/*
  2178. -
  2179. -    utils.c - miscellaneous utilities
  2180. -
  2181. -    This file is part of zsh, the Z shell.
  2182. -
  2183. -   zsh is free software; no one can prevent you from reading the source
  2184. -   code, or giving it to someone else.
  2185. -   This file is copyrighted under the GNU General Public License, which
  2186. -   can be found in the file called COPYING.
  2187. -
  2188. -   Copyright (C) 1990 Paul Falstad
  2189. -
  2190. -   zsh is distributed in the hope that it will be useful, but
  2191. -   WITHOUT ANY WARRANTY.  No author or distributor accepts
  2192. -   responsibility to anyone for the consequences of using it or for
  2193. -   whether it serves any particular purpose or works at all, unless he
  2194. -   says so in writing.  Refer to the GNU General Public License
  2195. -   for full details.
  2196. -
  2197. -   Everyone is granted permission to copy, modify and redistribute
  2198. -   zsh, but only under the conditions described in the GNU General Public
  2199. -   License.   A copy of this license is supposed to have been given to you
  2200. -   along with zsh so you can know your rights and responsibilities.
  2201. -   It should be in a file named COPYING.
  2202. -
  2203. -   Among other things, the copyright notice and this notice must be
  2204. -   preserved on all copies.
  2205. -
  2206. -*/
  2207. -
  2208. -#include "zsh.h"
  2209. -#include "funcs.h"
  2210. -#include <pwd.h>
  2211. -#include <stdarg.h> /* had to change this to stdarg.h.old on one machine */
  2212. -#include <errno.h>
  2213. -#include <sys/dir.h>
  2214. -#include <fcntl.h>
  2215. -
  2216. -/* add vars to the parm hash table */
  2217. -
  2218. -void addvars(table vars)
  2219. -{
  2220. -char *s1,*s2;
  2221. -Node node;
  2222. -
  2223. -    for (node = vars->first; node; node = node->next)
  2224. -        {
  2225. -        s1 = node->dat;
  2226. -        untokenize(s1);
  2227. -        node = node->next;
  2228. -        s2 = node->dat;
  2229. -        dovarsubs(&s2);
  2230. -        if (errflag)
  2231. -            break;
  2232. -        untokenize(s2);
  2233. -        setparm(s1,s2,0,0);
  2234. -        }
  2235. -    free(vars);
  2236. -}
  2237. -
  2238. -/* set a parameter to an integer value */
  2239. -
  2240. -void setiparm(char *s,long v,int isint)
  2241. -{
  2242. -struct pmnode *pmn,*pmo;
  2243. -
  2244. -    if (!strcmp(s,"RANDOM"))
  2245. -        {
  2246. -        srand((unsigned long) v);
  2247. -        return;
  2248. -        }
  2249. -    if (!strcmp(s,"SECONDS"))
  2250. -        {
  2251. -        shtimer = v+time(NULL);
  2252. -        return;
  2253. -        }
  2254. -    if (pmo = gethnode(s,parmhtab))
  2255. -        {
  2256. -        char buf[12];
  2257. -
  2258. -        pmn = alloc(sizeof *pmn);
  2259. -        if (pmn->isint = pmo->isint | isint)
  2260. -            pmn->u.val = v;
  2261. -        else
  2262. -            {
  2263. -            sprintf(buf,"%ld",v);
  2264. -            pmn->u.str = strdup(buf);
  2265. -            }
  2266. -        addhnode(s,pmn,parmhtab,freepm);
  2267. -        }
  2268. -    else if (getenv(s) || (opts[ALLEXPORT] == OPT_SET))
  2269. -        {
  2270. -        char buf[12];
  2271. -
  2272. -        sprintf(buf,"%ld",v);
  2273. -        putenv(tricat(s,"=",buf));
  2274. -        }
  2275. -    else
  2276. -        {
  2277. -        char buf[12];
  2278. -
  2279. -        pmn = alloc(sizeof *pmn);
  2280. -        if (pmn->isint = isint)
  2281. -            pmn->u.val = v;
  2282. -        else
  2283. -            {
  2284. -            sprintf(buf,"%ld",v);
  2285. -            pmn->u.str = strdup(buf);
  2286. -            }
  2287. -        addhnode(s,pmn,parmhtab,freepm);
  2288. -        addlocal(s);
  2289. -        }
  2290. -    if (!strcmp(s,"PERIOD"))
  2291. -        {
  2292. -        period = v*60;
  2293. -        lastperiod = time(NULL)+period;
  2294. -        }
  2295. -    if (!strcmp(s,"HISTSIZE"))
  2296. -        {
  2297. -        tevs = v;
  2298. -        if (tevs <= 2)
  2299. -            tevs = 2;
  2300. -        }
  2301. -}
  2302. -
  2303. -/* set a parameter to a string value */
  2304. -
  2305. -void setparm(char *s,char *t,int ex,int isint)
  2306. -{
  2307. -struct pmnode *pmn,*pmo;
  2308. -
  2309. -    if (!strcmp(s,"RANDOM"))
  2310. -        {
  2311. -        srand((unsigned long) atol(t));
  2312. -        return;
  2313. -        }
  2314. -    if (!strcmp(s,"SECONDS"))
  2315. -        {
  2316. -        shtimer = atol(t)+time(NULL);
  2317. -        return;
  2318. -        }
  2319. -    if (ex && gethnode(s,parmhtab))
  2320. -        freepm(remhnode(s,parmhtab));
  2321. -    if (pmo = gethnode(s,parmhtab))
  2322. -        {
  2323. -        pmn = alloc(sizeof *pmn);
  2324. -        if (pmn->isint = pmo->isint | isint)
  2325. -            {
  2326. -            pmn->u.val = matheval(t);
  2327. -            free(t);
  2328. -            t = NULL;
  2329. -            }
  2330. -        else
  2331. -            pmn->u.str = t;
  2332. -        addhnode(s,pmn,parmhtab,freepm);
  2333. -        }
  2334. -    else if (ex || getenv(s) || (opts[ALLEXPORT] == OPT_SET))
  2335. -        putenv(tricat(s,"=",t));
  2336. -    else
  2337. -        {
  2338. -        pmn = alloc(sizeof *pmn);
  2339. -        if (pmn->isint = isint)
  2340. -            {
  2341. -            pmn->u.val = matheval(t);
  2342. -            free(t);
  2343. -            t = NULL;
  2344. -            }
  2345. -        else
  2346. -            pmn->u.str = t;
  2347. -        addhnode(s,pmn,parmhtab,freepm);
  2348. -#if 0
  2349. -        addlocal(s);
  2350. -#endif
  2351. -        }
  2352. -    if (!t)
  2353. -        return;
  2354. -    if (!strcmp(s,"PATH"))
  2355. -        parsepath();
  2356. -    if (!strcmp(s,"CDPATH"))
  2357. -        parsecdpath();
  2358. -    if (!strcmp(s,"IFS"))
  2359. -        {
  2360. -        free(ifs);
  2361. -        ifs = strdup(t);
  2362. -        }
  2363. -    if (!strcmp(s,"PERIOD"))
  2364. -        {
  2365. -        period = atoi(t)*60;
  2366. -        lastperiod = time(NULL)+period;
  2367. -        }
  2368. -    if (!strcmp(s,"HISTSIZE"))
  2369. -        {
  2370. -        tevs = atoi(t);
  2371. -        if (tevs <= 2)
  2372. -            tevs = 2;
  2373. -        }
  2374. -    if (!strcmp(s,"HOME"))
  2375. -        {
  2376. -        free(home);
  2377. -        home = xsymlink(t);
  2378. -        }
  2379. -    if (!strcmp(s,"MAIL") || !strcmp(s,"MAILCHECK") || !strcmp(s,"MAILPATH"))
  2380. -        lastmailcheck = 0;
  2381. -}
  2382. -
  2383. -void unsetparm(char *s)
  2384. -{
  2385. -char **pp;
  2386. -
  2387. -    if (!strcmp(s,"HOME"))
  2388. -        return;
  2389. -    if (!strcmp(s,"PERIOD"))
  2390. -        period = 0;
  2391. -    if (!strcmp(s,"HISTSIZE"))
  2392. -        tevs = 1;
  2393. -    if (gethnode(s,parmhtab))
  2394. -        {
  2395. -        freepm(remhnode(s,parmhtab));
  2396. -        return;
  2397. -        }
  2398. -    for (pp = environ; *pp; pp++)
  2399. -        if (!strncmp(*pp,s,strlen(s)) && (*pp)[strlen(s)] == '=')
  2400. -            {
  2401. -            while (pp[0] = pp[1])
  2402. -                pp++;
  2403. -            return;
  2404. -            }
  2405. -}
  2406. -
  2407. -/* get the integer value of a parameter */
  2408. -
  2409. -long getiparm(char *s)
  2410. -{
  2411. -struct pmnode *pmn;
  2412. -char *t;
  2413. -
  2414. -    if (!isalpha(*s) && !s[1])
  2415. -        {
  2416. -        t = getsparmval(s,1);
  2417. -        return (t) ? atoi(t) : 0;
  2418. -        }
  2419. -    if (s[0] == 'T' && s[1] == 'C' && !s[4])    /* TCxx */
  2420. -        return tgetnum(s+2);
  2421. -    if (!strcmp(s,"RANDOM"))
  2422. -        return rand() & 0x7fff;
  2423. -    if (!strcmp(s,"LINENO"))
  2424. -        return lineno;
  2425. -    if (!strcmp(s,"SECONDS"))
  2426. -        return time(NULL)-shtimer;
  2427. -    if (pmn = gethnode(s,parmhtab))
  2428. -        {
  2429. -        if (pmn->isint)
  2430. -            return pmn->u.val;
  2431. -        return atol(pmn->u.str);
  2432. -        }
  2433. -    return atol(getenv(s));
  2434. -}
  2435. -
  2436. -/* get the string value of a parameter */
  2437. -
  2438. -char *getparm(char *s)
  2439. -{
  2440. -struct pmnode *pmn;
  2441. -
  2442. -    if (!isalpha(*s) && !s[1])
  2443. -        return getsparmval(s,1);
  2444. -    if (s[0] == 'T' && s[1] == 'C' && !s[4])    /* TCxx */
  2445. -        {
  2446. -        static char buf[1024];
  2447. -        char *ss = buf;
  2448. -        int t0;
  2449. -
  2450. -        if (tgetstr(s+2,&ss))
  2451. -            return buf;
  2452. -        if ((t0 = tgetnum(s+2)) != -1)
  2453. -            {
  2454. -            sprintf(buf,"%d",t0);
  2455. -            return buf;
  2456. -            }
  2457. -        return NULL;
  2458. -        }
  2459. -    if (!strcmp(s,"LINENO"))
  2460. -        {
  2461. -        static char buf[8];
  2462. -
  2463. -        sprintf(buf,"%d",lineno);
  2464. -        return buf;
  2465. -        }
  2466. -    if (!strcmp(s,"RANDOM"))
  2467. -        {
  2468. -        static char buf[8];
  2469. -
  2470. -        sprintf(buf,"%d",rand() & 0x7fff);
  2471. -        return buf;
  2472. -        }
  2473. -    if (!strcmp(s,"SECONDS"))
  2474. -        {
  2475. -        static char buf[12];
  2476. -
  2477. -        sprintf(buf,"%ld",time(NULL)-shtimer);
  2478. -        return buf;
  2479. -        }
  2480. -    if (pmn = gethnode(s,parmhtab))
  2481. -        {
  2482. -        static char buf[12];
  2483. -
  2484. -        if (pmn->isint)
  2485. -            {
  2486. -            sprintf(buf,"%ld",pmn->u.val);
  2487. -            return buf;
  2488. -            }
  2489. -        return pmn->u.str;
  2490. -        }
  2491. -    return getenv(s);
  2492. -}
  2493. -
  2494. -/* parse the PATH parameter into directory names in a array of
  2495. -    strings and create the command hash table */
  2496. -
  2497. -void parsepath(void)
  2498. -{
  2499. -char *pptr = getparm("PATH"),*ptr;
  2500. -
  2501. -    if (path)
  2502. -        {
  2503. -        while(pathct)
  2504. -            free(path[--pathct]);
  2505. -        free(path);
  2506. -        }
  2507. -    for (pathct = 1, ptr = pptr; *ptr; ptr++)
  2508. -        if (*ptr == ':')
  2509. -            pathct++;
  2510. -    path = (char **) zalloc(pathct*sizeof(char *));
  2511. -    pathct = 0;
  2512. -    ptr = pptr;
  2513. -    while(pptr)
  2514. -        {
  2515. -        ptr = strchr(pptr,':');
  2516. -        if (ptr)
  2517. -            *ptr = '\0';
  2518. -        path[pathct] = strdup(pptr);
  2519. -        if (ptr)
  2520. -            {
  2521. -            *ptr = ':';
  2522. -            pptr = ptr+1;
  2523. -            }
  2524. -        else
  2525. -            pptr = NULL;
  2526. -        if (!*path[pathct])
  2527. -            {
  2528. -            free(path[pathct]);
  2529. -            path[pathct] = strdup(".");
  2530. -            }
  2531. -        pathsub(&path[pathct]);
  2532. -        if (*path[pathct] != '/' && strcmp(path[pathct],"."))
  2533. -            {
  2534. -#ifdef PATH_WARNINGS
  2535. -            zerr("PATH component not absolute pathname: %s",path[pathct]);
  2536. -#endif
  2537. -            free(path[pathct--]);
  2538. -            }
  2539. -        pathct++;
  2540. -        }
  2541. -    createchtab();
  2542. -}
  2543. -
  2544. -void parsecdpath(void)
  2545. -{
  2546. -char *pptr = getparm("CDPATH"),*ptr;
  2547. -
  2548. -    if (cdpath)
  2549. -        {
  2550. -        while(cdpathct)
  2551. -            free(cdpath[--cdpathct]);
  2552. -        free(cdpath);
  2553. -        }
  2554. -    if (pptr == NULL)
  2555. -        {
  2556. -        cdpath = (char **) zalloc(sizeof(char *));
  2557. -        cdpath[0] = strdup(".");
  2558. -        cdpathct = 1;
  2559. -        return;
  2560. -        }
  2561. -    for (cdpathct = 2, ptr = pptr; *ptr; ptr++)
  2562. -        if (*ptr == ':')
  2563. -            cdpathct++;
  2564. -    cdpath = (char **) zalloc(cdpathct*sizeof(char *));
  2565. -    cdpath[0] = strdup(".");
  2566. -    cdpathct = 1;
  2567. -    ptr = pptr;
  2568. -    while (pptr)
  2569. -        {
  2570. -        ptr = strchr(pptr,':');
  2571. -        if (ptr)
  2572. -            *ptr = '\0';
  2573. -        cdpath[cdpathct] = strdup(pptr);
  2574. -        if (ptr)
  2575. -            {
  2576. -            *ptr = ':';
  2577. -            pptr = ptr+1;
  2578. -            }
  2579. -        else
  2580. -            pptr = NULL;
  2581. -        pathsub(&cdpath[cdpathct]);
  2582. -        if (*cdpath[cdpathct] != '/')
  2583. -            {
  2584. -#ifdef PATH_WARNINGS
  2585. -            zerr("CDPATH component not absolute pathname: %s",cdpath[cdpathct]);
  2586. -#endif
  2587. -            free(cdpath[cdpathct--]);
  2588. -            }
  2589. -        cdpathct++;
  2590. -        }
  2591. -}
  2592. -
  2593. -/* source a file */
  2594. -
  2595. -int source(char *s)
  2596. -{
  2597. -int fd,cj = curjob,iact = opts[INTERACTIVE];
  2598. -FILE *obshin = bshin;
  2599. -
  2600. -    fd = SHIN;
  2601. -    opts[INTERACTIVE] = OPT_UNSET;
  2602. -    if ((SHIN = movefd(open(s,O_RDONLY))) == -1)
  2603. -        {
  2604. -        SHIN = fd;
  2605. -        curjob = cj;
  2606. -        opts[INTERACTIVE] = iact;
  2607. -        return 1;
  2608. -        }
  2609. -    bshin = fdopen(SHIN,"r");
  2610. -    loop();
  2611. -    fclose(bshin);
  2612. -    opts[INTERACTIVE] = iact;
  2613. -    bshin = obshin;
  2614. -    SHIN = fd;
  2615. -    peek = EMPTY;
  2616. -    curjob = cj;
  2617. -    errflag = 0;
  2618. -    retflag = 0;
  2619. -    return 0;
  2620. -}
  2621. -
  2622. -/* try to source a file in our home directory */
  2623. -
  2624. -void sourcehome(char *s)
  2625. -{
  2626. -char buf[MAXPATHLEN];
  2627. -
  2628. -    sprintf(buf,"%s/%s",getparm("HOME"),s);
  2629. -    (void) source(buf);
  2630. -}
  2631. -
  2632. -/* print an error */
  2633. -
  2634. -void zerrnam(char *cmd, char *fmt, ...)
  2635. -{
  2636. -va_list ap;
  2637. -char *str;
  2638. -int num;
  2639. -
  2640. -    va_start(ap,fmt);
  2641. -    fputs(cmd,stderr);
  2642. -    putc(':',stderr);
  2643. -    putc(' ',stderr);
  2644. -    while (*fmt)
  2645. -        if (*fmt == '%')
  2646. -            {
  2647. -            fmt++;
  2648. -            switch(*fmt++)
  2649. -                {
  2650. -                case 's':    /* string */
  2651. -                    str = va_arg(ap,char *);
  2652. -                    while (*str)
  2653. -                        niceputc(*str++,stderr);
  2654. -                    break;
  2655. -                case 'l':    /* string with a length */
  2656. -                    num = va_arg(ap,int);
  2657. -                    str = va_arg(ap,char *);
  2658. -                    while (num--)
  2659. -                        niceputc(*str++,stderr);
  2660. -                    break;
  2661. -                case 'd':    /* number */
  2662. -                    num = va_arg(ap,int);
  2663. -                    fprintf(stderr,"%d",num);
  2664. -                    break;
  2665. -                case '%':
  2666. -                    putc('%',stderr);
  2667. -                    break;
  2668. -                case 'c':    /* char */
  2669. -                    num = va_arg(ap,int);
  2670. -                    niceputc(num,stderr);
  2671. -                    break;
  2672. -                case 'e':    /* system error */
  2673. -                    num = va_arg(ap,int);
  2674. -                    if (num == EINTR)
  2675. -                        {
  2676. -                        fputs("interrupt\n",stderr);
  2677. -                        errflag = 1;
  2678. -                        return;
  2679. -                        }
  2680. -                    fputc(tolower(sys_errlist[num][0]),stderr);
  2681. -                    fputs(sys_errlist[num]+1,stderr);
  2682. -                    break;
  2683. -                }
  2684. -            }
  2685. -        else
  2686. -            putc(*fmt++,stderr);
  2687. -    putc('\n',stderr);
  2688. -    va_end(ap);
  2689. -}
  2690. -
  2691. -void zerr(char *fmt,...)
  2692. -{
  2693. -va_list ap;
  2694. -char *str;
  2695. -int num;
  2696. -
  2697. -    va_start(ap,fmt);
  2698. -    fputs("zsh: ",stderr);
  2699. -    while (*fmt)
  2700. -        if (*fmt == '%')
  2701. -            {
  2702. -            fmt++;
  2703. -            switch(*fmt++)
  2704. -                {
  2705. -                case 's':
  2706. -                    str = va_arg(ap,char *);
  2707. -                    while (*str)
  2708. -                        niceputc(*str++,stderr);
  2709. -                    break;
  2710. -                case 'l':
  2711. -                    num = va_arg(ap,int);
  2712. -                    str = va_arg(ap,char *);
  2713. -                    while (num--)
  2714. -                        niceputc(*str++,stderr);
  2715. -                    break;
  2716. -                case 'd':
  2717. -                    num = va_arg(ap,int);
  2718. -                    fprintf(stderr,"%d",num);
  2719. -                    break;
  2720. -                case '%':
  2721. -                    putc('%',stderr);
  2722. -                    break;
  2723. -                case 'c':
  2724. -                    num = va_arg(ap,int);
  2725. -                    niceputc(num,stderr);
  2726. -                    break;
  2727. -                case 'e':
  2728. -                    num = va_arg(ap,int);
  2729. -                    if (num == EINTR)
  2730. -                        {
  2731. -                        fputs("interrupt\n",stderr);
  2732. -                        errflag = 1;
  2733. -                        return;
  2734. -                        }
  2735. -                    fputc(tolower(sys_errlist[num][0]),stderr);
  2736. -                    fputs(sys_errlist[num]+1,stderr);
  2737. -                    break;
  2738. -                }
  2739. -            }
  2740. -        else
  2741. -            putc(*fmt++,stderr);
  2742. -    putc('\n',stderr);
  2743. -    va_end(ap);
  2744. -}
  2745. -
  2746. -void niceputc(int c,FILE *f)
  2747. -{
  2748. -    if (istok(c))
  2749. -        {
  2750. -        if (c >= Pound && c <= Qtick)
  2751. -            putc(tokens[c-Pound],f);
  2752. -        return;
  2753. -        }
  2754. -    c &= 0x7f;
  2755. -    if (c >= ' ' && c < '\x7f')
  2756. -        putc(c,f);
  2757. -    else if (c == '\n')
  2758. -        {
  2759. -        putc('\\',f);
  2760. -        putc('n',f);
  2761. -        }
  2762. -    else
  2763. -        {
  2764. -        putc('^',f);
  2765. -        putc(c|'A',f);
  2766. -        }
  2767. -}
  2768. -
  2769. -/* enable ^C interrupts */
  2770. -
  2771. -void intr(void)
  2772. -{
  2773. -struct sigvec vec = { handler,sigmask(SIGINT),SV_INTERRUPT };
  2774. -    
  2775. -    if (interact)
  2776. -        sigvec(SIGINT,&vec,NULL);
  2777. -    sigsetmask(0);
  2778. -}
  2779. -
  2780. -void noholdintr(void)
  2781. -{
  2782. -    intr();
  2783. -}
  2784. -
  2785. -void holdintr(void)
  2786. -{
  2787. -struct sigvec vec = { handler,sigmask(SIGINT),0 };
  2788. -
  2789. -    if (interact)
  2790. -        {
  2791. -        sigvec(SIGINT,&vec,NULL);
  2792. -        sigsetmask(0);
  2793. -        }
  2794. -}
  2795. -
  2796. -char *fgetline(char *buf,int len,FILE *in)
  2797. -{
  2798. -    if (!fgets(buf,len,in))
  2799. -        return NULL;
  2800. -    buf[len] = '\0';
  2801. -    buf[strlen(buf)-1] = '\0';
  2802. -    return buf;
  2803. -}
  2804. -
  2805. -/* get a symlink-free pathname for s relative to PWD */
  2806. -
  2807. -char *findcwd(char *s)
  2808. -{
  2809. -char *t;
  2810. -
  2811. -    if (*s == '/')
  2812. -        return xsymlink(s);
  2813. -    s = tricat((cwd[1]) ? cwd : "","/",s);
  2814. -    t = xsymlink(s);
  2815. -    free(s);
  2816. -    return t;
  2817. -}
  2818. -
  2819. -static char xbuf[MAXPATHLEN];
  2820. -
  2821. -/* expand symlinks in s, and remove other weird things */
  2822. -
  2823. -char *xsymlink(char *s)
  2824. -{
  2825. -    if (*s != '/')
  2826. -        return NULL;
  2827. -    strcpy(xbuf,"");
  2828. -    if (xsymlinks(s+1))
  2829. -        return strdup(s);
  2830. -    if (!*xbuf)
  2831. -        return strdup("/");
  2832. -    return strdup(xbuf);
  2833. -}
  2834. -
  2835. -char **slashsplit(char *s)
  2836. -{
  2837. -char *t,**r,**q;
  2838. -int t0;
  2839. -
  2840. -    if (!*s)
  2841. -        return (char **) calloc(sizeof(char **),1);
  2842. -    for (t = s, t0 = 0; *t; t++)
  2843. -        if (*t == '/')
  2844. -            t0++;
  2845. -    q  = r = (char **) zalloc(sizeof(char **)*(t0+2));
  2846. -    while (t = strchr(s,'/'))
  2847. -        {
  2848. -        *t = '\0';
  2849. -        *q++ = strdup(s);
  2850. -        *t = '/';
  2851. -        while (*t == '/')
  2852. -            t++;
  2853. -        if (!*t)
  2854. -            {
  2855. -            *q = NULL;
  2856. -            return r;
  2857. -            }
  2858. -        s = t;
  2859. -        }
  2860. -    *q++ = strdup(s);
  2861. -    *q = NULL;
  2862. -    return r;
  2863. -}
  2864. -
  2865. -int islink(char *s)
  2866. -{
  2867. -char xbuf[MAXPATHLEN];
  2868. -
  2869. -    if (readlink(s,xbuf,1) == -1 && errno == EINVAL)
  2870. -        return 0;
  2871. -    return 1;
  2872. -}
  2873. -
  2874. -int xsymlinks(char *s)
  2875. -{
  2876. -char **pp,**opp;
  2877. -char xbuf2[MAXPATHLEN],xbuf3[MAXPATHLEN];
  2878. -int t0;
  2879. -
  2880. -    opp = pp = slashsplit(s);
  2881. -    for (; *pp; pp++)
  2882. -        {
  2883. -        if (!strcmp(*pp,"."))
  2884. -            {
  2885. -            free(*pp);
  2886. -            continue;
  2887. -            }
  2888. -        if (!strcmp(*pp,".."))
  2889. -            {
  2890. -            char *p;
  2891. -
  2892. -            free(*pp);
  2893. -            if (!strcmp(xbuf,"/"))
  2894. -                continue;
  2895. -            p = xbuf+strlen(xbuf);
  2896. -            while (*--p != '/');
  2897. -            *p = '\0';
  2898. -            continue;
  2899. -            }
  2900. -        sprintf(xbuf2,"%s/%s",xbuf,*pp);
  2901. -        t0 = readlink(xbuf2,xbuf3,MAXPATHLEN);
  2902. -        if (t0 == -1)
  2903. -            {
  2904. -            if (errno != EINVAL)
  2905. -                {
  2906. -                while (*pp)
  2907. -                    free(*pp++);
  2908. -                free(opp);
  2909. -                return 1;
  2910. -                }
  2911. -            strcat(xbuf,"/");
  2912. -            strcat(xbuf,*pp);
  2913. -            free(*pp);
  2914. -            }
  2915. -        else
  2916. -            {
  2917. -            xbuf3[t0] = '\0'; /* STUPID */
  2918. -            if (*xbuf3 == '/')
  2919. -                {
  2920. -                strcpy(xbuf,"");
  2921. -                if (xsymlinks(xbuf3+1))
  2922. -                    return 1;
  2923. -                }
  2924. -            else
  2925. -                if (xsymlinks(xbuf3))
  2926. -                    return 1;
  2927. -            free(*pp);
  2928. -            }
  2929. -        }
  2930. -    free(opp);
  2931. -    return 0;
  2932. -}
  2933. -
  2934. -void printdir(char *s)
  2935. -{
  2936. -int t0;
  2937. -
  2938. -    if (!strncmp(s,home,t0 = strlen(home)))
  2939. -        {
  2940. -        putchar('~');
  2941. -        fputs(s+t0,stdout);
  2942. -        }
  2943. -    else
  2944. -        fputs(s,stdout);
  2945. -}
  2946. -
  2947. -
  2948. -int ddifftime(time_t t1,time_t t2)
  2949. -{
  2950. -    return ((long) t2-(long) t1);
  2951. -}
  2952. -
  2953. -/* see if jobs need printing */
  2954. -
  2955. -void scanjobs(void)
  2956. -{
  2957. -int t0;
  2958. -
  2959. -    for (t0 = 1; t0 != MAXJOB; t0++)
  2960. -        if (jobtab[t0].stat & STAT_CHANGED)
  2961. -            printjob(jobtab+t0,0);
  2962. -}
  2963. -
  2964. -/* do pre-prompt stuff */
  2965. -
  2966. -void preprompt(void)
  2967. -{
  2968. -int diff;
  2969. -list list;
  2970. -char *mc = getparm("MAILCHECK"),*wc = getparm("LOGCHECK");
  2971. -struct schnode *sch,*schl;
  2972. -
  2973. -    if (unset(NOTIFY))
  2974. -        scanjobs();
  2975. -    if (errflag)
  2976. -        return;
  2977. -    if (list = gethnode("precmd",shfunchtab))
  2978. -        newrunlist(list);
  2979. -    if (errflag)
  2980. -        return;
  2981. -    if (period && (time(NULL) > lastperiod+period) &&
  2982. -            (list = gethnode("periodic",shfunchtab)))
  2983. -        {
  2984. -        newrunlist(list);
  2985. -        lastperiod = time(NULL);
  2986. -        }
  2987. -    if (errflag)
  2988. -        return;
  2989. -    if (getparm("WATCH"))
  2990. -        {
  2991. -        diff = (int) ddifftime(lastwatch,time(NULL));
  2992. -        if (diff > ((wc) ? atoi(wc)*60 : 300))
  2993. -            {
  2994. -            lastwatch = time(NULL);
  2995. -            watch();
  2996. -            }
  2997. -        }
  2998. -    if (errflag)
  2999. -        return;
  3000. -    diff = (int) ddifftime(lastmailcheck,time(NULL));
  3001. -    if (diff > ((mc) ? atoi(mc) : 60))
  3002. -        {
  3003. -        lastmailcheck = time(NULL);
  3004. -        if (getparm("MAILPATH"))
  3005. -            checkmailpath();
  3006. -        else
  3007. -            checkmail();
  3008. -        }
  3009. -    for (schl = (struct schnode *) &scheds, sch = scheds; sch;
  3010. -            sch = (schl = sch)->next)
  3011. -        {
  3012. -        if (sch->time < time(NULL))
  3013. -            {
  3014. -            execstring(sch->cmd);
  3015. -            schl->next = sch->next;
  3016. -            free(sch);
  3017. -            }
  3018. -        if (errflag)
  3019. -            return;
  3020. -        }
  3021. -}
  3022. -void checkmail(void)
  3023. -{
  3024. -struct stat st;
  3025. -char *s;
  3026. -
  3027. -    if (!(s = getparm("MAIL")))
  3028. -        return;
  3029. -    if (stat(s,&st) == -1)
  3030. -        {
  3031. -        if (errno != ENOENT)
  3032. -            zerr("%e: %s",errno,getparm("MAIL"));
  3033. -        lastmailval = 0;
  3034. -        lastmailsize = 0;
  3035. -        return;
  3036. -        }
  3037. -    else
  3038. -        if (lastmailval != -1 && lastmailval < st.st_mtime &&
  3039. -                lastmailsize < st.st_size)
  3040. -            zerr("you have new mail.");
  3041. -    lastmailval = st.st_mtime;
  3042. -    lastmailsize = st.st_size;
  3043. -}
  3044. -
  3045. -void checkfirstmail(void)
  3046. -{
  3047. -struct stat st;
  3048. -char *s;
  3049. -
  3050. -    if (!(s = getparm("MAIL")))
  3051. -        return;
  3052. -    if (stat(s,&st) == -1)
  3053. -        {
  3054. -        if (errno != ENOENT)
  3055. -            zerr("%e: %s",errno,getparm("MAIL"));
  3056. -        lastmailval = 0;
  3057. -        lastmailsize = 0;
  3058. -        return;
  3059. -        }
  3060. -    lastmailval = st.st_mtime;
  3061. -    lastmailsize = st.st_size;
  3062. -    zerr("you have mail.");
  3063. -}
  3064. -void checkmailpath(void)
  3065. -{
  3066. -struct stat st;
  3067. -char *s = getparm("MAILPATH"),*v,*u,c,d;
  3068. -
  3069. -    for (;;)
  3070. -        {
  3071. -        for (v = s; *v && *v != '?' && *v != ':'; v++);
  3072. -        c = *v;
  3073. -        *v = '\0';
  3074. -        if (c != '?')
  3075. -            u = NULL;
  3076. -        else
  3077. -            {
  3078. -            for (u = v+1; *u && *u != ':'; u++);
  3079. -            d = *u;
  3080. -            *u = '\0';
  3081. -            }
  3082. -        if (stat(s,&st) == -1)
  3083. -            {
  3084. -            if (errno != ENOENT)
  3085. -                zerr("%e: %s",errno,getparm("MAIL"));
  3086. -            }
  3087. -        else
  3088. -            if (lastmailval != -1 && lastmailval < st.st_mtime &&
  3089. -                    lastmailsize < st.st_size)
  3090. -                if (!u)
  3091. -                    fprintf(stderr,"You have new mail.\n");
  3092. -                else
  3093. -                    {
  3094. -                    char *z = u;
  3095. -
  3096. -                    while (*z)
  3097. -                        if (*z == '$' && z[1] == '_')
  3098. -                            {
  3099. -                            fprintf(stderr,"%s",s);
  3100. -                            z += 2;
  3101. -                            }
  3102. -                        else
  3103. -                            fputc(*z++,stderr);
  3104. -                    fputc('\n',stderr);
  3105. -                    }
  3106. -        lastmailval = st.st_mtime;
  3107. -        lastmailsize = st.st_size;
  3108. -        *v = c;
  3109. -        if (u)
  3110. -            *u = d;
  3111. -        if (!c || (u && !d))
  3112. -            break;
  3113. -        v = (u) ? u+1 : v+1;
  3114. -        }
  3115. -}
  3116. -
  3117. -/* create command hash table */
  3118. -
  3119. -void createchtab(void)
  3120. -{
  3121. -int t0,dot = 0;
  3122. -struct direct *de;
  3123. -DIR *dir;
  3124. -struct chnode *cc;
  3125. -
  3126. -    holdintr();
  3127. -    if (chtab)
  3128. -        freehtab(chtab,freechnode);
  3129. -    chtab = newhtable(101);
  3130. -    for (t0 = 0; t0 != pathct; t0++)
  3131. -        if (!strcmp(".",path[t0]))
  3132. -            {
  3133. -            dot = 1;
  3134. -            break;
  3135. -            }
  3136. -    for (t0 = pathct-1; t0 >= 0; t0--)
  3137. -        if (!strcmp(".",path[t0]))
  3138. -            dot = 0;
  3139. -        else
  3140. -            {
  3141. -            dir = opendir(path[t0]);
  3142. -            if (!dir)
  3143. -                {
  3144. -                zerr("%e: %s",errno,path[t0]);
  3145. -                continue;
  3146. -                }
  3147. -            readdir(dir); readdir(dir);
  3148. -            while (de = readdir(dir))
  3149. -                {
  3150. -                cc = alloc(sizeof(struct chnode));
  3151. -                cc->type = (dot) ? EXCMD_POSTDOT : EXCMD_PREDOT;
  3152. -                cc->globstat = GLOB;
  3153. -                cc->u.nam = tricat(path[t0],"/",de->d_name);
  3154. -                addhnode(strdup(de->d_name),cc,chtab,freechnode);
  3155. -                }
  3156. -            closedir(dir);
  3157. -            }
  3158. -    addintern(chtab);
  3159. -    noholdintr();
  3160. -}
  3161. -
  3162. -void freechnode(void *a)
  3163. -{
  3164. -struct chnode *c = (struct chnode *) a;
  3165. -
  3166. -    if (c->type != BUILTIN)
  3167. -        free(c->u.nam);
  3168. -    free(c);
  3169. -}
  3170. -
  3171. -void freestr(void *a)
  3172. -{
  3173. -    free(a);
  3174. -}
  3175. -
  3176. -void freeanode(void *a)
  3177. -{
  3178. -struct anode *c = (struct anode *) a;
  3179. -
  3180. -    free(c->text);
  3181. -    free(c);
  3182. -}
  3183. -
  3184. -void freeredir(void *a)
  3185. -{
  3186. -struct fnode *f = (struct fnode *) a;
  3187. -
  3188. -    if (f)
  3189. -        {
  3190. -        if (f->type == HEREDOC)
  3191. -            close(f->u.fd2);
  3192. -        else
  3193. -            free(f->u.name);
  3194. -        free(f);
  3195. -        }
  3196. -}
  3197. -
  3198. -void freeshfunc(void *a)
  3199. -{
  3200. -    freelist((list) a);
  3201. -}
  3202. -
  3203. -void freepm(void *a)
  3204. -{
  3205. -struct pmnode *pm = a;
  3206. -
  3207. -    if (!pm->isint)
  3208. -        free(pm->u.str);
  3209. -    free(pm);
  3210. -}
  3211. -
  3212. -void restoretty(void)
  3213. -{
  3214. -    settyinfo(&shttyinfo);
  3215. -}
  3216. -
  3217. -void gettyinfo(struct ttyinfo *ti)
  3218. -{
  3219. -    if (jobbing)
  3220. -        {
  3221. -#ifndef BUGGY_GCC
  3222. -#ifdef TERMIOS
  3223. -        ioctl(SHTTY,TCGETS,&ti->termios);
  3224. -#else
  3225. -        ioctl(SHTTY,TIOCGETP,&ti->sgttyb);
  3226. -        ioctl(SHTTY,TIOCGETC,&ti->tchars);
  3227. -        ioctl(SHTTY,TIOCGLTC,&ti->ltchars);
  3228. -#endif
  3229. -        ioctl(SHTTY,TIOCGWINSZ,&ti->winsize);
  3230. -#else
  3231. -#ifdef TERMIOS
  3232. -        ioctl(SHTTY,    (    0x40000000    |((sizeof( struct termios)&0xff        )<<16)|('T'<<8)| 8)  ,&ti->termios);
  3233. -#else
  3234. -        ioctl(SHTTY,(0x40000000|((sizeof(struct sgttyb)&0x1fff)<<16)|
  3235. -            ('t'<<8)|8),&ti->sgttyb);
  3236. -        ioctl(SHTTY,(0x40000000|((sizeof(struct tchars)&0x1fff)<<16)|
  3237. -            ('t'<<8)|18),&ti->tchars);
  3238. -        ioctl(SHTTY,(0x40000000|((sizeof(struct ltchars)&0x1fff)<<16)|
  3239. -            ('t'<<8)|116),&ti->ltchars);
  3240. -#endif
  3241. -        ioctl(SHTTY,(    0x40000000    |((sizeof( struct winsize)&0xff        )<<16)|('t'<<8)| 104)     ,&ti->winsize);
  3242. -#endif
  3243. -        }
  3244. -}
  3245. -
  3246. -void settyinfo(struct ttyinfo *ti)
  3247. -{
  3248. -    if (jobbing)
  3249. -        {
  3250. -#ifndef BUGGY_GCC
  3251. -#ifdef TERMIOS
  3252. -        ioctl(SHTTY,TCSETS,&ti->termios);
  3253. -#else
  3254. -        ioctl(SHTTY,TIOCSETP,&ti->sgttyb);
  3255. -        ioctl(SHTTY,TIOCSETC,&ti->tchars);
  3256. -        ioctl(SHTTY,TIOCSLTC,&ti->ltchars);
  3257. -#endif
  3258. -        ioctl(SHTTY,TIOCSWINSZ,&ti->winsize);
  3259. -#else
  3260. -#ifdef TERMIOS
  3261. -        ioctl(SHTTY,    (    0x80000000    |((sizeof( struct termios)&0xff        )<<16)|('T'<<8)| 9)  ,&ti->termios);
  3262. -#else
  3263. -        ioctl(SHTTY,(0x80000000|((sizeof( struct sgttyb)&0x1fff)<<16)|
  3264. -            ('t'<<8)|9),&ti->sgttyb);
  3265. -        ioctl(SHTTY,(0x80000000|((sizeof(struct tchars)&0x1fff)<<16)|
  3266. -            ('t'<<8)|17),&ti->tchars);
  3267. -        ioctl(SHTTY,(0x80000000|((sizeof(struct ltchars)&0x1fff)<<16)|
  3268. -            ('t'<<8)|117),&ti->ltchars);
  3269. -#endif
  3270. -        ioctl(SHTTY,(    0x80000000    |((sizeof( struct winsize)&0xff        )<<16)|('t'<<8)| 103)     ,&ti->winsize);
  3271. -#endif
  3272. -        }
  3273. -}
  3274. -
  3275. -int zyztem(char *s,char *t)
  3276. -{
  3277. -#ifdef WAITPID
  3278. -int pid,statusp;
  3279. -
  3280. -    if (!(pid = fork()))
  3281. -        {
  3282. -        s = tricat(s," ",t);
  3283. -        execl("/bin/sh","sh","-c",s,(char *) 0);
  3284. -        _exit(1);
  3285. -        }
  3286. -    waitpid(pid,&statusp,WUNTRACED);
  3287. -    if (WIFEXITED(SP(statusp)))
  3288. -        return WEXITSTATUS(SP(statusp));
  3289. -    return 1;
  3290. -#else
  3291. -    if (!waitfork())
  3292. -        {
  3293. -        s = tricat(s," ",t);
  3294. -        execl("/bin/sh","sh","-c",s,(char *) 0);
  3295. -        _exit(1);
  3296. -        }
  3297. -    return 0;
  3298. -#endif
  3299. -}
  3300. -
  3301. -#ifndef WAITPID
  3302. -
  3303. -/* fork a process and wait for it to complete without confusing
  3304. -    the SIGCHLD handler */
  3305. -
  3306. -int waitfork(void)
  3307. -{
  3308. -int pipes[2];
  3309. -char x;
  3310. -
  3311. -    pipe(pipes);
  3312. -    if (!fork())
  3313. -        {
  3314. -        close(pipes[0]);
  3315. -        signal(SIGCHLD,SIG_DFL);
  3316. -        if (!fork())
  3317. -            return 0;
  3318. -        wait(NULL);
  3319. -        _exit(0);
  3320. -        }
  3321. -    close(pipes[1]);
  3322. -    read(pipes[0],&x,1);
  3323. -    close(pipes[0]);
  3324. -    return 1;
  3325. -}
  3326. -
  3327. -#endif
  3328. -
  3329. -/* move a fd to a place >= 10 */
  3330. -
  3331. -int movefd(int fd)
  3332. -{
  3333. -int fe;
  3334. -
  3335. -    if (fd == -1)
  3336. -        return fd;
  3337. -    if ((fe = dup(fd)) < 10)
  3338. -        fe = movefd(fe);
  3339. -    close(fd);
  3340. -    return fe;
  3341. -}
  3342. -
  3343. -/* move fd x to y */
  3344. -
  3345. -void redup(int x,int y)
  3346. -{
  3347. -    if (x != y)
  3348. -        {
  3349. -        dup2(x,y);
  3350. -        close(x);
  3351. -        }
  3352. -}
  3353. -
  3354. -void settrap(char *s,int empty)
  3355. -{
  3356. -int t0;
  3357. -
  3358. -    if (strncmp(s,"TRAP",4))
  3359. -        return;
  3360. -    for (t0 = 0; t0 != SIGCOUNT+2; t0++)
  3361. -        if (!strcmp(s+4,sigs[t0]))
  3362. -            {
  3363. -            if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
  3364. -                    || t0 == SIGPIPE))
  3365. -                {
  3366. -                zerr("can't trap SIG%s in interactive shells",s);
  3367. -                return;
  3368. -                }
  3369. -            if (empty)
  3370. -                {
  3371. -                sigtrapped[t0] = 2;
  3372. -                if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
  3373. -                    {
  3374. -                    signal(t0,SIG_IGN);
  3375. -                    sigtrapped[t0] = 2;
  3376. -                    }
  3377. -                }
  3378. -            else
  3379. -                {
  3380. -                if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
  3381. -                    signal(t0,handler);
  3382. -                sigtrapped[t0] = 1;
  3383. -                }
  3384. -            return;
  3385. ---cut here---cut here---cut here---
  3386.