home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume29 / zsh2.2 / part07 < prev    next >
Text File  |  1992-05-13  |  50KB  |  2,273 lines

  1. Newsgroups: comp.sources.misc
  2. From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  3. Subject:  v29i103:  zsh2.2 - The Z shell, Part07/17
  4. Message-ID: <1992May13.160014.9065@sparky.imd.sterling.com>
  5. X-Md4-Signature: d4b7284ef1c152a41bdd8bc679dafb7e
  6. Date: Wed, 13 May 1992 16:00:14 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  10. Posting-number: Volume 29, Issue 103
  11. Archive-name: zsh2.2/part07
  12. Environment: BSD
  13. Supersedes: zsh2.1: Volume 24, Issue 1-19
  14.  
  15. #!/bin/sh
  16. # this is aa.07 (part 7 of zsh2.2)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file zsh2.2/src/builtin.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" != 7; 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.2/src/builtin.c'
  34. else
  35. echo 'x - continuing file zsh2.2/src/builtin.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/builtin.c' &&
  37. X    if (flags & BINF_ECHOPTS && arg && strcmp(arg,"-n"))
  38. X        optstr = NULL;
  39. X    if (optstr)
  40. X        while (arg &&
  41. X                ((sense = *arg == '-') || fset(BINF_PLUSOPTS) && *arg == '+') &&
  42. X                (fset(BINF_PLUSOPTS) || !atoi(arg)))
  43. X            {
  44. X            pp = arg;
  45. X            if (arg[1] == '-')
  46. X                arg++;
  47. X            if (!arg[1])
  48. X                {
  49. X                ops['-'] = 1;
  50. X                if (!sense)
  51. X                    ops['+'] = 1;
  52. X                }
  53. X            else
  54. X                ops['@'] = 1;
  55. X            op = -1;
  56. X            while (*++arg)
  57. X                if (strchr(b->optstr,op = *arg))
  58. X                    ops[*arg] = (sense) ? 1 : 2;
  59. X                else
  60. X                    break;
  61. X            if (*arg)
  62. X                {
  63. X                zerr("bad option: %c",NULL,*arg);
  64. X                return 1;
  65. X                }
  66. X            arg = ugetnode(args);
  67. X            if (fset(BINF_SETOPTS) && op == 'o')
  68. X                {
  69. X                int c;
  70. X                
  71. X                if (!arg)
  72. X                    prtopt();
  73. X                else
  74. X                    {
  75. X                    c = optlookup(arg);
  76. X                    if (c == -1)
  77. X                        {
  78. X                        zerr("bad option: %s",arg,0);
  79. X                        return 1;
  80. X                        }
  81. X                    else
  82. X                        {
  83. X                        ops[c] = ops['o'];
  84. X                        arg = ugetnode(args);
  85. X                        }
  86. X                    }
  87. X                }
  88. X            if ((fset(BINF_PRINTOPTS) && ops['R']) || ops['-'])
  89. X                break;
  90. X            if (fset(BINF_SETOPTS) && ops['A'])
  91. X                {
  92. X                auxdata = arg;
  93. X                arg = ugetnode(args);
  94. X                break;
  95. X                }
  96. X            if (fset(BINF_FCOPTS) && op == 'e')
  97. X                {
  98. X                auxdata = arg;
  99. X                arg = ugetnode(args);
  100. X                }
  101. X            if (fset(BINF_TYPEOPT) && (op == 'L' || op == 'R' ||
  102. X                    op == 'Z' || op == 'i') && arg && idigit(*arg))
  103. X                {
  104. X                auxlen = atoi(arg);
  105. X                arg = ugetnode(args);
  106. X                }
  107. X            }
  108. X    if (fset(BINF_R))
  109. X        auxdata = "-";
  110. X    if (pp = b->defopts)
  111. X        while (*pp)
  112. X            ops[*pp++] = 1;
  113. X    if (arg)
  114. X        {
  115. X        argc = 1;
  116. X        n = firstnode(args);
  117. X        while (n)
  118. X            argc++,incnode(n);
  119. X        }
  120. X    oargv = argv = (char **) ncalloc(sizeof(char **) * (argc+1));
  121. X    if (*argv++ = arg)
  122. X        while (*argv++ = ugetnode(args));
  123. X    argv = oargv;
  124. X    if (errflag)
  125. X        return 1;
  126. X    if (argc < b->minargs || (argc > b->maxargs && b->maxargs != -1)) {
  127. X        zerrnam(name,(argc < b->minargs)
  128. X            ? "not enough arguments" : "too many arguments",NULL,0);
  129. X        return 1;
  130. X    }
  131. X    if (isset(XTRACE)) {
  132. X        char **pp = argv;
  133. X        fprintf(stderr,"%s%s",(prompt4) ? prompt4 : "",name);
  134. X        while (*pp) fprintf(stderr," %s",*pp++);
  135. X        fputc('\n',stderr);
  136. X        fflush(stderr);
  137. X    }
  138. X    return (*(b->handlerfunc))(name,argv,ops,b->funcid);
  139. X}
  140. X
  141. Xstruct asgment *getasg(s) /**/
  142. Xchar *s;
  143. X{
  144. Xstatic struct asgment asg;
  145. X
  146. X    if (!s)
  147. X        return NULL;
  148. X    if (*s == '=')
  149. X        {
  150. X        zerr("bad assignment",NULL,0);
  151. X        return NULL;
  152. X        }
  153. X    asg.name = s;
  154. X    for (; *s && *s != '='; s++);
  155. X    if (*s)
  156. X        {
  157. X        *s = '\0';
  158. X        asg.value = s+1;
  159. X        }
  160. X    else
  161. X        asg.value = NULL;
  162. X    return &asg;
  163. X}
  164. X
  165. X/* ., source */
  166. X
  167. Xint bin_dot(name,argv,ops,func) /**/
  168. Xchar *name;char **argv;char *ops;int func;
  169. X{
  170. Xchar **old,*old0;
  171. Xint ret;
  172. Xchar buf[MAXPATHLEN];
  173. Xchar *s,**t,*enam;
  174. X
  175. X    if (!*argv)
  176. X        return 0;
  177. X    old = pparams;
  178. X    old0 = argzero;
  179. X    if (argv[1]) {
  180. X        permalloc();
  181. X        pparams = arrdup(argv+1);
  182. X        heapalloc();
  183. X    }
  184. X    enam = argzero = ztrdup(*argv);
  185. X    errno = ENOENT;
  186. X    ret = 1;
  187. X    for (s = argzero; *s; s++)
  188. X        if (*s == '/') {
  189. X            ret = source(argzero);
  190. X            break;
  191. X        }
  192. X    if (!*s) {
  193. X        for (t = path; *t; t++)
  194. X            if ((*t)[0] == '.' && !(*t)[1]) {
  195. X                ret = source(argzero);
  196. X                break;
  197. X            } else {
  198. X                sprintf(buf,"%s/%s",*t,argzero);
  199. X                if (access(buf,F_OK) == 0) {
  200. X                    ret = source(enam = buf);
  201. X                    break;
  202. X                }
  203. X            }
  204. X        if (!*t && access(argzero,F_OK) == 0)
  205. X            ret = source(enam = argzero);
  206. X    }
  207. X    if (argv[1]) {
  208. X        freearray(pparams);
  209. X        pparams = old;
  210. X    }
  211. X    if (ret) zerrnam(name,"%e: %s",enam,errno);
  212. X    free(argzero);
  213. X    argzero = old0;
  214. X    return ret;
  215. X}
  216. X
  217. Xint bin_set(name,argv,ops,func) /**/
  218. Xchar *name;char **argv;char *ops;int func;
  219. X{
  220. Xstruct option *opp;
  221. Xchar **x;
  222. X
  223. X    if (((ops['+'] && ops['-']) || !ops['-']) && !ops['@'] && !*argv)
  224. X        {
  225. X        showflag = ~0;
  226. X        showflag2 = ops['+'];
  227. X        listhtable(paramtab,(HFunc) printparam);
  228. X        }
  229. X   for (opp = optns; opp->name; opp++)
  230. X      if (ops[opp->id] == 1)
  231. X         opts[opp->id] = OPT_SET;
  232. X      else if (ops[opp->id] == 2)
  233. X         opts[opp->id] = OPT_UNSET;
  234. X    if (!*argv && !ops['-'])
  235. X        return 0;
  236. X    permalloc();
  237. X    x = arrdup(argv);
  238. X    heapalloc();
  239. X    if (ops['A'])
  240. X        setaparam(auxdata,x);
  241. X    else {
  242. X        freearray(pparams);
  243. X        pparams = x;
  244. X    }
  245. X    return 0;
  246. X}
  247. X
  248. X#define pttime(X) printf("%dm%ds",(X)/3600,(X)/60%60)
  249. X
  250. Xint bin_times(name,argv,ops,func) /**/
  251. Xchar *name;char **argv;char *ops;int func;
  252. X{
  253. Xstruct tms buf;
  254. X
  255. X    if (times(&buf) == -1)
  256. X        return 1;
  257. X    pttime(buf.tms_utime);
  258. X    putchar(' ');
  259. X    pttime(buf.tms_stime);
  260. X    putchar('\n');
  261. X    pttime(buf.tms_cutime);
  262. X    putchar(' ');
  263. X    pttime(buf.tms_cstime);
  264. X    putchar('\n');
  265. X    return 0;
  266. X}
  267. X
  268. Xint bin_getopts(name,argv,ops,func) /**/
  269. Xchar *name;char **argv;char *ops;int func;
  270. X{
  271. Xchar *optstr = *argv++,*var = *argv++;
  272. Xchar **args = (*argv) ? argv : pparams;
  273. Xstatic int optcind = 1,quiet;
  274. Xchar *str,optbuf[3],*opch = optbuf+1;
  275. X
  276. X    if (zoptind < 1) zoptind = 1;
  277. X    optbuf[0] = '+'; optbuf[1] = optbuf[2] = '\0';
  278. X    if (optarg) free(optarg);
  279. X    optarg = ztrdup("");
  280. X    setsparam(var,ztrdup(""));
  281. X    if (*optstr == ':') {
  282. X        quiet = 1;
  283. X        optstr++;
  284. X    }
  285. X    if (zoptind > arrlen(args)) return 1;
  286. X    str = args[zoptind-1];
  287. X    if (*str != '+' && *str != '-' || optcind >= strlen(str) ||
  288. X            !strcmp("--",str)) {
  289. X        if (*str == '+' || *str == '-')
  290. X            zoptind++;
  291. X        optcind = 0;
  292. X        return 1;
  293. X    }
  294. X    if (!optcind)
  295. X        optcind = 1;
  296. X    *opch = str[optcind++];
  297. X    if (!args[zoptind-1][optcind]) {
  298. X        zoptind++;
  299. X        optcind = 0;
  300. X    }
  301. X    for (; *optstr; optstr++)
  302. X        if (*opch == *optstr)
  303. X            break;
  304. X    if (!*optstr) {
  305. X        setsparam(var,ztrdup("?"));
  306. X        if (quiet) {
  307. X            free(optarg); optarg = ztrdup(opch);
  308. X            return 0;
  309. X        }
  310. X        zerr("bad option: %c",NULL,*opch); errflag = 0;
  311. X        return 0;
  312. X    }
  313. X    setsparam(var,ztrdup(opch-(*str == '+')));
  314. X    if (optstr[1] == ':') {
  315. X        if (!args[zoptind-1]) {
  316. X            if (quiet) {
  317. X                free(optarg); optarg = ztrdup(opch);
  318. X                setsparam(var,ztrdup(":"));
  319. X                return 0;
  320. X            }
  321. X            setsparam(var,ztrdup("?"));
  322. X            zerr("argument expected after %c option",NULL,*opch); errflag = 0;
  323. X            return 0;
  324. X        }
  325. X        free(optarg);
  326. X        optarg = ztrdup(args[zoptind-1]+optcind);
  327. X        zoptind++;
  328. X        optcind = 0;
  329. X    }
  330. X    return 0;
  331. X}
  332. X
  333. X/* get a signal number from a string */
  334. X
  335. Xint getsignum(s) /**/
  336. Xchar *s;
  337. X{
  338. Xint x = atoi(s),t0;
  339. X
  340. X    if (idigit(*s) && x >= 0 && x < VSIGCOUNT)
  341. X        return x;
  342. X    for (t0 = 0; t0 != VSIGCOUNT; t0++)
  343. X        if (!strcmp(s,sigs[t0]))
  344. X            return t0;
  345. X    return -1;
  346. X}
  347. X
  348. Xint bin_trap(name,argv,ops,func) /**/
  349. Xchar *name;char **argv;char *ops;int func;
  350. X{
  351. XList l;
  352. Xchar *arg;
  353. X
  354. X    if (!*argv) {
  355. X        int t0;
  356. X
  357. X        for (t0 = 0; t0 != VSIGCOUNT; t0++)
  358. X            if (sigtrapped[t0])
  359. X                if (!sigfuncs[t0])
  360. X                    printf("TRAP%s () {}\n",sigs[t0]);
  361. X                else {
  362. X                    char *s = getpermtext((vptr) sigfuncs[t0]);
  363. X                    printf("TRAP%s () {\n\t%s\n}\n",sigs[t0],s);
  364. X                    free(s);
  365. X                }
  366. X        return 0;
  367. X    }
  368. X    if (!strcmp(*argv,"-")) {
  369. X        int t0;
  370. X
  371. X        argv++;
  372. X        if (!*argv)
  373. X            for (t0 = 0; t0 != VSIGCOUNT; t0++) unsettrap(t0);
  374. X        else
  375. X            while (*argv) unsettrap(getsignum(*argv++));
  376. X        return 0;
  377. X    }
  378. X    arg = *argv++;
  379. X    if (!*arg) l = NULL;
  380. X    else if (!(l = parselstring(arg))) {
  381. X        zerrnam(name,"couldn't parse trap command",NULL,0);
  382. X        popheap();
  383. X        return 1;
  384. X    }
  385. X    for (; *argv; argv++) {
  386. X        int sg = getsignum(*argv);
  387. X        if (sg == -1) {
  388. X            zerrnam(name,"undefined signal: %s",*argv,0);
  389. X            break;
  390. X        }
  391. X        settrap(sg,l);
  392. X    }
  393. X    if (l) popheap();
  394. X    return errflag;
  395. X}
  396. X
  397. Xvoid printulimit(lim,hard) /**/
  398. Xint lim;int hard;
  399. X{
  400. Xlong t0;
  401. X
  402. X#ifdef RLIM_INFINITY
  403. X    t0 = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur;
  404. X    switch (lim)
  405. X        {
  406. X        case RLIMIT_CPU: printf("cpu time (seconds)         "); break;
  407. X        case RLIMIT_FSIZE: printf("file size (blocks)         "); t0 /= 512; break;
  408. X        case RLIMIT_DATA: printf("data seg size (kbytes)     "); t0 /= 1024; break;
  409. X        case RLIMIT_STACK: printf("stack size (kbytes)        "); t0 /= 1024; break;
  410. X        case RLIMIT_CORE: printf("core file size (blocks)    "); t0 /= 512; break;
  411. X#ifdef RLIMIT_RSS
  412. X        case RLIMIT_RSS: printf("resident set size (kbytes) "); t0 /= 1024; break;
  413. X#endif
  414. X#ifdef RLIMIT_NOFILE
  415. X        case RLIMIT_NOFILE: printf("file descriptors           "); break;
  416. X#endif
  417. X        }
  418. X    printf("%ld\n",t0);
  419. X#endif
  420. X}
  421. X
  422. Xint bin_ulimit(name,argv,ops,func) /**/
  423. Xchar *name;char **argv;char *ops;int func;
  424. X{
  425. Xint res,hard;
  426. X
  427. X#ifndef RLIM_INFINITY
  428. X    zerrnam(name,"not available on this system",NULL,0);
  429. X    return 1;
  430. X#else
  431. X    hard = ops['H'];
  432. X    if (ops['a'] || !ops['@'])
  433. X        res = -1;
  434. X    else if (ops['t'])
  435. X        res = RLIMIT_CPU;
  436. X    else if (ops['f'])
  437. X        res = RLIMIT_FSIZE;
  438. X    else if (ops['d'])
  439. X        res = RLIMIT_DATA;
  440. X    else if (ops['s'])
  441. X        res = RLIMIT_STACK;
  442. X    else if (ops['c'])
  443. X        res = RLIMIT_CORE;
  444. X#ifdef RLIMIT_RSS
  445. X    else if (ops['m'])
  446. X        res = RLIMIT_RSS;
  447. X#endif
  448. X#ifdef RLIMIT_NOFILE
  449. X    else if (ops['n'])
  450. X        res = RLIMIT_NOFILE;
  451. X#endif
  452. X    else
  453. X        {
  454. X        zerrnam(name,"no such limit",NULL,0);
  455. X        return 1;
  456. X        }
  457. X    if (res == -1)
  458. X        if (*argv)
  459. X            {
  460. X            zerrnam(name,"no arguments required after -a",NULL,0);
  461. X            return 1;
  462. X            }
  463. X        else
  464. X            {
  465. X            int t0;
  466. X
  467. X            for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
  468. X                printulimit(t0,hard);
  469. X            return 0;
  470. X            }
  471. X    if (!*argv)
  472. X        printulimit(res,hard);
  473. X    else if (strcmp(*argv,"unlimited"))
  474. X        {
  475. X        long t0;
  476. X        
  477. X        t0 = atol(*argv);
  478. X        switch(res)
  479. X            {
  480. X            case RLIMIT_FSIZE: case RLIMIT_CORE: t0 *= 512; break;
  481. X            case RLIMIT_DATA: case RLIMIT_STACK:
  482. X#ifdef RLIMIT_RSS
  483. X            case RLIMIT_RSS:
  484. X#endif
  485. X                t0 *= 1024; break;
  486. X            }
  487. X        if (hard)
  488. X            {
  489. X            if (t0 > limits[res].rlim_max && geteuid())
  490. X                {
  491. X                zerrnam(name,"can't raise hard limits",NULL,0);
  492. X                return 1;
  493. X                }
  494. X            limits[res].rlim_max = t0;
  495. X            }
  496. X        else
  497. X            {
  498. X            if (t0 > limits[res].rlim_max)
  499. X                {
  500. X                if (geteuid())
  501. X                    {
  502. X                    zerrnam(name,"value exceeds hard limit",NULL,0);
  503. X                    return 1;
  504. X                    }
  505. X                limits[res].rlim_max = limits[res].rlim_cur = t0;
  506. X                }
  507. X            else
  508. X                limits[res].rlim_cur = t0;
  509. X            }
  510. X        }
  511. X    else
  512. X        {
  513. X        if (hard)
  514. X            {
  515. X            if (geteuid())
  516. X                {
  517. X                zerrnam(name,"can't remove hard limits",NULL,0);
  518. X                return 1;
  519. X                }
  520. X            limits[res].rlim_max = RLIM_INFINITY;
  521. X            }
  522. X        else
  523. X            limits[res].rlim_cur = limits[res].rlim_max;
  524. X        }
  525. X    return 0;
  526. X#endif
  527. X}
  528. X
  529. Xint putraw(c) /**/
  530. Xint c;
  531. X{
  532. X    putchar(c);
  533. X    return 0;
  534. X}
  535. X
  536. Xint bin_echotc(name,argv,ops,func) /**/
  537. Xchar *name;char **argv;char *ops;int func;
  538. X{
  539. Xchar *s,buf[2048],*t,*u;
  540. Xint num,argct,t0;
  541. X
  542. X    s = *argv++;
  543. X    if (!termok)
  544. X        return 1;
  545. X    if ((num = tgetnum(s)) != -1)
  546. X        {
  547. X        printf("%d\n",num);
  548. X        return 0;
  549. X        }
  550. X    u = buf;
  551. X    t = tgetstr(s,&u);
  552. X    if (!t || !*t)
  553. X        {
  554. X        zerrnam(name,"no such capability: %s",s,0);
  555. X        return 1;
  556. X        }
  557. X    for (argct = 0, u = t; *u; u++)
  558. X        if (*u == '%')
  559. X            {
  560. X            if (u++, (*u == 'd' || *u == '2' || *u == '3' || *u == '.' ||
  561. X                    *u == '+'))
  562. X                argct++;
  563. X            }
  564. X    if (arrlen(argv) != argct)
  565. X        {
  566. X        zerrnam(name,(arrlen(argv) < argct) ? "not enough arguments" :
  567. X            "too many arguments",NULL,0);
  568. X        return 1;
  569. X        }
  570. X    if (!argct)
  571. X        tputs(t,1,putraw);
  572. X    else
  573. X        {
  574. X        t0 = (argv[1]) ? atoi(argv[1]) : atoi(*argv);
  575. X        tputs(tgoto(t,atoi(*argv),t0),t0,putraw);
  576. X        }
  577. X    return 0;
  578. X}
  579. X
  580. Xint bin_pwd(name,argv,ops,func) /**/
  581. Xchar *name;char **argv;char *ops;int func;
  582. X{
  583. X    printf("%s\n",pwd);
  584. X    return 0;
  585. X}
  586. X
  587. X#define TEST_END 0
  588. X#define TEST_INPAR 1
  589. X#define TEST_OUTPAR 2
  590. X#define TEST_STR 3
  591. X#define TEST_AND 4
  592. X#define TEST_OR 5
  593. X#define TEST_NOT 6
  594. X
  595. Xstatic char **tsp;
  596. Xstatic int *tip;
  597. X
  598. Xint bin_test(name,argv,ops,func) /**/
  599. Xchar *name;char **argv;char *ops;int func;
  600. X{
  601. Xchar **s;
  602. Xint cnt,*arr,*ap;
  603. XCond c;
  604. X
  605. X    if (func == BIN_BRACKET)
  606. X        {
  607. X        for (s = argv; *s; s++);
  608. X        if (s == argv || strcmp(s[-1],"]"))
  609. X            {
  610. X            zerrnam(name,"']' expected",NULL,0);
  611. X            return 1;
  612. X            }
  613. X        s[-1] = NULL;
  614. X        }
  615. X    for (s = argv, cnt = 0; *s; s++,cnt++);
  616. X    ap = arr = alloc((cnt+1)*sizeof *arr);
  617. X    for (s = argv; *s; s++,ap++)
  618. X        if (!strcmp(*s,"("))
  619. X            *ap = TEST_INPAR;
  620. X        else if (!strcmp(*s,")"))
  621. X            *ap = TEST_OUTPAR;
  622. X        else if (!strcmp(*s,"-a"))
  623. X            *ap = TEST_AND;
  624. X        else if (!strcmp(*s,"-o"))
  625. X            *ap = TEST_OR;
  626. X        else if (!strcmp(*s,"!"))
  627. X            *ap = TEST_NOT;
  628. X        else
  629. X            *ap = TEST_STR;
  630. X    *ap = TEST_END;
  631. X    tsp = argv;
  632. X    tip = arr;
  633. X    c = partest(0);
  634. X    if (*tip != TEST_END || errflag)
  635. X        {
  636. X        zerrnam(name,"parse error",NULL,0);
  637. X        return 1;
  638. X        }
  639. X    return (c) ? !evalcond(c) : 1;
  640. X}
  641. X
  642. XCond partest(level) /**/
  643. Xint level;
  644. X{
  645. XCond a,b;
  646. X
  647. X    switch (level)
  648. X        {
  649. X        case 0:
  650. X            a = partest(1);
  651. X            if (*tip == TEST_OR)
  652. X                {
  653. X                tip++,tsp++;
  654. X                b = makecond();
  655. X                b->left = a;
  656. X                b->right = partest(0);
  657. X                b->type = COND_OR;
  658. X                return b;
  659. X                }
  660. X            return a;
  661. X        case 1:
  662. X            a = partest(2);
  663. X            if (*tip == TEST_AND)
  664. X                {
  665. X                tip++,tsp++;
  666. X                b = makecond();
  667. X                b->left = a;
  668. X                b->right = partest(1);
  669. X                b->type = COND_AND;
  670. X                return b;
  671. X                }
  672. X            return a;
  673. X        case 2:
  674. X            if (*tip == TEST_NOT)
  675. X                {
  676. X                tip++,tsp++;
  677. X                b = makecond();
  678. X                b->left = partest(2);
  679. X                b->type = COND_NOT;
  680. X                return b;
  681. X                }
  682. X        case 3:
  683. X            if (*tip == TEST_INPAR)
  684. X                {
  685. X                tip++,tsp++;
  686. X                b = partest(0);
  687. X                if (*tip != TEST_OUTPAR)
  688. X                    {
  689. X                    zerrnam("test","parse error",NULL,0);
  690. X                    return NULL;
  691. X                    }
  692. X                tip++,tsp++;
  693. X                return b;
  694. X                }
  695. X            if (tip[0] != TEST_STR)
  696. X                {
  697. X                zerrnam("test","parse error",NULL,0);
  698. X                return NULL;
  699. X                }
  700. X            else if (tip[1] != TEST_STR)
  701. X                {
  702. X                b = makecond();
  703. X                if (!strcmp(*tsp,"-t"))
  704. X                    {
  705. X                    b->left = strdup("1");
  706. X                    b->type = 't';
  707. X                    }
  708. X                else
  709. X                    {
  710. X                    b->left = tsp[0];
  711. X                    b->type = 'n';
  712. X                    }
  713. X                tip++,tsp++;
  714. X                return b;
  715. X                }
  716. X            else if (tip[2] != TEST_STR)
  717. X                {
  718. X                b = par_cond_double(tsp[0],tsp[1]);
  719. X                tip += 2,tsp += 2;
  720. X                return b;
  721. X                }
  722. X            else
  723. X                {
  724. X                b = par_cond_triple(tsp[0],tsp[1],tsp[2]);
  725. X                tip += 3,tsp += 3;
  726. X                return b;
  727. X                }
  728. X        }
  729. X   return NULL;
  730. X}
  731. X
  732. Xint bin_compctl(name,argv,ops,func) /**/
  733. Xchar *name;char **argv;char *ops;int func;
  734. X{
  735. Xint flags = 0;
  736. XCompctl cc = NULL;
  737. Xchar *usrkeys = NULL;
  738. X
  739. X    for (; *argv && **argv == '-'; argv++)
  740. X        while (*++(*argv)) switch(**argv) {
  741. X        case 'c': flags |= CC_COMMPATH; break;
  742. X        case 'f': flags |= CC_FILES; break;
  743. X        case 'h': flags |= CC_HOSTS; break;
  744. X        case 'o': flags |= CC_OPTIONS; break;
  745. X        case 'v': flags |= CC_VARS; break;
  746. X        case 'b': flags |= CC_BINDINGS; break;
  747. X        case 'k':
  748. X            flags |= CC_USRKEYS;
  749. X            if ((*argv)[1]) { usrkeys = (*argv)+1; *argv = ""-1; }
  750. X            else if (!argv[1]) {
  751. X                zerrnam(name,"variable name expected after -k",NULL,0);
  752. X                return 1;
  753. X            } else { usrkeys = *++argv; *argv = ""-1; }
  754. X            break;
  755. X        case 'C': cc = &cc_compos; break;
  756. X        case 'D': cc = &cc_default; break;
  757. X        default: zerrnam(name,"bad option: %c",NULL,**argv); return 1;
  758. X        }
  759. X    if (cc) {
  760. X        cc->mask = flags;
  761. X        if (cc->keyvar) free(cc->keyvar);
  762. X        cc->keyvar  = ztrdup(usrkeys);
  763. X    }
  764. X    if (!*argv) {
  765. X        if (!cc) {
  766. X            showflag = flags;
  767. X            listhtable(compctltab,(HFunc) printcompctl);
  768. X            printcompctl("COMMAND",&cc_compos);
  769. X            printcompctl("DEFAULT",&cc_default);
  770. X        }
  771. X        return 0;
  772. X    }
  773. X    compctl_process(argv,flags,usrkeys);
  774. X    return 0;
  775. X}
  776. X
  777. Xvoid printcompctl(s,cc) /**/
  778. Xchar *s;Compctl cc;
  779. X{
  780. Xchar *css = "fchovb";
  781. X
  782. X    if (cc->mask & showflag) {
  783. X        puts(s);
  784. X    } else if (!showflag) {
  785. X        int flags = cc->mask;
  786. X        printf("%s -",s);
  787. X        while (*css) {
  788. X            if (flags & 1) putchar(*css);
  789. X            css++; flags >>= 1;
  790. X        }
  791. X        if (flags & 1) printf("k %s",cc->keyvar);
  792. X        putchar('\n');
  793. X    }
  794. X}
  795. X
  796. Xvoid compctl_process(s,mask,uk) /**/
  797. Xchar **s;int mask;char *uk;
  798. X{
  799. XCompctl cc;
  800. X
  801. X    for (;*s;s++) {
  802. X        cc = zalloc(sizeof *cc);
  803. X        cc->mask = mask; cc->keyvar = ztrdup(uk);
  804. X        addhnode(ztrdup(*s),cc,compctltab,freecompctl);
  805. X    }
  806. X}
  807. X
  808. Xint bin_ttyctl(name,argv,ops,func) /**/
  809. Xchar *name;char **argv;char *ops;int func;
  810. X{
  811. X    if (ops['f'] || !ops['@']) ttyfrozen = 1;
  812. X    else if (ops['u']) ttyfrozen = 0;
  813. X    return 0;
  814. X}
  815. X
  816. SHAR_EOF
  817. echo 'File zsh2.2/src/builtin.c is complete' &&
  818. chmod 0644 zsh2.2/src/builtin.c ||
  819. echo 'restore of zsh2.2/src/builtin.c failed'
  820. Wc_c="`wc -c < 'zsh2.2/src/builtin.c'`"
  821. test 61945 -eq "$Wc_c" ||
  822.     echo 'zsh2.2/src/builtin.c: original size 61945, current size' "$Wc_c"
  823. rm -f _shar_wnt_.tmp
  824. fi
  825. # ============= zsh2.2/src/cond.c ==============
  826. if test -f 'zsh2.2/src/cond.c' -a X"$1" != X"-c"; then
  827.     echo 'x - skipping zsh2.2/src/cond.c (File already exists)'
  828.     rm -f _shar_wnt_.tmp
  829. else
  830. > _shar_wnt_.tmp
  831. echo 'x - extracting zsh2.2/src/cond.c (Text)'
  832. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/cond.c' &&
  833. X/*
  834. X *
  835. X * cond.c - evaluate conditional expressions
  836. X *
  837. X * This file is part of zsh, the Z shell.
  838. X *
  839. X * This software is Copyright 1992 by Paul Falstad
  840. X *
  841. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  842. X * use this software as long as: there is no monetary profit gained
  843. X * specifically from the use or reproduction of this software, it is not
  844. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  845. X * included prominently in any copy made. 
  846. X *
  847. X * The author make no claims as to the fitness or correctness of this software
  848. X * for any use whatsoever, and it is provided as is. Any use of this software
  849. X * is at the user's own risk. 
  850. X *
  851. X */
  852. X
  853. X#include "zsh.h"
  854. X
  855. Xint evalcond(c) /**/
  856. XCond c;
  857. X{
  858. Xstruct stat *st;
  859. X
  860. X    switch (c->type)
  861. X        {
  862. X        case COND_NOT: return !evalcond(c->left);
  863. X        case COND_AND: return evalcond(c->left) && evalcond(c->right);
  864. X        case COND_OR: return evalcond(c->left) || evalcond(c->right);
  865. X        }
  866. X    singsub((char **) &c->left);
  867. X    untokenize(c->left);
  868. X    if (c->right)
  869. X        {
  870. X        singsub((char **) &c->right);
  871. X        if (c->type != COND_STREQ && c->type != COND_STRNEQ)
  872. X            untokenize(c->right);
  873. X        }
  874. X    switch (c->type)
  875. X        {
  876. X        case COND_STREQ: return matchpat(c->left,c->right);
  877. X        case COND_STRNEQ: return !matchpat(c->left,c->right);
  878. X        case COND_STRLT: return strcmp(c->left,c->right) < 0;
  879. X        case COND_STRGTR: return strcmp(c->left,c->right) > 0;
  880. X        case 'e': case 'a': return(doaccess(c->left,F_OK));
  881. X        case 'b': return(S_ISBLK(dostat(c->left)));
  882. X        case 'c': return(S_ISCHR(dostat(c->left)));
  883. X        case 'd': return(S_ISDIR(dostat(c->left)));
  884. X        case 'f': return(S_ISREG(dostat(c->left)));
  885. X        case 'g': return(!!(dostat(c->left) & S_ISGID));
  886. X        case 'k': return(!!(dostat(c->left) & S_ISVTX));
  887. X        case 'n': return(!!strlen(c->left));
  888. X        case 'o': return(optison(c->left));
  889. X        case 'p': return(S_ISFIFO(dostat(c->left)));
  890. X        case 'r': return(doaccess(c->left,R_OK));
  891. X        case 's': return((st = getstat(c->left)) && !!(st->st_size));
  892. X        case 'S': return(S_ISSOCK(dostat(c->left)));
  893. X        case 'u': return(!!(dostat(c->left) & S_ISUID));
  894. X        case 'w': return(doaccess(c->left,W_OK));
  895. X        case 'x': return(doaccess(c->left,X_OK));
  896. X        case 'z': return(!strlen(c->left));
  897. X        case 'h': case 'L': return(S_ISLNK(dolstat(c->left)));
  898. X        case 'O': return((st = getstat(c->left)) && st->st_uid == geteuid());
  899. X        case 'G': return((st = getstat(c->left)) && st->st_gid == getegid());
  900. X        case 't': return isatty(matheval(c->left));
  901. X        case COND_EQ: return matheval(c->left) == matheval(c->right);
  902. X        case COND_NE: return matheval(c->left) != matheval(c->right);
  903. X        case COND_LT: return matheval(c->left) < matheval(c->right);
  904. X        case COND_GT: return matheval(c->left) > matheval(c->right);
  905. X        case COND_LE: return matheval(c->left) <= matheval(c->right);
  906. X        case COND_GE: return matheval(c->left) >= matheval(c->right);
  907. X        case COND_NT: case COND_OT:
  908. X            {
  909. X            time_t a;
  910. X            if (!(st = getstat(c->left)))
  911. X                return 0;
  912. X            a = st->st_mtime;
  913. X            if (!(st = getstat(c->right)))
  914. X                return 0;
  915. X            return (c->type == COND_NT) ? a > st->st_mtime : a < st->st_mtime;
  916. X            }
  917. X        case COND_EF:
  918. X            {
  919. X            dev_t d;
  920. X            ino_t i;
  921. X
  922. X            if (!(st = getstat(c->left)))
  923. X                return 0;
  924. X            d = st->st_dev;
  925. X            i = st->st_ino;
  926. X            if (!(st = getstat(c->right)))
  927. X                return 0;
  928. X            return d == st->st_dev && i == st->st_ino;
  929. X            }
  930. X        default: zerr("bad cond structure",NULL,0);
  931. X        }
  932. X    return 0;
  933. X}
  934. X
  935. Xint doaccess(s,c) /**/
  936. Xchar *s;int c;
  937. X{
  938. X    return !access(s,c);
  939. X}
  940. X
  941. Xstatic struct stat st;
  942. X
  943. Xstruct stat *getstat(s) /**/
  944. Xchar *s;
  945. X{
  946. X    if (!strncmp(s,"/dev/fd/",8))
  947. X        {
  948. X        if (fstat(atoi(s+8),&st))
  949. X            return NULL;
  950. X        }
  951. X    else if (stat(s,&st))
  952. X        return NULL;
  953. X    return &st;
  954. X}
  955. X
  956. Xunsigned short dostat(s) /**/
  957. Xchar *s;
  958. X{
  959. Xstruct stat *st;
  960. X
  961. X    if (!(st = getstat(s)))
  962. X        return 0;
  963. X    return st->st_mode;
  964. X}
  965. X
  966. X/* pem@aaii.oz; needed since dostat now uses "stat" */
  967. X
  968. Xunsigned short dolstat(s) /**/
  969. Xchar *s;
  970. X{
  971. X    if (lstat(s, &st) < 0)
  972. X        return 0;
  973. X    return st.st_mode;
  974. X}
  975. X
  976. Xint optison(s) /**/
  977. Xchar *s;
  978. X{
  979. Xint i;
  980. X
  981. X    if (strlen(s) == 1)
  982. X        return opts[*s];
  983. X    if ((i = optlookup(s)) != -1)
  984. X        return opts[i];
  985. X    zerr("no such option: %s",s,0);
  986. X    return 0;
  987. X}
  988. X
  989. SHAR_EOF
  990. chmod 0644 zsh2.2/src/cond.c ||
  991. echo 'restore of zsh2.2/src/cond.c failed'
  992. Wc_c="`wc -c < 'zsh2.2/src/cond.c'`"
  993. test 4064 -eq "$Wc_c" ||
  994.     echo 'zsh2.2/src/cond.c: original size 4064, current size' "$Wc_c"
  995. rm -f _shar_wnt_.tmp
  996. fi
  997. # ============= zsh2.2/src/exec.c ==============
  998. if test -f 'zsh2.2/src/exec.c' -a X"$1" != X"-c"; then
  999.     echo 'x - skipping zsh2.2/src/exec.c (File already exists)'
  1000.     rm -f _shar_wnt_.tmp
  1001. else
  1002. > _shar_wnt_.tmp
  1003. echo 'x - extracting zsh2.2/src/exec.c (Text)'
  1004. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/exec.c' &&
  1005. X/*
  1006. X *
  1007. X * exec.c - command execution
  1008. X *
  1009. X * This file is part of zsh, the Z shell.
  1010. X *
  1011. X * This software is Copyright 1992 by Paul Falstad
  1012. X *
  1013. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  1014. X * use this software as long as: there is no monetary profit gained
  1015. X * specifically from the use or reproduction of this software, it is not
  1016. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  1017. X * included prominently in any copy made. 
  1018. X *
  1019. X * The author make no claims as to the fitness or correctness of this software
  1020. X * for any use whatsoever, and it is provided as is. Any use of this software
  1021. X * is at the user's own risk. 
  1022. X *
  1023. X */
  1024. X
  1025. X#include "zsh.h"
  1026. X#include <sys/errno.h>
  1027. X#ifdef __hpux
  1028. X#include <ndir.h>
  1029. X#else
  1030. X#include <sys/dir.h>
  1031. X#endif
  1032. X
  1033. X#define execerr() { if (forked) exit(1); \
  1034. X    closemnodes(mfds); errflag = 1; return; }
  1035. X
  1036. Xstatic Lklist args;
  1037. Xstatic Cmdnam cn;
  1038. X
  1039. X/* parse list in a string */
  1040. X
  1041. XList parselstring(s) /**/
  1042. Xchar *s;
  1043. X{
  1044. XList l;
  1045. X
  1046. X    hungets(s);
  1047. X    strinbeg();
  1048. X    pushheap();
  1049. X    if (!(l = parse_list())) {
  1050. X        strinend();
  1051. X        hflush();
  1052. X        popheap();
  1053. X        return NULL;
  1054. X    }
  1055. X    strinend();
  1056. X    return l;
  1057. X}
  1058. X
  1059. X/* execute a string */
  1060. X
  1061. Xvoid execstring(s) /**/
  1062. Xchar *s;
  1063. X{
  1064. XList l;
  1065. X
  1066. X    if (l = parselstring(s)) {
  1067. X        execlist(l);
  1068. X        popheap();
  1069. X    }
  1070. X}
  1071. X
  1072. X/* fork and set limits */
  1073. X
  1074. Xint phork() /**/
  1075. X{
  1076. Xint pid,t0;
  1077. X
  1078. X    if (thisjob >= MAXJOB-1) {
  1079. X        zerr("job table full",NULL,0);
  1080. X        return -1;
  1081. X    }
  1082. X    pid = fork();
  1083. X    if (pid == -1) {
  1084. X        zerr("fork failed: %e",NULL,errno);
  1085. X        return -1;
  1086. X    }
  1087. X#ifdef RLIM_INFINITY
  1088. X    if (!pid)
  1089. X        for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
  1090. X            setrlimit(t0,limits+t0);
  1091. X#endif
  1092. X    return pid;
  1093. X}
  1094. X
  1095. X/* execute a current shell command */
  1096. X
  1097. Xint execcursh(cmd) /**/
  1098. XCmd cmd;
  1099. X{
  1100. X    runlist(cmd->u.list);
  1101. X    cmd->u.list = NULL;
  1102. X    return lastval;
  1103. X}
  1104. X
  1105. X/* execve after handling $_ and #! */
  1106. X
  1107. X#define POUNDBANGLIMIT 64
  1108. X
  1109. Xint zexecve(pth,argv) /**/
  1110. Xchar *pth;char **argv;
  1111. X{
  1112. Xint eno;
  1113. Xstatic char buf[MAXPATHLEN*2];
  1114. Xchar **eep;
  1115. X
  1116. X    for (eep = environ; *eep; eep++)
  1117. X        if (**eep == '_' && (*eep)[1] == '=') break;
  1118. X    buf[0] = '_';
  1119. X    buf[1] = '=';
  1120. X    if (*pth == '/') strcpy(buf+2,pth);
  1121. X    else sprintf(buf+2,"%s/%s",pwd,pth);
  1122. X    if (!*eep) eep[1] = NULL;
  1123. X    *eep = buf;
  1124. X    execve(pth,argv,environ);
  1125. X    if ((eno = errno) == ENOEXEC) {
  1126. X        char buf[POUNDBANGLIMIT+1],*ptr,*ptr2,*argv0;
  1127. X        int fd,ct,t0;
  1128. X
  1129. X        if ((fd = open(pth,O_RDONLY)) >= 0) {
  1130. X            argv0 = *argv;
  1131. X            *argv = pth;
  1132. X            ct = read(fd,buf,POUNDBANGLIMIT);
  1133. X            close(fd);
  1134. X            if (ct > 0) {
  1135. X                if (buf[0] == '#')
  1136. X                    if (buf[1] == '!') {
  1137. X                        for (t0 = 0; t0 != ct; t0++)
  1138. X                            if (buf[t0] == '\n')
  1139. X                                buf[t0] = '\0';
  1140. X                        buf[POUNDBANGLIMIT] = '\0';
  1141. X                        for (ptr = buf+2; *ptr && *ptr == ' '; ptr++);
  1142. X                        for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++);
  1143. X                        if (*ptr) {
  1144. X                            *ptr = '\0';
  1145. X                            argv[-2] = ptr2;
  1146. X                            argv[-1] = ptr+1;
  1147. X                            execve(ptr2,argv-2,environ);
  1148. X                        } else {
  1149. X                            argv[-1] = ptr2;
  1150. X                            execve(ptr2,argv-1,environ);
  1151. X                        }
  1152. X                    } else {
  1153. X                        argv[-1] = "sh";
  1154. X                        execve("/bin/sh",argv-1,environ);
  1155. X                    }
  1156. X                else {
  1157. X                    for (t0 = 0; t0 != ct; t0++)
  1158. X                        if (!buf[t0]) break;
  1159. X                    if (t0 == ct) {
  1160. X                        argv[-1] = "sh";
  1161. X                        execve("/bin/sh",argv-1,environ);
  1162. X                    }
  1163. X                }
  1164. X            } else eno = errno;
  1165. X            *argv = argv0;
  1166. X        } else eno = errno;
  1167. X    }
  1168. X    return eno;
  1169. X}
  1170. X
  1171. X#define MAXCMDLEN (MAXPATHLEN*4)
  1172. X
  1173. X/* execute an external command */
  1174. X
  1175. Xvoid execute(dash) /**/
  1176. Xint dash;
  1177. X{
  1178. Xchar **argv,*arg0,**pp;
  1179. Xchar *z,*s,buf[MAXCMDLEN],buf2[MAXCMDLEN];
  1180. Xint ee = 0,eno = 0;
  1181. X
  1182. X    if (!full(args)) {
  1183. X        zerr("no command",NULL,0);
  1184. X        _exit(1);
  1185. X    }
  1186. X    cn = (Cmdnam) gethnode(peekfirst(args),cmdnamtab);
  1187. X    if (cn && cn->type == DISABLED)
  1188. X        cn = NULL;
  1189. X    if (s = zgetenv("STTY"))
  1190. X        zyztem("stty",s);
  1191. X    arg0 = peekfirst(args);
  1192. X    if (z = zgetenv("ARGV0")) {
  1193. X        setdata(firstnode(args),ztrdup(z));
  1194. X        delenv(z-6);
  1195. X    } else if (dash) {
  1196. X        sprintf(buf2,"-%s",arg0);
  1197. X        setdata(firstnode(args),ztrdup(buf2));
  1198. X    }
  1199. X    argv = makecline(args);
  1200. X    fixsigs();
  1201. X    if (strlen(arg0) > MAXPATHLEN) {
  1202. X        zerr("command too long: %s",arg0,0);
  1203. X        _exit(1);
  1204. X    }
  1205. X    for (s = arg0; *s; s++)
  1206. X        if (*s == '/') {
  1207. X            errno = zexecve(arg0,argv);
  1208. X            if (arg0 == s || unset(PATHDIRS)) {
  1209. X                zerr("%e: %s",arg0,errno);
  1210. X                _exit(1);
  1211. X            }
  1212. X            break;
  1213. X        }
  1214. X    if (cn && ISEXCMD(cn->type)) {
  1215. X        for (pp = path; pp < cn->pcomp; pp++)
  1216. X            if (**pp == '.' && (*pp)[1] == '\0') {
  1217. X                ee = zexecve(arg0,argv);
  1218. X                if (ee != ENOENT) eno = ee;
  1219. X            } else if (**pp != '/') {
  1220. X                z = buf;
  1221. X                strucpy(&z,*pp);
  1222. X                *z++ = '/';
  1223. X                strcpy(z,arg0);
  1224. X                ee = zexecve(buf,argv);
  1225. X                if (ee != ENOENT) eno = ee;
  1226. X            }
  1227. X        ee = zexecve(cn->u.nam,argv);
  1228. X        if (ee != ENOENT) eno = ee;
  1229. X    }
  1230. X    for (pp = path; *pp; pp++)
  1231. X        if ((*pp)[0] == '.' && !(*pp)[1]) {
  1232. X            ee = zexecve(arg0,argv);
  1233. X            if (ee != ENOENT) eno = ee;
  1234. X        } else {
  1235. X            z = buf;
  1236. X            strucpy(&z,*pp);
  1237. X            *z++ = '/';
  1238. X            strcpy(z,arg0);
  1239. X            ee = zexecve(buf,argv);
  1240. X            if (ee != ENOENT) eno = ee;
  1241. X        }
  1242. X    if (eno) zerr("%e: %s",arg0,eno);
  1243. X    else zerr("command not found: %s",arg0,0);
  1244. X    _exit(1);
  1245. X}
  1246. X
  1247. X#define try(X) { if (iscom(X)) return ztrdup(X); }
  1248. X
  1249. X/* get the full pathname of an external command */
  1250. X
  1251. Xchar *findcmd(arg0) /**/
  1252. Xchar *arg0;
  1253. X{
  1254. Xchar **pp;
  1255. Xchar *z,*s,buf[MAXCMDLEN];
  1256. X
  1257. X    cn = (Cmdnam) gethnode(arg0,cmdnamtab);
  1258. X    if (!cn && isset(HASHCMDS)) hashcmd(arg0,path);
  1259. X    if (cn && cn->type == DISABLED) cn = NULL;
  1260. X    if (strlen(arg0) > MAXPATHLEN) return NULL;
  1261. X    for (s = arg0; *s; s++)
  1262. X        if (*s == '/') {
  1263. X            try(arg0);
  1264. X            if (arg0 == s || unset(PATHDIRS)) {
  1265. X                return NULL;
  1266. X            }
  1267. X            break;
  1268. X        }
  1269. X    if (cn && ISEXCMD(cn->type)) {
  1270. X        for (pp = path; pp < cn->pcomp; pp++)
  1271. X            if (**pp != '/') {
  1272. X                z = buf;
  1273. X                strucpy(&z,*pp);
  1274. X                *z++ = '/';
  1275. X                strcpy(z,arg0);
  1276. X                try(buf);
  1277. X            }
  1278. X        try(cn->u.nam);
  1279. X    }
  1280. X    for (pp = path; *pp; pp++) {
  1281. X        z = buf;
  1282. X        strucpy(&z,*pp);
  1283. X        *z++ = '/';
  1284. X        strcpy(z,arg0);
  1285. X        try(buf);
  1286. X    }
  1287. X    return NULL;
  1288. X}
  1289. X
  1290. Xint iscom(s) /**/
  1291. Xchar *s;
  1292. X{
  1293. Xstruct stat statbuf;
  1294. X
  1295. X    return (access(s,X_OK) == 0 && stat(s,&statbuf) >= 0 &&
  1296. X            S_ISREG(statbuf.st_mode));
  1297. X}
  1298. X
  1299. Xint isrelative(s) /**/
  1300. Xchar *s;
  1301. X{
  1302. X    if (*s != '/') return 1;
  1303. X    for (; *s; s++)
  1304. X        if (*s == '.' && s[-1] == '/' &&
  1305. X            (s[1] == '/' || s[1] == '\0' ||
  1306. X                (s[1] == '.' && (s[2] == '/' || s[2] == '\0')))) return 1;
  1307. X    return 0;
  1308. X}
  1309. X
  1310. Xint hashcmd(arg0,pp) /**/
  1311. Xchar *arg0;char **pp;
  1312. X{
  1313. Xchar *s,buf[MAXPATHLEN];
  1314. Xchar **pq;
  1315. XDIR *dir;
  1316. Xstruct direct *de;
  1317. X
  1318. X    for (; *pp; pp++)
  1319. X        if (**pp == '/') {
  1320. X            s = buf;
  1321. X            strucpy(&s,*pp);
  1322. X            *s++ = '/';
  1323. X            strcpy(s,arg0);
  1324. X            if (iscom(buf)) break;
  1325. X        }
  1326. X    if (!*pp || isrelative(*pp)) return 0;
  1327. X    cn = (Cmdnam) zcalloc(sizeof *cn);
  1328. X    cn->type = EXCMD;
  1329. X    cn->pcomp = pp;
  1330. X    cn->u.nam = ztrdup(buf);
  1331. X    addhnode(ztrdup(arg0),cn,cmdnamtab,freecmdnam);
  1332. X    if (unset(HASHDIRS)) return 1;
  1333. X    for (pq = pathchecked; pq <= pp; pq++) {
  1334. X        if (isrelative(*pq) || !(dir = opendir(*pq))) continue;
  1335. X        readdir(dir); readdir(dir);
  1336. X        while (de = readdir(dir)) addhcmdnode(de->d_name,pq);
  1337. X        closedir(dir);
  1338. X    }
  1339. X    pathchecked = pp+1;
  1340. X    return 1;
  1341. X}
  1342. X
  1343. Xvoid fullhash() /**/
  1344. X{
  1345. Xchar **pq;
  1346. XDIR *dir;
  1347. Xstruct direct *de;
  1348. X
  1349. X    for (pq = pathchecked; *pq; pq++) {
  1350. X        if (isrelative(*pq) || !(dir = opendir(*pq))) continue;
  1351. X        readdir(dir); readdir(dir);
  1352. X        while (de = readdir(dir)) addhcmdnode(de->d_name,pq);
  1353. X        closedir(dir);
  1354. X    }
  1355. X    pathchecked = pq;
  1356. X}
  1357. X
  1358. Xvoid execlist(list) /**/
  1359. XList list;
  1360. X{
  1361. X    if (breaks) return;
  1362. X    if (!list) return;
  1363. X    simplifyright(list);
  1364. X    switch(list->type) {
  1365. X        case SYNC:
  1366. X        case ASYNC:
  1367. X            execlist2(list->left,list->type,!list->right);
  1368. X            if (sigtrapped[SIGDEBUG])
  1369. X                dotrap(SIGDEBUG);
  1370. X            if (sigtrapped[SIGERR] && lastval)
  1371. X                dotrap(SIGERR);
  1372. X            if (list->right && !retflag)
  1373. X                execlist(list->right);
  1374. X            break;
  1375. X    }
  1376. X}
  1377. X
  1378. Xvoid execlist2(list,type,last1) /**/
  1379. XSublist list;int type;int last1;
  1380. X{
  1381. X    if (!list) return;
  1382. X    switch(list->type) {
  1383. X        case END:
  1384. X            execpline(list,type,last1);
  1385. X            break;
  1386. X        case ORNEXT:
  1387. X            if (!execpline(list,SYNC,0)) execlist2(list->right,type,last1);
  1388. X            else while (list = list->right)
  1389. X                if (list->type == ANDNEXT) {
  1390. X                    execlist2(list->right,type,last1);
  1391. X                    return;
  1392. X                }
  1393. X            break;
  1394. X        case ANDNEXT:
  1395. X            if (execpline(list,SYNC,0)) execlist2(list->right,type,last1);
  1396. X            else while (list = list->right)
  1397. X                if (list->type == ORNEXT) {
  1398. X                    execlist2(list->right,type,last1);
  1399. X                    return;
  1400. X                }
  1401. X            break;
  1402. X    }
  1403. X}
  1404. X
  1405. Xint execpline(l,how,last1) /**/
  1406. XSublist l;int how;int last1;
  1407. X{
  1408. Xint ipipe[2],opipe[2];
  1409. X
  1410. X    if (!l) return 0;
  1411. X    ipipe[0] = ipipe[1] = opipe[0] = opipe[1] = 0;
  1412. X    blockchld();
  1413. X    if ((thisjob = getfreejob()) == -1)
  1414. X        return 1;
  1415. X    initjob();
  1416. X    if (how == TIMED) {
  1417. X        jobtab[thisjob].stat |= STAT_TIMED;
  1418. X        how = SYNC;
  1419. X    }
  1420. X    if (l->flags & PFLAG_COPROC) {
  1421. X        how = ASYNC;
  1422. X        if (coprocin >= 0) {
  1423. X            close(coprocin);
  1424. X            close(coprocout);
  1425. X        }
  1426. X        mpipe(ipipe);
  1427. X        mpipe(opipe);
  1428. X        coprocin = ipipe[0];
  1429. X        coprocout = opipe[1];
  1430. X    }
  1431. X    execpline2(l->left,how,opipe[0],ipipe[1],last1);
  1432. X    if (how == ASYNC) {
  1433. X        if (l->flags & PFLAG_COPROC) close(ipipe[1]);
  1434. X        spawnjob();
  1435. X        unblockchld();
  1436. X        return 1;
  1437. X    } else {
  1438. X        waitjobs();
  1439. X        unblockchld();
  1440. X        if (l->flags & PFLAG_NOT) lastval = !lastval;
  1441. X        return !lastval;
  1442. X    }
  1443. X}
  1444. X
  1445. Xvoid execpline2(pline,how,input,output,last1) /**/
  1446. XPline pline;int how;int input;int output;int last1;
  1447. X{
  1448. Xint pid;
  1449. Xint pipes[2];
  1450. X
  1451. X    if (breaks)
  1452. X        return;
  1453. X    if (!pline)
  1454. X        return;
  1455. X    if (pline->type == END) {
  1456. X        execcmd(pline->left,input,output,how==ASYNC,last1);
  1457. X        pline->left = NULL;
  1458. X    } else {
  1459. X        mpipe(pipes);
  1460. X        if (pline->left->type >= CURSH && how == SYNC) {
  1461. X
  1462. X            /* if we are doing "foo | bar" where foo is a current
  1463. X                shell command, do foo in a subshell and do
  1464. X                the rest of the pipeline in the current shell. */
  1465. X
  1466. X            if (!(pid = fork())) {
  1467. X                close(pipes[0]);
  1468. X                entersubsh(how==ASYNC);
  1469. X                exiting = 1;
  1470. X                execcmd(pline->left,input,pipes[1],how==ASYNC,0);
  1471. X                _exit(lastval);
  1472. X            } else if (pid == -1)
  1473. X                zerr("fork failed: %e",NULL,errno);
  1474. X            else {
  1475. X                char *text = getjobtext((vptr) pline->left);
  1476. X                addproc(pid,text);
  1477. X            }
  1478. X        } else {
  1479. X            /* otherwise just do the pipeline normally. */
  1480. X            execcmd(pline->left,input,pipes[1],how==ASYNC,0);
  1481. X        }
  1482. X        pline->left = NULL;
  1483. X        close(pipes[1]);
  1484. X        if (pline->right) {
  1485. X            execpline2(pline->right,how,pipes[0],output,last1);
  1486. X            close(pipes[0]);
  1487. X        }
  1488. X    }
  1489. X}
  1490. X
  1491. X/* make the argv array */
  1492. X
  1493. Xchar **makecline(list) /**/
  1494. Xstruct lklist *list;
  1495. X{
  1496. Xint ct = 0;
  1497. XLknode node;
  1498. Xchar **argv,**ptr;
  1499. X
  1500. X    if (isset(XTRACE)) {
  1501. X        fprintf(stderr,"%s",(prompt4) ? prompt4 : "");
  1502. X        for (node = firstnode(list); node; incnode(node),ct++);
  1503. X        ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
  1504. X        for (node = firstnode(list); node; incnode(node))
  1505. X            if (*(char *) getdata(node)) {
  1506. X                *ptr++ = getdata(node);
  1507. X                untokenize(getdata(node));
  1508. X                fputs(getdata(node),stderr);
  1509. X                if (nextnode(node))
  1510. X                    fputc(' ',stderr);
  1511. X            }
  1512. X        *ptr = NULL;
  1513. X        fputc('\n',stderr);
  1514. X        fflush(stderr);
  1515. X        return(argv);
  1516. X    } else {
  1517. X        for (node = firstnode(list); node; incnode(node),ct++);
  1518. X        ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
  1519. X        for (node = firstnode(list); node; incnode(node))
  1520. X            if (*(char *) getdata(node)) {
  1521. X                *ptr++ = getdata(node);
  1522. X                untokenize(getdata(node));
  1523. X            }
  1524. X        *ptr = NULL;
  1525. X        return(argv);
  1526. X    }
  1527. X}
  1528. X
  1529. X/* untokenize the command line and remove null arguments */
  1530. X
  1531. Xvoid fixcline(l) /**/
  1532. XLklist l;
  1533. X{
  1534. XLknode node,next;
  1535. X
  1536. X    for (node = firstnode(l); node; node = next) {
  1537. X        next = nextnode(node);
  1538. X        if (!*(char *) getdata(node)) uremnode(l,node);
  1539. X        else untokenize(getdata(node));
  1540. X    }
  1541. X}
  1542. X
  1543. Xvoid untokenize(s) /**/
  1544. Xchar *s;
  1545. X{
  1546. X    for (; *s; s++)
  1547. X        if (itok(*s))
  1548. X            if (*s == Nularg) chuck(s--);
  1549. X            else *s = ztokens[*s-Pound];
  1550. X}
  1551. X
  1552. X/* nonzero if we shouldn't clobber a file */
  1553. X
  1554. Xint dontclob(f) /**/
  1555. Xstruct redir *f;
  1556. X{
  1557. Xstruct stat buf;
  1558. X
  1559. X    if (unset(NOCLOBBER) || f->type & 1) return 0;
  1560. X    if (stat(f->name,&buf) == -1) return 1;
  1561. X    return S_ISREG(buf.st_mode);
  1562. X}
  1563. X
  1564. X/* close an multio (success) */
  1565. X
  1566. Xvoid closemn(mfds,fd) /**/
  1567. Xstruct multio **mfds;int fd;
  1568. X{
  1569. X    if (mfds[fd]) {
  1570. X        if (mfds[fd]->ct > 1)
  1571. X            if (mfds[fd]->rflag == 0)
  1572. X                catproc(mfds[fd]);
  1573. X            else
  1574. X                teeproc(mfds[fd]);
  1575. X        mfds[fd] = NULL;
  1576. X    }
  1577. X}
  1578. X
  1579. X/* close all the mnodes (failure) */
  1580. X
  1581. Xvoid closemnodes(mfds) /**/
  1582. Xstruct multio **mfds;
  1583. X{
  1584. Xint t0,t1;
  1585. X
  1586. X    for (t0 = 0; t0 != 10; t0++)
  1587. X        if (mfds[t0]) {
  1588. X            for (t1 = 0; t1 != mfds[t0]->ct; t1++)
  1589. X                close(mfds[t0]->fds[t1]);
  1590. X            mfds[t0] = NULL;
  1591. X        }
  1592. X}
  1593. X
  1594. X/* add a fd to an multio */
  1595. X/* an multio is a list of fds associated with a certain fd.
  1596. X    thus if you do "foo >bar >ble", the multio for fd 1 will have
  1597. X    two fds, the result of open("bar",...), and the result of
  1598. X    open("ble",....). */
  1599. X
  1600. Xvoid addfd(forked,save,mfds,fd1,fd2,rflag) /**/
  1601. Xint forked;int *save;struct multio **mfds;int fd1;int fd2;int rflag;
  1602. X{
  1603. Xint pipes[2];
  1604. X
  1605. X    if (!mfds[fd1]) {    /* starting a new multio */
  1606. X        mfds[fd1] = (struct multio *) alloc(sizeof(struct multio));
  1607. X        if (!forked && fd1 != fd2 && fd1 < 10)
  1608. X            save[fd1] = movefd(fd1);
  1609. X        redup(fd2,fd1);
  1610. X        mfds[fd1]->ct = 1;
  1611. X        mfds[fd1]->fds[0] = fd1;
  1612. X        mfds[fd1]->rflag = rflag;
  1613. X    } else {
  1614. X        if (mfds[fd1]->rflag != rflag) {
  1615. X            zerr("file mode mismatch on fd %d",NULL,fd1);
  1616. X            return;
  1617. X        }
  1618. X        if (mfds[fd1]->ct == 1) {        /* split the stream */
  1619. X            mfds[fd1]->fds[0] = movefd(fd1);
  1620. X            mfds[fd1]->fds[1] = movefd(fd2);
  1621. X            mpipe(pipes);
  1622. X            mfds[fd1]->pipe = pipes[1-rflag];
  1623. X            redup(pipes[rflag],fd1);
  1624. X            mfds[fd1]->ct = 2;
  1625. X        } else        /* add another fd to an already split stream */
  1626. X            mfds[fd1]->fds[mfds[fd1]->ct++] = movefd(fd2);
  1627. X    }
  1628. X}
  1629. X
  1630. Xvoid addvars(l,export) /**/
  1631. XLklist l;int export;
  1632. X{
  1633. Xstruct varasg *v;
  1634. XLklist vl;
  1635. X
  1636. X    while (full(l)) {
  1637. X        char **arr,**ptr;
  1638. X
  1639. X        v = (struct varasg *) ugetnode(l);
  1640. X        singsub(&v->name);
  1641. X        if (errflag)
  1642. X            return;
  1643. X        untokenize(v->name);
  1644. X        if (v->type == PMFLAG_s) {
  1645. X            vl = newlist();
  1646. X            addnode(vl,v->str);
  1647. X        } else
  1648. X            vl = v->arr;
  1649. X        prefork(vl);
  1650. X        if (errflag)
  1651. X            return;
  1652. X        postfork(vl,1);
  1653. X        if (errflag)
  1654. X            return;
  1655. X        if (v->type == PMFLAG_s && (!full(vl) || !nextnode(firstnode(vl)))) {
  1656. X            Param pm;
  1657. X            char *val;
  1658. X
  1659. X            if (!full(vl))
  1660. X                pm = setsparam(v->name,val = ztrdup(""));
  1661. X            else {
  1662. X                untokenize(peekfirst(vl));
  1663. X                pm = setsparam(v->name,val = ztrdup(ugetnode(vl)));
  1664. X            }
  1665. X            if (export && !(pm->flags & PMFLAG_x))
  1666. X                addenv(v->name,val);
  1667. X            continue;
  1668. X        }
  1669. X        ptr = arr = (char **) zalloc(sizeof(char **)*(countnodes(vl)+1));
  1670. X        while (full(vl)) {
  1671. X            char *pp;
  1672. X            pp = ugetnode(vl);
  1673. X            if (*pp) {
  1674. X                *ptr = ztrdup(pp);
  1675. X                untokenize(*ptr++);
  1676. X            }
  1677. X        }
  1678. X        *ptr = NULL;
  1679. X        setaparam(v->name,arr);
  1680. X    }
  1681. X}
  1682. X
  1683. Xvoid execcmd(cmd,input,output,bkg,last1) /**/
  1684. XCmd cmd;int input;int output;int bkg;int last1;
  1685. X{
  1686. Xint type;
  1687. Xlong pid = 0;
  1688. Xint save[10],t0;
  1689. Xstruct redir *fn;
  1690. Xstruct multio *mfds[10];
  1691. Xint fil,forked = 0,iscursh = 0,nullexec = 0;
  1692. Xchar *text;
  1693. X
  1694. X    args = cmd->args;
  1695. X    cn = NULL;
  1696. X    for (t0 = 0; t0 != 10; t0++) {
  1697. X        save[t0] = 0;
  1698. X        mfds[t0] = NULL;
  1699. X    }
  1700. X    if ((type = cmd->type) == SIMPLE && !full(args))
  1701. X        if (full(cmd->redir))
  1702. X            if (cmd->flags & CFLAG_EXEC) {
  1703. X                nullexec = 1;
  1704. X            } else if (!*nullcmd) {
  1705. X                zerr("redirection with no command",NULL,0);
  1706. X                errflag = lastval = 1;
  1707. X                return;
  1708. X            } else if (*readnullcmd &&
  1709. X                    ((Redir)peekfirst(cmd->redir))->type == READ &&
  1710. X                    !nextnode(firstnode(cmd->redir))) {
  1711. X                addnode(args,strdup(readnullcmd));
  1712. X            } else
  1713. X                addnode(args,strdup(nullcmd));
  1714. X        else {
  1715. X            addvars(cmd->vars,0);
  1716. X            return;
  1717. X        }
  1718. X    if (full(args) && *(char *) peekfirst(args) == '%') {
  1719. X        insnode(args,(Lknode) args,strdup((bkg) ? "bg" : "fg"));
  1720. X        bkg = 0;
  1721. X    }
  1722. X    if (isset(AUTORESUME) && !bkg && !full(cmd->redir) && full(args) &&
  1723. X            !input && type == SIMPLE && !nextnode(firstnode(args))) {
  1724. X        if (unset(NOTIFY)) scanjobs();
  1725. X        if (findjobnam(peekfirst(args)) != -1)
  1726. X            pushnode(args,strdup("fg"));
  1727. X    }
  1728. X    if (unset(RMSTARSILENT) && interact && isset(SHINSTDIN) &&
  1729. X                type == SIMPLE && full(args) && nextnode(firstnode(args)) &&
  1730. X                !strcmp(peekfirst(args),"rm")) {
  1731. X            char *s = getdata(nextnode(firstnode(args)));
  1732. X            int l = strlen(s);
  1733. X
  1734. X            if (s[0] == Star && !s[1])
  1735. X                checkrmall(pwd);
  1736. X            else if (l > 2 && s[l-2] == '/' && s[l-1] == Star) {
  1737. X                char t = s[l-2];
  1738. X                s[l-2] = 0;
  1739. X                checkrmall(s);
  1740. X                s[l-2] = t;
  1741. X            }
  1742. X    }
  1743. X    if (jobbing) {    /* get the text associated with this command */
  1744. X        char *s;
  1745. X        s = text = getjobtext((vptr) cmd);
  1746. X    } else text = NULL;
  1747. X    prefork(args);    /* do prefork substitutions */
  1748. X    if (errflag) {
  1749. X        lastval = 1;
  1750. X        return;
  1751. X    }
  1752. X    if (full(args) && ((char*)peekfirst(args))[0] == Inbrack &&
  1753. X            ((char*)peekfirst(args))[1] == '\0')
  1754. X        ((char*)peekfirst(args))[0] = '[';
  1755. X    if (type == SIMPLE && full(args) && !(cmd->flags & CFLAG_COMMAND)) {
  1756. X        char *s,*t;
  1757. X        cn = (Cmdnam) gethnode(t = s = peekfirst(args),cmdnamtab);
  1758. X        if (!cn && isset(HASHCMDS) && strcmp(t,"..")) {
  1759. X            while (*t && *t != '/') t++;
  1760. X            if (!*t) hashcmd(s,pathchecked);
  1761. X        }
  1762. X    }
  1763. X    if (type == SIMPLE && !cn && isset(AUTOCD) && isset(SHINSTDIN) &&
  1764. X            full(args) && !full(cmd->redir) &&
  1765. X            !nextnode(firstnode(args)) && cancd(peekfirst(args))) {
  1766. X        pushnode(args,strdup("cd"));
  1767. X        cn = (Cmdnam) gethnode("cd",cmdnamtab);
  1768. X    }
  1769. X
  1770. X    /* this is nonzero if cmd is a current shell procedure */
  1771. X
  1772. X    iscursh = (type >= CURSH) || (type == SIMPLE && cn &&
  1773. X        (cn->type == BUILTIN || cn->type == SHFUNC));
  1774. X
  1775. X    /* if this command is backgrounded or (this is an external
  1776. X        command and we are not exec'ing it) or this is a builtin
  1777. X        with output piped somewhere, then fork.  If this is the
  1778. X        last stage in a subshell pipeline, don't fork, but make
  1779. X        the rest of the function think we forked. */
  1780. X
  1781. X    if (bkg || !(iscursh || (cmd->flags & CFLAG_EXEC)) ||
  1782. X            (cn && (cn->type == BUILTIN || cn->type == SHFUNC) && output)) {
  1783. X        int synch[2];
  1784. X
  1785. X        pipe(synch);
  1786. X        pid = (last1 && execok()) ? 0 : phork();
  1787. X        if (pid == -1) {
  1788. X            close(synch[0]);
  1789. X            close(synch[1]);
  1790. X            return;
  1791. X        }
  1792. X        if (pid) {
  1793. X            close(synch[1]);
  1794. X            read(synch[0],"foo",1);
  1795. X            close(synch[0]);
  1796. X            if (pid == -1)
  1797. X                zerr("%e",NULL,errno);
  1798. X            else {
  1799. X                if (bkg) lastpid = pid;
  1800. X                ( void ) addproc(pid,text);
  1801. X            }
  1802. X            return;
  1803. X        }
  1804. X        close(synch[0]);
  1805. X        entersubsh(bkg);
  1806. X        close(synch[1]);
  1807. X        forked = 1;
  1808. X    }
  1809. X    if (bkg && isset(BGNICE))
  1810. X        nice(5);
  1811. X
  1812. X    /* perform postfork substitutions */
  1813. X    postfork(args,!(cmd->flags & CFLAG_NOGLOB));
  1814. X    if (errflag) {
  1815. X        lastval = 1;
  1816. X        goto err;
  1817. X    } else {
  1818. X        char *s;
  1819. X        while (full(args) && (s = peekfirst(args)) && !*s) ugetnode(args);
  1820. X    }
  1821. X
  1822. X    if (input)        /* add pipeline input/output to mnodes */
  1823. X        addfd(forked,save,mfds,0,input,0);
  1824. X    if (output)
  1825. X        addfd(forked,save,mfds,1,output,1);
  1826. X    spawnpipes(cmd->redir);        /* do process substitutions */
  1827. X    while (full(cmd->redir))
  1828. X        if ((fn = (struct redir*) ugetnode(cmd->redir))->type == INPIPE) {
  1829. X            if (fn->fd2 == -1)
  1830. X                execerr();
  1831. X            addfd(forked,save,mfds,fn->fd1,fn->fd2,0);
  1832. X        } else if (fn->type == OUTPIPE) {
  1833. X            if (fn->fd2 == -1)
  1834. X                execerr();
  1835. X            addfd(forked,save,mfds,fn->fd1,fn->fd2,1);
  1836. X        } else {
  1837. X            if (!(fn->type == HERESTR || fn->type == CLOSE || fn->type ==
  1838. X                    MERGE || fn->type == MERGEOUT))
  1839. X                if (xpandredir(fn,cmd->redir))
  1840. X                    continue;
  1841. X            if (errflag) execerr();
  1842. X            if (fn->type == HERESTR) {
  1843. X                fil = getherestr(fn);
  1844. X                if (fil == -1) {
  1845. X                    if (errno != EINTR)
  1846. X                        zerr("%e",NULL,errno);
  1847. X                    execerr();
  1848. X                }
  1849. X                addfd(forked,save,mfds,fn->fd1,fil,0);
  1850. X            } else if (fn->type == READ) {
  1851. X                fil = open(fn->name,O_RDONLY);
  1852. X                if (fil == -1) {
  1853. X                    if (errno != EINTR)
  1854. X                        zerr("%e: %s",fn->name,errno);
  1855. X                    execerr();
  1856. X                }
  1857. X                addfd(forked,save,mfds,fn->fd1,fil,0);
  1858. X            } else if (fn->type == CLOSE) {
  1859. X                if (!forked && fn->fd1 < 10)
  1860. X                    save[fn->fd1] = movefd(fn->fd1);
  1861. X                closemn(mfds,fn->fd1);
  1862. X                close(fn->fd1);
  1863. X            } else if (fn->type == MERGE || fn->type == MERGEOUT) {
  1864. X                if (fn->fd2 == FD_COPROC)
  1865. X                    fn->fd2 = (fn->type == MERGEOUT) ? coprocout : coprocin;
  1866. X                if (!forked && fn->fd1 < 10)
  1867. X                    save[fn->fd1] = movefd(fn->fd1);
  1868. X                closemn(mfds,fn->fd1);
  1869. X                fil = dup(fn->fd2);
  1870. X                addfd(forked,save,mfds,fn->fd1,fil,fn->type == MERGEOUT);
  1871. X            } else {
  1872. X                if (fn->type >= APP)
  1873. X                    fil = open(fn->name,
  1874. X                        (isset(NOCLOBBER) && !(fn->type & 1)) ?
  1875. X                        O_WRONLY|O_APPEND : O_WRONLY|O_APPEND|O_CREAT,0666);
  1876. X                else
  1877. X                    fil = open(fn->name,dontclob(fn) ? 
  1878. X                        O_WRONLY|O_CREAT|O_EXCL : O_WRONLY|O_CREAT|O_TRUNC,0666);
  1879. X                if (fil == -1) {
  1880. X                    if (errno != EINTR)
  1881. X                        zerr("%e: %s",fn->name,errno);
  1882. X                    execerr();
  1883. X                }
  1884. X                addfd(forked,save,mfds,fn->fd1,fil,1);
  1885. X            }
  1886. X        }
  1887. X    
  1888. X    /* we are done with redirection.  close the mnodes, spawning
  1889. X        tee/cat processes as necessary. */
  1890. X    for (t0 = 0; t0 != 10; t0++)
  1891. X        closemn(mfds,t0);
  1892. X
  1893. X    if (nullexec)
  1894. X        return;
  1895. X    if (unset(NOEXEC))
  1896. X        if (type >= CURSH)
  1897. X            {
  1898. X            static int (*func[]) DCLPROTO((Cmd)) = {
  1899. X                execcursh,exectime,execfuncdef,execfor,execwhile,
  1900. X                execrepeat,execif,execcase,execselect,execcond };
  1901. X    
  1902. X            fixcline(args);
  1903. X            lastval = (func[type-CURSH])(cmd);
  1904. X            }
  1905. X        else if (iscursh)        /* builtin or shell function */
  1906. X            {
  1907. X            if (cmd->vars)
  1908. X                addvars(cmd->vars,0);
  1909. X            fixcline(args);
  1910. X            if (cn && cn->type == SHFUNC)
  1911. X                execshfunc(cmd,cn);
  1912. X            else
  1913. X                {
  1914. X                if (forked) closem();
  1915. X                lastval = execbin(args,cn);
  1916. X                if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
  1917. X                        lastval && !subsh) {
  1918. X                    fprintf(stderr,"zsh: exit %d\n",lastval);
  1919. X                }
  1920. X                fflush(stdout);
  1921. X                if (ferror(stdout))
  1922. X                    {
  1923. X                    zerr("write error: %e",NULL,errno);
  1924. X                    clearerr(stdout);
  1925. X                    }
  1926. X                }
  1927. X            }
  1928. X        else
  1929. X            {
  1930. X            if (cmd->vars)
  1931. X                addvars(cmd->vars,1);
  1932. X            if (type == SIMPLE)
  1933. X                {
  1934. X                closem();
  1935. X                execute(cmd->flags & CFLAG_DASH);
  1936. X                }
  1937. X            else    /* ( ... ) */
  1938. X                execlist(cmd->u.list);
  1939. X            }
  1940. Xerr:
  1941. X    if (forked)
  1942. X        _exit(lastval);
  1943. X    fixfds(save);
  1944. X}
  1945. X
  1946. X/* restore fds after redirecting a builtin */
  1947. X
  1948. Xvoid fixfds(save) /**/
  1949. Xint *save;
  1950. X{
  1951. Xint t0;
  1952. X
  1953. X    for (t0 = 0; t0 != 10; t0++)
  1954. X        if (save[t0])
  1955. X            redup(save[t0],t0);
  1956. X}
  1957. X
  1958. Xvoid entersubsh(bkg) /**/
  1959. Xint bkg;
  1960. X{
  1961. X    if (!jobbing)
  1962. X        {
  1963. X        if (bkg && isatty(0))
  1964. X            {
  1965. X            close(0);
  1966. X            if (open("/dev/null",O_RDWR))
  1967. X                {
  1968. X                zerr("can't open /dev/null: %e",NULL,errno);
  1969. X                _exit(1);
  1970. X                }
  1971. X            }
  1972. X        }
  1973. X    else if (!jobtab[thisjob].gleader)
  1974. X        {
  1975. X        jobtab[thisjob].gleader = getpid();
  1976. X        setpgrp(0L,jobtab[thisjob].gleader);
  1977. X        if (!bkg)
  1978. X            attachtty(jobtab[thisjob].gleader);
  1979. X        }
  1980. X    else
  1981. X        setpgrp(0L,jobtab[thisjob].gleader);
  1982. X    subsh = 1;
  1983. X    if (SHTTY != -1)
  1984. X        {
  1985. X        close(SHTTY);
  1986. X        SHTTY = -1;
  1987. X        }
  1988. X    if (jobbing)
  1989. X        {
  1990. X        signal(SIGTTOU,SIG_DFL);
  1991. X        signal(SIGTTIN,SIG_DFL);
  1992. X        signal(SIGTSTP,SIG_DFL);
  1993. X        signal(SIGPIPE,SIG_DFL);
  1994. X        }
  1995. X    if (interact)
  1996. X        {
  1997. X        signal(SIGTERM,SIG_DFL);
  1998. X        if (sigtrapped[SIGINT])
  1999. X            signal(SIGINT,SIG_IGN);
  2000. X        }
  2001. X    if (!sigtrapped[SIGQUIT])
  2002. X        signal(SIGQUIT,SIG_DFL);
  2003. X    opts[MONITOR] = OPT_UNSET;
  2004. X    clearjobtab();
  2005. X}
  2006. X
  2007. X/* close all internal shell fds */
  2008. X
  2009. Xvoid closem() /**/
  2010. X{
  2011. Xint t0;
  2012. X
  2013. X    for (t0 = 10; t0 != NOFILE; t0++)
  2014. X        close(t0);
  2015. X}
  2016. X
  2017. X/* convert here document into a here string */
  2018. X
  2019. Xchar *gethere(str,typ) /**/
  2020. Xchar *str;int typ;
  2021. X{
  2022. Xchar pbuf[256];
  2023. Xint qt = 0,siz = 0,l,strip = 0;
  2024. Xchar *s,*t,*bptr;
  2025. X
  2026. X    for (s = str; *s; s++)
  2027. X        if (*s == Nularg)
  2028. X            qt = 1;
  2029. X    untokenize(str);
  2030. X    if (typ == HEREDOCDASH)
  2031. X        {
  2032. X        strip = 1;
  2033. X        while (*str == '\t')
  2034. X            str++;
  2035. X        }
  2036. X    t = ztrdup("");
  2037. X    for(;;)
  2038. X        {
  2039. X        char *u,*v;
  2040. X
  2041. X        if (!hgets(pbuf,256))
  2042. X            break;
  2043. X        bptr = pbuf;
  2044. X        if (strip)
  2045. X            while (*bptr == '\t')
  2046. X                bptr++;
  2047. X        for (u = bptr, v = str; *u != '\n' && *v; u++,v++)
  2048. X            if (*u != *v)
  2049. X                break;
  2050. X        if (!(*u == '\n' && !*v))
  2051. X            {
  2052. X            l = strlen(bptr);
  2053. X            if (!qt && l > 1 && bptr[l-1] == '\n' && bptr[l-2] == '\\')
  2054. X                bptr[l -= 2] = '\0';
  2055. X            t = realloc(t,siz+l+1);
  2056. X            strncpy(t+siz,bptr,l);
  2057. X            siz += l;
  2058. X            }
  2059. X        else
  2060. X            break;
  2061. X        }
  2062. X    t[siz] = '\0';
  2063. X    if (siz && t[siz-1] == '\n')
  2064. X        t[siz-1] = '\0';
  2065. X    if (!qt)
  2066. X        for (s = t; *s; s++)
  2067. X            if (*s == '$') {
  2068. X                *s = Qstring;
  2069. X            } else if (*s == '`') {
  2070. X                *s = Qtick;
  2071. X            } else if (*s == '(') {
  2072. X                *s = Inpar;
  2073. X            } else if (*s == ')') {
  2074. X                *s = Outpar;
  2075. X            } else if (*s == '\\' &&
  2076. X                (s[1] == '$' || s[1] == '`')) chuck(s);
  2077. X    s = strdup(t);
  2078. X    free(t);
  2079. X    return s;
  2080. X}
  2081. X
  2082. X/* open here string fd */
  2083. X
  2084. Xint getherestr(fn) /**/
  2085. Xstruct redir *fn;
  2086. X{
  2087. XLklist fake;
  2088. Xchar *s = gettemp(),*t;
  2089. Xint fd;
  2090. X
  2091. X    fake = newlist();
  2092. X    addnode(fake,fn->name);
  2093. X    prefork(fake);
  2094. X    if (!errflag)
  2095. X        postfork(fake,1);
  2096. X    if (errflag)
  2097. X        return -1;
  2098. X    if ((fd = open(s,O_CREAT|O_WRONLY,0600)) == -1)
  2099. X        return -1;
  2100. X    while (t = ugetnode(fake))
  2101. X        {
  2102. X        untokenize(t);
  2103. X        write(fd,t,strlen(t));
  2104. X        if (full(fake))
  2105. X            write(fd," ",1);
  2106. X        }
  2107. X    write(fd,"\n",1);
  2108. X    close(fd);
  2109. X    fd = open(s,O_RDONLY);
  2110. X    unlink(s);
  2111. X    return fd;
  2112. X}
  2113. X
  2114. Xvoid catproc(mn) /**/
  2115. Xstruct multio *mn;
  2116. X{
  2117. Xint len,t0;
  2118. Xchar *buf;
  2119. X
  2120. X    if (phork())
  2121. X        {
  2122. X        for (t0 = 0; t0 != mn->ct; t0++)
  2123. X            close(mn->fds[t0]);
  2124. X        close(mn->pipe);
  2125. X        return;
  2126. X        }
  2127. X    closeallelse(mn);
  2128. X    buf = zalloc(4096);
  2129. X    for (t0 = 0; t0 != mn->ct; t0++)
  2130. X        while (len = read(mn->fds[t0],buf,4096))
  2131. X            write(mn->pipe,buf,len);
  2132. X    _exit(0);
  2133. X}
  2134. Xvoid teeproc(mn) /**/
  2135. Xstruct multio *mn;
  2136. X{
  2137. Xint len,t0;
  2138. Xchar *buf;
  2139. X
  2140. X    if (phork())
  2141. X        {
  2142. X        for (t0 = 0; t0 != mn->ct; t0++)
  2143. X            close(mn->fds[t0]);
  2144. X        close(mn->pipe);
  2145. X        return;
  2146. X        }
  2147. X    buf = zalloc(4096);
  2148. X    closeallelse(mn);
  2149. X    while ((len = read(mn->pipe,buf,4096)) > 0)
  2150. X        for (t0 = 0; t0 != mn->ct; t0++)
  2151. X            write(mn->fds[t0],buf,len);
  2152. X    _exit(0);
  2153. X}
  2154. X
  2155. Xvoid closeallelse(mn) /**/
  2156. Xstruct multio *mn;
  2157. X{
  2158. Xint t0,t1;
  2159. X
  2160. X    for (t0 = 0; t0 != NOFILE; t0++)
  2161. X        if (mn->pipe != t0)
  2162. X            {
  2163. X            for (t1 = 0; t1 != mn->ct; t1++)
  2164. X                if (mn->fds[t1] == t0)
  2165. X                    break;
  2166. X            if (t1 == mn->ct)
  2167. X                close(t0);
  2168. X            }
  2169. X}
  2170. X
  2171. Xlong int zstrtol(s,t,base) /**/
  2172. Xchar *s;char **t;int base;
  2173. X{
  2174. Xint ret = 0;
  2175. X
  2176. X    if (base <= 10)
  2177. X        for (; *s >= '0' && *s < ('0'+base); s++)
  2178. X            ret = ret*base+*s-'0';
  2179. X    else
  2180. X        for (; idigit(*s) || (*s >= 'a' && *s < ('a'+base-10))
  2181. X                                || (*s >= 'A' && *s < ('A'+base-10)); s++)
  2182. X            ret = ret*base+(idigit(*s) ? (*s-'0') : (*s & 0x1f)+9);
  2183. X    if (t)
  2184. X        *t = (char *) s;
  2185. X    return ret;
  2186. X}
  2187. X
  2188. X/* $(...) */
  2189. X
  2190. XLklist getoutput(cmd,qt) /**/
  2191. Xchar *cmd;int qt;
  2192. X{
  2193. XList list;
  2194. Xint pipes[2];
  2195. X
  2196. X    if (*cmd == '<') {
  2197. X        int stream;
  2198. X        char *fi,*s,x;
  2199. X
  2200. X        for (cmd++; *cmd == ' '; cmd++);
  2201. X        for (s = cmd; *s && *s != ' '; s++)
  2202. X            if (*s == '\\') s++;
  2203. X            else if (*s == '$') *s = String;
  2204. X        x = *s;
  2205. X        *s = '\0';
  2206. X        fi = strdup(cmd);
  2207. X        *s = x;
  2208. X        if (*fi == '~')
  2209. X            *fi = Tilde;
  2210. X        else if (*fi == '=')
  2211. X            *fi = Equals;
  2212. X        singsub(&fi);
  2213. X        if (errflag)
  2214. X            return NULL;
  2215. X        stream = open(fi,O_RDONLY);
  2216. X        if (stream == -1) {
  2217. X            zerr("%e: %s",fi,errno);
  2218. X            return NULL;
  2219. X        }
  2220. X        return readoutput(stream,qt);
  2221. X    }
  2222. X    if (!(list = parselstring(cmd)))
  2223. X        return NULL;
  2224. X    mpipe(pipes);
  2225. X    if (phork())
  2226. X        {
  2227. X        popheap();
  2228. X        close(pipes[1]);
  2229. X        /* chldsuspend(); */
  2230. X        return readoutput(pipes[0],qt);
  2231. X        }
  2232. X    subsh = 1;
  2233. X    close(pipes[0]);
  2234. X    redup(pipes[1],1);
  2235. X    entersubsh(0);
  2236. X    signal(SIGTSTP,SIG_IGN);
  2237. X    exiting = 1;
  2238. X    execlist(list);
  2239. X    close(1);
  2240. X    exit(0);  return NULL;
  2241. X}
  2242. X
  2243. X/* read output of command substitution */
  2244. X
  2245. XLklist readoutput(in,qt) /**/
  2246. Xint in;int qt;
  2247. X{
  2248. XLklist ret;
  2249. Xchar *buf,*ptr;
  2250. Xint bsiz,c,cnt = 0;
  2251. XFILE *fin;
  2252. X
  2253. X    fin = fdopen(in,"r");
  2254. X    ret = newlist();
  2255. X    ptr = buf = ncalloc(bsiz = 64);
  2256. X    while ((c = fgetc(fin)) != EOF)
  2257. X        if (!qt && isep(c)) {
  2258. X            if (cnt) {
  2259. X                *ptr = '\0';
  2260. X                addnode(ret,buf);
  2261. X                ptr = buf = ncalloc(bsiz = 64);
  2262. X                cnt = 0;
  2263. SHAR_EOF
  2264. true || echo 'restore of zsh2.2/src/exec.c failed'
  2265. fi
  2266. echo 'End of zsh2.2 part 7'
  2267. echo 'File zsh2.2/src/exec.c is continued in part 8'
  2268. echo 8 > _shar_seq_.tmp
  2269. exit 0
  2270.  
  2271. exit 0 # Just in case...
  2272.