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

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