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

  1. Newsgroups: comp.sources.misc
  2. From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  3. Subject:  v24i010:  zsh2.1 - The Z shell, Part10/19
  4. Message-ID: <1991Oct26.014840.19355@sparky.imd.sterling.com>
  5. X-Md4-Signature: 1d50873c348f6aa03f43aa63c494f7f9
  6. Date: Sat, 26 Oct 1991 01:48:40 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
  10. Posting-number: Volume 24, Issue 10
  11. Archive-name: zsh2.1/part10
  12. Environment: BSD
  13. Supersedes: zsh2.00: Volume 18, Issue 84-98
  14.  
  15. #!/bin/sh
  16. # this is zshar.10 (part 10 of zsh2.1.0)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file zsh2.1/src/subst.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" != 10; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping zsh2.1/src/subst.c'
  34. else
  35. echo 'x - continuing file zsh2.1/src/subst.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.1/src/subst.c' &&
  37. X    if (isarr)
  38. X        if (plan9)
  39. X            {
  40. X            int dlen;
  41. X            char *y;
  42. X
  43. X            y = ncalloc((dlen = (char *) aptr-bptr+strlen(s)+1)+strlen(aval[0]));
  44. X            setdata(n,y);
  45. X            strcpy(y,ostr);
  46. X            strcat(y,aval[0]);
  47. X            strcat(y,s);
  48. X            while (*++aval)
  49. X                {
  50. X                char *x = ncalloc(dlen+strlen(*aval));
  51. X
  52. X                strcpy(x,ostr);
  53. X                strcat(x,*aval);
  54. X                strcat(x,s);
  55. X                insnode(l,n,x), incnode(n);
  56. X                }
  57. X            }
  58. X        else
  59. X            {
  60. X            char *zz;
  61. X
  62. X            zz = ncalloc((char *) aptr-(bptr)+strlen(aval[0])+1);
  63. X            setdata(n,zz);
  64. X            strcpy(zz,ostr);
  65. X            strcat(zz,*aval++);
  66. X            while (aval[1])
  67. X                insnode(l,n,*aval++), incnode(n);
  68. X            zz = ncalloc(strlen(*aval)+strlen(s)+1);
  69. X            strcpy(zz,*aval);
  70. X            strcat(zz,s);
  71. X            insnode(l,n,zz);
  72. X            }
  73. X    else
  74. X        {
  75. X        bptr = ncalloc((char *) aptr-bptr+strlen(val)+strlen(s)+1);
  76. X        setdata(n,bptr);
  77. X        strcpy(bptr,ostr);
  78. X        strcat(bptr,val);
  79. X        strcat(bptr,s);
  80. X        }
  81. X}
  82. X
  83. X/* arithmetic substitution */
  84. X
  85. Xvoid arithsubst(aptr,bptr) /**/
  86. Xvptr *aptr;char **bptr;
  87. X{
  88. Xchar *s = *aptr,*t,buf[16];
  89. Xlong v;
  90. X
  91. X    *s = '\0';
  92. X    for (; *s != Outbrack; s++);
  93. X    *s++ = '\0';
  94. X    v = matheval((char *) *aptr+2);
  95. X    sprintf(buf,"%ld",v);
  96. X    t = ncalloc(strlen(*bptr)+strlen(buf)+strlen(s)+1);
  97. X    strcpy(t,*bptr);
  98. X    strcat(t,buf);
  99. X    strcat(t,s);
  100. X    *bptr = t;
  101. X}
  102. X
  103. Xvoid modify(str,ptr) /**/
  104. Xchar **str;char **ptr;
  105. X{
  106. Xchar *ptr1,*ptr2,*ptr3,del,*lptr;
  107. Xint gbal;
  108. X
  109. X    if (**ptr == ':')
  110. X        *str = strdup(*str);
  111. X    while (**ptr == ':')
  112. X        {
  113. X        lptr = *ptr;
  114. X        (*ptr)++;
  115. X        gbal = 0;
  116. Xhere:
  117. X        switch(*(*ptr)++)
  118. X            {
  119. X            case 'h': remtpath(str); break;
  120. X            case 'r': remtext(str); break;
  121. X            case 'e': rembutext(str); break;
  122. X            case 't': remlpaths(str); break;
  123. X            case 'l': downcase(str); break;
  124. X            case 'u': upcase(str); break;
  125. X            case 's':
  126. X                if (hsubl)
  127. X                    free(hsubl);
  128. X                if (hsubr)
  129. X                    free(hsubr);
  130. X                ptr1 = *ptr;
  131. X                del = *ptr1++;
  132. X                for (ptr2 = ptr1; *ptr2 != del && *ptr2; ptr2++);
  133. X                if (!*ptr2)
  134. X                    {
  135. X                    zerr("bad subtitution",NULL,0);
  136. X                    errflag = 1;
  137. X                    return;
  138. X                    }
  139. X                *ptr2++ = '\0';
  140. X                for (ptr3 = ptr2; *ptr3 != del && *ptr3; ptr3++);
  141. X                if (*ptr3)
  142. X                    *ptr3++ = '\0';
  143. X                hsubl = ztrdup(ptr1);
  144. X                hsubr = ztrdup(ptr2);
  145. X                *ptr = ptr3;
  146. X            case '&':
  147. X                if (hsubl && hsubr)
  148. X                    subst(str,hsubl,hsubr,gbal);
  149. X                break;
  150. X            case 'g': gbal = 1; goto here;
  151. X            default: *ptr = lptr; return;
  152. X            }
  153. X        }
  154. X}
  155. X
  156. X/* get a directory stack entry */
  157. X
  158. Xchar *dstackent(val) /**/
  159. Xint val;
  160. X{
  161. XLknode node;
  162. X    if ((val < 0 && !firstnode(dirstack)) || !val--)
  163. X        return cwd;
  164. X    if (val < 0)
  165. X        node = lastnode(dirstack);
  166. X    else
  167. X        for (node = firstnode(dirstack); node && val; val--,incnode(node));
  168. X    if (!node)
  169. X        {
  170. X        zerr("not enough dir stack entries.",NULL,0);
  171. X        errflag = 1;
  172. X        return NULL;
  173. X        }
  174. X    return getdata(node);
  175. X}
  176. X
  177. X/* make an alias hash table node */
  178. X
  179. Xstruct alias *mkanode(txt,cmflag) /**/
  180. Xchar *txt;int cmflag;
  181. X{
  182. Xstruct alias *ptr = (Alias) zcalloc(sizeof *ptr);
  183. X
  184. X    ptr->text  = txt;
  185. X    ptr->cmd = cmflag;
  186. X    ptr->inuse = 0;
  187. X    return ptr;
  188. X}
  189. SHAR_EOF
  190. echo 'File zsh2.1/src/subst.c is complete' &&
  191. chmod 0644 zsh2.1/src/subst.c ||
  192. echo 'restore of zsh2.1/src/subst.c failed'
  193. Wc_c="`wc -c < 'zsh2.1/src/subst.c'`"
  194. test 15253 -eq "$Wc_c" ||
  195.     echo 'zsh2.1/src/subst.c: original size 15253, current size' "$Wc_c"
  196. rm -f _shar_wnt_.tmp
  197. fi
  198. # ============= zsh2.1/src/table.c ==============
  199. if test -f 'zsh2.1/src/table.c' -a X"$1" != X"-c"; then
  200.     echo 'x - skipping zsh2.1/src/table.c (File already exists)'
  201.     rm -f _shar_wnt_.tmp
  202. else
  203. > _shar_wnt_.tmp
  204. echo 'x - extracting zsh2.1/src/table.c (Text)'
  205. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/table.c' &&
  206. X/*
  207. X
  208. X    table.c - linked lists and hash tables
  209. X
  210. X    This file is part of zsh, the Z shell.
  211. X
  212. X    zsh is free software; no one can prevent you from reading the source
  213. X   code, or giving it to someone else.
  214. X
  215. X   This file is copyrighted under the GNU General Public License, which
  216. X   can be found in the file called COPYING.
  217. X
  218. X   Copyright (C) 1990, 1991 Paul Falstad
  219. X
  220. X   zsh is distributed in the hope that it will be useful, but
  221. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  222. X   responsibility to anyone for the consequences of using it or for
  223. X   whether it serves any particular purpose or works at all, unless he
  224. X   says so in writing.  Refer to the GNU General Public License
  225. X   for full details.
  226. X
  227. X   Everyone is granted permission to copy, modify and redistribute
  228. X   zsh, but only under the conditions described in the GNU General Public
  229. X   License.   A copy of this license is supposed to have been given to you
  230. X   along with zsh so you can know your rights and responsibilities.
  231. X   It should be in a file named COPYING.
  232. X
  233. X   Among other things, the copyright notice and this notice must be
  234. X   preserved on all copies.
  235. X
  236. X*/
  237. X
  238. X#define TABLE_C
  239. X#include "zsh.h"
  240. X
  241. X/* get an empty linked list header */
  242. X
  243. XLklist newlist() /**/
  244. X{
  245. XLklist list;
  246. X    list = (Lklist) alloc(sizeof *list);
  247. X    list->first = 0;
  248. X    list->last = (Lknode) list;
  249. X    return list;
  250. X}
  251. X
  252. X/* get an empty hash table */
  253. X
  254. XHashtab newhtable(size) /**/
  255. Xint size;
  256. X{
  257. XHashtab ret;
  258. X    ret = (Hashtab) zcalloc(sizeof *ret);
  259. X    ret->hsize = size;
  260. X    ret->nodes = (Hashnode*) zcalloc(size*sizeof(Hashnode));
  261. X    return ret;
  262. X}
  263. X/* Peter Weinberger's hash function */
  264. X
  265. Xint hasher(s) /**/
  266. Xchar *s;
  267. X{
  268. Xunsigned hash = 0,g;
  269. X    for (; *s; s++)
  270. X        {
  271. X        hash = (hash << 4) + *s;
  272. X        if (g = hash & 0xf0000000)
  273. X            {
  274. X            hash ^= g;
  275. X            hash ^= g >> 24;
  276. X            }
  277. X        }
  278. X    return hash;
  279. X}
  280. X
  281. X/* add a node to a hash table */
  282. X
  283. Xvoid Addhnode(nam,dat,ht,freefunc,canfree) /**/
  284. Xchar *nam;vptr dat;Hashtab ht;FFunc freefunc;int canfree;
  285. X{
  286. Xint hval = hasher(nam) % ht->hsize;
  287. Xstruct hashnode *hp = ht->nodes[hval],*hn;
  288. X    for (; hp; hp = hp->next)
  289. X        if (!strcmp(hp->nam,nam))
  290. X            {
  291. X            if (!freefunc)
  292. X                zerr("attempt to call NULL freefunc",NULL,0);
  293. X            else
  294. X                freefunc(hp->dat);
  295. X            hp->dat = dat;
  296. X            if (hp->canfree)
  297. X                {
  298. X                free(hp->nam);
  299. X                hp->nam = nam;
  300. X                }
  301. X            hp->canfree = canfree;
  302. X            return;
  303. X            }
  304. X    hn = (Hashnode) zcalloc(sizeof *hn);
  305. X    hn->nam = nam;
  306. X    hn->dat = dat;
  307. X    hn->canfree = canfree;
  308. X    hn->next = ht->nodes[hval];
  309. X    ht->nodes[hval] = hn;
  310. X    if (++ht->ct == ht->hsize*4)
  311. X        expandhtab(ht);
  312. X}
  313. X
  314. X/* expand hash tables when they get too many entries */
  315. X
  316. Xvoid expandhtab(ht) /**/
  317. XHashtab ht;
  318. X{
  319. Xstruct hashnode *hp,**arr,**ha,*hn;
  320. Xint osize = ht->hsize,nsize = osize*8;
  321. X
  322. X    ht->hsize = nsize;
  323. X    arr = ht->nodes;
  324. X    ht->nodes = (Hashnode*) zcalloc(nsize*sizeof(struct hashnode *));
  325. X    for (ha = arr; osize; osize--,ha++)
  326. X        for (hn = *ha; hn; )
  327. X            {
  328. X            Addhnode(hn->nam,hn->dat,ht,NULL,hn->canfree);
  329. X            hp = hn->next;
  330. X            free(hn);
  331. X            hn = hp;
  332. X            }
  333. X    free(arr);
  334. X}
  335. X
  336. X/* get an entry in a hash table */
  337. X
  338. Xvptr gethnode(nam,ht) /**/
  339. Xchar *nam;Hashtab ht;
  340. X{
  341. Xint hval = hasher(nam) % ht->hsize;
  342. Xstruct hashnode *hn = ht->nodes[hval];
  343. X    for (; hn; hn = hn->next)
  344. X        if (!strcmp(hn->nam,nam))
  345. X            return hn->dat;
  346. X    return NULL;
  347. X}
  348. Xvoid freehtab(ht,freefunc) /**/
  349. XHashtab ht;FFunc freefunc;
  350. X{
  351. Xint val;
  352. Xstruct hashnode *hn,**hp = &ht->nodes[0],*next;
  353. X    for (val = ht->hsize; val; val--,hp++)
  354. X        for (hn = *hp; hn; )
  355. X            {
  356. X            next = hn->next;
  357. X            freefunc(hn->dat);
  358. X            if (hn->canfree) free(hn->nam);
  359. X            free(hn);
  360. X            hn = next;
  361. X            }
  362. X    free(ht->nodes);
  363. X    free(ht);
  364. X}
  365. X
  366. X/* remove a hash table entry and return a pointer to it */
  367. X
  368. Xvptr remhnode(nam,ht) /**/
  369. Xchar *nam;Hashtab ht;
  370. X{
  371. Xint hval = hasher(nam) % ht->hsize;
  372. Xstruct hashnode *hn = ht->nodes[hval],*hp;
  373. Xvptr dat;
  374. X
  375. X    if (!hn)
  376. X        return NULL;
  377. X    if (!strcmp(hn->nam,nam))
  378. X        {
  379. X        ht->nodes[hval] = hn->next;
  380. X        dat = hn->dat;
  381. X        if (hn->canfree)
  382. X            free(hn->nam);
  383. X        free(hn);
  384. X        ht->ct--;
  385. X        return dat;
  386. X        }
  387. X    for (hp = hn, hn = hn->next; hn; hn = (hp = hn)->next)
  388. X        if (!strcmp(hn->nam,nam))
  389. X            {
  390. X            hp->next = hn->next;
  391. X            dat = hn->dat;
  392. X            if (hn->canfree)
  393. X                free(hn->nam);
  394. X            free(hn);
  395. X            ht->ct--;
  396. X            return dat;
  397. X            }
  398. X    return NULL;
  399. X}
  400. X
  401. X/* insert a node in a linked list after 'llast' */
  402. X
  403. Xvoid insnode(list,llast,dat) /**/
  404. XLklist list;Lknode llast;vptr dat;
  405. X{
  406. XLknode tmp;
  407. X    tmp = llast->next;
  408. X    llast->next = (Lknode) alloc(sizeof *tmp);
  409. X    llast->next->last = llast;
  410. X    llast->next->dat = dat;
  411. X    llast->next->next = tmp;
  412. X    if (tmp)
  413. X        tmp->last = llast->next;
  414. X    else
  415. X        list->last = llast->next;
  416. X}
  417. X
  418. Xvoid addnodeinorder(x,dat) /**/
  419. XLklist x; char *dat;
  420. X{
  421. XLknode y, l = NULL;
  422. X
  423. X    for (y = firstnode(x); y; incnode(y)) {
  424. X        if (forstrcmp((char **) &y->dat, &dat) >= 0) 
  425. X            break;
  426. X        l = y;
  427. X    }
  428. X    if (l == NULL)
  429. X        insnode(x, (Lknode) x, dat);
  430. X    else
  431. X        insnode(x, l, dat);
  432. X}
  433. X
  434. X
  435. X/* remove a node from a linked list */
  436. X
  437. Xvptr remnode(list,nd) /**/
  438. XLklist list;Lknode nd;
  439. X{
  440. Xvptr dat;
  441. X
  442. X    nd->last->next = nd->next;
  443. X    if (nd->next)
  444. X        nd->next->last = nd->last;
  445. X    else
  446. X        list->last = nd->last;
  447. X    free(nd);
  448. X    dat = nd->dat;
  449. X    return dat;
  450. X}
  451. X
  452. X/* remove a node from a linked list */
  453. X
  454. Xvptr uremnode(list,nd) /**/
  455. XLklist list;Lknode nd;
  456. X{
  457. Xvptr dat;
  458. X
  459. X    nd->last->next = nd->next;
  460. X    if (nd->next)
  461. X        nd->next->last = nd->last;
  462. X    else
  463. X        list->last = nd->last;
  464. X    dat = nd->dat;
  465. X    return dat;
  466. X}
  467. X
  468. X/* delete a character in a string */
  469. X
  470. Xvoid chuck(str) /**/
  471. Xchar *str;
  472. X{
  473. X    while (str[0] = str[1])
  474. X        str++;
  475. X}
  476. X
  477. X/* get top node in a linked list */
  478. X
  479. Xvptr getnode(list) /**/
  480. XLklist list;
  481. X{
  482. Xvptr dat;
  483. XLknode node = list->first;
  484. X    if (!node)
  485. X        return NULL;
  486. X    dat = node->dat;
  487. X    list->first = node->next;
  488. X    if (node->next)
  489. X        node->next->last = (Lknode) list;
  490. X    else
  491. X        list->last = (Lknode) list;
  492. X    free(node);
  493. X    return dat;
  494. X}
  495. X
  496. X/* get top node in a linked list without freeing */
  497. X
  498. Xvptr ugetnode(list) /**/
  499. XLklist list;
  500. X{
  501. Xvptr dat;
  502. XLknode node = list->first;
  503. X    if (!node)
  504. X        return NULL;
  505. X    dat = node->dat;
  506. X    list->first = node->next;
  507. X    if (node->next)
  508. X        node->next->last = (Lknode) list;
  509. X    else
  510. X        list->last = (Lknode) list;
  511. X    return dat;
  512. X}
  513. X
  514. Xvoid freetable(tab,freefunc) /**/
  515. XLklist tab;FFunc freefunc;
  516. X{
  517. XLknode node = tab->first,next;
  518. X    while (node)
  519. X        {
  520. X        next = node->next;
  521. X        if (freefunc)
  522. X            freefunc(node->dat);
  523. X        free(node);
  524. X        node = next;
  525. X        }
  526. X    free(tab);
  527. X}
  528. Xchar *ztrstr(s,t) /**/
  529. Xchar *s;char *t;
  530. X{
  531. Xchar *p1,*p2;
  532. X    for (; *s; s++)
  533. X        {
  534. X        for (p1 = s, p2 = t; *p2; p1++,p2++)
  535. X            if (*p1 != *p2)
  536. X                break;
  537. X        if (!*p2)
  538. X             return (char *) s;
  539. X        }
  540. X    return NULL;
  541. X}
  542. X
  543. X/* insert a list in another list */
  544. X
  545. Xvoid inslist(l,where,x) /**/
  546. XLklist l;Lknode where;Lklist x;
  547. X{
  548. XLknode nx = where->next;
  549. X
  550. X    if (!l->first)
  551. X        return;
  552. X    where->next = l->first;
  553. X    l->last->next = nx;
  554. X    l->first->last = where;
  555. X    if (nx)
  556. X        nx->last = l->last;
  557. X    else
  558. X        x->last = l->last;
  559. X}
  560. X
  561. Xint countnodes(x) /**/
  562. XLklist x;
  563. X{
  564. XLknode y;
  565. Xint ct = 0;
  566. X
  567. X    for (y = firstnode(x); y; incnode(y),ct++);
  568. X    return ct;
  569. X}
  570. X
  571. SHAR_EOF
  572. chmod 0644 zsh2.1/src/table.c ||
  573. echo 'restore of zsh2.1/src/table.c failed'
  574. Wc_c="`wc -c < 'zsh2.1/src/table.c'`"
  575. test 6824 -eq "$Wc_c" ||
  576.     echo 'zsh2.1/src/table.c: original size 6824, current size' "$Wc_c"
  577. rm -f _shar_wnt_.tmp
  578. fi
  579. # ============= zsh2.1/src/text.c ==============
  580. if test -f 'zsh2.1/src/text.c' -a X"$1" != X"-c"; then
  581.     echo 'x - skipping zsh2.1/src/text.c (File already exists)'
  582.     rm -f _shar_wnt_.tmp
  583. else
  584. > _shar_wnt_.tmp
  585. echo 'x - extracting zsh2.1/src/text.c (Text)'
  586. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/text.c' &&
  587. X/*
  588. X
  589. X    text.c - textual representations of syntax trees
  590. X
  591. X    This file is part of zsh, the Z shell.
  592. X
  593. X    zsh is free software; no one can prevent you from reading the source
  594. X   code, or giving it to someone else.
  595. X
  596. X   This file is copyrighted under the GNU General Public License, which
  597. X   can be found in the file called COPYING.
  598. X
  599. X   Copyright (C) 1990, 1991 Paul Falstad
  600. X
  601. X   zsh is distributed in the hope that it will be useful, but
  602. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  603. X   responsibility to anyone for the consequences of using it or for
  604. X   whether it serves any particular purpose or works at all, unless he
  605. X   says so in writing.  Refer to the GNU General Public License
  606. X   for full details.
  607. X
  608. X   Everyone is granted permission to copy, modify and redistribute
  609. X   zsh, but only under the conditions described in the GNU General Public
  610. X   License.   A copy of this license is supposed to have been given to you
  611. X   along with zsh so you can know your rights and responsibilities.
  612. X   It should be in a file named COPYING.
  613. X
  614. X   Among other things, the copyright notice and this notice must be
  615. X   preserved on all copies.
  616. X
  617. X*/
  618. X
  619. X#include "zsh.h"
  620. X
  621. Xstatic char *tptr,*tbuf,*tlim;
  622. Xstatic int tsiz,tindent,tnewlins;
  623. X
  624. X/* add a character to the text buffer */
  625. X
  626. Xvoid taddchr(c) /**/
  627. Xint c;
  628. X{
  629. X    *tptr++ = c;
  630. X    if (tptr == tlim)
  631. X        {
  632. X        tbuf = realloc(tbuf,tsiz *= 2);
  633. X        tlim = tbuf+tsiz;
  634. X        tptr = tbuf+tsiz/2;
  635. X        }
  636. X}
  637. X
  638. X/* add a string to the text buffer */
  639. X
  640. Xvoid taddstr(s) /**/
  641. Xchar *s;
  642. X{
  643. Xint sl = strlen(s);
  644. X
  645. X    while (tptr+sl >= tlim)
  646. X        {
  647. X        int x = tptr-tbuf;
  648. X
  649. X        tbuf = realloc(tbuf,tsiz *= 2);
  650. X        tlim = tbuf+tsiz;
  651. X        tptr = tbuf+x;
  652. X        }
  653. X    strcpy(tptr,s);
  654. X    tptr += sl;
  655. X}
  656. X
  657. X/* add an integer to the text buffer */
  658. X
  659. Xvoid taddint(x) /**/
  660. Xint x;
  661. X{
  662. Xchar buf[10];
  663. X
  664. X    sprintf(buf,"%d",x);
  665. X    taddstr(buf);
  666. X}
  667. X
  668. X/* add a newline, or something equivalent, to the text buffer */
  669. X
  670. Xvoid taddnl() /**/
  671. X{
  672. Xint t0;
  673. X
  674. X    if (tnewlins)
  675. X        {
  676. X        taddchr('\n');
  677. X        for (t0 = 0; t0 != tindent; t0++)
  678. X            taddchr('\t');
  679. X        }
  680. X    else
  681. X        taddstr("; ");
  682. X}
  683. X
  684. X/* get a textual representation of n */
  685. X
  686. Xchar *gettext(n,nls) /**/
  687. Xstruct node *n;int nls;
  688. X{
  689. X    tnewlins = nls;
  690. X    tbuf = zalloc(tsiz = 32);
  691. X    tptr = tbuf;
  692. X    tlim = tbuf+tsiz;
  693. X    tindent = 1;
  694. X    gettext2(n);
  695. X    *tptr = '\0';
  696. X    untokenize(tbuf);
  697. X    return tbuf;
  698. X}
  699. X
  700. X#define gt2(X) gettext2((struct node *) (X))
  701. X
  702. X/*
  703. X    "gettext2" or "type checking and how to avoid it"
  704. X    an epic function by Paul Falstad
  705. X*/
  706. X
  707. X#define _Cond(X) ((Cond) (X))
  708. X#define _Cmd(X) ((Cmd) (X))
  709. X#define _Pline(X) ((Pline) (X))
  710. X#define _Sublist(X) ((Sublist) (X))
  711. X#define _List(X) ((List) (X))
  712. X#define _casecmd(X) ((struct casecmd *) (X))
  713. X#define _ifcmd(X) ((struct ifcmd *) (X))
  714. X#define _whilecmd(X) ((struct whilecmd *) (X))
  715. X
  716. Xvoid gettext2(n) /**/
  717. Xstruct node *n;
  718. X{
  719. XCmd nn;
  720. XCond nm;
  721. X
  722. X    if (!n)
  723. X        return;
  724. X    switch (n->type)
  725. X        {
  726. X        case N_LIST:
  727. X            gt2(_List(n)->left);
  728. X            if (_List(n)->type == ASYNC)
  729. X                taddstr(" &");
  730. X            simplifyright(_List(n));
  731. X            if (_List(n)->right)
  732. X                {
  733. X                if (tnewlins)
  734. X                    taddnl();
  735. X                else
  736. X                    taddstr((_List(n)->type == ASYNC) ? " " : "; ");
  737. X                gt2(_List(n)->right);
  738. X                }
  739. X            break;
  740. X        case N_SUBLIST:
  741. X            if (_Sublist(n)->flags & PFLAG_NOT)
  742. X                taddstr("! ");
  743. X            if (_Sublist(n)->flags & PFLAG_COPROC)
  744. X                taddstr("coproc ");
  745. X            gt2(_Sublist(n)->left);
  746. X            if (_Sublist(n)->right)
  747. X                {
  748. X                taddstr((_Sublist(n)->type == ORNEXT) ? " || " : " && ");
  749. X                gt2(_Sublist(n)->right);
  750. X                }
  751. X            break;
  752. X        case N_PLINE:
  753. X            gt2(_Pline(n)->left);
  754. X            if (_Pline(n)->type == PIPE)
  755. X                {
  756. X                taddstr(" | ");
  757. X                gt2(_Pline(n)->right);
  758. X                }
  759. X            break;
  760. X        case N_CMD:
  761. X            nn = _Cmd(n);
  762. X            if (nn->flags & CFLAG_EXEC)
  763. X                taddstr("exec ");
  764. X            if (nn->flags & CFLAG_COMMAND)
  765. X                taddstr("command ");
  766. X            switch (nn->type)
  767. X                {
  768. X                case SIMPLE:
  769. X                    getsimptext(nn);
  770. X                    break;
  771. X                case SUBSH:
  772. X                    taddstr("( ");
  773. X                    tindent++;
  774. X                    gt2(nn->u.list);
  775. X                    tindent--;
  776. X                    taddstr(" )");
  777. X                    break;
  778. X                case ZCTIME:
  779. X                    taddstr("time ");
  780. X                    tindent++;
  781. X                    gt2(nn->u.pline);
  782. X                    tindent--;
  783. X                    break;
  784. X                case FUNCDEF:
  785. X                    taddlist(nn->args);
  786. X                    taddstr(" () {");
  787. X                    tindent++;
  788. X                    taddnl();
  789. X                    gt2(nn->u.list);
  790. X                    tindent--;
  791. X                    taddnl();
  792. X                    taddstr("}");
  793. X                    break;
  794. X                case CURSH:
  795. X                    taddstr("{ ");
  796. X                    tindent++;
  797. X                    gt2(nn->u.list);
  798. X                    tindent--;
  799. X                    taddstr(" }");
  800. X                    break;
  801. X                case CFOR:
  802. X                case CSELECT:
  803. X                    taddstr((nn->type == CFOR) ? "for " : "select ");
  804. X                    taddstr(nn->u.forcmd->name);
  805. X                    if (nn->u.forcmd->inflag)
  806. X                        {
  807. X                        taddstr(" in ");
  808. X                        taddlist(nn->args);
  809. X                        }
  810. X                    taddnl();
  811. X                    taddstr("do");
  812. X                    tindent++;
  813. X                    taddnl();
  814. X                    gt2(nn->u.forcmd->list);
  815. X                    taddnl();
  816. X                    tindent--;
  817. X                    taddstr("done");
  818. X                    break;
  819. X                case CIF:
  820. X                    gt2(nn->u.ifcmd);
  821. X                    taddstr("fi");
  822. X                    break;
  823. X                case CCASE:
  824. X                    taddstr("case ");
  825. X                    taddlist(nn->args);
  826. X                    taddstr(" in");
  827. X                    tindent++;
  828. X                    taddnl();
  829. X                    gt2(nn->u.casecmd);
  830. X                    tindent--;
  831. X                    if (tnewlins)
  832. X                        taddnl();
  833. X                    else
  834. X                        taddchr(' ');
  835. X                    taddstr("esac");
  836. X                    break;
  837. X                case COND:
  838. X                    taddstr("[[ ");
  839. X                    gt2(nn->u.cond);
  840. X                    taddstr(" ]]");
  841. X                    break;
  842. X                case CREPEAT:
  843. X                    taddstr("repeat ");
  844. X                    taddlist(nn->args);
  845. X                    taddnl();
  846. X                    taddstr("do");
  847. X                    tindent++;
  848. X                    taddnl();
  849. X                    gt2(nn->u.list);
  850. X                    tindent--;
  851. X                    taddnl();
  852. X                    taddstr("done");
  853. X                    break;
  854. X                case CWHILE:
  855. X                    gt2(nn->u.whilecmd);
  856. X                    break;
  857. X                }
  858. X            getredirs(nn);
  859. X            break;
  860. X        case N_COND:
  861. X            nm = _Cond(n);
  862. X            switch (nm->type)
  863. X                {
  864. X                case COND_NOT:
  865. X                    taddstr("! ");
  866. X                    gt2(nm->left);
  867. X                    break;
  868. X                case COND_AND:
  869. X                    taddstr("( ");
  870. X                    gt2(nm->left);
  871. X                    taddstr(" && ");
  872. X                    gt2(nm->right);
  873. X                    taddstr(" )");
  874. X                    break;
  875. X                case COND_OR:
  876. X                    taddstr("( ");
  877. X                    gt2(nm->left);
  878. X                    taddstr(" || ");
  879. X                    gt2(nm->right);
  880. X                    taddstr(" )");
  881. X                    break;
  882. X                default:
  883. X                    {
  884. X                    static char *c1[] = {
  885. X                        " = "," != "," < "," > "," -nt "," -ot "," -ef "," -eq ",
  886. X                        " -ne "," -lt "," -gt "," -le "," -ge "
  887. X                        };
  888. X                    if (nm->right)
  889. X                        taddstr(nm->left);
  890. X                    if (nm->type <= COND_GE)
  891. X                        taddstr(c1[nm->type-COND_STREQ]);
  892. X                    else
  893. X                        {
  894. X                        char c2[5];
  895. X                        c2[0] = ' '; c2[1] = '-';
  896. X                        c2[2] = nm->type;
  897. X                        c2[3] = ' '; c2[4] = '\0';
  898. X                        taddstr(c2);
  899. X                        }
  900. X                    taddstr((nm->right) ? nm->right : nm->left);
  901. X                    }
  902. X                    break;
  903. X                }
  904. X            break;
  905. X        case N_CASE:
  906. X            taddstr(_casecmd(n)->pat);
  907. X            taddstr(") ");
  908. X            tindent++;
  909. X            gt2(_casecmd(n)->list);
  910. X            tindent--;
  911. X            taddstr(";;");
  912. X            if (tnewlins)
  913. X                taddnl();
  914. X            else
  915. X                taddchr(' ');
  916. X            gt2(_casecmd(n)->next);
  917. X            break;
  918. X        case N_IF:
  919. X            if (_ifcmd(n)->ifl)
  920. X                {
  921. X                taddstr("if ");
  922. X                tindent++;
  923. X                gt2(_ifcmd(n)->ifl);
  924. X                tindent--;
  925. X                taddnl();
  926. X                taddstr("then");
  927. X                }
  928. X            else
  929. X                taddchr('e');
  930. X            tindent++;
  931. X            taddnl();
  932. X            gt2(_ifcmd(n)->thenl);
  933. X            tindent--;
  934. X            taddnl();
  935. X            if (_ifcmd(n)->next)
  936. X                {
  937. X                taddstr("els");
  938. X                gt2(_ifcmd(n)->next);
  939. X                }
  940. X            break;
  941. X        case N_WHILE:
  942. X            taddstr((_whilecmd(n)->cond) ? "until " : "while ");
  943. X            tindent++;
  944. X            gt2(_whilecmd(n)->cont);
  945. X            tindent--;
  946. X            taddnl();
  947. X            taddstr("do");
  948. X            tindent++;
  949. X            taddnl();
  950. X            gt2(_whilecmd(n)->loop);
  951. X            tindent--;
  952. X            taddnl();
  953. X            taddstr("done");
  954. X            break;
  955. X        }
  956. X}
  957. X
  958. Xvoid getsimptext(cmd) /**/
  959. XCmd cmd;
  960. X{
  961. XLknode n;
  962. X
  963. X    for (n = firstnode(cmd->vars); n; incnode(n))
  964. X        {
  965. X        struct varasg *v = getdata(n);
  966. X
  967. X        taddstr(v->name);
  968. X        taddchr('=');
  969. X        if ((v->type & PMTYPE) == PMFLAG_A)
  970. X            {
  971. X            taddchr('(');
  972. X            taddlist(v->arr);
  973. X            taddstr(") ");
  974. X            }
  975. X        else
  976. X            {
  977. X            taddstr(v->str);
  978. X            taddchr(' ');
  979. X            }
  980. X        }
  981. X    taddlist(cmd->args);
  982. X}
  983. X
  984. Xvoid getredirs(cmd) /**/
  985. XCmd cmd;
  986. X{
  987. XLknode n;
  988. Xstatic char *fstr[] = {
  989. X    ">",">!",">>",">>!",">&",">&!",">>&",">>&!","<","<<","<&",">&",">&-",
  990. X    ">&-","..","..","<<<"
  991. X    };
  992. X
  993. X    taddchr(' ');
  994. X    for (n = firstnode(cmd->redir); n; incnode(n))
  995. X        {
  996. X        struct redir *f = getdata(n);
  997. X
  998. X        switch(f->type)
  999. X            {
  1000. X            case WRITE: case WRITENOW: case APP: case APPNOW: case READ:
  1001. X            case HERESTR:
  1002. X                if (f->fd1 != ((f->type == READ) ? 0 : 1))
  1003. X                    taddchr('0'+f->fd1);
  1004. X                taddstr(fstr[f->type]);
  1005. X                taddchr(' ');
  1006. X                taddstr(f->name);
  1007. X                taddchr(' ');
  1008. X                break;
  1009. X            case MERGE: case MERGEOUT:
  1010. X                if (f->fd1 != ((f->type == MERGEOUT) ? 1 : 0))
  1011. X                    taddchr('0'+f->fd1);
  1012. X                taddstr(fstr[f->type]);
  1013. X                taddchr(' ');
  1014. X                taddint(f->fd2);
  1015. X                taddchr(' ');
  1016. X                break;
  1017. X            case CLOSE:
  1018. X                taddchr(f->fd1+'0');
  1019. X                taddstr(">&- ");
  1020. X                break;
  1021. X            case INPIPE:
  1022. X            case OUTPIPE:
  1023. X                if (f->fd1 != ((f->type == INPIPE) ? 0 : 1))
  1024. X                    taddchr('0'+f->fd1);
  1025. X                taddstr((f->type == INPIPE) ? "< " : "> ");
  1026. X                taddstr(f->name);
  1027. X                taddchr(' ');
  1028. X                break;
  1029. X            }
  1030. X        }
  1031. X    tptr--;
  1032. X}
  1033. X
  1034. Xvoid taddlist(l) /**/
  1035. XLklist l;
  1036. X{
  1037. XLknode n;
  1038. X
  1039. X    for (n = firstnode(l); n; incnode(n))
  1040. X        {
  1041. X        taddstr(getdata(n));
  1042. X        taddchr(' ');
  1043. X        }
  1044. X    tptr--;
  1045. X}
  1046. SHAR_EOF
  1047. chmod 0644 zsh2.1/src/text.c ||
  1048. echo 'restore of zsh2.1/src/text.c failed'
  1049. Wc_c="`wc -c < 'zsh2.1/src/text.c'`"
  1050. test 8703 -eq "$Wc_c" ||
  1051.     echo 'zsh2.1/src/text.c: original size 8703, current size' "$Wc_c"
  1052. rm -f _shar_wnt_.tmp
  1053. fi
  1054. # ============= zsh2.1/src/utils.c ==============
  1055. if test -f 'zsh2.1/src/utils.c' -a X"$1" != X"-c"; then
  1056.     echo 'x - skipping zsh2.1/src/utils.c (File already exists)'
  1057.     rm -f _shar_wnt_.tmp
  1058. else
  1059. > _shar_wnt_.tmp
  1060. echo 'x - extracting zsh2.1/src/utils.c (Text)'
  1061. sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/utils.c' &&
  1062. X/*
  1063. X
  1064. X    utils.c - miscellaneous utilities
  1065. X
  1066. X    This file is part of zsh, the Z shell.
  1067. X
  1068. X   zsh is free software; no one can prevent you from reading the source
  1069. X   code, or giving it to someone else.
  1070. X   This file is copyrighted under the GNU General Public License, which
  1071. X   can be found in the file called COPYING.
  1072. X
  1073. X   Copyright (C) 1990, 1991 Paul Falstad
  1074. X
  1075. X   zsh is distributed in the hope that it will be useful, but
  1076. X   WITHOUT ANY WARRANTY.  No author or distributor accepts
  1077. X   responsibility to anyone for the consequences of using it or for
  1078. X   whether it serves any particular purpose or works at all, unless he
  1079. X   says so in writing.  Refer to the GNU General Public License
  1080. X   for full details.
  1081. X
  1082. X   Everyone is granted permission to copy, modify and redistribute
  1083. X   zsh, but only under the conditions described in the GNU General Public
  1084. X   License.   A copy of this license is supposed to have been given to you
  1085. X   along with zsh so you can know your rights and responsibilities.
  1086. X   It should be in a file named COPYING.
  1087. X
  1088. X   Among other things, the copyright notice and this notice must be
  1089. X   preserved on all copies.
  1090. X
  1091. X*/
  1092. X
  1093. X#include "zsh.h"
  1094. X#include <pwd.h>
  1095. X#include <errno.h>
  1096. X#ifdef __hpux
  1097. X#include <ndir.h>
  1098. X#else
  1099. X#ifndef SYSV
  1100. X#include <sys/dir.h>
  1101. X#endif
  1102. X#endif
  1103. X#include <fcntl.h>
  1104. X
  1105. X#ifdef SYSV
  1106. X#define direct dirent
  1107. X#undef TIOCGWINSZ
  1108. Xint readlink(s,t,z)
  1109. Xchar *s;char *t;int z;
  1110. X{
  1111. Xreturn -1;
  1112. X}
  1113. X#endif
  1114. X
  1115. X/* source a file */
  1116. X
  1117. Xint source(s) /**/
  1118. Xchar *s;
  1119. X{
  1120. Xint fd,cj = thisjob;
  1121. Xint oldlineno = lineno,oldshst;
  1122. XFILE *obshin = bshin;
  1123. X
  1124. X    fd = SHIN;
  1125. X    lineno = 0;
  1126. X    oldshst = opts[SHINSTDIN];
  1127. X    opts[SHINSTDIN] = OPT_UNSET;
  1128. X    if ((SHIN = movefd(open(s,O_RDONLY))) == -1)
  1129. X        {
  1130. X        SHIN = fd;
  1131. X        thisjob = cj;
  1132. X        opts[SHINSTDIN] = oldshst;
  1133. X        return 1;
  1134. X        }
  1135. X    bshin = fdopen(SHIN,"r");
  1136. X    loop();
  1137. X    fclose(bshin);
  1138. X    bshin = obshin;
  1139. X    opts[SHINSTDIN] = oldshst;
  1140. X    SHIN = fd;
  1141. X    thisjob = cj;
  1142. X    errflag = 0;
  1143. X    retflag = 0;
  1144. X    lineno = oldlineno;
  1145. X    return 0;
  1146. X}
  1147. X
  1148. X/* try to source a file in the home directory */
  1149. X
  1150. Xvoid sourcehome(s) /**/
  1151. Xchar *s;
  1152. X{
  1153. Xchar buf[MAXPATHLEN];
  1154. Xchar *h;
  1155. X
  1156. X    if (!(h = getsparam("ZDOTDIR")))
  1157. X        h = home;
  1158. X    sprintf(buf,"%s/%s",h,s);
  1159. X    (void) source(buf);
  1160. X}
  1161. X
  1162. X/* print an error */
  1163. X
  1164. Xvoid zerrnam(cmd,fmt,str,num) /**/
  1165. Xchar *cmd; char *fmt; char *str;int num;
  1166. X{
  1167. X    if (cmd)
  1168. X        {
  1169. X        if (errflag || noerrs)
  1170. X            return;
  1171. X        errflag = 1;
  1172. X        trashzle();
  1173. X        if (isset(SHINSTDIN))
  1174. X            fprintf(stderr,"%s: ",cmd);
  1175. X        else
  1176. X            fprintf(stderr,"%s: %s: ",argzero,cmd);
  1177. X        }
  1178. X    while (*fmt)
  1179. X        if (*fmt == '%')
  1180. X            {
  1181. X            fmt++;
  1182. X            switch(*fmt++)
  1183. X                {
  1184. X                case 's':
  1185. X                    while (*str)
  1186. X                        niceputc(*str++,stderr);
  1187. X                    break;
  1188. X                case 'l':
  1189. X                    while (num--)
  1190. X                        niceputc(*str++,stderr);
  1191. X                    break;
  1192. X                case 'd':
  1193. X                    fprintf(stderr,"%d",num);
  1194. X                    break;
  1195. X                case '%':
  1196. X                    putc('%',stderr);
  1197. X                    break;
  1198. X                case 'c':
  1199. X                    niceputc(num,stderr);
  1200. X                    break;
  1201. X                case 'e':
  1202. X                    if (num == EINTR)
  1203. X                        {
  1204. X                        fputs("interrupt\n",stderr);
  1205. X                        errflag = 1;
  1206. X                        return;
  1207. X                        }
  1208. X                    if (num == EIO)
  1209. X                        fputs(sys_errlist[num],stderr);
  1210. X                    else
  1211. X                        {
  1212. X                        fputc(tulower(sys_errlist[num][0]),stderr);
  1213. X                        fputs(sys_errlist[num]+1,stderr);
  1214. X                        }
  1215. X                    break;
  1216. X                }
  1217. X            }
  1218. X        else
  1219. X            putc(*fmt++,stderr);
  1220. X    if (unset(SHINSTDIN) && lineno)
  1221. X        fprintf(stderr," [%ld]\n",lineno);
  1222. X    else
  1223. X        putc('\n',stderr);
  1224. X    fflush(stderr);
  1225. X}
  1226. X
  1227. Xvoid zerr(fmt,str,num) /**/
  1228. Xchar *fmt; char *str;int num;
  1229. X{
  1230. X    if (errflag || noerrs)
  1231. X        return;
  1232. X    errflag = 1;
  1233. X    trashzle();
  1234. X    fprintf(stderr,"%s: ",(isset(SHINSTDIN)) ? "zsh" : argzero);
  1235. X    zerrnam(NULL,fmt,str,num);
  1236. X}
  1237. X
  1238. Xvoid niceputc(c,f) /**/
  1239. Xint c;FILE *f;
  1240. X{
  1241. X    if (itok(c))
  1242. X        {
  1243. X        if (c >= Pound && c <= Comma)
  1244. X            putc(ztokens[c-Pound],f);
  1245. X        return;
  1246. X        }
  1247. X    c &= 0x7f;
  1248. X    if (c >= ' ' && c < 0x7f)
  1249. X        putc(c,f);
  1250. X    else if (c == '\n')
  1251. X        {
  1252. X        putc('\\',f);
  1253. X        putc('n',f);
  1254. X        }
  1255. X    else
  1256. X        {
  1257. X        putc('^',f);
  1258. X        putc(c|'@',f);
  1259. X        }
  1260. X}
  1261. X
  1262. X/* enable ^C interrupts */
  1263. X
  1264. Xvoid intr() /**/
  1265. X{
  1266. X#ifdef SV_INTERRUPT
  1267. Xstatic struct sigvec vec = { handler,sigmask(SIGINT),SV_INTERRUPT };
  1268. X
  1269. X    if (interact)
  1270. X        sigvec(SIGINT,&vec,NULL);
  1271. X#else
  1272. X    if (interact)
  1273. X        signal(SIGINT,handler);
  1274. X#endif
  1275. X}
  1276. X
  1277. Xvoid noholdintr() /**/
  1278. X{
  1279. X    intr();
  1280. X}
  1281. X
  1282. Xvoid holdintr() /**/
  1283. X{
  1284. X#ifdef SV_INTERRUPT
  1285. Xstatic struct sigvec vec = { handler,sigmask(SIGINT),0 };
  1286. X
  1287. X    if (interact) sigvec(SIGINT,&vec,NULL);
  1288. X#else
  1289. X    if (interact) signal(SIGINT,SIG_IGN);
  1290. X#endif
  1291. X}
  1292. X
  1293. Xchar *fgetline(buf,len,in) /**/
  1294. Xchar *buf;int len;FILE *in;
  1295. X{
  1296. X    if (!fgets(buf,len,in))
  1297. X        return NULL;
  1298. X    buf[len] = '\0';
  1299. X    buf[strlen(buf)-1] = '\0';
  1300. X    return buf;
  1301. X}
  1302. X
  1303. X/* get a symlink-free pathname for s relative to PWD */
  1304. X
  1305. Xchar *findcwd(s) /**/
  1306. Xchar *s;
  1307. X{
  1308. Xchar *t;
  1309. X
  1310. X    if (*s == '/')
  1311. X        return xsymlink(s);
  1312. X    s = tricat((cwd[1]) ? cwd : "","/",s);
  1313. X    t = xsymlink(s);
  1314. X    free(s);
  1315. X    return t;
  1316. X}
  1317. X
  1318. Xstatic char xbuf[MAXPATHLEN];
  1319. X
  1320. X/* get rid of this */
  1321. Xchar *fixcwd(s) /**/
  1322. Xchar *s;
  1323. X{
  1324. Xstruct stat sbuf,tbuf;
  1325. Xchar *t;
  1326. X
  1327. X    strcpy(xbuf,"");
  1328. X    if (*s == '/')
  1329. X        t = ztrdup(s);
  1330. X    else
  1331. X        t = tricat((cwd[1]) ? cwd : "","/",s);
  1332. X    (void) xsymlinks(t+1,0); 
  1333. X    free(t);
  1334. X    if (!*xbuf)
  1335. X        strcpy(xbuf,"/");
  1336. X    if (stat(xbuf,&sbuf) == 0 && stat(".",&tbuf) == 0)
  1337. X        if (!(sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino))
  1338. X            chdir(xbuf);
  1339. X    return ztrdup(xbuf);
  1340. X}
  1341. X
  1342. Xint ispwd(s) /**/
  1343. Xchar *s;
  1344. X{
  1345. Xstruct stat sbuf,tbuf;
  1346. X
  1347. X    if (stat(s,&sbuf) == 0 && stat(".",&tbuf) == 0)
  1348. X        if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino)
  1349. X            return 1;
  1350. X    return 0;
  1351. X}
  1352. X
  1353. X/* expand symlinks in s, and remove other weird things */
  1354. X
  1355. Xchar *xsymlink(s) /**/
  1356. Xchar *s;
  1357. X{
  1358. X    if (unset(CHASELINKS))
  1359. X        return ztrdup(s);
  1360. X    if (*s != '/')
  1361. X        return NULL;
  1362. X    strcpy(xbuf,"");
  1363. X    if (xsymlinks(s+1,1))
  1364. X        return ztrdup(s);
  1365. X    if (!*xbuf)
  1366. X        return ztrdup("/");
  1367. X    return ztrdup(xbuf);
  1368. X}
  1369. X
  1370. Xchar **slashsplit(s) /**/
  1371. Xchar *s;
  1372. X{
  1373. Xchar *t,**r,**q;
  1374. Xint t0;
  1375. X
  1376. X    if (!*s)
  1377. X        return (char **) zcalloc(sizeof(char **));
  1378. X    for (t = s, t0 = 0; *t; t++)
  1379. X        if (*t == '/')
  1380. X            t0++;
  1381. X    q  = r = (char **) zalloc(sizeof(char **)*(t0+2));
  1382. X    while (t = strchr(s,'/'))
  1383. X        {
  1384. X        *t = '\0';
  1385. X        *q++ = ztrdup(s);
  1386. X        *t = '/';
  1387. X        while (*t == '/')
  1388. X            t++;
  1389. X        if (!*t)
  1390. X            {
  1391. X            *q = NULL;
  1392. X            return r;
  1393. X            }
  1394. X        s = t;
  1395. X        }
  1396. X    *q++ = ztrdup(s);
  1397. X    *q = NULL;
  1398. X    return r;
  1399. X}
  1400. X
  1401. Xint islink(s) /**/
  1402. Xchar *s;
  1403. X{
  1404. X    return readlink(s,NULL,0) == 0;
  1405. X}
  1406. X
  1407. X/* expands symlinks and .. or . expressions */
  1408. X/* if flag = 0, only expand .. and . expressions */
  1409. X
  1410. Xint xsymlinks(s,flag) /**/
  1411. Xchar *s;int flag;
  1412. X{
  1413. Xchar **pp,**opp;
  1414. Xchar xbuf2[MAXPATHLEN],xbuf3[MAXPATHLEN];
  1415. Xint t0;
  1416. X
  1417. X    opp = pp = slashsplit(s);
  1418. X    for (; *pp; pp++)
  1419. X        {
  1420. X        if (!strcmp(*pp,"."))
  1421. X            {
  1422. X            free(*pp);
  1423. X            continue;
  1424. X            }
  1425. X        if (!strcmp(*pp,".."))
  1426. X            {
  1427. X            char *p;
  1428. X
  1429. X            free(*pp);
  1430. X            if (!strcmp(xbuf,"/"))
  1431. X                continue;
  1432. X            p = xbuf+strlen(xbuf);
  1433. X            while (*--p != '/');
  1434. X            *p = '\0';
  1435. X            continue;
  1436. X            }
  1437. X        if (unset(CHASELINKS))
  1438. X            {
  1439. X            strcat(xbuf,"/");
  1440. X            strcat(xbuf,*pp);
  1441. X            free(*pp);
  1442. X            continue;
  1443. X            }
  1444. X        sprintf(xbuf2,"%s/%s",xbuf,*pp);
  1445. X        t0 = readlink(xbuf2,xbuf3,MAXPATHLEN);
  1446. X        if (t0 == -1 || !flag)
  1447. X            {
  1448. X            strcat(xbuf,"/");
  1449. X            strcat(xbuf,*pp);
  1450. X            free(*pp);
  1451. X            }
  1452. X        else
  1453. X            {
  1454. X            xbuf3[t0] = '\0'; /* STUPID */
  1455. X            if (*xbuf3 == '/')
  1456. X                {
  1457. X                strcpy(xbuf,"");
  1458. X                if (xsymlinks(xbuf3+1,flag))
  1459. X                    return 1;
  1460. X                }
  1461. X            else
  1462. X                if (xsymlinks(xbuf3,flag))
  1463. X                    return 1;
  1464. X            free(*pp);
  1465. X            }
  1466. X        }
  1467. X    free(opp);
  1468. X    return 0;
  1469. X}
  1470. X
  1471. X/* print a directory */
  1472. X
  1473. Xvoid printdir(s) /**/
  1474. Xchar *s;
  1475. X{
  1476. Xint t0;
  1477. X
  1478. X    t0 = finddir(s);
  1479. X    if (t0 == -1)
  1480. X        {
  1481. X        if (!strncmp(s,home,t0 = strlen(home)) && t0 > 1)
  1482. X            {
  1483. X            putchar('~');
  1484. X            fputs(s+t0,stdout);
  1485. X            }
  1486. X        else
  1487. X            fputs(s,stdout);
  1488. X        }
  1489. X    else
  1490. X        {
  1491. X        putchar('~');
  1492. X        fputs(usernames[t0],stdout);
  1493. X        fputs(s+strlen(userdirs[t0]),stdout);
  1494. X        }
  1495. X}
  1496. X
  1497. X/* see if a path has a named directory as its prefix */
  1498. X
  1499. Xint finddir(s) /**/
  1500. Xchar *s;
  1501. X{
  1502. Xint t0,t1,step;
  1503. X
  1504. X    if (userdirsz)
  1505. X        {
  1506. X        step = t0 = userdirsz/2;
  1507. X        for(;;)
  1508. X            {
  1509. X            t1 = (userdirs[t0]) ? dircmp(userdirs[t0],s) : 1;
  1510. X            if (!t1)
  1511. X                {
  1512. X                while (t0 != userdirsz-1 && userdirs[t0+1] && 
  1513. X                        !dircmp(userdirs[t0+1],s)) 
  1514. X                    t0++;
  1515. X                return t0;
  1516. X                }
  1517. X            if (!step)
  1518. X                break;
  1519. X            if (t1 > 0)
  1520. X                t0 = t0-step+step/2;
  1521. X            else
  1522. X                t0 += step/2;
  1523. X            step /= 2;
  1524. X            }
  1525. X        }
  1526. X    return -1;
  1527. X}
  1528. X
  1529. X/* add a named directory */
  1530. X
  1531. Xvoid adduserdir(s,t) /**/
  1532. Xchar *s;char *t;
  1533. X{
  1534. Xint t0,t1;
  1535. X
  1536. X    if (!interact || ((t0 = finddir(t)) != -1 && !strcmp(s,usernames[t0])))
  1537. X        return;
  1538. X    if (!strcmp(t,"/"))
  1539. X        return;
  1540. X    if ((t0 = finddir(t)) != -1 && !strcmp(s,usernames[t0]))
  1541. X        return;
  1542. X    if (userdirsz == userdirct)
  1543. X        {
  1544. X        userdirsz *= 2;
  1545. X        userdirs = (char **) realloc((char *) userdirs,
  1546. X            sizeof(char **)*userdirsz);
  1547. X        usernames = (char **) realloc((char *) usernames,
  1548. X            sizeof(char **)*userdirsz);
  1549. X        for (t0 = userdirct; t0 != userdirsz; t0++)
  1550. X            userdirs[t0] = usernames[t0] = NULL;
  1551. X        }
  1552. X    for (t0 = 0; t0 != userdirct; t0++)
  1553. X        if (strcmp(userdirs[t0],t) > 0)
  1554. X            break;
  1555. X    for (t1 = userdirct-1; t1 >= t0; t1--)
  1556. X        {
  1557. X        userdirs[t1+1] = userdirs[t1];
  1558. X        usernames[t1+1] = usernames[t1];
  1559. X        }
  1560. X    userdirs[t0] = ztrdup(t);
  1561. X    usernames[t0] = ztrdup(s);
  1562. X    userdirct++;
  1563. X}
  1564. X
  1565. Xint dircmp(s,t) /**/
  1566. Xchar *s;char *t;
  1567. X{
  1568. X    for (; *s && *t; s++,t++)
  1569. X        if (*s != *t)
  1570. X            return *s-*t;
  1571. X    if (!*s && (!*t || *t == '/'))
  1572. X        return 0;
  1573. X    return *s-*t;
  1574. X}
  1575. X
  1576. Xint ddifftime(t1,t2) /**/
  1577. Xtime_t t1;time_t t2;
  1578. X{
  1579. X    return ((long) t2-(long) t1);
  1580. X}
  1581. X
  1582. X/* see if jobs need printing */
  1583. X
  1584. Xvoid scanjobs() /**/
  1585. X{
  1586. Xint t0;
  1587. X
  1588. X    for (t0 = 1; t0 != MAXJOB; t0++)
  1589. X        if (jobtab[t0].stat & STAT_CHANGED)
  1590. X            printjob(jobtab+t0,0);
  1591. X}
  1592. X
  1593. X/* do pre-prompt stuff */
  1594. X
  1595. Xvoid preprompt() /**/
  1596. X{
  1597. Xint diff;
  1598. XList list;
  1599. Xstruct schedcmd *sch,*schl;
  1600. X
  1601. X    if (unset(NOTIFY))
  1602. X        scanjobs();
  1603. X    if (errflag)
  1604. X        return;
  1605. X    if (list = getshfunc("precmd"))
  1606. X        newrunlist(list);
  1607. X    if (errflag)
  1608. X        return;
  1609. X    if (period && (time(NULL) > lastperiod+period) &&
  1610. X            (list = getshfunc("periodic")))
  1611. X        {
  1612. X        newrunlist(list);
  1613. X        lastperiod = time(NULL);
  1614. X        }
  1615. X    if (errflag)
  1616. X        return;
  1617. X    if (watch)
  1618. X        {
  1619. X        diff = (int) ddifftime(lastwatch,time(NULL));
  1620. X        if (diff > logcheck)
  1621. X            {
  1622. X            dowatch();
  1623. X            lastwatch = time(NULL);
  1624. X            }
  1625. X        }
  1626. X    if (errflag)
  1627. X        return;
  1628. X    diff = (int) ddifftime(lastmailcheck,time(NULL));
  1629. X    if (diff > mailcheck)
  1630. X        {
  1631. X        if (mailpath && *mailpath)
  1632. X            checkmailpath(mailpath);
  1633. X        else if (mailfile)
  1634. X            {
  1635. X            char *x[2];
  1636. X
  1637. X            x[0] = mailfile;
  1638. X            x[1] = NULL;
  1639. X            checkmailpath(x);
  1640. X            }
  1641. X        lastmailcheck = time(NULL);
  1642. X        }
  1643. X    for (schl = (struct schedcmd *) &schedcmds, sch = schedcmds; sch;
  1644. X            sch = (schl = sch)->next)
  1645. X        {
  1646. X        if (sch->time < time(NULL))
  1647. X            {
  1648. X            execstring(sch->cmd);
  1649. X            schl->next = sch->next;
  1650. X            free(sch->cmd);
  1651. X            free(sch);
  1652. X            }
  1653. X        if (errflag)
  1654. X            return;
  1655. X        }
  1656. X}
  1657. X
  1658. Xint arrlen(s) /**/
  1659. Xchar **s;
  1660. X{
  1661. Xint t0;
  1662. X
  1663. X    for (t0 = 0; *s; s++,t0++);
  1664. X    return t0;
  1665. X}
  1666. X
  1667. Xvoid checkmailpath(s) /**/
  1668. Xchar **s;
  1669. X{
  1670. Xstruct stat st;
  1671. Xchar *v,*u,c;
  1672. X
  1673. X    while (*s)
  1674. X        {
  1675. X        for (v = *s; *v && *v != '?'; v++);
  1676. X        c = *v;
  1677. X        *v = '\0';
  1678. X        if (c != '?')
  1679. X            u = NULL;
  1680. X        else
  1681. X            u = v+1;
  1682. X        if (stat(*s,&st) == -1)
  1683. X            {
  1684. X            if (errno != ENOENT)
  1685. X                zerr("%e: %s",*s,errno);
  1686. X            }
  1687. X        else if (S_ISDIR(st.st_mode))
  1688. X            {
  1689. X            Lklist l;
  1690. X            DIR *lock = opendir(s);
  1691. X            char buf[MAXPATHLEN*2],**arr,**ap;
  1692. X            struct direct *de;
  1693. X            int ct = 1;
  1694. X
  1695. X            if (lock)
  1696. X                {
  1697. X                pushheap();
  1698. X                heapalloc();
  1699. X                l = newlist();
  1700. X                readdir(lock); readdir(lock);
  1701. X                while (de = readdir(lock))
  1702. X                    {
  1703. X                    if (errflag)
  1704. X                        break;
  1705. X                    if (u)
  1706. X                        sprintf(buf,"%s/%s?%s",*s,de->d_name,u);
  1707. X                    else
  1708. X                        sprintf(buf,"%s/%s",*s,de->d_name);
  1709. X                    addnode(l,strdup(buf));
  1710. X                    ct++;
  1711. X                    }
  1712. X                closedir(lock);
  1713. X                ap = arr = (char **) alloc(ct*sizeof(char *));
  1714. X                while (*ap++ = ugetnode(l));
  1715. X                checkmailpath(arr);
  1716. X                popheap();
  1717. X                }
  1718. X            }
  1719. X        else
  1720. X            {
  1721. X            if (st.st_size && st.st_atime <= st.st_mtime &&
  1722. X                    st.st_mtime > lastmailcheck)
  1723. X                if (!u)
  1724. X                    {
  1725. X                    fprintf(stderr,"You have new mail.\n",*s);
  1726. X                    fflush(stderr);
  1727. X                    }
  1728. X                else
  1729. X                    {
  1730. X                    char *z = u;
  1731. X
  1732. X                    while (*z)
  1733. X                        if (*z == '$' && z[1] == '_')
  1734. X                            {
  1735. X                            fprintf(stderr,"%s",*s);
  1736. X                            z += 2;
  1737. X                            }
  1738. X                        else
  1739. X                            fputc(*z++,stderr);
  1740. X                    fputc('\n',stderr);
  1741. X                    fflush(stderr);
  1742. X                    }
  1743. X            if (isset(MAILWARNING) && st.st_atime > st.st_mtime &&
  1744. X                    st.st_atime > lastmailcheck && st.st_size)
  1745. X                {
  1746. X                fprintf(stderr,"The mail in %s has been read.\n",*s);
  1747. X                fflush(stderr);
  1748. X                }
  1749. X            }
  1750. X        *v = c;
  1751. X        s++;
  1752. X        }
  1753. X}
  1754. X
  1755. Xvoid saveoldfuncs(x,y) /**/
  1756. Xchar *x;Cmdnam y;
  1757. X{
  1758. XCmdnam cc;
  1759. X
  1760. X    if (y->type == SHFUNC || y->type == DISABLED)
  1761. X        {
  1762. X        cc = (Cmdnam) zcalloc(sizeof *cc);
  1763. X        *cc = *y;
  1764. X        y->u.list = NULL;
  1765. X        addhnode(ztrdup(x),cc,cmdnamtab,freecmdnam);
  1766. X        }
  1767. X}
  1768. X
  1769. X/* create command hashtable */
  1770. X
  1771. Xvoid newcmdnamtab() /**/
  1772. X{
  1773. Xint t0,dot = 0,pathct;
  1774. Xstruct direct *de;
  1775. XDIR *dir;
  1776. XCmdnam cc;
  1777. XHashtab oldcnt;
  1778. X
  1779. X    oldcnt = cmdnamtab;
  1780. X    permalloc();
  1781. X    cmdnamtab = newhtable(101);
  1782. X    if (pathsuppress) {
  1783. X        addbuiltins();
  1784. X        if (oldcnt) {
  1785. X            listhtable(oldcnt,(HFunc) saveoldfuncs);
  1786. X            freehtab(oldcnt,freecmdnam);
  1787. X        }
  1788. X        lastalloc();
  1789. X        return;
  1790. X    }
  1791. X    holdintr();
  1792. X    for (t0 = 0; path[t0]; t0++)
  1793. X        if (!strcmp(".",path[t0]))
  1794. X            {
  1795. X            dot = 1;
  1796. X            break;
  1797. X            }
  1798. X    for (pathct = arrlen(path), t0 = pathct-1; t0 >= 0; t0--)
  1799. X        if (!strcmp(".",path[t0]))
  1800. X            dot = 0;
  1801. X        else if (strncmp("/./",path[t0],3))
  1802. X            {
  1803. X            dir = opendir(path[t0]);
  1804. X            if (!dir)
  1805. X                continue;
  1806. X            readdir(dir); readdir(dir);
  1807. X            while (de = readdir(dir))
  1808. X                {
  1809. X                cc = (Cmdnam) zcalloc(sizeof *cc);
  1810. X                cc->type = (dot) ? EXCMD_POSTDOT : EXCMD_PREDOT;
  1811. X                cc->u.nam = tricat(path[t0],"/",de->d_name);
  1812. X                addhnode(ztrdup(de->d_name),cc,cmdnamtab,freecmdnam);
  1813. X                }
  1814. X            closedir(dir);
  1815. X            }
  1816. X    addbuiltins();
  1817. X    if (oldcnt)
  1818. X        {
  1819. X        listhtable(oldcnt,(HFunc) saveoldfuncs);
  1820. X        freehtab(oldcnt,freecmdnam);
  1821. X        }
  1822. X    noholdintr();
  1823. X    lastalloc();
  1824. X}
  1825. X
  1826. Xvoid freecmdnam(a) /**/
  1827. Xvptr a;
  1828. X{
  1829. Xstruct cmdnam *c = (struct cmdnam *) a;
  1830. X
  1831. X    if (c->type == SHFUNC) {
  1832. X        if (c->u.list)
  1833. X            freestruct(c->u.list);
  1834. X    } else if (c->type != BUILTIN && c->type != DISABLED)
  1835. X        free(c->u.nam);
  1836. X    free(c);
  1837. X}
  1838. X
  1839. Xvoid freestr(a) /**/
  1840. Xvptr a;
  1841. X{
  1842. X    free(a);
  1843. X}
  1844. X
  1845. Xvoid freeanode(a) /**/
  1846. Xvptr a;
  1847. X{
  1848. Xstruct alias *c = (struct alias *) a;
  1849. X
  1850. X    free(c->text);
  1851. X    free(c);
  1852. X}
  1853. X
  1854. Xvoid freepm(a) /**/
  1855. Xvptr a;
  1856. X{
  1857. Xstruct param *pm = (Param) a;
  1858. X
  1859. X    free(pm);
  1860. X}
  1861. X
  1862. Xvoid restoretty() /**/
  1863. X{
  1864. X    settyinfo(&shttyinfo);
  1865. X}
  1866. X
  1867. Xvoid gettyinfo(ti) /**/
  1868. Xstruct ttyinfo *ti;
  1869. X{
  1870. X    if (SHTTY != -1)
  1871. X        {
  1872. X#ifdef TERMIOS
  1873. X#ifdef __hpux
  1874. X        if (tcgetattr(SHTTY,&ti->termios) == -1)
  1875. X#else
  1876. X        if (ioctl(SHTTY,TCGETS,&ti->termios) == -1)
  1877. X#endif
  1878. X            zerr("bad tcgets: %e",NULL,errno);
  1879. X#else
  1880. X#ifdef TERMIO
  1881. X        ioctl(SHTTY,TCGETA,&ti->termio);
  1882. X#else
  1883. X        ioctl(SHTTY,TIOCGETP,&ti->sgttyb);
  1884. X        ioctl(SHTTY,TIOCLGET,&ti->lmodes);
  1885. X        ioctl(SHTTY,TIOCGETC,&ti->tchars);
  1886. X        ioctl(SHTTY,TIOCGLTC,&ti->ltchars);
  1887. X#endif
  1888. X#endif
  1889. X#ifdef TIOCGWINSZ
  1890. X        if (ioctl(SHTTY,TIOCGWINSZ,&ti->winsize) == -1)
  1891. X            zerr("bad tiocgwinsz: %e",NULL,errno);
  1892. X#endif
  1893. X        }
  1894. X}
  1895. X
  1896. Xvoid settyinfo(ti) /**/
  1897. Xstruct ttyinfo *ti;
  1898. X{
  1899. X    if (SHTTY != -1)
  1900. X        {
  1901. X#ifdef TERMIOS
  1902. X#ifdef __hpux
  1903. X        if (tcsetattr(SHTTY, TCSADRAIN, &ti->termios) == -1)
  1904. X#else
  1905. X        if (ioctl(SHTTY,TCSETS,&ti->termios) == -1)
  1906. X#endif
  1907. X            zerr("settyinfo: %e",NULL,errno);
  1908. X#else
  1909. X#ifdef TERMIO
  1910. X        ioctl(SHTTY,TCSETA,&ti->termio);
  1911. X#else
  1912. X        ioctl(SHTTY,TIOCSETN,&ti->sgttyb);
  1913. X        ioctl(SHTTY,TIOCLSET,&ti->lmodes);
  1914. X        ioctl(SHTTY,TIOCSETC,&ti->tchars);
  1915. X        ioctl(SHTTY,TIOCSLTC,&ti->ltchars);
  1916. X#endif
  1917. X#endif
  1918. X#ifdef TIOCGWINSZ
  1919. X        signal(SIGWINCH,SIG_IGN);
  1920. X        if (ioctl(SHTTY,TIOCSWINSZ,&ti->winsize) == -1)
  1921. X            zerr("settyinfo: %e",NULL,errno);
  1922. X        signal(SIGWINCH,handler);
  1923. X#endif
  1924. X        }
  1925. X}
  1926. X
  1927. X#define SANEKEY(X) \
  1928. X    if (ti->X == -1 && savedttyinfo.X != -1) ti->X = savedttyinfo.X;
  1929. X
  1930. Xvoid sanetty(ti) /**/
  1931. Xstruct ttyinfo *ti;
  1932. X{
  1933. Xint t0;
  1934. X
  1935. X#ifdef TERMIOS
  1936. X    ti->termios.c_lflag |= ICANON|ECHO;
  1937. X    for (t0 = 0; t0 != NCCS; t0++)
  1938. X        if (!ti->termios.c_cc[t0] && savedttyinfo.termios.c_cc[t0])
  1939. X            ti->termios.c_cc[t0] = savedttyinfo.termios.c_cc[t0];
  1940. X#else
  1941. X#ifdef TERMIO
  1942. X    ti->termio.c_lflag |= ICANON|ECHO;
  1943. X    for (t0 = 0; t0 != NCC; t0++)
  1944. X        if (!ti->termio.c_cc[t0] && savedttyinfo.termio.c_cc[t0])
  1945. X            ti->termio.c_cc[t0] = savedttyinfo.termio.c_cc[t0];
  1946. X#else
  1947. X    ti->sgttyb.sg_flags = (ti->sgttyb.sg_flags & ~CBREAK) | ECHO;
  1948. X    SANEKEY(tchars.t_quitc);
  1949. X    SANEKEY(tchars.t_startc);
  1950. X    SANEKEY(tchars.t_stopc);
  1951. X    SANEKEY(ltchars.t_suspc);
  1952. X    SANEKEY(ltchars.t_dsuspc);
  1953. X    SANEKEY(ltchars.t_lnextc);
  1954. X#endif
  1955. X#endif
  1956. X}
  1957. X
  1958. Xvoid adjustwinsize() /**/
  1959. X{
  1960. X#ifdef TIOCGWINSZ
  1961. X    ioctl(SHTTY,TIOCGWINSZ,&shttyinfo.winsize);
  1962. X    if (!(columns = shttyinfo.winsize.ws_col))
  1963. X        columns = 80;
  1964. X    lines = shttyinfo.winsize.ws_row;
  1965. X    if (zleactive)
  1966. X        refresh();
  1967. X#endif
  1968. X}
  1969. X
  1970. Xint zyztem(s,t) /**/
  1971. Xchar *s;char *t;
  1972. X{
  1973. X#ifdef WAITPID
  1974. Xint pid,statusp;
  1975. X
  1976. X    if (!(pid = fork()))
  1977. X        {
  1978. X        s = tricat(s," ",t);
  1979. X        execl("/bin/sh","sh","-c",s,(char *) 0);
  1980. X        _exit(1);
  1981. X        }
  1982. X    while (waitpid(pid,&statusp,WUNTRACED) == -1 && errno == EINTR);
  1983. X    if (WIFEXITED(SP(statusp)))
  1984. X        return WEXITSTATUS(SP(statusp));
  1985. X    return 1;
  1986. X#else
  1987. X    if (!waitfork())
  1988. X        {
  1989. X        s = tricat(s," ",t);
  1990. X        execl("/bin/sh","sh","-c",s,(char *) 0);
  1991. X        _exit(1);
  1992. X        }
  1993. X    return 0;
  1994. X#endif
  1995. X}
  1996. X
  1997. X#ifndef WAITPID
  1998. X
  1999. X/* fork a process and wait for it to complete without confusing
  2000. X    the SIGCHLD handler */
  2001. X
  2002. Xint waitfork() /**/
  2003. X{
  2004. Xint pipes[2];
  2005. Xchar x;
  2006. X
  2007. X    pipe(pipes);
  2008. X    if (!fork())
  2009. X        {
  2010. X        close(pipes[0]);
  2011. X        signal(SIGCHLD,SIG_DFL);
  2012. X        if (!fork())
  2013. X            return 0;
  2014. X        wait(NULL);
  2015. X        _exit(0);
  2016. X        }
  2017. X    close(pipes[1]);
  2018. X    read(pipes[0],&x,1);
  2019. X    close(pipes[0]);
  2020. X    return 1;
  2021. X}
  2022. X
  2023. X#endif
  2024. X
  2025. X/* move a fd to a place >= 10 */
  2026. X
  2027. Xint movefd(fd) /**/
  2028. Xint fd;
  2029. X{
  2030. Xint fe;
  2031. X
  2032. X    if (fd == -1)
  2033. X        return fd;
  2034. X#ifdef F_DUPFD
  2035. X    fe = fcntl(fd,F_DUPFD,10);
  2036. X#else
  2037. X    if ((fe = dup(fd)) < 10)
  2038. X        fe = movefd(fe);
  2039. X#endif
  2040. X    close(fd);
  2041. X    return fe;
  2042. X}
  2043. X
  2044. X/* move fd x to y */
  2045. X
  2046. Xvoid redup(x,y) /**/
  2047. Xint x;int y;
  2048. X{
  2049. X    if (x != y)
  2050. X        {
  2051. X        dup2(x,y);
  2052. X        close(x);
  2053. X        }
  2054. X}
  2055. X
  2056. Xvoid settrap(t0,l) /**/
  2057. Xint t0;List l;
  2058. X{
  2059. XCmd c;
  2060. X
  2061. X    if (l)
  2062. X        {
  2063. X        c = l->left->left->left;
  2064. X        if (c->type == SIMPLE && !full(c->args) && !full(c->redir)
  2065. X                && !full(c->vars) && !c->flags)
  2066. X            l = NULL;
  2067. X        }
  2068. X    if (t0 == -1)
  2069. X        return;
  2070. X    if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
  2071. X            || t0 == SIGPIPE))
  2072. X        {
  2073. X        zerr("can't trap SIG%s in interactive shells",sigs[t0-1],0);
  2074. X        return;
  2075. X        }
  2076. X    if (!l)
  2077. X        {
  2078. X        sigtrapped[t0] = 2;
  2079. X        if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
  2080. X            {
  2081. X            signal(t0,SIG_IGN);
  2082. X            sigtrapped[t0] = 2;
  2083. X            }
  2084. X        }
  2085. X    else
  2086. X        {
  2087. X        if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
  2088. X            signal(t0,handler);
  2089. X        sigtrapped[t0] = 1;
  2090. X        permalloc();
  2091. X        sigfuncs[t0] = (List) dupstruct(l);
  2092. X        heapalloc();
  2093. X        }
  2094. X}
  2095. X
  2096. Xvoid unsettrap(t0) /**/
  2097. Xint t0;
  2098. X{
  2099. X    if (t0 == -1)
  2100. X        return;
  2101. X    if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
  2102. X            || t0 == SIGPIPE))
  2103. X        {
  2104. X        zerr("can't trap SIG%s in interactive shells",sigs[t0],0);
  2105. X        return;
  2106. X        }
  2107. X    sigtrapped[t0] = 0;
  2108. X    if (t0 == SIGINT)
  2109. X        intr();
  2110. X    else if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
  2111. X        signal(t0,SIG_DFL);
  2112. X    if (sigfuncs[t0])
  2113. X        freestruct(sigfuncs[t0]);
  2114. X}
  2115. X
  2116. Xvoid dotrap(sig) /**/
  2117. Xint sig;
  2118. X{
  2119. Xint sav;
  2120. X
  2121. X    sav = sigtrapped[sig];
  2122. X    if (sav == 2)
  2123. X        return;
  2124. X    sigtrapped[sig] = 2;
  2125. X    if (sigfuncs[sig])
  2126. X        newrunlist(sigfuncs[sig]);
  2127. X    sigtrapped[sig] = sav;
  2128. X}
  2129. X
  2130. X/* copy len chars from t into s, and null terminate */
  2131. X
  2132. Xvoid ztrncpy(s,t,len) /**/
  2133. Xchar *s;char *t;int len;
  2134. X{
  2135. X    while (len--) *s++ = *t++;
  2136. X    *s = '\0';
  2137. X}
  2138. X
  2139. X/* copy t into *s and update s */
  2140. X
  2141. Xvoid strucpy(s,t) /**/
  2142. Xchar **s;char *t;
  2143. X{
  2144. Xchar *u = *s;
  2145. X
  2146. X    while (*u++ = *t++);
  2147. X    *s = u-1;
  2148. X}
  2149. X
  2150. Xvoid struncpy(s,t,n) /**/
  2151. Xchar **s;char *t;int n;
  2152. X{
  2153. Xchar *u = *s;
  2154. X
  2155. X    while (n--)
  2156. X        *u++ = *t++;
  2157. X    *s = u;
  2158. X    *u = '\0';
  2159. X}
  2160. X
  2161. Xvoid checkrmall() /**/
  2162. X{
  2163. X    fflush(stdin);
  2164. X    fprintf(stderr,"zsh: sure you want to delete all the files in %s? ",cwd);
  2165. X    fflush(stderr);
  2166. X    feep();
  2167. X    errflag |= (getquery() != 'y');
  2168. X}
  2169. X
  2170. Xint getquery() /**/
  2171. X{
  2172. Xchar c;
  2173. X
  2174. X    setcbreak();
  2175. X    if (read(SHTTY,&c,1) == 1)
  2176. X        if (c == 'y' || c == 'Y' || c == '\t') c = 'y';
  2177. X    unsetcbreak();
  2178. X    if (c != '\n')
  2179. X        write(2,"\n",1);
  2180. X    return (int) c;
  2181. X}
  2182. X
  2183. Xstatic int d;
  2184. Xstatic char *guess,*best;
  2185. X
  2186. Xvoid spscannodis(s,cn) /**/
  2187. Xchar *s;char *cn;
  2188. X{
  2189. X    if (((Cmdnam) cn)->type != DISABLED)
  2190. X        spscan(s,NULL);
  2191. X}
  2192. X
  2193. Xvoid spscan(s,junk) /**/
  2194. Xchar *s;char *junk;
  2195. X{
  2196. Xint nd;
  2197. X
  2198. X    nd = spdist(s,guess,strlen(guess)/4+1);
  2199. X    if (nd <= d)
  2200. X        {
  2201. X        best = s;
  2202. X        d = nd;
  2203. X        }
  2204. X}
  2205. X
  2206. X/* spellcheck a word */
  2207. X/* fix s and s2 ; if s2 is non-null, fix the history list too */
  2208. X
  2209. Xvoid spckword(s,s2,tptr,cmd,ask) /**/
  2210. Xchar **s;char **s2;char **tptr;int cmd;int ask;
  2211. X{
  2212. Xchar *t,*u;
  2213. Xint x;
  2214. X
  2215. X    if (**s == '-' || **s == '%')
  2216. X        return;
  2217. X    if (!strcmp(*s,"in"))
  2218. X        return;
  2219. X    if (gethnode(*s,cmdnamtab) || gethnode(*s,aliastab) || strlen(*s) == 1)
  2220. X        return;
  2221. X    for (t = *s; *t; t++)
  2222. X        if (itok(*t))
  2223. X            return;
  2224. X    if (access(*s,F_OK) == 0)
  2225. X        return;
  2226. X    best = NULL;
  2227. X    for (t = *s; *t; t++)
  2228. X        if (*t == '/')
  2229. X            break;
  2230. X    if ((u = spname(*s)) != *s)
  2231. X        best = u;
  2232. X    else if (!*t && !cmd) {
  2233. X        guess = *s;
  2234. X        d = 100;
  2235. X        listhtable(aliastab,spscan);
  2236. X        listhtable(cmdnamtab,spscan);
  2237. X    }
  2238. X    if (best && strlen(best) > 1 && strcmp(best,*s)) {
  2239. X        if (ask) {
  2240. X            char *p = sprompt;
  2241. X            while (*p) {
  2242. X                if (*p == '%') {
  2243. X                    if (p[1] == 'r') fprintf(stderr,"%s",best);
  2244. X                    if (p[1] == 's') fprintf(stderr,"%s",*s);
  2245. X                    if (p[1]) p++;
  2246. X                } else fputc(*p,stderr);
  2247. X                p++;
  2248. X            }
  2249. X            fflush(stderr);
  2250. X            feep();
  2251. X            x = getquery();
  2252. X        } else
  2253. X            x = 'y';
  2254. X        if (x == 'y') {
  2255. X            *s = strdup(best);
  2256. X            if (s2) {
  2257. X                if (*tptr && !strcmp(hlastw,*s2)) {
  2258. X                    char *z;
  2259. X                    hptr = hlastw;
  2260. X                    for (z = best; *z; z++) hwaddc(*z);
  2261. X                    hwaddc(HISTSPACE);
  2262. X                    *tptr = hptr-1;
  2263. X                    **tptr = '\0';
  2264. X                }
  2265. X                *s2 = strdup(best);
  2266. X            }
  2267. X        } else if (x == 'a') {
  2268. X            histdone |= HISTFLAG_NOEXEC;
  2269. X        } else if (x == 'e') {
  2270. X            histdone |= HISTFLAG_NOEXEC;
  2271. X            zrecall = 1;
  2272. X        }
  2273. X    }
  2274. X}
  2275. X
  2276. Xint ztrftime(buf,bufsize,fmt,tm) /**/
  2277. Xchar *buf;int bufsize;char *fmt;struct tm *tm;
  2278. X{
  2279. Xstatic char *astr[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  2280. Xstatic char *estr[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
  2281. X    "Aug","Sep","Oct","Nov","Dec"};
  2282. Xstatic char *lstr[] = {"12"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9",
  2283. X    "10","11"};
  2284. X
  2285. X    while (*fmt)
  2286. X        if (*fmt == '%')
  2287. X            {
  2288. X            fmt++;
  2289. X            switch(*fmt++)
  2290. X                {
  2291. X                case 'a':
  2292. X                    strucpy(&buf,astr[tm->tm_wday]);
  2293. X                    break;
  2294. X                case 'b':
  2295. X                    strucpy(&buf,estr[tm->tm_mon]);
  2296. X                    break;
  2297. X                case 'd':
  2298. X                    *buf++ = '0'+tm->tm_mday/10;
  2299. X                    *buf++ = '0'+tm->tm_mday%10;
  2300. X                    break;
  2301. X                case 'e':
  2302. X                    if (tm->tm_mday > 9)
  2303. X                        *buf++ = '0'+tm->tm_mday/10;
  2304. X                    *buf++ = '0'+tm->tm_mday%10;
  2305. X                    break;
  2306. X                case 'k':
  2307. X                    if (tm->tm_hour > 9)
  2308. X                        *buf++ = '0'+tm->tm_hour/10;
  2309. X                    *buf++ = '0'+tm->tm_hour%10;
  2310. X                    break;
  2311. X                case 'l':
  2312. X                    strucpy(&buf,lstr[tm->tm_hour%12]);
  2313. X                    break;
  2314. X                case 'm':
  2315. X                    *buf++ = '0'+(tm->tm_mon+1)/10;
  2316. X                    *buf++ = '0'+(tm->tm_mon+1)%10;
  2317. X                    break;
  2318. X                case 'M':
  2319. X                    *buf++ = '0'+tm->tm_min/10;
  2320. X                    *buf++ = '0'+tm->tm_min%10;
  2321. X                    break;
  2322. X                case 'p':
  2323. X                    *buf++ = (tm->tm_hour > 11) ? 'p' : 'a';
  2324. X                    *buf++ = 'm';
  2325. X                    break;
  2326. X                case 'S':
  2327. X                    *buf++ = '0'+tm->tm_sec/10;
  2328. X                    *buf++ = '0'+tm->tm_sec%10;
  2329. X                    break;
  2330. X                case 'y':
  2331. X                    *buf++ = '0'+tm->tm_year/10;
  2332. X                    *buf++ = '0'+tm->tm_year%10;
  2333. X                    break;
  2334. X                default:
  2335. X                    exit(20);
  2336. X                }
  2337. X            }
  2338. X        else
  2339. X            *buf++ = *fmt++;
  2340. X    *buf = '\0';
  2341. X    return 0;
  2342. X}
  2343. X
  2344. Xchar *join(arr,delim) /**/
  2345. Xchar **arr;int delim;
  2346. X{
  2347. Xint len = 0;
  2348. Xchar **s,*ret,*ptr;
  2349. X
  2350. X    for (s = arr; *s; s++)
  2351. X        len += strlen(*s)+1;
  2352. X    if (!len)
  2353. X        return ztrdup("");
  2354. X    ptr = ret = zalloc(len);
  2355. X    for (s = arr; *s; s++)
  2356. X        {
  2357. X        strucpy(&ptr,*s);
  2358. X        *ptr++ = delim;
  2359. X        }
  2360. X    ptr[-1] = '\0';
  2361. X    return ret;
  2362. X}
  2363. X
  2364. Xchar *spacejoin(s) /**/
  2365. Xchar **s;
  2366. X{
  2367. X    return join(s,*ifs);
  2368. X}
  2369. X
  2370. Xchar *colonjoin(s) /**/
  2371. Xchar **s;
  2372. X{
  2373. X    return join(s,':');
  2374. X}
  2375. X
  2376. Xchar **colonsplit(s) /**/
  2377. Xchar *s;
  2378. X{
  2379. Xint ct;
  2380. Xchar *t,**ret,**ptr;
  2381. X
  2382. X    for (t = s, ct = 0; *t; t++)
  2383. X        if (*t == ':')
  2384. X            ct++;
  2385. X    ptr = ret = (char **) zalloc(sizeof(char **)*(ct+2));
  2386. X    t = s;
  2387. X    do
  2388. X        {
  2389. X        for (s = t; *t && *t != ':'; t++);
  2390. X        *ptr = zalloc((t-s)+1);
  2391. X        ztrncpy(*ptr++,s,t-s);
  2392. X        }
  2393. X    while (*t++);
  2394. X    *ptr = NULL;
  2395. X    return ret;
  2396. X}
  2397. X
  2398. Xchar **spacesplit(s) /**/
  2399. Xchar *s;
  2400. X{
  2401. Xint ct;
  2402. Xchar *t,**ret,**ptr;
  2403. X
  2404. X    for (t = s, ct = 0; *t; t++)
  2405. X        if (iblank(*t))
  2406. X            ct++;
  2407. X    ptr = ret = (char **) zalloc(sizeof(char **)*(ct+2));
  2408. X    t = s;
  2409. X    do
  2410. X        {
  2411. X        for (s = t; *t && !inblank(*t); t++);
  2412. X        *ptr = zalloc((t-s)+1);
  2413. X        ztrncpy(*ptr++,s,t-s);
  2414. X        }
  2415. X    while (*t++);
  2416. X    *ptr = NULL;
  2417. X    return ret;
  2418. X}
  2419. X
  2420. XList getshfunc(nam) /**/
  2421. Xchar *nam;
  2422. X{
  2423. XCmdnam x = (Cmdnam) gethnode(nam,cmdnamtab);
  2424. X
  2425. X    return (x && x->type == SHFUNC) ? x->u.list : NULL;
  2426. X}
  2427. X
  2428. X/* allocate a tree element */
  2429. X
  2430. Xvptr allocnode(type) /**/
  2431. Xint type;
  2432. X{
  2433. Xint t0;
  2434. Xstruct node *n = (struct node *) alloc(sizeof *n);
  2435. Xstatic int typetab[N_COUNT][4] = {
  2436. X    NT_NODE,NT_NODE,0,0,
  2437. X    NT_NODE,NT_NODE,0,0,
  2438. X    NT_NODE,NT_NODE,0,0,
  2439. X    NT_STR|NT_LIST,NT_NODE,NT_NODE|NT_LIST,NT_NODE|NT_LIST,
  2440. X    NT_STR,0,0,0,
  2441. X    NT_NODE,NT_NODE,0,0,
  2442. X    NT_STR,NT_NODE,0,0,
  2443. X    NT_NODE,NT_STR,NT_NODE,0,
  2444. X    NT_NODE,NT_NODE,NT_NODE,0,
  2445. X    NT_NODE,NT_NODE,0,0,
  2446. X    NT_STR,NT_STR,NT_STR|NT_LIST,0
  2447. X    };
  2448. X
  2449. X    n->type = type;
  2450. X    for (t0 = 0; t0 != 4; t0++)
  2451. X        n->types[t0] = typetab[type][t0];
  2452. X    return (vptr) n;
  2453. X}
  2454. X
  2455. X/* duplicate a syntax tree */
  2456. X
  2457. Xvptr dupstruct(a) /**/
  2458. Xvptr a;
  2459. X{
  2460. Xstruct node *n = a,*m;
  2461. Xint t0;
  2462. X
  2463. X    m = alloc(sizeof *m);
  2464. X    *m = *n;
  2465. X    for (t0 = 0; t0 != 4; t0++)
  2466. X        if (m->ptrs[t0])
  2467. X            switch(m->types[t0])
  2468. X                {
  2469. X                case NT_NODE: m->ptrs[t0] = dupstruct(m->ptrs[t0]); break;
  2470. X                case NT_STR: m->ptrs[t0] =
  2471. X                    (useheap) ? strdup(m->ptrs[t0]) : ztrdup(m->ptrs[t0]); break;
  2472. X                case NT_LIST|NT_NODE:
  2473. X                    m->ptrs[t0] = duplist(m->ptrs[t0],dupstruct); break;
  2474. X                case NT_LIST|NT_STR:
  2475. X                    m->ptrs[t0] = duplist(m->ptrs[t0],(VFunc)
  2476. X                        ((useheap) ? strdup : ztrdup));
  2477. X                    break;
  2478. X                }
  2479. X    return (vptr) m;
  2480. X}
  2481. X
  2482. X/* free a syntax tree */
  2483. X
  2484. Xvoid freestruct(a) /**/
  2485. Xvptr a;
  2486. X{
  2487. Xstruct node *n = (struct node *) a;
  2488. Xint t0;
  2489. X
  2490. X    for (t0 = 0; t0 != 4; t0++)
  2491. X        if (n->ptrs[t0])
  2492. X            switch(n->types[t0])
  2493. X                {
  2494. X                case NT_NODE: freestruct(n->ptrs[t0]); break;
  2495. X                case NT_STR: free(n->ptrs[t0]); break;
  2496. X                case NT_LIST|NT_STR: freetable(n->ptrs[t0],freestr); break;
  2497. X                case NT_LIST|NT_NODE: freetable(n->ptrs[t0],freestruct); break;
  2498. X                }
  2499. X    free(n);
  2500. X}
  2501. X
  2502. XLklist duplist(l,func) /**/
  2503. SHAR_EOF
  2504. true || echo 'restore of zsh2.1/src/utils.c failed'
  2505. fi
  2506. echo 'End of zsh2.1.0 part 10'
  2507. echo 'File zsh2.1/src/utils.c is continued in part 11'
  2508. echo 11 > _shar_seq_.tmp
  2509. exit 0
  2510.  
  2511. exit 0 # Just in case...
  2512. -- 
  2513. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2514. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2515. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2516. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2517.