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

  1. Newsgroups: comp.sources.misc
  2. From: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
  3. Subject: v35i058:  zsh - The Z Shell, version 2.3.1, Part08/22
  4. Message-ID: <1993Feb20.212307.28579@sparky.imd.sterling.com>
  5. X-Md4-Signature: 3be6b34a9bb71c4ba8cbe65a22f1d0fc
  6. Date: Sat, 20 Feb 1993 21:23:07 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
  10. Posting-number: Volume 35, Issue 58
  11. Archive-name: zsh/part08
  12. Environment: UNIX
  13. Supersedes: zsh2.2: Volume 29, Issue 97-113
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  src/builtin.c.01 src/config.h.sample
  22. # Wrapped by mattson@odin on Sat Feb  6 14:41:52 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 8 (of 22)."'
  26. if test -f 'src/builtin.c.01' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'src/builtin.c.01'\"
  28. else
  29.   echo shar: Extracting \"'src/builtin.c.01'\" \(49195 characters\)
  30.   sed "s/^X//" >'src/builtin.c.01' <<'END_OF_FILE'
  31. X/*
  32. X *
  33. X * builtin.c - builtin commands
  34. X *
  35. X * This file is part of zsh, the Z shell.
  36. X *
  37. X * This software is Copyright 1992 by Paul Falstad
  38. X *
  39. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  40. X * use this software as long as: there is no monetary profit gained
  41. X * specifically from the use or reproduction of this software, it is not
  42. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  43. X * included prominently in any copy made. 
  44. X *
  45. X * The author make no claims as to the fitness or correctness of this software
  46. X * for any use whatsoever, and it is provided as is. Any use of this software
  47. X * is at the user's own risk. 
  48. X *
  49. X */
  50. X
  51. X#include "zsh.h"
  52. X#include <sys/errno.h>
  53. X
  54. X#define makecond() allocnode(N_COND)
  55. X
  56. X/* builtin flags */
  57. X
  58. X#define BINF_PLUSOPTS        1        /* +xyz legal */
  59. X#define BINF_R                    2        /* this is r (fc -e -) */
  60. X#define BINF_PRINTOPTS        4
  61. X#define BINF_SETOPTS            8
  62. X#define BINF_FCOPTS          16
  63. X#define BINF_TYPEOPT      32
  64. X#define BINF_TYPEOPTS      (BINF_TYPEOPT|BINF_PLUSOPTS)
  65. X#define BINF_ECHOPTS      64
  66. X
  67. X/* builtin funcs */
  68. X
  69. X#define BIN_TYPESET 0
  70. X#define BIN_BG 1
  71. X#define BIN_FG 2
  72. X#define BIN_JOBS 3
  73. X#define BIN_WAIT 4
  74. X#define BIN_DISOWN 5
  75. X#define BIN_BREAK 6
  76. X#define BIN_CONTINUE 7
  77. X#define BIN_EXIT 8
  78. X#define BIN_RETURN 9
  79. X#define BIN_SHIFT 10
  80. X#define BIN_CD 11
  81. X#define BIN_POPD 12
  82. X#define BIN_PUSHD 13
  83. X#define BIN_PRINT 14
  84. X#define BIN_EVAL 15
  85. X#define BIN_SCHED 16
  86. X#define BIN_FC 17
  87. X#define BIN_PUSHLINE 18
  88. X#define BIN_LOGOUT 19
  89. X#define BIN_BUILTIN 20
  90. X#define BIN_TEST 21
  91. X#define BIN_BRACKET 22
  92. X
  93. Xstruct bincmd {
  94. X    char *name;
  95. X    int (*handlerfunc) DCLPROTO((char *,char **,char *,int));
  96. X    int minargs;        /* min # of args */
  97. X    int maxargs;        /* max # of args, or -1 for no limit */
  98. X    int flags;            /* BINF_flags (see above) */
  99. X    int funcid;            /* xbins (see above) for overloaded handlerfuncs */
  100. X    char *optstr;        /* string of legal options */
  101. X    char *defopts;        /* options set by default for overloaded handlerfuncs */
  102. X    };
  103. X
  104. X/* structure for foo=bar assignments */
  105. X
  106. Xstruct asgment {
  107. X    struct asgment *next;
  108. X    char *name,*value;
  109. X    };
  110. X
  111. Xstatic char *auxdata;
  112. Xstatic int auxlen;
  113. Xstatic int showflag = 0,showflag2 = 0;
  114. X
  115. X#define NULLBINCMD ((int (*) DCLPROTO((char *,char **,char *,int))) 0)
  116. X
  117. Xstruct bincmd builtins[] = {
  118. X    {"[",bin_test,0,-1,0,BIN_BRACKET,NULL,NULL},
  119. X    {".",bin_dot,1,-1,0,0,NULL,NULL},
  120. X    {":",bin_colon,0,-1,0,0,NULL,NULL},
  121. X    {"alias",bin_alias,0,-1,0,0,"ga",NULL},
  122. X    {"autoload",bin_typeset,0,-1,BINF_TYPEOPTS,0,"tx","fu"},
  123. X    {"bg",bin_fg,0,-1,0,BIN_BG,NULL,NULL},
  124. X    {"bindkey",bin_bindkey,0,-1,0,0,"asvemdrl",NULL},
  125. X    {"break",bin_break,0,1,0,BIN_BREAK,NULL,NULL},
  126. X    {"builtin",NULLBINCMD,0,0,0,BIN_BUILTIN,NULL,NULL},
  127. X    {"bye",bin_break,0,1,0,BIN_EXIT,NULL,NULL},
  128. X    {"cd",bin_cd,0,2,0,BIN_CD,NULL,NULL},
  129. X    {"chdir",bin_cd,0,2,0,BIN_CD,NULL,NULL},
  130. X    {"compctl",bin_compctl,0,-1,0,0,NULL,NULL},
  131. X    {"continue",bin_break,0,1,0,BIN_CONTINUE,NULL,NULL},
  132. X    {"declare",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL},
  133. X    {"dirs",bin_dirs,0,-1,0,0,"v",NULL},
  134. X    {"disable",bin_disable,1,-1,0,0,NULL,NULL},
  135. X    {"disown",bin_fg,1,-1,0,BIN_DISOWN,NULL,NULL},
  136. X    {"echo",bin_print,0,-1,BINF_PRINTOPTS|BINF_ECHOPTS,BIN_PRINT,"n","-"},
  137. X    {"echotc",bin_echotc,1,-1,0,0,NULL,NULL},
  138. X    {"enable",bin_enable,1,-1,0,0,NULL,NULL},
  139. X    {"eval",bin_eval,0,-1,0,BIN_EVAL,NULL,NULL},
  140. X    {"exit",bin_break,0,1,0,BIN_EXIT,NULL,NULL},
  141. X    {"export",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtu","x"},
  142. X    {"false",bin_let,0,0,0,0,NULL,NULL},
  143. X    {"fc",bin_fc,0,-1,BINF_FCOPTS,BIN_FC,"nlreIRWAdDfE",NULL},
  144. X    {"fg",bin_fg,0,-1,0,BIN_FG,NULL,NULL},
  145. X    {"functions",bin_typeset,0,-1,BINF_TYPEOPTS,0,"tu","f"},
  146. X    {"getln",bin_read,0,-1,0,0,NULL,"zr"},
  147. X    {"getopts",bin_getopts,2,-1,0,0,NULL,NULL},
  148. X    {"hash",bin_hash,2,2,0,0,"r",NULL},
  149. X    {"history",bin_fc,0,-1,0,BIN_FC,"nrdDfE","l"},
  150. X    {"integer",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZlrtux","i"},
  151. X    {"jobs",bin_fg,0,-1,0,BIN_JOBS,"lpZ",NULL},
  152. X    {"kill",bin_kill,0,-1,0,0,NULL,NULL},
  153. X    {"let",bin_let,1,-1,0,0,NULL,NULL},
  154. X    {"limit",bin_limit,0,-1,0,0,"sh",NULL},
  155. X    {"local",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL},
  156. X    {"log",bin_log,0,0,0,0,NULL,NULL},
  157. X    {"logout",bin_break,0,1,0,BIN_LOGOUT,NULL,NULL},
  158. X    {"popd",bin_cd,0,2,0,BIN_POPD,NULL,NULL},
  159. X    {"print",bin_print,0,-1,BINF_PRINTOPTS,BIN_PRINT,"RDPnrslzNu0123456789p-",NULL},
  160. X    {"pushd",bin_cd,0,2,0,BIN_PUSHD,NULL,NULL},
  161. X    {"pushln",bin_print,0,-1,BINF_PRINTOPTS,BIN_PRINT,NULL,"-nz"},
  162. X    {"pwd",bin_pwd,0,0,0,0,NULL,NULL},
  163. X    {"r",bin_fc,0,-1,BINF_R,BIN_FC,"nrl",NULL},
  164. X    {"read",bin_read,0,-1,0,0,"rzu0123456789p",NULL},
  165. X    {"readonly",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfiltux","r"},
  166. X    {"rehash",bin_rehash,0,0,0,0,"f",NULL},
  167. X    {"return",bin_break,0,1,0,BIN_RETURN,NULL,NULL},
  168. X    {"sched",bin_sched,0,-1,0,0,NULL,NULL},
  169. X    {"set",bin_set,0,-1,BINF_SETOPTS|BINF_PLUSOPTS,0,"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZaefghjklmnosuvwxy",NULL},
  170. X    {"setopt",bin_setopt,0,-1,BINF_PLUSOPTS,0,"0123456789BCDEFGHIJKLMNOPQRSTUVWXYZaefghjklmnosuvwxy",NULL},
  171. X    {"shift",bin_break,0,1,0,BIN_SHIFT,NULL,NULL},
  172. X    {"source",bin_dot,1,-1,0,0,NULL,NULL},
  173. X    {"suspend",bin_suspend,0,0,0,0,"f",NULL},
  174. X    {"test",bin_test,0,-1,0,BIN_TEST,NULL,NULL},
  175. X    {"ttyctl",bin_ttyctl,0,0,0,0,"fu",NULL},
  176. X    {"times",bin_times,0,0,0,0,NULL,NULL},
  177. X    {"trap",bin_trap,0,-1,0,0,NULL,NULL},
  178. X    {"true",bin_colon,0,0,0,0,NULL,NULL},
  179. X    {"type",bin_whence,0,-1,0,0,"pfa","v"},
  180. X    {"typeset",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL},
  181. X    {"ulimit",bin_ulimit,0,1,0,0,"HSacdfmnt",NULL},
  182. X    {"umask",bin_umask,0,1,0,0,NULL,NULL},
  183. X    {"unalias",bin_unalias,1,-1,0,0,NULL,NULL},
  184. X    {"unfunction",bin_unhash,1,-1,0,0,NULL,NULL},
  185. X    {"unhash",bin_unhash,1,-1,0,0,NULL,NULL},
  186. X    {"unlimit",bin_unlimit,0,-1,0,0,"h",NULL},
  187. X    {"unset",bin_unset,1,-1,0,0,NULL,NULL},
  188. X    {"unsetopt",bin_setopt,0,-1,BINF_PLUSOPTS,1,"0123456789BCDEFGHIJKLMNOPQRSTUWXYZabefghjklmnosuvwxy",NULL},
  189. X    {"vared",bin_vared,1,1,0,0,NULL,NULL},
  190. X    {"wait",bin_fg,0,-1,0,BIN_WAIT,NULL,NULL},
  191. X    {"whence",bin_whence,0,-1,0,0,"pvcfa",NULL},
  192. X    {"which",bin_whence,0,-1,0,0,"pa","c"},
  193. X    {NULL,NULLBINCMD,0,0,0,0,NULL,NULL}
  194. X    };
  195. X
  196. X/* print options */
  197. X
  198. Xstatic void prtopt()
  199. X{
  200. Xstruct option *opp;
  201. X
  202. X    if (isset(KSHOPTIONPRINT)) {
  203. X        printf("Current option settings\n");
  204. X        for (opp = optns; opp->name; opp++)
  205. X            printf("%-20s%s\n", opp->name, isset(opp->id) ? "on" : "off");
  206. X    } else
  207. X        for (opp = optns; opp->name; opp++)
  208. X            if (isset(opp->id))
  209. X                puts(opp->name);
  210. X}
  211. X
  212. X/* add builtins to the command hash table */
  213. X
  214. Xvoid addbuiltins() /**/
  215. X{
  216. Xstruct cmdnam *c;
  217. Xstruct bincmd *b;
  218. Xint t0;
  219. X
  220. X    for (t0 = 0, b = builtins; b->name; b++,t0++)
  221. X        {
  222. X        c = (Cmdnam) zcalloc(sizeof *c);
  223. X        c->type = BUILTIN;
  224. X        c->u.binnum = t0;
  225. X        addhperm(b->name,c,cmdnamtab,freecmdnam);
  226. X        }
  227. X}
  228. X
  229. X/* enable */
  230. X
  231. Xint bin_enable(name,argv,ops,whocares) /**/
  232. Xchar *name;char **argv;char *ops;int whocares;
  233. X{
  234. Xstruct cmdnam *c;
  235. Xstruct bincmd *b;
  236. Xint t0,ret = 0;
  237. X
  238. X    for (; *argv; argv++)
  239. X        {
  240. X        for (t0 = 0, b = builtins; b->name; b++,t0++)
  241. X            if (!strcmp(*argv,b->name))
  242. X                break;
  243. X        if (!b->name)
  244. X            {
  245. X            zerrnam(name,"no such builtin: %s",*argv,0);
  246. X            ret = 1;
  247. X            }
  248. X        else
  249. X            {
  250. X            c = (Cmdnam) zcalloc(sizeof *c);
  251. X            c->type = BUILTIN;
  252. X            c->u.binnum = t0;
  253. X            addhperm(b->name,c,cmdnamtab,freecmdnam);
  254. X            }
  255. X        }
  256. X    return ret;
  257. X}
  258. X
  259. X/* :, true */
  260. X
  261. Xint bin_colon(name,argv,ops,whocares) /**/
  262. Xchar *name;char **argv;char *ops;int whocares;
  263. X{
  264. X    return 0;
  265. X}
  266. X
  267. X/* break, bye, continue, exit, logout, return, shift */
  268. X
  269. Xint bin_break(name,argv,ops,func) /**/
  270. Xchar *name;char **argv;char *ops;int func;
  271. X{
  272. Xint num = -1;
  273. X
  274. X    if (*argv)
  275. X        num = matheval(*argv);
  276. X    if ((func == BIN_BREAK || func == BIN_CONTINUE) && !loops)
  277. X        {
  278. X        if (func == BIN_CONTINUE)
  279. X            zerrnam(name,"not in loop",NULL,0);
  280. X        return 1;
  281. X        }
  282. X    switch (func)
  283. X        {
  284. X        case BIN_CONTINUE:
  285. X            contflag = 1;
  286. X        case BIN_BREAK:
  287. X            breaks = (num == -1) ? 1 : num;
  288. X            if (breaks > loops) breaks = loops;
  289. X            break;
  290. X        case BIN_LOGOUT:
  291. X            if (!islogin)
  292. X                {
  293. X                zerrnam(name,"not login shell",NULL,0);
  294. X                return 1;
  295. X                }
  296. X        case BIN_EXIT:
  297. X            zexit((num == -1) ? lastval : num);
  298. X            break;
  299. X        case BIN_RETURN:
  300. X            retflag = 1;
  301. X            breaks = loops;
  302. X            return lastval = (num == -1) ? lastval : num;
  303. X        case BIN_SHIFT:
  304. X            {
  305. X            char **s;
  306. X
  307. X            if (num == -1)
  308. X                num = 1;
  309. X            if (num > arrlen(pparams))
  310. X                num = arrlen(pparams);
  311. X            permalloc();
  312. X            s = arrdup(pparams+num);
  313. X            heapalloc();
  314. X            freearray(pparams);
  315. X            pparams = s;
  316. X            break;
  317. X            }
  318. X        }
  319. X    return 0;
  320. X}
  321. X
  322. X/* bg, disown, fg, jobs, wait */
  323. X
  324. Xint bin_fg(name,argv,ops,func) /**/
  325. Xchar *name;char **argv;char *ops;int func;
  326. X{
  327. Xint job,lng,firstjob = -1,retval = 0;
  328. X
  329. X    if (ops['Z']) { if (*argv) strcpy(hackzero,*argv); return 0; }
  330. X    lng = (ops['l']) ? 1 : (ops['p']) ? 2 : 0;
  331. X    if ((func == BIN_FG || func == BIN_BG) && !jobbing)
  332. X        {
  333. X        zerrnam(name,"no job control in this shell.",NULL,0);
  334. X        return 1;
  335. X        }
  336. X    if (unset(NOTIFY)) scanjobs();
  337. X    if (curjob != -1 && !(jobtab[curjob].stat & STAT_INUSE))
  338. X        {
  339. X        curjob = prevjob; setprevjob();
  340. X        if (curjob != -1 && !(jobtab[curjob].stat & STAT_INUSE))
  341. X            curjob = prevjob; setprevjob();
  342. X        }
  343. X    if (func == BIN_JOBS)
  344. X        stopmsg = 2;
  345. X    if (!*argv)
  346. X        if (func == BIN_FG || func == BIN_BG)
  347. X            {
  348. X            if (curjob == -1 || curjob == thisjob)
  349. X                {
  350. X                zerrnam(name,"no current job",NULL,0);
  351. X                return 1;
  352. X                }
  353. X            firstjob = curjob;
  354. X            }
  355. X        else if (func == BIN_JOBS)
  356. X            {
  357. X            for (job = 0; job != MAXJOB; job++)
  358. X                if (job != thisjob && jobtab[job].stat)
  359. X                    printjob(job+jobtab,lng);
  360. X            return 0;
  361. X            }
  362. X        else
  363. X            {
  364. X            for (job = 0; job != MAXJOB; job++)
  365. X                if (job != thisjob && jobtab[job].stat)
  366. X                    waitjob(job);
  367. X            return lastval;
  368. X            }
  369. X    for (; (firstjob != -1) || *argv; ( void ) (*argv && argv++))
  370. X        {
  371. X        int stopped,ocj = thisjob;
  372. X
  373. X        if (func == BIN_WAIT && isanum(*argv)) {
  374. X            waitforpid((long) atoi(*argv));
  375. X            retval = lastval;
  376. X            thisjob = ocj;
  377. X            continue;
  378. X        }
  379. X        job = (*argv) ? getjob(*argv,name) : firstjob;
  380. X        firstjob = -1;
  381. X        if (job == -1)
  382. X            break;
  383. X        if (!(jobtab[job].stat & STAT_INUSE))
  384. X            {
  385. X            zerrnam(name,"no such job: %d",0,job);
  386. X            return 1;
  387. X            }
  388. X        switch (func)
  389. X            {
  390. X            case BIN_FG:
  391. X            case BIN_BG:
  392. X                if (stopped = (jobtab[job].stat & STAT_STOPPED))
  393. X                    makerunning(jobtab+job);
  394. X                else if (func == BIN_BG)
  395. X                    {
  396. X                    zerrnam(name,"job already in background",NULL,0);
  397. X                    thisjob = ocj;
  398. X                    return 1;
  399. X                    }
  400. X                if (curjob == job)
  401. X                    {
  402. X                    curjob = prevjob;
  403. X                    prevjob = (func == BIN_BG) ? -1 : job;
  404. X                    }
  405. X                if (prevjob == job)
  406. X                    prevjob = -1;
  407. X                if (prevjob == -1)
  408. X                    setprevjob();
  409. X                if (curjob == -1)
  410. X                    {
  411. X                    curjob = prevjob;
  412. X                    setprevjob();
  413. X                    }
  414. X                printjob(jobtab+job,(stopped) ? -1 : 0);
  415. X                if (func == BIN_FG)
  416. X                    {
  417. X                    thisjob = job;
  418. X                    if (strcmp(jobtab[job].pwd,pwd))
  419. X                        {
  420. X                        printf("(pwd : ");
  421. X                        printdir(jobtab[job].pwd);
  422. X                        printf(")\n");
  423. X                        }
  424. X                    fflush(stdout);
  425. X                    attachtty(jobtab[job].gleader);
  426. X                    }
  427. X                if (stopped)
  428. X                    killpg(jobtab[job].gleader,SIGCONT);
  429. X                if (func == BIN_FG)
  430. X                    waitjobs();
  431. X                break;
  432. X            case BIN_JOBS:
  433. X                printjob(job+jobtab,lng);
  434. X                break;
  435. X            case BIN_WAIT:
  436. X                waitjob(job);
  437. X                retval = lastval;
  438. X                break;
  439. X            case BIN_DISOWN:
  440. X                {
  441. X                static struct job zero;
  442. X                jobtab[job] = zero;
  443. X                break;
  444. X                }
  445. X            }
  446. X        thisjob = ocj;
  447. X        }
  448. X    return retval;
  449. X}
  450. X
  451. X/* false, let */
  452. X
  453. Xint bin_let(name,argv,ops,func) /**/
  454. Xchar *name;char **argv;char *ops;int func;
  455. X{
  456. Xlong val = 0;
  457. X
  458. X    while (*argv)
  459. X        val = matheval(*argv++);
  460. X    return !val;
  461. X}
  462. X
  463. X/* print the directory stack */
  464. X
  465. Xstatic void pdstack()
  466. X{
  467. XLknode node;
  468. X
  469. X    printdir(pwd);
  470. X    for (node = firstnode(dirstack); node; incnode(node))
  471. X        {
  472. X        putchar(' ');
  473. X        printdir(getdata(node));
  474. X        }
  475. X    putchar('\n');
  476. X}
  477. X
  478. X/* exit the shell */
  479. X
  480. Xint zexit(val) /**/
  481. Xint val;
  482. X{
  483. X    if (isset(MONITOR))
  484. X        if (!stopmsg) {
  485. X            checkjobs();
  486. X            if (stopmsg) {
  487. X                stopmsg = 2;
  488. X                return 1;
  489. X            }
  490. X        } else killrunjobs();
  491. X    if (unset(NORCS) && interact) {
  492. X        if (isset(APPENDHISTORY)) {
  493. X            savehistfile(getsparam("HISTFILE"),0,3);
  494. X            readhistfile(getsparam("HISTFILE"),0);
  495. X        }
  496. X        savehistfile(getsparam("HISTFILE"),0,0);
  497. X        if (islogin)
  498. X            sourcehome(".zlogout");
  499. X    }
  500. X    if (sigtrapped[SIGEXIT])
  501. X        dotrap(SIGEXIT);
  502. X    exit(val); return 0;
  503. X}
  504. X
  505. X/* identify an option name */
  506. X
  507. Xint optlookup(s) /**/
  508. Xchar *s;
  509. X{
  510. Xchar *t;
  511. Xstruct option *o;
  512. X
  513. X    t = s = strdup(s);
  514. X    while (*t)
  515. X        if (*t == '_')
  516. X            chuck(t);
  517. X        else {
  518. X            *t = tulower(*t);
  519. X            t++;
  520. X        }
  521. X    for (o = optns; o->name; o++)
  522. X        if (!strcmp(o->name,s))
  523. X            return o->id;
  524. X    return -1;
  525. X}
  526. X
  527. X/* setopt, unsetopt */
  528. X
  529. Xint bin_setopt(nam,args,ops,isun) /**/
  530. Xchar *nam;char **args;char *ops;int isun;
  531. X{
  532. Xstruct option *opp;
  533. Xint c;
  534. X
  535. X    if (!ops['@'] && !*args) {
  536. X        if (!isun)
  537. X            prtopt();
  538. X        return 0;
  539. X    }
  540. X    for (opp = optns; opp->name; opp++)
  541. X        if (ops[opp->id] == 1+isun)
  542. X            opts[(int)opp->id] = OPT_SET;
  543. X        else if (ops[(int)opp->id] == 2-isun)
  544. X            opts[(int)opp->id] = OPT_UNSET;
  545. X    while (*args) {
  546. X        c = optlookup(*args++);
  547. X        if (c != -1) {
  548. X            if (c == INTERACTIVE)
  549. X                zerrnam(nam,"can't change option: %s",args[-1],0);
  550. X            else
  551. X                opts[c] = (isun) ? OPT_UNSET : OPT_SET;
  552. X        } else {
  553. X            zerrnam(nam,"no such option: %s",args[-1],0);
  554. X            return 1;
  555. X        }
  556. X    }
  557. X    return 0;
  558. X}
  559. X
  560. X/* execute func on each member of the hash table ht */
  561. X
  562. Xstatic hnamcmp DCLPROTO((struct hashnode **a,struct hashnode **b));
  563. Xstatic int hnamcmp(a,b)
  564. Xstruct hashnode **a;struct hashnode **b;
  565. X{
  566. X    return forstrcmp(&((*a)->nam), &((*b)->nam));
  567. X}
  568. X
  569. Xvoid listhtable(ht,func) /**/
  570. XHashtab ht;HFunc func;
  571. X{
  572. Xint t0;
  573. Xstruct hashnode *hn;
  574. X
  575. X#ifndef HASHORDER
  576. X
  577. Xint nhash; struct hashnode **hnsorttab, **htp;
  578. X
  579. X    for (nhash = 0, t0 = ht->hsize-1; t0 >= 0; t0--)
  580. X        for (hn = ht->nodes[t0]; hn; hn = hn->next)
  581. X            nhash++;
  582. X
  583. X    hnsorttab = (struct hashnode **)zalloc (nhash * sizeof(struct hashnode *));
  584. X    for (htp = hnsorttab, t0 = ht->hsize-1; t0 >= 0; t0--)
  585. X        for (hn = ht->nodes[t0]; hn; hn = hn->next)
  586. X            *htp++ = hn;
  587. X
  588. X    qsort((vptr)&hnsorttab[0],nhash,sizeof(struct hashnode *),
  589. X            (int (*) DCLPROTO((const void *, const void *)))hnamcmp);
  590. X
  591. X    for (htp = hnsorttab; nhash; nhash--, htp++)
  592. X        func((*htp)->nam, (char *) (*htp));
  593. X
  594. X    free (hnsorttab);
  595. X
  596. X#else
  597. X
  598. X    for (t0 = ht->hsize-1; t0 >= 0; t0--)
  599. X        for (hn = ht->nodes[t0]; hn; hn = hn->next)
  600. X            func(hn->nam,(char *) hn);
  601. X
  602. X#endif HASHORDER
  603. X}
  604. X
  605. X/* print a shell function (used with listhtable) */
  606. X
  607. Xvoid pshfunc(s,cc) /**/
  608. Xchar *s;Cmdnam cc;
  609. X{
  610. Xchar *t;
  611. X
  612. X    if (cc->type != SHFUNC)
  613. X        return;
  614. X    if (showflag && (cc->flags & showflag2) != showflag2)
  615. X        return;
  616. X    if (cc->flags & PMFLAG_u)
  617. X        printf("undefined ");
  618. X    if (cc->flags & PMFLAG_t)
  619. X        printf("traced ");
  620. X    if (!cc->u.list || !showflag) {
  621. X        printf("%s ()\n",s);
  622. X        return;
  623. X    }
  624. X    t = getpermtext((vptr) (cc->u.list));
  625. X    printf("%s () {\n\t%s\n}\n",s,t);
  626. X    free(t);
  627. X}
  628. X
  629. Xvoid niceprint(s) /**/
  630. Xchar *s;
  631. X{
  632. X    niceprintf(s,stdout);
  633. X}
  634. X
  635. Xvoid niceprintf(s,f) /**/
  636. Xchar *s;FILE *f;
  637. X{
  638. X    for (; *s; s++)
  639. X        {
  640. X        if (isprint(*s))
  641. X            fputc(*s,f);
  642. X        else if (*s == '\n')
  643. X            {
  644. X            putc('\\',f);
  645. X            putc('n',f);
  646. X            }
  647. X        else
  648. X            {
  649. X            putc('^',f);
  650. X            fputc(*s | 0x40,f);
  651. X            }
  652. X        }
  653. X}
  654. X
  655. Xint bin_umask(nam,args,ops,func) /**/
  656. Xchar *nam;char **args;char *ops;int func;
  657. X{
  658. Xint um;
  659. Xchar *s = *args;
  660. X
  661. X    um = umask(0);
  662. X    umask(um);
  663. X    if (!s)
  664. X        {
  665. X        printf("%03o\n",um);
  666. X        return 0;
  667. X        }
  668. X    if (idigit(*s))
  669. X        {
  670. X        um = zstrtol(s,&s,8);
  671. X        if (*s)
  672. X            {
  673. X            zerrnam(nam,"bad umask",NULL,0);
  674. X            return 1;
  675. X            }
  676. X        }
  677. X    else
  678. X        {
  679. X        int whomask,op,mask;
  680. X
  681. X        for (;;)
  682. X            {
  683. X            if (*s == 'u')
  684. X                s++, whomask = 0100;
  685. X            else if (*s == 'g')
  686. X                s++, whomask = 0010;
  687. X            else if (*s == 'o')
  688. X                s++, whomask = 0001;
  689. X            else
  690. X                whomask = 0111;
  691. X            op = *s++;
  692. X            if (!(op == '+' || op == '-' || op == '='))
  693. X                {
  694. X                zerrnam(nam,"bad symbolic mode operator: %c",NULL,op);
  695. X                return 1;
  696. X                }
  697. X            mask = whomask;
  698. X            if (*s == 'r')
  699. X                mask *= 04;
  700. X            else if (*s == 'w')
  701. X                mask *= 02;
  702. X            else if (*s != 'x')
  703. X                {
  704. X                zerrnam(nam,"bad symbolic mode permission: %c",NULL,*s);
  705. X                return 1;
  706. X                }
  707. X            if (op == '+')
  708. X                um |= mask;
  709. X            else if (op == '-')
  710. X                um &= ~mask;
  711. X            else /* op == '=' */
  712. X                um = (um & ~(whomask*07)) | mask;
  713. X            if (*++s == ',')
  714. X                s++;
  715. X            else
  716. X                break;
  717. X            }
  718. X        if (*s)
  719. X            {
  720. X            zerrnam(nam,"bad character in symbolic mode: %c",NULL,*s);
  721. X            return 1;
  722. X            }
  723. X        }
  724. X    umask(um);
  725. X    return 0;
  726. X}
  727. X
  728. X/* type, whence, which */
  729. X
  730. Xint bin_whence(nam,argv,ops,func) /**/
  731. Xchar *nam;char **argv;char *ops;int func;
  732. X{
  733. Xstruct cmdnam *chn;
  734. Xstruct alias *a;
  735. Xint retval = 0;
  736. Xint csh = ops['c'],all = ops['a'];
  737. Xint v = ops['v'] || csh;
  738. Xchar *cnam;
  739. Xint informed;
  740. X
  741. X    for (; *argv; argv++) {
  742. X        informed = 0;
  743. X        if (!ops['p'] && (a = (Alias) gethnode(*argv,aliastab))) {
  744. X            if (a->cmd < 0)
  745. X                printf((csh) ? "%s: shell reserved word\n" :
  746. X                    (v) ? "%s is a reserved word\n" : "%s\n",*argv);
  747. X            else if (!v)
  748. X                puts(a->text);
  749. X            else if (a->cmd)
  750. X                printf((csh) ? "%s: aliased to %s\n" :
  751. X                    "%s is an alias for %s\n",*argv,a->text);
  752. X            else
  753. X                printf((csh) ? "%s: globally aliased to %s\n" :
  754. X                    "%s is a global alias for %s\n",*argv,a->text);
  755. X            retval = 0;
  756. X            if (!all) continue;
  757. X            informed = 1;
  758. X        }
  759. X        if (!ops['p'] && (chn = (Cmdnam) gethnode(*argv,cmdnamtab)) &&
  760. X                (chn->type == SHFUNC || chn->type == BUILTIN)) {
  761. X            if (chn->type == SHFUNC) {
  762. X                if (csh || ops['f']) {
  763. X                    showflag = 1; showflag2 = 0;
  764. X                    pshfunc(*argv,chn);
  765. X                } else {
  766. X                    printf((v) ? "%s is a function\n" : "%s\n",*argv);
  767. X                }
  768. X            } else
  769. X                printf((csh) ? "%s: shell built-in command\n" :
  770. X                    (v) ? "%s is a shell builtin\n" : "%s\n",*argv);
  771. X            retval = 0;
  772. X            if (!all) continue;
  773. X            informed = 1;
  774. X        }
  775. X        if (all) {
  776. X            char **pp,buf[MAXPATHLEN],*z;
  777. X            for (pp = path; *pp; pp++) {
  778. X                z = buf;
  779. X                strucpy(&z,*pp);
  780. X                *z++ = '/';
  781. X                strcpy(z,*argv);
  782. X                if (iscom(buf)) {
  783. X                    if (v && !csh) printf("%s is %s\n",*argv,buf);
  784. X                    else puts(buf);
  785. X                    retval = 0;
  786. X                    informed = 1;
  787. X                }
  788. X            }
  789. X            if (!informed && v) {
  790. X                printf("%s not found\n",*argv);
  791. X                retval = 1;
  792. X                break;
  793. X            }
  794. X        } else if (!(cnam = findcmd(*argv))) {
  795. X            if (v) printf("%s not found\n",*argv);
  796. X            retval = 1;
  797. X            break;
  798. X        } else {
  799. X            if (v && !csh) printf("%s is %s\n",*argv,cnam);
  800. X            else puts(cnam);
  801. X            retval = 0;
  802. X            free(cnam);
  803. X        }
  804. X    }
  805. X    return retval;
  806. X}
  807. X
  808. X/* cd, chdir, pushd, popd */
  809. X
  810. Xint bin_cd(nam,argv,ops,func) /**/
  811. Xchar *nam;char **argv;char *ops;int func;
  812. X{
  813. Xchar *dest, *dir;
  814. X
  815. X    if (func == BIN_CD && isset(AUTOPUSHD))
  816. X        func = BIN_PUSHD;
  817. X    dir = dest = cd_get_dest(nam,argv,ops,func);
  818. X    if (!dest)
  819. X        return 1;
  820. X    dest = cd_do_chdir(nam,dest);
  821. X    if (dest != dir)
  822. X        free(dir);
  823. X    if (!dest)
  824. X        return 1;
  825. X    cd_new_pwd(func,dest);
  826. X    free(dest);
  827. X    return 0;
  828. X}
  829. X
  830. Xchar *cd_get_dest(nam,argv,ops,func) /**/
  831. Xchar *nam;char **argv;char *ops;int func;
  832. X{
  833. Xchar *dest;
  834. X
  835. X    if (!argv[0])
  836. X        if (func == BIN_CD || ((func == BIN_PUSHD && isset(PUSHDTOHOME))
  837. X                || empty(dirstack)))
  838. X            dest = ztrdup(home);
  839. X        else
  840. X            dest = ztrdup(getnode(dirstack));
  841. X    else if (!argv[1]) {
  842. X        Lknode n;
  843. X        int dd;
  844. X        char *end;
  845. X
  846. X        if (argv[0][1] && argv[0][0] == (isset(PUSHDMINUS) ? '-' : '+')) {
  847. X            dd = zstrtol(argv[0]+1,&end,10)-1;
  848. X            if (dd < 0 || *end != '\0') {
  849. X                zerrnam(nam,"%s: bad directory specification",argv[0],0);
  850. X                return NULL;
  851. X            }
  852. X            for (n = firstnode(dirstack); n && dd; dd--, incnode(n));
  853. X            if (!n) {
  854. X                zerrnam(nam,"no such entry in dir stack",NULL,0);
  855. X                return NULL;
  856. X            }
  857. X            dest = remnode(dirstack,n);
  858. X        } else if (argv[0][1] && argv[0][0] == (isset(PUSHDMINUS) ? '+' : '-')) {
  859. X            dd = zstrtol(argv[0]+1,&end,10);
  860. X            if (*end != '\0') {
  861. X                zerrnam(nam,"%s: bad directory specification",argv[0],0);
  862. X                return NULL;
  863. X            }
  864. X            for (n = lastnode(dirstack); n != (Lknode) dirstack && dd;
  865. X                    dd--, n = prevnode(n));
  866. X            if (n == (Lknode) dirstack) {
  867. X                zerrnam(nam,"no such entry in dir stack",NULL,0);
  868. X                return NULL;
  869. X            }
  870. X            dest = remnode(dirstack,n);
  871. X        } else {
  872. X            if (!strcmp(argv[0],"-")) printdircr(dest = ztrdup(oldpwd));
  873. X            else dest = ztrdup(argv[0]);
  874. X        }
  875. X    } else {
  876. X        char *u;
  877. X        int len1,len2,len3;
  878. X
  879. X        if (!(u = ztrstr(pwd,argv[0]))) {
  880. X            zerrnam(nam,"string not in pwd: %s",argv[0],0);
  881. X            return NULL;
  882. X        }
  883. X        len1 = strlen(argv[0]);
  884. X        len2 = strlen(argv[1]);
  885. X        len3 = u-pwd;
  886. X        dest = zalloc(len3+len2+strlen(u+len1)+1);
  887. X        strncpy(dest,pwd,len3);
  888. X        strcpy(dest+len3,argv[1]);
  889. X        strcat(dest,u+len1);
  890. X        printdircr(dest);
  891. X    }
  892. X    return dest;
  893. X}
  894. X
  895. Xchar *cd_do_chdir(cnam,dest) /**/
  896. Xchar *cnam; char *dest;
  897. X{
  898. Xint hasdot = 0, eno = ENOENT;
  899. Xchar **pp,*ret;
  900. X
  901. X    if (*dest == '/') {
  902. X        if (ret = cd_try_chdir(NULL,dest)) return ret;
  903. X        zerrnam(cnam,"%e: %s",dest,errno);
  904. X        return NULL;
  905. X    }
  906. X    for (pp = cdpath; *pp; pp++)
  907. X        if ((*pp)[0] == '.' && (*pp)[1] == '\0') hasdot = 1;
  908. X    if (!hasdot) {
  909. X        if (ret = cd_try_chdir(NULL,dest)) return ret;
  910. X        if (errno != ENOENT) eno = errno;
  911. X    }
  912. X    for (pp = cdpath; *pp; pp++) {
  913. X        if (ret = cd_try_chdir(*pp,dest)) {
  914. X            if (strcmp(*pp,".")) {
  915. X                printdircr(ret);
  916. X            }
  917. X            return ret;
  918. X        }
  919. X        if (errno != ENOENT) eno = errno;
  920. X    }
  921. X    if (isset(CDABLEVARS)) {
  922. X        char *s = getsparam(dest);
  923. X        if (s && *s == '/' && chdir(s) != -1) {
  924. X            printdircr(s);
  925. X            return ztrdup(s);
  926. X        }
  927. X        if (errno != ENOENT) eno = errno;
  928. X    }
  929. X    zerrnam(cnam,"%e: %s",dest,eno);
  930. X    return NULL;
  931. X}
  932. X
  933. Xchar *cd_try_chdir(pfix,dest) /**/
  934. Xchar *pfix; char *dest;
  935. X{
  936. Xchar buf[MAXPATHLEN], buf2[MAXPATHLEN];
  937. Xchar *s;
  938. Xint dotsct;
  939. X
  940. X    if (pfix) sprintf(buf,"%s/%s",(!strcmp("/",pfix)) ? "" : pfix,dest); 
  941. X    else strcpy(buf,dest);
  942. X    dotsct = fixdir(buf2,buf);
  943. X    if (buf2[0] == '/') return (chdir(buf) == -1) ? NULL : ztrdup(buf2);
  944. X    if (!dotsct) {
  945. X        if (chdir(buf) == -1) return NULL;
  946. X        if (*buf2) sprintf(buf,"%s/%s",(!strcmp("/",pwd)) ? "" : pwd,buf2);
  947. X        else strcpy(buf,pwd);
  948. X        return ztrdup(buf);
  949. X    }
  950. X    strcpy(buf,pwd);
  951. X    s = buf+strlen(buf)-1;
  952. X    while (dotsct--) while (s != buf) if (*--s == '/') break;
  953. X    if (s == buf || *buf2) s++;
  954. X    strcpy(s,buf2);
  955. X    if (chdir(buf) != -1 || chdir(dest) != -1) return ztrdup(buf);
  956. X    return NULL;
  957. X}
  958. X
  959. Xint fixdir(d,s) /**/
  960. Xchar *d; char *s;
  961. X{
  962. Xint ct = 0;
  963. Xchar *d0 = d;
  964. X
  965. X#ifdef HAS_RFS
  966. X    while (*s == '/' && s[1] == '.' && s[2] == '.') {
  967. X        *d++ = '/'; *d++ = '.'; *d++ = '.';
  968. X        s += 3;
  969. X    }
  970. X#endif
  971. X#ifdef apollo
  972. X    if (*s == '/') *d++ = *s++;   /*added RBC 18/05/92 */
  973. X#endif    
  974. X    for (;;) {
  975. X        if (*s == '/') {
  976. X            *d++ = *s++;
  977. X            while (*s == '/') s++;
  978. X        }
  979. X        if (!*s) {
  980. X            while (d > d0+1 && d[-1] == '/') d--;
  981. X            *d = '\0';
  982. X            return ct;
  983. X        }
  984. X        if (s[0] == '.' && s[1] == '.' && (s[2] == '\0' || s[2] == '/')) {
  985. X            if (d > d0+1) {
  986. X                for (d--; d > d0+1 && d[-1] != '/'; d--);
  987. X                if (d[-1] != '/') d--;
  988. X            } else ct++;
  989. X            s += 2; if (*s) s++;
  990. X        } else if (s[0] == '.' && (s[1] == '/' || s[1] == '\0')) {
  991. X            s++; if (*s) s++;
  992. X        } else {
  993. X            while (*s != '/' && *s != '\0') *d++ = *s++;
  994. X        }
  995. X    }
  996. X}
  997. X
  998. Xvoid cd_new_pwd(func,s) /**/
  999. Xint func; char *s;
  1000. X{
  1001. XParam pm;
  1002. XList l;
  1003. Xchar *new_pwd;
  1004. X
  1005. X    if (isset(CHASELINKS))
  1006. X        new_pwd = findpwd(s);
  1007. X    else
  1008. X        new_pwd = ztrdup(s);
  1009. X    if (!strcmp(new_pwd, pwd)) {
  1010. X        free(new_pwd);
  1011. X#ifdef ALWAYS_DO_CD_PROCESSING
  1012. X        if (unset(PUSHDSILENT) && func != BIN_CD && isset(INTERACTIVE))
  1013. X            pdstack();
  1014. X        if (l = getshfunc("chpwd")) {
  1015. X            fflush(stdout); fflush(stderr);
  1016. X            doshfuncnoval(dupstruct(l),NULL,0);
  1017. X        }
  1018. X#endif
  1019. X        return;
  1020. X    }
  1021. X    free(oldpwd);
  1022. X    oldpwd = pwd;
  1023. X    pwd = new_pwd;
  1024. X    if ((pm = gethnode("PWD", paramtab)) &&
  1025. X         (pm->flags & PMFLAG_x) && pm->env)
  1026. X        pm->env = replenv(pm->env,pwd);
  1027. X    if ((pm = gethnode("OLDPWD", paramtab)) &&
  1028. X         (pm->flags & PMFLAG_x) && pm->env)
  1029. X        pm->env = replenv(pm->env,oldpwd);
  1030. X    if (func == BIN_PUSHD) {
  1031. X        permalloc();
  1032. X        if (isset(PUSHDIGNOREDUPS)) {
  1033. X            Lknode n;
  1034. X            char *nodedata;
  1035. X            for (n = firstnode(dirstack); n; incnode(n)) {
  1036. X                nodedata = getdata(n);
  1037. X                if (!strcmp(oldpwd,nodedata) || !strcmp(pwd,nodedata)) {
  1038. X                    free(remnode(dirstack,n)); break;
  1039. X                }
  1040. X            }    
  1041. X        }
  1042. X        pushnode(dirstack,ztrdup(oldpwd));
  1043. X        heapalloc();
  1044. X    }
  1045. X    if (unset(PUSHDSILENT) && func != BIN_CD && isset(INTERACTIVE))
  1046. X        pdstack();
  1047. X    if (l = getshfunc("chpwd")) {
  1048. X        fflush(stdout); fflush(stderr);
  1049. X        doshfuncnoval(dupstruct(l),NULL,0);
  1050. X    }
  1051. X    if (dirstacksize != -1 && countnodes(dirstack) >= dirstacksize) {
  1052. X        if (dirstacksize < 2)
  1053. X            dirstacksize = 2;
  1054. X        else
  1055. X            free(remnode(dirstack,lastnode(dirstack)));
  1056. X    }
  1057. X}
  1058. X
  1059. Xvoid convertwd(s,t,off) /**/
  1060. Xchar *s; char *t; int off;
  1061. X{
  1062. Xchar *u,*start;
  1063. X
  1064. X    *t++ = '/';
  1065. X    start = t;
  1066. X    while (off--) *t++ = *s++;
  1067. X    for (;;) {
  1068. X        while (*s == '/') s++;
  1069. X        for (u = s; *u && *u != '/'; u++);
  1070. X        if (!strncmp(s,".",u-s)) {
  1071. X            ;
  1072. X        } else if (!strncmp(s,"..",u-s)) {
  1073. X            while (t != start && *--t != '/');
  1074. X        } else {
  1075. X            if (t != start) *t++ = '/';
  1076. X            struncpy(&t,s,u-s);
  1077. X        }
  1078. X        if (!*u) break;
  1079. X        s = u;
  1080. X    }
  1081. X    *t = '\0';
  1082. X}
  1083. X
  1084. Xint bin_rehash(name,argv,ops,func) /**/
  1085. Xchar *name;char **argv;char *ops;int func;
  1086. X{
  1087. X    newcmdnamtab();
  1088. X    if (ops['f']) fullhash();
  1089. X    return 0;
  1090. X}
  1091. X
  1092. Xint bin_hash(name,argv,ops,func) /**/
  1093. Xchar *name;char **argv;char *ops;int func;
  1094. X{
  1095. Xstruct cmdnam *chn;
  1096. X
  1097. X    chn = (Cmdnam) zcalloc(sizeof *chn);
  1098. X    chn->type = EXCMD;
  1099. X    chn->pcomp = NULL; /* this is probably a bug ! */
  1100. X    chn->u.nam = ztrdup(argv[1]);
  1101. X    addhnode(ztrdup(argv[0]),chn,cmdnamtab,freecmdnam);
  1102. X    return 0;
  1103. X}
  1104. X
  1105. X/* != 0 if s is a prefix of t */
  1106. X
  1107. Xint prefix(s,t) /**/
  1108. Xchar *s;char *t;
  1109. X{
  1110. X    while (*s && *t && *s == *t) s++,t++;
  1111. X    return (!*s);
  1112. X}
  1113. X
  1114. X/* convert %%, %1, %foo, %?bar? to a job number */
  1115. X
  1116. Xint getjob(s,prog) /**/
  1117. Xchar *s;char *prog;
  1118. X{
  1119. Xint t0,retval;
  1120. X
  1121. X    if (*s != '%')
  1122. X        goto jump;
  1123. X    s++;
  1124. X    if (*s == '%' || *s == '+' || !*s)
  1125. X        {
  1126. X        if (curjob == -1)
  1127. X            {
  1128. X            zerrnam(prog,"no current job",NULL,0);
  1129. X            retval = -1; goto done;
  1130. X            }
  1131. X        retval = curjob; goto done;
  1132. X        }
  1133. X    if (*s == '-')
  1134. X        {
  1135. X        if (prevjob == -1)
  1136. X            {
  1137. X            zerrnam(prog,"no previous job",NULL,0);
  1138. X            retval = -1; goto done;
  1139. X            }
  1140. X        retval = prevjob; goto done;
  1141. X        }
  1142. X    if (idigit(*s))
  1143. X        {
  1144. X        t0 = atoi(s);
  1145. X        if (t0 && t0 < MAXJOB && jobtab[t0].stat && t0 != thisjob)
  1146. X            { retval = t0; goto done; }
  1147. X        zerrnam(prog,"no such job",NULL,0);
  1148. X        retval = -1; goto done;
  1149. X        }
  1150. X    if (*s == '?')
  1151. X        {
  1152. X        struct process *pn;
  1153. X
  1154. X        for (t0 = MAXJOB-1; t0 >= 0; t0--)
  1155. X            if (jobtab[t0].stat && t0 != thisjob)
  1156. X                for (pn = jobtab[t0].procs; pn; pn = pn->next)
  1157. X                    if (ztrstr(pn->text,s+1))
  1158. X                        { retval = t0; goto done; }
  1159. X        zerrnam(prog,"job not found: %s",s,0);
  1160. X        retval = -1; goto done;
  1161. X        }
  1162. Xjump:
  1163. X    if ((t0 = findjobnam(s)) != -1)
  1164. X        { retval = t0; goto done; }
  1165. X    zerrnam(prog,"job not found: %s",s,0);
  1166. X    retval = -1;
  1167. Xdone:
  1168. X    return retval;
  1169. X}
  1170. X
  1171. X/* find a job named s */
  1172. X
  1173. Xint findjobnam(s) /**/
  1174. Xchar *s;
  1175. X{
  1176. Xint t0;
  1177. X
  1178. X    for (t0 = MAXJOB-1; t0 >= 0; t0--)
  1179. X        if (jobtab[t0].stat && jobtab[t0].procs && t0 != thisjob && 
  1180. X                jobtab[t0].procs->text && prefix(s,jobtab[t0].procs->text))
  1181. X            return t0;
  1182. X    return -1;
  1183. X}
  1184. X
  1185. Xint isanum(s) /**/
  1186. Xchar *s;
  1187. X{
  1188. X    while (*s == '-' || idigit(*s)) s++;
  1189. X    return *s == '\0';
  1190. X}
  1191. X
  1192. Xint bin_kill(nam,argv,ops,func) /**/
  1193. Xchar *nam;char **argv;char *ops;int func;
  1194. X{
  1195. Xint sig = SIGTERM;
  1196. Xint retval = 0;
  1197. X
  1198. X    if (*argv && **argv == '-') {
  1199. X        if (idigit((*argv)[1]))
  1200. X            sig = atoi(*argv+1);
  1201. X        else {
  1202. X            if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
  1203. X                printf("%s",sigs[1]);
  1204. X                for (sig = 2; sig <= SIGCOUNT; sig++)
  1205. X                    printf(" %s",sigs[sig]);
  1206. X                putchar('\n');
  1207. X                return 0;
  1208. X            }
  1209. X            for (sig = 1; sig <= SIGCOUNT; sig++)
  1210. X                if (!strcmp(sigs[sig],*argv+1)) break;
  1211. X            if (sig > SIGCOUNT) {
  1212. X                zerrnam(nam,"unknown signal: SIG%s",*argv+1,0);
  1213. X                zerrnam(nam,"type kill -l for a List of signals",NULL,0);
  1214. X                return 1;
  1215. X            }
  1216. X        }
  1217. X        argv++;
  1218. X    }
  1219. X    for (; *argv; argv++) {
  1220. X        if (**argv == '%') {
  1221. X            int p = getjob(*argv,"kill");
  1222. X
  1223. X            if (p == -1) {
  1224. X                retval = 1;
  1225. X                continue;
  1226. X            }
  1227. X            if (killjb(jobtab+p,sig) == -1) {
  1228. X                zerrnam("kill","kill failed: %e",NULL,errno);
  1229. X                retval = 1;
  1230. X                continue;
  1231. X            }
  1232. X            if (jobtab[p].stat & STAT_STOPPED) {
  1233. X                if (sig == SIGCONT)
  1234. X                    jobtab[p].stat &= ~STAT_STOPPED;
  1235. X                if (sig != SIGKILL && sig != SIGCONT && sig != SIGTSTP
  1236. X                        && sig != SIGTTOU && sig != SIGTTIN && sig != SIGSTOP)
  1237. X                    killjb(jobtab+p,SIGCONT);
  1238. X            }
  1239. X        } else if (!isanum(*argv)) {
  1240. X            zerrnam("kill","illegal pid: %s",*argv,0);
  1241. X            retval = 1;
  1242. X        } else if (kill(atoi(*argv),sig) == -1) {
  1243. X            zerrnam("kill","kill failed: %e",NULL,errno);
  1244. X            retval = 1;
  1245. X        }
  1246. X    }
  1247. X    return retval;
  1248. X}
  1249. X
  1250. Xstatic char *recs[] = {
  1251. X    "cputime","filesize","datasize","stacksize","coredumpsize",
  1252. X#ifdef RLIMIT_RSS
  1253. X#ifdef RLIMIT_MEMLOCK
  1254. X    "memoryuse",
  1255. X#else
  1256. X    "resident",
  1257. X#endif /* RLIMIT_MEMLOCK */
  1258. X#endif /* RLIMIT_RSS */
  1259. X#ifdef RLIMIT_MEMLOCK
  1260. X    "memorylocked",
  1261. X#endif
  1262. X#ifdef RLIMIT_NPROC
  1263. X    "maxproc",
  1264. X#endif
  1265. X#ifdef RLIMIT_OFILE
  1266. X    "openfiles",
  1267. X#endif
  1268. X#ifdef RLIMIT_NOFILE
  1269. X    "descriptors",
  1270. X#endif
  1271. X#ifdef RLIMIT_VMEM
  1272. X    "memorysize"
  1273. X#endif
  1274. X    };
  1275. X
  1276. Xint bin_limit(nam,argv,ops,func) /**/
  1277. Xchar *nam;char **argv;char *ops;int func;
  1278. X{
  1279. X#ifndef RLIM_INFINITY
  1280. X    zerrnam(nam,"not available on this system",NULL,0);
  1281. X    return 1;
  1282. X#else
  1283. Xchar *s;
  1284. Xint hard = ops['h'],t0,lim;
  1285. Xlong val;
  1286. X
  1287. X    if (ops['s'])
  1288. X        {
  1289. X        if (*argv)
  1290. X            zerrnam(nam,"arguments after -s ignored",NULL,0);
  1291. X        for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
  1292. X            if (setrlimit(t0,limits+t0) < 0)
  1293. X                zerrnam(nam,"setrlimit failed: %e",NULL,errno);
  1294. X        return 0;
  1295. X        }
  1296. X    if (!*argv)
  1297. X        {
  1298. X        showlimits(hard,-1);
  1299. X        return 0;
  1300. X        }
  1301. X    while (s = *argv++)
  1302. X        {
  1303. X        for (lim = -1, t0 = 0; t0 != RLIM_NLIMITS; t0++)
  1304. X            if (!strncmp(recs[t0],s,strlen(s)))
  1305. X                {
  1306. X                if (lim != -1)
  1307. X                    lim = -2;
  1308. X                else
  1309. X                    lim = t0;
  1310. X                }
  1311. X        if (lim < 0)
  1312. X            {
  1313. X            zerrnam("limit",
  1314. X                (lim == -2) ? "ambiguous resource specification: %s"
  1315. X                                : "no such resource: %s",s,0);
  1316. X            return 1;
  1317. X            }
  1318. X        if (!(s = *argv++))
  1319. X            {
  1320. X            showlimits(hard,lim);
  1321. X            return 0;
  1322. X            }
  1323. X        if (!lim)
  1324. X            {
  1325. X            val = zstrtol(s,&s,10);
  1326. X            if (*s)
  1327. X                if ((*s == 'h' || *s == 'H') && !s[1])
  1328. X                    val *= 3600L;
  1329. X                else if ((*s == 'm' || *s == 'M') && !s[1])
  1330. X                    val *= 60L;
  1331. X                else if (*s == ':')
  1332. X                    val = val*60+zstrtol(s+1,&s,10);
  1333. X                else
  1334. X                    {
  1335. X                    zerrnam("limit","unknown scaling factor: %s",s,0);
  1336. X                    return 1;
  1337. X                    }
  1338. X            }
  1339. X#ifdef RLIMIT_NPROC
  1340. X        else if (lim == RLIMIT_NPROC)
  1341. X            val = zstrtol(s,&s,10);
  1342. X#endif
  1343. X#ifdef RLIMIT_OFILE
  1344. X        else if (lim == RLIMIT_OFILE)
  1345. X            val = zstrtol(s,&s,10);
  1346. X#endif
  1347. X#ifdef RLIMIT_NOFILE
  1348. X        else if (lim == RLIMIT_NOFILE)
  1349. X            val = zstrtol(s,&s,10);
  1350. X#endif
  1351. X        else
  1352. X            {
  1353. X            val = zstrtol(s,&s,10);
  1354. X            if (!*s || ((*s == 'k' || *s == 'K') && !s[1]))
  1355. X                val *= 1024L;
  1356. X            else if ((*s == 'M' || *s == 'm') && !s[1])
  1357. X                val *= 1024L*1024;
  1358. X            else
  1359. X                {
  1360. X                zerrnam("limit","unknown scaling factor: %s",s,0);
  1361. X                return 1;
  1362. X                }
  1363. X            }
  1364. X        if (hard)
  1365. X            if (val > limits[lim].rlim_max && geteuid())
  1366. X                {
  1367. X                zerrnam("limit","can't raise hard limits",NULL,0);
  1368. X                return 1;
  1369. X                }
  1370. X            else
  1371. X                {
  1372. X                limits[lim].rlim_max = val;
  1373. X                if (limits[lim].rlim_max < limits[lim].rlim_cur)
  1374. X                    limits[lim].rlim_cur = limits[lim].rlim_max;
  1375. X                }
  1376. X        else
  1377. X            if (val > limits[lim].rlim_max)
  1378. X                {
  1379. X                zerrnam("limit","limit exceeds hard limit",NULL,0);
  1380. X                return 1;
  1381. X                }
  1382. X            else
  1383. X                limits[lim].rlim_cur = val;
  1384. X        }
  1385. X    return 0;
  1386. X#endif
  1387. X}
  1388. X
  1389. Xint bin_unlimit(nam,argv,ops,func) /**/
  1390. Xchar *nam;char **argv;char *ops;int func;
  1391. X{
  1392. X#ifndef RLIM_INFINITY
  1393. X    zerrnam(nam,"not available on this system",NULL,0);
  1394. X    return 1;
  1395. X#else
  1396. Xint hard = ops['h'],t0,lim;
  1397. X
  1398. X    if (hard && geteuid())
  1399. X        {
  1400. X        zerrnam(nam,"can't remove hard limits",NULL,0);
  1401. X        return 1;
  1402. X        }
  1403. X    if (!*argv)
  1404. X        {
  1405. X        for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
  1406. X            {
  1407. X            if (hard)
  1408. X                limits[t0].rlim_max = RLIM_INFINITY;
  1409. X            else
  1410. X                limits[t0].rlim_cur = limits[t0].rlim_max;
  1411. X            }
  1412. X        return 0;
  1413. X        }
  1414. X    for (; *argv; argv++)
  1415. X        {
  1416. X        for (lim = -1, t0 = 0; t0 != RLIM_NLIMITS; t0++)
  1417. X            if (!strncmp(recs[t0],*argv,strlen(*argv)))
  1418. X                {
  1419. X                if (lim != -1)
  1420. X                    lim = -2;
  1421. X                else
  1422. X                    lim = t0;
  1423. X                }
  1424. X        if (lim < 0)
  1425. X            {
  1426. X            zerrnam(nam,
  1427. X                (lim == -2) ? "ambiguous resource specification: %s"
  1428. X                                : "no such resource: %s",*argv,0);
  1429. X            return 1;
  1430. X            }
  1431. X        if (hard)
  1432. X            limits[lim].rlim_max = RLIM_INFINITY;
  1433. X        else
  1434. X            limits[lim].rlim_cur = limits[lim].rlim_max;
  1435. X        }
  1436. X    return 0;
  1437. X#endif
  1438. X}
  1439. X
  1440. Xvoid showlimits(hard,lim) /**/
  1441. Xint hard;int lim;
  1442. X{
  1443. Xint t0;
  1444. Xlong val;
  1445. X
  1446. X#ifdef RLIM_INFINITY
  1447. X    for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
  1448. X        if (t0 == lim || lim == -1)
  1449. X            {
  1450. X            printf("%-16s",recs[t0]);
  1451. X            val = (hard) ? limits[t0].rlim_max : limits[t0].rlim_cur;
  1452. X            if (val == RLIM_INFINITY)
  1453. X                printf("unlimited\n");
  1454. X            else if (!t0)
  1455. X                printf("%d:%02d:%02d\n",(int) (val/3600),
  1456. X                    (int) (val/60) % 60,(int) (val % 60));
  1457. X#ifdef RLIMIT_NPROC
  1458. X            else if (t0 == RLIMIT_NPROC)
  1459. X                printf("%d\n",(int) val);
  1460. X#endif
  1461. X#ifdef RLIMIT_OFILE
  1462. X            else if (t0 == RLIMIT_OFILE)
  1463. X                printf("%d\n",(int) val);
  1464. X#endif
  1465. X#ifdef RLIMIT_NOFILE
  1466. X            else if (t0 == RLIMIT_NOFILE)
  1467. X                printf("%d\n",(int) val);
  1468. X#endif
  1469. X            else if (val >= 1024L*1024L)
  1470. X                printf("%ldMb\n",val/(1024L*1024L));
  1471. X            else
  1472. X                printf("%ldKb\n",val/1024L);
  1473. X            }
  1474. X#endif
  1475. X}
  1476. X
  1477. Xint bin_sched(nam,argv,ops,func) /**/
  1478. Xchar *nam;char **argv;char *ops;int func;
  1479. X{
  1480. Xchar *s = *argv++;
  1481. Xtime_t t;
  1482. Xlong h,m;
  1483. Xstruct tm *tm;
  1484. Xstruct schedcmd *sch,*sch2,*schl;
  1485. Xint t0;
  1486. X
  1487. X    if (s && *s == '-')
  1488. X        {
  1489. X        t0 = atoi(s+1);
  1490. X
  1491. X        if (!t0)
  1492. X            {
  1493. X            zerrnam("sched","usage for delete: sched -<item#>.",NULL,0);
  1494. X            return 1;
  1495. X            }
  1496. X        for (schl = (struct schedcmd *) &schedcmds, sch = schedcmds, t0--;
  1497. X                sch && t0; sch = (schl = sch)->next, t0--);
  1498. X        if (!sch)
  1499. X            {
  1500. X            zerrnam("sched","not that many entries",NULL,0);
  1501. X            return 1;
  1502. X            }
  1503. X        schl->next = sch->next;
  1504. X        free(sch->cmd);
  1505. X        free(sch);
  1506. X        return 0;
  1507. X        }
  1508. X    if (!s)
  1509. X        {
  1510. X        char tbuf[40];
  1511. X
  1512. X        for (t0 = 1, sch = schedcmds; sch; sch = sch->next,t0++)
  1513. X            {
  1514. X            t = sch->time;
  1515. X            tm = localtime(&t);
  1516. X            ztrftime(tbuf,20,"%a %b %e %k:%M:%S",tm);
  1517. X            printf("%3d %s %s\n",t0,tbuf,sch->cmd);
  1518. X            }
  1519. X        return 0;
  1520. X        }
  1521. X    else if (!*argv)
  1522. X        {
  1523. X        zerrnam("sched","not enough arguments",NULL,0);
  1524. X        return 1;
  1525. X        }
  1526. X    if (*s == '+')
  1527. X        {
  1528. X        h = zstrtol(s+1,&s,10);
  1529. X        if (*s != ':')
  1530. X            {
  1531. X            zerrnam("sched","bad time specifier",NULL,0);
  1532. X            return 1;
  1533. X            }
  1534. X        m = zstrtol(s+1,&s,10);
  1535. X        if (*s)
  1536. X            {
  1537. X            zerrnam("sched","bad time specifier",NULL,0);
  1538. X            return 1;
  1539. X            }
  1540. X        t = time(NULL)+h*3600+m*60;
  1541. X        }
  1542. X    else
  1543. X        {
  1544. X        h = zstrtol(s,&s,10);
  1545. X        if (*s != ':')
  1546. X            {
  1547. X            zerrnam("sched","bad time specifier",NULL,0);
  1548. X            return 1;
  1549. X            }
  1550. X        m = zstrtol(s+1,&s,10);
  1551. X        if (*s && *s != 'a' && *s != 'p')
  1552. X            {
  1553. X            zerrnam("sched","bad time specifier",NULL,0);
  1554. X            return 1;
  1555. X            }
  1556. X        t = time(NULL);
  1557. X        tm = localtime(&t);
  1558. X        t -= tm->tm_sec+tm->tm_min*60+tm->tm_hour*3600;
  1559. X        if (*s == 'p')
  1560. X            h += 12;
  1561. X        t += h*3600+m*60;
  1562. X        if (t < time(NULL))
  1563. X            t += 3600*24;
  1564. X        }
  1565. X    sch = zcalloc(sizeof *sch);
  1566. X    sch->time = t;
  1567. X    sch->cmd = ztrdup(spacejoin(argv));
  1568. X    sch->next = NULL;
  1569. X    for (sch2 = (struct schedcmd *) &schedcmds; sch2->next; sch2 = sch2->next);
  1570. X    sch2->next = sch;
  1571. X    return 0;
  1572. X}
  1573. X
  1574. Xint bin_eval(nam,argv,ops,func) /**/
  1575. Xchar *nam;char **argv;char *ops;int func;
  1576. X{
  1577. Xchar *s = ztrdup(spacejoin(argv));
  1578. XList list;
  1579. X
  1580. X    hungets(s);
  1581. X    free(s);
  1582. X    strinbeg();
  1583. X    if (!(list = parse_list()))
  1584. X        {
  1585. X        hflush();
  1586. X        strinend();
  1587. X        return 1;
  1588. X        }
  1589. X    strinend();
  1590. X    runlist(list);
  1591. X    return lastval;
  1592. X}
  1593. X
  1594. X/* get the history event associated with s */
  1595. X
  1596. Xint fcgetcomm(s) /**/
  1597. Xchar *s;
  1598. X{
  1599. Xint cmd;
  1600. X
  1601. X    if (cmd = atoi(s))
  1602. X        {
  1603. X        if (cmd < 0)
  1604. X            cmd = curhist+cmd+1;
  1605. X        return cmd;
  1606. X        }
  1607. X    cmd = hcomsearch(s);
  1608. X    if (cmd == -1)
  1609. X        zerrnam("fc","event not found: %s",s,0);
  1610. X    return cmd;
  1611. X}
  1612. X
  1613. X/* perform old=new substituion */
  1614. X
  1615. Xint fcsubs(sp,sub) /**/
  1616. Xchar **sp;struct asgment *sub;
  1617. X{
  1618. Xchar *s1,*s2,*s3,*s4,*s = *sp,*s5;
  1619. Xint subbed = 0;
  1620. X
  1621. X    while (sub)
  1622. X        {
  1623. X        s1 = sub->name;
  1624. X        s2 = sub->value;
  1625. X        sub = sub->next;
  1626. X        s5 = s;
  1627. X        while (s3 = (char *) ztrstr(s5,s1))
  1628. X            {
  1629. X            s4 = alloc(1+(s3-s)+strlen(s2)+strlen(s3+strlen(s1)));
  1630. X            ztrncpy(s4,s,s3-s);
  1631. X            strcat(s4,s2);
  1632. X            s5 = s4+strlen(s4);
  1633. X            strcat(s4,s3+strlen(s1));
  1634. X            s = s4;
  1635. X            subbed = 1;
  1636. X            }
  1637. X        }
  1638. X    *sp = s;
  1639. X    return subbed;
  1640. X}
  1641. X
  1642. X/* print a series of history events to a file */
  1643. X
  1644. Xint fclist(f,n,r,D,d,first,last,subs) /**/
  1645. XFILE *f;int n;int r;int D;int d;int first;int last;struct asgment *subs;
  1646. X{
  1647. Xint done = 0;
  1648. Xchar *s,*hs;
  1649. XHistent ent;
  1650. X
  1651. X    if (r) {
  1652. X        r = last;
  1653. X        last = first;
  1654. X        first = r;
  1655. X    }
  1656. X    if (!subs) done = 1;
  1657. X    for (;;) {
  1658. X        hs = quietgetevent(first);
  1659. X        if (!hs) {
  1660. X            zerrnam("fc","no such event: %d",NULL,first);
  1661. X            return 1;
  1662. X        }
  1663. X        s = makehstr(hs);
  1664. X        done |= fcsubs(&s,subs);
  1665. X        if (n) fprintf(f,"%5d  ",first);
  1666. X        ent = NULL;
  1667. X        if (d) {
  1668. X            struct tm *ltm;
  1669. X            
  1670. X            if (!ent) ent = gethistent(first);
  1671. X            ltm = localtime(&ent->stim);
  1672. X            if (d >= 2) {
  1673. X                if (d >= 4) {
  1674. X                    fprintf(f,"%d.%d.%d ",
  1675. X                        ltm->tm_mday,ltm->tm_mon+1,
  1676. X                        ltm->tm_year+1900);
  1677. X                } else {
  1678. X                    fprintf(f,"%d/%d/%d ",
  1679. X                        ltm->tm_mon+1,
  1680. X                        ltm->tm_mday,
  1681. X                        ltm->tm_year+1900);
  1682. X        }
  1683. X            }
  1684. X            fprintf(f,"%02d:%02d  ",ltm->tm_hour, ltm->tm_min);
  1685. X        }
  1686. X        if (D) {
  1687. X            long diff;
  1688. X
  1689. X            if (!ent) ent = gethistent(first);
  1690. X            diff = (ent->ftim) ? ent->ftim-ent->stim : 0;
  1691. X            fprintf(f,"%d:%02d  ",diff/60,diff%60);
  1692. X        }
  1693. X        if (f == stdout) {
  1694. X            niceprintf(s,f);
  1695. X            putc('\n',f);
  1696. X        } else fprintf(f,"%s\n",s);
  1697. X        if (first == last) break;
  1698. X        else if (first > last) first--;
  1699. X        else first++;
  1700. X    }
  1701. X    if (f != stdout) fclose(f);
  1702. X    if (!done) {
  1703. X        zerrnam("fc","no substitutions performed",NULL,0);
  1704. X        return 1;
  1705. X    }
  1706. X    return 0;
  1707. X}
  1708. X
  1709. Xint fcedit(ename,fn) /**/
  1710. Xchar *ename;char *fn;
  1711. X{
  1712. X    if (!strcmp(ename,"-"))
  1713. X        return 1;
  1714. X    return !zyztem(ename,fn);
  1715. X}
  1716. X
  1717. X/* fc, history, r */
  1718. X
  1719. Xint bin_fc(nam,argv,ops,func) /**/
  1720. Xchar *nam;char **argv;char *ops;int func;
  1721. X{
  1722. Xint first = -1,last = -1,retval,delayrem,minflag = 0;
  1723. Xchar *s;
  1724. Xstruct asgment *asgf = NULL,*asgl = NULL;
  1725. X
  1726. X    if (!interact) {
  1727. X        zerrnam(nam,"not interactive shell",NULL,0);
  1728. X        return 1;
  1729. X    }
  1730. X    delayrem = !strcmp(nam,"r")
  1731. X          && argv[0]
  1732. X          &&(argv[1] || !strchr(argv[0],'='));
  1733. X    if (!delayrem && !(ops['l'] && unset(HISTNOSTORE))) remhist();
  1734. X    if (ops['R']) {
  1735. X        readhistfile(*argv ? *argv : getsparam("HISTFILE"),1);
  1736. X        return 0;
  1737. X    }
  1738. X    if (ops['W']) {
  1739. X        savehistfile(*argv ? *argv : getsparam("HISTFILE"),1,
  1740. X                 (ops['I'] ? 2 : 0));
  1741. X        return 0;
  1742. X    }
  1743. X    if (ops['A']) {
  1744. X        savehistfile(*argv ? *argv : getsparam("HISTFILE"),1,
  1745. X                 (ops['I'] ? 3 : 1));
  1746. X        return 0;
  1747. X    }
  1748. X    while (*argv && equalsplit(*argv,&s)) {
  1749. X        struct asgment *a = (struct asgment *) alloc(sizeof *a);
  1750. X
  1751. X        if (!asgf) asgf = asgl = a;
  1752. X        else {
  1753. X            asgl->next = a;
  1754. X            asgl = a;
  1755. X        }
  1756. X        a->name = *argv;
  1757. X        a->value = s;
  1758. X        argv++;
  1759. X    }
  1760. X    if (*argv) {
  1761. X        minflag = **argv == '-';
  1762. X        first = fcgetcomm(*argv);
  1763. X        if (first == -1) return 1;
  1764. X        argv++;
  1765. X    }
  1766. X    if (*argv) {
  1767. X        last = fcgetcomm(*argv);
  1768. X        if (last == -1) return 1;
  1769. X        argv++;
  1770. X    }
  1771. X    if (*argv) {
  1772. X        zerrnam("fc","too many arguments",NULL,0);
  1773. X        return 1;
  1774. X    }
  1775. X    if (delayrem) remhist();
  1776. X    if (first == -1) first = (ops['l']) ? curhist-16 : curhist;
  1777. X    if (last == -1) last = (ops['l']) ? curhist : first;
  1778. X    if (first < firsthist()) first = firsthist();
  1779. X    if (last == -1) last = (minflag) ? curhist : first;
  1780. X    if (ops['l'])
  1781. X        retval = fclist(stdout,!ops['n'],ops['r'],ops['D'],
  1782. X                ops['d'] + ops['f'] * 2 + ops['E'] * 4,
  1783. X            first,last,asgf);
  1784. X    else {
  1785. X        FILE *out;
  1786. X        char *fil = gettemp();
  1787. X
  1788. X        retval = 1;
  1789. X        out = fopen(fil,"w");
  1790. X        if (!out)
  1791. X            zerrnam("fc","can't open temp file: %e",NULL,errno);
  1792. X        else {
  1793. X            if (!fclist(out,0,ops['r'],0,0,first,last,asgf))
  1794. X                if (fcedit(auxdata ? auxdata : fceditparam,fil))
  1795. X                    if (stuff(fil))
  1796. X                        zerrnam("fc","%e: %s",s,errno);
  1797. X                    else
  1798. X                        retval = 0;
  1799. X        }
  1800. X        unlink(fil);
  1801. X    }
  1802. X    return retval;
  1803. X}
  1804. X
  1805. Xint bin_suspend(name,argv,ops,func) /**/
  1806. Xchar *name;char **argv;char *ops;int func;
  1807. X{
  1808. X    if (islogin && !ops['f']) {
  1809. X        zerrnam(name,"can't suspend login shell",NULL,0);
  1810. X        return 1;
  1811. X    }
  1812. X    if (jobbing) {
  1813. X        signal(SIGPIPE,SIG_DFL);
  1814. X        signal(SIGTTIN,SIG_DFL);
  1815. X        signal(SIGTSTP,SIG_DFL);
  1816. X        signal(SIGTTOU,SIG_DFL);
  1817. X    }
  1818. X    kill(0,SIGTSTP);
  1819. X    if (jobbing) {
  1820. X        while (gettygrp() != mypgrp) {
  1821. X            sleep(1);
  1822. X            if (gettygrp() != mypgrp) kill(0,SIGTTIN);
  1823. X        }
  1824. X        signal(SIGTTOU,SIG_IGN);
  1825. X        signal(SIGTSTP,SIG_IGN);
  1826. X        signal(SIGTTIN,SIG_IGN);
  1827. X        signal(SIGPIPE,SIG_IGN);
  1828. X    }
  1829. X    return 0;
  1830. X}
  1831. X
  1832. Xint bin_alias(name,argv,ops,func) /**/
  1833. Xchar *name;char **argv;char *ops;int func;
  1834. X{
  1835. Xstruct alias *an;
  1836. Xstruct asgment *asg;
  1837. Xint incm = !(ops['a'] || ops['g']),ret = 0;
  1838. X
  1839. X    showflag = !incm;
  1840. X    if (!*argv)
  1841. X        listhtable(aliastab,(HFunc) printalias);
  1842. X    else while (asg = getasg(*argv++))
  1843. X        {
  1844. X        if (asg->value)
  1845. X            addhnode(ztrdup(asg->name),mkanode(ztrdup(asg->value),incm),
  1846. X                aliastab,freeanode);
  1847. X        else if (an = (Alias) gethnode(asg->name,aliastab))
  1848. X            printalias(asg->name,an);
  1849. X        else
  1850. X            ret = 1;
  1851. X        }
  1852. X    return ret;
  1853. X}
  1854. X
  1855. X/* print an alias; used with listhtable */
  1856. X
  1857. Xvoid printalias(s,a) /**/
  1858. Xchar *s;struct alias *a;
  1859. X{
  1860. X    if (a->cmd >= 0 && !(showflag && a->cmd))
  1861. X        printf("%s=%s\n",s,a->text);
  1862. X}
  1863. X
  1864. X/* print a param; used with listhtable */
  1865. X
  1866. Xvoid printparam(s,p) /**/
  1867. Xchar *s;Param p;
  1868. X{
  1869. X    if (showflag > 0 && !(p->flags & showflag))
  1870. X        return;
  1871. X    if (!showflag)
  1872. X        {
  1873. X        int fgs = p->flags;
  1874. X
  1875. X        if (fgs & PMFLAG_i) printf("integer ");
  1876. X        if (fgs & PMFLAG_A) printf("array ");
  1877. X        if (fgs & PMFLAG_L) printf("left justified %d ",p->ct);
  1878. X        if (fgs & PMFLAG_R) printf("right justified %d ",p->ct);
  1879. X        if (fgs & PMFLAG_Z) printf("zero filled %d ",p->ct);
  1880. X        if (fgs & PMFLAG_l) printf("lowercase ");
  1881. X        if (fgs & PMFLAG_u) printf("uppercase ");
  1882. X        if (fgs & PMFLAG_r) printf("readonly ");
  1883. X        if (fgs & PMFLAG_t) printf("tagged ");
  1884. X        if (fgs & PMFLAG_x) printf("exported ");
  1885. X        }
  1886. X    if (showflag2)
  1887. X        printf("%s\n",s);
  1888. X    else
  1889. X        {
  1890. X        char *t,**u;
  1891. X
  1892. X        printf("%s=",s);
  1893. X        switch (p->flags & PMTYPE)
  1894. X            {
  1895. X            case PMFLAG_s:
  1896. X                if (p->gets.cfn && (t = p->gets.cfn(p)))
  1897. X                    puts(t);
  1898. X                else
  1899. X                    putchar('\n');
  1900. X                break;
  1901. X            case PMFLAG_i: printf("%ld\n",p->gets.ifn(p)); break;
  1902. X            case PMFLAG_A:
  1903. X                putchar('(');
  1904. X                u = p->gets.afn(p);
  1905. X                if (!*u)
  1906. X                    printf(")\n");
  1907. X                else
  1908. X                    {
  1909. X                    while (u[1])
  1910. X                        printf("%s ",*u++);
  1911. X                    printf("%s)\n",*u);
  1912. X                    }
  1913. X                break;
  1914. X            }
  1915. X        }
  1916. X}
  1917. X
  1918. X/* autoload, declare, export, functions, integer, local, readonly, typeset */
  1919. X
  1920. Xint bin_typeset(name,argv,ops,func) /**/
  1921. Xchar *name;char **argv;char *ops;int func;
  1922. X{
  1923. Xint on = 0,off = 0,roff,bit = 1,retcode = 0;
  1924. Xchar *optstr = "LRZilurtx";
  1925. Xstruct param *pm;
  1926. Xstruct asgment *asg;
  1927. X
  1928. X    for (; *optstr; optstr++,bit <<= 1)
  1929. X        if (ops[*optstr] == 1)
  1930. X            on |= bit;
  1931. X        else if (ops[*optstr] == 2)
  1932. X            off |= bit;
  1933. X    roff = off;
  1934. X    if (ops['f']) {
  1935. X        on &= PMFLAG_t|PMFLAG_u;
  1936. X        off &= PMFLAG_t|PMFLAG_u;
  1937. X        showflag = (ops['f'] == 1);
  1938. X        if (ops['@'] && ((off & ~PMFLAG_t) || (on & ~(PMFLAG_u|PMFLAG_t)))) {
  1939. X            zerrnam(name,"invalid option(s)",NULL,0);
  1940. X            return 1;
  1941. X        }
  1942. X        showflag2 = 0;
  1943. X        if (!*argv) {
  1944. X            showflag2 = off|on;
  1945. X            listhtable(cmdnamtab,(HFunc) pshfunc);
  1946. X        } else for (; *argv; argv++) {
  1947. X            Cmdnam cc;
  1948. X
  1949. X            if ((cc = (Cmdnam) gethnode(*argv,cmdnamtab)) && cc->type == SHFUNC)
  1950. X                if (on|off) cc->flags = (cc->flags | on) & (~off);
  1951. X                else pshfunc(*argv,cc);
  1952. X            else if (on & PMFLAG_u) {
  1953. X                cc = (Cmdnam) zcalloc(sizeof *cc);
  1954. X                cc->type = SHFUNC;
  1955. X                cc->flags = on;
  1956. X                addhnode(ztrdup(*argv),cc,cmdnamtab,freecmdnam);
  1957. X            } else
  1958. X                retcode = 1;
  1959. X        }
  1960. X        return retcode;
  1961. X    }
  1962. X    if (on & PMFLAG_L)
  1963. X        off |= PMFLAG_R;
  1964. X    if (on & PMFLAG_R)
  1965. X        off |= PMFLAG_L;
  1966. X    if (on & PMFLAG_u)
  1967. X        off |= PMFLAG_l;
  1968. X    if (on & PMFLAG_l)
  1969. X        off |= PMFLAG_u;
  1970. X    on &= ~off;
  1971. X    showflag = showflag2 = 0;
  1972. X    if (!*argv) {
  1973. X        showflag = on|off;
  1974. X        showflag2 = roff;
  1975. X        listhtable(paramtab,(HFunc) printparam);
  1976. X    } else while (asg = getasg(*argv++)) {
  1977. X        if (asg->value && *asg->value == '~') {
  1978. X            *asg->value = Tilde;
  1979. X            singsub(&asg->value);
  1980. X        }
  1981. X        pm = (Param) gethnode(asg->name,paramtab);
  1982. X        if (pm) {
  1983. X            if (!on && !roff && !asg->value) {
  1984. X                printparam(asg->name,pm);
  1985. X                continue;
  1986. X            }
  1987. X            pm->flags = (pm->flags | on) & ~off;
  1988. X            if ((on & (PMFLAG_L | PMFLAG_R | PMFLAG_Z | PMFLAG_i)) 
  1989. X                    && (pmtype(pm) != PMFLAG_A))
  1990. X                pm->ct = auxlen;
  1991. X            if (pmtype(pm) != PMFLAG_A) {
  1992. X                if (pm->flags & PMFLAG_x) {
  1993. X                    if (!pm->env)
  1994. X                        pm->env = addenv(asg->name,
  1995. X                            (asg->value) ? asg->value : getsparam(asg->name));
  1996. X                } else if (pm->env) {
  1997. X                    delenv(pm->env);
  1998. X                    free(pm->env);
  1999. X                    pm->env = NULL;
  2000. X                }
  2001. X                if (asg->value)
  2002. X                    setsparam(asg->name,ztrdup(asg->value));
  2003. X            }
  2004. X        } else {
  2005. X            if (locallist && !(on & PMFLAG_x)) {
  2006. X                permalloc();
  2007. X                addnode(locallist,ztrdup(asg->name));
  2008. X                heapalloc();
  2009. X            }
  2010. X            createparam(ztrdup(asg->name),
  2011. X                ztrdup((asg->value) ? asg->value : ""),on);
  2012. X            pm = (Param) gethnode(asg->name,paramtab);
  2013. X            pm->ct = auxlen;
  2014. X        }
  2015. X    }
  2016. X    return 0;
  2017. X}
  2018. X
  2019. X/* convert s with escape sequences */
  2020. X
  2021. Xchar *escsubst(s,nnl) /**/
  2022. Xchar *s; int *nnl;
  2023. X{
  2024. Xchar *t = alloc(strlen(s)+1),*ret = t;
  2025. X
  2026. X    for (; *s; s++)
  2027. X        if (*s == '\\' && s[1])
  2028. X            switch (*++s) {
  2029. X                case 'b': *t++ = '\b'; break;
  2030. X                case 'c': *nnl |= 1; break;
  2031. X                case 'e': *t++ = '\033'; break;
  2032. X                case 'f': *t++ = '\f'; break;
  2033. X                case 'n': *t++ = '\n'; break;
  2034. X                case 'r': *t++ = '\r'; break;
  2035. X                case 't': *t++ = '\t'; break;
  2036. X                case 'v': *t++ = '\v'; break;
  2037. X                case '\\': *t++ = '\\'; break;
  2038. X                case '0': *t++ = zstrtol(s,&s,8); s--; break;
  2039. X                default: *t++ = '\\'; *t++ = *s; break;
  2040. X            }
  2041. X        else *t++ = *s;
  2042. X    *t = '\0';
  2043. X    return ret;
  2044. X}
  2045. X
  2046. X/* echo, print, pushln */
  2047. X
  2048. Xint bin_print(name,args,ops,func) /**/
  2049. Xchar *name;char **args;char *ops;int func;
  2050. X{
  2051. Xint nnl = 0, fd;
  2052. XHistent ent;
  2053. XFILE *fout = stdout;
  2054. X
  2055. X    if (ops['z']) {
  2056. X        permalloc();
  2057. X        pushnode(bufstack,ztrdup(spacejoin(args)));
  2058. X        heapalloc();
  2059. X        return 0;
  2060. X    }
  2061. X    if (ops['s']) {
  2062. X        permalloc();
  2063. X        ent = gethistent(++curhist);
  2064. X        ent->lex = ztrdup(join(args,HISTSPACE));
  2065. X        ent->lit = ztrdup(join(args,' '));
  2066. X        ent->stim = ent->ftim = time(NULL);
  2067. X        ent->flags = 0;
  2068. X        heapalloc();
  2069. X        return 0;
  2070. X    }
  2071. X    if (ops['R'])
  2072. X        ops['r'] = 1;
  2073. X    if (ops['u'] || ops['p']) {
  2074. X        if (ops['u']) {
  2075. X            for (fd = 0; fd < 10; fd++) if (ops[fd+'0']) break;
  2076. X            if (fd == 10) fd = 0;
  2077. X        } else fd = coprocout;
  2078. X        if ((fd = dup(fd)) < 0) {
  2079. X            zerrnam(name,"bad file number",NULL,0);
  2080. X            return 1;
  2081. X        }
  2082. X        if ((fout = fdopen(fd,"w")) == 0) {
  2083. X            zerrnam(name,"bad mode on fd",NULL,0);
  2084. X            return 1;
  2085. X        }
  2086. X    }
  2087. X    for (; *args; args++) {
  2088. X        if (!ops['r']) *args = escsubst(*args,&nnl);
  2089. X        if (ops['D']) fprintdir(*args,fout);
  2090. X        else if (ops['P']) {
  2091. X            int junk;
  2092. X            fputs(putprompt(*args,&junk,0),fout);
  2093. X        } else fputs(*args,fout);
  2094. X        if (args[1]) fputc(ops['l'] ? '\n' : ops['0'] ? '\0' : ' ',fout);
  2095. X    }
  2096. X    if (!(ops['n'] || nnl)) fputc(ops['N'] ? '\0' : '\n',fout);
  2097. X    if (fout != stdout) fclose(fout);
  2098. X    return 0;
  2099. X}
  2100. X
  2101. Xint bin_dirs(name,argv,ops,func) /**/
  2102. Xchar *name;char **argv;char *ops;int func;
  2103. X{
  2104. XLklist l;
  2105. X
  2106. X    if (ops['v'])
  2107. X        {
  2108. X        Lknode node;
  2109. X        int t0 = 1;
  2110. X
  2111. X        printf("0\t");
  2112. X        printdir(pwd);
  2113. X        for (node = firstnode(dirstack); node; incnode(node))
  2114. X            {
  2115. X            printf("\n%d\t",t0++);
  2116. X            printdir(getdata(node));
  2117. X            }
  2118. X        putchar('\n');
  2119. X        return 0;
  2120. X        }
  2121. X    if (!*argv)
  2122. X        {
  2123. X        pdstack();
  2124. X        return 0;
  2125. X        }
  2126. X    permalloc();
  2127. X    l = newlist();
  2128. X    if (!*argv)
  2129. X        {
  2130. X        heapalloc();
  2131. X        return 0;
  2132. X        }
  2133. X    while (*argv)
  2134. X        addnode(l,ztrdup(*argv++));
  2135. X    freetable(dirstack,freestr);
  2136. X    dirstack = l;
  2137. X    heapalloc();
  2138. X    return 0;
  2139. X}
  2140. X
  2141. Xint bin_unalias(name,argv,ops,func) /**/
  2142. Xchar *name;char **argv;char *ops;int func;
  2143. X{
  2144. Xint ret = 0;
  2145. Xvptr dat;
  2146. X
  2147. X    while (*argv)
  2148. X        {
  2149. X        if (dat = remhnode(*argv++,aliastab))
  2150. X            freeanode(dat);
  2151. X        else
  2152. X            ret = 1;
  2153. X        }
  2154. X    return ret;
  2155. X}
  2156. X
  2157. Xint bin_disable(name,argv,ops,func) /**/
  2158. Xchar *name;char **argv;char *ops;int func;
  2159. X{
  2160. XCmdnam chn;
  2161. X
  2162. X    while (*argv) {
  2163. X        if (!strncmp(*argv,"TRAP",4))
  2164. X            unsettrap(getsignum(*argv+4));
  2165. X        chn = zalloc(sizeof *chn);
  2166. X        chn->type = DISABLED;
  2167. X        addhnode(ztrdup(*argv++),chn,cmdnamtab,freecmdnam);
  2168. X    }
  2169. X    return 0;
  2170. X}
  2171. X
  2172. Xint bin_unhash(name,argv,ops,func) /**/
  2173. Xchar *name;char **argv;char *ops;int func;
  2174. X{
  2175. Xvptr dat;
  2176. X
  2177. X    while (*argv) {
  2178. X        if (!strncmp(*argv,"TRAP",4)) unsettrap(getsignum(*argv+4));
  2179. X        if (dat = remhnode(*argv++,cmdnamtab)) freecmdnam(dat);
  2180. X    }
  2181. X    return 0;
  2182. X}
  2183. X
  2184. Xint bin_unset(name,argv,ops,func) /**/
  2185. Xchar *name;char **argv;char *ops;int func;
  2186. X{
  2187. Xint retval = 0;
  2188. Xchar *s;
  2189. X
  2190. X    while (s = *argv++)
  2191. X        if (gethnode(s,paramtab))
  2192. X            unsetparam(s);
  2193. X        else
  2194. X            retval = 1;
  2195. X    return retval;
  2196. X}
  2197. X
  2198. Xstatic char *zbuf;
  2199. Xstatic int readfd;
  2200. X
  2201. Xint zread() /**/
  2202. X{
  2203. Xchar cc;
  2204. X
  2205. X    if (zbuf)
  2206. X        return (*zbuf) ? *zbuf++ : EOF;
  2207. X    if (read(readfd,&cc,1) != 1)
  2208. X        return EOF;
  2209. X    return cc;
  2210. X}
  2211. X
  2212. Xint bin_read(name,args,ops,func) /**/
  2213. Xchar *name;char **args;char *ops;int func;
  2214. X{
  2215. Xchar *reply,*pmpt;
  2216. Xint bsiz,c = 0,gotnl = 0;
  2217. Xchar *buf,*bptr;
  2218. X
  2219. X    reply = (*args) ? *args++ : "REPLY";
  2220. X    if (ops['u'] && !ops['p']) {
  2221. X        for (readfd = 0; readfd < 10; ++readfd) if (ops[readfd+'0']) break;
  2222. X        if (readfd == 10) readfd = 0;
  2223. X    } else if (ops['p']) readfd = coprocin;
  2224. X    else {
  2225. X        attachtty((jobtab[thisjob].gleader) ? jobtab[thisjob].gleader : mypgrp);
  2226. X        readfd = 0;
  2227. X        if (isatty(0)) {
  2228. X            for (pmpt = reply; *pmpt && *pmpt != '?'; pmpt++);
  2229. X            if (*pmpt++) {
  2230. X                write(2,pmpt,strlen(pmpt));
  2231. X                pmpt[-1] = '\0';
  2232. X            }
  2233. X        }
  2234. X#if 0
  2235. X        else if (isset(SHINSTDIN) && unset(INTERACTIVE)) {
  2236. X            if (isatty(1)) readfd = 1;
  2237. X            else if (isatty(2)) readfd = 2;
  2238. X        }
  2239. X#endif
  2240. X    }
  2241. X    zbuf = (!ops['z']) ? NULL :
  2242. X        (full(bufstack)) ? (char *) getnode(bufstack) : NULL;
  2243. X    while (*args) {
  2244. X        buf = bptr = zalloc(bsiz = 64);
  2245. X        for(;;) {
  2246. X            if (gotnl) break;
  2247. X            c = zread();
  2248. X            if (!ops['r'] && c == '\n' && bptr != buf && bptr[-1] == '\\') {
  2249. X                bptr--;
  2250. X                continue;
  2251. X            }
  2252. X            if (c == EOF || (isep(c) && bptr != buf) || c == '\n') break;
  2253. X            if (isep(c)) continue;
  2254. X            *bptr++ = c;
  2255. X            if (bptr == buf+bsiz) {
  2256. X                buf = realloc(buf,bsiz *= 2);
  2257. X                bptr = buf+(bsiz/2);
  2258. X            }
  2259. X        }
  2260. X        if (c == EOF) {
  2261. X            if (readfd == coprocin) {
  2262. X                close(coprocin);
  2263. X                close(coprocout);
  2264. X                coprocin = coprocout = -1;
  2265. X            }
  2266. X            return 1;
  2267. X        }
  2268. X        if (c == '\n') gotnl = 1;
  2269. X        *bptr = '\0';
  2270. X        setsparam(reply,buf);
  2271. X        reply = *args++;
  2272. X    }
  2273. X    buf = bptr = zalloc(bsiz = 64);
  2274. X    if (!gotnl)
  2275. X        for (;;) {
  2276. X            c = zread();
  2277. X            if (!ops['r'] && c == '\n' && bptr != buf && bptr[-1] == '\\') {
  2278. X                bptr--;
  2279. X                continue;
  2280. X            }
  2281. X            if (c == EOF || (c == '\n' && !zbuf)) break;
  2282. X            if (isep(c) && bptr == buf) continue;
  2283. X            *bptr++ = c;
  2284. X            if (bptr == buf+bsiz) {
  2285. X                buf = realloc(buf,bsiz *= 2);
  2286. X                bptr = buf+(bsiz/2);
  2287. X            }
  2288. X        }
  2289. X    while(bptr > buf && isep(bptr[-1])) bptr--;
  2290. X    *bptr = '\0';
  2291. X    setsparam(reply,buf);
  2292. X    if (c == EOF) {
  2293. X        if (readfd == coprocin) {
  2294. X            close(coprocin);
  2295. X            close(coprocout);
  2296. X            coprocin = coprocout = -1;
  2297. X        }
  2298. X        return 1;
  2299. X    }
  2300. X    return 0;
  2301. X}
  2302. X
  2303. Xint bin_vared(name,args,ops,func) /**/
  2304. Xchar *name;char **args;char *ops;int func;
  2305. X{
  2306. END_OF_FILE
  2307.   if test 49195 -ne `wc -c <'src/builtin.c.01'`; then
  2308.     echo shar: \"'src/builtin.c.01'\" unpacked with wrong size!
  2309.   fi
  2310.   # end of 'src/builtin.c.01'
  2311. fi
  2312. if test -f 'src/config.h.sample' -a "${1}" != "-c" ; then 
  2313.   echo shar: Will not clobber existing file \"'src/config.h.sample'\"
  2314. else
  2315.   echo shar: Extracting \"'src/config.h.sample'\" \(2966 characters\)
  2316.   sed "s/^X//" >'src/config.h.sample' <<'END_OF_FILE'
  2317. X/* this file is created automatically by buildzsh */
  2318. X
  2319. X/* define this if you are sysvish */
  2320. X/* #define SYSV */
  2321. X
  2322. X#define TERMIOS
  2323. X/* #define TTY_NEEDS_DRAINING */
  2324. X/* #define CLOBBERS_TYPEAHEAD */
  2325. X
  2326. X#define HAS_DIRENT
  2327. X
  2328. X#define HAS_UNISTD
  2329. X
  2330. X#define HAS_STDLIB
  2331. X
  2332. X#define HAS_STRING
  2333. X
  2334. X#define HAS_MEMORY
  2335. X
  2336. X#define HAS_LOCALE
  2337. X
  2338. X/*#define HAS_UTMPX*/
  2339. X
  2340. X#define UTMP_HOST
  2341. X
  2342. X/*#define HAS_TIME*/
  2343. X
  2344. X/*#define HAS_WAIT*/
  2345. X
  2346. X/* define this if you have WAITPID */
  2347. X#define WAITPID
  2348. X
  2349. X/* define this if you have SELECT */
  2350. X#define HAS_SELECT
  2351. X
  2352. X/* define this if you have <sys/select.h> */
  2353. X/* #define HAS_SYS_SELECT */
  2354. X
  2355. X/* we can't just test for S_IFIFO or check to see if the mknod worked,
  2356. X   because the NeXTs sold by a vendor which will remain nameless will
  2357. X   happily create the FIFO for you, and then panic when you try to do
  2358. X    something weird with them, because they aren't supported by the OS. */
  2359. X
  2360. X/* #define NO_FIFOS */
  2361. X
  2362. X/* define this if you have strftime() */
  2363. X#define HAS_STRFTIME
  2364. X
  2365. X#define HAS_TCSETPGRP
  2366. X
  2367. X#define HAS_TCCRAP
  2368. X
  2369. X#define HAS_SETPGID
  2370. X
  2371. X/* #define HAS_SIGRELSE */
  2372. X
  2373. X/* define this if you have RFS */
  2374. X/* #define HAS_RFS */
  2375. X
  2376. X/* define this if you have a working getrusage and wait3 */
  2377. X#define HAS_RUSAGE
  2378. X/* define this if you use NIS for your passwd map */
  2379. X#define HAS_NIS_PASSWD
  2380. X
  2381. X/* define this if your signal handlers return void */
  2382. X#define SIGVOID
  2383. X#ifdef sgi
  2384. X#undef SIGVOID
  2385. X#endif
  2386. X
  2387. X/* define this if signal handlers need to be reset each time */
  2388. X/* #define RESETHANDNEEDED */
  2389. X
  2390. X#ifdef SIGVOID
  2391. X#define HANDTYPE void
  2392. X#else
  2393. X#define HANDTYPE int
  2394. X#define INTHANDTYPE
  2395. X#endif
  2396. X
  2397. X/* a string corresponding to the host type */
  2398. X#define HOSTTYPE "sun4"
  2399. X
  2400. X/* the default editor for the fc builtin */
  2401. X#define DEFFCEDIT "vi"
  2402. X
  2403. X/* the path of wtmp */
  2404. X#define WTMP_FILE "/var/adm/wtmp"
  2405. X
  2406. X/* the path of utmp */
  2407. X#define UTMP_FILE "/etc/utmp"
  2408. X
  2409. X/* default prefix for temporary files */
  2410. X#define DEFTMPPREFIX "/tmp/zsh"
  2411. X
  2412. X/* define if you prefer "suspended" to "stopped" */
  2413. X#define USE_SUSPENDED
  2414. X
  2415. X/* the file to source absolutely first whenever zsh is run; if undefined,
  2416. X      don't source anything */
  2417. X#define GLOBALZSHENV "/etc/zshenv"
  2418. X
  2419. X/* the file to source whenever zsh is run; if undefined, don't source
  2420. X    anything */
  2421. X#define GLOBALZSHRC "/etc/zshrc"
  2422. X
  2423. X/* the file to source whenever zsh is run as a login shell; if
  2424. X    undefined, don't source anything */
  2425. X#define GLOBALZLOGIN "/etc/zlogin"
  2426. X
  2427. X/* the file to source whenever zsh is run as a login shell, before
  2428. X    zshrc is read; if undefined, don't source anything */
  2429. X#define GLOBALZPROFILE "/etc/zprofile"
  2430. X
  2431. X/* the default HISTSIZE */
  2432. X#define DEFAULT_HISTSIZE 30
  2433. X
  2434. X#define _BSD_SIGNALS   /* this could be an iris, you never know */
  2435. X#define _BSD           /* this could be HP-UX, you never know */
  2436. X#define _BSD_INCLUDES  /* this could be AIX, you never know */
  2437. X#define _BBN_POSIX_SUPPORT    /* this could be nX, you never know */
  2438. X
  2439. X/* if your compiler doesn't like void *, change this to char *
  2440. X    and ignore all the warnings.
  2441. X*/
  2442. X
  2443. Xtypedef void *vptr;
  2444. X
  2445. X#define JOB_CONTROL
  2446. END_OF_FILE
  2447.   if test 2966 -ne `wc -c <'src/config.h.sample'`; then
  2448.     echo shar: \"'src/config.h.sample'\" unpacked with wrong size!
  2449.   fi
  2450.   # end of 'src/config.h.sample'
  2451. fi
  2452. echo shar: End of archive 8 \(of 22\).
  2453. cp /dev/null ark8isdone
  2454. MISSING=""
  2455. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
  2456.     if test ! -f ark${I}isdone ; then
  2457.     MISSING="${MISSING} ${I}"
  2458.     fi
  2459. done
  2460. if test "${MISSING}" = "" ; then
  2461.     echo You have unpacked all 22 archives.
  2462.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2463. else
  2464.     echo You still must unpack the following archives:
  2465.     echo "        " ${MISSING}
  2466. fi
  2467. exit 0
  2468.  
  2469. exit 0 # Just in case...
  2470.