home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume35 / zsh / part11 < prev    next >
Text File  |  1993-02-20  |  57KB  |  2,518 lines

  1. Newsgroups: comp.sources.misc
  2. From: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
  3. Subject: v35i061:  zsh - The Z Shell, version 2.3.1, Part11/22
  4. Message-ID: <1993Feb20.212421.28812@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4295def6480eba2e83756ba2e6fc71cc
  6. Date: Sat, 20 Feb 1993 21:24:21 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
  10. Posting-number: Volume 35, Issue 61
  11. Archive-name: zsh/part11
  12. Environment: UNIX
  13. Supersedes: zsh2.2: Volume 29, Issue 97-113
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  src/jobs.c src/zsh.h
  22. # Wrapped by mattson@odin on Sat Feb  6 14:41:53 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 11 (of 22)."'
  26. if test -f 'src/jobs.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'src/jobs.c'\"
  28. else
  29.   echo shar: Extracting \"'src/jobs.c'\" \(17010 characters\)
  30.   sed "s/^X//" >'src/jobs.c' <<'END_OF_FILE'
  31. X/*
  32. X *
  33. X * jobs.c - job control
  34. X *
  35. X * This file is part of zsh, the Z shell.
  36. X *
  37. X * This software is Copyright 1992 by Paul Falstad
  38. X *
  39. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  40. X * use this software as long as: there is no monetary profit gained
  41. X * specifically from the use or reproduction of this software, it is not
  42. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  43. X * included prominently in any copy made. 
  44. X *
  45. X * The author make no claims as to the fitness or correctness of this software
  46. X * for any use whatsoever, and it is provided as is. Any use of this software
  47. X * is at the user's own risk. 
  48. X *
  49. X */
  50. X
  51. X#include "zsh.h"
  52. X#include <sys/errno.h>
  53. X
  54. X/* empty job structure for quick clearing of jobtab entries */
  55. X
  56. Xstatic struct job zero = {
  57. X    0L, 0, (char *)NULL, (struct process *) NULL, (Lklist) NULL
  58. X};
  59. X
  60. X#ifdef INTHANDTYPE
  61. X#define RETURN return 0
  62. X#else
  63. X#define RETURN return
  64. X#endif
  65. X
  66. X/* the signal handler */
  67. X
  68. XHANDTYPE handler(sig) /**/
  69. Xint sig;
  70. X{
  71. Xlong pid;
  72. Xint statusp;
  73. XJob jn;
  74. Xstruct process *pn;
  75. X#ifdef HAS_RUSAGE
  76. Xstruct rusage ru;
  77. X#else
  78. Xlong chlds,chldu;
  79. X#endif
  80. X
  81. X#ifdef RESETHANDNEEDED
  82. X    signal(sig,handler);
  83. X#endif
  84. X    if (sig == SIGHUP)
  85. X        {
  86. X        if (sigtrapped[SIGHUP])
  87. X            dotrap(SIGHUP);
  88. X        else
  89. X            {
  90. X            stopmsg = 1;
  91. X            zexit(SIGHUP);
  92. X            }
  93. X        }
  94. X    if (sig == SIGINT)
  95. X        {
  96. X        if (sigtrapped[SIGINT])
  97. X            dotrap(SIGINT);
  98. X        else
  99. X            {
  100. X            breaks = loops;
  101. X            errflag = 1;
  102. X            }
  103. X        RETURN;
  104. X        }
  105. X#ifdef SIGWINCH
  106. X    if (sig == SIGWINCH)
  107. X        adjustwinsize();
  108. X#endif
  109. X    if (sig != SIGCHLD)
  110. X        {
  111. X        dotrap(sig);
  112. X        if (sig == SIGALRM)
  113. X            {
  114. X            if (!sigtrapped[SIGALRM])
  115. X                {
  116. X                zerr("timeout",NULL,0);
  117. X                exit(1);
  118. X                }
  119. X            else if (tmout)
  120. X                {
  121. X                alarm(tmout);
  122. X                }
  123. X            }
  124. X        RETURN;
  125. X        }
  126. X    for (;;)
  127. X        {
  128. X#ifdef HAS_RUSAGE
  129. X        pid = wait3((vptr) &statusp,WNOHANG|WUNTRACED,&ru);
  130. X#else
  131. X#ifndef WNOHANG
  132. X        pid = wait(&statusp);
  133. X#else
  134. X#ifdef WAITPID
  135. X        pid = waitpid(-1,(vptr) &statusp,WNOHANG|WUNTRACED);
  136. X#else
  137. X        pid = wait3((vptr) &statusp,WNOHANG|WUNTRACED,NULL);
  138. X#endif
  139. X#endif
  140. X        chlds = shtms.tms_cstime;
  141. X        chldu = shtms.tms_cutime;
  142. X        times(&shtms);
  143. X#endif
  144. X        if (pid == -1)
  145. X            {
  146. X            if (errno != ECHILD)
  147. X                zerr("wait failed: %e",NULL,errno);
  148. X            RETURN;
  149. X            }
  150. X        if (!pid)
  151. X            RETURN;
  152. X        if (pid == cmdoutpid) {
  153. X            cmdoutpid = 0;
  154. X            if (WIFSIGNALED(statusp))
  155. X                {
  156. X                cmdoutval = (0200 | WTERMSIG(statusp));
  157. X                if (WTERMSIG(statusp) == SIGINT)
  158. X                    (void) kill(getpid(),SIGINT);
  159. X                else if (sigtrapped[WTERMSIG(statusp)])
  160. X                    dotrap(WTERMSIG(statusp));
  161. X                }
  162. X            else
  163. X                cmdoutval = WEXITSTATUS(statusp);
  164. X            RETURN;
  165. X        }
  166. X        findproc(pid,&jn,&pn);    /* find the process of this pid */
  167. X        if (jn)
  168. X            {
  169. X            pn->statusp = statusp;
  170. X#ifdef HAS_RUSAGE
  171. X            pn->ti.ru = ru;
  172. X#else
  173. X            pn->ti.st = shtms.tms_cstime-chlds;
  174. X            pn->ti.ut = shtms.tms_cutime-chldu;
  175. X#endif
  176. X            pn->endtime = time(NULL);
  177. X            updatestatus(jn);
  178. X            }
  179. X#if 0
  180. X        else if (WIFSTOPPED(statusp))
  181. X            kill(pid,SIGKILL);    /* kill stopped untraced children */
  182. X#endif
  183. X        }
  184. X}
  185. X
  186. X/* change job table entry from stopped to running */
  187. X
  188. Xvoid makerunning(jn) /**/
  189. XJob jn;
  190. X{
  191. Xstruct process *pn;
  192. X
  193. X    jn->stat &= ~STAT_STOPPED;
  194. X    for (pn = jn->procs; pn; pn = pn->next)
  195. X        if (WIFSTOPPED(pn->statusp))
  196. X            pn->statusp = SP_RUNNING;
  197. X}
  198. X
  199. X/* update status of job, possibly printing it */
  200. X
  201. Xvoid updatestatus(jn) /**/
  202. XJob jn;
  203. X{
  204. Xstruct process *pn;
  205. Xint notrunning = 1,alldone = 1,val = 0,job = jn-jobtab,somestopped = 0;
  206. X
  207. X    for (pn = jn->procs; pn; pn = pn->next)
  208. X        {
  209. X        if (pn->statusp == SP_RUNNING)
  210. X            notrunning = 0;
  211. X        if (pn->statusp == SP_RUNNING || WIFSTOPPED(pn->statusp))
  212. X            alldone = 0;
  213. X        if (WIFSTOPPED(pn->statusp))
  214. X            somestopped = 1;
  215. X        if (!pn->next && jn)
  216. X            val = (WIFSIGNALED(pn->statusp)) ?
  217. X                0200 | WTERMSIG(pn->statusp) : WEXITSTATUS(pn->statusp);
  218. X        }
  219. X    if (!notrunning)
  220. X        return;
  221. X    if (somestopped && (jn->stat & STAT_STOPPED))
  222. X        return;
  223. X    jn->stat |= (alldone) ? STAT_CHANGED|STAT_DONE :
  224. X        STAT_CHANGED|STAT_STOPPED;
  225. X    if (alldone && job == thisjob)
  226. X        {
  227. X        if (!ttyfrozen && !val) {
  228. X            gettyinfo(&shttyinfo);
  229. X            if (interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))
  230. X                sanetty(&shttyinfo);
  231. X#ifdef TIOCSWINSZ
  232. X            if (!(columns = shttyinfo.winsize.ws_col))
  233. X                columns = 80;
  234. X            lines = shttyinfo.winsize.ws_row;
  235. X#endif
  236. X        } else
  237. X            settyinfo(&shttyinfo);
  238. X        lastval = val;
  239. X        }
  240. X    if ((jn->stat & (STAT_DONE|STAT_STOPPED)) == STAT_STOPPED) {
  241. X        prevjob = curjob;
  242. X        curjob = job;
  243. X    }
  244. X    if ((isset(NOTIFY) || job == thisjob) && jn->stat & STAT_LOCKED) {
  245. X        printjob(jn,!!isset(LONGLISTJOBS));
  246. X        if (zleactive) refresh();
  247. X    }
  248. X    if (sigtrapped[SIGCHLD] && job != thisjob)
  249. X        dotrap(SIGCHLD);
  250. X}
  251. X
  252. X/* find process and job associated with pid */
  253. X
  254. Xvoid findproc(pid,jptr,pptr) /**/
  255. Xint pid;Job *jptr;struct process **pptr;
  256. X{
  257. Xstruct process *pn;
  258. Xint jn;
  259. X
  260. X    for (jn = 1; jn != MAXJOB; jn++)
  261. X        for (pn = jobtab[jn].procs; pn; pn = pn->next)
  262. X            if (pn->pid == pid)
  263. X                {
  264. X                *pptr = pn;
  265. X                *jptr = jobtab+jn;
  266. X                return;
  267. X                }
  268. X    *pptr = NULL;
  269. X    *jptr = NULL;
  270. X}
  271. X
  272. X/*
  273. X    lng = 0 means jobs 
  274. X    lng = 1 means jobs -l
  275. X    lng = 2 means jobs -p
  276. X*/
  277. X
  278. Xvoid printjob(jn,lng) /**/
  279. XJob jn;int lng;
  280. X{
  281. Xint job = jn-jobtab,len = 9,sig,sflag = 0,llen;
  282. Xint conted = 0,lineleng = getlineleng(),skip = 0,doputnl = 0;
  283. Xstruct process *pn;
  284. X
  285. X    if (lng < 0)
  286. X        {
  287. X        conted = 1;
  288. X        lng = 0;
  289. X        }
  290. X
  291. X    /* find length of longest signame, check to see if we
  292. X        really need to print this job */
  293. X
  294. X    for (pn = jn->procs; pn; pn = pn->next)
  295. X        {
  296. X        if (pn->statusp != SP_RUNNING)
  297. X            if (WIFSIGNALED(pn->statusp))
  298. X                {
  299. X                sig = WTERMSIG(pn->statusp);
  300. X                llen = strlen(sigmsg[sig]);
  301. X                if (WCOREDUMP(pn->statusp))
  302. X                    llen += 14;
  303. X                if (llen > len)
  304. X                    len = llen;
  305. X                if (sig != SIGINT && sig != SIGPIPE)
  306. X                    sflag = 1;
  307. X                else if (sig == SIGINT)
  308. X                    errflag = 1;
  309. X                if (job == thisjob && sig == SIGINT)
  310. X                    doputnl = 1;
  311. X                }
  312. X            else if (WIFSTOPPED(pn->statusp))
  313. X                {
  314. X                sig = WSTOPSIG(pn->statusp);
  315. X                if (strlen(sigmsg[sig]) > len)
  316. X                    len = strlen(sigmsg[sig]);
  317. X                if (job == thisjob && sig == SIGTSTP)
  318. X                    doputnl = 1;
  319. X                }
  320. X            else if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
  321. X                    WEXITSTATUS(pn->statusp))
  322. X                sflag = 1;
  323. X        }
  324. X
  325. X    /* print if necessary */
  326. X
  327. X    if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag ||
  328. X            job != thisjob))
  329. X        {
  330. X        int len2,fline = 1;
  331. X        struct process *qn;
  332. X
  333. X        trashzle();
  334. X        if (doputnl)
  335. X            putc('\n',stderr);
  336. X        for (pn = jn->procs; pn;)
  337. X            {
  338. X            len2 = ((job == thisjob) ? 5 : 10)+len; /* 2 spaces */
  339. X            if (lng)
  340. X                qn = pn->next;
  341. X            else for (qn = pn->next; qn; qn = qn->next)
  342. X                {
  343. X                if (qn->statusp != pn->statusp)
  344. X                    break;
  345. X                if (strlen(qn->text)+len2+((qn->next) ? 3 : 0) > lineleng)
  346. X                    break;
  347. X                len2 += strlen(qn->text)+2;
  348. X                }
  349. X            if (job != thisjob)
  350. X                if (fline)
  351. X                    fprintf(stderr,"[%d]  %c ",jn-jobtab,(job == curjob) ? '+' :
  352. X                        (job == prevjob) ? '-' : ' ');
  353. X                else
  354. X                    fprintf(stderr,(job > 9) ? "        " : "       ");
  355. X            else
  356. X                fprintf(stderr,"zsh: ");
  357. X            if (lng)
  358. X                if (lng == 1)
  359. X                    fprintf(stderr,"%d ",pn->pid);
  360. X                else
  361. X                    {
  362. X                    int x = jn->gleader;
  363. X
  364. X                    fprintf(stderr,"%d ",x);
  365. X                    do skip++; while (x /= 10);
  366. X                    skip++;
  367. X                    lng = 0;
  368. X                    }
  369. X            else
  370. X                fprintf(stderr,"%*s",skip,"");
  371. X            if (pn->statusp == SP_RUNNING)
  372. X                if (!conted)
  373. X                    fprintf(stderr,"running%*s",len-7+2,"");
  374. X                else
  375. X                    fprintf(stderr,"continued%*s",len-9+2,"");
  376. X            else if (WIFEXITED(pn->statusp))
  377. X                if (WEXITSTATUS(pn->statusp))
  378. X                    fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(pn->statusp),
  379. X                        len-9+2,"");
  380. X                else
  381. X                    fprintf(stderr,"done%*s",len-4+2,"");
  382. X            else if (WIFSTOPPED(pn->statusp))
  383. X                fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(pn->statusp)]);
  384. X            else if (WCOREDUMP(pn->statusp))
  385. X                fprintf(stderr,"%s (core dumped)%*s",
  386. X                    sigmsg[WTERMSIG(pn->statusp)],
  387. X                    len-14+2-strlen(sigmsg[WTERMSIG(pn->statusp)]),"");
  388. X            else
  389. X                fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(pn->statusp)]);
  390. X            for (; pn != qn; pn = pn->next)
  391. X                fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text);
  392. X            putc('\n',stderr);
  393. X            fline = 0;
  394. X            }
  395. X        }
  396. X    else if (doputnl && interact)
  397. X        putc('\n',stderr);
  398. X    fflush(stderr);
  399. X
  400. X    /* print "(pwd now: foo)" messages */
  401. X
  402. X    if (interact && job==thisjob && strcmp(jn->pwd,pwd))
  403. X        {
  404. X        printf("(pwd now: ");
  405. X        printdir(pwd);
  406. X        printf(")\n");
  407. X        fflush(stdout);
  408. X        }
  409. X
  410. X    /* delete job if done */
  411. X
  412. X    if (jn->stat & STAT_DONE)
  413. X        {
  414. X        struct process *nx;
  415. X        char *s;
  416. X
  417. X        if ((jn->stat & STAT_TIMED) || (reporttime != -1 && report(jn))) {
  418. X            dumptime(jn);
  419. X        }
  420. X        for (pn = jn->procs; pn; pn = nx)
  421. X            {
  422. X            nx = pn->next;
  423. X            free(pn);
  424. X            }
  425. X        free(jn->pwd);
  426. X        if (jn->filelist)
  427. X            {
  428. X            while (s = getnode(jn->filelist))
  429. X                {
  430. X                unlink(s);
  431. X                free(s);
  432. X                }
  433. X            free(jn->filelist);
  434. X            }
  435. X        *jn = zero;
  436. X        if (job == curjob)
  437. X            {
  438. X            curjob = prevjob;
  439. X            prevjob = job;
  440. X            }
  441. X        if (job == prevjob)
  442. X            setprevjob();
  443. X        }
  444. X    else
  445. X        jn->stat &= ~STAT_CHANGED;
  446. X}
  447. X
  448. X/* set the previous job to something reasonable */
  449. X
  450. Xvoid setprevjob() /**/
  451. X{
  452. Xint t0;
  453. X
  454. X    for (t0 = MAXJOB-1; t0; t0--)
  455. X        if ((jobtab[t0].stat & STAT_INUSE) && (jobtab[t0].stat & STAT_STOPPED) &&
  456. X                t0 != curjob && t0 != thisjob)
  457. X            break;
  458. X    if (!t0)
  459. X        for (t0 = MAXJOB-1; t0; t0--)
  460. X            if ((jobtab[t0].stat & STAT_INUSE) && t0 != curjob && t0 != thisjob)
  461. X                break;
  462. X    prevjob = (t0) ? t0 : -1;
  463. X}
  464. X
  465. X/* initialize a job table entry */
  466. X
  467. Xvoid initjob() /**/
  468. X{
  469. X    jobtab[thisjob].pwd = ztrdup(pwd);
  470. X    jobtab[thisjob].stat = STAT_INUSE;
  471. X    jobtab[thisjob].gleader = 0;
  472. X}
  473. X
  474. X/* add a process to the current job */
  475. X
  476. Xstruct process *addproc(pid,text) /**/
  477. Xlong pid;char *text;
  478. X{
  479. Xstruct process *process;
  480. X
  481. X    if (!jobtab[thisjob].gleader) jobtab[thisjob].gleader = pid;
  482. X    process = zcalloc(sizeof *process);
  483. X    process->pid = pid;
  484. X    if (text) strcpy(process->text,text);
  485. X    else *process->text = '\0';
  486. X    process->next = NULL;
  487. X    process->statusp = SP_RUNNING;
  488. X    process->bgtime = time(NULL);
  489. X    if (jobtab[thisjob].procs) {
  490. X        struct process *n;
  491. X        for (n = jobtab[thisjob].procs; n->next; n = n->next);
  492. X        process->next = NULL;
  493. X        n->next = process;
  494. X    } else jobtab[thisjob].procs = process;
  495. X    return process;
  496. X}
  497. X
  498. X/* determine if it's all right to exec a command without
  499. X    forking in last component of subshells; it's not ok if we have files
  500. X    to delete */
  501. X
  502. Xint execok() /**/
  503. X{
  504. XJob jn;
  505. X
  506. X    if (!exiting)
  507. X        return 0;
  508. X    for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++)
  509. X        if (jn->stat && jn->filelist)
  510. X            return 0;
  511. X    return 1;
  512. X
  513. X}
  514. X
  515. Xvoid waitforpid(pid) /**/
  516. Xlong pid;
  517. X{
  518. X    while (!errflag && (kill(pid,0) >= 0 || errno != ESRCH)) chldsuspend();
  519. X}
  520. X
  521. X/* wait for a job to finish */
  522. X
  523. Xvoid waitjob(job) /**/
  524. Xint job;
  525. X{
  526. XJob jn;
  527. X
  528. X    if (jobtab[job].procs)    /* if any forks were done */
  529. X        {
  530. X        jobtab[job].stat |= STAT_LOCKED;
  531. X        if (jobtab[job].stat & STAT_CHANGED)
  532. X            printjob(jobtab+job,!!isset(LONGLISTJOBS));
  533. X        while (jobtab[job].stat &&
  534. X                !(jobtab[job].stat & (STAT_DONE|STAT_STOPPED)))
  535. X            chldsuspend();
  536. X        }
  537. X    else    /* else do what printjob() usually does */
  538. X        {
  539. X        char *s;
  540. X
  541. X        jn = jobtab+job;
  542. X        free(jn->pwd);
  543. X        if (jn->filelist)
  544. X            {
  545. X            while (s = getnode(jn->filelist))
  546. X                {
  547. X                unlink(s);
  548. X                free(s);
  549. X                }
  550. X            free(jn->filelist);
  551. X            }
  552. X        *jn = zero;
  553. X        }
  554. X}
  555. X
  556. X/* wait for running job to finish */
  557. X
  558. Xvoid waitjobs() /**/
  559. X{
  560. X    waitjob(thisjob);
  561. X    thisjob = -1;
  562. X}
  563. X
  564. X/* clear job table when entering subshells */
  565. X
  566. Xvoid clearjobtab() /**/
  567. X{
  568. Xint t0;
  569. X
  570. X    for (t0 = 1; t0 != MAXJOB; t0++) {
  571. X        if (jobtab[thisjob].pwd)
  572. X            free(jobtab[thisjob].pwd);
  573. X        jobtab[thisjob] = zero;
  574. X    }
  575. X}
  576. X
  577. X/* get a free entry in the job table to use */
  578. X
  579. Xint getfreejob() /**/
  580. X{
  581. Xint t0;
  582. X
  583. X    for (t0 = 1; t0 != MAXJOB; t0++)
  584. X        if (!jobtab[t0].stat) {
  585. X            jobtab[t0].stat |= STAT_INUSE;
  586. X            return t0;
  587. X        }
  588. X    zerr("job table full or recursion limit exceeded",NULL,0);
  589. X    return -1;
  590. X}
  591. X
  592. X/* print pids for & */
  593. X
  594. Xvoid spawnjob() /**/
  595. X{
  596. Xstruct process *pn;
  597. X
  598. X    if (!subsh)
  599. X        {
  600. X        if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED))
  601. X            {
  602. X            curjob = thisjob;
  603. X            setprevjob();
  604. X            }
  605. X        else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED))
  606. X            prevjob = thisjob;
  607. X        if (interact && jobbing && jobtab[thisjob].procs)
  608. X            {
  609. X            fprintf(stderr,"[%d]",thisjob);
  610. X            for (pn = jobtab[thisjob].procs; pn; pn = pn->next)
  611. X                fprintf(stderr," %d",pn->pid);
  612. X            fprintf(stderr,"\n");
  613. X            fflush(stderr);
  614. X            }
  615. X        }
  616. X    if (!jobtab[thisjob].procs)
  617. X        {
  618. X        char *s;
  619. X        struct job *jn;
  620. X
  621. X        jn = jobtab+thisjob;
  622. X        free(jn->pwd);
  623. X        if (jn->filelist)
  624. X            {
  625. X            while (s = getnode(jn->filelist))
  626. X                {
  627. X                unlink(s);
  628. X                free(s);
  629. X                }
  630. X            free(jn->filelist);
  631. X            }
  632. X        *jn = zero;
  633. X        }
  634. X    else
  635. X        jobtab[thisjob].stat |= STAT_LOCKED;
  636. X    thisjob = -1;
  637. X}
  638. X
  639. Xvoid fixsigs() /**/
  640. X{
  641. X    unblockchld();
  642. X}
  643. X
  644. Xint report(j) /**/
  645. XJob j;
  646. X{
  647. X    if (!j->procs) return 0;
  648. X#ifdef HAS_RUSAGE
  649. X    return (j->procs->ti.ru.ru_utime.tv_sec+j->procs->ti.ru.ru_stime.tv_sec)
  650. X                 >= reporttime;
  651. X#else
  652. X    return (j->procs->ti.ut+j->procs->ti.st)/HZ >= reporttime;
  653. X#endif
  654. X}
  655. X
  656. Xvoid printtime(real,ti,desc) /**/
  657. Xtime_t real;struct timeinfo *ti;char *desc;
  658. X{
  659. Xchar *s;
  660. X#ifdef HAS_RUSAGE
  661. X#ifdef sun
  662. Xlong ticks = 1;
  663. Xint pk = getpagesize()/1024;
  664. X#else
  665. Xlong sec;
  666. X#endif
  667. Xstruct rusage *ru = &ti->ru;
  668. X#endif
  669. X
  670. X    if (!desc) desc = "";
  671. X#ifdef HAS_RUSAGE
  672. X#ifdef sun
  673. X    ticks = (ru->ru_utime.tv_sec+ru->ru_stime.tv_sec)*HZ+
  674. X              (ru->ru_utime.tv_usec+ru->ru_stime.tv_usec)*HZ/1000000;
  675. X    if (!ticks) ticks = 1;
  676. X#else
  677. X    sec = ru->ru_utime.tv_sec + ru->ru_stime.tv_sec;
  678. X    if (!sec) sec = 1;
  679. X#endif
  680. X#endif
  681. X    for (s = timefmt; *s; s++)
  682. X        if (*s == '%')
  683. X            switch(s++,*s)
  684. X                {
  685. X                case 'E': fprintf(stderr,"%lds",real); break;
  686. X#ifndef HAS_RUSAGE
  687. X                case 'U': fprintf(stderr,"%ld.%03lds",
  688. X                    ti->ut/HZ,ti->ut*1000/HZ%1000); break;
  689. X                case 'S': fprintf(stderr,"%ld.%03lds",
  690. X                    ti->st/HZ,ti->st*1000/HZ%1000); break;
  691. X                case 'P':
  692. X                    if (real)
  693. X                        fprintf(stderr,"%d%%",
  694. X                            (int) (100*((ti->ut+ti->st)/HZ))/real);
  695. X                    break;
  696. X#else
  697. X                case 'U': fprintf(stderr,"%ld.%03lds",
  698. X                    ru->ru_utime.tv_sec,ru->ru_utime.tv_usec/1000); break;
  699. X                case 'S': fprintf(stderr,"%ld.%03lds",
  700. X                    ru->ru_stime.tv_sec,ru->ru_stime.tv_usec/1000); break;
  701. X                case 'P':
  702. X                    if (real)
  703. X                        fprintf(stderr,"%d%%",
  704. X                            (int) (100*(ru->ru_utime.tv_sec+ru->ru_stime.tv_sec))
  705. X                                / real);
  706. X                    break;
  707. X                case 'W': fprintf(stderr,"%ld",ru->ru_nswap); break;
  708. X#ifdef sun
  709. X                case 'K': case 'D':
  710. X                    fprintf(stderr,"%ld",ru->ru_idrss/ticks*pk); break;
  711. X                case 'M': fprintf(stderr,"%ld",ru->ru_maxrss*pk); break;
  712. X#else
  713. X                case 'X': fprintf(stderr,"%ld",ru->ru_ixrss/sec); break;
  714. X                case 'D': fprintf(stderr,"%ld",
  715. X                    (ru->ru_idrss+ru->ru_isrss)/sec); break;
  716. X                case 'K': fprintf(stderr,"%ld",
  717. X                    (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss)/sec); break;
  718. X                case 'M': fprintf(stderr,"%ld",ru->ru_maxrss/1024); break;
  719. X#endif
  720. X                case 'F': fprintf(stderr,"%ld",ru->ru_majflt); break;
  721. X                case 'R': fprintf(stderr,"%ld",ru->ru_minflt); break;
  722. X                case 'I': fprintf(stderr,"%ld",ru->ru_inblock); break;
  723. X                case 'O': fprintf(stderr,"%ld",ru->ru_oublock); break;
  724. X                case 'r': fprintf(stderr,"%ld",ru->ru_msgrcv); break;
  725. X                case 's': fprintf(stderr,"%ld",ru->ru_msgsnd); break;
  726. X                case 'k': fprintf(stderr,"%ld",ru->ru_nsignals); break;
  727. X                case 'w': fprintf(stderr,"%ld",ru->ru_nvcsw); break;
  728. X                case 'c': fprintf(stderr,"%ld",ru->ru_nivcsw); break;
  729. X#endif
  730. X                case 'J': fprintf(stderr,"%s",desc); break;
  731. X                default: fprintf(stderr,"%%%c",*s); break;
  732. X                }
  733. X        else
  734. X            putc(*s,stderr);
  735. X    putc('\n',stderr);
  736. X    fflush(stderr);
  737. X}
  738. X
  739. Xvoid dumptime(jn) /**/
  740. XJob jn;
  741. X{
  742. Xstruct process *pn;
  743. X
  744. X    if (!jn->procs)
  745. X        return;
  746. X    for (pn = jn->procs; pn; pn = pn->next)
  747. X        printtime(pn->endtime-pn->bgtime,&pn->ti,pn->text);
  748. X}
  749. X
  750. Xvoid shelltime() /**/
  751. X{
  752. Xstruct timeinfo ti;
  753. X#ifdef HAS_RUSAGE
  754. Xstruct rusage ru;
  755. X
  756. X    getrusage(RUSAGE_SELF,&ru);
  757. X    memcpy(&ti.ru,&ru,sizeof(ru));
  758. X    printtime(time(NULL)-shtimer,&ti,"shell");
  759. X
  760. X    getrusage(RUSAGE_CHILDREN,&ru);
  761. X    memcpy(&ti.ru,&ru,sizeof(ru));
  762. X    printtime(time(NULL)-shtimer,&ti,"children");
  763. X#else
  764. Xstruct tms buf;
  765. X
  766. X    times(&buf);
  767. X    ti.ut = buf.tms_utime;
  768. X    ti.st = buf.tms_stime;
  769. X    printtime(time(NULL)-shtimer,&ti,"shell");
  770. X    ti.ut = buf.tms_cutime;
  771. X    ti.st = buf.tms_cstime;
  772. X    printtime(time(NULL)-shtimer,&ti,"children");
  773. X#endif
  774. X}
  775. X
  776. X/* SIGHUP any jobs left running */
  777. X
  778. Xvoid killrunjobs() /**/
  779. X{
  780. Xint t0,killed = 0;
  781. X
  782. X    if (isset(NOHUP)) return;
  783. X    for (t0 = 1; t0 != MAXJOB; t0++)
  784. X        if (t0 != thisjob && (jobtab[t0].stat & STAT_LOCKED) &&
  785. X                !(jobtab[t0].stat & STAT_STOPPED)) {
  786. X            if (killpg(jobtab[t0].gleader,SIGHUP) != -1) killed++;
  787. X        }
  788. X    if (killed) zerr("warning: %d jobs SIGHUPed",NULL,killed);
  789. X}
  790. X
  791. X/* check to see if user has jobs running/stopped */
  792. X
  793. Xvoid checkjobs() /**/
  794. X{
  795. Xint t0;
  796. X
  797. X    scanjobs();
  798. X    for (t0 = 1; t0 != MAXJOB; t0++)
  799. X        if (t0 != thisjob && jobtab[t0].stat & STAT_LOCKED)
  800. X            break;
  801. X    if (t0 != MAXJOB) {
  802. X        if (jobtab[t0].stat & STAT_STOPPED) {
  803. X#ifdef USE_SUSPENDED
  804. X            zerr("you have suspended jobs.",NULL,0);
  805. X#else
  806. X            zerr("you have stopped jobs.",NULL,0);
  807. X#endif
  808. X        } else
  809. X            zerr("you have running jobs.",NULL,0);
  810. X        stopmsg = 1;
  811. X    }
  812. X}
  813. X
  814. X/* send a signal to a job (simply involves kill if monitoring is on) */
  815. X
  816. Xint killjb(jn,sig) /**/
  817. XJob jn;int sig;
  818. X{
  819. Xstruct process *pn;
  820. Xint err = 0;
  821. X
  822. X    if (jobbing)
  823. X        return(killpg(jn->gleader,sig));
  824. X    for (pn = jn->procs; pn; pn = pn->next)
  825. X        if ((err = kill(pn->pid,sig)) == -1 && errno != ESRCH)
  826. X            return -1;
  827. X    return err;
  828. X}
  829. END_OF_FILE
  830.   if test 17010 -ne `wc -c <'src/jobs.c'`; then
  831.     echo shar: \"'src/jobs.c'\" unpacked with wrong size!
  832.   fi
  833.   # end of 'src/jobs.c'
  834. fi
  835. if test -f 'src/zsh.h' -a "${1}" != "-c" ; then 
  836.   echo shar: Will not clobber existing file \"'src/zsh.h'\"
  837. else
  838.   echo shar: Extracting \"'src/zsh.h'\" \(34760 characters\)
  839.   sed "s/^X//" >'src/zsh.h' <<'END_OF_FILE'
  840. X/*
  841. X *
  842. X * zsh.h - standard header file
  843. X *
  844. X * This file is part of zsh, the Z shell.
  845. X *
  846. X * This software is Copyright 1992 by Paul Falstad
  847. X *
  848. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  849. X * use this software as long as: there is no monetary profit gained
  850. X * specifically from the use or reproduction of this software, it is not
  851. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  852. X * included prominently in any copy made. 
  853. X *
  854. X * The author make no claims as to the fitness or correctness of this software
  855. X * for any use whatsoever, and it is provided as is. Any use of this software
  856. X * is at the user's own risk. 
  857. X *
  858. X */
  859. X
  860. X#include "config.h"
  861. X
  862. X#include <stdio.h>
  863. X#include <ctype.h>
  864. X
  865. X#ifdef HAS_STRING
  866. X#include <string.h>
  867. X#else
  868. X#include <strings.h>
  869. X#endif
  870. X
  871. X#ifdef HAS_MEMORY
  872. X#include <memory.h>
  873. X#endif
  874. X
  875. X#ifdef HAS_LOCALE
  876. X#include <locale.h>
  877. X#endif
  878. X
  879. X#ifdef HAS_STDLIB
  880. X#include <stdlib.h>
  881. X#endif
  882. X
  883. X#ifdef SYSV
  884. X#ifndef SYSVR4
  885. X#include <sys/bsdtypes.h>
  886. X#define _POSIX_SOURCE
  887. X#include <sys/limits.h>
  888. X#include <sys/sioctl.h>
  889. X#define MAXPATHLEN PATH_MAX
  890. X#define lstat stat
  891. X#endif
  892. Xextern int gethostname();
  893. X#define sigmask(m) m
  894. X#else
  895. X#include <sys/types.h>        /* this is the key to the whole thing */
  896. X#endif
  897. X
  898. X#ifdef _IBMR2
  899. X#undef _BSD   /* union wait SUCKS! */
  900. X#include <sys/wait.h>
  901. X#define _BSD
  902. X#else
  903. X#ifdef HAS_WAIT
  904. X#include <wait.h>
  905. X#else
  906. X#include <sys/wait.h>
  907. X#endif
  908. X#endif
  909. X
  910. X#ifdef HAS_TIME
  911. X#include <time.h>
  912. X#else
  913. X#include <sys/time.h>
  914. X#endif
  915. X
  916. X#ifdef SYSV
  917. X#include <fcntl.h>
  918. X#else
  919. X#include <sys/file.h>
  920. X#endif
  921. X
  922. X#if !defined(SYSV) || defined(SYSVR4)
  923. X#include <sys/resource.h>
  924. X#endif
  925. X
  926. X#include <signal.h>
  927. X
  928. X#ifdef TERMIO
  929. X#define VDISABLEVAL -1
  930. X#define TIO 1
  931. X#include <sys/termio.h>
  932. X#else
  933. X#ifdef TERMIOS
  934. X#define VDISABLEVAL 0
  935. X#define TIO 1
  936. X#include <termios.h>
  937. X#else
  938. X#include <sgtty.h>
  939. X#endif
  940. X#endif
  941. X
  942. X#if defined(SYSV) && !defined(SYSVR4)
  943. X#define readlink(s,t,z)    (-1)
  944. X#undef TIOCGWINSZ
  945. X#endif
  946. X
  947. X#include <sys/param.h>
  948. X#include <sys/times.h>
  949. X
  950. X#ifdef HAS_DIRENT
  951. X#include <dirent.h>
  952. X#define direct dirent
  953. X#else
  954. X#include <sys/dir.h>
  955. X#endif
  956. X
  957. X#ifdef SYSV
  958. X#undef _POSIX_SOURCE
  959. X#endif
  960. X
  961. X#ifdef __hp9000s800
  962. X#include <sys/bsdtty.h>
  963. X#endif
  964. X
  965. X#if !defined(sun) && !defined(SYSVR4)
  966. X#include <sys/ioctl.h>
  967. X#else
  968. X#include <sys/filio.h>
  969. X#endif
  970. X
  971. X#ifdef __STDC__
  972. X#define DCLPROTO(X) X
  973. X#ifdef HAS_UNISTD
  974. X#include <unistd.h>
  975. X#endif
  976. X#include <fcntl.h>
  977. X#include <sys/stat.h>
  978. X#undef NULL
  979. X#define NULL ((void *)0)
  980. X#else /* K&R C */
  981. X#define DCLPROTO(X) ()
  982. X#define const
  983. X#include <sys/stat.h>
  984. X#ifndef NULL
  985. X#define NULL 0
  986. X#endif
  987. X#endif
  988. X
  989. X#ifdef HAS_UTMPX
  990. X#include <utmpx.h>
  991. X# define utmp utmpx
  992. X# define ut_time ut_xtime
  993. X# undef UTMP_FILE
  994. X# define UTMP_FILE UTMPX_FILE
  995. X# undef WTMP_FILE
  996. X# define WTMP_FILE WTMPX_FILE
  997. X#else
  998. X#include <utmp.h>
  999. X#endif
  1000. X
  1001. X#if !defined(UTMP_FILE) && defined(_PATH_UTMP)
  1002. X#define UTMP_FILE _PATH_UTMP
  1003. X#endif
  1004. X#if !defined(WTMP_FILE) && defined(_PATH_WTMP)
  1005. X#define WTMP_FILE _PATH_WTMP
  1006. X#endif
  1007. X
  1008. X#define DEFWORDCHARS "*?_-.[]~=/&;!#$%^(){}<>"
  1009. X#define DEFTIMEFMT "%E real  %U user  %S system  %P %J"
  1010. X#ifdef UTMP_HOST
  1011. X#define DEFWATCHFMT "%n has %a %l from %m."
  1012. X#else
  1013. X#define DEFWATCHFMT "%n has %a %l."
  1014. X#endif
  1015. X
  1016. X#ifdef GLOBALS
  1017. X#define EXTERN
  1018. X#else
  1019. X#define EXTERN extern
  1020. X#endif
  1021. X
  1022. X#ifdef HAS_STRING
  1023. X#define killpg(pgrp,sig) kill(-(pgrp),sig)
  1024. X#endif
  1025. X
  1026. X/* SYSV or POSIX compatible BSD */
  1027. X#if defined(SYSV) || ( defined(BSD) && BSD >= 199103 )
  1028. X#define getpgrp(X)  getpgrp()
  1029. X#endif
  1030. X
  1031. X#ifndef F_OK
  1032. X#define F_OK 00
  1033. X#define R_OK 04
  1034. X#define W_OK 02
  1035. X#define X_OK 01
  1036. X#endif
  1037. X
  1038. X#include "zle.h"
  1039. X
  1040. X/* size of job list */
  1041. X
  1042. X#define MAXJOB 80
  1043. X
  1044. X/* memory allocation routines - changed with permalloc()/heapalloc() */
  1045. X
  1046. Xvptr (*alloc)DCLPROTO((int));
  1047. Xvptr (*ncalloc)DCLPROTO((int));
  1048. X
  1049. X#define addhnode(A,B,C,D) Addhnode(A,B,C,D,1)
  1050. X#define addhperm(A,B,C,D) Addhnode(A,B,C,D,0)
  1051. X
  1052. X/* character tokens */
  1053. X
  1054. X#define ALPOP            ((char) 0x81)
  1055. X#define HISTSPACE        ((char) 0x83)
  1056. X#define Pound            ((char) 0x84)
  1057. X#define String            ((char) 0x85)
  1058. X#define Hat                ((char) 0x86)
  1059. X#define Star            ((char) 0x87)
  1060. X#define Inpar            ((char) 0x88)
  1061. X#define Outpar            ((char) 0x89)
  1062. X#define Qstring        ((char) 0x8a)
  1063. X#define Equals            ((char) 0x8b)
  1064. X#define Bar                ((char) 0x8c)
  1065. X#define Inbrace        ((char) 0x8d)
  1066. X#define Outbrace        ((char) 0x8e)
  1067. X#define Inbrack        ((char) 0x8f)
  1068. X#define Outbrack        ((char) 0x90)
  1069. X#define Tick            ((char) 0x91)
  1070. X#define Inang            ((char) 0x92)
  1071. X#define Outang            ((char) 0x93)
  1072. X#define Quest            ((char) 0x94)
  1073. X#define Tilde            ((char) 0x95)
  1074. X#define Qtick            ((char) 0x96)
  1075. X#define Comma            ((char) 0x97)
  1076. X#define Snull            ((char) 0x98)
  1077. X#define Dnull            ((char) 0x99)
  1078. X#define Bnull            ((char) 0x9a)
  1079. X#define Nularg            ((char) 0x9b)
  1080. X
  1081. X#define INULL(x)        (((x) & 0x98) == 0x98)
  1082. X
  1083. X/* Character tokens are sometimes casted to (unsigned char)'s. Unfortunately,
  1084. X   SVR4's deceiving compiler botches non-terminal, same size, signed to unsigned
  1085. X    promotions; i.e. (int) (unsigned char) ((char) -1) evaluates to -1,
  1086. X    not 255 as it should!
  1087. X
  1088. X    We circumvent the troubles of such shameful delinquency by casting to a
  1089. X    larger unsigned type then back down to unsigned char.
  1090. X        -- Marc Boucher <marc@cam.org>
  1091. X    <daniel@ug.eds.com> 25-Jan-1993  Dec Alpha OSF compilers have the same property
  1092. X*/
  1093. X
  1094. X#if (defined(SYSVR4) || defined (__osf__)) && !defined(__GNUC__)
  1095. X#define STOUC(X)    ((unsigned char)(unsigned short)(X))
  1096. X#else
  1097. X#define STOUC(X)    ((unsigned char)(X))
  1098. X#endif
  1099. X
  1100. X/*
  1101. X * The source was full of implicit casts between signed and unsigned
  1102. X * character pointers.  To get a clean compile, I've made these casts
  1103. X * explicit, but the potential for error is still there.  If your machine
  1104. X * needs special treatment, just define your own macros here.
  1105. X *     --jim <jmattson@ucsd.edu>
  1106. X */
  1107. X#define STOUCP(X)    ((unsigned char *)(X))
  1108. X#define UTOSCP(X)    ((char *)(X))
  1109. X
  1110. X/* chars that need to be quoted if meant literally */
  1111. X
  1112. X#define SPECCHARS "#$^*()$=|{}[]`<>?~;&!\n\t \\\'\""
  1113. X
  1114. X/* ALPOP in the form of a string */
  1115. X
  1116. X#define ALPOPS " \201"
  1117. X#define HISTMARK "\201"
  1118. X
  1119. X#define SEPER 1
  1120. X#define NEWLIN 2
  1121. X#define LEXERR 3
  1122. X#define SEMI 4
  1123. X#define DSEMI 5
  1124. X#define AMPER 6
  1125. X#define INPAR 7
  1126. X#define INBRACE 8
  1127. X#define OUTPAR 9
  1128. X#define DBAR 10
  1129. X#define DAMPER 11
  1130. X#define BANG 12
  1131. X#define OUTBRACE 13
  1132. X#define OUTANG 14
  1133. X#define OUTANGBANG 15
  1134. X#define DOUTANG 16
  1135. X#define DOUTANGBANG 17
  1136. X#define INANG 18
  1137. X#define DINANG 19
  1138. X#define DINANGDASH 20
  1139. X#define INANGAMP 21
  1140. X#define OUTANGAMP 22
  1141. X#define OUTANGAMPBANG 23
  1142. X#define DOUTANGAMP 24
  1143. X#define DOUTANGAMPBANG 25
  1144. X#define TRINANG 26
  1145. X#define BAR 27
  1146. X#define BARAMP 28
  1147. X#define DINBRACK 29
  1148. X#define DOUTBRACK 30
  1149. X#define STRING 31
  1150. X#define ENVSTRING 32
  1151. X#define ENVARRAY 33
  1152. X#define ENDINPUT 34
  1153. X#define INOUTPAR 35
  1154. X#define DO 36
  1155. X#define DONE 37
  1156. X#define ESAC 38
  1157. X#define THEN 39
  1158. X#define ELIF 40
  1159. X#define ELSE 41
  1160. X#define FI 42
  1161. X#define FOR 43
  1162. X#define CASE 44
  1163. X#define IF 45
  1164. X#define WHILE 46
  1165. X#define FUNC 47
  1166. X#define REPEAT 48
  1167. X#define TIME 49
  1168. X#define UNTIL 50
  1169. X#define EXEC 51
  1170. X#define COMMAND 52
  1171. X#define SELECT 53
  1172. X#define COPROC 54
  1173. X#define NOGLOB 55
  1174. X#define DASH 56
  1175. X#define NOCORRECT 57
  1176. X#define FOREACH 58
  1177. X#define ZEND 59
  1178. X
  1179. X#define WRITE 0
  1180. X#define WRITENOW 1
  1181. X#define APP 2
  1182. X#define APPNOW 3
  1183. X#define MERGEOUT 4
  1184. X#define MERGEOUTNOW 5
  1185. X#define ERRAPP 6
  1186. X#define ERRAPPNOW 7
  1187. X#define READ 8
  1188. X#define HEREDOC 9
  1189. X#define HEREDOCDASH 10
  1190. X#define HERESTR 11
  1191. X#define MERGE 12
  1192. X#define CLOSE 13
  1193. X#define INPIPE 14
  1194. X#define OUTPIPE 15
  1195. X#define NONE 16
  1196. X
  1197. X#ifdef GLOBALS
  1198. Xint redirtab[TRINANG-OUTANG+1] = {
  1199. X    WRITE,
  1200. X    WRITENOW,
  1201. X    APP,
  1202. X    APPNOW,
  1203. X    READ,
  1204. X    HEREDOC,
  1205. X    HEREDOCDASH,
  1206. X    MERGE,
  1207. X    MERGEOUT,
  1208. X    MERGEOUTNOW,
  1209. X    ERRAPP,
  1210. X    ERRAPPNOW,
  1211. X    HERESTR,
  1212. X};
  1213. X#else
  1214. Xextern int redirtab[TRINANG-OUTANG+1];
  1215. X#endif
  1216. X
  1217. X#ifdef GLOBALS
  1218. Xchar nulstring[] = { Nularg, '\0' };
  1219. Xint nulstrlen = sizeof(nulstring) - 1;
  1220. X#else
  1221. Xextern char nulstring[];
  1222. Xextern int nulstrlen;
  1223. X#endif
  1224. X
  1225. X#define IS_READFD(X) ((X)>=READ && (X)<=MERGE)
  1226. X#define IS_REDIROP(X) ((X)>=OUTANG && (X)<=TRINANG)
  1227. X#define IS_ERROR_REDIR(X) ((X)>=MERGEOUT && (X)<=ERRAPPNOW)
  1228. X#define UN_ERROR_REDIR(X) ((X)-MERGEOUT+WRITE)
  1229. X
  1230. X#define FD_WORD   -1
  1231. X#define FD_COPROC -2
  1232. X#define FD_CLOSE  -3
  1233. X
  1234. Xextern char **environ;
  1235. X
  1236. Xtypedef struct hashtab *Hashtab;
  1237. Xtypedef struct hashnode *Hashnode;
  1238. Xtypedef struct schedcmd *Schedcmd;
  1239. Xtypedef struct alias *Alias;
  1240. Xtypedef struct process *Process;
  1241. Xtypedef struct job *Job;
  1242. Xtypedef struct value *Value;
  1243. Xtypedef struct arrind *Arrind;
  1244. Xtypedef struct varasg *Varasg;
  1245. Xtypedef struct param *Param;
  1246. Xtypedef struct cmdnam *Cmdnam;
  1247. Xtypedef struct cond *Cond;
  1248. Xtypedef struct cmd *Cmd;
  1249. Xtypedef struct pline *Pline;
  1250. Xtypedef struct sublist *Sublist;
  1251. Xtypedef struct list *List;
  1252. Xtypedef struct lklist *Lklist;
  1253. Xtypedef struct lknode *Lknode;
  1254. Xtypedef struct comp *Comp;
  1255. Xtypedef struct redir *Redir;
  1256. Xtypedef struct complist *Complist;
  1257. Xtypedef struct heap *Heap;
  1258. Xtypedef struct histent *Histent;
  1259. Xtypedef struct compctl *Compctl;
  1260. Xtypedef void (*FFunc)DCLPROTO((vptr));
  1261. Xtypedef vptr (*VFunc)DCLPROTO((vptr));
  1262. Xtypedef void (*HFunc)DCLPROTO((char *,char *));
  1263. X
  1264. X/* linked list abstract data type */
  1265. X
  1266. Xstruct lknode;
  1267. Xstruct lklist;
  1268. X
  1269. Xstruct lknode {
  1270. X   Lknode next,last;
  1271. X   vptr dat;
  1272. X   };
  1273. Xstruct lklist {
  1274. X   Lknode first,last;
  1275. X   };
  1276. X
  1277. X#define addnode(X,Y) insnode(X,(X)->last,Y)
  1278. X#define full(X) ((X)->first != NULL)
  1279. X#define empty(X) ((X)->first == NULL)
  1280. X#define firstnode(X) ((X)->first)
  1281. X#define getaddrdata(X) (&((X)->dat))
  1282. X#define getdata(X) ((X)->dat)
  1283. X#define setdata(X,Y) ((X)->dat = (Y))
  1284. X#define lastnode(X) ((X)->last)
  1285. X#define nextnode(X) ((X)->next)
  1286. X#define prevnode(X) ((X)->last)
  1287. X#define peekfirst(X) ((X)->first->dat)
  1288. X#define pushnode(X,Y) insnode(X,(Lknode) X,Y)
  1289. X#define incnode(X) (X = nextnode(X))
  1290. X#define gethistent(X) (histentarr+((X)%histentct))
  1291. X
  1292. X/* node structure for syntax trees */
  1293. X
  1294. X/* struct list, struct sublist, struct pline, etc.  all fit the form
  1295. X    of this structure and are used interchangably
  1296. X*/
  1297. X
  1298. Xstruct node {
  1299. X    int data[4];            /* arbitrary integer data */
  1300. X    vptr ptrs[4];            /* arbitrary pointer data */
  1301. X    int types[4];            /* what ptrs[] are pointing to */
  1302. X    int type;                /* node type */
  1303. X    };
  1304. X
  1305. X#define N_LIST 0
  1306. X#define N_SUBLIST 1
  1307. X#define N_PLINE 2
  1308. X#define N_CMD 3
  1309. X#define N_REDIR 4
  1310. X#define N_COND 5
  1311. X#define N_FOR 6
  1312. X#define N_CASE 7
  1313. X#define N_IF 8
  1314. X#define N_WHILE 9
  1315. X#define N_VARASG 10
  1316. X#define N_COUNT 11
  1317. X
  1318. X/* values for types[4] */
  1319. X
  1320. X#define NT_EMPTY 0
  1321. X#define NT_NODE  1
  1322. X#define NT_STR   2
  1323. X#define NT_LIST  4
  1324. X#define NT_MALLOC 8
  1325. X
  1326. X/* tree element for lists */
  1327. X
  1328. Xstruct list {
  1329. X    int type;
  1330. X    int ifil[3];        /* to fit struct node */
  1331. X   Sublist left;
  1332. X   List right;
  1333. X   };
  1334. X
  1335. X#define SYNC 0        /* ; */
  1336. X#define ASYNC 1    /* & */
  1337. X#define TIMED 2
  1338. X
  1339. X/* tree element for sublists */
  1340. X
  1341. Xstruct sublist {
  1342. X    int type;
  1343. X    int flags;            /* see PFLAGs below */
  1344. X    int ifil[2];
  1345. X    Pline left;
  1346. X    Sublist right;
  1347. X    };
  1348. X
  1349. X#define ORNEXT 10        /* || */
  1350. X#define ANDNEXT 11    /* && */
  1351. X
  1352. X#define PFLAG_NOT 1            /* ! ... */
  1353. X#define PFLAG_COPROC 32        /* coproc ... */
  1354. X
  1355. X/* tree element for pipes */
  1356. X
  1357. Xstruct pline {
  1358. X    int type;
  1359. X    int ifil[3];
  1360. X   Cmd left;
  1361. X   Pline right;
  1362. X   };
  1363. X
  1364. X#define END        0    /* pnode *right is null */
  1365. X#define PIPE    1    /* pnode *right is the rest of the pipeline */
  1366. X
  1367. X/* tree element for commands */
  1368. X
  1369. Xstruct cmd {
  1370. X    int type;
  1371. X    int flags;                /* see CFLAGs below */
  1372. X    int ifil[2];
  1373. X   Lklist args;            /* command & argmument List (char *'s) */
  1374. X    union {
  1375. X       List list;            /* for SUBSH/CURSH/SHFUNC */
  1376. X        struct forcmd *forcmd;
  1377. X        struct casecmd *casecmd;
  1378. X        struct ifcmd *ifcmd;
  1379. X        struct whilecmd *whilecmd;
  1380. X        Sublist pline;
  1381. X        Cond cond;
  1382. X        } u;
  1383. X   Lklist redir;            /* i/o redirections (struct redir *'s) */
  1384. X    Lklist vars;            /* param assignments (struct varasg *'s) */
  1385. X   };
  1386. X
  1387. X#define SIMPLE 0
  1388. X#define SUBSH 1
  1389. X#define CURSH 2
  1390. X#define ZCTIME 3
  1391. X#define FUNCDEF 4
  1392. X#define CFOR 5
  1393. X#define CWHILE 6
  1394. X#define CREPEAT 7
  1395. X#define CIF 8
  1396. X#define CCASE 9
  1397. X#define CSELECT 10
  1398. X#define COND 11
  1399. X
  1400. X#define CFLAG_EXEC 1            /* exec ... */
  1401. X#define CFLAG_COMMAND 2        /* command ... */
  1402. X#define CFLAG_NOGLOB 4     /* noglob ... */
  1403. X#define CFLAG_DASH 8            /* - ... */
  1404. X
  1405. X/* tree element for redirection lists */
  1406. X
  1407. Xstruct redir {
  1408. X    int type,fd1,fd2,ifil;
  1409. X    char *name;
  1410. X   };
  1411. X
  1412. X/* tree element for conditionals */
  1413. X
  1414. Xstruct cond {
  1415. X    int type;        /* can be cond_type, or a single letter (-a, -b, ...) */
  1416. X    int ifil[3];
  1417. X    vptr left,right,vfil[2];
  1418. X    int types[4],typ;    /* from struct node.  DO NOT REMOVE */
  1419. X    };
  1420. X
  1421. X#define COND_NOT 0
  1422. X#define COND_AND 1
  1423. X#define COND_OR 2
  1424. X#define COND_STREQ 3
  1425. X#define COND_STRNEQ 4
  1426. X#define COND_STRLT 5
  1427. X#define COND_STRGTR 6
  1428. X#define COND_NT 7
  1429. X#define COND_OT 8
  1430. X#define COND_EF 9
  1431. X#define COND_EQ 10
  1432. X#define COND_NE 11
  1433. X#define COND_LT 12
  1434. X#define COND_GT 13
  1435. X#define COND_LE 14
  1436. X#define COND_GE 15
  1437. X
  1438. Xstruct forcmd {        /* for/select */
  1439. X                            /* Cmd->args contains list of words to loop thru */
  1440. X    int inflag;            /* if there is an in ... clause */
  1441. X    int ifil[3];
  1442. X    char *name;            /* parameter to assign values to */
  1443. X    List list;            /* list to look through for each name */
  1444. X    };
  1445. Xstruct casecmd {
  1446. X                            /* Cmd->args contains word to test */
  1447. X    int ifil[4];
  1448. X    struct casecmd *next;
  1449. X    char *pat;
  1450. X    List list;                    /* list to execute */
  1451. X    };
  1452. X
  1453. X/*
  1454. X
  1455. X    a command like "if foo then bar elif baz then fubar else fooble"
  1456. X    generates a tree like:
  1457. X
  1458. X    struct ifcmd a = { next =  &b,  ifl = "foo", thenl = "bar" }
  1459. X    struct ifcmd b = { next =  &c,  ifl = "baz", thenl = "fubar" }
  1460. X    struct ifcmd c = { next = NULL, ifl = NULL, thenl = "fooble" }
  1461. X
  1462. X*/
  1463. X
  1464. Xstruct ifcmd {
  1465. X    int ifil[4];
  1466. X    struct ifcmd *next;
  1467. X    List ifl;
  1468. X    List thenl;
  1469. X    };
  1470. X
  1471. Xstruct whilecmd {
  1472. X    int cond;        /* 0 for while, 1 for until */
  1473. X    int ifil[3];
  1474. X    List cont;        /* condition */
  1475. X    List loop;        /* list to execute until condition met */
  1476. X    };
  1477. X
  1478. X/* structure used for multiple i/o redirection */
  1479. X/* one for each fd open */
  1480. X
  1481. Xstruct multio {
  1482. X    int ct;                /* # of redirections on this fd */
  1483. X    int rflag;            /* 0 if open for reading, 1 if open for writing */
  1484. X    int pipe;            /* fd of pipe if ct > 1 */
  1485. X    int fds[NOFILE];    /* list of src/dests redirected to/from this fd */
  1486. X   }; 
  1487. X
  1488. X/* node used in command path hash table (cmdnamtab) */
  1489. X
  1490. Xstruct cmdnam 
  1491. X{
  1492. X    struct hashnode *next; int canfree; char *nam; /* hash data */
  1493. X    int type,flags;
  1494. X    union {
  1495. X        char *nam;        /* full pathname if type != BUILTIN */
  1496. X        int binnum;        /* func to exec if type == BUILTIN */
  1497. X        List list;        /* list to exec if type == SHFUNC */
  1498. X        } u;
  1499. X    char **pcomp;        /* location in path for EXCMD's */
  1500. X    };
  1501. X
  1502. X#define EXCMD 0
  1503. X#define BUILTIN 2
  1504. X#define SHFUNC 3
  1505. X#define DISABLED 4
  1506. X#define ISEXCMD(X) ((X)==EXCMD)
  1507. X
  1508. X/* node used in parameter hash table (paramtab) */
  1509. X
  1510. Xstruct param {
  1511. X    struct hashnode *next; int canfree; char *nam; /* hash data */
  1512. X    union {
  1513. X        char **arr;        /* value if declared array */
  1514. X        char *str;        /* value if declared string (scalar) */
  1515. X        long val;        /* value if declared integer */
  1516. X        } u;
  1517. X    union {                /* functions to call to set value */
  1518. X        void (*cfn)DCLPROTO((Param,char *));
  1519. X        void (*ifn)DCLPROTO((Param,long));
  1520. X        void (*afn)DCLPROTO((Param,char **));
  1521. X        } sets;
  1522. X    union {                /* functions to call to get value */
  1523. X        char *(*cfn)DCLPROTO((Param));
  1524. X        long (*ifn)DCLPROTO((Param));
  1525. X        char **(*afn)DCLPROTO((Param));
  1526. X        } gets;
  1527. X    int ct;                /* output base or field width */
  1528. X    int flags;
  1529. X    vptr data;            /* used by getfns */
  1530. X    char *env;            /* location in environment, if exported */
  1531. X    char *ename;        /* name of corresponding environment var */
  1532. X    };
  1533. X
  1534. X#define PMFLAG_s 0        /* scalar */
  1535. X#define PMFLAG_L 1        /* left justify and remove leading blanks */
  1536. X#define PMFLAG_R 2        /* right justify and fill with leading blanks */
  1537. X#define PMFLAG_Z 4        /* right justify and fill with leading zeros */
  1538. X#define PMFLAG_i 8        /* integer */
  1539. X#define PMFLAG_l 16        /* all lower case */
  1540. X#define PMFLAG_u 32        /* all upper case */
  1541. X#define PMFLAG_r 64        /* readonly */
  1542. X#define PMFLAG_t 128        /* tagged */
  1543. X#define PMFLAG_x 256        /* exported */
  1544. X#define PMFLAG_A 512        /* array */
  1545. X#define PMFLAG_SPECIAL    1024
  1546. X#define PMTYPE (PMFLAG_i|PMFLAG_A)
  1547. X#define pmtype(X) ((X)->flags & PMTYPE)
  1548. X
  1549. X/* variable assignment tree element */
  1550. X
  1551. Xstruct varasg {
  1552. X    int type;            /* nonzero means array */
  1553. X    int ifil[3];
  1554. X    char *name;
  1555. X    char *str;            /* should've been a union here.  oh well */
  1556. X    Lklist arr;
  1557. X    };
  1558. X
  1559. X/* lvalue for variable assignment/expansion */
  1560. X
  1561. Xstruct value {
  1562. X    int isarr;
  1563. X    struct param *pm;        /* parameter node */
  1564. X    int a;                    /* first element of array slice, or -1 */
  1565. X    int b;                    /* last element of array slice, or -1 */
  1566. X    };
  1567. X
  1568. Xstruct fdpair {
  1569. X    int fd1,fd2;
  1570. X    };
  1571. X
  1572. X/* tty state structure */
  1573. X
  1574. Xstruct ttyinfo {
  1575. X#ifdef TERMIOS
  1576. X    struct termios tio;
  1577. X#else
  1578. X#ifdef TERMIO
  1579. X    struct termio tio;
  1580. X#else
  1581. X    struct sgttyb sgttyb;
  1582. X    int lmodes;
  1583. X    struct tchars tchars;
  1584. X    struct ltchars ltchars;
  1585. X#endif
  1586. X#endif
  1587. X#ifdef TIOCGWINSZ
  1588. X    struct winsize winsize;
  1589. X#endif
  1590. X    };
  1591. X
  1592. XEXTERN struct ttyinfo savedttyinfo;
  1593. X
  1594. X/* entry in job table */
  1595. X
  1596. Xstruct job {
  1597. X    long gleader;                    /* process group leader of this job */
  1598. X    int stat;
  1599. X    char *pwd;                        /* current working dir of shell when
  1600. X                                            this job was spawned */
  1601. X    struct process *procs;        /* list of processes */
  1602. X    Lklist filelist;                /* list of files to delete when done */
  1603. X    };
  1604. X
  1605. X#define STAT_CHANGED 1        /* status changed and not reported */
  1606. X#define STAT_STOPPED 2        /* all procs stopped or exited */
  1607. X#define STAT_TIMED 4            /* job is being timed */
  1608. X#define STAT_DONE 8
  1609. X#define STAT_LOCKED 16        /* shell is finished creating this job,
  1610. X                                        may be deleted from job table */
  1611. X#define STAT_INUSE 64        /* this job entry is in use */
  1612. X
  1613. X#define SP_RUNNING -1        /* fake statusp for running jobs */
  1614. X
  1615. X#ifndef RUSAGE_CHILDREN
  1616. X#undef HAS_RUSAGE
  1617. X#endif
  1618. X
  1619. Xstruct timeinfo {
  1620. X#ifdef HAS_RUSAGE
  1621. X    struct rusage ru;
  1622. X#else
  1623. X    long ut, st;
  1624. X#endif
  1625. X};
  1626. X
  1627. X/* node in job process lists */
  1628. X
  1629. X#define JOBTEXTSIZE 80
  1630. X
  1631. Xstruct process {
  1632. X    struct process *next;
  1633. X    long pid;
  1634. X    char text[JOBTEXTSIZE];        /* text to print when 'jobs' is run */
  1635. X    int statusp;                    /* return code from wait3() */
  1636. X    struct timeinfo ti;
  1637. X    time_t bgtime;                    /* time job was spawned */
  1638. X    time_t endtime;                /* time job exited */
  1639. X    };
  1640. X
  1641. X/* node in alias hash table */
  1642. X
  1643. Xstruct alias {
  1644. X    struct hashnode *next; int canfree; char *nam; /* hash data */
  1645. X    char *text;            /* expansion of alias */
  1646. X    int cmd;                /* one for regular aliases,
  1647. X                                zero for global aliases,
  1648. X                                negative for reserved words */
  1649. X    int inuse;            /* alias is being expanded */
  1650. X    };
  1651. X
  1652. X/* node in sched list */
  1653. X
  1654. Xstruct schedcmd {
  1655. X    struct schedcmd *next;
  1656. X    char *cmd;        /* command to run */
  1657. X    time_t time;    /* when to run it */
  1658. X    };
  1659. X
  1660. X#define MAXAL 20    /* maximum number of aliases expanded at once */
  1661. X
  1662. X/* hash table node */
  1663. X
  1664. Xstruct hashnode {
  1665. X    struct hashnode *next;
  1666. X    int canfree;        /* nam is free()able */
  1667. X    char *nam;
  1668. X    };
  1669. X
  1670. X/* hash table */
  1671. X
  1672. Xstruct hashtab {
  1673. X    int hsize;                            /* size of nodes[] */
  1674. X    int ct;                                /* # of elements */
  1675. X    struct hashnode **nodes;        /* array of size hsize */
  1676. X    };
  1677. X
  1678. X/* history entry */
  1679. X
  1680. Xstruct histent {
  1681. X    char *lex;            /* lexical history line */
  1682. X    char *lit;            /* literal history line */
  1683. X    time_t stim;        /* command started time (datestamp) */
  1684. X    time_t ftim;        /* command finished time */
  1685. X    int flags;        /* Misc flags */
  1686. X    };
  1687. X
  1688. X#define HIST_OLD    0x00000001    /* Command is already written to disk*/
  1689. X
  1690. X/* completion control */
  1691. X
  1692. Xstruct compctl {
  1693. X    struct hashnode *next; int canfree; char *nam; /* hash data */
  1694. X    int mask;
  1695. X    char *keyvar;
  1696. X    };
  1697. X
  1698. X#define CC_FILES        1
  1699. X#define CC_COMMPATH    2
  1700. X#define CC_HOSTS        4
  1701. X#define CC_OPTIONS    8
  1702. X#define CC_VARS        16
  1703. X#define CC_BINDINGS    32
  1704. X#define CC_USRKEYS   64
  1705. X
  1706. Xextern char *sys_errlist[];
  1707. Xextern int errno;
  1708. X
  1709. X/* values in opts[] array */
  1710. X
  1711. X#define OPT_INVALID 1    /* opt is invalid, like -$ */
  1712. X#define OPT_UNSET 0
  1713. X#define OPT_SET 2
  1714. X
  1715. X/* the options */
  1716. X
  1717. Xstruct option {
  1718. X    char *name;
  1719. X    char id;            /* corresponding letter */
  1720. X    };
  1721. X
  1722. X#define CORRECT '0'
  1723. X#define NOCLOBBER '1'
  1724. X#define NOBADPATTERN '2'
  1725. X#define NONOMATCH '3'
  1726. X#define GLOBDOTS '4'
  1727. X#define NOTIFY '5'
  1728. X#define BGNICE '6'
  1729. X#define IGNOREEOF '7'
  1730. X#define MARKDIRS '8'
  1731. X#define AUTOLIST '9'
  1732. X#define NOBEEP 'B'
  1733. X#define PRINTEXITVALUE 'C'
  1734. X#define PUSHDTOHOME 'D'
  1735. X#define PUSHDSILENT 'E'
  1736. X#define NOGLOBOPT 'F'
  1737. X#define NULLGLOB 'G'
  1738. X#define RMSTARSILENT 'H'
  1739. X#define IGNOREBRACES 'I'
  1740. X#define AUTOCD 'J'
  1741. X#define NOBANGHIST 'K'
  1742. X#define SUNKEYBOARDHACK 'L'
  1743. X#define SINGLELINEZLE 'M'
  1744. X#define AUTOPUSHD 'N'
  1745. X#define CORRECTALL 'O'
  1746. X#define RCEXPANDPARAM 'P'
  1747. X#define PATHDIRS 'Q'
  1748. X#define LONGLISTJOBS 'R'
  1749. X#define RECEXACT 'S'
  1750. X#define CDABLEVARS 'T'
  1751. X#define MAILWARNING 'U'
  1752. X#define NOPROMPTCR 'V'
  1753. X#define AUTORESUME 'W'
  1754. X#define LISTTYPES 'X'
  1755. X#define MENUCOMPLETE 'Y'
  1756. X#define USEZLE 'Z'
  1757. X#define ALLEXPORT 'a'
  1758. X#define ERREXIT 'e'
  1759. X#define NORCS 'f'
  1760. X#define HISTIGNORESPACE 'g'
  1761. X#define HISTIGNOREDUPS 'h'
  1762. X#define INTERACTIVE 'i'
  1763. X#define HISTLIT 'j'
  1764. X#define INTERACTIVECOMMENTS 'k'
  1765. X#define LOGINSHELL 'l'
  1766. X#define MONITOR 'm'
  1767. X#define NOEXEC 'n'
  1768. X#define SHINSTDIN 's'
  1769. X#define NOUNSET 'u'
  1770. X#define VERBOSE 'v'
  1771. X#define CHASELINKS 'w'
  1772. X#define XTRACE 'x'
  1773. X#define SHWORDSPLIT 'y'
  1774. X#define MENUCOMPLETEBEEP '\2'
  1775. X#define HISTNOSTORE '\3'
  1776. X#define EXTENDEDGLOB '\5'
  1777. X#define GLOBCOMPLETE '\6'
  1778. X#define CSHJUNKIEQUOTES '\7'
  1779. X#define PUSHDMINUS '\10'
  1780. X#define CSHJUNKIELOOPS '\11'
  1781. X#define RCQUOTES '\12'
  1782. X#define KSHOPTIONPRINT '\13'
  1783. X#define NOSHORTLOOPS '\14'
  1784. X#define LASTMENU '\15'
  1785. X#define AUTOMENU '\16'
  1786. X#define HISTVERIFY '\17'
  1787. X#define NOLISTBEEP '\20'
  1788. X#define NOHUP '\21'
  1789. X#define NOEQUALS '\22'
  1790. X#define CSHNULLGLOB '\23'
  1791. X#define HASHCMDS '\24'
  1792. X#define HASHDIRS '\25'
  1793. X#define NUMERICGLOBSORT '\26'
  1794. X#define BRACECCL '\27'
  1795. X#define HASHLISTALL '\30'
  1796. X#define OVERSTRIKE '\31'
  1797. X#define NOHISTBEEP '\32'
  1798. X#define PUSHDIGNOREDUPS '\33'
  1799. X#define AUTOREMOVESLASH '\34'
  1800. X#define EXTENDEDHISTORY '\35'
  1801. X#define APPENDHISTORY '\36'
  1802. X
  1803. X#ifndef GLOBALS
  1804. Xextern struct option optns[];
  1805. X#else
  1806. Xstruct option optns[] = {
  1807. X    {"correct",CORRECT},
  1808. X    {"noclobber",NOCLOBBER},
  1809. X    {"nobadpattern",NOBADPATTERN},
  1810. X    {"nonomatch",NONOMATCH},
  1811. X    {"globdots",GLOBDOTS},
  1812. X    {"notify",NOTIFY},
  1813. X    {"bgnice",BGNICE},
  1814. X    {"ignoreeof",IGNOREEOF},
  1815. X    {"markdirs",MARKDIRS},
  1816. X    {"autolist",AUTOLIST},
  1817. X    {"nobeep",NOBEEP},
  1818. X    {"printexitvalue",PRINTEXITVALUE},
  1819. X    {"pushdtohome",PUSHDTOHOME},
  1820. X    {"pushdsilent",PUSHDSILENT},
  1821. X    {"noglob",NOGLOBOPT},
  1822. X    {"nullglob",NULLGLOB},
  1823. X    {"rmstarsilent",RMSTARSILENT},
  1824. X    {"ignorebraces",IGNOREBRACES},
  1825. X    {"braceccl",BRACECCL},
  1826. X    {"autocd",AUTOCD},
  1827. X    {"nobanghist",NOBANGHIST},
  1828. X    {"sunkeyboardhack",SUNKEYBOARDHACK},
  1829. X    {"singlelinezle",SINGLELINEZLE},
  1830. X    {"autopushd",AUTOPUSHD},
  1831. X    {"correctall",CORRECTALL},
  1832. X    {"rcexpandparam",RCEXPANDPARAM},
  1833. X    {"pathdirs",PATHDIRS},
  1834. X    {"longlistjobs",LONGLISTJOBS},
  1835. X    {"recexact",RECEXACT},
  1836. X    {"cdablevars",CDABLEVARS},
  1837. X    {"mailwarning",MAILWARNING},
  1838. X    {"nopromptcr",NOPROMPTCR},
  1839. X    {"autoresume",AUTORESUME},
  1840. X    {"listtypes",LISTTYPES},
  1841. X    {"menucomplete",MENUCOMPLETE},
  1842. X    {"zle",USEZLE},
  1843. X    {"allexport",ALLEXPORT},
  1844. X    {"errexit",ERREXIT},
  1845. X    {"norcs",NORCS},
  1846. X    {"histignorespace",HISTIGNORESPACE},
  1847. X    {"histignoredups",HISTIGNOREDUPS},
  1848. X    {"interactive",INTERACTIVE},
  1849. X    {"histlit",HISTLIT},
  1850. X    {"interactivecomments",INTERACTIVECOMMENTS},
  1851. X    {"login",LOGINSHELL},
  1852. X    {"monitor",MONITOR},
  1853. X    {"noexec",NOEXEC},
  1854. X    {"shinstdin",SHINSTDIN},
  1855. X    {"nounset",NOUNSET},
  1856. X    {"verbose",VERBOSE},
  1857. X    {"chaselinks",CHASELINKS},
  1858. X    {"xtrace",XTRACE},
  1859. X    {"shwordsplit",SHWORDSPLIT},
  1860. X    {"menucompletebeep",MENUCOMPLETEBEEP},
  1861. X    {"histnostore",HISTNOSTORE},
  1862. X    {"extendedglob",EXTENDEDGLOB},
  1863. X    {"globcomplete",GLOBCOMPLETE},
  1864. X    {"cshjunkiequotes",CSHJUNKIEQUOTES},
  1865. X    {"pushdminus",PUSHDMINUS},
  1866. X    {"cshjunkieloops",CSHJUNKIELOOPS},
  1867. X    {"rcquotes",RCQUOTES},
  1868. X    {"noshortloops",NOSHORTLOOPS},
  1869. X    {"lastmenu",LASTMENU},
  1870. X    {"automenu",AUTOMENU},
  1871. X    {"histverify",HISTVERIFY},
  1872. X    {"nolistbeep",NOLISTBEEP},
  1873. X    {"nohup",NOHUP},
  1874. X    {"noequals",NOEQUALS},
  1875. X    {"kshoptionprint",KSHOPTIONPRINT},
  1876. X    {"cshnullglob",CSHNULLGLOB},
  1877. X    {"hashcmds",HASHCMDS},
  1878. X    {"hashdirs",HASHDIRS},
  1879. X    {"numericglobsort",NUMERICGLOBSORT},
  1880. X    {"hashlistall",HASHLISTALL},
  1881. X    {"overstrike",OVERSTRIKE},
  1882. X    {"nohistbeep",NOHISTBEEP},
  1883. X    {"pushdignoredups",PUSHDIGNOREDUPS},
  1884. X    {"autoremoveslash",AUTOREMOVESLASH},
  1885. X    {"extendedhistory",EXTENDEDHISTORY},
  1886. X    {"appendhistory",APPENDHISTORY},
  1887. X    {NULL,0}
  1888. X};
  1889. X#endif
  1890. X
  1891. X#define ALSTAT_MORE 1    /* last alias ended with ' ' */
  1892. X#define ALSTAT_JUNK 2    /* don't put word in history List */
  1893. X
  1894. X#undef isset
  1895. X#define isset(X) (opts[(int)X] == OPT_SET)
  1896. X#define unset(X) (opts[(int)X] == OPT_UNSET)
  1897. X#define interact (isset(INTERACTIVE))
  1898. X#define jobbing (isset(MONITOR))
  1899. X#define jobbingv opts[MONITOR]
  1900. X#define nointr() signal(SIGINT,SIG_IGN)
  1901. X#define islogin (isset(LOGINSHELL))
  1902. X
  1903. X#ifndef SYSVR4
  1904. X#ifndef _IBMR2
  1905. X#undef WIFSTOPPED
  1906. X#undef WIFSIGNALED
  1907. X#undef WIFEXITED
  1908. X#undef WEXITSTATUS
  1909. X#undef WTERMSIG
  1910. X#undef WSTOPSIG
  1911. X#undef WCOREDUMP
  1912. X
  1913. X#define WIFSTOPPED(X) (((X)&0377)==0177)
  1914. X#define WIFSIGNALED(X) (((X)&0377)!=0&&((X)&0377)!=0177)
  1915. X#define WIFEXITED(X) (((X)&0377)==0)
  1916. X#define WEXITSTATUS(X) (((X)>>8)&0377)
  1917. X#define WTERMSIG(X) ((X)&0177)
  1918. X#define WSTOPSIG(X) (((X)>>8)&0377)
  1919. X#endif
  1920. X#define WCOREDUMP(X) ((X)&0200)
  1921. X#endif
  1922. X
  1923. X#ifndef S_ISBLK
  1924. X#define    _IFMT        0170000
  1925. X#define    _IFDIR    0040000
  1926. X#define    _IFCHR    0020000
  1927. X#define    _IFBLK    0060000
  1928. X#define    _IFREG    0100000
  1929. X#define    _IFIFO    0010000
  1930. X#define    S_ISBLK(m)    (((m)&_IFMT) == _IFBLK)
  1931. X#define    S_ISCHR(m)    (((m)&_IFMT) == _IFCHR)
  1932. X#define    S_ISDIR(m)    (((m)&_IFMT) == _IFDIR)
  1933. X#define    S_ISFIFO(m)    (((m)&_IFMT) == _IFIFO)
  1934. X#define    S_ISREG(m)    (((m)&_IFMT) == _IFREG)
  1935. X#endif
  1936. X
  1937. X#ifndef _IFMT
  1938. X#define _IFMT 0170000
  1939. X#endif
  1940. X
  1941. X#ifndef S_ISSOCK
  1942. X#define    _IFSOCK    0140000
  1943. X#define    S_ISSOCK(m)    (((m)&_IFMT) == _IFSOCK)
  1944. X#endif
  1945. X
  1946. X#ifndef S_ISLNK
  1947. X#define    _IFLNK    0120000
  1948. X#define    S_ISLNK(m)    (((m)&_IFMT) == _IFLNK)
  1949. X#endif
  1950. X
  1951. X#if S_IFIFO == S_IFSOCK
  1952. X#undef S_IFIFO
  1953. X#endif
  1954. X
  1955. X#ifndef S_IFIFO
  1956. X#define NO_FIFOS
  1957. X#endif
  1958. X
  1959. X/* buffered shell input for non-interactive shells */
  1960. X
  1961. XEXTERN FILE *bshin;
  1962. X
  1963. X/* NULL-terminated arrays containing path, cdpath, etc. */
  1964. X
  1965. XEXTERN char **path,**cdpath,**fpath,**watch,**mailpath;
  1966. XEXTERN char **manpath,**tildedirs,**fignore;
  1967. XEXTERN char **hosts,**psvar;
  1968. X
  1969. X/* named directories */
  1970. X
  1971. XEXTERN char **userdirs,**usernames;
  1972. X
  1973. X/* size of userdirs[], # of userdirs */
  1974. X
  1975. XEXTERN int userdirsz,userdirct;
  1976. X
  1977. XEXTERN char *mailfile;
  1978. X
  1979. XEXTERN char *yytext;
  1980. X
  1981. X/* error/break flag */
  1982. X
  1983. XEXTERN int errflag;
  1984. X
  1985. XEXTERN char *tokstr;
  1986. XEXTERN int tok, tokfd;
  1987. X
  1988. X/* lexical analyzer error flag */
  1989. X
  1990. XEXTERN int lexstop;
  1991. X
  1992. X/* suppress error messages */
  1993. X
  1994. XEXTERN int noerrs;
  1995. X
  1996. X/* current history event number */
  1997. X
  1998. XEXTERN int curhist;
  1999. X
  2000. X/* if != 0, this is the first line of the command */
  2001. X
  2002. XEXTERN int isfirstln;
  2003. X
  2004. X/* if != 0, this is the first char of the command (not including
  2005. X    white space */
  2006. X
  2007. XEXTERN int isfirstch;
  2008. X
  2009. X/* number of history entries */
  2010. X
  2011. XEXTERN int histentct;
  2012. X
  2013. X/* array of history entries */
  2014. X
  2015. XEXTERN Histent histentarr;
  2016. X
  2017. X/* capacity of history lists */
  2018. X
  2019. XEXTERN int histsiz,lithistsiz;
  2020. X
  2021. X/* if = 1, we have performed history substitution on the current line
  2022. X     if = 2, we have used the 'p' modifier */
  2023. X
  2024. XEXTERN int histdone;
  2025. X
  2026. X/* default event (usually curhist-1, that is, "!!") */
  2027. X
  2028. XEXTERN int defev;
  2029. X
  2030. X/* != 0 if we are about to read a command word */
  2031. X
  2032. XEXTERN int incmdpos;
  2033. X
  2034. X/* != 0 if we are in the middle of a [[ ... ]] */
  2035. X
  2036. XEXTERN int incond;
  2037. X
  2038. X/* != 0 if we are after a redirection (for ctxtlex only) */
  2039. X
  2040. XEXTERN int inredir;
  2041. X
  2042. X/* != 0 if we are about to read a case pattern */
  2043. X
  2044. XEXTERN int incasepat;
  2045. X
  2046. X/* != 0 if we just read FUNCTION */
  2047. X
  2048. XEXTERN int infunc;
  2049. X
  2050. X/* != 0 if we just read a newline */
  2051. X
  2052. XEXTERN int isnewlin;
  2053. X
  2054. X/* the lists of history events */
  2055. X
  2056. XEXTERN Lklist histlist,lithistlist;
  2057. X
  2058. X/* the directory stack */
  2059. X
  2060. XEXTERN Lklist dirstack;
  2061. X
  2062. X/* the zle buffer stack */
  2063. X
  2064. XEXTERN Lklist bufstack;
  2065. X
  2066. X/* the input queue (stack?)
  2067. X
  2068. X    inbuf    = start of buffer
  2069. X    inbufptr = location in buffer (= inbuf for a FULL buffer)
  2070. X                                            (= inbuf+inbufsz for an EMPTY buffer)
  2071. X    inbufct  = # of chars in buffer (inbufptr+inbufct == inbuf+inbufsz)
  2072. X    inbufsz  = max size of buffer
  2073. X*/
  2074. X
  2075. XEXTERN char *inbuf,*inbufptr;
  2076. XEXTERN int inbufct,inbufsz;
  2077. X
  2078. XEXTERN char *ifs;        /* $IFS */
  2079. X
  2080. XEXTERN char *oldpwd;    /* $OLDPWD */
  2081. X
  2082. XEXTERN char *underscore; /* $_ */
  2083. X
  2084. X/* != 0 if this is a subshell */
  2085. X
  2086. XEXTERN int subsh;
  2087. X
  2088. X/* # of break levels */
  2089. X
  2090. XEXTERN int breaks;
  2091. X
  2092. X/* != 0 if we have a return pending */
  2093. X
  2094. XEXTERN int retflag;
  2095. X
  2096. X/* how far we've hashed the PATH so far */
  2097. X
  2098. XEXTERN char **pathchecked;
  2099. X
  2100. X/* # of nested loops we are in */
  2101. X
  2102. XEXTERN int loops;
  2103. X
  2104. X/* # of continue levels */
  2105. X
  2106. XEXTERN int contflag;
  2107. X
  2108. X/* the job we are working on */
  2109. X
  2110. XEXTERN int thisjob;
  2111. X
  2112. X/* the current job (+) */
  2113. X
  2114. XEXTERN int curjob;
  2115. X
  2116. X/* the previous job (-) */
  2117. X
  2118. XEXTERN int prevjob;
  2119. X
  2120. X/* hash table containing the aliases and reserved words */
  2121. X
  2122. XEXTERN Hashtab aliastab;
  2123. X
  2124. X/* hash table containing the parameters */
  2125. X
  2126. XEXTERN Hashtab paramtab;
  2127. X
  2128. X/* hash table containing the builtins/shfuncs/hashed commands */
  2129. X
  2130. XEXTERN Hashtab cmdnamtab;
  2131. X
  2132. X/* hash table containing the zle multi-character bindings */
  2133. X
  2134. XEXTERN Hashtab xbindtab;
  2135. X
  2136. X/* hash table for completion info for commands */
  2137. X
  2138. XEXTERN Hashtab compctltab;
  2139. X
  2140. X/* default completion infos */
  2141. X
  2142. XEXTERN struct compctl cc_compos, cc_default;
  2143. X
  2144. X/* the job table */
  2145. X
  2146. XEXTERN struct job jobtab[MAXJOB];
  2147. X
  2148. X/* shell timings */
  2149. X
  2150. X#ifndef HAS_RUSAGE
  2151. XEXTERN struct tms shtms;
  2152. X#endif
  2153. X
  2154. X/* the list of sched jobs pending */
  2155. X
  2156. XEXTERN struct schedcmd *schedcmds;
  2157. X
  2158. X/* the last l for s/l/r/ history substitution */
  2159. X
  2160. XEXTERN char *hsubl;
  2161. X
  2162. X/* the last r for s/l/r/ history substitution */
  2163. X
  2164. XEXTERN char *hsubr;
  2165. X
  2166. XEXTERN char *username;    /* $USERNAME */
  2167. XEXTERN char *logname;    /* $LOGNAME */
  2168. XEXTERN long lastval;        /* $? */
  2169. XEXTERN long baud;            /* $BAUD */
  2170. XEXTERN long columns;        /* $COLUMNS */
  2171. XEXTERN long lines;        /* $LINES */
  2172. XEXTERN long reporttime; /* $REPORTTIME */
  2173. X
  2174. X/* input fd from the coprocess */
  2175. X
  2176. XEXTERN int coprocin;
  2177. X
  2178. X/* output fd from the coprocess */
  2179. X
  2180. XEXTERN int coprocout;
  2181. X
  2182. XEXTERN long mailcheck;    /* $MAILCHECK */
  2183. XEXTERN long logcheck;    /* $LOGCHECK */
  2184. X
  2185. X/* the last time we checked mail */
  2186. X
  2187. XEXTERN time_t lastmailcheck;
  2188. X
  2189. X/* the last time we checked the people in the WATCH variable */
  2190. X
  2191. XEXTERN time_t lastwatch;
  2192. X
  2193. X/* the last time we did the periodic() shell function */
  2194. X
  2195. XEXTERN time_t lastperiod;
  2196. X
  2197. X/* $SECONDS = time(NULL) - shtimer */
  2198. X
  2199. XEXTERN time_t shtimer;
  2200. X
  2201. XEXTERN long mypid;        /* $$ */
  2202. XEXTERN long lastpid;        /* $! */
  2203. XEXTERN long ppid;            /* $PPID */
  2204. X
  2205. X/* the process group of the shell */
  2206. X
  2207. XEXTERN long mypgrp;
  2208. X
  2209. XEXTERN char *pwd;            /* $PWD */
  2210. XEXTERN char *optarg;        /* $OPTARG */
  2211. XEXTERN long zoptind;        /* $OPTIND */
  2212. XEXTERN char *prompt;        /* $PROMPT */
  2213. XEXTERN char *rprompt;    /* $RPROMPT */
  2214. XEXTERN char *prompt2;    /* etc. */
  2215. XEXTERN char *prompt3;
  2216. XEXTERN char *prompt4;
  2217. XEXTERN char *sprompt;
  2218. XEXTERN char *timefmt;
  2219. XEXTERN char *watchfmt;
  2220. XEXTERN char *wordchars;
  2221. XEXTERN char *fceditparam;
  2222. XEXTERN char *tmpprefix;
  2223. XEXTERN char *rstring, *Rstring;
  2224. XEXTERN char *postedit;
  2225. X
  2226. XEXTERN char *argzero;    /* $0 */
  2227. X
  2228. XEXTERN char *hackzero;
  2229. X
  2230. X/* the hostname */
  2231. X
  2232. XEXTERN char *hostnam;
  2233. X
  2234. XEXTERN char *home;        /* $HOME */
  2235. XEXTERN char **pparams;    /* $argv */
  2236. X
  2237. X/* the default command for null commands */
  2238. X
  2239. XEXTERN char *nullcmd;
  2240. XEXTERN char *readnullcmd;
  2241. X
  2242. X/* the List of local variables we have to destroy */
  2243. X
  2244. XEXTERN Lklist locallist;
  2245. X
  2246. X/* the shell input fd */
  2247. X
  2248. XEXTERN int SHIN;
  2249. X
  2250. X/* the shell tty fd */
  2251. X
  2252. XEXTERN int SHTTY;
  2253. X
  2254. X/* the stack of aliases we are expanding */
  2255. X
  2256. XEXTERN struct alias *alstack[MAXAL];
  2257. X
  2258. X/* the alias stack pointer; also, the number of aliases currently
  2259. X     being expanded */
  2260. X
  2261. XEXTERN int alstackind;
  2262. X
  2263. X/* != 0 means we are reading input from a string */
  2264. X
  2265. XEXTERN int strin;
  2266. X
  2267. X/* period between periodic() commands, in seconds */
  2268. X
  2269. XEXTERN long period;
  2270. X
  2271. X/* != 0 means history substitution is turned off */
  2272. X
  2273. XEXTERN int stophist;
  2274. X
  2275. XEXTERN int lithist;
  2276. X
  2277. X/* this line began with a space, so junk it if HISTIGNORESPACE is on */
  2278. X
  2279. XEXTERN int spaceflag;
  2280. X
  2281. X/* don't do spelling correction */
  2282. X
  2283. XEXTERN int nocorrect;
  2284. X
  2285. X/* != 0 means we have removed the current event from the history List */
  2286. X
  2287. XEXTERN int histremmed;
  2288. X
  2289. X/* the options; e.g. if opts['a'] == OPT_SET, -a is turned on */
  2290. X
  2291. XEXTERN int opts[128];
  2292. X
  2293. XEXTERN long lineno;        /* LINENO */
  2294. XEXTERN long listmax;        /* LISTMAX */
  2295. XEXTERN long savehist;    /* SAVEHIST */
  2296. XEXTERN long shlvl;        /* SHLVL */
  2297. XEXTERN long tmout;        /* TMOUT */
  2298. XEXTERN long dirstacksize;    /* DIRSTACKSIZE */
  2299. X
  2300. X/* != 0 means we have called execlist() and then intend to exit(),
  2301. X     so don't fork if not necessary */
  2302. X
  2303. XEXTERN int exiting;
  2304. X
  2305. XEXTERN int lastbase;        /* last input base we used */
  2306. X
  2307. X/* the limits for child processes */
  2308. X
  2309. X#ifdef RLIM_INFINITY
  2310. XEXTERN struct rlimit limits[RLIM_NLIMITS];
  2311. X#endif
  2312. X
  2313. X/* the current word in the history List */
  2314. X
  2315. XEXTERN char *hlastw;
  2316. X
  2317. X/* pointer into the history line */
  2318. X
  2319. XEXTERN char *hptr;
  2320. X
  2321. X/* the current history line */
  2322. X
  2323. XEXTERN char *chline;
  2324. X
  2325. X/* the termcap buffer */
  2326. X
  2327. XEXTERN char termbuf[1024];
  2328. X
  2329. X/* $TERM */
  2330. X
  2331. XEXTERN char *term;
  2332. X
  2333. X/* != 0 if this $TERM setup is usable */
  2334. X
  2335. XEXTERN int termok;
  2336. X
  2337. X/* flag for CSHNULLGLOB */
  2338. X
  2339. XEXTERN int badcshglob;
  2340. X
  2341. X/* max size of histline */
  2342. X
  2343. XEXTERN int hlinesz;
  2344. X
  2345. X/* the alias expansion status - if == ALSTAT_MORE, we just finished
  2346. X    expanding an alias ending with a space */
  2347. X
  2348. XEXTERN int alstat;
  2349. X
  2350. X/* we have printed a 'you have stopped (running) jobs.' message */
  2351. X
  2352. XEXTERN int stopmsg;
  2353. X
  2354. X/* the default tty state */
  2355. X
  2356. XEXTERN struct ttyinfo shttyinfo;
  2357. X
  2358. X/* $TTY */
  2359. X
  2360. XEXTERN char *ttystrname;
  2361. X
  2362. X/* 1 if ttyctl -f has been executed */
  2363. X
  2364. XEXTERN int ttyfrozen;
  2365. X
  2366. X/* list of memory heaps */
  2367. X
  2368. XEXTERN Lklist heaplist;
  2369. X
  2370. X/* != 0 if we are allocating in the heaplist */
  2371. X
  2372. XEXTERN int useheap;
  2373. X
  2374. X/* pid of process undergoing 'process substitution' */
  2375. X
  2376. XEXTERN int cmdoutpid;
  2377. X
  2378. X/* exit status of process undergoing 'process substitution' */
  2379. X
  2380. XEXTERN int cmdoutval;
  2381. X
  2382. X#include "signals.h"
  2383. X
  2384. X#ifdef GLOBALS
  2385. X
  2386. X/* signal names */
  2387. Xchar **sigptr = sigs;
  2388. X
  2389. X/* tokens */
  2390. Xchar *ztokens = "#$^*()$=|{}[]`<>?~`,'\"\\";
  2391. X
  2392. X#else
  2393. Xextern char *ztokens,**sigptr;
  2394. X#endif
  2395. X
  2396. X#define SIGERR (SIGCOUNT+1)
  2397. X#define SIGDEBUG (SIGCOUNT+2)
  2398. X#define VSIGCOUNT (SIGCOUNT+3)
  2399. X#define SIGEXIT 0
  2400. X
  2401. X/* signals that are trapped = 1, signals ignored =2 */
  2402. X
  2403. XEXTERN int sigtrapped[VSIGCOUNT];
  2404. X
  2405. X/* trap functions for each signal */
  2406. X
  2407. XEXTERN List sigfuncs[VSIGCOUNT];
  2408. X
  2409. X/* $HISTCHARS */
  2410. X
  2411. XEXTERN unsigned char bangchar,hatchar,hashchar;
  2412. X
  2413. XEXTERN int eofseen;
  2414. X
  2415. X/* we are parsing a line sent to use by the editor */
  2416. X
  2417. XEXTERN int zleparse;
  2418. X
  2419. XEXTERN int wordbeg;
  2420. X
  2421. XEXTERN int parbegin;
  2422. X
  2423. X/* interesting termcap strings */
  2424. X
  2425. X#define TCCLEARSCREEN 0
  2426. X#define TCLEFT 1
  2427. X#define TCMULTLEFT 2
  2428. X#define TCRIGHT 3
  2429. X#define TCMULTRIGHT 4
  2430. X#define TCUP 5
  2431. X#define TCMULTUP 6
  2432. X#define TCDOWN 7
  2433. X#define TCMULTDOWN 8
  2434. X#define TCDEL 9
  2435. X#define TCMULTDEL 10
  2436. X#define TCINS 11
  2437. X#define TCMULTINS 12
  2438. X#define TCCLEAREOD 13
  2439. X#define TCCLEAREOL 14
  2440. X#define TCINSLINE 15
  2441. X#define TCDELLINE 16
  2442. X#define TC_COUNT 17
  2443. X
  2444. X/* lengths of each string */
  2445. X
  2446. XEXTERN int tclen[TC_COUNT];
  2447. X
  2448. XEXTERN char *tcstr[TC_COUNT];
  2449. X
  2450. X#ifdef GLOBALS
  2451. X
  2452. X/* names of the strings we want */
  2453. X
  2454. Xchar *tccapnams[TC_COUNT] = {
  2455. X    "cl","le","LE","nd","RI","up","UP","do",
  2456. X    "DO","dc","DC","ic","IC","cd","ce","al","dl"
  2457. X    };
  2458. X
  2459. X#else
  2460. Xextern char *tccapnams[TC_COUNT];
  2461. X#endif
  2462. X
  2463. X#define tccan(X) (!!tclen[X])
  2464. X
  2465. X#define HISTFLAG_DONE   1
  2466. X#define HISTFLAG_NOEXEC 2
  2467. X#define HISTFLAG_RECALL 4
  2468. X
  2469. X#include "ztype.h"
  2470. X#include "funcs.h"
  2471. X
  2472. X#ifdef HAS_SETPGID
  2473. X#define setpgrp setpgid
  2474. X#endif
  2475. X
  2476. X#define _INCLUDE_POSIX_SOURCE
  2477. X#define _INCLUDE_XOPEN_SOURCE
  2478. X#define _INCLUDE_HPUX_SOURCE
  2479. X
  2480. X#ifdef SV_BSDSIG
  2481. X#define SV_INTERRUPT SV_BSDSIG
  2482. X#endif
  2483. X
  2484. X#ifdef HAS_SIGRELSE
  2485. X#define blockchld() sighold(SIGCHLD)
  2486. X#define unblockchld() sigrelse(SIGCHLD)
  2487. X#define chldsuspend() sigpause(SIGCHLD)
  2488. X#else
  2489. X#define blockchld() sigblock(sigmask(SIGCHLD))
  2490. X#define unblockchld() sigsetmask(0)
  2491. X#define chldsuspend() sigpause(0)
  2492. X#endif
  2493. END_OF_FILE
  2494.   if test 34760 -ne `wc -c <'src/zsh.h'`; then
  2495.     echo shar: \"'src/zsh.h'\" unpacked with wrong size!
  2496.   fi
  2497.   # end of 'src/zsh.h'
  2498. fi
  2499. echo shar: End of archive 11 \(of 22\).
  2500. cp /dev/null ark11isdone
  2501. MISSING=""
  2502. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
  2503.     if test ! -f ark${I}isdone ; then
  2504.     MISSING="${MISSING} ${I}"
  2505.     fi
  2506. done
  2507. if test "${MISSING}" = "" ; then
  2508.     echo You have unpacked all 22 archives.
  2509.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2510. else
  2511.     echo You still must unpack the following archives:
  2512.     echo "        " ${MISSING}
  2513. fi
  2514. exit 0
  2515.  
  2516. exit 0 # Just in case...
  2517.