home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume24 / zsh2.1 / part06 < prev    next >
Text File  |  1991-10-24  |  49KB  |  2,426 lines

  1. Newsgroups: comp.sources.misc
  2. From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  3. Subject:  v24i006:  zsh2.1 - The Z shell, Part06/19
  4. Message-ID: <1991Oct24.190840.25712@sparky.imd.sterling.com>
  5. X-Md4-Signature: 01c07cafb955e10e801560c9c5869f5c
  6. Date: Thu, 24 Oct 1991 19:08:40 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  10. Posting-number: Volume 24, Issue 6
  11. Archive-name: zsh2.1/part06
  12. Environment: BSD
  13. Supersedes: zsh2.00: Volume 18, Issue 84-98
  14.  
  15. #!/bin/sh
  16. # this is zshar.06 (part 6 of zsh2.1.0)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file zsh2.1/src/exec.c continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 6; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping zsh2.1/src/exec.c'
  34. else
  35. echo 'x - continuing file zsh2.1/src/exec.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.1/src/exec.c' &&
  37. X    blockchld();
  38. X    if ((thisjob = getfreejob()) == -1)
  39. X        return 1;
  40. X    initjob();
  41. X    if (how == TIMED)
  42. X        {
  43. X        jobtab[thisjob].stat |= STAT_TIMED;
  44. X        how = SYNC;
  45. X        }
  46. X    if (l->flags & PFLAG_COPROC)
  47. X        {
  48. X        how = ASYNC;
  49. X        mpipe(ipipe);
  50. X        mpipe(opipe);
  51. X        if (coprocin)
  52. X            {
  53. X            close(coprocin);
  54. X            close(coprocout);
  55. X            }
  56. X        coprocin = ipipe[0];
  57. X        coprocout = opipe[1];
  58. X        }
  59. X    execpline2(l->left,how,opipe[0],ipipe[1],last1);
  60. X    if (how == ASYNC)
  61. X        {
  62. X        spawnjob();
  63. X        unblockchld();
  64. X        return 1;
  65. X        }
  66. X    else
  67. X        {
  68. X        waitjobs();
  69. X        unblockchld();
  70. X        if (l->flags & PFLAG_NOT)
  71. X            lastval = !lastval;
  72. X        return !lastval;
  73. X        }
  74. X}
  75. X
  76. Xvoid execpline2(pline,how,input,output,last1) /**/
  77. XPline pline;int how;int input;int output;int last1;
  78. X{
  79. Xint pid;
  80. Xint pipes[2];
  81. X
  82. X    if (breaks)
  83. X        return;
  84. X    if (!pline)
  85. X        return;
  86. X    if (pline->type == END)
  87. X        {
  88. X        execcmd(pline->left,input,output,how==ASYNC,last1);
  89. X        pline->left = NULL;
  90. X        }
  91. X    else
  92. X        {
  93. X        mpipe(pipes);
  94. X
  95. X        /* if we are doing "foo | bar" where foo is a current
  96. X            shell command, do foo in the current shell and do
  97. X            the rest of the pipeline in a subshell. */
  98. X
  99. X        if (pline->left->type >= CURSH && how == SYNC)
  100. X            {
  101. X            if (!(pid = fork()))
  102. X                {
  103. X                close(pipes[1]);
  104. X                entersubsh(how==ASYNC);
  105. X                exiting = 1;
  106. X                execpline2(pline->right,ASYNC,pipes[0],output,1);
  107. X                _exit(lastval);
  108. X                }
  109. X            else if (pid == -1)
  110. X                zerr("fork failed: %e",NULL,errno);
  111. X            else
  112. X                {
  113. X                char *s,*text;
  114. X
  115. X                close(pipes[0]);
  116. X                text = s = gettext((vptr) pline->right,0);
  117. X                addproc(pid,text)->lastfg = 1;
  118. X                pline->right = NULL;
  119. X                }
  120. X            }
  121. X
  122. X        /* otherwise just do the pipeline normally. */
  123. X
  124. X        execcmd(pline->left,input,pipes[1],how==ASYNC,0);
  125. X        pline->left = NULL;
  126. X        close(pipes[1]);
  127. X        if (pline->right)
  128. X            {
  129. X            execpline2(pline->right,how,pipes[0],output,last1);
  130. X            close(pipes[0]);
  131. X            }
  132. X        }
  133. X}
  134. X
  135. X/* make the argv array */
  136. X
  137. Xchar **makecline(list) /**/
  138. Xstruct lklist *list;
  139. X{
  140. Xint ct = 0;
  141. XLknode node;
  142. Xchar **argv,**ptr;
  143. X
  144. X    if (isset(XTRACE))
  145. X        {
  146. X        fprintf(stderr,"%s",(prompt4) ? prompt4 : "");
  147. X        for (node = firstnode(list); node; incnode(node),ct++);
  148. X        ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
  149. X        for (node = firstnode(list); node; incnode(node))
  150. X            if (*(char *) getdata(node))
  151. X                {
  152. X                *ptr++ = getdata(node);
  153. X                untokenize(getdata(node));
  154. X                fputs(getdata(node),stderr);
  155. X                if (nextnode(node))
  156. X                    fputc(' ',stderr);
  157. X                }
  158. X        *ptr = NULL;
  159. X        fputc('\n',stderr);
  160. X        fflush(stderr);
  161. X        return(argv);
  162. X        }
  163. X    else
  164. X        {
  165. X        for (node = firstnode(list); node; incnode(node),ct++);
  166. X        ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
  167. X        for (node = firstnode(list); node; incnode(node))
  168. X            if (*(char *) getdata(node))
  169. X                {
  170. X                *ptr++ = getdata(node);
  171. X                untokenize(getdata(node));
  172. X                }
  173. X        *ptr = NULL;
  174. X        return(argv);
  175. X        }
  176. X}
  177. X
  178. X/* untokenize the command line and remove null arguments */
  179. X
  180. Xvoid fixcline(l) /**/
  181. XLklist l;
  182. X{
  183. XLknode node,next;
  184. X
  185. X    for (node = firstnode(l); node; node = next)
  186. X        {
  187. X        next = nextnode(node);
  188. X        if (!*(char *) getdata(node))
  189. X            uremnode(l,node);
  190. X        else
  191. X            untokenize(getdata(node));
  192. X        }
  193. X}
  194. X
  195. Xvoid untokenize(s) /**/
  196. Xchar *s;
  197. X{
  198. X    for (; *s; s++)
  199. X        if (itok(*s))
  200. X            if (*s == Nularg)
  201. X                chuck(s--);
  202. X            else
  203. X                *s = ztokens[*s-Pound];
  204. X}
  205. X
  206. X/* nonzero if we shouldn't clobber a file */
  207. X
  208. Xint dontclob(f) /**/
  209. Xstruct redir *f;
  210. X{
  211. Xstruct stat buf;
  212. X
  213. X    if (unset(NOCLOBBER) || f->type & 1)
  214. X        return 0;
  215. X    if (stat(f->name,&buf) == -1)
  216. X        return 1;
  217. X    return S_ISREG(buf.st_mode);
  218. X}
  219. X
  220. X/* close an multio (success) */
  221. X
  222. Xvoid closemn(mfds,fd) /**/
  223. Xstruct multio **mfds;int fd;
  224. X{
  225. X    if (mfds[fd])
  226. X        {
  227. X        if (mfds[fd]->ct > 1)
  228. X            if (mfds[fd]->rflag == 0)
  229. X                catproc(mfds[fd]);
  230. X            else
  231. X                teeproc(mfds[fd]);
  232. X        mfds[fd] = NULL;
  233. X        }
  234. X}
  235. X
  236. X/* close all the mnodes (failure) */
  237. X
  238. Xvoid closemnodes(mfds) /**/
  239. Xstruct multio **mfds;
  240. X{
  241. Xint t0,t1;
  242. X
  243. X    for (t0 = 0; t0 != 10; t0++)
  244. X        if (mfds[t0])
  245. X            {
  246. X            for (t1 = 0; t1 != mfds[t0]->ct; t1++)
  247. X                close(mfds[t0]->fds[t1]);
  248. X            mfds[t0] = NULL;
  249. X            }
  250. X}
  251. X
  252. X/* add a fd to an multio */
  253. X/* an multio is a list of fds associated with a certain fd.
  254. X    thus if you do "foo >bar >ble", the multio for fd 1 will have
  255. X    two fds, the result of open("bar",...), and the result of
  256. X    open("ble",....). */
  257. X
  258. Xvoid addfd(forked,save,mfds,fd1,fd2,rflag) /**/
  259. Xint forked;int *save;struct multio **mfds;int fd1;int fd2;int rflag;
  260. X{
  261. Xint pipes[2];
  262. X
  263. X    if (!mfds[fd1])    /* starting a new multio */
  264. X        {
  265. X        mfds[fd1] = (struct multio *) alloc(sizeof(struct multio));
  266. X        if (!forked && fd1 != fd2 && fd1 < 10)
  267. X            save[fd1] = movefd(fd1);
  268. X        redup(fd2,fd1);
  269. X        mfds[fd1]->ct = 1;
  270. X        mfds[fd1]->fds[0] = fd1;
  271. X        mfds[fd1]->rflag = rflag;
  272. X        }
  273. X    else
  274. X        {
  275. X        if (mfds[fd1]->rflag != rflag)
  276. X            {
  277. X            zerr("file mode mismatch on fd %d",NULL,fd1);
  278. X            return;
  279. X            }
  280. X        if (mfds[fd1]->ct == 1)        /* split the stream */
  281. X            {
  282. X            mfds[fd1]->fds[0] = movefd(fd1);
  283. X            mfds[fd1]->fds[1] = movefd(fd2);
  284. X            mpipe(pipes);
  285. X            mfds[fd1]->pipe = pipes[1-rflag];
  286. X            redup(pipes[rflag],fd1);
  287. X            mfds[fd1]->ct = 2;
  288. X            }
  289. X        else        /* add another fd to an already split stream */
  290. X            mfds[fd1]->fds[mfds[fd1]->ct++] = movefd(fd2);
  291. X        }
  292. X}
  293. X
  294. Xvoid addvars(l,export) /**/
  295. XLklist l;int export;
  296. X{
  297. Xstruct varasg *v;
  298. XLklist vl;
  299. X
  300. X    while (full(l))
  301. X        {
  302. X        char **arr,**ptr;
  303. X
  304. X        v = (struct varasg *) ugetnode(l);
  305. X        singsub(&v->name);
  306. X        if (errflag)
  307. X            return;
  308. X        untokenize(v->name);
  309. X        if (v->type == PMFLAG_s)
  310. X            {
  311. X            vl = newlist();
  312. X            addnode(vl,v->str);
  313. X            }
  314. X        else
  315. X            vl = v->arr;
  316. X        prefork(vl);
  317. X        if (errflag)
  318. X            return;
  319. X        postfork(vl,1);
  320. X        if (errflag)
  321. X            return;
  322. X        if (v->type == PMFLAG_s && (!full(vl) || !nextnode(firstnode(vl))))
  323. X            {
  324. X            Param pm;
  325. X            char *val;
  326. X
  327. X            if (!full(vl))
  328. X                pm = setsparam(v->name,val = ztrdup(""));
  329. X            else
  330. X                {
  331. X                untokenize(peekfirst(vl));
  332. X                pm = setsparam(v->name,val = ztrdup(ugetnode(vl)));
  333. X                }
  334. X            if (export && !(pm->flags & PMFLAG_x))
  335. X                addenv(v->name,val);
  336. X            continue;
  337. X            }
  338. X        ptr = arr = (char **) zalloc(sizeof(char **)*(countnodes(vl)+1));
  339. X        while (full(vl))
  340. X            {
  341. X            *ptr = ztrdup(ugetnode(vl));
  342. X            untokenize(*ptr++);
  343. X            }
  344. X        *ptr = NULL;
  345. X        setaparam(v->name,arr);
  346. X        }
  347. X}
  348. X
  349. Xvoid execcmd(cmd,input,output,bkg,last1) /**/
  350. XCmd cmd;int input;int output;int bkg;int last1;
  351. X{
  352. Xint type;
  353. Xlong pid = 0;
  354. XLklist args = cmd->args;
  355. Xint save[10],t0;
  356. Xstruct redir *fn;
  357. Xstruct multio *mfds[10];
  358. Xint fil,forked = 0,iscursh = 0,nullexec = 0;
  359. XCmdnam chn = NULL;
  360. Xchar *text;
  361. X
  362. X    for (t0 = 0; t0 != 10; t0++)
  363. X        {
  364. X        save[t0] = 0;
  365. X        mfds[t0] = NULL;
  366. X        }
  367. X    if ((type = cmd->type) == SIMPLE && !full(args))
  368. X        if (full(cmd->redir))
  369. X            if (cmd->flags & CFLAG_EXEC)
  370. X                nullexec = 1;
  371. X            else if (!*nullcmd)
  372. X                {
  373. X                zerr("redirection with no command",NULL,0);
  374. X                errflag = lastval = 1;
  375. X                return;
  376. X                }
  377. X            else
  378. X                addnode(args,strdup(nullcmd));
  379. X        else
  380. X            {
  381. X            addvars(cmd->vars,0);
  382. X            return;
  383. X            }
  384. X    if (full(args) && *(char *) peekfirst(args) == '%')
  385. X        {
  386. X        insnode(args,(Lknode) args,strdup((bkg) ? "bg" : "fg"));
  387. X        bkg = 0;
  388. X        }
  389. X    if (isset(AUTORESUME) && !bkg && !full(cmd->redir) && full(args) &&
  390. X            !input && type == SIMPLE && !nextnode(firstnode(args)) &&
  391. X            findjobnam(peekfirst(args)) != -1)
  392. X        pushnode(args,strdup("fg"));
  393. X    if (unset(RMSTARSILENT) && interact && isset(SHINSTDIN) &&
  394. X                type == SIMPLE && full(args) && nextnode(firstnode(args)) &&
  395. X                !strcmp(peekfirst(args),"rm"))
  396. X            {
  397. X            char *s = getdata(nextnode(firstnode(args)));
  398. X
  399. X            if (s[0] == Star && !s[1])
  400. X                checkrmall();
  401. X            }
  402. X    if (jobbing)    /* get the text associated with this command */
  403. X        {
  404. X        char *s;
  405. X        s = text = gettext((vptr) cmd,0);
  406. X        }
  407. X    else
  408. X        text = NULL;
  409. X    prefork(args);    /* do prefork substitutions */
  410. X    if (errflag)
  411. X        {
  412. X        lastval = 1;
  413. X        return;
  414. X        }
  415. X    if (full(args) && ((char*)peekfirst(args))[0] == Inbrack &&
  416. X            ((char*)peekfirst(args))[1] == '\0')
  417. X        ((char*)peekfirst(args))[0] = '[';
  418. X    if (full(args) && !(cmd->flags & CFLAG_COMMAND))
  419. X        chn = (Cmdnam) gethnode(peekfirst(args),cmdnamtab);
  420. X    if (type == SIMPLE && !pathsuppress && !chn && isset(AUTOCD) &&
  421. X            full(args) && !full(cmd->redir) &&
  422. X            !nextnode(firstnode(args)) && cancd(peekfirst(args)))
  423. X        {
  424. X        pushnode(args,strdup("cd"));
  425. X        chn = (Cmdnam) gethnode("cd",cmdnamtab);
  426. X        }
  427. X
  428. X    /* this is nonzero if cmd is a current shell procedure */
  429. X
  430. X    iscursh = (type >= CURSH) || (type == SIMPLE && chn &&
  431. X        (chn->type == BUILTIN || chn->type == SHFUNC));
  432. X
  433. X    /* if this command is backgrounded or (this is an external
  434. X        command and we are not exec'ing it) or this is a builtin
  435. X        with output piped somewhere, then fork.  If this is the
  436. X        last stage in a subshell pipeline, don't fork, but make
  437. X        the rest of the function think we forked. */
  438. X
  439. X    if (bkg || !(iscursh || (cmd->flags & CFLAG_EXEC)) ||
  440. X            (chn && (chn->type == BUILTIN || chn->type == SHFUNC) && output))
  441. X        {
  442. X        int synch[2];
  443. X
  444. X        pipe(synch);
  445. X        pid = (last1 && execok()) ? 0 : phork();
  446. X        if (pid == -1)
  447. X            {
  448. X            close(synch[0]);
  449. X            close(synch[1]);
  450. X            return;
  451. X            }
  452. X        if (pid)
  453. X            {
  454. X            close(synch[1]);
  455. X            read(synch[0],"foo",1);
  456. X            close(synch[0]);
  457. X            if (pid == -1)
  458. X                zerr("%e",NULL,errno);
  459. X            else
  460. X                ( void ) addproc(pid,text);
  461. X            return;
  462. X            }
  463. X        close(synch[0]);
  464. X        entersubsh(bkg);
  465. X        close(synch[1]);
  466. X        forked = 1;
  467. X        }
  468. X    if (bkg && isset(BGNICE))    /* stupid */
  469. X        nice(5);
  470. X    if (input)        /* add pipeline input/output to mnodes */
  471. X        addfd(forked,save,mfds,0,input,0);
  472. X    if (output)
  473. X        addfd(forked,save,mfds,1,output,1);
  474. X    spawnpipes(cmd->redir);        /* do process substitutions */
  475. X    while (full(cmd->redir))
  476. X        if ((fn = (struct redir*) ugetnode(cmd->redir))->type == INPIPE)
  477. X            {
  478. X            if (fn->fd2 == -1)
  479. X                execerr();
  480. X            addfd(forked,save,mfds,fn->fd1,fn->fd2,0);
  481. X            }
  482. X        else if (fn->type == OUTPIPE)
  483. X            {
  484. X            if (fn->fd2 == -1)
  485. X                execerr();
  486. X            addfd(forked,save,mfds,fn->fd1,fn->fd2,1);
  487. X            }
  488. X        else
  489. X            {
  490. X            if (!(fn->type == HERESTR || fn->type == CLOSE || fn->type ==
  491. X                    MERGE || fn->type == MERGEOUT))
  492. X                if (xpandredir(fn,cmd->redir))
  493. X                    continue;
  494. X            if (fn->type == HERESTR)
  495. X                {
  496. X                fil = getherestr(fn);
  497. X                if (fil == -1)
  498. X                    {
  499. X                    if (errno != EINTR)
  500. X                        zerr("%e",NULL,errno);
  501. X                    execerr();
  502. X                    }
  503. X                addfd(forked,save,mfds,fn->fd1,fil,0);
  504. X                }
  505. X            else if (fn->type == READ)
  506. X                {
  507. X                fil = open(fn->name,O_RDONLY);
  508. X                if (fil == -1)
  509. X                    {
  510. X                    if (errno != EINTR)
  511. X                        zerr("%e: %s",fn->name,errno);
  512. X                    execerr();
  513. X                    }
  514. X                addfd(forked,save,mfds,fn->fd1,fil,0);
  515. X                }
  516. X            else if (fn->type == CLOSE)
  517. X                {
  518. X                if (!forked && fn->fd1 < 10)
  519. X                    save[fn->fd1] = movefd(fn->fd1);
  520. X                closemn(mfds,fn->fd1);
  521. X                close(fn->fd1);
  522. X                }
  523. X            else if (fn->type == MERGE || fn->type == MERGEOUT)
  524. X                {
  525. X                fil = dup(fn->fd2);
  526. X                if (mfds[fn->fd1])
  527. X                    redup(fil,fn->fd1);
  528. X                else
  529. X                    addfd(forked,save,mfds,fn->fd1,fil,fn->type == MERGEOUT);
  530. X                }
  531. X            else
  532. X                {
  533. X                if (fn->type >= APP)
  534. X                    fil = open(fn->name,isset(NOCLOBBER) ?
  535. X                        O_WRONLY|O_APPEND : O_WRONLY|O_APPEND|O_CREAT,0666);
  536. X                else
  537. X                    fil = open(fn->name,dontclob(fn) ? 
  538. X                        O_WRONLY|O_CREAT|O_EXCL : O_WRONLY|O_CREAT|O_TRUNC,0666);
  539. X                if (fil == -1)
  540. X                    {
  541. X                    if (errno != EINTR)
  542. X                        zerr("%e: %s",fn->name,errno);
  543. X                    execerr();
  544. X                    }
  545. X                addfd(forked,save,mfds,fn->fd1,fil,1);
  546. X                }
  547. X            }
  548. X    /* perform postfork substitutions */
  549. X    /* you put this here so that ls *.sdfoij >& /dev/null works, remember? */
  550. X    postfork(args,!(cmd->flags & CFLAG_NOGLOB));
  551. X    if (errflag)
  552. X        {
  553. X        lastval = 1;
  554. X        goto err;
  555. X        }
  556. X    
  557. X    /* we are done with redirection.  close the mnodes, spawning
  558. X        tee/cat processes as necessary. */
  559. X    for (t0 = 0; t0 != 10; t0++)
  560. X        closemn(mfds,t0);
  561. X
  562. X    if (nullexec)
  563. X        return;
  564. X    if (unset(NOEXEC))
  565. X        if (type >= ZCTIME)
  566. X            {
  567. X            static int (*func[]) DCLPROTO((Cmd)) = {
  568. X                exectime,execcursh,execfuncdef,execfor,execwhile,
  569. X                execrepeat,execif,execcase,execselect,execcond };
  570. X    
  571. X            fixcline(args);
  572. X            lastval = (func[type-ZCTIME])(cmd);
  573. X            }
  574. X        else if (iscursh)        /* builtin or shell function */
  575. X            {
  576. X            if (cmd->vars)
  577. X                addvars(cmd->vars,0);
  578. X            fixcline(args);
  579. X            if (chn && chn->type == SHFUNC)
  580. X                execshfunc(cmd,chn);
  581. X            else
  582. X                {
  583. X                lastval = execbin(args,chn);
  584. X                if (isset(PRINTEXITVALUE) && lastval)
  585. X                    zerr("exit %d",NULL,lastval);
  586. X                fflush(stdout);
  587. X                if (ferror(stdout))
  588. X                    {
  589. X                    zerr("write error: %e",NULL,errno);
  590. X                    clearerr(stdout);
  591. X                    }
  592. X                }
  593. X            }
  594. X        else
  595. X            {
  596. X            if (cmd->vars)
  597. X                addvars(cmd->vars,1);
  598. X            if (type == SIMPLE)
  599. X                {
  600. X                closem();
  601. X                execute(args,cmd->flags & CFLAG_DASH);
  602. X                }
  603. X            else    /* ( ... ) */
  604. X                execlist(cmd->u.list);
  605. X            }
  606. Xerr:
  607. X    if (forked)
  608. X        _exit(lastval);
  609. X    fixfds(save);
  610. X}
  611. X
  612. X/* restore fds after redirecting a builtin */
  613. X
  614. Xvoid fixfds(save) /**/
  615. Xint *save;
  616. X{
  617. Xint t0;
  618. X
  619. X    for (t0 = 0; t0 != 10; t0++)
  620. X        if (save[t0])
  621. X            redup(save[t0],t0);
  622. X}
  623. X
  624. Xvoid entersubsh(bkg) /**/
  625. Xint bkg;
  626. X{
  627. X    if (!jobbing)
  628. X        {
  629. X        if (bkg && isatty(0))
  630. X            {
  631. X            close(0);
  632. X            if (open("/dev/null",O_RDWR))
  633. X                {
  634. X                zerr("can't open /dev/null: %e",NULL,errno);
  635. X                _exit(1);
  636. X                }
  637. X            }
  638. X        }
  639. X    else if (!jobtab[thisjob].gleader)
  640. X        {
  641. X        jobtab[thisjob].gleader = getpid();
  642. X        setpgrp(0L,jobtab[thisjob].gleader);
  643. X        if (!bkg)
  644. X            attachtty(jobtab[thisjob].gleader);
  645. X        }
  646. X    else
  647. X        setpgrp(0L,jobtab[thisjob].gleader);
  648. X    subsh = 1;
  649. X    if (SHTTY != -1)
  650. X        {
  651. X        close(SHTTY);
  652. X        SHTTY = -1;
  653. X        }
  654. X    if (jobbing)
  655. X        {
  656. X        signal(SIGTTOU,SIG_DFL);
  657. X        signal(SIGTTIN,SIG_DFL);
  658. X        signal(SIGTSTP,SIG_DFL);
  659. X        signal(SIGPIPE,SIG_DFL);
  660. X        }
  661. X    if (interact)
  662. X        {
  663. X        signal(SIGTERM,SIG_DFL);
  664. X        if (sigtrapped[SIGINT])
  665. X            signal(SIGINT,SIG_IGN);
  666. X        }
  667. X    if (!sigtrapped[SIGQUIT])
  668. X        signal(SIGQUIT,SIG_DFL);
  669. X    opts[MONITOR] = OPT_UNSET;
  670. X    clearjobtab();
  671. X}
  672. X
  673. X/* close all internal shell fds */
  674. X
  675. Xvoid closem() /**/
  676. X{
  677. Xint t0;
  678. X
  679. X    for (t0 = 10; t0 != NOFILE; t0++)
  680. X        close(t0);
  681. X}
  682. X
  683. X/* convert here document into a here string */
  684. X
  685. Xchar *gethere(str,typ) /**/
  686. Xchar *str;int typ;
  687. X{
  688. Xchar pbuf[256];
  689. Xint qt = 0,siz = 0,l,strip = 0;
  690. Xchar *s,*t,*bptr;
  691. X
  692. X    for (s = str; *s; s++)
  693. X        if (*s == Nularg)
  694. X            qt = 1;
  695. X    untokenize(str);
  696. X    if (typ == HEREDOCDASH)
  697. X        {
  698. X        strip = 1;
  699. X        while (*str == '\t')
  700. X            str++;
  701. X        }
  702. X    t = ztrdup("");
  703. X    for(;;)
  704. X        {
  705. X        char *u,*v;
  706. X
  707. X        if (!fgets(pbuf,256,bshin))
  708. X            break;
  709. X        bptr = pbuf;
  710. X        if (strip)
  711. X            while (*bptr == '\t')
  712. X                bptr++;
  713. X        for (u = bptr, v = str; *u != '\n' && *v; u++,v++)
  714. X            if (*u != *v)
  715. X                break;
  716. X        if (!(*u == '\n' && !*v))
  717. X            {
  718. X            l = strlen(bptr);
  719. X            if (!qt && l > 1 && bptr[l-1] == '\n' && bptr[l-2] == '\\')
  720. X                bptr[l -= 2] = '\0';
  721. X            t = realloc(t,siz+l+1);
  722. X            strncpy(t+siz,bptr,l);
  723. X            siz += l;
  724. X            }
  725. X        else
  726. X            break;
  727. X        }
  728. X    t[siz] = '\0';
  729. X    if (siz && t[siz-1] == '\n')
  730. X        t[siz-1] = '\0';
  731. X    if (!qt)
  732. X        for (s = t; *s; s++)
  733. X            if (*s == '$')
  734. X                *s = Qstring;
  735. X            else if (*s == '`')
  736. X                *s = Qtick;
  737. X            else if (*s == '\\')
  738. X                {
  739. X                s++;
  740. X                if (!*s)
  741. X                    break;
  742. X                }
  743. X    s = strdup(t);
  744. X    free(t);
  745. X    return s;
  746. X}
  747. X
  748. X/* open here string fd */
  749. X
  750. Xint getherestr(fn) /**/
  751. Xstruct redir *fn;
  752. X{
  753. XLklist fake;
  754. Xchar *s = gettemp(),*t;
  755. Xint fd;
  756. X
  757. X    fake = newlist();
  758. X    addnode(fake,fn->name);
  759. X    prefork(fake);
  760. X    if (!errflag)
  761. X        postfork(fake,1);
  762. X    if (errflag)
  763. X        return -1;
  764. X    if ((fd = open(s,O_CREAT|O_WRONLY,0600)) == -1)
  765. X        return -1;
  766. X    while (t = ugetnode(fake))
  767. X        {
  768. X        untokenize(t);
  769. X        write(fd,t,strlen(t));
  770. X        if (full(fake))
  771. X            write(fd," ",1);
  772. X        }
  773. X    write(fd,"\n",1);
  774. X    close(fd);
  775. X    fd = open(s,O_RDONLY);
  776. X    unlink(s);
  777. X    return fd;
  778. X}
  779. X
  780. Xvoid catproc(mn) /**/
  781. Xstruct multio *mn;
  782. X{
  783. Xint len,t0;
  784. Xchar *buf;
  785. X
  786. X    if (phork())
  787. X        {
  788. X        for (t0 = 0; t0 != mn->ct; t0++)
  789. X            close(mn->fds[t0]);
  790. X        close(mn->pipe);
  791. X        return;
  792. X        }
  793. X    closeallelse(mn);
  794. X    buf = zalloc(4096);
  795. X    for (t0 = 0; t0 != mn->ct; t0++)
  796. X        while (len = read(mn->fds[t0],buf,4096))
  797. X            write(mn->pipe,buf,len);
  798. X    _exit(0);
  799. X}
  800. Xvoid teeproc(mn) /**/
  801. Xstruct multio *mn;
  802. X{
  803. Xint len,t0;
  804. Xchar *buf;
  805. X
  806. X    if (phork())
  807. X        {
  808. X        for (t0 = 0; t0 != mn->ct; t0++)
  809. X            close(mn->fds[t0]);
  810. X        close(mn->pipe);
  811. X        return;
  812. X        }
  813. X    buf = zalloc(4096);
  814. X    closeallelse(mn);
  815. X    while ((len = read(mn->pipe,buf,4096)) > 0)
  816. X        for (t0 = 0; t0 != mn->ct; t0++)
  817. X            write(mn->fds[t0],buf,len);
  818. X    _exit(0);
  819. X}
  820. X
  821. Xvoid closeallelse(mn) /**/
  822. Xstruct multio *mn;
  823. X{
  824. Xint t0,t1;
  825. X
  826. X    for (t0 = 0; t0 != NOFILE; t0++)
  827. X        if (mn->pipe != t0)
  828. X            {
  829. X            for (t1 = 0; t1 != mn->ct; t1++)
  830. X                if (mn->fds[t1] == t0)
  831. X                    break;
  832. X            if (t1 == mn->ct)
  833. X                close(t0);
  834. X            }
  835. X}
  836. X
  837. Xlong int zstrtol(s,t,base) /**/
  838. Xchar *s;char **t;int base;
  839. X{
  840. Xint ret = 0;
  841. X
  842. X    if (base <= 10)
  843. X        for (; *s >= '0' && *s < ('0'+base); s++)
  844. X            ret = ret*base+*s-'0';
  845. X    else
  846. X        for (; idigit(*s) || (*s >= 'a' && *s < ('a'+base-10))
  847. X                                || (*s >= 'A' && *s < ('A'+base-10)); s++)
  848. X            ret = ret*base+(idigit(*s) ? (*s-'0') : (*s & 0x1f)+9);
  849. X    if (t)
  850. X        *t = (char *) s;
  851. X    return ret;
  852. X}
  853. X
  854. X/* $(...) */
  855. X
  856. XLklist getoutput(cmd,qt) /**/
  857. Xchar *cmd;int qt;
  858. X{
  859. XList list;
  860. Xint pipes[2];
  861. X
  862. X    if (*cmd == '<')
  863. X        {
  864. X        int stream;
  865. X        char *fi,*s,x;
  866. X
  867. X        for (cmd++; *cmd == ' '; cmd++);
  868. X        for (s = cmd; *s && *s != ' '; s++)
  869. X            if (*s == '\\') s++;
  870. X            else if (*s == '$') *s = String;
  871. X        x = *s;
  872. X        *s = '\0';
  873. X        fi = strdup(cmd);
  874. X        *s = x;
  875. X        if (*fi == '~')
  876. X            *fi = Tilde;
  877. X        else if (*fi == '=')
  878. X            *fi = Equals;
  879. X        singsub(&fi);
  880. X        if (errflag)
  881. X            return NULL;
  882. X        stream = open(fi,O_RDONLY);
  883. X        if (stream == -1)
  884. X            {
  885. X            zerr("%e: %s",cmd+1,errno);
  886. X            return NULL;
  887. X            }
  888. X        return readoutput(stream,qt);
  889. X        }
  890. X    if (!(list = parselstring(cmd)))
  891. X        return NULL;
  892. X    mpipe(pipes);
  893. X    if (phork())
  894. X        {
  895. X        popheap();
  896. X        close(pipes[1]);
  897. X        /* chldsuspend(); */
  898. X        return readoutput(pipes[0],qt);
  899. X        }
  900. X    subsh = 1;
  901. X    close(pipes[0]);
  902. X    redup(pipes[1],1);
  903. X    entersubsh(0);
  904. X    signal(SIGTSTP,SIG_IGN);
  905. X    exiting = 1;
  906. X    execlist(list);
  907. X    close(1);
  908. X    exit(0);  return NULL;
  909. X}
  910. X
  911. X/* read output of command substitution */
  912. X
  913. XLklist readoutput(in,qt) /**/
  914. Xint in;int qt;
  915. X{
  916. XLklist ret;
  917. Xchar *buf,*ptr;
  918. Xint bsiz,c,cnt = 0;
  919. XFILE *fin;
  920. X
  921. X    fin = fdopen(in,"r");
  922. X    ret = newlist();
  923. X    ptr = buf = zalloc(bsiz = 256);
  924. X    while ((c = fgetc(fin)) != EOF)
  925. X        if (!qt && isep(c))
  926. X            {
  927. X            if (cnt)
  928. X                {
  929. X                *ptr = '\0';
  930. X                addnode(ret,ztrdup(buf));
  931. X                cnt = 0;
  932. X                ptr = buf;
  933. X                }
  934. X            }
  935. X        else
  936. X            {
  937. X            *ptr++ = c;
  938. X            if (++cnt == bsiz)
  939. X                {
  940. X                char *pp = zalloc(bsiz *= 2);
  941. X                
  942. X                memcpy(pp,buf,cnt);
  943. X                free(buf);
  944. X                ptr = (buf = pp)+cnt;
  945. X                }
  946. X            }
  947. X    if (ptr != buf && ptr[-1] == '\n')
  948. X        ptr[-1] = '\0';
  949. X    else
  950. X        *ptr = '\0';
  951. X    if (cnt)
  952. X        addnode(ret,ztrdup(buf));
  953. X    free(buf);
  954. X    fclose(fin);
  955. X    return ret;
  956. X}
  957. X
  958. X/* =(...) */
  959. X
  960. Xchar *getoutputfile(cmd) /**/
  961. Xchar *cmd;
  962. X{
  963. X#ifdef WAITPID
  964. Xint pid;
  965. X#endif
  966. Xchar *nam = gettemp(),*str;
  967. Xint tfil;
  968. XList list;
  969. X
  970. X    if (thisjob == -1)
  971. X        return NULL;
  972. X    for (str = cmd; *str && *str != Outpar; str++);
  973. X    if (!*str)
  974. X        zerr("oops.",NULL,0);
  975. X    *str = '\0';
  976. X    if (!(list = parselstring(cmd)))
  977. X        return NULL;
  978. X    permalloc();
  979. X    if (!jobtab[thisjob].filelist)
  980. X        jobtab[thisjob].filelist = newlist();
  981. X    addnode(jobtab[thisjob].filelist,ztrdup(nam));
  982. X    heapalloc();
  983. X#ifdef WAITPID
  984. X    if (pid = phork())
  985. X        {
  986. X        popheap();
  987. X        waitpid(pid,NULL,WUNTRACED);
  988. X        return nam;
  989. X        }
  990. X#else
  991. X    if (waitfork())
  992. X        return nam;
  993. X#endif
  994. X    subsh = 1;
  995. X    close(1);
  996. X    entersubsh(0);
  997. X    tfil = creat(nam,0666);
  998. X    exiting = 1;
  999. X    execlist(list);
  1000. X    close(1);
  1001. X    exit(0); return NULL;
  1002. X}
  1003. X
  1004. X/* get a temporary named pipe */
  1005. X
  1006. Xchar *namedpipe() /**/
  1007. X{
  1008. Xchar *tnam = gettemp();
  1009. X
  1010. X    mknod(tnam,0010666,0);
  1011. X    return tnam;
  1012. X}
  1013. X
  1014. X/* <(...) */
  1015. X
  1016. Xchar *getoutproc(cmd) /**/
  1017. Xchar *cmd;
  1018. X{
  1019. XList list;
  1020. Xint fd;
  1021. Xchar *pnam,*str;
  1022. X
  1023. X    if (thisjob == -1)
  1024. X        return NULL;
  1025. X    for (str = cmd; *str && *str != Outpar; str++);
  1026. X    if (!*str)
  1027. X        zerr("oops.",NULL,0);
  1028. X    *str = '\0';
  1029. X    pnam = namedpipe();
  1030. X    permalloc();
  1031. X    if (!jobtab[thisjob].filelist)
  1032. X        jobtab[thisjob].filelist = newlist();
  1033. X    addnode(jobtab[thisjob].filelist,ztrdup(pnam));
  1034. X    heapalloc();
  1035. X    if (!(list = parselstring(cmd)))
  1036. X        return NULL;
  1037. X    if (phork())
  1038. X        {
  1039. X        popheap();
  1040. X        return pnam;
  1041. X        }
  1042. X    entersubsh(1);
  1043. X    fd = open(pnam,O_WRONLY);
  1044. X    if (fd == -1)
  1045. X        {
  1046. X        zerr("can't open %s: %e",pnam,errno);
  1047. X        _exit(0);
  1048. X        }
  1049. X    redup(fd,1);
  1050. X    fd = open("/dev/null",O_RDONLY);
  1051. X    redup(fd,0);
  1052. X    exiting = 1;
  1053. X    execlist(list);
  1054. X    close(1);
  1055. X    _exit(0);  return NULL;
  1056. X}
  1057. X
  1058. X/* >(...) */
  1059. X
  1060. Xchar *getinproc(cmd) /**/
  1061. Xchar *cmd;
  1062. X{
  1063. XList list;
  1064. Xint pid,fd;
  1065. Xchar *pnam,*str;
  1066. X
  1067. X    if (thisjob == -1)
  1068. X        return NULL;
  1069. X    for (str = cmd; *str && *str != Outpar; str++);
  1070. X    if (!*str)
  1071. X        zerr("oops.",NULL,0);
  1072. X    *str = '\0';
  1073. X    pnam = namedpipe();
  1074. X    permalloc();
  1075. X    if (!jobtab[thisjob].filelist)
  1076. X        jobtab[thisjob].filelist = newlist();
  1077. X    addnode(jobtab[thisjob].filelist,ztrdup(pnam));
  1078. X    heapalloc();
  1079. X    if (!(list = parselstring(cmd)))
  1080. X        return NULL;
  1081. X    if (pid = phork())
  1082. X        {
  1083. X        popheap();
  1084. X        return pnam;
  1085. X        }
  1086. X    entersubsh(1);
  1087. X    fd = open(pnam,O_RDONLY);
  1088. X    redup(fd,0);
  1089. X    exiting = 1;
  1090. X    execlist(list);
  1091. X    _exit(0);  return NULL;
  1092. X}
  1093. X
  1094. X/* > >(...) (does not use named pipes) */
  1095. X
  1096. Xint getinpipe(cmd) /**/
  1097. Xchar *cmd;
  1098. X{
  1099. XList list;
  1100. Xint pipes[2];
  1101. Xchar *str = cmd;
  1102. X
  1103. X    for (str = cmd; *str && *str != Outpar; str++);
  1104. X    if (!*str)
  1105. X        zerr("oops.",NULL,0);
  1106. X    *str = '\0';
  1107. X    if (!(list = parselstring(cmd+2)))
  1108. X        return -1;
  1109. X    mpipe(pipes);
  1110. X    if (phork())
  1111. X        {
  1112. X        popheap();
  1113. X        close(pipes[1]);
  1114. X        return pipes[0];
  1115. X        }
  1116. X    close(pipes[0]);
  1117. X    entersubsh(1);
  1118. X    redup(pipes[1],1);
  1119. X    exiting = 1;
  1120. X    execlist(list);
  1121. X    _exit(0);  return 0;
  1122. X}
  1123. X
  1124. X/* < <(...) */
  1125. X
  1126. Xint getoutpipe(cmd) /**/
  1127. Xchar *cmd;
  1128. X{
  1129. XList list;
  1130. Xint pipes[2];
  1131. Xchar *str;
  1132. X
  1133. X    for (str = cmd; *str && *str != Outpar; str++);
  1134. X    if (!*str)
  1135. X        zerr("oops.",NULL,0);
  1136. X    *str = '\0';
  1137. X    if (!(list = parselstring(cmd+2)))
  1138. X        return -1;
  1139. X    strinend();
  1140. X    mpipe(pipes);
  1141. X    if (phork())
  1142. X        {
  1143. X        popheap();
  1144. X        close(pipes[0]);
  1145. X        return pipes[1];
  1146. X        }
  1147. X    close(pipes[1]);
  1148. X    entersubsh(1);
  1149. X    redup(pipes[0],0);
  1150. X    exiting = 1;
  1151. X    execlist(list);
  1152. X    _exit(0);  return 0;
  1153. X}
  1154. X
  1155. X/* run a list, saving the current job num */
  1156. X
  1157. Xvoid runlist(l) /**/
  1158. XList l;
  1159. X{
  1160. Xint cj = thisjob;
  1161. X
  1162. X    execlist(l);
  1163. X    thisjob = cj;
  1164. X}
  1165. X
  1166. Xchar *gettemp() /**/
  1167. X{
  1168. X    return mktemp(dyncat(tmpprefix,"XXXXXX"));
  1169. X}
  1170. X
  1171. X/* my getwd; all the other ones I tried confused the SIGCHLD handler */
  1172. X
  1173. Xchar *zgetwd() /**/
  1174. X{
  1175. Xstatic char buf0[MAXPATHLEN];
  1176. Xchar buf3[MAXPATHLEN],*buf2 = buf0+1;
  1177. Xstruct stat sbuf;
  1178. Xstruct direct *de;
  1179. XDIR *dir;
  1180. Xino_t ino = -1;
  1181. Xdev_t dev = -1;
  1182. X
  1183. X    holdintr();
  1184. X    buf2[0] = '\0';
  1185. X    buf0[0] = '/';
  1186. X    for(;;)
  1187. X        {
  1188. X        if (stat(".",&sbuf) < 0)
  1189. X            {
  1190. X            chdir(buf0);
  1191. X            noholdintr();
  1192. X            return ztrdup(".");
  1193. X            }
  1194. X        ino = sbuf.st_ino;
  1195. X        dev = sbuf.st_dev;
  1196. X        if (stat("..",&sbuf) < 0)
  1197. X            {
  1198. X            chdir(buf0);
  1199. X            noholdintr();
  1200. X            return ztrdup(".");
  1201. X            }
  1202. X        if (sbuf.st_ino == ino && sbuf.st_dev == dev)
  1203. X            {
  1204. X            chdir(buf0);
  1205. X            noholdintr();
  1206. X            return ztrdup(buf0);
  1207. X            }
  1208. X        dir = opendir("..");
  1209. X        if (!dir)
  1210. X            {
  1211. X            chdir(buf0);
  1212. X            noholdintr();
  1213. X            return ztrdup(".");
  1214. X            }
  1215. X        chdir("..");
  1216. X        readdir(dir); readdir(dir);
  1217. X        while (de = readdir(dir))
  1218. X            if (de->d_ino == ino)
  1219. X                {
  1220. X                lstat(de->d_name,&sbuf);
  1221. X                if (sbuf.st_dev == dev)
  1222. X                    goto match;
  1223. X                }
  1224. X        rewinddir(dir);
  1225. X        readdir(dir); readdir(dir);
  1226. X        while (de = readdir(dir))
  1227. X            {
  1228. X            lstat(de->d_name,&sbuf);
  1229. X            if (sbuf.st_dev == dev)
  1230. X                goto match;
  1231. X            }
  1232. X        noholdintr();
  1233. X        closedir(dir);
  1234. X        return ztrdup(".");
  1235. Xmatch:
  1236. X        strcpy(buf3,de->d_name);
  1237. X        if (*buf2)
  1238. X            strcat(buf3,"/");
  1239. X        strcat(buf3,buf2);
  1240. X        strcpy(buf2,buf3);
  1241. X        closedir(dir);
  1242. X        }
  1243. X}
  1244. X
  1245. X/* open pipes with fds >= 10 */
  1246. X
  1247. Xvoid mpipe(pp) /**/
  1248. Xint *pp;
  1249. X{
  1250. X    pipe(pp);
  1251. X    pp[0] = movefd(pp[0]);
  1252. X    pp[1] = movefd(pp[1]);
  1253. X}
  1254. X
  1255. X/* do process substitution with redirection */
  1256. X
  1257. Xvoid spawnpipes(l) /**/
  1258. XLklist l;
  1259. X{
  1260. XLknode n = firstnode(l);
  1261. XRedir f;
  1262. X
  1263. X    for (; n; incnode(n))
  1264. X        {
  1265. X        f = (Redir) getdata(n);
  1266. X        if (f->type == OUTPIPE)
  1267. X            {
  1268. X            char *str = f->name;
  1269. X            f->fd2 = getoutpipe(str);
  1270. X            }
  1271. X        if (f->type == INPIPE)
  1272. X            {
  1273. X            char *str = f->name;
  1274. X            f->fd2 = getinpipe(str);
  1275. X            }
  1276. X        }
  1277. X}
  1278. X
  1279. X/* perform time ... command */
  1280. X
  1281. Xint exectime(cmd) /**/
  1282. XCmd cmd;
  1283. X{
  1284. Xint jb = thisjob;
  1285. X
  1286. X    execpline(cmd->u.pline,TIMED,0);
  1287. X    thisjob = jb;
  1288. X    return lastval;
  1289. X}
  1290. X
  1291. X/* define a function */
  1292. X
  1293. Xint execfuncdef(cmd) /**/
  1294. XCmd cmd;
  1295. X{
  1296. XCmdnam cc;
  1297. Xchar *s;
  1298. X
  1299. X    permalloc();
  1300. X    while (s = ugetnode(cmd->args))
  1301. X        {
  1302. X        cc = (Cmdnam) zalloc(sizeof *cc);
  1303. X        cc->type = SHFUNC;
  1304. X        cc->flags = 0;
  1305. X        if (!cmd->u.list)
  1306. X            cc->u.list = NULL;
  1307. X        else
  1308. X            cc->u.list = (List) dupstruct(cmd->u.list);
  1309. X        addhnode(ztrdup(s),cc,cmdnamtab,freecmdnam);
  1310. X        if (!strncmp(s,"TRAP",4))
  1311. X            {
  1312. X            int t0 = getsignum(s+4);
  1313. X
  1314. X            if (t0 != -1)
  1315. X                settrap(t0,cmd->u.list);
  1316. X            }
  1317. X        }
  1318. X    heapalloc();
  1319. X    return 0;
  1320. X}
  1321. X
  1322. X/* evaluate a [[ ... ]] */
  1323. X
  1324. Xint execcond(cmd) /**/
  1325. XCmd cmd;
  1326. X{
  1327. X    return !evalcond(cmd->u.cond);
  1328. X}
  1329. X
  1330. Xvoid execshfunc(cmd,cn) /**/
  1331. XCmd cmd;Cmdnam cn;
  1332. X{
  1333. Xchar **tab,**x,*oargv0;
  1334. Xint oxtr = opts[XTRACE],flags,xexittr;
  1335. XList l;
  1336. XLklist olist;
  1337. Xchar *s;
  1338. XList xexitfn;
  1339. X
  1340. X    if (errflag)
  1341. X        return;
  1342. X    l = cn->u.list;
  1343. X    if (!l)
  1344. X        {
  1345. X        char *nam;
  1346. X
  1347. X        if (!(l = getfpfunc(nam = peekfirst(cmd->args))))
  1348. X            {
  1349. X            zerr("function not found: %s",nam,0);
  1350. X            lastval = 1;
  1351. X            return;
  1352. X            }
  1353. X        cn->flags &= ~PMFLAG_u;
  1354. X        permalloc();
  1355. X        cn->u.list = (List) dupstruct(l);
  1356. X        heapalloc();
  1357. X        }
  1358. X    flags = cn->flags;
  1359. X    xexittr = sigtrapped[SIGEXIT];
  1360. X    xexitfn = sigfuncs[SIGEXIT];
  1361. X    tab = pparams;
  1362. X    oargv0 = argzero;
  1363. X    optind = 0;
  1364. X    if (flags & PMFLAG_t)
  1365. X        opts[XTRACE] = OPT_SET;
  1366. X    pparams = x = (char **) zcalloc(((sizeof *x)*(1+countnodes(cmd->args))));
  1367. X    argzero = ztrdup(ugetnode(cmd->args));
  1368. X    while (*x = ugetnode(cmd->args))
  1369. X        *x = ztrdup(*x), x++;
  1370. X    permalloc();
  1371. X    olist = locallist;
  1372. X    locallist = newlist();
  1373. X    heapalloc();
  1374. X    newrunlist(l);
  1375. X    while (s = getnode(locallist))
  1376. X        unsetparam(s);
  1377. X    free(locallist);
  1378. X    locallist = olist;
  1379. X    retflag = 0;
  1380. X    cmd->u.list = NULL;
  1381. X    freearray(pparams);
  1382. X    free(argzero);
  1383. X    argzero = oargv0;
  1384. X    pparams = tab;
  1385. X    if (sigfuncs[SIGEXIT] && sigfuncs[SIGEXIT] != xexitfn)
  1386. X        {
  1387. X        dotrap(SIGEXIT);
  1388. X        freestruct(sigfuncs[SIGEXIT]);
  1389. X        }
  1390. X    sigtrapped[SIGEXIT] = xexittr;
  1391. X    sigfuncs[SIGEXIT] = xexitfn;
  1392. X    opts[XTRACE] = oxtr;
  1393. X}
  1394. X
  1395. X/* search fpath for an undefined function */
  1396. X
  1397. XList getfpfunc(s) /**/
  1398. Xchar *s;
  1399. X{
  1400. Xchar **pp = fpath,buf[MAXPATHLEN];
  1401. Xint fd;
  1402. X
  1403. X    for (; *pp; pp++)
  1404. X        {
  1405. X        sprintf(buf,"%s/%s",*pp,s);
  1406. X        if (!access(buf,R_OK) && (fd = open(buf,O_RDONLY)) != -1)
  1407. X            {
  1408. X            int len = lseek(fd,0,2);
  1409. X
  1410. X            if (len == -1)
  1411. X                close(fd);
  1412. X            else
  1413. X                {
  1414. X                char *d;
  1415. X
  1416. X                lseek(fd,0,0);
  1417. X                d = zcalloc(len+1);
  1418. X                if (read(fd,d,len) != len)
  1419. X                    {
  1420. X                    free(d);
  1421. X                    close(fd);
  1422. X                    }
  1423. X                else
  1424. X                    {
  1425. X                    close(fd);
  1426. X                    return parselstring(d);
  1427. X                    }
  1428. X                }
  1429. X            }
  1430. X        }
  1431. X    return NULL;
  1432. X}
  1433. X
  1434. X/* check to see if AUTOCD applies here */
  1435. X
  1436. Xint cancd(s)
  1437. Xchar *s;
  1438. X{
  1439. X    if (*s != '/')
  1440. X        {
  1441. X        char sbuf[MAXPATHLEN],**cp;
  1442. X
  1443. X        if (cancd2(s))
  1444. X            return 1;
  1445. X        if (access(s,X_OK) == 0)
  1446. X            return 0;
  1447. X        for (cp = cdpath; *cp; cp++)
  1448. X            {
  1449. X            sprintf(sbuf,"%s/%s",*cp,s);
  1450. X            if (cancd2(sbuf))
  1451. X                return 1;
  1452. X            }
  1453. X        return 0;
  1454. X        }
  1455. X    return cancd2(s);
  1456. X}
  1457. X
  1458. Xint cancd2(s)
  1459. Xchar *s;
  1460. X{
  1461. Xstruct stat buf;
  1462. X
  1463. X    return !(access(s,X_OK) || stat(s,&buf) || !S_ISDIR(buf.st_mode));
  1464. X}
  1465. X
  1466. SHAR_EOF
  1467. echo 'File zsh2.1/src/exec.c is complete' &&
  1468. chmod 0644 zsh2.1/src/exec.c ||
  1469. echo 'restore of zsh2.1/src/exec.c failed'
  1470. Wc_c="`wc -c < 'zsh2.1/src/exec.c'`"
  1471. test 33003 -eq "$Wc_c" ||
  1472.     echo 'zsh2.1/src/exec.c: original size 33003, current size' "$Wc_c"
  1473. rm -f _shar_wnt_.tmp
  1474. fi
  1475. # ============= zsh2.1/src/funcs.h ==============
  1476. if test -f 'zsh2.1/src/funcs.h' -a X"$1" != X"-c"; then
  1477.     echo 'x - skipping zsh2.1/src/funcs.h (File already exists)'
  1478.     rm -f _shar_wnt_.tmp
  1479. else
  1480. > _shar_wnt_.tmp
  1481. echo 'x - extracting zsh2.1/src/funcs.h (Text)'
  1482. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/funcs.h' &&
  1483. Xstruct asgment;
  1484. Xstruct utmp;
  1485. X
  1486. X#include "builtin.pro"
  1487. X#include "cond.pro"
  1488. X#include "exec.pro"
  1489. X#include "glob.pro"
  1490. X#include "hist.pro"
  1491. X#include "init.pro"
  1492. X#include "jobs.pro"
  1493. X#include "lex.pro"
  1494. X#include "loop.pro"
  1495. X#include "math.pro"
  1496. X#include "mem.pro"
  1497. X#include "params.pro"
  1498. X#include "parse.pro"
  1499. X#include "subst.pro"
  1500. X#include "table.pro"
  1501. X#include "text.pro"
  1502. X#include "utils.pro"
  1503. X#include "watch.pro"
  1504. X#include "zle_hist.pro"
  1505. X#include "zle_main.pro"
  1506. X#include "zle_misc.pro"
  1507. X#include "zle_move.pro"
  1508. X#include "zle_refresh.pro"
  1509. X#include "zle_tricky.pro"
  1510. X#include "zle_utils.pro"
  1511. X#include "zle_vi.pro"
  1512. X#include "zle_word.pro"
  1513. X
  1514. Xchar *mktemp DCLPROTO((char *));
  1515. Xchar *malloc DCLPROTO((int));
  1516. X#ifndef __STDC__
  1517. Xchar *realloc DCLPROTO((char *,int));
  1518. Xchar *calloc DCLPROTO((int,int));
  1519. X#endif /* __STDC__ */
  1520. Xchar *ttyname DCLPROTO((int));
  1521. X
  1522. Xextern char PC, *BC, *UP;
  1523. Xextern short ospeed;
  1524. Xextern int tgetent DCLPROTO((char *bp, char *name));
  1525. Xextern int tgetnum DCLPROTO((char *id));
  1526. Xextern int tgetflag DCLPROTO((char *id));
  1527. Xextern char *tgetstr DCLPROTO((char *id, char **area));
  1528. Xextern char *tgoto DCLPROTO((char *cm, int destcol, int destline));
  1529. Xextern int tputs DCLPROTO((char *cp, int affcnt, int (*outc)()));
  1530. SHAR_EOF
  1531. chmod 0644 zsh2.1/src/funcs.h ||
  1532. echo 'restore of zsh2.1/src/funcs.h failed'
  1533. Wc_c="`wc -c < 'zsh2.1/src/funcs.h'`"
  1534. test 1198 -eq "$Wc_c" ||
  1535.     echo 'zsh2.1/src/funcs.h: original size 1198, current size' "$Wc_c"
  1536. rm -f _shar_wnt_.tmp
  1537. fi
  1538. # ============= zsh2.1/src/glob.c ==============
  1539. if test -f 'zsh2.1/src/glob.c' -a X"$1" != X"-c"; then
  1540.     echo 'x - skipping zsh2.1/src/glob.c (File already exists)'
  1541.     rm -f _shar_wnt_.tmp
  1542. else
  1543. > _shar_wnt_.tmp
  1544. echo 'x - extracting zsh2.1/src/glob.c (Text)'
  1545. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/glob.c' &&
  1546. X/*
  1547. X
  1548. X    glob.c - filename generation
  1549. X
  1550. X    This file is part of zsh, the Z shell.
  1551. X
  1552. X    zsh is free software; no one can prevent you from reading the source
  1553. X   code, or giving it to someone else.
  1554. X
  1555. X   This file is copyrighted under the GNU General Public License, which
  1556. X   can be found in the file called COPYING.
  1557. X
  1558. X   Copyright (C) 1990, 1991 Paul Falstad
  1559. X
  1560. X   zsh is distributed in the hope that it will be useful, but
  1561. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  1562. X   responsibility to anyone for the consequences of using it or for
  1563. X   whether it serves any particular purpose or works at all, unless he
  1564. X   says so in writing.  Refer to the GNU General Public License
  1565. X   for full details.
  1566. X
  1567. X   Everyone is granted permission to copy, modify and redistribute
  1568. X   zsh, but only under the conditions described in the GNU General Public
  1569. X   License.   A copy of this license is supposed to have been given to you
  1570. X   along with zsh so you can know your rights and responsibilities.
  1571. X   It should be in a file named COPYING.
  1572. X
  1573. X   Among other things, the copyright notice and this notice must be
  1574. X   preserved on all copies.
  1575. X
  1576. X*/
  1577. X
  1578. X#include "zsh.h"
  1579. X
  1580. X#ifdef __hpux
  1581. X#include <ndir.h>
  1582. X#else
  1583. X#ifdef SYSV
  1584. X#define direct dirent
  1585. X#else
  1586. X#include <sys/dir.h>
  1587. X#endif
  1588. X#endif
  1589. X#include <sys/errno.h>
  1590. X
  1591. X#define exists(X) (access(X,0) == 0)
  1592. X
  1593. Xstatic int mode;                /* != 0 if we are parsing glob patterns */
  1594. Xstatic int pathpos;            /* position in pathbuf */
  1595. Xstatic int matchsz;            /* size of matchbuf */
  1596. Xstatic int matchct;            /* number of matches found */
  1597. Xstatic char pathbuf[MAXPATHLEN];    /* pathname buffer */
  1598. Xstatic char **matchbuf;        /* array of matches */
  1599. Xstatic char **matchptr;        /* &matchbuf[matchct] */
  1600. X
  1601. X/* max # of qualifiers */
  1602. X
  1603. X#define QUALCT 16
  1604. X
  1605. Xstatic int (*qualfuncs[QUALCT])DCLPROTO((struct stat *,long));
  1606. Xstatic long qualdata[QUALCT];
  1607. Xstatic int qualsense[QUALCT];
  1608. Xstatic int qualct;
  1609. X
  1610. X/* pathname component in filename patterns */
  1611. X
  1612. Xstruct complist {
  1613. X    Complist next;
  1614. X    Comp comp;
  1615. X    int closure;    /* 1 if this is a (foo/)# */
  1616. X    };
  1617. Xstruct comp {
  1618. X    Comp left,right,next;
  1619. X    char *str;
  1620. X    int closure,last;
  1621. X    };
  1622. X
  1623. Xvoid glob(list,np) /**/
  1624. XLklist list;Lknode *np;
  1625. X{
  1626. XLknode node = prevnode(*np);
  1627. XLknode next = nextnode(*np);
  1628. Xint sl;            /* length of the pattern */
  1629. Xchar *ostr;        /* the pattern before the parser chops it up */
  1630. XComplist q;        /* pattern after parsing */
  1631. Xchar *str = getdata(*np);    /* the pattern */
  1632. X
  1633. X    sl = strlen(str);
  1634. X    ostr = strdup(str);
  1635. X    uremnode(list,*np);
  1636. X    qualct = 0;
  1637. X    if (str[sl-1] == Outpar)    /* check for qualifiers */
  1638. X        {
  1639. X        char *s;
  1640. X        int sense = 0;
  1641. X        long data;
  1642. X        int (*func) DCLPROTO((struct stat *,long));
  1643. X
  1644. X        for (s = str+sl-2; s != str; s--)
  1645. X            if (*s == Bar || *s == Outpar || *s == Inpar)
  1646. X                break;
  1647. X        if (*s == Inpar)
  1648. X            {
  1649. X            *s++ = '\0';
  1650. X            func = NULL;
  1651. X            while (*s != Outpar)
  1652. X                {
  1653. X                func = NULL;
  1654. X                if (idigit(*s))
  1655. X                    {
  1656. X                    func = qualflags;
  1657. X                    data = 0;
  1658. X                    while (idigit(*s))
  1659. X                        data = data*010+(*s++-'0');
  1660. X                    }
  1661. X                else switch (*s++)
  1662. X                    {
  1663. X                    case Hat: case '^': sense = 1-sense; break;
  1664. X#ifdef S_IFLNK
  1665. X                    case '@': func = qualmode; data = S_IFLNK; break;
  1666. X#endif
  1667. X#ifdef S_IFSOCK
  1668. X                    case '=': func = qualmode; data = S_IFSOCK; break;
  1669. X#endif
  1670. X#ifdef S_IFIFO
  1671. X                    case 'p': func = qualmode; data = S_IFIFO; break;
  1672. X#endif
  1673. X                    case '/': func = qualmode; data = S_IFDIR; break;
  1674. X                    case '.': func = qualmode; data = S_IFREG; break;
  1675. X                    case '%': func = qualisdev; break;
  1676. X                    case Star:  func = qualiscom; break;
  1677. X                    case 'R': func = qualflags; data = 0004; break;
  1678. X                    case 'W': func = qualflags; data = 0002; break;
  1679. X                    case 'X': func = qualflags; data = 0001; break;
  1680. X                    case 'r': func = qualflags; data = 0400; break;
  1681. X                    case 'w': func = qualflags; data = 0200; break;
  1682. X                    case 'x': func = qualflags; data = 0100; break;
  1683. X                    case 's': func = qualflags; data = 04000; break;
  1684. X                    case 'S': func = qualflags; data = 02000; break;
  1685. X                    case 'd': func = qualdev; data = qgetnum(&s); break;
  1686. X                    case 'l': func = qualnlink; data = qgetnum(&s); break;
  1687. X                    case 'U': func = qualuid; data = geteuid(); break;
  1688. X                    case 'G': func = qualgid; data = getegid(); break;
  1689. X                    case 'u': func = qualuid; data = qgetnum(&s); break;
  1690. X                    case 'g': func = qualgid; data = qgetnum(&s); break;
  1691. X                    default: zerr("unknown file attribute",NULL,0); return;
  1692. X                    }
  1693. X                if (func)
  1694. X                    {
  1695. X                    if (qualct == QUALCT-1)
  1696. X                        {
  1697. X                        zerr("too many qualifiers",NULL,0);
  1698. X                        return;
  1699. X                        }
  1700. X                    qualfuncs[qualct] = func;
  1701. X                    qualsense[qualct] = sense;
  1702. X                    qualdata[qualct] = data;
  1703. X                    qualct++;
  1704. X                    }
  1705. X                if (errflag)
  1706. X                    return;
  1707. X                }
  1708. X            }
  1709. X        }
  1710. X    else if (str[sl-1] == '/')        /* foo/ == foo(/) */
  1711. X        {
  1712. X        str[sl-1] = '\0';
  1713. X        qualfuncs[0] = qualmode;
  1714. X        qualdata[0] = S_IFDIR;
  1715. X        qualsense[0] = 0;
  1716. X        qualct = 1;
  1717. X        }
  1718. X    qualfuncs[qualct] = NULL;
  1719. X    if (*str == '/')    /* pattern has absolute path */
  1720. X        {
  1721. X        str++;
  1722. X        pathbuf[0] = '/';
  1723. X        pathbuf[pathpos = 1] = '\0';
  1724. X        }
  1725. X    else        /* pattern is relative to cwd */
  1726. X        pathbuf[pathpos = 0] = '\0';
  1727. X    q = parsepat(str);
  1728. X    if (!q || errflag)    /* if parsing failed */
  1729. X        {
  1730. X        if (isset(NOBADPATTERN))
  1731. X            {
  1732. X            insnode(list,node,ostr);
  1733. X            return;
  1734. X            }
  1735. X        errflag = 0;
  1736. X        zerr("bad pattern: %s",ostr,0);
  1737. X        return;
  1738. X        }
  1739. X    matchptr = matchbuf = (char **) zalloc((matchsz = 16)*sizeof(char *));
  1740. X    matchct = 0;
  1741. X    scanner(q);        /* do the globbing */
  1742. X    if (matchct)
  1743. X        badcshglob |= 2;
  1744. X    else if (unset(NULLGLOB))
  1745. X        if (isset(CSHNULLGLOB)) {
  1746. X            badcshglob |= 1;
  1747. X        } else if (unset(NONOMATCH)) {
  1748. X            zerr("no matches found: %s",ostr,0);
  1749. X            free(matchbuf);
  1750. X            return;
  1751. X        } else {
  1752. X            *matchptr++ = strdup(ostr);
  1753. X            matchct = 1;
  1754. X        }
  1755. X    qsort(&matchbuf[0],matchct,sizeof(char *),notstrcmp);
  1756. X    matchptr = matchbuf;
  1757. X    while (matchct--)            /* insert matches in the arg list */
  1758. X        insnode(list,node,*matchptr++);
  1759. X    free(matchbuf);
  1760. X    *np = (next) ? prevnode(next) : lastnode(list);
  1761. X}
  1762. X
  1763. X/* get number after qualifier */
  1764. X
  1765. Xlong qgetnum(s) /**/
  1766. Xchar **s;
  1767. X{
  1768. Xlong v = 0;
  1769. X
  1770. X    if (!idigit(**s))
  1771. X        {
  1772. X        zerr("number expected",NULL,0);
  1773. X        return 0;
  1774. X        }
  1775. X    while (idigit(**s))
  1776. X        v = v*10+*(*s)++-'0';
  1777. X    return v;
  1778. X}
  1779. X
  1780. Xint notstrcmp(a,b) /**/
  1781. Xchar **a;char **b;
  1782. X{
  1783. Xchar *c = *b,*d = *a;
  1784. Xint x1,x2;
  1785. X
  1786. X    for (; *c == *d && *c; c++,d++);
  1787. X    x1 = atoi(c); x2 = atoi(d);
  1788. X    if (x1==x2)
  1789. X        return ((int) (unsigned char) *c-(int) (unsigned char) *d);
  1790. X    return x1-x2;
  1791. X}
  1792. X
  1793. Xint forstrcmp(a,b) /**/
  1794. Xchar **a;char **b;
  1795. X{
  1796. Xchar *c = *b,*d = *a;
  1797. X
  1798. X    for (; *c == *d && *c; c++,d++);
  1799. X    return ((int) (unsigned char) *d-(int) (unsigned char) *c);
  1800. X}
  1801. X
  1802. X/* add a match to the list */
  1803. X
  1804. Xvoid insert(s) /**/
  1805. Xchar *s;
  1806. X{
  1807. Xstruct stat buf;
  1808. X
  1809. X    if (isset(MARKDIRS) && !lstat(s,&buf) && S_ISDIR(buf.st_mode)) /* grrr */
  1810. X        {
  1811. X        char *t;
  1812. X        int ll = strlen(s);
  1813. X
  1814. X        t = ncalloc(ll+2);
  1815. X        strcpy(t,s);
  1816. X        t[ll] = '/';
  1817. X        t[ll+1] = '\0';
  1818. X        s = t;
  1819. X        }
  1820. X    *matchptr++ = s;
  1821. X    if (++matchct == matchsz)
  1822. X        {
  1823. X        matchbuf = (char **) realloc((char *) matchbuf,
  1824. X            sizeof(char **)*(matchsz *= 2));
  1825. X        matchptr = matchbuf+matchct;
  1826. X        }
  1827. X}
  1828. X
  1829. X/* check to see if str is eligible for filename generation */
  1830. X
  1831. Xint haswilds(str) /**/
  1832. Xchar *str;
  1833. X{
  1834. X    if (!str[1] && (*str == Inbrack || *str == Outbrack))
  1835. X        return 0;
  1836. X    if (str[0] == '%')
  1837. X        return 0;
  1838. X    for (; *str; str++)
  1839. X        if (str[0] == Star && str[1] == Star &&
  1840. X             str[2] == Star && str[3] == Star && str[4] == '/')
  1841. X            return 1;
  1842. X        else if (*str == Pound || *str == Hat || *str == Star ||
  1843. X                *str == Bar || *str == Inbrack || *str == Inang ||
  1844. X                *str == Quest)
  1845. X            return 1;
  1846. X    return 0;
  1847. X}
  1848. X
  1849. X/* check to see if str is eligible for brace expansion */
  1850. X
  1851. Xint hasbraces(str) /**/
  1852. Xchar *str;
  1853. X{
  1854. Xint mb,bc,cmct1,cmct2;
  1855. Xchar *lbr = NULL;
  1856. X
  1857. X    if (str[0] == Inbrace && str[1] == Outbrace)
  1858. X        return 0;
  1859. X    for (mb = bc = cmct1 = cmct2 = 0; *str; str++)
  1860. X        {
  1861. X        if (*str == Inbrace)
  1862. X            {
  1863. X            if (!bc)
  1864. X                lbr = str;
  1865. X            bc++;
  1866. X            if (str[4] == Outbrace && str[2] == '-') /* {a-z} */
  1867. X                {
  1868. X                cmct1++;
  1869. X                if (bc == 1)
  1870. X                    cmct2++;
  1871. X                }
  1872. X            }
  1873. X        else if (*str == Outbrace)
  1874. X            {
  1875. X            bc--;
  1876. X            if (!bc)
  1877. X                {
  1878. X                if (!cmct2)
  1879. X                    {
  1880. X                    *lbr = '{';
  1881. X                    *str = '}';
  1882. X                    }
  1883. X                cmct2 = 0;
  1884. X                }
  1885. X            }
  1886. X        else if (*str == Comma && bc)
  1887. X            {
  1888. X            cmct1++;
  1889. X            if (bc == 1)
  1890. X                cmct2++;
  1891. X            }
  1892. X        if (bc > mb)
  1893. X            mb = bc;
  1894. X        if (bc < 0)
  1895. X            return 0;
  1896. X        }
  1897. X    return (mb && bc == 0 && cmct1);
  1898. X}
  1899. X
  1900. X/* expand stuff like >>*.c */
  1901. X
  1902. Xint xpandredir(fn,tab) /**/
  1903. Xstruct redir *fn;Lklist tab;
  1904. X{
  1905. XLklist fake;
  1906. Xchar *nam;
  1907. Xstruct redir *ff;
  1908. Xint ret = 0;
  1909. X
  1910. X    fake = newlist();
  1911. X    addnode(fake,fn->name);
  1912. X    prefork(fake);
  1913. X    if (!errflag)
  1914. X        postfork(fake,1);
  1915. X    if (errflag)
  1916. X        return 0;
  1917. X    if (full(fake) && !nextnode(firstnode(fake)))
  1918. X        {
  1919. X        fn->name = peekfirst(fake);
  1920. X        untokenize(fn->name);
  1921. X        }
  1922. X    else
  1923. X        while (nam = ugetnode(fake))
  1924. X            {
  1925. X            ff = alloc(sizeof *ff);
  1926. X            *ff = *fn;
  1927. X            ff->name = nam;
  1928. X            addnode(tab,ff);
  1929. X            ret = 1;
  1930. X            }
  1931. X    return ret;
  1932. X}
  1933. X
  1934. X/* concatenate s1 and s2 in dynamically allocated buffer */
  1935. X
  1936. Xchar *dyncat(s1,s2) /**/
  1937. Xchar *s1;char *s2;
  1938. X{
  1939. Xchar *ptr;
  1940. X    ptr = ncalloc(strlen(s1)+strlen(s2)+1);
  1941. X    strcpy(ptr,s1);
  1942. X    strcat(ptr,s2);
  1943. X    return ptr;
  1944. X}
  1945. X
  1946. X/* concatenate s1, s2, and s3 in dynamically allocated buffer */
  1947. X
  1948. Xchar *tricat(s1,s2,s3) /**/
  1949. Xchar *s1;char *s2;char *s3;
  1950. X{
  1951. Xchar *ptr;
  1952. X
  1953. X    ptr = zalloc(strlen(s1)+strlen(s2)+strlen(s3)+1);
  1954. X    strcpy(ptr,s1);
  1955. X    strcat(ptr,s2);
  1956. X    strcat(ptr,s3);
  1957. X    return ptr;
  1958. X}
  1959. X
  1960. X/* brace expansion */
  1961. X
  1962. Xvoid xpandbraces(list,np) /**/
  1963. XLklist list;Lknode *np;
  1964. X{
  1965. XLknode node = (*np),last = prevnode(node);
  1966. Xchar *str = getdata(node),*str3 = str,*str2;
  1967. Xint prev;
  1968. X
  1969. X    for (; *str != Inbrace; str++);
  1970. X     if (str[2] == '-' && str[4] == Outbrace)     /* {a-z} */
  1971. X        {
  1972. X        char c1,c2;
  1973. X
  1974. X        uremnode(list,node);
  1975. X        chuck(str);
  1976. X        c1 = *str;
  1977. X        chuck(str);
  1978. X        chuck(str);
  1979. X        c2 = *str;
  1980. X        chuck(str);
  1981. X        if (itok(c1))
  1982. X            c1 = ztokens[c1-Pound];
  1983. X        if (itok(c2))
  1984. X            c2 = ztokens[c2-Pound];
  1985. X        if (c1 < c2)
  1986. X            for (; c2 >= c1; c2--)    /* {a-z} */
  1987. X                {
  1988. X                *str = c2;
  1989. X                insnode(list,last,strdup(str3));
  1990. X                }
  1991. X        else
  1992. X            for (; c2 <= c1; c2++)    /* {z-a} */
  1993. X                {
  1994. X                *str = c2;
  1995. X                insnode(list,last,strdup(str3));
  1996. X                }
  1997. X        *np = nextnode(last);
  1998. X        return;
  1999. X        }
  2000. X    prev = str-str3;
  2001. X    str2 = getparen(str++);
  2002. X    if (!str2)
  2003. X        {
  2004. X        zerr("how did you get this error?",NULL,0);
  2005. X        return;
  2006. X        }
  2007. X    uremnode(list,node);
  2008. X    node = last;
  2009. X    for(;;)
  2010. X        {
  2011. X        char *zz,*str4;
  2012. X        int cnt;
  2013. X        
  2014. X        for (str4 = str, cnt = 0; cnt || *str != Comma && *str !=
  2015. X                Outbrace; str++)
  2016. X            if (*str == Inbrace)
  2017. X                cnt++;
  2018. X            else if (*str == Outbrace)
  2019. X                cnt--;
  2020. X            else if (!*str)
  2021. X                exit(10);
  2022. X        zz = zalloc(prev+(str-str4)+strlen(str2)+1);
  2023. X        ztrncpy(zz,str3,prev);
  2024. X        strncat(zz,str4,str-str4);
  2025. X        strcat(zz,str2);
  2026. X        insnode(list,node,zz);
  2027. X        incnode(node);
  2028. X        if (*str != Outbrace)
  2029. X            str++;
  2030. X        else
  2031. X            break;
  2032. X        }
  2033. X    *np = nextnode(last);
  2034. X}
  2035. X
  2036. X/* get closing paren, given pointer to opening paren */
  2037. X
  2038. Xchar *getparen(str) /**/
  2039. Xchar *str;
  2040. X{
  2041. Xint cnt = 1;
  2042. Xchar typein = *str++,typeout = typein+1;
  2043. X
  2044. X    for (; *str && cnt; str++)
  2045. X        if (*str == typein)
  2046. X            cnt++;
  2047. X        else if (*str == typeout)
  2048. X            cnt--;
  2049. X    if (!str && cnt)
  2050. X        return NULL;
  2051. X    return str;
  2052. X}
  2053. X
  2054. X/* check to see if a matches b (b is not a filename pattern) */
  2055. X
  2056. Xint matchpat(a,b) /**/
  2057. Xchar *a;char *b;
  2058. X{
  2059. XComp c;
  2060. Xint val,len;
  2061. Xchar *b2;
  2062. X
  2063. X    remnulargs(b);
  2064. X    len = strlen(b);
  2065. X    b2 = alloc(len+3);
  2066. X    strcpy(b2+1,b);
  2067. X    b2[0] = Inpar;
  2068. X    b2[len+1] = Outpar;
  2069. X    b2[len+2] = '\0';
  2070. X    c = parsereg(b2);
  2071. X    if (!c)
  2072. X        {
  2073. X        zerr("bad pattern: %s",b,0);
  2074. X        return 0;
  2075. X        }
  2076. X    val = domatch(a,c,0);
  2077. X    return val;
  2078. X}
  2079. X
  2080. X/* do the ${foo%%bar}, ${foo#bar} stuff */
  2081. X/* please do not laugh at this code. */
  2082. X
  2083. Xvoid getmatch(sp,pat,dd) /**/
  2084. Xchar **sp;char *pat;int dd;
  2085. X{
  2086. XComp c;
  2087. Xchar *t,*lng = NULL,cc,*s = *sp;
  2088. X
  2089. X    remnulargs(pat);
  2090. X    c = parsereg(pat);
  2091. X    if (!c)
  2092. X        {
  2093. X        zerr("bad pattern: %s",pat,0);
  2094. X        return;
  2095. X        }
  2096. X    if (!(dd & 2))
  2097. X        {
  2098. X        for (t = s; t==s || t[-1]; t++)
  2099. X            {
  2100. X            cc = *t;
  2101. X            *t = '\0';
  2102. X            if (domatch(s,c,0))
  2103. X                {
  2104. X                if (!(dd & 1))
  2105. X                    {
  2106. X                    *t = cc;
  2107. X                    t = strdup(t);
  2108. X                    *sp = t;
  2109. X                    return;
  2110. X                    }
  2111. X                lng = t;
  2112. X                }
  2113. X            *t = cc;
  2114. X            }
  2115. X        if (lng)
  2116. X            {
  2117. X            t = strdup(lng);
  2118. X            *sp = t;
  2119. X            return;
  2120. X            }
  2121. X        }
  2122. X    else
  2123. X        {
  2124. X        for (t = s+strlen(s); t >= s; t--)
  2125. X            {
  2126. X            if (domatch(t,c,0))
  2127. X                {
  2128. X                if (!(dd & 1))
  2129. X                    {
  2130. X                    cc = *t;
  2131. X                    *t = '\0';
  2132. X                    *sp = strdup(*sp);
  2133. X                    *t = cc;
  2134. X                    return;
  2135. X                    }
  2136. X                lng = t;
  2137. X                }
  2138. X            }
  2139. X        if (lng)
  2140. X            {
  2141. X            cc = *lng;
  2142. X            *lng = '\0';
  2143. X            *sp = strdup(*sp);
  2144. X            *lng = cc;
  2145. X            return;
  2146. X            }
  2147. X        }
  2148. X}
  2149. X
  2150. X/* add a component to pathbuf */
  2151. X
  2152. Xstatic int addpath(s)
  2153. Xchar *s;
  2154. X{
  2155. X    if (strlen(s)+pathpos >= MAXPATHLEN) return 0;
  2156. X    while (pathbuf[pathpos++] = *s++);
  2157. X    pathbuf[pathpos-1] = '/';
  2158. X    pathbuf[pathpos] = '\0';
  2159. X    return 1;
  2160. X}
  2161. X
  2162. Xchar *getfullpath(s) /**/
  2163. Xchar *s;
  2164. X{
  2165. Xstatic char buf[MAXPATHLEN];
  2166. X
  2167. X    strcpy(buf,pathbuf);
  2168. X    strcat(buf,s);
  2169. X    return buf;
  2170. X}
  2171. X
  2172. X/* do the globbing */
  2173. X
  2174. Xvoid scanner(q) /**/
  2175. XComplist q;
  2176. X{
  2177. XComp c;
  2178. Xint closure;
  2179. X
  2180. X    if (closure = q->closure)    /* (foo/)# */
  2181. X        if (q->closure == 2)        /* (foo/)## */
  2182. X            q->closure = 1;
  2183. X        else
  2184. X            scanner(q->next);
  2185. X    if (c = q->comp)
  2186. X        {
  2187. X        if (!(c->next || c->left) && !haswilds(c->str))
  2188. X            if (q->next)
  2189. X                {
  2190. X                int oppos = pathpos;
  2191. X
  2192. X                if (errflag)
  2193. X                    return;
  2194. X                if (q->closure && !strcmp(c->str,".")) return;
  2195. X                if (!addpath(c->str)) return;
  2196. X                if (!closure || exists(pathbuf))
  2197. X                    scanner((q->closure) ? q : q->next);
  2198. X                pathbuf[pathpos = oppos] = '\0';
  2199. X                }
  2200. X            else
  2201. X                {
  2202. X                char *s;
  2203. X
  2204. X                if (exists(s = getfullpath(c->str)))
  2205. X                    insert(strdup(s));
  2206. X                }
  2207. X        else
  2208. X            {
  2209. X            char *fn;
  2210. X            int dirs = !!q->next;
  2211. X            struct direct *de;
  2212. X            DIR *lock = opendir((*pathbuf) ? pathbuf : ".");
  2213. X             
  2214. X            if (lock == NULL)
  2215. X                return;
  2216. X            readdir(lock); readdir(lock);     /* skip . and .. */
  2217. X            while (de = readdir(lock))
  2218. X                {
  2219. X                if (errflag)
  2220. X                    break;
  2221. X                fn = &de->d_name[0];
  2222. X                if (domatch(fn,c,unset(GLOBDOTS)))
  2223. X                    {
  2224. X                    int oppos = pathpos;
  2225. X
  2226. X                    if (dirs)
  2227. X                        {
  2228. X                        if (closure)
  2229. X                            {
  2230. X                            int type3;
  2231. X                            struct stat buf;
  2232. X
  2233. X                             if (lstat(getfullpath(fn),&buf) == -1)
  2234. X                                {
  2235. X                                if (errno != ENOENT && errno != EINTR &&
  2236. X                                        errno != ENOTDIR)
  2237. X                                    {
  2238. X                                    zerr("%e: %s",fn,errno);
  2239. X                                    errflag = 0;
  2240. X                                    }
  2241. X                                continue;
  2242. X                                }
  2243. X                            type3 = buf.st_mode & S_IFMT;
  2244. X                            if (type3 != S_IFDIR)
  2245. X                                continue;
  2246. X                            }
  2247. X                        if (addpath(fn))
  2248. X                            scanner((q->closure) ? q : q->next); /* scan next level */
  2249. X                        pathbuf[pathpos = oppos] = '\0';
  2250. X                        }
  2251. X                    else
  2252. X                        {
  2253. X                        if (qualct)    /* do the (X) (^X) stuff */
  2254. X                            {
  2255. X                            int (**fptr)DCLPROTO((struct stat *,long)) = qualfuncs;
  2256. X                            int *sptr = qualsense;
  2257. X                            long *lptr = qualdata;
  2258. X                            struct stat buf;
  2259. X    
  2260. X                            if (lstat(getfullpath(fn),&buf) == -1)
  2261. X                                {
  2262. X                                if (errno != ENOENT && errno != EINTR)
  2263. X                                    {
  2264. X                                    zerr("%e: %s",fn,errno);
  2265. X                                    errflag = 0;
  2266. X                                    }
  2267. X                                continue;
  2268. X                                }
  2269. X                            while (*fptr)
  2270. X                                if (!(!!((*fptr++)(&buf,*lptr++)) ^ *sptr++))
  2271. X                                    {
  2272. X                                    fptr = NULL;
  2273. X                                    break;
  2274. X                                    }
  2275. X                            if (!fptr)
  2276. X                                continue;
  2277. X                            }
  2278. X                        insert(dyncat(pathbuf,fn));
  2279. X                        }
  2280. X                    }
  2281. X                }
  2282. X            closedir(lock);
  2283. X            }
  2284. X        }
  2285. X    else
  2286. X        zerr("no idea how you got this error message.",NULL,0);
  2287. X}
  2288. X
  2289. X/* do the [..(foo)..] business */
  2290. X
  2291. Xint minimatch(pat,str) /**/
  2292. Xchar **pat;char **str;
  2293. X{
  2294. Xchar *pt = *pat+1,*s = *str;
  2295. X    
  2296. X    for (; *pt != Outpar; s++,pt++)
  2297. X        if ((*pt != Quest || !*s) && *pt != *s)
  2298. X            {
  2299. X            *pat = getparen(*pat)-1;
  2300. X            return 0;
  2301. X            }
  2302. X    *str = s-1;
  2303. X    return 1;
  2304. X}
  2305. X
  2306. Xstatic char *pptr;
  2307. Xstatic Comp tail = 0;
  2308. Xstatic int first;
  2309. X
  2310. Xint domatch(str,c,fist) /**/
  2311. Xchar *str;Comp c;int fist;
  2312. X{
  2313. X    pptr = str;
  2314. X    first = fist;
  2315. X    return doesmatch(c);
  2316. X}
  2317. X
  2318. X/* see if current pattern matches c */
  2319. X
  2320. Xint doesmatch(c) /**/
  2321. XComp c;
  2322. X{
  2323. Xchar *pat = c->str;
  2324. X
  2325. X    if (c->closure == 1)
  2326. X        {
  2327. X        char *saves = pptr;
  2328. X        int savei = first;
  2329. X
  2330. X        if (doesmatch(c->next))
  2331. X            return 1;
  2332. X        pptr = saves;
  2333. X        first = savei;
  2334. X        }
  2335. X    for(;;)
  2336. X        {
  2337. X        if (!pat || !*pat)
  2338. X            {
  2339. X            char *saves;
  2340. X            int savei;
  2341. X
  2342. X            if (errflag)
  2343. X                return 0;
  2344. X            saves = pptr;
  2345. X            savei = first;
  2346. X            if (c->left || c->right)
  2347. X                if (!doesmatch(c->left))
  2348. X                    if (c->right)
  2349. X                        {
  2350. X                        pptr = saves;
  2351. X                        first = savei;
  2352. X                        if (!doesmatch(c->right))
  2353. X                            return 0;
  2354. X                        }
  2355. X                    else
  2356. X                        return 0;
  2357. X            if (c->closure)
  2358. X                return doesmatch(c);
  2359. X            if (!c->next)
  2360. X                return (!c->last || !*pptr);
  2361. X            return doesmatch(c->next);
  2362. X            }
  2363. X        if (first && *pptr == '.' && *pat != '.')
  2364. X            return 0;
  2365. X        if (*pat == Star)    /* final * is not expanded to ?#; returns success */
  2366. X            {
  2367. X            while (*pptr) pptr++;
  2368. X            return 1;
  2369. X            }
  2370. X        first = 0;
  2371. X        if (*pat == Quest && *pptr)
  2372. X            {
  2373. X            pptr++;
  2374. X            pat++;
  2375. X            continue;
  2376. X            }
  2377. X        if (*pat == Hat)
  2378. X            return 1-doesmatch(c->next);
  2379. X        if (*pat == Inbrack) {
  2380. X            if (!*pptr) break;
  2381. X            if (pat[1] == Hat || pat[1] == '^') {
  2382. X                pat[1] = Hat;
  2383. X                for (pat += 2; *pat != Outbrack && *pat; pat++)
  2384. X                    if (*pat == '-' && pat[-1] != Hat && pat[1] != Outbrack) {
  2385. X                        if (pat[-1] <= *pptr && pat[1] >= *pptr)
  2386. X                            break;
  2387. X                    } else if (*pptr == *pat) break;
  2388. X                if (!*pat) {
  2389. X                    zerr("something is very wrong.",NULL,0);
  2390. X                    return 0;
  2391. X                }
  2392. X                if (*pat != Outbrack)
  2393. X                    break;
  2394. X                pat++;
  2395. X                pptr++;
  2396. X                continue;
  2397. X            } else {
  2398. X                for (pat++; *pat != Outbrack && *pat; pat++)
  2399. X                    if (*pat == Inpar) {
  2400. X                        if (minimatch(&pat,&pptr))
  2401. X                            break;
  2402. X                    } else if (*pat == '-' && pat[-1] != Inbrack &&
  2403. X                            pat[1] != Outbrack) {
  2404. X                        if (pat[-1] <= *pptr && pat[1] >= *pptr)
  2405. X                            break;
  2406. X                    } else if (*pptr == *pat) break;
  2407. X                if (!pat || !*pat) {
  2408. X                    zerr("oh dear.  that CAN'T be right.",NULL,0);
  2409. X                    return 0;
  2410. SHAR_EOF
  2411. true || echo 'restore of zsh2.1/src/glob.c failed'
  2412. fi
  2413. echo 'End of zsh2.1.0 part 6'
  2414. echo 'File zsh2.1/src/glob.c is continued in part 7'
  2415. echo 7 > _shar_seq_.tmp
  2416. exit 0
  2417.  
  2418. exit 0 # Just in case...
  2419. -- 
  2420. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2421. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2422. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2423. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2424.