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

  1. Newsgroups: comp.sources.misc
  2. From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  3. Subject:  v29i108:  zsh2.2 - The Z shell, Part12/17
  4. Message-ID: <1992May13.160617.10110@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4f4958fa69994fbb18b4bc808dc08443
  6. Date: Wed, 13 May 1992 16:06:17 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  10. Posting-number: Volume 29, Issue 108
  11. Archive-name: zsh2.2/part12
  12. Environment: BSD
  13. Supersedes: zsh2.1: Volume 24, Issue 1-19
  14.  
  15. #!/bin/sh
  16. # this is aa.12 (part 12 of zsh2.2)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file zsh2.2/src/utils.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" != 12; 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/utils.c'
  34. else
  35. echo 'x - continuing file zsh2.2/src/utils.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/utils.c' &&
  37. X    lineno = 0;
  38. X    oldshst = opts[SHINSTDIN];
  39. X    opts[SHINSTDIN] = OPT_UNSET;
  40. X    if ((SHIN = movefd(open(s,O_RDONLY))) == -1)
  41. X        {
  42. X        SHIN = fd;
  43. X        thisjob = cj;
  44. X        opts[SHINSTDIN] = oldshst;
  45. X        return 1;
  46. X        }
  47. X    bshin = fdopen(SHIN,"r");
  48. X    loop();
  49. X    fclose(bshin);
  50. X    bshin = obshin;
  51. X    opts[SHINSTDIN] = oldshst;
  52. X    SHIN = fd;
  53. X    thisjob = cj;
  54. X    errflag = 0;
  55. X    retflag = 0;
  56. X    lineno = oldlineno;
  57. X    return 0;
  58. X}
  59. X
  60. X/* try to source a file in the home directory */
  61. X
  62. Xvoid sourcehome(s) /**/
  63. Xchar *s;
  64. X{
  65. Xchar buf[MAXPATHLEN];
  66. Xchar *h;
  67. X
  68. X    if (!(h = getsparam("ZDOTDIR")))
  69. X        h = home;
  70. X    sprintf(buf,"%s/%s",h,s);
  71. X    (void) source(buf);
  72. X}
  73. X
  74. X/* print an error */
  75. X
  76. Xvoid zerrnam(cmd,fmt,str,num) /**/
  77. Xchar *cmd; char *fmt; char *str;int num;
  78. X{
  79. X    if (cmd)
  80. X        {
  81. X        if (errflag || noerrs)
  82. X            return;
  83. X        errflag = 1;
  84. X        trashzle();
  85. X        if (isset(SHINSTDIN))
  86. X            fprintf(stderr,"%s: ",cmd);
  87. X        else
  88. X            fprintf(stderr,"%s: %s: ",argzero,cmd);
  89. X        }
  90. X    while (*fmt)
  91. X        if (*fmt == '%')
  92. X            {
  93. X            fmt++;
  94. X            switch(*fmt++)
  95. X                {
  96. X                case 's':
  97. X                    while (*str)
  98. X                        niceputc(*str++,stderr);
  99. X                    break;
  100. X                case 'l':
  101. X                    while (num--)
  102. X                        niceputc(*str++,stderr);
  103. X                    break;
  104. X                case 'd':
  105. X                    fprintf(stderr,"%d",num);
  106. X                    break;
  107. X                case '%':
  108. X                    putc('%',stderr);
  109. X                    break;
  110. X                case 'c':
  111. X                    niceputc(num,stderr);
  112. X                    break;
  113. X                case 'e':
  114. X                    if (num == EINTR)
  115. X                        {
  116. X                        fputs("interrupt\n",stderr);
  117. X                        errflag = 1;
  118. X                        return;
  119. X                        }
  120. X                    if (num == EIO)
  121. X                        fputs(sys_errlist[num],stderr);
  122. X                    else
  123. X                        {
  124. X                        fputc(tulower(sys_errlist[num][0]),stderr);
  125. X                        fputs(sys_errlist[num]+1,stderr);
  126. X                        }
  127. X                    break;
  128. X                }
  129. X            }
  130. X        else
  131. X            putc(*fmt++,stderr);
  132. X    if (unset(SHINSTDIN) && lineno)
  133. X        fprintf(stderr," [%ld]\n",lineno);
  134. X    else
  135. X        putc('\n',stderr);
  136. X    fflush(stderr);
  137. X}
  138. X
  139. Xvoid zerr(fmt,str,num) /**/
  140. Xchar *fmt; char *str;int num;
  141. X{
  142. X    if (errflag || noerrs)
  143. X        return;
  144. X    errflag = 1;
  145. X    trashzle();
  146. X    fprintf(stderr,"%s: ",(isset(SHINSTDIN)) ? "zsh" : argzero);
  147. X    zerrnam(NULL,fmt,str,num);
  148. X}
  149. X
  150. Xvoid niceputc(c,f) /**/
  151. Xint c;FILE *f;
  152. X{
  153. X    if (itok(c))
  154. X        {
  155. X        if (c >= Pound && c <= Comma)
  156. X            putc(ztokens[c-Pound],f);
  157. X        return;
  158. X        }
  159. X    c &= 0xff;
  160. X    if (isprint(c))
  161. X        putc(c,f);
  162. X    else if (c == '\n')
  163. X        {
  164. X        putc('\\',f);
  165. X        putc('n',f);
  166. X        }
  167. X    else
  168. X        {
  169. X        putc('^',f);
  170. X        putc(c|'@',f);
  171. X        }
  172. X}
  173. X
  174. X/* enable ^C interrupts */
  175. X
  176. Xvoid intr() /**/
  177. X{
  178. X#ifdef SV_INTERRUPT
  179. Xstatic struct sigvec vec = { handler,sigmask(SIGINT),SV_INTERRUPT };
  180. X
  181. X    if (interact)
  182. X        sigvec(SIGINT,&vec,NULL);
  183. X#else
  184. X    if (interact)
  185. X        signal(SIGINT,handler);
  186. X#endif
  187. X}
  188. X
  189. Xvoid noholdintr() /**/
  190. X{
  191. X    intr();
  192. X}
  193. X
  194. Xvoid holdintr() /**/
  195. X{
  196. X#ifdef SV_INTERRUPT
  197. Xstatic struct sigvec vec = { handler,sigmask(SIGINT),0 };
  198. X
  199. X    if (interact) sigvec(SIGINT,&vec,NULL);
  200. X#else
  201. X    if (interact) signal(SIGINT,SIG_IGN);
  202. X#endif
  203. X}
  204. X
  205. Xchar *fgetline(buf,len,in) /**/
  206. Xchar *buf;int len;FILE *in;
  207. X{
  208. X    if (!fgets(buf,len,in))
  209. X        return NULL;
  210. X    buf[len] = '\0';
  211. X    buf[strlen(buf)-1] = '\0';
  212. X    return buf;
  213. X}
  214. X
  215. X/* get a symlink-free pathname for s relative to PWD */
  216. X
  217. Xchar *findpwd(s) /**/
  218. Xchar *s;
  219. X{
  220. Xchar *t;
  221. X
  222. X    if (*s == '/')
  223. X        return xsymlink(s);
  224. X    s = tricat((pwd[1]) ? pwd : "","/",s);
  225. X    t = xsymlink(s);
  226. X    free(s);
  227. X    return t;
  228. X}
  229. X
  230. Xstatic char xbuf[MAXPATHLEN];
  231. X
  232. X#if 0
  233. Xchar *fixpwd(s) /**/
  234. Xchar *s;
  235. X{
  236. Xstruct stat sbuf,tbuf;
  237. Xchar *t;
  238. X
  239. X    strcpy(xbuf,"");
  240. X    if (*s == '/')
  241. X        t = ztrdup(s);
  242. X    else
  243. X        t = tricat((pwd[1]) ? pwd : "","/",s);
  244. X    (void) xsymlinks(t+1,0); 
  245. X    free(t);
  246. X    if (!*xbuf)
  247. X        strcpy(xbuf,"/");
  248. X    if (stat(xbuf,&sbuf) == 0 && stat(".",&tbuf) == 0)
  249. X        if (!(sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino))
  250. X            chdir(xbuf);
  251. X    return ztrdup(xbuf);
  252. X}
  253. X#endif
  254. X
  255. Xint ispwd(s) /**/
  256. Xchar *s;
  257. X{
  258. Xstruct stat sbuf,tbuf;
  259. X
  260. X    if (stat(s,&sbuf) == 0 && stat(".",&tbuf) == 0)
  261. X        if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino)
  262. X            return 1;
  263. X    return 0;
  264. X}
  265. X
  266. X/* expand symlinks in s, and remove other weird things */
  267. X
  268. Xchar *xsymlink(s) /**/
  269. Xchar *s;
  270. X{
  271. X    if (unset(CHASELINKS))
  272. X        return ztrdup(s);
  273. X    if (*s != '/')
  274. X        return NULL;
  275. X    strcpy(xbuf,"");
  276. X    if (xsymlinks(s+1,1))
  277. X        return ztrdup(s);
  278. X    if (!*xbuf)
  279. X        return ztrdup("/");
  280. X    return ztrdup(xbuf);
  281. X}
  282. X
  283. Xchar **slashsplit(s) /**/
  284. Xchar *s;
  285. X{
  286. Xchar *t,**r,**q;
  287. Xint t0;
  288. X
  289. X    if (!*s)
  290. X        return (char **) zcalloc(sizeof(char **));
  291. X    for (t = s, t0 = 0; *t; t++)
  292. X        if (*t == '/')
  293. X            t0++;
  294. X    q  = r = (char **) zalloc(sizeof(char **)*(t0+2));
  295. X    while (t = strchr(s,'/'))
  296. X        {
  297. X        *t = '\0';
  298. X        *q++ = ztrdup(s);
  299. X        *t = '/';
  300. X        while (*t == '/')
  301. X            t++;
  302. X        if (!*t)
  303. X            {
  304. X            *q = NULL;
  305. X            return r;
  306. X            }
  307. X        s = t;
  308. X        }
  309. X    *q++ = ztrdup(s);
  310. X    *q = NULL;
  311. X    return r;
  312. X}
  313. X
  314. Xint islink(s) /**/
  315. Xchar *s;
  316. X{
  317. X    return readlink(s,NULL,0) == 0;
  318. X}
  319. X
  320. X/* expands symlinks and .. or . expressions */
  321. X/* if flag = 0, only expand .. and . expressions */
  322. X
  323. Xint xsymlinks(s,flag) /**/
  324. Xchar *s;int flag;
  325. X{
  326. Xchar **pp,**opp;
  327. Xchar xbuf2[MAXPATHLEN],xbuf3[MAXPATHLEN];
  328. Xint t0;
  329. X
  330. X    opp = pp = slashsplit(s);
  331. X    for (; *pp; pp++)
  332. X        {
  333. X        if (!strcmp(*pp,"."))
  334. X            {
  335. X            free(*pp);
  336. X            continue;
  337. X            }
  338. X        if (!strcmp(*pp,".."))
  339. X            {
  340. X            char *p;
  341. X
  342. X            free(*pp);
  343. X            if (!strcmp(xbuf,"/"))
  344. X                continue;
  345. X            p = xbuf+strlen(xbuf);
  346. X            while (*--p != '/');
  347. X            *p = '\0';
  348. X            continue;
  349. X            }
  350. X        if (unset(CHASELINKS))
  351. X            {
  352. X            strcat(xbuf,"/");
  353. X            strcat(xbuf,*pp);
  354. X            free(*pp);
  355. X            continue;
  356. X            }
  357. X        sprintf(xbuf2,"%s/%s",xbuf,*pp);
  358. X        t0 = readlink(xbuf2,xbuf3,MAXPATHLEN);
  359. X        if (t0 == -1 || !flag)
  360. X            {
  361. X            strcat(xbuf,"/");
  362. X            strcat(xbuf,*pp);
  363. X            free(*pp);
  364. X            }
  365. X        else
  366. X            {
  367. X            xbuf3[t0] = '\0'; /* STUPID */
  368. X            if (*xbuf3 == '/')
  369. X                {
  370. X                strcpy(xbuf,"");
  371. X                if (xsymlinks(xbuf3+1,flag))
  372. X                    return 1;
  373. X                }
  374. X            else
  375. X                if (xsymlinks(xbuf3,flag))
  376. X                    return 1;
  377. X            free(*pp);
  378. X            }
  379. X        }
  380. X    free(opp);
  381. X    return 0;
  382. X}
  383. X
  384. X/* print a directory */
  385. X
  386. Xvoid fprintdir(s, f) /**/
  387. Xchar *s; FILE *f;
  388. X{
  389. Xint t0;
  390. X
  391. X    t0 = finddir(s);
  392. X    if (t0 == -1)
  393. X        {
  394. X        if (!strncmp(s,home,t0 = strlen(home)) && t0 > 1)
  395. X            {
  396. X            putc('~', f);
  397. X            fputs(s+t0,f);
  398. X            }
  399. X        else
  400. X            fputs(s,f);
  401. X        }
  402. X    else
  403. X        {
  404. X        putc('~', f);
  405. X        fputs(usernames[t0],f);
  406. X        fputs(s+strlen(userdirs[t0]),f);
  407. X        }
  408. X}
  409. X
  410. Xvoid printdir(s) /**/
  411. Xchar *s;
  412. X{
  413. X    fprintdir(s, stdout);
  414. X}
  415. X
  416. Xvoid printdircr(s) /**/
  417. Xchar *s;
  418. X{
  419. X    fprintdir(s, stdout);
  420. X    putchar('\n');
  421. X}
  422. X
  423. X/* see if a path has a named directory as its prefix */
  424. X
  425. Xint finddir(s) /**/
  426. Xchar *s;
  427. X{
  428. Xint t0,t1,step;
  429. X
  430. X    if (userdirsz)
  431. X        {
  432. X        step = t0 = userdirsz/2;
  433. X        for(;;)
  434. X            {
  435. X            t1 = (userdirs[t0]) ? dircmp(userdirs[t0],s) : 1;
  436. X            if (!t1)
  437. X                {
  438. X                while (t0 != userdirsz-1 && userdirs[t0+1] && 
  439. X                        !dircmp(userdirs[t0+1],s)) 
  440. X                    t0++;
  441. X                return t0;
  442. X                }
  443. X            if (!step)
  444. X                break;
  445. X            if (t1 > 0)
  446. X                t0 = t0-step+step/2;
  447. X            else
  448. X                t0 += step/2;
  449. X            step /= 2;
  450. X            }
  451. X        }
  452. X    return -1;
  453. X}
  454. X
  455. X/* add a named directory */
  456. X
  457. Xvoid adduserdir(s,t) /**/
  458. Xchar *s;char *t;
  459. X{
  460. Xint t0,t1;
  461. X
  462. X    if (!interact || ((t0 = finddir(t)) != -1 && !strcmp(s,usernames[t0])))
  463. X        return;
  464. X    if (!strcmp(t,"/"))
  465. X        return;
  466. X    if ((t0 = finddir(t)) != -1 && !strcmp(s,usernames[t0]))
  467. X        return;
  468. X    if (userdirsz == userdirct)
  469. X        {
  470. X        userdirsz *= 2;
  471. X        userdirs = (char **) realloc((char *) userdirs,
  472. X            sizeof(char **)*userdirsz);
  473. X        usernames = (char **) realloc((char *) usernames,
  474. X            sizeof(char **)*userdirsz);
  475. X        for (t0 = userdirct; t0 != userdirsz; t0++)
  476. X            userdirs[t0] = usernames[t0] = NULL;
  477. X        }
  478. X    for (t0 = 0; t0 != userdirct; t0++)
  479. X        if (strcmp(userdirs[t0],t) > 0)
  480. X            break;
  481. X    for (t1 = userdirct-1; t1 >= t0; t1--)
  482. X        {
  483. X        userdirs[t1+1] = userdirs[t1];
  484. X        usernames[t1+1] = usernames[t1];
  485. X        }
  486. X    userdirs[t0] = ztrdup(t);
  487. X    usernames[t0] = ztrdup(s);
  488. X    userdirct++;
  489. X}
  490. X
  491. Xint dircmp(s,t) /**/
  492. Xchar *s;char *t;
  493. X{
  494. X    for (; *s && *t; s++,t++)
  495. X        if (*s != *t)
  496. X            return *s-*t;
  497. X    if (!*s && (!*t || *t == '/'))
  498. X        return 0;
  499. X    return *s-*t;
  500. X}
  501. X
  502. Xint ddifftime(t1,t2) /**/
  503. Xtime_t t1;time_t t2;
  504. X{
  505. X    return ((long) t2-(long) t1);
  506. X}
  507. X
  508. X/* see if jobs need printing */
  509. X
  510. Xvoid scanjobs() /**/
  511. X{
  512. Xint t0;
  513. X
  514. X    for (t0 = 1; t0 != MAXJOB; t0++)
  515. X        if (jobtab[t0].stat & STAT_CHANGED)
  516. X            printjob(jobtab+t0,0);
  517. X}
  518. X
  519. X/* do pre-prompt stuff */
  520. X
  521. Xvoid preprompt() /**/
  522. X{
  523. Xint diff;
  524. XList list;
  525. Xstruct schedcmd *sch,*schl;
  526. X
  527. X    if (unset(NOTIFY))
  528. X        scanjobs();
  529. X    if (errflag)
  530. X        return;
  531. X    if (list = getshfunc("precmd")) doshfuncnoval(list,NULL,0);
  532. X    if (errflag)
  533. X        return;
  534. X    if (period && (time(NULL) > lastperiod+period) &&
  535. X            (list = getshfunc("periodic"))) {
  536. X        doshfuncnoval(list,NULL,0);
  537. X        lastperiod = time(NULL);
  538. X    }
  539. X    if (errflag)
  540. X        return;
  541. X    if (watch)
  542. X        {
  543. X        diff = (int) ddifftime(lastwatch,time(NULL));
  544. X        if (diff > logcheck)
  545. X            {
  546. X            dowatch();
  547. X            lastwatch = time(NULL);
  548. X            }
  549. X        }
  550. X    if (errflag)
  551. X        return;
  552. X    diff = (int) ddifftime(lastmailcheck,time(NULL));
  553. X    if (diff > mailcheck)
  554. X        {
  555. X        if (mailpath && *mailpath)
  556. X            checkmailpath(mailpath);
  557. X        else if (mailfile)
  558. X            {
  559. X            char *x[2];
  560. X
  561. X            x[0] = mailfile;
  562. X            x[1] = NULL;
  563. X            checkmailpath(x);
  564. X            }
  565. X        lastmailcheck = time(NULL);
  566. X        }
  567. X    for (schl = (struct schedcmd *) &schedcmds, sch = schedcmds; sch;
  568. X            sch = (schl = sch)->next)
  569. X        {
  570. X        if (sch->time < time(NULL))
  571. X            {
  572. X            execstring(sch->cmd);
  573. X            schl->next = sch->next;
  574. X            free(sch->cmd);
  575. X            free(sch);
  576. X            }
  577. X        if (errflag)
  578. X            return;
  579. X        }
  580. X}
  581. X
  582. Xint arrlen(s) /**/
  583. Xchar **s;
  584. X{
  585. Xint t0;
  586. X
  587. X    for (t0 = 0; *s; s++,t0++);
  588. X    return t0;
  589. X}
  590. X
  591. Xvoid checkmailpath(s) /**/
  592. Xchar **s;
  593. X{
  594. Xstruct stat st;
  595. Xchar *v,*u,c;
  596. X
  597. X    while (*s)
  598. X        {
  599. X        for (v = *s; *v && *v != '?'; v++);
  600. X        c = *v;
  601. X        *v = '\0';
  602. X        if (c != '?')
  603. X            u = NULL;
  604. X        else
  605. X            u = v+1;
  606. X        if (stat(*s,&st) == -1)
  607. X            {
  608. X            if (errno != ENOENT)
  609. X                zerr("%e: %s",*s,errno);
  610. X            }
  611. X        else if (S_ISDIR(st.st_mode))
  612. X            {
  613. X            Lklist l;
  614. X            DIR *lock = opendir(*s);
  615. X            char buf[MAXPATHLEN*2],**arr,**ap;
  616. X            struct direct *de;
  617. X            int ct = 1;
  618. X
  619. X            if (lock)
  620. X                {
  621. X                pushheap();
  622. X                heapalloc();
  623. X                l = newlist();
  624. X                readdir(lock); readdir(lock);
  625. X                while (de = readdir(lock))
  626. X                    {
  627. X                    if (errflag)
  628. X                        break;
  629. X                    if (u)
  630. X                        sprintf(buf,"%s/%s?%s",*s,de->d_name,u);
  631. X                    else
  632. X                        sprintf(buf,"%s/%s",*s,de->d_name);
  633. X                    addnode(l,strdup(buf));
  634. X                    ct++;
  635. X                    }
  636. X                closedir(lock);
  637. X                ap = arr = (char **) alloc(ct*sizeof(char *));
  638. X                while (*ap++ = ugetnode(l));
  639. X                checkmailpath(arr);
  640. X                popheap();
  641. X                }
  642. X            }
  643. X        else
  644. X            {
  645. X            if (st.st_size && st.st_atime <= st.st_mtime &&
  646. X                    st.st_mtime > lastmailcheck)
  647. X                if (!u)
  648. X                    {
  649. X                    fprintf(stderr,"You have new mail.\n",*s);
  650. X                    fflush(stderr);
  651. X                    }
  652. X                else
  653. X                    {
  654. X                    char *z = u;
  655. X
  656. X                    while (*z)
  657. X                        if (*z == '$' && z[1] == '_')
  658. X                            {
  659. X                            fprintf(stderr,"%s",*s);
  660. X                            z += 2;
  661. X                            }
  662. X                        else
  663. X                            fputc(*z++,stderr);
  664. X                    fputc('\n',stderr);
  665. X                    fflush(stderr);
  666. X                    }
  667. X            if (isset(MAILWARNING) && st.st_atime > st.st_mtime &&
  668. X                    st.st_atime > lastmailcheck && st.st_size)
  669. X                {
  670. X                fprintf(stderr,"The mail in %s has been read.\n",*s);
  671. X                fflush(stderr);
  672. X                }
  673. X            }
  674. X        *v = c;
  675. X        s++;
  676. X        }
  677. X}
  678. X
  679. Xvoid saveoldfuncs(x,y) /**/
  680. Xchar *x;Cmdnam y;
  681. X{
  682. XCmdnam cc;
  683. X
  684. X    if (y->type == SHFUNC || y->type == DISABLED)
  685. X        {
  686. X        cc = (Cmdnam) zcalloc(sizeof *cc);
  687. X        *cc = *y;
  688. X        y->u.list = NULL;
  689. X        addhnode(ztrdup(x),cc,cmdnamtab,freecmdnam);
  690. X        }
  691. X}
  692. X
  693. X/* create command hashtable */
  694. X
  695. Xvoid newcmdnamtab() /**/
  696. X{
  697. XHashtab oldcnt;
  698. X
  699. X    oldcnt = cmdnamtab;
  700. X    permalloc();
  701. X    cmdnamtab = newhtable(101);
  702. X    addbuiltins();
  703. X    if (oldcnt) {
  704. X        listhtable(oldcnt,(HFunc) saveoldfuncs);
  705. X        freehtab(oldcnt,freecmdnam);
  706. X    }
  707. X    lastalloc();
  708. X    pathchecked = path;
  709. X}
  710. X
  711. Xvoid freecmdnam(a) /**/
  712. Xvptr a;
  713. X{
  714. Xstruct cmdnam *c = (struct cmdnam *) a;
  715. X
  716. X    if (c->type == SHFUNC) {
  717. X        if (c->u.list)
  718. X            freestruct(c->u.list);
  719. X    } else if (c->type != BUILTIN && c->type != DISABLED)
  720. X        free(c->u.nam);
  721. X    free(c);
  722. X}
  723. X
  724. Xvoid freecompctl(a) /**/
  725. Xvptr a;
  726. X{
  727. XCompctl cc = (Compctl) a;
  728. X
  729. X    free(cc);
  730. X}
  731. X
  732. Xvoid freestr(a) /**/
  733. Xvptr a;
  734. X{
  735. X    free(a);
  736. X}
  737. X
  738. Xvoid freeanode(a) /**/
  739. Xvptr a;
  740. X{
  741. Xstruct alias *c = (struct alias *) a;
  742. X
  743. X    free(c->text);
  744. X    free(c);
  745. X}
  746. X
  747. Xvoid freepm(a) /**/
  748. Xvptr a;
  749. X{
  750. Xstruct param *pm = (Param) a;
  751. X
  752. X    free(pm);
  753. X}
  754. X
  755. Xvoid restoretty() /**/
  756. X{
  757. X    settyinfo(&shttyinfo);
  758. X}
  759. X
  760. Xvoid gettyinfo(ti) /**/
  761. Xstruct ttyinfo *ti;
  762. X{
  763. X    if (SHTTY != -1)
  764. X        {
  765. X#ifdef TERMIOS
  766. X#ifdef HAS_TCCRAP
  767. X        if (tcgetattr(SHTTY,&ti->tio) == -1)
  768. X#else
  769. X        if (ioctl(SHTTY,TCGETS,&ti->tio) == -1)
  770. X#endif
  771. X            zerr("bad tcgets: %e",NULL,errno);
  772. X#else
  773. X#ifdef TERMIO
  774. X        ioctl(SHTTY,TCGETA,&ti->tio);
  775. X#else
  776. X        ioctl(SHTTY,TIOCGETP,&ti->sgttyb);
  777. X        ioctl(SHTTY,TIOCLGET,&ti->lmodes);
  778. X        ioctl(SHTTY,TIOCGETC,&ti->tchars);
  779. X        ioctl(SHTTY,TIOCGLTC,&ti->ltchars);
  780. X#endif
  781. X#endif
  782. X#ifdef TIOCGWINSZ
  783. X        if (ioctl(SHTTY,TIOCGWINSZ,&ti->winsize) == -1)
  784. X        /*    zerr("bad tiocgwinsz: %e",NULL,errno)*/;
  785. X#endif
  786. X        }
  787. X}
  788. X
  789. Xvoid settyinfo(ti) /**/
  790. Xstruct ttyinfo *ti;
  791. X{
  792. X    if (SHTTY != -1)
  793. X        {
  794. X#ifdef TERMIOS
  795. X#ifdef HAS_TCCRAP
  796. X#ifndef TCSADRAIN
  797. X#define TCSADRAIN 1   /* XXX Princeton's include files are screwed up */
  798. X#endif
  799. X        if (tcsetattr(SHTTY, TCSADRAIN, &ti->tio) == -1)
  800. X#else
  801. X        if (ioctl(SHTTY,TCSETS,&ti->tio) == -1)
  802. X#endif
  803. X        /*    zerr("settyinfo: %e",NULL,errno)*/;
  804. X#else
  805. X#ifdef TERMIO
  806. X        ioctl(SHTTY,TCSETA,&ti->tio);
  807. X#else
  808. X        ioctl(SHTTY,TIOCSETN,&ti->sgttyb);
  809. X        ioctl(SHTTY,TIOCLSET,&ti->lmodes);
  810. X        ioctl(SHTTY,TIOCSETC,&ti->tchars);
  811. X        ioctl(SHTTY,TIOCSLTC,&ti->ltchars);
  812. X#endif
  813. X#endif
  814. X#ifdef TIOCGWINSZ
  815. X        signal(SIGWINCH,SIG_IGN);
  816. X        if (ioctl(SHTTY,TIOCSWINSZ,&ti->winsize) == -1)
  817. X        /*    zerr("settyinfo: %e",NULL,errno)*/;
  818. X        signal(SIGWINCH,handler);
  819. X#endif
  820. X        }
  821. X}
  822. X
  823. X#define SANEKEY(X) \
  824. X    if (ti->X == -1 && savedttyinfo.X != -1) ti->X = savedttyinfo.X;
  825. X
  826. Xvoid sanetty(ti) /**/
  827. Xstruct ttyinfo *ti;
  828. X{
  829. Xint t0;
  830. X
  831. X#ifdef TIO
  832. X    ti->tio.c_lflag |= ICANON|ECHO;
  833. X#ifdef FLUSHO
  834. X    ti->tio.c_lflag &= ~FLUSHO;
  835. X#endif
  836. X    for (t0 = 0; t0 !=
  837. X#ifdef NCCS
  838. X    NCCS
  839. X#else
  840. X    NCC
  841. X#endif
  842. X    ; t0++)
  843. X        if (ti->tio.c_cc[t0] == VDISABLEVAL &&
  844. X                savedttyinfo.tio.c_cc[t0] != VDISABLEVAL)
  845. X            ti->tio.c_cc[t0] = savedttyinfo.tio.c_cc[t0];
  846. X#else
  847. X    ti->sgttyb.sg_flags = (ti->sgttyb.sg_flags & ~CBREAK) | ECHO;
  848. X    ti->lmodes &= ~LFLUSHO;
  849. X    SANEKEY(tchars.t_quitc);
  850. X    SANEKEY(tchars.t_startc);
  851. X    SANEKEY(tchars.t_stopc);
  852. X    SANEKEY(ltchars.t_suspc);
  853. X    SANEKEY(ltchars.t_dsuspc);
  854. X    SANEKEY(ltchars.t_lnextc);
  855. X    SANEKEY(ltchars.t_flushc);
  856. X#endif
  857. X}
  858. X
  859. Xvoid adjustwinsize() /**/
  860. X{
  861. X#ifdef TIOCGWINSZ
  862. X    ioctl(SHTTY,TIOCGWINSZ,&shttyinfo.winsize);
  863. X    if (!(columns = shttyinfo.winsize.ws_col)) columns = 80;
  864. X    lines = shttyinfo.winsize.ws_row;
  865. X    setintenv("COLUMNS",columns);
  866. X    setintenv("LINES",lines);
  867. X    if (zleactive) refresh();
  868. X#endif
  869. X}
  870. X
  871. Xint zyztem(s,t) /**/
  872. Xchar *s;char *t;
  873. X{
  874. X#ifdef WAITPID
  875. Xint pid,statusp;
  876. X
  877. X    if (!(pid = fork()))
  878. X        {
  879. X        s = tricat(s," ",t);
  880. X        execl("/bin/sh","sh","-c",s,(char *) 0);
  881. X        _exit(1);
  882. X        }
  883. X    while (waitpid(pid,&statusp,WUNTRACED) == -1 && errno == EINTR);
  884. X    if (WIFEXITED(statusp))
  885. X        return WEXITSTATUS(statusp);
  886. X    return 1;
  887. X#else
  888. X    if (!waitfork())
  889. X        {
  890. X        s = tricat(s," ",t);
  891. X        execl("/bin/sh","sh","-c",s,(char *) 0);
  892. X        _exit(1);
  893. X        }
  894. X    return 0;
  895. X#endif
  896. X}
  897. X
  898. X#ifndef WAITPID
  899. X
  900. X/* fork a process and wait for it to complete without confusing
  901. X    the SIGCHLD handler */
  902. X
  903. Xint waitfork() /**/
  904. X{
  905. Xint pipes[2];
  906. Xchar x;
  907. X
  908. X    pipe(pipes);
  909. X    if (!fork())
  910. X        {
  911. X        close(pipes[0]);
  912. X        signal(SIGCHLD,SIG_DFL);
  913. X        if (!fork())
  914. X            return 0;
  915. X        wait(NULL);
  916. X        _exit(0);
  917. X        }
  918. X    close(pipes[1]);
  919. X    read(pipes[0],&x,1);
  920. X    close(pipes[0]);
  921. X    return 1;
  922. X}
  923. X
  924. X#endif
  925. X
  926. X/* move a fd to a place >= 10 */
  927. X
  928. Xint movefd(fd) /**/
  929. Xint fd;
  930. X{
  931. Xint fe;
  932. X
  933. X    if (fd == -1)
  934. X        return fd;
  935. X#ifdef F_DUPFD
  936. X    fe = fcntl(fd,F_DUPFD,10);
  937. X#else
  938. X    if ((fe = dup(fd)) < 10)
  939. X        fe = movefd(fe);
  940. X#endif
  941. X    close(fd);
  942. X    return fe;
  943. X}
  944. X
  945. X/* move fd x to y */
  946. X
  947. Xvoid redup(x,y) /**/
  948. Xint x;int y;
  949. X{
  950. X    if (x != y)
  951. X        {
  952. X        dup2(x,y);
  953. X        close(x);
  954. X        }
  955. X}
  956. X
  957. Xvoid settrap(t0,l) /**/
  958. Xint t0;List l;
  959. X{
  960. XCmd c;
  961. X
  962. X    if (l)
  963. X        {
  964. X        c = l->left->left->left;
  965. X        if (c->type == SIMPLE && !full(c->args) && !full(c->redir)
  966. X                && !full(c->vars) && !c->flags)
  967. X            l = NULL;
  968. X        }
  969. X    if (t0 == -1)
  970. X        return;
  971. X    if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
  972. X            || t0 == SIGPIPE))
  973. X        {
  974. X        zerr("can't trap SIG%s in interactive shells",sigs[t0-1],0);
  975. X        return;
  976. X        }
  977. X    if (!l)
  978. X        {
  979. X        sigtrapped[t0] = 2;
  980. X        if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
  981. X            {
  982. X            signal(t0,SIG_IGN);
  983. X            sigtrapped[t0] = 2;
  984. X            }
  985. X        }
  986. X    else
  987. X        {
  988. X        if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
  989. X            signal(t0,handler);
  990. X        sigtrapped[t0] = 1;
  991. X        permalloc();
  992. X        sigfuncs[t0] = (List) dupstruct(l);
  993. X        heapalloc();
  994. X        }
  995. X}
  996. X
  997. Xvoid unsettrap(t0) /**/
  998. Xint t0;
  999. X{
  1000. X    if (t0 == -1)
  1001. X        return;
  1002. X    if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
  1003. X            || t0 == SIGPIPE)) {
  1004. X        return;
  1005. X    }
  1006. X    sigtrapped[t0] = 0;
  1007. X    if (t0 == SIGINT) intr();
  1008. X    else if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD) signal(t0,SIG_DFL);
  1009. X    if (sigfuncs[t0]) freestruct(sigfuncs[t0]);
  1010. X}
  1011. X
  1012. Xvoid dotrap(sig) /**/
  1013. Xint sig;
  1014. X{
  1015. Xint sav,savval;
  1016. X
  1017. X    sav = sigtrapped[sig];
  1018. X    savval = lastval;
  1019. X    if (sav == 2)
  1020. X        return;
  1021. X    sigtrapped[sig] = 2;
  1022. X    if (sigfuncs[sig]) {
  1023. X        lexsave();
  1024. X        doshfuncnoval(sigfuncs[sig],NULL,0);
  1025. X        lexrestore();
  1026. X    }
  1027. X    sigtrapped[sig] = sav;
  1028. X    lastval = savval;
  1029. X}
  1030. X
  1031. X/* copy len chars from t into s, and null terminate */
  1032. X
  1033. Xvoid ztrncpy(s,t,len) /**/
  1034. Xchar *s;char *t;int len;
  1035. X{
  1036. X    while (len--) *s++ = *t++;
  1037. X    *s = '\0';
  1038. X}
  1039. X
  1040. X/* copy t into *s and update s */
  1041. X
  1042. Xvoid strucpy(s,t) /**/
  1043. Xchar **s;char *t;
  1044. X{
  1045. Xchar *u = *s;
  1046. X
  1047. X    while (*u++ = *t++);
  1048. X    *s = u-1;
  1049. X}
  1050. X
  1051. Xvoid struncpy(s,t,n) /**/
  1052. Xchar **s;char *t;int n;
  1053. X{
  1054. Xchar *u = *s;
  1055. X
  1056. X    while (n--)
  1057. X        *u++ = *t++;
  1058. X    *s = u;
  1059. X    *u = '\0';
  1060. X}
  1061. X
  1062. Xvoid checkrmall(s) /**/
  1063. Xchar *s;
  1064. X{
  1065. X    fflush(stdin);
  1066. X    if (*s == '/')
  1067. X        fprintf(stderr,"zsh: sure you want to delete all the files in %s? ",s);
  1068. X    else
  1069. X        fprintf(stderr,"zsh: sure you want to delete all the files in %s/%s? ",
  1070. X            (pwd[1]) ? pwd : "",s);
  1071. X    fflush(stderr);
  1072. X    feep();
  1073. X    errflag |= (getquery() != 'y');
  1074. X}
  1075. X
  1076. Xint getquery() /**/
  1077. X{
  1078. Xchar c;
  1079. Xlong val;
  1080. X
  1081. X    setcbreak();
  1082. X#ifdef FIONREAD
  1083. X    ioctl(SHTTY,FIONREAD,&val);
  1084. X    if (val) { unsetcbreak(); write(2,"n\n",2); return 'n'; }
  1085. X#endif
  1086. X    if (read(SHTTY,&c,1) == 1)
  1087. X        if (c == 'y' || c == 'Y' || c == '\t') c = 'y';
  1088. X    unsetcbreak();
  1089. X    if (c != '\n')
  1090. X        write(2,"\n",1);
  1091. X    return (int) c;
  1092. X}
  1093. X
  1094. Xstatic int d;
  1095. Xstatic char *guess,*best;
  1096. X
  1097. Xvoid spscannodis(s,cn) /**/
  1098. Xchar *s;char *cn;
  1099. X{
  1100. X    if (((Cmdnam) cn)->type != DISABLED)
  1101. X        spscan(s,NULL);
  1102. X}
  1103. X
  1104. Xvoid spscan(s,junk) /**/
  1105. Xchar *s;char *junk;
  1106. X{
  1107. Xint nd;
  1108. X
  1109. X    nd = spdist(s,guess,strlen(guess)/4+1);
  1110. X    if (nd <= d) {
  1111. X        best = s;
  1112. X        d = nd;
  1113. X    }
  1114. X}
  1115. X
  1116. X/* spellcheck a word */
  1117. X/* fix s and s2 ; if s2 is non-null, fix the history list too */
  1118. X
  1119. Xvoid spckword(s,s2,tptr,cmd,ask) /**/
  1120. Xchar **s;char **s2;char **tptr;int cmd;int ask;
  1121. X{
  1122. Xchar *t,*u;
  1123. Xchar firstchar;
  1124. Xint x;
  1125. Xint pram = 0;
  1126. X
  1127. X    if (**s == '-' || **s == '%')
  1128. X        return;
  1129. X    if (!strcmp(*s,"in"))
  1130. X        return;
  1131. X    if (!(*s)[0] || !(*s)[1]) return;
  1132. X    if (gethnode(*s,cmdnamtab) || gethnode(*s,aliastab)) return;
  1133. X    t = *s;
  1134. X    if (*t == Tilde || *t == Equals || *t == String) t++;
  1135. X    for (; *t; t++) if (itok(*t)) return;
  1136. X    best = NULL;
  1137. X    for (t = *s; *t; t++) if (*t == '/') break;
  1138. X    if (**s == String) {
  1139. X        if (*t) return;
  1140. X        pram = 1;
  1141. X        guess = *s+1;
  1142. X        d = 100;
  1143. X        listhtable(paramtab,spscan);
  1144. X    } else {
  1145. X        if ((u = spname(guess = *s)) != *s)
  1146. X            best = u;
  1147. X        if (!*t && !cmd) {
  1148. X            if (access(*s,F_OK) == 0) return;
  1149. X            if (hashcmd(*s,pathchecked)) return;
  1150. X            guess = *s;
  1151. X            d = 100;
  1152. X            listhtable(aliastab,spscan);
  1153. X            listhtable(cmdnamtab,spscan);
  1154. X        }
  1155. X    }
  1156. X    if (errflag) return;
  1157. X    if (best && strlen(best) > 1 && strcmp(best,guess)) {
  1158. X        if (ask) {
  1159. X            char *pp;
  1160. X            int junk;
  1161. X
  1162. X            rstring = best; Rstring = guess;
  1163. X            firstchar = *guess;
  1164. X            if (*guess == Tilde) *guess = '~';
  1165. X            else if (*guess == String) *guess = '$';
  1166. X            else if (*guess == Equals) *guess = '=';
  1167. X            pp = putprompt(sprompt,&junk);
  1168. X            *guess = firstchar;
  1169. X            fprintf(stderr,"%s",pp);
  1170. X            fflush(stderr);
  1171. X            feep();
  1172. X            x = getquery();
  1173. X        } else
  1174. X            x = 'y';
  1175. X        if (x == 'y') {
  1176. X            if (!pram) {
  1177. X                *s = strdup(best);
  1178. X            } else {
  1179. X                *s = alloc(strlen(best)+2);
  1180. X                strcpy(*s+1,best);
  1181. X                **s = String;
  1182. X            }
  1183. X            if (s2) {
  1184. X                if (*tptr && !strcmp(hlastw,*s2) && hlastw < hptr) {
  1185. X                    char *z;
  1186. X                    hptr = hlastw;
  1187. X                    if (pram) hwaddc('$');
  1188. X                    for (z = best; *z; z++) hwaddc(*z);
  1189. X                    hwaddc(HISTSPACE);
  1190. X                    *tptr = hptr-1;
  1191. X                    **tptr = '\0';
  1192. X                }
  1193. X                *s2 = strdup(best);
  1194. X            }
  1195. X        } else if (x == 'a') {
  1196. X            histdone |= HISTFLAG_NOEXEC;
  1197. X        } else if (x == 'e') {
  1198. X            histdone |= HISTFLAG_NOEXEC|HISTFLAG_RECALL;
  1199. X        }
  1200. X    }
  1201. X}
  1202. X
  1203. Xint ztrftime(buf,bufsize,fmt,tm) /**/
  1204. Xchar *buf;int bufsize;char *fmt;struct tm *tm;
  1205. X{
  1206. Xstatic char *astr[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  1207. Xstatic char *estr[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
  1208. X    "Aug","Sep","Oct","Nov","Dec"};
  1209. Xstatic char *lstr[] = {"12"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9",
  1210. X    "10","11"};
  1211. Xchar tmp[3];
  1212. X#ifdef HAS_STRFTIME
  1213. Xchar *origbuf = buf;
  1214. X#endif
  1215. X
  1216. X    tmp[0] = '%'; tmp[2] = '\0';
  1217. X    while (*fmt)
  1218. X        if (*fmt == '%')
  1219. X            {
  1220. X            fmt++;
  1221. X            switch(*fmt++)
  1222. X                {
  1223. X                case 'a':
  1224. X                    strucpy(&buf,astr[tm->tm_wday]);
  1225. X                    break;
  1226. X                case 'b':
  1227. X                    strucpy(&buf,estr[tm->tm_mon]);
  1228. X                    break;
  1229. X                case 'd':
  1230. X                    *buf++ = '0'+tm->tm_mday/10;
  1231. X                    *buf++ = '0'+tm->tm_mday%10;
  1232. X                    break;
  1233. X                case 'e':
  1234. X                    if (tm->tm_mday > 9)
  1235. X                        *buf++ = '0'+tm->tm_mday/10;
  1236. X                    *buf++ = '0'+tm->tm_mday%10;
  1237. X                    break;
  1238. X                case 'k':
  1239. X                    if (tm->tm_hour > 9)
  1240. X                        *buf++ = '0'+tm->tm_hour/10;
  1241. X                    *buf++ = '0'+tm->tm_hour%10;
  1242. X                    break;
  1243. X                case 'l':
  1244. X                    strucpy(&buf,lstr[tm->tm_hour%12]);
  1245. X                    break;
  1246. X                case 'm':
  1247. X                    *buf++ = '0'+(tm->tm_mon+1)/10;
  1248. X                    *buf++ = '0'+(tm->tm_mon+1)%10;
  1249. X                    break;
  1250. X                case 'M':
  1251. X                    *buf++ = '0'+tm->tm_min/10;
  1252. X                    *buf++ = '0'+tm->tm_min%10;
  1253. X                    break;
  1254. X                case 'p':
  1255. X                    *buf++ = (tm->tm_hour > 11) ? 'p' : 'a';
  1256. X                    *buf++ = 'm';
  1257. X                    break;
  1258. X                case 'S':
  1259. X                    *buf++ = '0'+tm->tm_sec/10;
  1260. X                    *buf++ = '0'+tm->tm_sec%10;
  1261. X                    break;
  1262. X                case 'y':
  1263. X                    *buf++ = '0'+tm->tm_year/10;
  1264. X                    *buf++ = '0'+tm->tm_year%10;
  1265. X                    break;
  1266. X                default:
  1267. X#ifdef HAS_STRFTIME
  1268. X                    *buf = '\0';
  1269. X                    tmp[1] = fmt[-1];
  1270. X                    strftime(buf,bufsize-strlen(origbuf),tmp,tm);
  1271. X                    buf += strlen(buf);
  1272. X#else
  1273. X                    *buf++ = '%';
  1274. X                    *buf++ = fmt[-1];
  1275. X#endif
  1276. X                    break;
  1277. X                }
  1278. X            }
  1279. X        else
  1280. X            *buf++ = *fmt++;
  1281. X    *buf = '\0';
  1282. X    return 0;
  1283. X}
  1284. X
  1285. Xchar *join(arr,delim) /**/
  1286. Xchar **arr;int delim;
  1287. X{
  1288. Xint len = 0;
  1289. Xchar **s,*ret,*ptr;
  1290. Xstatic char *lastmem = NULL;
  1291. X
  1292. X    for (s = arr; *s; s++)
  1293. X        len += strlen(*s)+1;
  1294. X    if (!len) return "";
  1295. X    if (lastmem) free(lastmem);
  1296. X    lastmem = ptr = ret = zalloc(len);
  1297. X    for (s = arr; *s; s++) {
  1298. X        strucpy(&ptr,*s);
  1299. X        *ptr++ = delim;
  1300. X    }
  1301. X    ptr[-1] = '\0';
  1302. X    return ret;
  1303. X}
  1304. X
  1305. Xchar *spacejoin(s) /**/
  1306. Xchar **s;
  1307. X{
  1308. X    return join(s,*ifs);
  1309. X}
  1310. X
  1311. Xchar *colonjoin(s) /**/
  1312. Xchar **s;
  1313. X{
  1314. X    return join(s,':');
  1315. X}
  1316. X
  1317. Xchar **colonsplit(s) /**/
  1318. Xchar *s;
  1319. X{
  1320. Xint ct;
  1321. Xchar *t,**ret,**ptr;
  1322. Xchar **lastmem = NULL;
  1323. X
  1324. X    for (t = s, ct = 0; *t; t++) if (*t == ':') ct++;
  1325. X    if (lastmem) freearray(lastmem);
  1326. X    lastmem = ptr = ret = (char **) zalloc(sizeof(char **)*(ct+2));
  1327. X    t = s;
  1328. X    do {
  1329. X        for (s = t; *t && *t != ':'; t++);
  1330. X        *ptr = zalloc((t-s)+1);
  1331. X        ztrncpy(*ptr++,s,t-s);
  1332. X    }
  1333. X    while (*t++);
  1334. X    *ptr = NULL;
  1335. X    return ret;
  1336. X}
  1337. X
  1338. Xchar **spacesplit(s) /**/
  1339. Xchar *s;
  1340. X{
  1341. Xint ct;
  1342. Xchar *t,**ret,**ptr;
  1343. X
  1344. X    for (t = s, ct = 0; *t; t++)
  1345. X        if (isep(*t)) ct++;
  1346. X    ptr = ret = (char **) zalloc(sizeof(char **)*(ct+2));
  1347. X    t = s;
  1348. X    do {
  1349. X        for (s = t; *t && !isep(*t); t++);
  1350. X        *ptr = zalloc((t-s)+1);
  1351. X        ztrncpy(*ptr++,s,t-s);
  1352. X    } while (*t++);
  1353. X    *ptr = NULL;
  1354. X    return ret;
  1355. X}
  1356. X
  1357. XList getshfunc(nam) /**/
  1358. Xchar *nam;
  1359. X{
  1360. XCmdnam x = (Cmdnam) gethnode(nam,cmdnamtab);
  1361. X
  1362. X    return (x && x->type == SHFUNC) ? x->u.list : NULL;
  1363. X}
  1364. X
  1365. X/* allocate a tree element */
  1366. X
  1367. Xvptr allocnode(type) /**/
  1368. Xint type;
  1369. X{
  1370. Xint t0;
  1371. Xstruct node *n = (struct node *) alloc(sizeof *n);
  1372. Xstatic int typetab[N_COUNT][4] = {
  1373. X    NT_NODE,NT_NODE,0,0,
  1374. X    NT_NODE,NT_NODE,0,0,
  1375. X    NT_NODE,NT_NODE,0,0,
  1376. X    NT_STR|NT_LIST,NT_NODE,NT_NODE|NT_LIST,NT_NODE|NT_LIST,
  1377. X    NT_STR,0,0,0,
  1378. X    NT_NODE,NT_NODE,0,0,
  1379. X    NT_STR,NT_NODE,0,0,
  1380. X    NT_NODE,NT_STR,NT_NODE,0,
  1381. X    NT_NODE,NT_NODE,NT_NODE,0,
  1382. X    NT_NODE,NT_NODE,0,0,
  1383. X    NT_STR,NT_STR,NT_STR|NT_LIST,0
  1384. X    };
  1385. X
  1386. X    n->type = type;
  1387. X    for (t0 = 0; t0 != 4; t0++)
  1388. X        n->types[t0] = typetab[type][t0];
  1389. X    return (vptr) n;
  1390. X}
  1391. X
  1392. X/* duplicate a syntax tree */
  1393. X
  1394. Xvptr dupstruct(a) /**/
  1395. Xvptr a;
  1396. X{
  1397. Xstruct node *n = a,*m;
  1398. Xint t0;
  1399. X
  1400. X    if (!a) return NULL;
  1401. X    m = alloc(sizeof *m);
  1402. X    *m = *n;
  1403. X    for (t0 = 0; t0 != 4; t0++)
  1404. X        if (m->ptrs[t0])
  1405. X            switch(m->types[t0])
  1406. X                {
  1407. X                case NT_NODE: m->ptrs[t0] = dupstruct(m->ptrs[t0]); break;
  1408. X                case NT_STR: m->ptrs[t0] =
  1409. X                    (useheap) ? strdup(m->ptrs[t0]) : ztrdup(m->ptrs[t0]); break;
  1410. X                case NT_LIST|NT_NODE:
  1411. X                    m->ptrs[t0] = duplist(m->ptrs[t0],dupstruct); break;
  1412. X                case NT_LIST|NT_STR:
  1413. X                    m->ptrs[t0] = duplist(m->ptrs[t0],(VFunc)
  1414. X                        ((useheap) ? strdup : ztrdup));
  1415. X                    break;
  1416. X                }
  1417. X    return (vptr) m;
  1418. X}
  1419. X
  1420. X/* free a syntax tree */
  1421. X
  1422. Xvoid freestruct(a) /**/
  1423. Xvptr a;
  1424. X{
  1425. Xstruct node *n = (struct node *) a;
  1426. Xint t0;
  1427. X
  1428. X    for (t0 = 0; t0 != 4; t0++)
  1429. X        if (n->ptrs[t0])
  1430. X            switch(n->types[t0])
  1431. X                {
  1432. X                case NT_NODE: freestruct(n->ptrs[t0]); break;
  1433. X                case NT_STR: free(n->ptrs[t0]); break;
  1434. X                case NT_LIST|NT_STR: freetable(n->ptrs[t0],freestr); break;
  1435. X                case NT_LIST|NT_NODE: freetable(n->ptrs[t0],freestruct); break;
  1436. X                }
  1437. X    free(n);
  1438. X}
  1439. X
  1440. XLklist duplist(l,func) /**/
  1441. XLklist l;VFunc func;
  1442. X{
  1443. XLklist ret;
  1444. XLknode node;
  1445. X
  1446. X    ret = newlist();
  1447. X    for (node = firstnode(l); node; incnode(node))
  1448. X        addnode(ret,func(getdata(node)));
  1449. X    return ret;
  1450. X}
  1451. X
  1452. Xchar **mkarray(s) /**/
  1453. Xchar *s;
  1454. X{
  1455. Xchar **t = (char **) zalloc((s) ? (2*sizeof s) : (sizeof s));
  1456. X
  1457. X    if (*t = s) t[1] = NULL;
  1458. X    return t;
  1459. X}
  1460. X
  1461. Xvoid feep() /**/
  1462. X{
  1463. X    if (unset(NOBEEP))
  1464. X        write(2,"\07",1);
  1465. X}
  1466. X
  1467. Xvoid freearray(s) /**/
  1468. Xchar **s;
  1469. X{
  1470. Xchar **t = s;
  1471. X
  1472. X    while (*s)
  1473. X        free(*s++);
  1474. X    free(t);
  1475. X}
  1476. X
  1477. Xint equalsplit(s,t) /**/
  1478. Xchar *s;char **t;
  1479. X{
  1480. X    for (; *s && *s != '='; s++);
  1481. X    if (*s == '=')
  1482. X        {
  1483. X        *s++ = '\0';
  1484. X        *t = s;
  1485. X        return 1;
  1486. X        }
  1487. X    return 0;
  1488. X}
  1489. X
  1490. X/* see if the right side of a list is trivial */
  1491. X
  1492. Xvoid simplifyright(l) /**/
  1493. XList l;
  1494. X{
  1495. XCmd c;
  1496. X
  1497. X    if (!l->right)
  1498. X        return;
  1499. X    if (l->right->right || l->right->left->right ||
  1500. X            l->right->left->left->right)
  1501. X        return;
  1502. X    c = l->left->left->left;
  1503. X    if (c->type != SIMPLE || full(c->args) || full(c->redir)
  1504. X            || full(c->vars))
  1505. X        return;
  1506. X    l->right = NULL;
  1507. X    return;
  1508. X}
  1509. X
  1510. X/* initialize the ztypes table */
  1511. X
  1512. Xvoid inittyptab() /**/
  1513. X{
  1514. Xint t0;
  1515. Xchar *s;
  1516. X
  1517. X    for (t0 = 0; t0 != 256; t0++)
  1518. X        typtab[t0] = 0;
  1519. X    for (t0 = 0; t0 != 32; t0++)
  1520. X        typtab[t0] = typtab[t0+128] = ICNTRL;
  1521. X    typtab[127] = ICNTRL;
  1522. X    for (t0 = '0'; t0 <= '9'; t0++)
  1523. X        typtab[t0] = IDIGIT|IALNUM|IWORD|IIDENT|IUSER;
  1524. X    for (t0 = 'a'; t0 <= 'z'; t0++)
  1525. X        typtab[t0] = typtab[t0-'a'+'A'] = IALPHA|IALNUM|IIDENT|IUSER|IWORD;
  1526. X    for (t0 = 0240; t0 != 0400; t0++)
  1527. X        typtab[t0] = IALPHA|IALNUM|IIDENT|IUSER|IWORD;
  1528. X    typtab['_'] = IIDENT|IUSER;
  1529. X    typtab['-'] = IUSER;
  1530. X    typtab[' '] |= IBLANK|INBLANK;
  1531. X    typtab['\t'] |= IBLANK|INBLANK;
  1532. X    typtab['\n'] |= INBLANK;
  1533. X    for (t0 = (int) (unsigned char) ALPOP; t0 <= (int) (unsigned char) Nularg;
  1534. X            t0++)
  1535. X        typtab[t0] |= ITOK;
  1536. X    for (s = ifs; *s; s++)
  1537. X        typtab[(int) (unsigned char) *s] |= ISEP;
  1538. X    for (s = wordchars; *s; s++)
  1539. X        typtab[(int) (unsigned char) *s] |= IWORD;
  1540. X    for (s = SPECCHARS; *s; s++)
  1541. X        typtab[(int) (unsigned char) *s] |= ISPECIAL;
  1542. X}
  1543. X
  1544. Xchar **arrdup(s) /**/
  1545. Xchar **s;
  1546. X{
  1547. Xchar **x,**y;
  1548. X
  1549. X    y = x = (char **) ncalloc(sizeof(char *)*(arrlen(s)+1));
  1550. X    while (*x++ = strdup(*s++));
  1551. X    return y;
  1552. X}
  1553. X
  1554. X/* next few functions stolen (with changes) from Kernighan & Pike */
  1555. X/* "The UNIX Programming Environment" (w/o permission) */
  1556. X
  1557. Xchar *spname (oldname) /**/
  1558. Xchar *oldname;
  1559. X{
  1560. X    char *p,guess[MAXPATHLEN+1],best[MAXPATHLEN+1];
  1561. X    static char newname[MAXPATHLEN+1];
  1562. X    char *new = newname, *old;
  1563. X
  1564. X    if (itok(*oldname)) {
  1565. X        singsub(&oldname);
  1566. X        if (!oldname) return NULL;
  1567. X    }
  1568. X    if (access(oldname,F_OK) == 0) return NULL;
  1569. X    old = oldname;
  1570. X    for (;;) {
  1571. X        while (*old == '/') *new++ = *old++;
  1572. X        *new = '\0';
  1573. X        if (*old == '\0') return newname;
  1574. X        p = guess;
  1575. X        for (; *old != '/' && *old != '\0'; old++)
  1576. X            if (p < guess+MAXPATHLEN) *p++ = *old;
  1577. X        *p = '\0';
  1578. X        if (mindist(newname,guess,best) >= 3) return NULL;
  1579. X        for (p = best; *new = *p++; ) new++;
  1580. X    }
  1581. X}
  1582. X
  1583. Xint mindist(dir,guess,best) /**/
  1584. Xchar *dir;char *guess;char *best;
  1585. X{
  1586. X    int d,nd;
  1587. X    DIR *dd;
  1588. X    struct direct *de;
  1589. X    char buf[MAXPATHLEN];
  1590. X
  1591. X    if (dir[0] == '\0')
  1592. X        dir = ".";
  1593. X    d = 100;
  1594. X    sprintf(buf,"%s/%s",dir,guess);
  1595. X    if (access(buf,F_OK) == 0) { strcpy(best,guess); return 0; }
  1596. X    if (!(dd = opendir(dir))) return d;
  1597. X    while (de = readdir(dd)) {
  1598. X        nd = spdist(de->d_name,guess,strlen(guess)/4+1);
  1599. X        if (nd <= d) {
  1600. X            strcpy(best,de->d_name);
  1601. X            d = nd;
  1602. X            if (d == 0) break;
  1603. X        }
  1604. X    }
  1605. X    closedir(dd);
  1606. X    return d;
  1607. X}
  1608. X
  1609. Xint spdist(s,t,thresh) /**/
  1610. Xchar *s;char *t;int thresh;
  1611. X{
  1612. Xchar *p,*q;
  1613. Xchar *keymap =
  1614. X"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
  1615. X\t1234567890-=\t\
  1616. X\tqwertyuiop[]\t\
  1617. X\tasdfghjkl;'\n\t\
  1618. X\tzxcvbnm,./\t\t\t\
  1619. X\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
  1620. X\t!@#$%^&*()_+\t\
  1621. X\tQWERTYUIOP{}\t\
  1622. X\tASDFGHJKL:\"\n\t\
  1623. X\tZXCVBNM<>?\n\n\t\
  1624. X\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
  1625. X
  1626. X    if (!strcmp(s,t))
  1627. X        return 0;
  1628. X    /* any number of upper/lower mistakes allowed (dist = 1) */
  1629. X    for (p = s, q = t; *p && tulower(*p) == tulower(*q); p++,q++);
  1630. X    if (!*p && !*q)
  1631. X        return 1;
  1632. X    if (!thresh)
  1633. X        return 200;
  1634. X    for (p = s, q = t; *p && *q; p++,q++)
  1635. X        if (*p == *q) continue;    /* don't consider "aa" transposed, ash */
  1636. X        else if (p[1] == q[0] && q[1] == p[0])  /* transpositions */
  1637. X            return spdist(p+2,q+2,thresh-1)+1;
  1638. X        else if (p[1] == q[0])    /* missing letter */
  1639. X            return spdist(p+1,q+0,thresh-1)+2;
  1640. X        else if (p[0] == q[1])    /* missing letter */
  1641. X            return spdist(p+0,q+1,thresh-1)+2;
  1642. X        else if (*p != *q)
  1643. X            break;
  1644. X    if ((!*p && strlen(q) == 1) || (!*q && strlen(p) == 1))
  1645. X        return 2;
  1646. X    for (p = s, q = t; *p && *q; p++,q++)
  1647. X        if (p[0] != q[0] && p[1] == q[1])
  1648. X            {
  1649. X            int t0;
  1650. X            char *z;
  1651. X
  1652. X            /* mistyped letter */
  1653. X
  1654. X            if (!(z = strchr(keymap,p[0])) || *z == '\n' || *z == '\t')
  1655. X                return spdist(p+1,q+1,thresh-1)+1;
  1656. X            t0 = z-keymap;
  1657. X            if (*q == keymap[t0-15] || *q == keymap[t0-14] ||
  1658. X                    *q == keymap[t0-13] ||
  1659. X                    *q == keymap[t0-1] || *q == keymap[t0+1] ||
  1660. X                    *q == keymap[t0+13] || *q == keymap[t0+14] ||
  1661. X                    *q == keymap[t0+15])
  1662. X                return spdist(p+1,q+1,thresh-1)+2;
  1663. X            return 200;
  1664. X            }
  1665. X        else if (*p != *q)
  1666. X            break;
  1667. X    return 200;
  1668. X}
  1669. X
  1670. Xchar *zgetenv(s) /**/
  1671. Xchar *s;
  1672. X{
  1673. Xchar **av,*p,*q;
  1674. X
  1675. X    for (av = environ; *av; av++)
  1676. X        {
  1677. X        for (p = *av, q = s; *p && *p != '=' && *q && *p == *q; p++,q++);
  1678. X        if (*p == '=' && !*q)
  1679. X            return p+1;
  1680. X        }
  1681. X    return NULL;
  1682. X}
  1683. X
  1684. Xint tulower(c) /**/
  1685. Xint c;
  1686. X{
  1687. X    c &= 0xff;
  1688. X    return (isupper(c) ? tolower(c) : c);
  1689. X}
  1690. X
  1691. Xint tuupper(c) /**/
  1692. Xint c;
  1693. X{
  1694. X    c &= 0xff;
  1695. X    return (islower(c) ? toupper(c) : c);
  1696. X}
  1697. X
  1698. X#ifdef SYSV
  1699. X#include <sys/utsname.h>
  1700. X
  1701. Xint gethostname(nameptr, maxlength)
  1702. Xchar *nameptr;
  1703. Xint maxlength;
  1704. X{
  1705. Xstruct utsname *name;
  1706. Xint result;
  1707. X
  1708. X    result = uname(name);
  1709. X    if (result >= 0) {
  1710. X        strcpy(nameptr,name->sysname);
  1711. X        return 0;
  1712. X    } else return -1;
  1713. X}
  1714. X#endif
  1715. X
  1716. X/* set cbreak mode, or the equivalent */
  1717. X
  1718. Xvoid setcbreak() /**/
  1719. X{
  1720. Xstruct ttyinfo ti;
  1721. X
  1722. X    ti = shttyinfo;
  1723. X#ifdef TIO
  1724. X    ti.tio.c_lflag &= ~ICANON;
  1725. X    ti.tio.c_cc[VMIN] = 1;
  1726. X    ti.tio.c_cc[VTIME] = 0;
  1727. X#else
  1728. X    ti.sgttyb.sg_flags |= CBREAK;
  1729. X#endif
  1730. X    settyinfo(&ti);
  1731. X}
  1732. X
  1733. Xint getlineleng() /**/
  1734. X{
  1735. Xint z;
  1736. X
  1737. X#ifdef TIOCSWINSZ
  1738. X    z = shttyinfo.winsize.ws_col;
  1739. X    return (z) ? z : 80;
  1740. X#else
  1741. X    return 80;
  1742. X#endif
  1743. X}
  1744. X
  1745. Xvoid unsetcbreak() /**/
  1746. X{
  1747. X    settyinfo(&shttyinfo);
  1748. X}
  1749. X
  1750. X/* give the tty to some process */
  1751. X
  1752. Xvoid attachtty(pgrp) /**/
  1753. Xlong pgrp;
  1754. X{
  1755. Xstatic int ep = 0;
  1756. X
  1757. X    if (jobbing) {
  1758. X#ifdef HAS_TCSETPGRP
  1759. X        if (SHTTY != -1 && tcsetpgrp(SHTTY,pgrp) == -1 && !ep)
  1760. X#else
  1761. X        int arg = pgrp;
  1762. X        if (SHTTY != -1 && ioctl(SHTTY,TIOCSPGRP,&arg) == -1 && !ep)
  1763. X#endif
  1764. X            {
  1765. X            zerr("can't set tty pgrp: %e",NULL,errno);
  1766. X            fflush(stderr);
  1767. X            opts[MONITOR] = OPT_UNSET;
  1768. X            ep =1;
  1769. X            errflag = 0;
  1770. X            }
  1771. X    }
  1772. X}
  1773. X
  1774. X/* get the tty pgrp */
  1775. X
  1776. Xlong gettygrp() /**/
  1777. X{
  1778. Xint arg = -1;
  1779. X
  1780. X    if (SHTTY == -1) return -1;
  1781. X#ifdef HAS_TCSETPGRP
  1782. X    arg = tcgetpgrp(SHTTY);
  1783. X#else
  1784. X    ioctl(SHTTY,TIOCGPGRP,&arg);
  1785. X#endif
  1786. X    return arg;
  1787. X}
  1788. SHAR_EOF
  1789. echo 'File zsh2.2/src/utils.c is complete' &&
  1790. chmod 0644 zsh2.2/src/utils.c ||
  1791. echo 'restore of zsh2.2/src/utils.c failed'
  1792. Wc_c="`wc -c < 'zsh2.2/src/utils.c'`"
  1793. test 32116 -eq "$Wc_c" ||
  1794.     echo 'zsh2.2/src/utils.c: original size 32116, current size' "$Wc_c"
  1795. rm -f _shar_wnt_.tmp
  1796. fi
  1797. # ============= zsh2.2/src/watch.c ==============
  1798. if test -f 'zsh2.2/src/watch.c' -a X"$1" != X"-c"; then
  1799.     echo 'x - skipping zsh2.2/src/watch.c (File already exists)'
  1800.     rm -f _shar_wnt_.tmp
  1801. else
  1802. > _shar_wnt_.tmp
  1803. echo 'x - extracting zsh2.2/src/watch.c (Text)'
  1804. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/watch.c' &&
  1805. X/*
  1806. X *
  1807. X * watch.c - login/logout watching
  1808. X *
  1809. X * This file is part of zsh, the Z shell.
  1810. X *
  1811. X * This software is Copyright 1992 by Paul Falstad
  1812. X *
  1813. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  1814. X * use this software as long as: there is no monetary profit gained
  1815. X * specifically from the use or reproduction of this software, it is not
  1816. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  1817. X * included prominently in any copy made. 
  1818. X *
  1819. X * The author make no claims as to the fitness or correctness of this software
  1820. X * for any use whatsoever, and it is provided as is. Any use of this software
  1821. X * is at the user's own risk. 
  1822. X *
  1823. X */
  1824. X
  1825. X#include "zsh.h"
  1826. X#include <utmp.h>
  1827. X
  1828. Xstatic int wtabsz;
  1829. Xstruct utmp *wtab;
  1830. X
  1831. X/* get the time of login/logout for WATCH */
  1832. X
  1833. Xtime_t getlogtime(u,inout) /**/
  1834. Xstruct utmp *u;int inout;
  1835. X{
  1836. XFILE *in;
  1837. Xstruct utmp uu;
  1838. Xint first = 1;
  1839. Xint srchlimit = 50; /* max number of wtmp records to search */
  1840. X
  1841. X    if (inout)
  1842. X        return u->ut_time;
  1843. X    if (!(in = fopen(WTMP_FILE,"r")))
  1844. X        return time(NULL);
  1845. X    fseek(in,0,2);
  1846. X    do
  1847. X        {
  1848. X        if (fseek(in,((first) ? -1 : -2)*sizeof(struct utmp),1))
  1849. X            {
  1850. X            fclose(in);
  1851. X            return time(NULL);
  1852. X            }
  1853. X        first = 0;
  1854. X        if (!fread(&uu,sizeof(struct utmp),1,in))
  1855. X            {
  1856. X            fclose(in);
  1857. X            return time(NULL);
  1858. X            }
  1859. X        if (uu.ut_time < lastwatch || !srchlimit--)
  1860. X            {
  1861. X            fclose(in);
  1862. X            return time(NULL);
  1863. X            }
  1864. X        }
  1865. X    while (memcmp(&uu,u,sizeof(struct utmp)));
  1866. X    do
  1867. X        if (!fread(&uu,sizeof(struct utmp),1,in))
  1868. X            {
  1869. X            fclose(in);
  1870. X            return time(NULL);
  1871. X            }
  1872. X    while (strncmp(uu.ut_line,u->ut_line,8));
  1873. X    fclose(in);
  1874. X    return uu.ut_time;
  1875. X}
  1876. X
  1877. X/* print a login/logout event */
  1878. X
  1879. Xvoid watchlog2(inout,u,fmt) /**/
  1880. Xint inout;struct utmp *u;char *fmt;
  1881. X{
  1882. Xchar *p,buf[40],*bf;
  1883. Xint i;
  1884. Xtime_t timet;
  1885. Xstruct tm *tm = NULL;
  1886. X
  1887. X    while (*fmt)
  1888. X        if (*fmt != '%')
  1889. X            putchar(*fmt++);
  1890. X        else
  1891. X            {
  1892. X            fmt++;
  1893. X            switch(*fmt++)
  1894. X                {
  1895. X                case 'n':
  1896. X                    printf("%.*s",8,u->ut_name);
  1897. X                    break;
  1898. X                case 'a':
  1899. X                    printf("%s",(!inout) ? "logged off" : "logged on");
  1900. X                    break;
  1901. X                case 'l':
  1902. X                    if (u->ut_line[0] == 't')
  1903. X                        printf("%.*s",5,u->ut_line+3);
  1904. X                    else
  1905. X                        printf("%.*s",8,u->ut_line);
  1906. X                    break;
  1907. X#ifdef UTMP_HOST
  1908. X                case 'm':
  1909. X                    for (p = u->ut_host,i = 16; i && *p;i--,p++)
  1910. X                        {
  1911. X                        if (*p == '.' && !idigit(p[1]))
  1912. X                            break;
  1913. X                        putchar(*p);
  1914. X                        }
  1915. X                    break;
  1916. X                case 'M':
  1917. X                    printf("%.*s",16,u->ut_host);
  1918. X                    break;
  1919. X#endif
  1920. X                case 't':
  1921. X                case '@':
  1922. X                    timet = getlogtime(u,inout);
  1923. X                    tm = localtime(&timet);
  1924. X                    ztrftime(buf,40,"%l:%M%p",tm);
  1925. X                    printf("%s",(*buf == ' ') ? buf+1 : buf);
  1926. X                    break;
  1927. X                case 'T':
  1928. X                    timet = getlogtime(u,inout);
  1929. X                    tm = localtime(&timet);
  1930. X                    ztrftime(buf,40,"%k:%M",tm);
  1931. X                    printf("%s",buf);
  1932. X                    break;
  1933. X                case 'w':
  1934. X                    timet = getlogtime(u,inout);
  1935. X                    tm = localtime(&timet);
  1936. X                    ztrftime(buf,40,"%a %e",tm);
  1937. X                    printf("%s",buf);
  1938. X                    break;
  1939. X                case 'W':
  1940. X                    timet = getlogtime(u,inout);
  1941. X                    tm = localtime(&timet);
  1942. X                    ztrftime(buf,40,"%m/%d/%y",tm);
  1943. X                    printf("%s",buf);
  1944. X                    break;
  1945. X                case 'D':
  1946. X                    timet = getlogtime(u,inout);
  1947. X                    tm = localtime(&timet);
  1948. X                    ztrftime(buf,40,"%y-%m-%d",tm);
  1949. X                    printf("%s",buf);
  1950. X                    break;
  1951. X                case '%':
  1952. X                    putchar('%');
  1953. X                    break;
  1954. X                case 'S':
  1955. X                    bf = buf;
  1956. X                    if (tgetstr("so",&bf))
  1957. X                        fputs(buf,stdout);
  1958. X                    break;
  1959. X                case 's':
  1960. X                    bf = buf;
  1961. X                    if (tgetstr("se",&bf))
  1962. X                        fputs(buf,stdout);
  1963. X                    break;
  1964. X                case 'B':
  1965. X                    bf = buf;
  1966. X                    if (tgetstr("md",&bf))
  1967. X                        fputs(buf,stdout);
  1968. X                    break;
  1969. X                case 'b':
  1970. X                    bf = buf;
  1971. X                    if (tgetstr("me",&bf))
  1972. X                        fputs(buf,stdout);
  1973. X                    break;
  1974. X                case 'U':
  1975. X                    bf = buf;
  1976. X                    if (tgetstr("us",&bf))
  1977. X                        fputs(buf,stdout);
  1978. X                    break;
  1979. X                case 'u':
  1980. X                    bf = buf;
  1981. X                    if (tgetstr("ue",&bf))
  1982. X                        fputs(buf,stdout);
  1983. X                    break;
  1984. X                default:
  1985. X                    putchar('%');
  1986. X                    putchar(fmt[-1]);
  1987. X                    break;
  1988. X                }
  1989. X            }
  1990. X    putchar('\n');
  1991. X}
  1992. X
  1993. X/* check the List for login/logouts */
  1994. X
  1995. Xvoid watchlog(inout,u,w,fmt) /**/
  1996. Xint inout;struct utmp *u;char **w;char *fmt;
  1997. X{
  1998. Xchar *v,*vv,sav;
  1999. Xint bad;
  2000. X
  2001. X    if (*w && !strcmp(*w,"all"))
  2002. X        {
  2003. X        watchlog2(inout,u,fmt);
  2004. X        return;
  2005. X        }
  2006. X    for (; *w; w++)
  2007. X        {
  2008. X        bad = 0;
  2009. X        v = *w;
  2010. X        if (*v != '@' && *v != '%')
  2011. X            {
  2012. X            for (vv = v; *vv && *vv != '@' && *vv != '%'; vv++);
  2013. X            sav = *vv;
  2014. X            *vv = '\0';
  2015. X            if (strncmp(u->ut_name,v,8))
  2016. X                bad = 1;
  2017. X            *vv = sav;
  2018. X            v = vv;
  2019. X            }
  2020. X        for (;;)
  2021. X            if (*v == '%')
  2022. X                {
  2023. X                for (vv = ++v; *vv && *vv != '@'; vv++);
  2024. X                sav = *vv;
  2025. X                *vv = '\0';
  2026. X                if (strncmp(u->ut_line,v,8))
  2027. X                    bad = 1;
  2028. X                *vv = sav;
  2029. X                v = vv;
  2030. X                }
  2031. X#ifdef UTMP_HOST
  2032. X            else if (*v == '@')
  2033. X                {
  2034. X                for (vv = ++v; *vv && *vv != '%'; vv++);
  2035. X                sav = *vv;
  2036. X                *vv = '\0';
  2037. X                if (strncmp(u->ut_host,v,strlen(v)))
  2038. X                    bad = 1;
  2039. X                *vv = sav;
  2040. X                v = vv;
  2041. X                }
  2042. X#endif
  2043. X            else
  2044. X                break;
  2045. X        if (!bad)
  2046. X            {
  2047. X            watchlog2(inout,u,fmt);
  2048. X            return;
  2049. X            }
  2050. X        }
  2051. X}
  2052. X
  2053. X/* compare 2 utmp entries */
  2054. X
  2055. Xint ucmp(u,v) /**/
  2056. Xstruct utmp *u;struct utmp *v;
  2057. X{
  2058. X    if (u->ut_time == v->ut_time)
  2059. X        return strncmp(u->ut_line,v->ut_line,8);
  2060. X    return u->ut_time - v->ut_time;
  2061. X}
  2062. X
  2063. X/* initialize the user List */
  2064. X
  2065. Xvoid readwtab() /**/
  2066. X{
  2067. Xstruct utmp *uptr;
  2068. Xint wtabmax = 32;
  2069. XFILE *in;
  2070. X
  2071. X    wtabsz = 0;
  2072. X    if (!(in = fopen(UTMP_FILE,"r"))) return;
  2073. X    uptr = wtab = (struct utmp *) zalloc(wtabmax*sizeof(struct utmp));
  2074. X    while (fread(uptr,sizeof(struct utmp),1,in))
  2075. X#ifdef USER_PROCESS
  2076. X        if (uptr->ut_type == USER_PROCESS)
  2077. X#else
  2078. X        if (uptr->ut_name[0])
  2079. X#endif
  2080. X            {
  2081. X            uptr++;
  2082. X            if (++wtabsz == wtabmax)
  2083. X                uptr = (wtab = (struct utmp *) realloc((vptr) wtab,(wtabmax*=2)*
  2084. X                    sizeof(struct utmp)))+wtabsz;
  2085. X            }
  2086. X    fclose(in);
  2087. X    if (wtabsz)
  2088. X        qsort(wtab,wtabsz,sizeof(struct utmp),ucmp);
  2089. X}
  2090. X
  2091. X/* check for login/logout events; executed before each prompt
  2092. X    if WATCH is set */
  2093. X
  2094. Xvoid dowatch() /**/
  2095. X{
  2096. Xchar **s = watch;
  2097. Xchar *fmt = (watchfmt) ? watchfmt : DEFWATCHFMT;
  2098. XFILE *in;
  2099. Xint utabsz = 0,utabmax = wtabsz+4,uct,wct;
  2100. Xstruct utmp *utab,*uptr,*wptr;
  2101. X
  2102. X    holdintr();
  2103. X    if (!fmt)
  2104. X        fmt = "%n has %a %l from %m.";
  2105. X    if (!wtab) {
  2106. X        readwtab();
  2107. X        noholdintr();
  2108. X        return;
  2109. X    }
  2110. X    uptr = utab = (struct utmp *) zalloc(utabmax*sizeof(struct utmp));
  2111. X    if (!(in = fopen(UTMP_FILE,"r"))) {
  2112. X        free(utab);
  2113. X        return;
  2114. X    }
  2115. X    while (fread(uptr,sizeof *uptr,1,in))
  2116. X#ifdef USER_PROCESS
  2117. X        if (uptr->ut_type == USER_PROCESS)
  2118. X#else
  2119. X        if (uptr->ut_name[0])
  2120. X#endif
  2121. X            {
  2122. X            uptr++;
  2123. X            if (++utabsz == utabmax)
  2124. X                uptr = (utab = (struct utmp *) realloc((vptr) utab,(utabmax*=2)*
  2125. X                    sizeof(struct utmp)))+utabsz;
  2126. X            }
  2127. X    fclose(in);
  2128. X    noholdintr();
  2129. X    if (errflag) {
  2130. X        free(utab);
  2131. X        return;
  2132. X    }
  2133. X    if (utabsz)
  2134. X        qsort(utab,utabsz,sizeof(struct utmp),ucmp);
  2135. X
  2136. X    wct = wtabsz; uct = utabsz;
  2137. X    uptr = utab; wptr = wtab;
  2138. X    if (errflag) {
  2139. X        free(utab);
  2140. X        return;
  2141. X    }
  2142. X    while ((uct || wct) && !errflag)
  2143. X        if (!uct || (wct && ucmp(uptr,wptr) > 0))
  2144. X            wct--,watchlog(0,wptr++,s,fmt);
  2145. X        else if (!wct || (uct && ucmp(uptr,wptr) < 0))
  2146. X            uct--,watchlog(1,uptr++,s,fmt);
  2147. X        else
  2148. X            uptr++,wptr++,wct--,uct--;
  2149. X    free(wtab);
  2150. X    wtab = utab;
  2151. X    wtabsz = utabsz;
  2152. X    fflush(stdout);
  2153. X}
  2154. X
  2155. Xint bin_log(nam,argv,ops,func) /**/
  2156. Xchar *nam;char **argv;char *ops;int func;
  2157. X{
  2158. X    if (!watch)
  2159. X        return 1;
  2160. X    if (wtab)
  2161. X        free(wtab);
  2162. X    wtab = (struct utmp *) zalloc(1);
  2163. X    wtabsz = 0;
  2164. X    dowatch();
  2165. X    return 0;
  2166. X}
  2167. X
  2168. SHAR_EOF
  2169. chmod 0644 zsh2.2/src/watch.c ||
  2170. echo 'restore of zsh2.2/src/watch.c failed'
  2171. Wc_c="`wc -c < 'zsh2.2/src/watch.c'`"
  2172. test 7149 -eq "$Wc_c" ||
  2173.     echo 'zsh2.2/src/watch.c: original size 7149, current size' "$Wc_c"
  2174. rm -f _shar_wnt_.tmp
  2175. fi
  2176. # ============= zsh2.2/src/zle.h ==============
  2177. if test -f 'zsh2.2/src/zle.h' -a X"$1" != X"-c"; then
  2178.     echo 'x - skipping zsh2.2/src/zle.h (File already exists)'
  2179.     rm -f _shar_wnt_.tmp
  2180. else
  2181. > _shar_wnt_.tmp
  2182. echo 'x - extracting zsh2.2/src/zle.h (Text)'
  2183. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle.h' &&
  2184. X/*
  2185. X *
  2186. X * zle.h - header file for line editor
  2187. X *
  2188. X * This file is part of zsh, the Z shell.
  2189. X *
  2190. X * This software is Copyright 1992 by Paul Falstad
  2191. X *
  2192. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  2193. X * use this software as long as: there is no monetary profit gained
  2194. X * specifically from the use or reproduction of this software, it is not
  2195. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  2196. X * included prominently in any copy made. 
  2197. X *
  2198. X * The author make no claims as to the fitness or correctness of this software
  2199. X * for any use whatsoever, and it is provided as is. Any use of this software
  2200. X * is at the user's own risk. 
  2201. X *
  2202. X */
  2203. X
  2204. X#ifdef ZLEGLOBALS
  2205. X#define ZLEXTERN
  2206. X#else
  2207. X#define ZLEXTERN extern
  2208. X#endif
  2209. X
  2210. X#ifdef ZLE
  2211. X
  2212. X/* cursor position */
  2213. XZLEXTERN int cs;
  2214. X
  2215. X/* line length */
  2216. XZLEXTERN int ll;
  2217. X
  2218. X/* size of line buffer */
  2219. XZLEXTERN int linesz;
  2220. X
  2221. X/* location of mark */
  2222. XZLEXTERN int mark;
  2223. X
  2224. X/* last character pressed */
  2225. XZLEXTERN int c;
  2226. X
  2227. X/* the z_ binding id for this key */
  2228. XZLEXTERN int bindk;
  2229. X
  2230. X/* command argument */
  2231. XZLEXTERN int mult;
  2232. X
  2233. X/* insert mode/overwrite mode flag */
  2234. XZLEXTERN int insmode;
  2235. X
  2236. X/* cost of last update */
  2237. XZLEXTERN int cost;
  2238. X
  2239. X/* flags associated with last command */
  2240. XZLEXTERN int lastcmd;
  2241. X
  2242. X/* column position before last LINEMOVE movement */
  2243. XZLEXTERN int lastcol;
  2244. X
  2245. X/* != 0 if we're getting a vi range */
  2246. XZLEXTERN int virangeflag;
  2247. X
  2248. X/* kludge to get cw and dw to work right */
  2249. XZLEXTERN int wordflag;
  2250. X
  2251. X#endif
  2252. X
  2253. X/* last named command done */
  2254. XZLEXTERN int lastnamed;
  2255. X
  2256. X/* != 0 if we're done editing */
  2257. XZLEXTERN int done;
  2258. X
  2259. X/* length of prompt on screen */
  2260. XZLEXTERN int pptlen;
  2261. X
  2262. X/* current history line number */
  2263. XZLEXTERN int histline;
  2264. X
  2265. XZLEXTERN int eofsent;
  2266. X
  2267. X/* != 0 if we need to call resetvideo() */
  2268. XZLEXTERN int resetneeded;
  2269. X
  2270. X/* != 0 if the line editor is active */
  2271. XZLEXTERN int zleactive;
  2272. X
  2273. X/* the line buffer */
  2274. XZLEXTERN unsigned char *line;
  2275. X
  2276. X/* the cut buffer */
  2277. XZLEXTERN char *cutbuf;
  2278. X
  2279. X/* prompt and rprompt */
  2280. XZLEXTERN char *pmpt, *pmpt2;
  2281. X
  2282. X/* the last line in the history (the current one) */
  2283. XZLEXTERN char *curhistline;
  2284. X
  2285. X/* the status line */
  2286. XZLEXTERN char *statusline;
  2287. X
  2288. X/* 1 if a complete added a slash at the end of a directory name */
  2289. XZLEXTERN int addedslash;
  2290. X
  2291. X/*
  2292. X    the current history line and cursor position for the top line
  2293. X    on the buffer stack
  2294. X*/
  2295. X
  2296. XZLEXTERN int stackhist,stackcs;
  2297. X
  2298. X/* != 0 if we are in the middle of a menu completion */
  2299. XZLEXTERN int menucmp;
  2300. X
  2301. X/* != 0 if we are making undo records */
  2302. XZLEXTERN int undoing;
  2303. X
  2304. X/* last vi change buffer */
  2305. XZLEXTERN int vichgbufsz,vichgbufptr,vichgflag;
  2306. XZLEXTERN char *vichgbuf;
  2307. X
  2308. XZLEXTERN int viinsbegin;
  2309. X
  2310. Xtypedef void bindfunc DCLPROTO((void));
  2311. Xtypedef bindfunc *F;
  2312. X
  2313. Xstruct key {
  2314. X    struct hashnode *next; int canfree; char *nam; /* hash data */
  2315. X    int func;            /* function code for this key */
  2316. X    char *str;            /* string corresponding to this key,
  2317. X                                if func = z_sequenceleadin                 */
  2318. X    int len;                /* length of string */
  2319. X    };
  2320. Xstruct zlecmd {
  2321. X    char *name;            /* name of function */
  2322. X    F func;                /* handler function */
  2323. X    int flags;
  2324. X    };
  2325. X
  2326. X/* undo event */
  2327. X
  2328. Xstruct undoent {
  2329. X    int pref;        /* number of initial chars unchanged */
  2330. X    int suff;        /* number of trailing chars unchanged */
  2331. X    int len;            /* length of changed chars */
  2332. X    int cs;            /* cursor pos before change */
  2333. X    char *change;    /* NOT null terminated */
  2334. X    };
  2335. X
  2336. X#define UNDOCT 64
  2337. X
  2338. Xstruct undoent undos[UNDOCT];
  2339. X
  2340. X/* the line before last mod (for undo purposes) */
  2341. XZLEXTERN unsigned char *lastline;
  2342. X
  2343. X/* buffer specified with "x */
  2344. XZLEXTERN int vibufspec;
  2345. X
  2346. XZLEXTERN int undoct,lastcs;
  2347. X
  2348. XZLEXTERN char *visrchstr;
  2349. XZLEXTERN int visrchsense;
  2350. X
  2351. X#define ZLE_MOVEMENT       1
  2352. X#define ZLE_MENUCMP       2
  2353. X#define ZLE_UNDO           4
  2354. X#define ZLE_YANK          8
  2355. X#define ZLE_LINEMOVE      16
  2356. X#define ZLE_ARG           32
  2357. X#define ZLE_NAMEDBUFFER 128
  2358. X#define ZLE_KILL        (64|ZLE_NAMEDBUFFER)
  2359. X#define ZLE_HISTSEARCH  256
  2360. X#define ZLE_NEGARG      512
  2361. X#define ZLE_INSERT     1024
  2362. X
  2363. Xtypedef struct key *Key;
  2364. X
  2365. XZLEXTERN int *bindtab;
  2366. Xextern int emacsbind[256];
  2367. XZLEXTERN int altbindtab[256],mainbindtab[256];
  2368. Xextern int viinsbind[],vicmdbind[];
  2369. XZLEXTERN int vimarkcs[27],vimarkline[27];
  2370. X
  2371. X#define KRINGCT 8
  2372. XZLEXTERN char *kring[KRINGCT];
  2373. XZLEXTERN int kringnum;
  2374. XZLEXTERN char *vibuf[36];
  2375. X
  2376. X#define z_acceptandhold 0
  2377. X#define z_acceptandinfernexthistory 1
  2378. X#define z_acceptandmenucomplete 2
  2379. X#define z_acceptline 3
  2380. X#define z_acceptlineanddownhistory 4
  2381. X#define z_backwardchar 5
  2382. X#define z_backwarddeletechar 6
  2383. X#define z_backwarddeleteword 7
  2384. X#define z_backwardkillline 8
  2385. X#define z_backwardkillword 9
  2386. X#define z_backwardword 10
  2387. X#define z_beginningofbufferorhistory 11
  2388. X#define z_beginningofhistory 12
  2389. X#define z_beginningofline 13
  2390. X#define z_beginningoflinehist 14
  2391. X#define z_capitalizeword 15
  2392. X#define z_clearscreen 16
  2393. X#define z_completeword 17
  2394. X#define z_copyprevword 18
  2395. X#define z_copyregionaskill 19
  2396. X#define z_deletechar 20
  2397. X#define z_deletecharorlist 21
  2398. X#define z_deleteword 22
  2399. X#define z_digitargument 23
  2400. X#define z_downcaseword 24
  2401. X#define z_downhistory 25
  2402. X#define z_downlineorhistory 26
  2403. X#define z_endofbufferorhistory 27
  2404. X#define z_endofhistory 28
  2405. X#define z_endofline 29
  2406. X#define z_endoflinehist 30
  2407. X#define z_exchangepointandmark 31
  2408. X#define z_executelastnamedcmd 32
  2409. X#define z_executenamedcmd 33
  2410. X#define z_expandhistory 34
  2411. X#define z_expandorcomplete 35
  2412. X#define z_expandword 36
  2413. X#define z_forwardchar 37
  2414. X#define z_forwardword 38
  2415. X#define z_getline 39
  2416. X#define z_gosmacstransposechars 40
  2417. X#define z_historyincrementalsearchbackward 41
  2418. X#define z_historyincrementalsearchforward 42
  2419. X#define z_historysearchbackward 43
  2420. X#define z_historysearchforward 44
  2421. X#define z_infernexthistory 45
  2422. X#define z_insertlastword 46
  2423. X#define z_killbuffer 47
  2424. X#define z_killline 48
  2425. X#define z_killregion 49
  2426. X#define z_killwholeline 50
  2427. X#define z_listchoices 51
  2428. X#define z_listexpand 52
  2429. X#define z_magicspace 53
  2430. X#define z_menucompleteword 54
  2431. X#define z_menuexpandorcomplete 55
  2432. X#define z_overwritemode 56
  2433. X#define z_pushline 57
  2434. X#define z_quotedinsert 58
  2435. X#define z_quoteline 59
  2436. X#define z_quoteregion 60
  2437. X#define z_redisplay 61
  2438. X#define z_reversemenucomplete 62
  2439. X#define z_runhelp 63
  2440. X#define z_selfinsert 64
  2441. X#define z_selfinsertunmeta 65
  2442. X#define z_sendbreak 66
  2443. X#define z_sendstring 67
  2444. X#define z_sequenceleadin 68
  2445. X#define z_setmarkcommand 69
  2446. X#define z_spellword 70
  2447. X#define z_toggleliteralhistory 71
  2448. X#define z_transposechars 72
  2449. X#define z_transposewords 73
  2450. X#define z_undefinedkey 74
  2451. X#define z_undo 75
  2452. X#define z_universalargument 76
  2453. X#define z_upcaseword 77
  2454. X#define z_uphistory 78
  2455. X#define z_uplineorhistory 79
  2456. X#define z_viaddeol 80
  2457. X#define z_viaddnext 81
  2458. X#define z_vibackwardblankword 82
  2459. X#define z_vibackwardchar 83
  2460. X#define z_vibackwarddeletechar 84
  2461. X#define z_vibeginningofline 85
  2462. X#define z_vicapslockpanic 86
  2463. X#define z_vichange 87
  2464. X#define z_vichangeeol 88
  2465. X#define z_vichangewholeline 89
  2466. X#define z_vicmdmode 90
  2467. X#define z_videlete 91
  2468. X#define z_videletechar 92
  2469. X#define z_vidigitorbeginningofline 93
  2470. X#define z_viendofline 94
  2471. X#define z_vifetchhistory 95
  2472. X#define z_vifindnextchar 96
  2473. X#define z_vifindnextcharskip 97
  2474. X#define z_vifindprevchar 98
  2475. X#define z_vifindprevcharskip 99
  2476. X#define z_vifirstnonblank 100
  2477. X#define z_viforwardblankword 101
  2478. X#define z_viforwardblankwordend 102
  2479. X#define z_viforwardchar 103
  2480. SHAR_EOF
  2481. true || echo 'restore of zsh2.2/src/zle.h failed'
  2482. fi
  2483. echo 'End of zsh2.2 part 12'
  2484. echo 'File zsh2.2/src/zle.h is continued in part 13'
  2485. echo 13 > _shar_seq_.tmp
  2486. exit 0
  2487.  
  2488. exit 0 # Just in case...
  2489.