home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume20 / perl3.0 / part07 < prev    next >
Encoding:
Internet Message Format  |  1989-10-30  |  49.1 KB

  1. Subject:  v20i090:  Perl, a language with features of C/sed/awk/shell/etc, Part07/24
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
  7. Posting-number: Volume 20, Issue 90
  8. Archive-name: perl3.0/part07
  9.  
  10. #! /bin/sh
  11.  
  12. # Make a new directory for the perl sources, cd to it, and run kits 1
  13. # thru 24 through sh.  When all 24 kits have been run, read README.
  14.  
  15. echo "This is perl 3.0 kit 7 (of 24).  If kit 7 is complete, the line"
  16. echo '"'"End of kit 7 (of 24)"'" will echo at the end.'
  17. echo ""
  18. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  19. mkdir  2>/dev/null
  20. echo Extracting doio.c
  21. sed >doio.c <<'!STUFFY!FUNK!' -e 's/X//'
  22. X/* $Header: doio.c,v 3.0 89/10/18 15:10:54 lwall Locked $
  23. X *
  24. X *    Copyright (c) 1989, Larry Wall
  25. X *
  26. X *    You may distribute under the terms of the GNU General Public License
  27. X *    as specified in the README file that comes with the perl 3.0 kit.
  28. X *
  29. X * $Log:    doio.c,v $
  30. X * Revision 3.0  89/10/18  15:10:54  lwall
  31. X * 3.0 baseline
  32. X * 
  33. X */
  34. X
  35. X#include "EXTERN.h"
  36. X#include "perl.h"
  37. X
  38. X#ifdef SOCKET
  39. X#include <sys/socket.h>
  40. X#include <netdb.h>
  41. X#endif
  42. X
  43. X#include <errno.h>
  44. X#ifdef I_PWD
  45. X#include <pwd.h>
  46. X#endif
  47. X#ifdef I_GRP
  48. X#include <grp.h>
  49. X#endif
  50. X
  51. Xextern int errno;
  52. X
  53. Xbool
  54. Xdo_open(stab,name)
  55. XSTAB *stab;
  56. Xregister char *name;
  57. X{
  58. X    FILE *fp;
  59. X    int len = strlen(name);
  60. X    register STIO *stio = stab_io(stab);
  61. X    char *myname = savestr(name);
  62. X    int result;
  63. X    int fd;
  64. X    int writing = 0;
  65. X    char mode[3];        /* stdio file mode ("r\0" or "r+\0") */
  66. X
  67. X    name = myname;
  68. X    forkprocess = 1;        /* assume true if no fork */
  69. X    while (len && isspace(name[len-1]))
  70. X    name[--len] = '\0';
  71. X    if (!stio)
  72. X    stio = stab_io(stab) = stio_new();
  73. X    else if (stio->ifp) {
  74. X    fd = fileno(stio->ifp);
  75. X    if (stio->type == '|')
  76. X        result = mypclose(stio->ifp);
  77. X    else if (stio->ifp != stio->ofp) {
  78. X        if (stio->ofp)
  79. X        fclose(stio->ofp);
  80. X        result = fclose(stio->ifp);
  81. X    }
  82. X    else if (stio->type != '-')
  83. X        result = fclose(stio->ifp);
  84. X    else
  85. X        result = 0;
  86. X    if (result == EOF && fd > 2)
  87. X        fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
  88. X          stab_name(stab));
  89. X    stio->ofp = stio->ifp = Nullfp;
  90. X    }
  91. X    if (*name == '+' && len > 1 && name[len-1] != '|') {    /* scary */
  92. X    mode[1] = *name++;
  93. X    mode[2] = '\0';
  94. X    --len;
  95. X    writing = 1;
  96. X    }
  97. X    else  {
  98. X    mode[1] = '\0';
  99. X    }
  100. X    stio->type = *name;
  101. X    if (*name == '|') {
  102. X    for (name++; isspace(*name); name++) ;
  103. X#ifdef TAINT
  104. X    taintenv();
  105. X    taintproper("Insecure dependency in piped open");
  106. X#endif
  107. X    fp = mypopen(name,"w");
  108. X    writing = 1;
  109. X    }
  110. X    else if (*name == '>' && name[1] == '>') {
  111. X#ifdef TAINT
  112. X    taintproper("Insecure dependency in open");
  113. X#endif
  114. X    mode[0] = stio->type = 'a';
  115. X    for (name += 2; isspace(*name); name++) ;
  116. X    fp = fopen(name, mode);
  117. X    writing = 1;
  118. X    }
  119. X    else if (*name == '>' && name[1] == '&') {
  120. X#ifdef TAINT
  121. X    taintproper("Insecure dependency in open");
  122. X#endif
  123. X    for (name += 2; isspace(*name); name++) ;
  124. X    if (isdigit(*name))
  125. X        fd = atoi(name);
  126. X    else {
  127. X        stab = stabent(name,FALSE);
  128. X        if (stab_io(stab) && stab_io(stab)->ifp) {
  129. X        fd = fileno(stab_io(stab)->ifp);
  130. X        stio->type = stab_io(stab)->type;
  131. X        }
  132. X        else
  133. X        fd = -1;
  134. X    }
  135. X    fp = fdopen(dup(fd),stio->type == 'a' ? "a" :
  136. X      (stio->type == '<' ? "r" : "w") );
  137. X    writing = 1;
  138. X    }
  139. X    else if (*name == '>') {
  140. X#ifdef TAINT
  141. X    taintproper("Insecure dependency in open");
  142. X#endif
  143. X    for (name++; isspace(*name); name++) ;
  144. X    if (strEQ(name,"-")) {
  145. X        fp = stdout;
  146. X        stio->type = '-';
  147. X    }
  148. X    else  {
  149. X        mode[0] = 'w';
  150. X        fp = fopen(name,mode);
  151. X    }
  152. X    writing = 1;
  153. X    }
  154. X    else {
  155. X    if (*name == '<') {
  156. X        for (name++; isspace(*name); name++) ;
  157. X        if (strEQ(name,"-")) {
  158. X        fp = stdin;
  159. X        stio->type = '-';
  160. X        }
  161. X        else  {
  162. X        mode[0] = 'r';
  163. X        fp = fopen(name,mode);
  164. X        }
  165. X    }
  166. X    else if (name[len-1] == '|') {
  167. X#ifdef TAINT
  168. X        taintenv();
  169. X        taintproper("Insecure dependency in piped open");
  170. X#endif
  171. X        name[--len] = '\0';
  172. X        while (len && isspace(name[len-1]))
  173. X        name[--len] = '\0';
  174. X        for (; isspace(*name); name++) ;
  175. X        fp = mypopen(name,"r");
  176. X        stio->type = '|';
  177. X    }
  178. X    else {
  179. X        stio->type = '<';
  180. X        for (; isspace(*name); name++) ;
  181. X        if (strEQ(name,"-")) {
  182. X        fp = stdin;
  183. X        stio->type = '-';
  184. X        }
  185. X        else
  186. X        fp = fopen(name,"r");
  187. X    }
  188. X    }
  189. X    Safefree(myname);
  190. X    if (!fp)
  191. X    return FALSE;
  192. X    if (stio->type &&
  193. X      stio->type != '|' && stio->type != '-') {
  194. X    if (fstat(fileno(fp),&statbuf) < 0) {
  195. X        (void)fclose(fp);
  196. X        return FALSE;
  197. X    }
  198. X    if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
  199. X#ifdef S_IFSOCK
  200. X        (statbuf.st_mode & S_IFMT) != S_IFSOCK &&
  201. X#endif
  202. X#ifdef S_IFFIFO
  203. X        (statbuf.st_mode & S_IFMT) != S_IFFIFO &&
  204. X#endif
  205. X        (statbuf.st_mode & S_IFMT) != S_IFCHR) {
  206. X        (void)fclose(fp);
  207. X        return FALSE;
  208. X    }
  209. X    }
  210. X    stio->ifp = fp;
  211. X    if (writing)
  212. X    stio->ofp = fp;
  213. X    return TRUE;
  214. X}
  215. X
  216. XFILE *
  217. Xnextargv(stab)
  218. Xregister STAB *stab;
  219. X{
  220. X    register STR *str;
  221. X    char *oldname;
  222. X    int filemode,fileuid,filegid;
  223. X
  224. X    while (alen(stab_xarray(stab)) >= 0) {
  225. X    str = ashift(stab_xarray(stab));
  226. X    str_sset(stab_val(stab),str);
  227. X    STABSET(stab_val(stab));
  228. X    oldname = str_get(stab_val(stab));
  229. X    if (do_open(stab,oldname)) {
  230. X        if (inplace) {
  231. X#ifdef TAINT
  232. X        taintproper("Insecure dependency in inplace open");
  233. X#endif
  234. X        filemode = statbuf.st_mode;
  235. X        fileuid = statbuf.st_uid;
  236. X        filegid = statbuf.st_gid;
  237. X        if (*inplace) {
  238. X            str_cat(str,inplace);
  239. X#ifdef RENAME
  240. X            (void)rename(oldname,str->str_ptr);
  241. X#else
  242. X            (void)UNLINK(str->str_ptr);
  243. X            (void)link(oldname,str->str_ptr);
  244. X            (void)UNLINK(oldname);
  245. X#endif
  246. X        }
  247. X        else {
  248. X            (void)UNLINK(oldname);
  249. X        }
  250. X
  251. X        str_nset(str,">",1);
  252. X        str_cat(str,oldname);
  253. X        errno = 0;        /* in case sprintf set errno */
  254. X        if (!do_open(argvoutstab,str->str_ptr))
  255. X            fatal("Can't do inplace edit");
  256. X        defoutstab = argvoutstab;
  257. X#ifdef FCHMOD
  258. X        (void)fchmod(fileno(stab_io(argvoutstab)->ifp),filemode);
  259. X#else
  260. X        (void)chmod(oldname,filemode);
  261. X#endif
  262. X#ifdef FCHOWN
  263. X        (void)fchown(fileno(stab_io(argvoutstab)->ifp),fileuid,filegid);
  264. X#else
  265. X        (void)chown(oldname,fileuid,filegid);
  266. X#endif
  267. X        }
  268. X        str_free(str);
  269. X        return stab_io(stab)->ifp;
  270. X    }
  271. X    else
  272. X        fprintf(stderr,"Can't open %s\n",str_get(str));
  273. X    str_free(str);
  274. X    }
  275. X    if (inplace) {
  276. X    (void)do_close(argvoutstab,FALSE);
  277. X    defoutstab = stabent("STDOUT",TRUE);
  278. X    }
  279. X    return Nullfp;
  280. X}
  281. X
  282. Xbool
  283. Xdo_close(stab,explicit)
  284. XSTAB *stab;
  285. Xbool explicit;
  286. X{
  287. X    bool retval = FALSE;
  288. X    register STIO *stio = stab_io(stab);
  289. X    int status;
  290. X
  291. X    if (!stio) {        /* never opened */
  292. X    if (dowarn && explicit)
  293. X        warn("Close on unopened file <%s>",stab_name(stab));
  294. X    return FALSE;
  295. X    }
  296. X    if (stio->ifp) {
  297. X    if (stio->type == '|') {
  298. X        status = mypclose(stio->ifp);
  299. X        retval = (status >= 0);
  300. X        statusvalue = (unsigned)status & 0xffff;
  301. X    }
  302. X    else if (stio->type == '-')
  303. X        retval = TRUE;
  304. X    else {
  305. X        if (stio->ofp && stio->ofp != stio->ifp)        /* a socket */
  306. X        fclose(stio->ofp);
  307. X        retval = (fclose(stio->ifp) != EOF);
  308. X    }
  309. X    stio->ofp = stio->ifp = Nullfp;
  310. X    }
  311. X    if (explicit)
  312. X    stio->lines = 0;
  313. X    stio->type = ' ';
  314. X    return retval;
  315. X}
  316. X
  317. Xbool
  318. Xdo_eof(stab)
  319. XSTAB *stab;
  320. X{
  321. X    register STIO *stio;
  322. X    int ch;
  323. X
  324. X    if (!stab) {            /* eof() */
  325. X    if (argvstab)
  326. X        stio = stab_io(argvstab);
  327. X    else
  328. X        return TRUE;
  329. X    }
  330. X    else
  331. X    stio = stab_io(stab);
  332. X
  333. X    if (!stio)
  334. X    return TRUE;
  335. X
  336. X    while (stio->ifp) {
  337. X
  338. X#ifdef STDSTDIO            /* (the code works without this) */
  339. X    if (stio->ifp->_cnt > 0)    /* cheat a little, since */
  340. X        return FALSE;        /* this is the most usual case */
  341. X#endif
  342. X
  343. X    ch = getc(stio->ifp);
  344. X    if (ch != EOF) {
  345. X        (void)ungetc(ch, stio->ifp);
  346. X        return FALSE;
  347. X    }
  348. X    if (!stab) {            /* not necessarily a real EOF yet? */
  349. X        if (!nextargv(argvstab))    /* get another fp handy */
  350. X        return TRUE;
  351. X    }
  352. X    else
  353. X        return TRUE;        /* normal fp, definitely end of file */
  354. X    }
  355. X    return TRUE;
  356. X}
  357. X
  358. Xlong
  359. Xdo_tell(stab)
  360. XSTAB *stab;
  361. X{
  362. X    register STIO *stio;
  363. X
  364. X    if (!stab)
  365. X    goto phooey;
  366. X
  367. X    stio = stab_io(stab);
  368. X    if (!stio || !stio->ifp)
  369. X    goto phooey;
  370. X
  371. X    if (feof(stio->ifp))
  372. X    (void)fseek (stio->ifp, 0L, 2);        /* ultrix 1.2 workaround */
  373. X
  374. X    return ftell(stio->ifp);
  375. X
  376. Xphooey:
  377. X    if (dowarn)
  378. X    warn("tell() on unopened file");
  379. X    return -1L;
  380. X}
  381. X
  382. Xbool
  383. Xdo_seek(stab, pos, whence)
  384. XSTAB *stab;
  385. Xlong pos;
  386. Xint whence;
  387. X{
  388. X    register STIO *stio;
  389. X
  390. X    if (!stab)
  391. X    goto nuts;
  392. X
  393. X    stio = stab_io(stab);
  394. X    if (!stio || !stio->ifp)
  395. X    goto nuts;
  396. X
  397. X    if (feof(stio->ifp))
  398. X    (void)fseek (stio->ifp, 0L, 2);        /* ultrix 1.2 workaround */
  399. X
  400. X    return fseek(stio->ifp, pos, whence) >= 0;
  401. X
  402. Xnuts:
  403. X    if (dowarn)
  404. X    warn("seek() on unopened file");
  405. X    return FALSE;
  406. X}
  407. X
  408. Xint
  409. Xdo_ctl(optype,stab,func,argstr)
  410. Xint optype;
  411. XSTAB *stab;
  412. Xint func;
  413. XSTR *argstr;
  414. X{
  415. X    register STIO *stio;
  416. X    register char *s;
  417. X    int retval;
  418. X
  419. X    if (!stab || !argstr)
  420. X    return -1;
  421. X    stio = stab_io(stab);
  422. X    if (!stio)
  423. X    return -1;
  424. X
  425. X    if (argstr->str_pok || !argstr->str_nok) {
  426. X    if (!argstr->str_pok)
  427. X        s = str_get(argstr);
  428. X
  429. X#ifdef IOCPARM_MASK
  430. X#ifndef IOCPARM_LEN
  431. X#define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
  432. X#endif
  433. X#endif
  434. X#ifdef IOCPARM_LEN
  435. X    retval = IOCPARM_LEN(func);    /* on BSDish systes we're safe */
  436. X#else
  437. X    retval = 256;            /* otherwise guess at what's safe */
  438. X#endif
  439. X    if (argstr->str_cur < retval) {
  440. X        str_grow(argstr,retval+1);
  441. X        argstr->str_cur = retval;
  442. X    }
  443. X
  444. X    s = argstr->str_ptr;
  445. X    s[argstr->str_cur] = 17;    /* a little sanity check here */
  446. X    }
  447. X    else {
  448. X    retval = (int)str_gnum(argstr);
  449. X    s = (char*)retval;        /* ouch */
  450. X    }
  451. X
  452. X#ifndef lint
  453. X    if (optype == O_IOCTL)
  454. X    retval = ioctl(fileno(stio->ifp), func, s);
  455. X    else
  456. X#ifdef I_FCNTL
  457. X    retval = fcntl(fileno(stio->ifp), func, s);
  458. X#else
  459. X    fatal("fcntl is not implemented");
  460. X#endif
  461. X#else /* lint */
  462. X    retval = 0;
  463. X#endif /* lint */
  464. X
  465. X    if (argstr->str_pok) {
  466. X    if (s[argstr->str_cur] != 17)
  467. X        fatal("Return value overflowed string");
  468. X    s[argstr->str_cur] = 0;        /* put our null back */
  469. X    }
  470. X    return retval;
  471. X}
  472. X
  473. Xint
  474. Xdo_stat(str,arg,gimme,arglast)
  475. XSTR *str;
  476. Xregister ARG *arg;
  477. Xint gimme;
  478. Xint *arglast;
  479. X{
  480. X    register ARRAY *ary = stack;
  481. X    register int sp = arglast[0] + 1;
  482. X    int max = 13;
  483. X    register int i;
  484. X
  485. X    if ((arg[1].arg_type & A_MASK) == A_WORD) {
  486. X    tmpstab = arg[1].arg_ptr.arg_stab;
  487. X    if (tmpstab != defstab) {
  488. X        statstab = tmpstab;
  489. X        str_set(statname,"");
  490. X        if (!stab_io(tmpstab) ||
  491. X          fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
  492. X        max = 0;
  493. X        }
  494. X    }
  495. X    }
  496. X    else {
  497. X    str_sset(statname,ary->ary_array[sp]);
  498. X    statstab = Nullstab;
  499. X#ifdef SYMLINK
  500. X    if (arg->arg_type == O_LSTAT)
  501. X        i = lstat(str_get(statname),&statcache);
  502. X    else
  503. X#endif
  504. X        i = stat(str_get(statname),&statcache);
  505. X    if (i < 0)
  506. X        max = 0;
  507. X    }
  508. X
  509. X    if (gimme != G_ARRAY) {
  510. X    if (max)
  511. X        str_sset(str,&str_yes);
  512. X    else
  513. X        str_sset(str,&str_undef);
  514. X    STABSET(str);
  515. X    ary->ary_array[sp] = str;
  516. X    return sp;
  517. X    }
  518. X    sp--;
  519. X    if (max) {
  520. X#ifndef lint
  521. X    (void)astore(ary,++sp,
  522. X      str_2static(str_nmake((double)statcache.st_dev)));
  523. X    (void)astore(ary,++sp,
  524. X      str_2static(str_nmake((double)statcache.st_ino)));
  525. X    (void)astore(ary,++sp,
  526. X      str_2static(str_nmake((double)statcache.st_mode)));
  527. X    (void)astore(ary,++sp,
  528. X      str_2static(str_nmake((double)statcache.st_nlink)));
  529. X    (void)astore(ary,++sp,
  530. X      str_2static(str_nmake((double)statcache.st_uid)));
  531. X    (void)astore(ary,++sp,
  532. X      str_2static(str_nmake((double)statcache.st_gid)));
  533. X    (void)astore(ary,++sp,
  534. X      str_2static(str_nmake((double)statcache.st_rdev)));
  535. X    (void)astore(ary,++sp,
  536. X      str_2static(str_nmake((double)statcache.st_size)));
  537. X    (void)astore(ary,++sp,
  538. X      str_2static(str_nmake((double)statcache.st_atime)));
  539. X    (void)astore(ary,++sp,
  540. X      str_2static(str_nmake((double)statcache.st_mtime)));
  541. X    (void)astore(ary,++sp,
  542. X      str_2static(str_nmake((double)statcache.st_ctime)));
  543. X#ifdef STATBLOCKS
  544. X    (void)astore(ary,++sp,
  545. X      str_2static(str_nmake((double)statcache.st_blksize)));
  546. X    (void)astore(ary,++sp,
  547. X      str_2static(str_nmake((double)statcache.st_blocks)));
  548. X#else
  549. X    (void)astore(ary,++sp,
  550. X      str_2static(str_make("",0)));
  551. X    (void)astore(ary,++sp,
  552. X      str_2static(str_make("",0)));
  553. X#endif
  554. X#else /* lint */
  555. X    (void)astore(ary,++sp,str_nmake(0.0));
  556. X#endif /* lint */
  557. X    }
  558. X    return sp;
  559. X}
  560. X
  561. Xint
  562. Xlooks_like_number(str)
  563. XSTR *str;
  564. X{
  565. X    register char *s;
  566. X    register char *send;
  567. X
  568. X    if (!str->str_pok)
  569. X    return TRUE;
  570. X    s = str->str_ptr; 
  571. X    send = s + str->str_cur;
  572. X    while (isspace(*s))
  573. X    s++;
  574. X    if (s >= send)
  575. X    return FALSE;
  576. X    if (*s == '+' || *s == '-')
  577. X    s++;
  578. X    while (isdigit(*s))
  579. X    s++;
  580. X    if (s == send)
  581. X    return TRUE;
  582. X    if (*s == '.') 
  583. X    s++;
  584. X    else if (s == str->str_ptr)
  585. X    return FALSE;
  586. X    while (isdigit(*s))
  587. X    s++;
  588. X    if (s == send)
  589. X    return TRUE;
  590. X    if (*s == 'e' || *s == 'E') {
  591. X    s++;
  592. X    if (*s == '+' || *s == '-')
  593. X        s++;
  594. X    while (isdigit(*s))
  595. X        s++;
  596. X    }
  597. X    while (isspace(*s))
  598. X    s++;
  599. X    if (s >= send)
  600. X    return TRUE;
  601. X    return FALSE;
  602. X}
  603. X
  604. Xbool
  605. Xdo_print(str,fp)
  606. Xregister STR *str;
  607. XFILE *fp;
  608. X{
  609. X    register char *tmps;
  610. X
  611. X    if (!fp) {
  612. X    if (dowarn)
  613. X        warn("print to unopened file");
  614. X    return FALSE;
  615. X    }
  616. X    if (!str)
  617. X    return FALSE;
  618. X    if (ofmt &&
  619. X      ((str->str_nok && str->str_u.str_nval != 0.0)
  620. X       || (looks_like_number(str) && str_gnum(str) != 0.0) ) )
  621. X    fprintf(fp, ofmt, str->str_u.str_nval);
  622. X    else {
  623. X    tmps = str_get(str);
  624. X    if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'a' && tmps[3] == 'b'
  625. X      && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
  626. X        tmps = stab_name(((STAB*)str));    /* a stab value, be nice */
  627. X        str = ((STAB*)str)->str_magic;
  628. X        putc('*',fp);
  629. X    }
  630. X    if (str->str_cur && fwrite(tmps,1,str->str_cur,fp) == 0)
  631. X        return FALSE;
  632. X    }
  633. X    return TRUE;
  634. X}
  635. X
  636. Xbool
  637. Xdo_aprint(arg,fp,arglast)
  638. Xregister ARG *arg;
  639. Xregister FILE *fp;
  640. Xint *arglast;
  641. X{
  642. X    register STR **st = stack->ary_array;
  643. X    register int sp = arglast[1];
  644. X    register int retval;
  645. X    register int items = arglast[2] - sp;
  646. X
  647. X    if (!fp) {
  648. X    if (dowarn)
  649. X        warn("print to unopened file");
  650. X    return FALSE;
  651. X    }
  652. X    st += ++sp;
  653. X    if (arg->arg_type == O_PRTF) {
  654. X    do_sprintf(arg->arg_ptr.arg_str,items,st);
  655. X    retval = do_print(arg->arg_ptr.arg_str,fp);
  656. X    }
  657. X    else {
  658. X    retval = (items <= 0);
  659. X    for (; items > 0; items--,st++) {
  660. X        if (retval && ofslen) {
  661. X        if (fwrite(ofs, 1, ofslen, fp) == 0) {
  662. X            retval = FALSE;
  663. X            break;
  664. X        }
  665. X        }
  666. X        if (!(retval = do_print(*st, fp)))
  667. X        break;
  668. X    }
  669. X    if (retval && orslen)
  670. X        if (fwrite(ors, 1, orslen, fp) == 0)
  671. X        retval = FALSE;
  672. X    }
  673. X    return retval;
  674. X}
  675. X
  676. Xint
  677. Xmystat(arg,str)
  678. XARG *arg;
  679. XSTR *str;
  680. X{
  681. X    STIO *stio;
  682. X
  683. X    if (arg[1].arg_type & A_DONT) {
  684. X    stio = stab_io(arg[1].arg_ptr.arg_stab);
  685. X    if (stio && stio->ifp) {
  686. X        statstab = arg[1].arg_ptr.arg_stab;
  687. X        str_set(statname,"");
  688. X        return fstat(fileno(stio->ifp), &statcache);
  689. X    }
  690. X    else {
  691. X        if (arg[1].arg_ptr.arg_stab == defstab)
  692. X        return 0;
  693. X        if (dowarn)
  694. X        warn("Stat on unopened file <%s>",
  695. X          stab_name(arg[1].arg_ptr.arg_stab));
  696. X        statstab = Nullstab;
  697. X        str_set(statname,"");
  698. X        return -1;
  699. X    }
  700. X    }
  701. X    else {
  702. X    statstab = Nullstab;
  703. X    str_sset(statname,str);
  704. X    return stat(str_get(str),&statcache);
  705. X    }
  706. X}
  707. X
  708. XSTR *
  709. Xdo_fttext(arg,str)
  710. Xregister ARG *arg;
  711. XSTR *str;
  712. X{
  713. X    int i;
  714. X    int len;
  715. X    int odd = 0;
  716. X    STDCHAR tbuf[512];
  717. X    register STDCHAR *s;
  718. X    register STIO *stio;
  719. X
  720. X    if (arg[1].arg_type & A_DONT) {
  721. X    if (arg[1].arg_ptr.arg_stab == defstab) {
  722. X        if (statstab)
  723. X        stio = stab_io(statstab);
  724. X        else {
  725. X        str = statname;
  726. X        goto really_filename;
  727. X        }
  728. X    }
  729. X    else {
  730. X        statstab = arg[1].arg_ptr.arg_stab;
  731. X        str_set(statname,"");
  732. X        stio = stab_io(statstab);
  733. X    }
  734. X    if (stio && stio->ifp) {
  735. X#ifdef STDSTDIO
  736. X        fstat(fileno(stio->ifp),&statcache);
  737. X        if (stio->ifp->_cnt <= 0) {
  738. X        i = getc(stio->ifp);
  739. X        if (i != EOF)
  740. X            (void)ungetc(i,stio->ifp);
  741. X        }
  742. X        if (stio->ifp->_cnt <= 0)    /* null file is anything */
  743. X        return &str_yes;
  744. X        len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
  745. X        s = stio->ifp->_base;
  746. X#else
  747. X        fatal("-T and -B not implemented on filehandles\n");
  748. X#endif
  749. X    }
  750. X    else {
  751. X        if (dowarn)
  752. X        warn("Test on unopened file <%s>",
  753. X          stab_name(arg[1].arg_ptr.arg_stab));
  754. X        return &str_undef;
  755. X    }
  756. X    }
  757. X    else {
  758. X    statstab = Nullstab;
  759. X    str_sset(statname,str);
  760. X      really_filename:
  761. X    i = open(str_get(str),0);
  762. X    if (i < 0)
  763. X        return &str_undef;
  764. X    fstat(i,&statcache);
  765. X    len = read(i,tbuf,512);
  766. X    if (len <= 0)        /* null file is anything */
  767. X        return &str_yes;
  768. X    (void)close(i);
  769. X    s = tbuf;
  770. X    }
  771. X
  772. X    /* now scan s to look for textiness */
  773. X
  774. X    for (i = 0; i < len; i++,s++) {
  775. X    if (!*s) {            /* null never allowed in text */
  776. X        odd += len;
  777. X        break;
  778. X    }
  779. X    else if (*s & 128)
  780. X        odd++;
  781. X    else if (*s < 32 &&
  782. X      *s != '\n' && *s != '\r' && *s != '\b' &&
  783. X      *s != '\t' && *s != '\f' && *s != 27)
  784. X        odd++;
  785. X    }
  786. X
  787. X    if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
  788. X    return &str_no;
  789. X    else
  790. X    return &str_yes;
  791. X}
  792. X
  793. Xbool
  794. Xdo_aexec(really,arglast)
  795. XSTR *really;
  796. Xint *arglast;
  797. X{
  798. X    register STR **st = stack->ary_array;
  799. X    register int sp = arglast[1];
  800. X    register int items = arglast[2] - sp;
  801. X    register char **a;
  802. X    char **argv;
  803. X    char *tmps;
  804. X
  805. X    if (items) {
  806. X    New(401,argv, items+1, char*);
  807. X    a = argv;
  808. X    for (st += ++sp; items > 0; items--,st++) {
  809. X        if (*st)
  810. X        *a++ = str_get(*st);
  811. X        else
  812. X        *a++ = "";
  813. X    }
  814. X    *a = Nullch;
  815. X#ifdef TAINT
  816. X    if (*argv[0] != '/')    /* will execvp use PATH? */
  817. X        taintenv();        /* testing IFS here is overkill, probably */
  818. X#endif
  819. X    if (really && *(tmps = str_get(really)))
  820. X        execvp(tmps,argv);
  821. X    else
  822. X        execvp(argv[0],argv);
  823. X    Safefree(argv);
  824. X    }
  825. X    return FALSE;
  826. X}
  827. X
  828. Xbool
  829. Xdo_exec(cmd)
  830. Xchar *cmd;
  831. X{
  832. X    register char **a;
  833. X    register char *s;
  834. X    char **argv;
  835. X    char flags[10];
  836. X
  837. X#ifdef TAINT
  838. X    taintenv();
  839. X    taintproper("Insecure dependency in exec");
  840. X#endif
  841. X
  842. X    /* save an extra exec if possible */
  843. X
  844. X    if (csh > 0 && strnEQ(cmd,"/bin/csh -c",11)) {
  845. X    strcpy(flags,"-c");
  846. X    s = cmd+11;
  847. X    if (*s == 'f') {
  848. X        s++;
  849. X        strcat(flags,"f");
  850. X    }
  851. X    if (*s == ' ')
  852. X        s++;
  853. X    if (*s++ == '\'') {
  854. X        char *ncmd = s;
  855. X
  856. X        while (*s)
  857. X        s++;
  858. X        if (s[-1] == '\n')
  859. X        *--s = '\0';
  860. X        if (s[-1] == '\'') {
  861. X        *--s = '\0';
  862. X        execl("/bin/csh","csh", flags,ncmd,(char*)0);
  863. X        *s = '\'';
  864. X        return FALSE;
  865. X        }
  866. X    }
  867. X    }
  868. X
  869. X    /* see if there are shell metacharacters in it */
  870. X
  871. X    for (s = cmd; *s; s++) {
  872. X    if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
  873. X        if (*s == '\n' && !s[1]) {
  874. X        *s = '\0';
  875. X        break;
  876. X        }
  877. X      doshell:
  878. X        execl("/bin/sh","sh","-c",cmd,(char*)0);
  879. X        return FALSE;
  880. X    }
  881. X    }
  882. X    New(402,argv, (s - cmd) / 2 + 2, char*);
  883. X
  884. X    a = argv;
  885. X    for (s = cmd; *s;) {
  886. X    while (*s && isspace(*s)) s++;
  887. X    if (*s)
  888. X        *(a++) = s;
  889. X    while (*s && !isspace(*s)) s++;
  890. X    if (*s)
  891. X        *s++ = '\0';
  892. X    }
  893. X    *a = Nullch;
  894. X    if (argv[0]) {
  895. X    execvp(argv[0],argv);
  896. X    if (errno == ENOEXEC)        /* for system V NIH syndrome */
  897. X        goto doshell;
  898. X    }
  899. X    Safefree(argv);
  900. X    return FALSE;
  901. X}
  902. X
  903. X#ifdef SOCKET
  904. Xint
  905. Xdo_socket(stab, arglast)
  906. XSTAB *stab;
  907. Xint *arglast;
  908. X{
  909. X    register STR **st = stack->ary_array;
  910. X    register int sp = arglast[1];
  911. X    register STIO *stio;
  912. X    int domain, type, protocol, fd;
  913. X
  914. X    if (!stab)
  915. X    return FALSE;
  916. X
  917. X    stio = stab_io(stab);
  918. X    if (!stio)
  919. X    stio = stab_io(stab) = stio_new();
  920. X    else if (stio->ifp)
  921. X    do_close(stab,FALSE);
  922. X
  923. X    domain = (int)str_gnum(st[++sp]);
  924. X    type = (int)str_gnum(st[++sp]);
  925. X    protocol = (int)str_gnum(st[++sp]);
  926. X#ifdef TAINT
  927. X    taintproper("Insecure dependency in socket");
  928. X#endif
  929. X    fd = socket(domain,type,protocol);
  930. X    if (fd < 0)
  931. X    return FALSE;
  932. X    stio->ifp = fdopen(fd, "r");    /* stdio gets confused about sockets */
  933. X    stio->ofp = fdopen(fd, "w");
  934. X    stio->type = 's';
  935. X
  936. X    return TRUE;
  937. X}
  938. X
  939. Xint
  940. Xdo_bind(stab, arglast)
  941. XSTAB *stab;
  942. Xint *arglast;
  943. X{
  944. X    register STR **st = stack->ary_array;
  945. X    register int sp = arglast[1];
  946. X    register STIO *stio;
  947. X    char *addr;
  948. X
  949. X    if (!stab)
  950. X    goto nuts;
  951. X
  952. X    stio = stab_io(stab);
  953. X    if (!stio || !stio->ifp)
  954. X    goto nuts;
  955. X
  956. X    addr = str_get(st[++sp]);
  957. X#ifdef TAINT
  958. X    taintproper("Insecure dependency in bind");
  959. X#endif
  960. X    return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
  961. X
  962. Xnuts:
  963. X    if (dowarn)
  964. X    warn("bind() on closed fd");
  965. X    return FALSE;
  966. X
  967. X}
  968. X
  969. Xint
  970. Xdo_connect(stab, arglast)
  971. XSTAB *stab;
  972. Xint *arglast;
  973. X{
  974. X    register STR **st = stack->ary_array;
  975. X    register int sp = arglast[1];
  976. X    register STIO *stio;
  977. X    char *addr;
  978. X
  979. X    if (!stab)
  980. X    goto nuts;
  981. X
  982. X    stio = stab_io(stab);
  983. X    if (!stio || !stio->ifp)
  984. X    goto nuts;
  985. X
  986. X    addr = str_get(st[++sp]);
  987. X#ifdef TAINT
  988. X    taintproper("Insecure dependency in connect");
  989. X#endif
  990. X    return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
  991. X
  992. Xnuts:
  993. X    if (dowarn)
  994. X    warn("connect() on closed fd");
  995. X    return FALSE;
  996. X
  997. X}
  998. X
  999. Xint
  1000. Xdo_listen(stab, arglast)
  1001. XSTAB *stab;
  1002. Xint *arglast;
  1003. X{
  1004. X    register STR **st = stack->ary_array;
  1005. X    register int sp = arglast[1];
  1006. X    register STIO *stio;
  1007. X    int backlog;
  1008. X
  1009. X    if (!stab)
  1010. X    goto nuts;
  1011. X
  1012. X    stio = stab_io(stab);
  1013. X    if (!stio || !stio->ifp)
  1014. X    goto nuts;
  1015. X
  1016. X    backlog = (int)str_gnum(st[++sp]);
  1017. X    return listen(fileno(stio->ifp), backlog) >= 0;
  1018. X
  1019. Xnuts:
  1020. X    if (dowarn)
  1021. X    warn("listen() on closed fd");
  1022. X    return FALSE;
  1023. X}
  1024. X
  1025. Xvoid
  1026. Xdo_accept(str, nstab, gstab)
  1027. XSTR *str;
  1028. XSTAB *nstab;
  1029. XSTAB *gstab;
  1030. X{
  1031. X    register STIO *nstio;
  1032. X    register STIO *gstio;
  1033. X    int len = sizeof buf;
  1034. X    int fd;
  1035. X
  1036. X    if (!nstab)
  1037. X    goto badexit;
  1038. X    if (!gstab)
  1039. X    goto nuts;
  1040. X
  1041. X    gstio = stab_io(gstab);
  1042. X    nstio = stab_io(nstab);
  1043. X
  1044. X    if (!gstio || !gstio->ifp)
  1045. X    goto nuts;
  1046. X    if (!nstio)
  1047. X    nstio = stab_io(nstab) = stio_new();
  1048. X    else if (nstio->ifp)
  1049. X    do_close(nstab,FALSE);
  1050. X
  1051. X    fd = accept(fileno(gstio->ifp),buf,&len);
  1052. X    if (fd < 0)
  1053. X    goto badexit;
  1054. X    nstio->ifp = fdopen(fd, "r");
  1055. X    nstio->ofp = fdopen(fd, "w");
  1056. X    nstio->type = 's';
  1057. X
  1058. X    str_nset(str, buf, len);
  1059. X    return;
  1060. X
  1061. Xnuts:
  1062. X    if (dowarn)
  1063. X    warn("accept() on closed fd");
  1064. Xbadexit:
  1065. X    str_sset(str,&str_undef);
  1066. X    return;
  1067. X}
  1068. X
  1069. Xint
  1070. Xdo_shutdown(stab, arglast)
  1071. XSTAB *stab;
  1072. Xint *arglast;
  1073. X{
  1074. X    register STR **st = stack->ary_array;
  1075. X    register int sp = arglast[1];
  1076. X    register STIO *stio;
  1077. X    int how;
  1078. X
  1079. X    if (!stab)
  1080. X    goto nuts;
  1081. X
  1082. X    stio = stab_io(stab);
  1083. X    if (!stio || !stio->ifp)
  1084. X    goto nuts;
  1085. X
  1086. X    how = (int)str_gnum(st[++sp]);
  1087. X    return shutdown(fileno(stio->ifp), how) >= 0;
  1088. X
  1089. Xnuts:
  1090. X    if (dowarn)
  1091. X    warn("shutdown() on closed fd");
  1092. X    return FALSE;
  1093. X
  1094. X}
  1095. X
  1096. Xint
  1097. Xdo_sopt(optype, stab, arglast)
  1098. Xint optype;
  1099. XSTAB *stab;
  1100. Xint *arglast;
  1101. X{
  1102. X    register STR **st = stack->ary_array;
  1103. X    register int sp = arglast[1];
  1104. X    register STIO *stio;
  1105. X    int fd;
  1106. X    int lvl;
  1107. X    int optname;
  1108. X
  1109. X    if (!stab)
  1110. X    goto nuts;
  1111. X
  1112. X    stio = stab_io(stab);
  1113. X    if (!stio || !stio->ifp)
  1114. X    goto nuts;
  1115. X
  1116. X    fd = fileno(stio->ifp);
  1117. X    lvl = (int)str_gnum(st[sp+1]);
  1118. X    optname = (int)str_gnum(st[sp+2]);
  1119. X    switch (optype) {
  1120. X    case O_GSOCKOPT:
  1121. X    st[sp] = str_2static(str_new(257));
  1122. X    st[sp]->str_cur = 256;
  1123. X    if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1124. X        goto nuts;
  1125. X    break;
  1126. X    case O_SSOCKOPT:
  1127. X    st[sp] = st[sp+3];
  1128. X    if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
  1129. X        goto nuts;
  1130. X    st[sp] = &str_yes;
  1131. X    break;
  1132. X    }
  1133. X    
  1134. X    return sp;
  1135. X
  1136. Xnuts:
  1137. X    if (dowarn)
  1138. X    warn("shutdown() on closed fd");
  1139. X    st[sp] = &str_undef;
  1140. X    return sp;
  1141. X
  1142. X}
  1143. X
  1144. Xint
  1145. Xdo_getsockname(optype, stab, arglast)
  1146. Xint optype;
  1147. XSTAB *stab;
  1148. Xint *arglast;
  1149. X{
  1150. X    register STR **st = stack->ary_array;
  1151. X    register int sp = arglast[1];
  1152. X    register STIO *stio;
  1153. X    int fd;
  1154. X
  1155. X    if (!stab)
  1156. X    goto nuts;
  1157. X
  1158. X    stio = stab_io(stab);
  1159. X    if (!stio || !stio->ifp)
  1160. X    goto nuts;
  1161. X
  1162. X    st[sp] = str_2static(str_new(257));
  1163. X    st[sp]->str_cur = 256;
  1164. X    fd = fileno(stio->ifp);
  1165. X    switch (optype) {
  1166. X    case O_GETSOCKNAME:
  1167. X    if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1168. X        goto nuts;
  1169. X    break;
  1170. X    case O_GETPEERNAME:
  1171. X    if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1172. X        goto nuts;
  1173. X    break;
  1174. X    }
  1175. X    
  1176. X    return sp;
  1177. X
  1178. Xnuts:
  1179. X    if (dowarn)
  1180. X    warn("shutdown() on closed fd");
  1181. X    st[sp] = &str_undef;
  1182. X    return sp;
  1183. X
  1184. X}
  1185. X
  1186. Xint
  1187. Xdo_ghent(which,gimme,arglast)
  1188. Xint which;
  1189. Xint gimme;
  1190. Xint *arglast;
  1191. X{
  1192. X    register ARRAY *ary = stack;
  1193. X    register int sp = arglast[0];
  1194. X    register char **elem;
  1195. X    register STR *str;
  1196. X    struct hostent *gethostbynam();
  1197. X    struct hostent *gethostbyaddr();
  1198. X#ifdef GETHOSTENT
  1199. X    struct hostent *gethostent();
  1200. X#endif
  1201. X    struct hostent *hent;
  1202. X    unsigned long len;
  1203. X
  1204. X    if (gimme != G_ARRAY) {
  1205. X    astore(ary, ++sp, str_static(&str_undef));
  1206. X    return sp;
  1207. X    }
  1208. X
  1209. X    if (which == O_GHBYNAME) {
  1210. X    char *name = str_get(ary->ary_array[sp+1]);
  1211. X
  1212. X    hent = gethostbyname(name);
  1213. X    }
  1214. X    else if (which == O_GHBYADDR) {
  1215. X    STR *addrstr = ary->ary_array[sp+1];
  1216. X    int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
  1217. X    char *addr = str_get(addrstr);
  1218. X
  1219. X    hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
  1220. X    }
  1221. X    else
  1222. X#ifdef GETHOSTENT
  1223. X    hent = gethostent();
  1224. X#else
  1225. X    fatal("gethostent not implemented");
  1226. X#endif
  1227. X    if (hent) {
  1228. X#ifndef lint
  1229. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1230. X    str_set(str, hent->h_name);
  1231. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1232. X    for (elem = hent->h_aliases; *elem; elem++) {
  1233. X        str_cat(str, *elem);
  1234. X        if (elem[1])
  1235. X        str_ncat(str," ",1);
  1236. X    }
  1237. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1238. X    str_numset(str, (double)hent->h_addrtype);
  1239. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1240. X    len = hent->h_length;
  1241. X    str_numset(str, (double)len);
  1242. X#ifdef h_addr
  1243. X    for (elem = hent->h_addr_list; *elem; elem++) {
  1244. X        (void)astore(ary, ++sp, str = str_static(&str_no));
  1245. X        str_nset(str, *elem, len);
  1246. X    }
  1247. X#else
  1248. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1249. X    str_nset(str, hent->h_addr, len);
  1250. X#endif /* h_addr */
  1251. X#else /* lint */
  1252. X    elem = Nullch;
  1253. X    elem = elem;
  1254. X    (void)astore(ary, ++sp, str_static(&str_no));
  1255. X#endif /* lint */
  1256. X    }
  1257. X
  1258. X    return sp;
  1259. X}
  1260. X
  1261. Xint
  1262. Xdo_gnent(which,gimme,arglast)
  1263. Xint which;
  1264. Xint gimme;
  1265. Xint *arglast;
  1266. X{
  1267. X    register ARRAY *ary = stack;
  1268. X    register int sp = arglast[0];
  1269. X    register char **elem;
  1270. X    register STR *str;
  1271. X    struct netent *getnetbyname();
  1272. X    struct netent *getnetbyaddr();
  1273. X    struct netent *getnetent();
  1274. X    struct netent *nent;
  1275. X
  1276. X    if (gimme != G_ARRAY) {
  1277. X    astore(ary, ++sp, str_static(&str_undef));
  1278. X    return sp;
  1279. X    }
  1280. X
  1281. X    if (which == O_GNBYNAME) {
  1282. X    char *name = str_get(ary->ary_array[sp+1]);
  1283. X
  1284. X    nent = getnetbyname(name);
  1285. X    }
  1286. X    else if (which == O_GNBYADDR) {
  1287. X    STR *addrstr = ary->ary_array[sp+1];
  1288. X    int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
  1289. X    char *addr = str_get(addrstr);
  1290. X
  1291. X    nent = getnetbyaddr(addr,addrtype);
  1292. X    }
  1293. X    else
  1294. X    nent = getnetent();
  1295. X
  1296. X    if (nent) {
  1297. X#ifndef lint
  1298. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1299. X    str_set(str, nent->n_name);
  1300. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1301. X    for (elem = nent->n_aliases; *elem; elem++) {
  1302. X        str_cat(str, *elem);
  1303. X        if (elem[1])
  1304. X        str_ncat(str," ",1);
  1305. X    }
  1306. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1307. X    str_numset(str, (double)nent->n_addrtype);
  1308. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1309. X    str_numset(str, (double)nent->n_net);
  1310. X#else /* lint */
  1311. X    elem = Nullch;
  1312. X    elem = elem;
  1313. X    (void)astore(ary, ++sp, str_static(&str_no));
  1314. X#endif /* lint */
  1315. X    }
  1316. X
  1317. X    return sp;
  1318. X}
  1319. X
  1320. Xint
  1321. Xdo_gpent(which,gimme,arglast)
  1322. Xint which;
  1323. Xint gimme;
  1324. Xint *arglast;
  1325. X{
  1326. X    register ARRAY *ary = stack;
  1327. X    register int sp = arglast[0];
  1328. X    register char **elem;
  1329. X    register STR *str;
  1330. X    struct protoent *getprotobyname();
  1331. X    struct protoent *getprotobynumber();
  1332. X    struct protoent *getprotoent();
  1333. X    struct protoent *pent;
  1334. X
  1335. X    if (gimme != G_ARRAY) {
  1336. X    astore(ary, ++sp, str_static(&str_undef));
  1337. X    return sp;
  1338. X    }
  1339. X
  1340. X    if (which == O_GPBYNAME) {
  1341. X    char *name = str_get(ary->ary_array[sp+1]);
  1342. X
  1343. X    pent = getprotobyname(name);
  1344. X    }
  1345. X    else if (which == O_GPBYNUMBER) {
  1346. X    int proto = (int)str_gnum(ary->ary_array[sp+1]);
  1347. X
  1348. X    pent = getprotobynumber(proto);
  1349. X    }
  1350. X    else
  1351. X    pent = getprotoent();
  1352. X
  1353. X    if (pent) {
  1354. X#ifndef lint
  1355. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1356. X    str_set(str, pent->p_name);
  1357. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1358. X    for (elem = pent->p_aliases; *elem; elem++) {
  1359. X        str_cat(str, *elem);
  1360. X        if (elem[1])
  1361. X        str_ncat(str," ",1);
  1362. X    }
  1363. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1364. X    str_numset(str, (double)pent->p_proto);
  1365. X#else /* lint */
  1366. X    elem = Nullch;
  1367. X    elem = elem;
  1368. X    (void)astore(ary, ++sp, str_static(&str_no));
  1369. X#endif /* lint */
  1370. X    }
  1371. X
  1372. X    return sp;
  1373. X}
  1374. X
  1375. Xint
  1376. Xdo_gsent(which,gimme,arglast)
  1377. Xint which;
  1378. Xint gimme;
  1379. Xint *arglast;
  1380. X{
  1381. X    register ARRAY *ary = stack;
  1382. X    register int sp = arglast[0];
  1383. X    register char **elem;
  1384. X    register STR *str;
  1385. X    struct servent *getservbyname();
  1386. X    struct servent *getservbynumber();
  1387. X    struct servent *getservent();
  1388. X    struct servent *sent;
  1389. X
  1390. X    if (gimme != G_ARRAY) {
  1391. X    astore(ary, ++sp, str_static(&str_undef));
  1392. X    return sp;
  1393. X    }
  1394. X
  1395. X    if (which == O_GSBYNAME) {
  1396. X    char *name = str_get(ary->ary_array[sp+1]);
  1397. X    char *proto = str_get(ary->ary_array[sp+2]);
  1398. X
  1399. X    if (proto && !*proto)
  1400. X        proto = Nullch;
  1401. X
  1402. X    sent = getservbyname(name,proto);
  1403. X    }
  1404. X    else if (which == O_GSBYPORT) {
  1405. X    int port = (int)str_gnum(ary->ary_array[sp+1]);
  1406. X    char *proto = str_get(ary->ary_array[sp+2]);
  1407. X
  1408. X    sent = getservbyport(port,proto);
  1409. X    }
  1410. X    else
  1411. X    sent = getservent();
  1412. X    if (sent) {
  1413. X#ifndef lint
  1414. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1415. X    str_set(str, sent->s_name);
  1416. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1417. X    for (elem = sent->s_aliases; *elem; elem++) {
  1418. X        str_cat(str, *elem);
  1419. X        if (elem[1])
  1420. X        str_ncat(str," ",1);
  1421. X    }
  1422. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1423. X#ifdef NTOHS
  1424. X    str_numset(str, (double)ntohs(sent->s_port));
  1425. X#else
  1426. X    str_numset(str, (double)(sent->s_port));
  1427. X#endif
  1428. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1429. X    str_set(str, sent->s_proto);
  1430. X#else /* lint */
  1431. X    elem = Nullch;
  1432. X    elem = elem;
  1433. X    (void)astore(ary, ++sp, str_static(&str_no));
  1434. X#endif /* lint */
  1435. X    }
  1436. X
  1437. X    return sp;
  1438. X}
  1439. X
  1440. Xint
  1441. Xdo_select(gimme,arglast)
  1442. Xint gimme;
  1443. Xint *arglast;
  1444. X{
  1445. X    register STR **st = stack->ary_array;
  1446. X    register int sp = arglast[0];
  1447. X    register int i;
  1448. X    register int j;
  1449. X    register char *s;
  1450. X    register STR *str;
  1451. X    double value;
  1452. X    int maxlen = 0;
  1453. X    int nfound;
  1454. X    struct timeval timebuf;
  1455. X    struct timeval *tbuf = &timebuf;
  1456. X
  1457. X    for (i = 1; i <= 3; i++) {
  1458. X    j = st[sp+i]->str_len;
  1459. X    if (maxlen < j)
  1460. X        maxlen = j;
  1461. X    }
  1462. X    for (i = 1; i <= 3; i++) {
  1463. X    str = st[sp+i];
  1464. X    j = str->str_len;
  1465. X    if (j < maxlen) {
  1466. X        if (str->str_pok) {
  1467. X        str_grow(str,maxlen);
  1468. X        s = str_get(str) + j;
  1469. X        while (++j <= maxlen) {
  1470. X            *s++ = '\0';
  1471. X        }
  1472. X        }
  1473. X        else if (str->str_ptr) {
  1474. X        Safefree(str->str_ptr);
  1475. X        str->str_ptr = Nullch;
  1476. X        }
  1477. X    }
  1478. X    }
  1479. X    str = st[sp+4];
  1480. X    if (str->str_nok || str->str_pok) {
  1481. X    value = str_gnum(str);
  1482. X    if (value < 0.0)
  1483. X        value = 0.0;
  1484. X    timebuf.tv_sec = (long)value;
  1485. X    value -= (double)timebuf.tv_sec;
  1486. X    timebuf.tv_usec = (long)(value * 1000000.0);
  1487. X    }
  1488. X    else
  1489. X    tbuf = Null(struct timeval*);
  1490. X
  1491. X    nfound = select(
  1492. X    maxlen * 8,
  1493. X    st[sp+1]->str_ptr,
  1494. X    st[sp+2]->str_ptr,
  1495. X    st[sp+3]->str_ptr,
  1496. X    tbuf);
  1497. X
  1498. X    st[++sp] = str_static(&str_no);
  1499. X    str_numset(st[sp], (double)nfound);
  1500. X    if (gimme == G_ARRAY && tbuf) {
  1501. X    value = (double)(timebuf.tv_sec) +
  1502. X        (double)(timebuf.tv_usec) / 1000000.0;
  1503. X    st[++sp] = str_static(&str_no);
  1504. X    str_numset(st[sp], value);
  1505. X    }
  1506. X    return sp;
  1507. X}
  1508. X
  1509. Xint
  1510. Xdo_spair(stab1, stab2, arglast)
  1511. XSTAB *stab1;
  1512. XSTAB *stab2;
  1513. Xint *arglast;
  1514. X{
  1515. X    register STR **st = stack->ary_array;
  1516. X    register int sp = arglast[2];
  1517. X    register STIO *stio1;
  1518. X    register STIO *stio2;
  1519. X    int domain, type, protocol, fd[2];
  1520. X
  1521. X    if (!stab1 || !stab2)
  1522. X    return FALSE;
  1523. X
  1524. X    stio1 = stab_io(stab1);
  1525. X    stio2 = stab_io(stab2);
  1526. X    if (!stio1)
  1527. X    stio1 = stab_io(stab1) = stio_new();
  1528. X    else if (stio1->ifp)
  1529. X    do_close(stab1,FALSE);
  1530. X    if (!stio2)
  1531. X    stio2 = stab_io(stab2) = stio_new();
  1532. X    else if (stio2->ifp)
  1533. X    do_close(stab2,FALSE);
  1534. X
  1535. X    domain = (int)str_gnum(st[++sp]);
  1536. X    type = (int)str_gnum(st[++sp]);
  1537. X    protocol = (int)str_gnum(st[++sp]);
  1538. X#ifdef TAINT
  1539. X    taintproper("Insecure dependency in socketpair");
  1540. X#endif
  1541. X#ifdef SOCKETPAIR
  1542. X    if (socketpair(domain,type,protocol,fd) < 0)
  1543. X    return FALSE;
  1544. X#else
  1545. X    fatal("Socketpair unimplemented");
  1546. X#endif
  1547. X    stio1->ifp = fdopen(fd[0], "r");
  1548. X    stio1->ofp = fdopen(fd[0], "w");
  1549. X    stio1->type = 's';
  1550. X    stio2->ifp = fdopen(fd[1], "r");
  1551. X    stio2->ofp = fdopen(fd[1], "w");
  1552. X    stio2->type = 's';
  1553. X
  1554. X    return TRUE;
  1555. X}
  1556. X
  1557. X#endif /* SOCKET */
  1558. X
  1559. Xint
  1560. Xdo_gpwent(which,gimme,arglast)
  1561. Xint which;
  1562. Xint gimme;
  1563. Xint *arglast;
  1564. X{
  1565. X#ifdef I_PWD
  1566. X    register ARRAY *ary = stack;
  1567. X    register int sp = arglast[0];
  1568. X    register char **elem;
  1569. X    register STR *str;
  1570. X    struct passwd *getpwnam();
  1571. X    struct passwd *getpwuid();
  1572. X    struct passwd *getpwent();
  1573. X    struct passwd *pwent;
  1574. X    unsigned long len;
  1575. X
  1576. X    if (gimme != G_ARRAY) {
  1577. X    astore(ary, ++sp, str_static(&str_undef));
  1578. X    return sp;
  1579. X    }
  1580. X
  1581. X    if (which == O_GPWNAM) {
  1582. X    char *name = str_get(ary->ary_array[sp+1]);
  1583. X
  1584. X    pwent = getpwnam(name);
  1585. X    }
  1586. X    else if (which == O_GPWUID) {
  1587. X    int uid = (int)str_gnum(ary->ary_array[sp+1]);
  1588. X
  1589. X    pwent = getpwuid(uid);
  1590. X    }
  1591. X    else
  1592. X    pwent = getpwent();
  1593. X
  1594. X    if (pwent) {
  1595. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1596. X    str_set(str, pwent->pw_name);
  1597. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1598. X    str_set(str, pwent->pw_passwd);
  1599. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1600. X    str_numset(str, (double)pwent->pw_uid);
  1601. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1602. X    str_numset(str, (double)pwent->pw_gid);
  1603. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1604. X#ifdef PWQUOTA
  1605. X    str_numset(str, (double)pwent->pw_quota);
  1606. X#else
  1607. X#ifdef PWAGE
  1608. X    str_set(str, pwent->pw_age);
  1609. X#endif
  1610. X#endif
  1611. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1612. X    str_set(str, pwent->pw_comment);
  1613. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1614. X    str_set(str, pwent->pw_gecos);
  1615. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1616. X    str_set(str, pwent->pw_dir);
  1617. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1618. X    str_set(str, pwent->pw_shell);
  1619. X    }
  1620. X
  1621. X    return sp;
  1622. X#else
  1623. X    fatal("password routines not implemented");
  1624. X#endif
  1625. X}
  1626. X
  1627. Xint
  1628. Xdo_ggrent(which,gimme,arglast)
  1629. Xint which;
  1630. Xint gimme;
  1631. Xint *arglast;
  1632. X{
  1633. X#ifdef I_GRP
  1634. X    register ARRAY *ary = stack;
  1635. X    register int sp = arglast[0];
  1636. X    register char **elem;
  1637. X    register STR *str;
  1638. X    struct group *getgrnam();
  1639. X    struct group *getgrgid();
  1640. X    struct group *getgrent();
  1641. X    struct group *grent;
  1642. X    unsigned long len;
  1643. X
  1644. X    if (gimme != G_ARRAY) {
  1645. X    astore(ary, ++sp, str_static(&str_undef));
  1646. X    return sp;
  1647. X    }
  1648. X
  1649. X    if (which == O_GGRNAM) {
  1650. X    char *name = str_get(ary->ary_array[sp+1]);
  1651. X
  1652. X    grent = getgrnam(name);
  1653. X    }
  1654. X    else if (which == O_GGRGID) {
  1655. X    int gid = (int)str_gnum(ary->ary_array[sp+1]);
  1656. X
  1657. X    grent = getgrgid(gid);
  1658. X    }
  1659. X    else
  1660. X    grent = getgrent();
  1661. X
  1662. X    if (grent) {
  1663. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1664. X    str_set(str, grent->gr_name);
  1665. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1666. X    str_set(str, grent->gr_passwd);
  1667. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1668. X    str_numset(str, (double)grent->gr_gid);
  1669. X    (void)astore(ary, ++sp, str = str_static(&str_no));
  1670. X    for (elem = grent->gr_mem; *elem; elem++) {
  1671. X        str_cat(str, *elem);
  1672. X        if (elem[1])
  1673. X        str_ncat(str," ",1);
  1674. X    }
  1675. X    }
  1676. X
  1677. X    return sp;
  1678. X#else
  1679. X    fatal("group routines not implemented");
  1680. X#endif
  1681. X}
  1682. X
  1683. Xint
  1684. Xdo_dirop(optype,stab,gimme,arglast)
  1685. Xint optype;
  1686. XSTAB *stab;
  1687. Xint gimme;
  1688. Xint *arglast;
  1689. X{
  1690. X#ifdef DIRENT
  1691. X    register ARRAY *ary = stack;
  1692. X    register STR **st = ary->ary_array;
  1693. X    register int sp = arglast[1];
  1694. X    register STIO *stio;
  1695. X    long along;
  1696. X    long telldir();
  1697. X    struct DIRENT *readdir();
  1698. X    register struct DIRENT *dp;
  1699. X
  1700. X    if (!stab)
  1701. X    goto nope;
  1702. X    if (!(stio = stab_io(stab)))
  1703. X    stio = stab_io(stab) = stio_new();
  1704. X    if (!stio->dirp && optype != O_OPENDIR)
  1705. X    goto nope;
  1706. X    st[sp] = &str_yes;
  1707. X    switch (optype) {
  1708. X    case O_OPENDIR:
  1709. X    if (stio->dirp)
  1710. X        closedir(stio->dirp);
  1711. X    if (!(stio->dirp = opendir(str_get(st[sp+1]))))
  1712. X        goto nope;
  1713. X    break;
  1714. X    case O_READDIR:
  1715. X    if (gimme == G_ARRAY) {
  1716. X        --sp;
  1717. X        while (dp = readdir(stio->dirp)) {
  1718. X#ifdef DIRNAMLEN
  1719. X        (void)astore(ary,++sp,
  1720. X          str_2static(str_make(dp->d_name,dp->d_namlen)));
  1721. X#else
  1722. X        (void)astore(ary,++sp,
  1723. X          str_2static(str_make(dp->d_name,0)));
  1724. X#endif
  1725. X        }
  1726. X    }
  1727. X    else {
  1728. X        if (!(dp = readdir(stio->dirp)))
  1729. X        goto nope;
  1730. X        st[sp] = str_static(&str_undef);
  1731. X#ifdef DIRNAMLEN
  1732. X        str_nset(st[sp], dp->d_name, dp->d_namlen);
  1733. X#else
  1734. X        str_set(st[sp], dp->d_name);
  1735. X#endif
  1736. X    }
  1737. X    break;
  1738. X    case O_TELLDIR:
  1739. X    st[sp] = str_static(&str_undef);
  1740. X    str_numset(st[sp], (double)telldir(stio->dirp));
  1741. X    break;
  1742. X    case O_SEEKDIR:
  1743. X    st[sp] = str_static(&str_undef);
  1744. X    along = (long)str_gnum(st[sp+1]);
  1745. X    (void)seekdir(stio->dirp,along);
  1746. X    break;
  1747. X    case O_REWINDDIR:
  1748. X    st[sp] = str_static(&str_undef);
  1749. X    (void)rewinddir(stio->dirp);
  1750. X    break;
  1751. X    case O_CLOSEDIR:
  1752. X    st[sp] = str_static(&str_undef);
  1753. X    (void)closedir(stio->dirp);
  1754. X    stio->dirp = 0;
  1755. X    break;
  1756. X    }
  1757. X    return sp;
  1758. X
  1759. Xnope:
  1760. X    st[sp] = &str_undef;
  1761. X    return sp;
  1762. X
  1763. X#else
  1764. X    fatal("Unimplemented directory operation");
  1765. X#endif
  1766. X}
  1767. X
  1768. Xapply(type,arglast)
  1769. Xint type;
  1770. Xint *arglast;
  1771. X{
  1772. X    register STR **st = stack->ary_array;
  1773. X    register int sp = arglast[1];
  1774. X    register int items = arglast[2] - sp;
  1775. X    register int val;
  1776. X    register int val2;
  1777. X    register int tot = 0;
  1778. X    char *s;
  1779. X
  1780. X#ifdef TAINT
  1781. X    for (st += ++sp; items--; st++)
  1782. X    tainted |= (*st)->str_tainted;
  1783. X    st = stack->ary_array;
  1784. X    sp = arglast[1];
  1785. X    items = arglast[2] - sp;
  1786. X#endif
  1787. X    switch (type) {
  1788. X    case O_CHMOD:
  1789. X#ifdef TAINT
  1790. X    taintproper("Insecure dependency in chmod");
  1791. X#endif
  1792. X    if (--items > 0) {
  1793. X        tot = items;
  1794. X        val = (int)str_gnum(st[++sp]);
  1795. X        while (items--) {
  1796. X        if (chmod(str_get(st[++sp]),val))
  1797. X            tot--;
  1798. X        }
  1799. X    }
  1800. X    break;
  1801. X    case O_CHOWN:
  1802. X#ifdef TAINT
  1803. X    taintproper("Insecure dependency in chown");
  1804. X#endif
  1805. X    if (items > 2) {
  1806. X        items -= 2;
  1807. X        tot = items;
  1808. X        val = (int)str_gnum(st[++sp]);
  1809. X        val2 = (int)str_gnum(st[++sp]);
  1810. X        while (items--) {
  1811. X        if (chown(str_get(st[++sp]),val,val2))
  1812. X            tot--;
  1813. X        }
  1814. X    }
  1815. X    break;
  1816. X    case O_KILL:
  1817. X#ifdef TAINT
  1818. X    taintproper("Insecure dependency in kill");
  1819. X#endif
  1820. X    if (--items > 0) {
  1821. X        tot = items;
  1822. X        s = str_get(st[++sp]);
  1823. X        if (isupper(*s)) {
  1824. X        if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
  1825. X            s += 3;
  1826. X        if (!(val = whichsig(s)))
  1827. X            fatal("Unrecognized signal name \"%s\"",s);
  1828. X        }
  1829. X        else
  1830. X        val = (int)str_gnum(st[sp]);
  1831. X        if (val < 0) {
  1832. X        val = -val;
  1833. X        while (items--) {
  1834. X            int proc = (int)str_gnum(st[++sp]);
  1835. X#ifdef KILLPG
  1836. X            if (killpg(proc,val))    /* BSD */
  1837. X#else
  1838. X            if (kill(-proc,val))    /* SYSV */
  1839. X#endif
  1840. X            tot--;
  1841. X        }
  1842. X        }
  1843. X        else {
  1844. X        while (items--) {
  1845. X            if (kill((int)(str_gnum(st[++sp])),val))
  1846. X            tot--;
  1847. X        }
  1848. X        }
  1849. X    }
  1850. X    break;
  1851. X    case O_UNLINK:
  1852. X#ifdef TAINT
  1853. X    taintproper("Insecure dependency in unlink");
  1854. X#endif
  1855. X    tot = items;
  1856. X    while (items--) {
  1857. X        s = str_get(st[++sp]);
  1858. X        if (euid || unsafe) {
  1859. X        if (UNLINK(s))
  1860. X            tot--;
  1861. X        }
  1862. X        else {    /* don't let root wipe out directories without -U */
  1863. X#ifdef SYMLINK
  1864. X        if (lstat(s,&statbuf) < 0 ||
  1865. X#else
  1866. X        if (stat(s,&statbuf) < 0 ||
  1867. X#endif
  1868. X          (statbuf.st_mode & S_IFMT) == S_IFDIR )
  1869. X            tot--;
  1870. X        else {
  1871. X            if (UNLINK(s))
  1872. X            tot--;
  1873. X        }
  1874. X        }
  1875. X    }
  1876. X    break;
  1877. X    case O_UTIME:
  1878. X#ifdef TAINT
  1879. X    taintproper("Insecure dependency in utime");
  1880. X#endif
  1881. X    if (items > 2) {
  1882. X        struct {
  1883. X        long    atime,
  1884. X            mtime;
  1885. X        } utbuf;
  1886. X
  1887. X        utbuf.atime = (long)str_gnum(st[++sp]);    /* time accessed */
  1888. X        utbuf.mtime = (long)str_gnum(st[++sp]);    /* time modified */
  1889. X        items -= 2;
  1890. X#ifndef lint
  1891. X        tot = items;
  1892. X        while (items--) {
  1893. X        if (utime(str_get(st[++sp]),&utbuf))
  1894. X            tot--;
  1895. X        }
  1896. X#endif
  1897. X    }
  1898. X    else
  1899. X        items = 0;
  1900. X    break;
  1901. X    }
  1902. X    return tot;
  1903. X}
  1904. X
  1905. X/* Do the permissions allow some operation?  Assumes statcache already set. */
  1906. X
  1907. Xint
  1908. Xcando(bit, effective, statbufp)
  1909. Xint bit;
  1910. Xint effective;
  1911. Xregister struct stat *statbufp;
  1912. X{
  1913. X    if ((effective ? euid : uid) == 0) {    /* root is special */
  1914. X    if (bit == S_IEXEC) {
  1915. X        if (statbufp->st_mode & 0111 ||
  1916. X          (statbufp->st_mode & S_IFMT) == S_IFDIR )
  1917. X        return TRUE;
  1918. X    }
  1919. X    else
  1920. X        return TRUE;        /* root reads and writes anything */
  1921. X    return FALSE;
  1922. X    }
  1923. X    if (statbufp->st_uid == (effective ? euid : uid) ) {
  1924. X    if (statbufp->st_mode & bit)
  1925. X        return TRUE;    /* ok as "user" */
  1926. X    }
  1927. X    else if (ingroup((int)statbufp->st_gid,effective)) {
  1928. X    if (statbufp->st_mode & bit >> 3)
  1929. X        return TRUE;    /* ok as "group" */
  1930. X    }
  1931. X    else if (statbufp->st_mode & bit >> 6)
  1932. X    return TRUE;    /* ok as "other" */
  1933. X    return FALSE;
  1934. X}
  1935. X
  1936. Xint
  1937. Xingroup(testgid,effective)
  1938. Xint testgid;
  1939. Xint effective;
  1940. X{
  1941. X    if (testgid == (effective ? egid : gid))
  1942. X    return TRUE;
  1943. X#ifdef GETGROUPS
  1944. X#ifndef NGROUPS
  1945. X#define NGROUPS 32
  1946. X#endif
  1947. X    {
  1948. X    GIDTYPE gary[NGROUPS];
  1949. X    int anum;
  1950. X
  1951. X    anum = getgroups(NGROUPS,gary);
  1952. X    while (--anum >= 0)
  1953. X        if (gary[anum] == testgid)
  1954. X        return TRUE;
  1955. X    }
  1956. X#endif
  1957. X    return FALSE;
  1958. X}
  1959. !STUFFY!FUNK!
  1960. echo Extracting regcomp.h
  1961. sed >regcomp.h <<'!STUFFY!FUNK!' -e 's/X//'
  1962. X/* $Header: regcomp.h,v 3.0 89/10/18 15:22:39 lwall Locked $
  1963. X *
  1964. X * $Log:    regcomp.h,v $
  1965. X * Revision 3.0  89/10/18  15:22:39  lwall
  1966. X * 3.0 baseline
  1967. X * 
  1968. X */
  1969. X
  1970. X/*
  1971. X * The "internal use only" fields in regexp.h are present to pass info from
  1972. X * compile to execute that permits the execute phase to run lots faster on
  1973. X * simple cases.  They are:
  1974. X *
  1975. X * regstart    str that must begin a match; Nullch if none obvious
  1976. X * reganch    is the match anchored (at beginning-of-line only)?
  1977. X * regmust    string (pointer into program) that match must include, or NULL
  1978. X *  [regmust changed to STR* for bminstr()--law]
  1979. X * regmlen    length of regmust string
  1980. X *  [regmlen not used currently]
  1981. X *
  1982. X * Regstart and reganch permit very fast decisions on suitable starting points
  1983. X * for a match, cutting down the work a lot.  Regmust permits fast rejection
  1984. X * of lines that cannot possibly match.  The regmust tests are costly enough
  1985. X * that regcomp() supplies a regmust only if the r.e. contains something
  1986. X * potentially expensive (at present, the only such thing detected is * or +
  1987. X * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  1988. X * supplied because the test in regexec() needs it and regcomp() is computing
  1989. X * it anyway.
  1990. X * [regmust is now supplied always.  The tests that use regmust have a
  1991. X * heuristic that disables the test if it usually matches.]
  1992. X *
  1993. X * [In fact, we now use regmust in many cases to locate where the search
  1994. X * starts in the string, so if regback is >= 0, the regmust search is never
  1995. X * wasted effort.  The regback variable says how many characters back from
  1996. X * where regmust matched is the earliest possible start of the match.
  1997. X * For instance, /[a-z].foo/ has a regmust of 'foo' and a regback of 2.]
  1998. X */
  1999. X
  2000. X/*
  2001. X * Structure for regexp "program".  This is essentially a linear encoding
  2002. X * of a nondeterministic finite-state machine (aka syntax charts or
  2003. X * "railroad normal form" in parsing technology).  Each node is an opcode
  2004. X * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  2005. X * all nodes except BRANCH implement concatenation; a "next" pointer with
  2006. X * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  2007. X * have one of the subtle syntax dependencies:  an individual BRANCH (as
  2008. X * opposed to a collection of them) is never concatenated with anything
  2009. X * because of operator precedence.)  The operand of some types of node is
  2010. X * a literal string; for others, it is a node leading into a sub-FSM.  In
  2011. X * particular, the operand of a BRANCH node is the first node of the branch.
  2012. X * (NB this is *not* a tree structure:  the tail of the branch connects
  2013. X * to the thing following the set of BRANCHes.)  The opcodes are:
  2014. X */
  2015. X
  2016. X/* definition    number    opnd?    meaning */
  2017. X#define    END    0    /* no    End of program. */
  2018. X#define    BOL    1    /* no    Match "" at beginning of line. */
  2019. X#define    EOL    2    /* no    Match "" at end of line. */
  2020. X#define    ANY    3    /* no    Match any one character. */
  2021. X#define    ANYOF    4    /* str    Match any character in this string. */
  2022. X#define    ANYBUT    5    /* str    Match any character not in this string. */
  2023. X#define    BRANCH    6    /* node    Match this alternative, or the next... */
  2024. X#define    BACK    7    /* no    Match "", "next" ptr points backward. */
  2025. X#define    EXACTLY    8    /* str    Match this string (preceded by length). */
  2026. X#define    NOTHING    9    /* no    Match empty string. */
  2027. X#define    STAR    10    /* node    Match this (simple) thing 0 or more times. */
  2028. X#define    PLUS    11    /* node    Match this (simple) thing 1 or more times. */
  2029. X#define ALNUM    12    /* no    Match any alphanumeric character */
  2030. X#define NALNUM    13    /* no    Match any non-alphanumeric character */
  2031. X#define BOUND    14    /* no    Match "" at any word boundary */
  2032. X#define NBOUND    15    /* no    Match "" at any word non-boundary */
  2033. X#define SPACE    16    /* no    Match any whitespace character */
  2034. X#define NSPACE    17    /* no    Match any non-whitespace character */
  2035. X#define DIGIT    18    /* no    Match any numeric character */
  2036. X#define NDIGIT    19    /* no    Match any non-numeric character */
  2037. X#define REF    20    /* no    Match some already matched string */
  2038. X#define    OPEN    30    /* no    Mark this point in input as start of #n. */
  2039. X            /*    OPEN+1 is number 1, etc. */
  2040. X#define    CLOSE    40    /* no    Analogous to OPEN. */
  2041. X/* CLOSE must be last one! see regmust finder */
  2042. X
  2043. X/*
  2044. X * Opcode notes:
  2045. X *
  2046. X * BRANCH    The set of branches constituting a single choice are hooked
  2047. X *        together with their "next" pointers, since precedence prevents
  2048. X *        anything being concatenated to any individual branch.  The
  2049. X *        "next" pointer of the last BRANCH in a choice points to the
  2050. X *        thing following the whole choice.  This is also where the
  2051. X *        final "next" pointer of each individual branch points; each
  2052. X *        branch starts with the operand node of a BRANCH node.
  2053. X *
  2054. X * BACK        Normal "next" pointers all implicitly point forward; BACK
  2055. X *        exists to make loop structures possible.
  2056. X *
  2057. X * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
  2058. X *        BRANCH structures using BACK.  Simple cases (one character
  2059. X *        per match) are implemented with STAR and PLUS for speed
  2060. X *        and to minimize recursive plunges.
  2061. X *
  2062. X * OPEN,CLOSE    ...are numbered at compile time.
  2063. X */
  2064. X
  2065. X/* The following have no fixed length. */
  2066. X#ifndef DOINIT
  2067. Xextern char varies[];
  2068. X#else
  2069. Xchar varies[] = {BRANCH,BACK,STAR,PLUS,
  2070. X    REF+1,REF+2,REF+3,REF+4,REF+5,REF+6,REF+7,REF+8,REF+9,0};
  2071. X#endif
  2072. X
  2073. X/* The following always have a length of 1. */
  2074. X#ifndef DOINIT
  2075. Xextern char simple[];
  2076. X#else
  2077. Xchar simple[] = {ANY,ANYOF,ANYBUT,ALNUM,NALNUM,SPACE,NSPACE,DIGIT,NDIGIT,0};
  2078. X#endif
  2079. X
  2080. XEXT char regdummy;
  2081. X
  2082. X/*
  2083. X * A node is one char of opcode followed by two chars of "next" pointer.
  2084. X * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  2085. X * value is a positive offset from the opcode of the node containing it.
  2086. X * An operand, if any, simply follows the node.  (Note that much of the
  2087. X * code generation knows about this implicit relationship.)
  2088. X *
  2089. X * Using two bytes for the "next" pointer is vast overkill for most things,
  2090. X * but allows patterns to get big without disasters.
  2091. X *
  2092. X * [If REGALIGN is defined, the "next" pointer is always aligned on an even
  2093. X * boundary, and reads the offset directly as a short.  Also, there is no
  2094. X * special test to reverse the sign of BACK pointers since the offset is
  2095. X * stored negative.]
  2096. X */
  2097. X
  2098. X#ifndef gould
  2099. X#ifndef cray
  2100. X#define REGALIGN
  2101. X#endif
  2102. X#endif
  2103. X
  2104. X#define    OP(p)    (*(p))
  2105. X
  2106. X#ifndef lint
  2107. X#ifdef REGALIGN
  2108. X#define NEXT(p) (*(short*)(p+1))
  2109. X#else
  2110. X#define    NEXT(p)    (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
  2111. X#endif
  2112. X#else /* lint */
  2113. X#define NEXT(p) 0
  2114. X#endif /* lint */
  2115. X
  2116. X#define    OPERAND(p)    ((p) + 3)
  2117. X
  2118. X#ifdef REGALIGN
  2119. X#define    NEXTOPER(p)    ((p) + 4)
  2120. X#else
  2121. X#define    NEXTOPER(p)    ((p) + 3)
  2122. X#endif
  2123. X
  2124. X#define MAGIC 0234
  2125. X
  2126. X/*
  2127. X * Utility definitions.
  2128. X */
  2129. X#ifndef lint
  2130. X#ifndef CHARBITS
  2131. X#define    UCHARAT(p)    ((int)*(unsigned char *)(p))
  2132. X#else
  2133. X#define    UCHARAT(p)    ((int)*(p)&CHARBITS)
  2134. X#endif
  2135. X#else /* lint */
  2136. X#define UCHARAT(p)    regdummy
  2137. X#endif /* lint */
  2138. X
  2139. X#define    FAIL(m)    fatal("/%s/: %s",regprecomp,m)
  2140. X
  2141. Xchar *regnext();
  2142. X#ifdef DEBUGGING
  2143. Xvoid regdump();
  2144. Xchar *regprop();
  2145. X#endif
  2146. X
  2147. !STUFFY!FUNK!
  2148. echo ""
  2149. echo "End of kit 7 (of 24)"
  2150. cat /dev/null >kit7isdone
  2151. run=''
  2152. config=''
  2153. for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; do
  2154.     if test -f kit${iskit}isdone; then
  2155.     run="$run $iskit"
  2156.     else
  2157.     todo="$todo $iskit"
  2158.     fi
  2159. done
  2160. case $todo in
  2161.     '')
  2162.     echo "You have run all your kits.  Please read README and then type Configure."
  2163.     chmod 755 Configure
  2164.     ;;
  2165.     *)  echo "You have run$run."
  2166.     echo "You still need to run$todo."
  2167.     ;;
  2168. esac
  2169. : Someone might mail this, so...
  2170. exit
  2171.  
  2172.