home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume18 / perl / part03 < prev    next >
Internet Message Format  |  1991-04-14  |  52KB

  1. From: lwall@netlabs.com (Larry Wall)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i021:  perl - The perl programming language, Part03/36
  4. Message-ID: <1991Apr15.015255.6606@sparky.IMD.Sterling.COM>
  5. Date: 15 Apr 91 01:52:55 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: da963dae 59afafe5 01ae7e75 426ec3bc
  8.  
  9. Submitted-by: Larry Wall <lwall@netlabs.com>
  10. Posting-number: Volume 18, Issue 21
  11. Archive-name: perl/part03
  12.  
  13. [There are 36 kits for perl version 4.0.]
  14.  
  15. #! /bin/sh
  16.  
  17. # Make a new directory for the perl sources, cd to it, and run kits 1
  18. # thru 36 through sh.  When all 36 kits have been run, read README.
  19.  
  20. echo "This is perl 4.0 kit 3 (of 36).  If kit 3 is complete, the line"
  21. echo '"'"End of kit 3 (of 36)"'" will echo at the end.'
  22. echo ""
  23. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  24. mkdir  2>/dev/null
  25. echo Extracting doio.c:AA
  26. sed >doio.c:AA <<'!STUFFY!FUNK!' -e 's/X//'
  27. X/* $RCSfile: doio.c,v $$Revision: 4.0.1.1 $$Date: 91/04/11 17:41:06 $
  28. X *
  29. X *    Copyright (c) 1989, Larry Wall
  30. X *
  31. X *    You may distribute under the terms of the GNU General Public License
  32. X *    as specified in the README file that comes with the perl 3.0 kit.
  33. X *
  34. X * $Log:    doio.c,v $
  35. X * Revision 4.0.1.1  91/04/11  17:41:06  lwall
  36. X * patch1: hopefully straightened out some of the Xenix mess
  37. X * 
  38. X * Revision 4.0  91/03/20  01:07:06  lwall
  39. X * 4.0 baseline.
  40. X * 
  41. X */
  42. X
  43. X#include "EXTERN.h"
  44. X#include "perl.h"
  45. X
  46. X#ifdef HAS_SOCKET
  47. X#include <sys/socket.h>
  48. X#include <netdb.h>
  49. X#endif
  50. X
  51. X#ifdef HAS_SELECT
  52. X#ifdef I_SYS_SELECT
  53. X#ifndef I_SYS_TIME
  54. X#include <sys/select.h>
  55. X#endif
  56. X#endif
  57. X#endif
  58. X
  59. X#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
  60. X#include <sys/ipc.h>
  61. X#ifdef HAS_MSG
  62. X#include <sys/msg.h>
  63. X#endif
  64. X#ifdef HAS_SEM
  65. X#include <sys/sem.h>
  66. X#endif
  67. X#ifdef HAS_SHM
  68. X#include <sys/shm.h>
  69. X#endif
  70. X#endif
  71. X
  72. X#ifdef I_PWD
  73. X#include <pwd.h>
  74. X#endif
  75. X#ifdef I_GRP
  76. X#include <grp.h>
  77. X#endif
  78. X#ifdef I_UTIME
  79. X#include <utime.h>
  80. X#endif
  81. X#ifdef I_FCNTL
  82. X#include <fcntl.h>
  83. X#endif
  84. X#ifdef I_SYS_FILE
  85. X#include <sys/file.h>
  86. X#endif
  87. X
  88. Xint laststatval = -1;
  89. Xint laststype = O_STAT;
  90. X
  91. Xbool
  92. Xdo_open(stab,name,len)
  93. XSTAB *stab;
  94. Xregister char *name;
  95. Xint len;
  96. X{
  97. X    FILE *fp;
  98. X    register STIO *stio = stab_io(stab);
  99. X    char *myname = savestr(name);
  100. X    int result;
  101. X    int fd;
  102. X    int writing = 0;
  103. X    char mode[3];        /* stdio file mode ("r\0" or "r+\0") */
  104. X
  105. X    name = myname;
  106. X    forkprocess = 1;        /* assume true if no fork */
  107. X    while (len && isspace(name[len-1]))
  108. X    name[--len] = '\0';
  109. X    if (!stio)
  110. X    stio = stab_io(stab) = stio_new();
  111. X    else if (stio->ifp) {
  112. X    fd = fileno(stio->ifp);
  113. X    if (stio->type == '|')
  114. X        result = mypclose(stio->ifp);
  115. X    else if (stio->type == '-')
  116. X        result = 0;
  117. X    else if (stio->ifp != stio->ofp) {
  118. X        if (stio->ofp) {
  119. X        result = fclose(stio->ofp);
  120. X        fclose(stio->ifp);    /* clear stdio, fd already closed */
  121. X        }
  122. X        else
  123. X        result = fclose(stio->ifp);
  124. X    }
  125. X    else
  126. X        result = fclose(stio->ifp);
  127. X    if (result == EOF && fd > 2)
  128. X        fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
  129. X          stab_name(stab));
  130. X    stio->ofp = stio->ifp = Nullfp;
  131. X    }
  132. X    if (*name == '+' && len > 1 && name[len-1] != '|') {    /* scary */
  133. X    mode[1] = *name++;
  134. X    mode[2] = '\0';
  135. X    --len;
  136. X    writing = 1;
  137. X    }
  138. X    else  {
  139. X    mode[1] = '\0';
  140. X    }
  141. X    stio->type = *name;
  142. X    if (*name == '|') {
  143. X    for (name++; isspace(*name); name++) ;
  144. X#ifdef TAINT
  145. X    taintenv();
  146. X    taintproper("Insecure dependency in piped open");
  147. X#endif
  148. X    fp = mypopen(name,"w");
  149. X    writing = 1;
  150. X    }
  151. X    else if (*name == '>') {
  152. X#ifdef TAINT
  153. X    taintproper("Insecure dependency in open");
  154. X#endif
  155. X    name++;
  156. X    if (*name == '>') {
  157. X        mode[0] = stio->type = 'a';
  158. X        name++;
  159. X    }
  160. X    else
  161. X        mode[0] = 'w';
  162. X    writing = 1;
  163. X    if (*name == '&') {
  164. X      duplicity:
  165. X        name++;
  166. X        while (isspace(*name))
  167. X        name++;
  168. X        if (isdigit(*name))
  169. X        fd = atoi(name);
  170. X        else {
  171. X        stab = stabent(name,FALSE);
  172. X        if (!stab || !stab_io(stab))
  173. X            return FALSE;
  174. X        if (stab_io(stab) && stab_io(stab)->ifp) {
  175. X            fd = fileno(stab_io(stab)->ifp);
  176. X            if (stab_io(stab)->type == 's')
  177. X            stio->type = 's';
  178. X        }
  179. X        else
  180. X            fd = -1;
  181. X        }
  182. X        if (!(fp = fdopen(fd = dup(fd),mode))) {
  183. X        close(fd);
  184. X        }
  185. X    }
  186. X    else {
  187. X        while (isspace(*name))
  188. X        name++;
  189. X        if (strEQ(name,"-")) {
  190. X        fp = stdout;
  191. X        stio->type = '-';
  192. X        }
  193. X        else  {
  194. X        fp = fopen(name,mode);
  195. X        }
  196. X    }
  197. X    }
  198. X    else {
  199. X    if (*name == '<') {
  200. X        mode[0] = 'r';
  201. X        name++;
  202. X        while (isspace(*name))
  203. X        name++;
  204. X        if (*name == '&')
  205. X        goto duplicity;
  206. X        if (strEQ(name,"-")) {
  207. X        fp = stdin;
  208. X        stio->type = '-';
  209. X        }
  210. X        else
  211. X        fp = fopen(name,mode);
  212. X    }
  213. X    else if (name[len-1] == '|') {
  214. X#ifdef TAINT
  215. X        taintenv();
  216. X        taintproper("Insecure dependency in piped open");
  217. X#endif
  218. X        name[--len] = '\0';
  219. X        while (len && isspace(name[len-1]))
  220. X        name[--len] = '\0';
  221. X        for (; isspace(*name); name++) ;
  222. X        fp = mypopen(name,"r");
  223. X        stio->type = '|';
  224. X    }
  225. X    else {
  226. X        stio->type = '<';
  227. X        for (; isspace(*name); name++) ;
  228. X        if (strEQ(name,"-")) {
  229. X        fp = stdin;
  230. X        stio->type = '-';
  231. X        }
  232. X        else
  233. X        fp = fopen(name,"r");
  234. X    }
  235. X    }
  236. X    Safefree(myname);
  237. X    if (!fp)
  238. X    return FALSE;
  239. X    if (stio->type &&
  240. X      stio->type != '|' && stio->type != '-') {
  241. X    if (fstat(fileno(fp),&statbuf) < 0) {
  242. X        (void)fclose(fp);
  243. X        return FALSE;
  244. X    }
  245. X    if (S_ISSOCK(statbuf.st_mode))
  246. X        stio->type = 's';    /* in case a socket was passed in to us */
  247. X#ifdef S_IFMT
  248. X    else if (!(statbuf.st_mode & S_IFMT))
  249. X        stio->type = 's';    /* some OS's return 0 on fstat()ed socket */
  250. X#endif
  251. X    }
  252. X#if defined(HAS_FCNTL) && defined(F_SETFD)
  253. X    fd = fileno(fp);
  254. X    fcntl(fd,F_SETFD,fd >= 3);
  255. X#endif
  256. X    stio->ifp = fp;
  257. X    if (writing) {
  258. X    if (stio->type != 's')
  259. X        stio->ofp = fp;
  260. X    else
  261. X        if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
  262. X        fclose(fp);
  263. X        stio->ifp = Nullfp;
  264. X        }
  265. X    }
  266. X    return TRUE;
  267. X}
  268. X
  269. XFILE *
  270. Xnextargv(stab)
  271. Xregister STAB *stab;
  272. X{
  273. X    register STR *str;
  274. X    int filedev;
  275. X    int fileino;
  276. X    int fileuid;
  277. X    int filegid;
  278. X    static int filemode = 0;
  279. X    static int lastfd;
  280. X    static char *oldname;
  281. X
  282. X    if (!argvoutstab)
  283. X    argvoutstab = stabent("ARGVOUT",TRUE);
  284. X    if (filemode & (S_ISUID|S_ISGID)) {
  285. X    fflush(stab_io(argvoutstab)->ifp);  /* chmod must follow last write */
  286. X#ifdef HAS_FCHMOD
  287. X    (void)fchmod(lastfd,filemode);
  288. X#else
  289. X    (void)chmod(oldname,filemode);
  290. X#endif
  291. X    }
  292. X    filemode = 0;
  293. X    while (alen(stab_xarray(stab)) >= 0) {
  294. X    str = ashift(stab_xarray(stab));
  295. X    str_sset(stab_val(stab),str);
  296. X    STABSET(stab_val(stab));
  297. X    oldname = str_get(stab_val(stab));
  298. X    if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
  299. X        if (inplace) {
  300. X#ifdef TAINT
  301. X        taintproper("Insecure dependency in inplace open");
  302. X#endif
  303. X        if (strEQ(oldname,"-")) {
  304. X            str_free(str);
  305. X            defoutstab = stabent("STDOUT",TRUE);
  306. X            return stab_io(stab)->ifp;
  307. X        }
  308. X        filedev = statbuf.st_dev;
  309. X        fileino = statbuf.st_ino;
  310. X        filemode = statbuf.st_mode;
  311. X        fileuid = statbuf.st_uid;
  312. X        filegid = statbuf.st_gid;
  313. X        if (!S_ISREG(filemode)) {
  314. X            warn("Can't do inplace edit: %s is not a regular file",
  315. X              oldname );
  316. X            do_close(stab,FALSE);
  317. X            str_free(str);
  318. X            continue;
  319. X        }
  320. X        if (*inplace) {
  321. X#ifdef SUFFIX
  322. X            add_suffix(str,inplace);
  323. X#else
  324. X            str_cat(str,inplace);
  325. X#endif
  326. X#ifndef FLEXFILENAMES
  327. X            if (stat(str->str_ptr,&statbuf) >= 0
  328. X              && statbuf.st_dev == filedev
  329. X              && statbuf.st_ino == fileino ) {
  330. X            warn("Can't do inplace edit: %s > 14 characters",
  331. X              str->str_ptr );
  332. X            do_close(stab,FALSE);
  333. X            str_free(str);
  334. X            continue;
  335. X            }
  336. X#endif
  337. X#ifdef HAS_RENAME
  338. X#ifndef MSDOS
  339. X            if (rename(oldname,str->str_ptr) < 0) {
  340. X            warn("Can't rename %s to %s: %s, skipping file",
  341. X              oldname, str->str_ptr, strerror(errno) );
  342. X            do_close(stab,FALSE);
  343. X            str_free(str);
  344. X            continue;
  345. X            }
  346. X#else
  347. X            do_close(stab,FALSE);
  348. X            (void)unlink(str->str_ptr);
  349. X            (void)rename(oldname,str->str_ptr);
  350. X            do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
  351. X#endif /* MSDOS */
  352. X#else
  353. X            (void)UNLINK(str->str_ptr);
  354. X            if (link(oldname,str->str_ptr) < 0) {
  355. X            warn("Can't rename %s to %s: %s, skipping file",
  356. X              oldname, str->str_ptr, strerror(errno) );
  357. X            do_close(stab,FALSE);
  358. X            str_free(str);
  359. X            continue;
  360. X            }
  361. X            (void)UNLINK(oldname);
  362. X#endif
  363. X        }
  364. X        else {
  365. X#ifndef MSDOS
  366. X            if (UNLINK(oldname) < 0) {
  367. X            warn("Can't rename %s to %s: %s, skipping file",
  368. X              oldname, str->str_ptr, strerror(errno) );
  369. X            do_close(stab,FALSE);
  370. X            str_free(str);
  371. X            continue;
  372. X            }
  373. X#else
  374. X            fatal("Can't do inplace edit without backup");
  375. X#endif
  376. X        }
  377. X
  378. X        str_nset(str,">",1);
  379. X        str_cat(str,oldname);
  380. X        errno = 0;        /* in case sprintf set errno */
  381. X        if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
  382. X            warn("Can't do inplace edit on %s: %s",
  383. X              oldname, strerror(errno) );
  384. X            do_close(stab,FALSE);
  385. X            str_free(str);
  386. X            continue;
  387. X        }
  388. X        defoutstab = argvoutstab;
  389. X        lastfd = fileno(stab_io(argvoutstab)->ifp);
  390. X        (void)fstat(lastfd,&statbuf);
  391. X#ifdef HAS_FCHMOD
  392. X        (void)fchmod(lastfd,filemode);
  393. X#else
  394. X        (void)chmod(oldname,filemode);
  395. X#endif
  396. X        if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
  397. X#ifdef HAS_FCHOWN
  398. X            (void)fchown(lastfd,fileuid,filegid);
  399. X#else
  400. X#ifdef HAS_CHOWN
  401. X            (void)chown(oldname,fileuid,filegid);
  402. X#endif
  403. X#endif
  404. X        }
  405. X        }
  406. X        str_free(str);
  407. X        return stab_io(stab)->ifp;
  408. X    }
  409. X    else
  410. X        fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
  411. X    str_free(str);
  412. X    }
  413. X    if (inplace) {
  414. X    (void)do_close(argvoutstab,FALSE);
  415. X    defoutstab = stabent("STDOUT",TRUE);
  416. X    }
  417. X    return Nullfp;
  418. X}
  419. X
  420. X#ifdef HAS_PIPE
  421. Xvoid
  422. Xdo_pipe(str, rstab, wstab)
  423. XSTR *str;
  424. XSTAB *rstab;
  425. XSTAB *wstab;
  426. X{
  427. X    register STIO *rstio;
  428. X    register STIO *wstio;
  429. X    int fd[2];
  430. X
  431. X    if (!rstab)
  432. X    goto badexit;
  433. X    if (!wstab)
  434. X    goto badexit;
  435. X
  436. X    rstio = stab_io(rstab);
  437. X    wstio = stab_io(wstab);
  438. X
  439. X    if (!rstio)
  440. X    rstio = stab_io(rstab) = stio_new();
  441. X    else if (rstio->ifp)
  442. X    do_close(rstab,FALSE);
  443. X    if (!wstio)
  444. X    wstio = stab_io(wstab) = stio_new();
  445. X    else if (wstio->ifp)
  446. X    do_close(wstab,FALSE);
  447. X
  448. X    if (pipe(fd) < 0)
  449. X    goto badexit;
  450. X    rstio->ifp = fdopen(fd[0], "r");
  451. X    wstio->ofp = fdopen(fd[1], "w");
  452. X    wstio->ifp = wstio->ofp;
  453. X    rstio->type = '<';
  454. X    wstio->type = '>';
  455. X    if (!rstio->ifp || !wstio->ofp) {
  456. X    if (rstio->ifp) fclose(rstio->ifp);
  457. X    else close(fd[0]);
  458. X    if (wstio->ofp) fclose(wstio->ofp);
  459. X    else close(fd[1]);
  460. X    goto badexit;
  461. X    }
  462. X
  463. X    str_sset(str,&str_yes);
  464. X    return;
  465. X
  466. Xbadexit:
  467. X    str_sset(str,&str_undef);
  468. X    return;
  469. X}
  470. X#endif
  471. X
  472. Xbool
  473. Xdo_close(stab,explicit)
  474. XSTAB *stab;
  475. Xbool explicit;
  476. X{
  477. X    bool retval = FALSE;
  478. X    register STIO *stio;
  479. X    int status;
  480. X
  481. X    if (!stab)
  482. X    stab = argvstab;
  483. X    if (!stab)
  484. X    return FALSE;
  485. X    stio = stab_io(stab);
  486. X    if (!stio) {        /* never opened */
  487. X    if (dowarn && explicit)
  488. X        warn("Close on unopened file <%s>",stab_name(stab));
  489. X    return FALSE;
  490. X    }
  491. X    if (stio->ifp) {
  492. X    if (stio->type == '|') {
  493. X        status = mypclose(stio->ifp);
  494. X        retval = (status == 0);
  495. X        statusvalue = (unsigned short)status & 0xffff;
  496. X    }
  497. X    else if (stio->type == '-')
  498. X        retval = TRUE;
  499. X    else {
  500. X        if (stio->ofp && stio->ofp != stio->ifp) {        /* a socket */
  501. X        retval = (fclose(stio->ofp) != EOF);
  502. X        fclose(stio->ifp);    /* clear stdio, fd already closed */
  503. X        }
  504. X        else
  505. X        retval = (fclose(stio->ifp) != EOF);
  506. X    }
  507. X    stio->ofp = stio->ifp = Nullfp;
  508. X    }
  509. X    if (explicit)
  510. X    stio->lines = 0;
  511. X    stio->type = ' ';
  512. X    return retval;
  513. X}
  514. X
  515. Xbool
  516. Xdo_eof(stab)
  517. XSTAB *stab;
  518. X{
  519. X    register STIO *stio;
  520. X    int ch;
  521. X
  522. X    if (!stab) {            /* eof() */
  523. X    if (argvstab)
  524. X        stio = stab_io(argvstab);
  525. X    else
  526. X        return TRUE;
  527. X    }
  528. X    else
  529. X    stio = stab_io(stab);
  530. X
  531. X    if (!stio)
  532. X    return TRUE;
  533. X
  534. X    while (stio->ifp) {
  535. X
  536. X#ifdef STDSTDIO            /* (the code works without this) */
  537. X    if (stio->ifp->_cnt > 0)    /* cheat a little, since */
  538. X        return FALSE;        /* this is the most usual case */
  539. X#endif
  540. X
  541. X    ch = getc(stio->ifp);
  542. X    if (ch != EOF) {
  543. X        (void)ungetc(ch, stio->ifp);
  544. X        return FALSE;
  545. X    }
  546. X#ifdef STDSTDIO
  547. X    if (stio->ifp->_cnt < -1)
  548. X        stio->ifp->_cnt = -1;
  549. X#endif
  550. X    if (!stab) {            /* not necessarily a real EOF yet? */
  551. X        if (!nextargv(argvstab))    /* get another fp handy */
  552. X        return TRUE;
  553. X    }
  554. X    else
  555. X        return TRUE;        /* normal fp, definitely end of file */
  556. X    }
  557. X    return TRUE;
  558. X}
  559. X
  560. Xlong
  561. Xdo_tell(stab)
  562. XSTAB *stab;
  563. X{
  564. X    register STIO *stio;
  565. X
  566. X    if (!stab)
  567. X    goto phooey;
  568. X
  569. X    stio = stab_io(stab);
  570. X    if (!stio || !stio->ifp)
  571. X    goto phooey;
  572. X
  573. X    if (feof(stio->ifp))
  574. X    (void)fseek (stio->ifp, 0L, 2);        /* ultrix 1.2 workaround */
  575. X
  576. X    return ftell(stio->ifp);
  577. X
  578. Xphooey:
  579. X    if (dowarn)
  580. X    warn("tell() on unopened file");
  581. X    return -1L;
  582. X}
  583. X
  584. Xbool
  585. Xdo_seek(stab, pos, whence)
  586. XSTAB *stab;
  587. Xlong pos;
  588. Xint whence;
  589. X{
  590. X    register STIO *stio;
  591. X
  592. X    if (!stab)
  593. X    goto nuts;
  594. X
  595. X    stio = stab_io(stab);
  596. X    if (!stio || !stio->ifp)
  597. X    goto nuts;
  598. X
  599. X    if (feof(stio->ifp))
  600. X    (void)fseek (stio->ifp, 0L, 2);        /* ultrix 1.2 workaround */
  601. X
  602. X    return fseek(stio->ifp, pos, whence) >= 0;
  603. X
  604. Xnuts:
  605. X    if (dowarn)
  606. X    warn("seek() on unopened file");
  607. X    return FALSE;
  608. X}
  609. X
  610. Xint
  611. Xdo_ctl(optype,stab,func,argstr)
  612. Xint optype;
  613. XSTAB *stab;
  614. Xint func;
  615. XSTR *argstr;
  616. X{
  617. X    register STIO *stio;
  618. X    register char *s;
  619. X    int retval;
  620. X
  621. X    if (!stab || !argstr)
  622. X    return -1;
  623. X    stio = stab_io(stab);
  624. X    if (!stio)
  625. X    return -1;
  626. X
  627. X    if (argstr->str_pok || !argstr->str_nok) {
  628. X    if (!argstr->str_pok)
  629. X        s = str_get(argstr);
  630. X
  631. X#ifdef IOCPARM_MASK
  632. X#ifndef IOCPARM_LEN
  633. X#define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
  634. X#endif
  635. X#endif
  636. X#ifdef IOCPARM_LEN
  637. X    retval = IOCPARM_LEN(func);    /* on BSDish systes we're safe */
  638. X#else
  639. X    retval = 256;            /* otherwise guess at what's safe */
  640. X#endif
  641. X    if (argstr->str_cur < retval) {
  642. X        Str_Grow(argstr,retval+1);
  643. X        argstr->str_cur = retval;
  644. X    }
  645. X
  646. X    s = argstr->str_ptr;
  647. X    s[argstr->str_cur] = 17;    /* a little sanity check here */
  648. X    }
  649. X    else {
  650. X    retval = (int)str_gnum(argstr);
  651. X#ifdef MSDOS
  652. X    s = (char*)(long)retval;        /* ouch */
  653. X#else
  654. X    s = (char*)retval;        /* ouch */
  655. X#endif
  656. X    }
  657. X
  658. X#ifndef lint
  659. X    if (optype == O_IOCTL)
  660. X    retval = ioctl(fileno(stio->ifp), func, s);
  661. X    else
  662. X#ifdef MSDOS
  663. X    fatal("fcntl is not implemented");
  664. X#else
  665. X#ifdef HAS_FCNTL
  666. X    retval = fcntl(fileno(stio->ifp), func, s);
  667. X#else
  668. X    fatal("fcntl is not implemented");
  669. X#endif
  670. X#endif
  671. X#else /* lint */
  672. X    retval = 0;
  673. X#endif /* lint */
  674. X
  675. X    if (argstr->str_pok) {
  676. X    if (s[argstr->str_cur] != 17)
  677. X        fatal("Return value overflowed string");
  678. X    s[argstr->str_cur] = 0;        /* put our null back */
  679. X    }
  680. X    return retval;
  681. X}
  682. X
  683. Xint
  684. Xdo_stat(str,arg,gimme,arglast)
  685. XSTR *str;
  686. Xregister ARG *arg;
  687. Xint gimme;
  688. Xint *arglast;
  689. X{
  690. X    register ARRAY *ary = stack;
  691. X    register int sp = arglast[0] + 1;
  692. X    int max = 13;
  693. X
  694. X    if ((arg[1].arg_type & A_MASK) == A_WORD) {
  695. X    tmpstab = arg[1].arg_ptr.arg_stab;
  696. X    if (tmpstab != defstab) {
  697. X        laststype = O_STAT;
  698. X        statstab = tmpstab;
  699. X        str_set(statname,"");
  700. X        if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
  701. X          fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
  702. X        max = 0;
  703. X        laststatval = -1;
  704. X        }
  705. X    }
  706. X    else if (laststatval < 0)
  707. X        max = 0;
  708. X    }
  709. X    else {
  710. X    str_set(statname,str_get(ary->ary_array[sp]));
  711. X    statstab = Nullstab;
  712. X#ifdef HAS_LSTAT
  713. X    laststype = arg->arg_type;
  714. X    if (arg->arg_type == O_LSTAT)
  715. X        laststatval = lstat(str_get(statname),&statcache);
  716. X    else
  717. X#endif
  718. X        laststatval = stat(str_get(statname),&statcache);
  719. X    if (laststatval < 0)
  720. X        max = 0;
  721. X    }
  722. X
  723. X    if (gimme != G_ARRAY) {
  724. X    if (max)
  725. X        str_sset(str,&str_yes);
  726. X    else
  727. X        str_sset(str,&str_undef);
  728. X    STABSET(str);
  729. X    ary->ary_array[sp] = str;
  730. X    return sp;
  731. X    }
  732. X    sp--;
  733. X    if (max) {
  734. X#ifndef lint
  735. X    (void)astore(ary,++sp,
  736. X      str_2mortal(str_nmake((double)statcache.st_dev)));
  737. X    (void)astore(ary,++sp,
  738. X      str_2mortal(str_nmake((double)statcache.st_ino)));
  739. X    (void)astore(ary,++sp,
  740. X      str_2mortal(str_nmake((double)statcache.st_mode)));
  741. X    (void)astore(ary,++sp,
  742. X      str_2mortal(str_nmake((double)statcache.st_nlink)));
  743. X    (void)astore(ary,++sp,
  744. X      str_2mortal(str_nmake((double)statcache.st_uid)));
  745. X    (void)astore(ary,++sp,
  746. X      str_2mortal(str_nmake((double)statcache.st_gid)));
  747. X    (void)astore(ary,++sp,
  748. X      str_2mortal(str_nmake((double)statcache.st_rdev)));
  749. X    (void)astore(ary,++sp,
  750. X      str_2mortal(str_nmake((double)statcache.st_size)));
  751. X    (void)astore(ary,++sp,
  752. X      str_2mortal(str_nmake((double)statcache.st_atime)));
  753. X    (void)astore(ary,++sp,
  754. X      str_2mortal(str_nmake((double)statcache.st_mtime)));
  755. X    (void)astore(ary,++sp,
  756. X      str_2mortal(str_nmake((double)statcache.st_ctime)));
  757. X#ifdef STATBLOCKS
  758. X    (void)astore(ary,++sp,
  759. X      str_2mortal(str_nmake((double)statcache.st_blksize)));
  760. X    (void)astore(ary,++sp,
  761. X      str_2mortal(str_nmake((double)statcache.st_blocks)));
  762. X#else
  763. X    (void)astore(ary,++sp,
  764. X      str_2mortal(str_make("",0)));
  765. X    (void)astore(ary,++sp,
  766. X      str_2mortal(str_make("",0)));
  767. X#endif
  768. X#else /* lint */
  769. X    (void)astore(ary,++sp,str_nmake(0.0));
  770. X#endif /* lint */
  771. X    }
  772. X    return sp;
  773. X}
  774. X
  775. X#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
  776. X    /* code courtesy of William Kucharski */
  777. X#define HAS_CHSIZE
  778. X
  779. Xint chsize(fd, length)
  780. Xint fd;            /* file descriptor */
  781. Xoff_t length;        /* length to set file to */
  782. X{
  783. X    extern long lseek();
  784. X    struct flock fl;
  785. X    struct stat filebuf;
  786. X
  787. X    if (fstat(fd, &filebuf) < 0)
  788. X    return -1;
  789. X
  790. X    if (filebuf.st_size < length) {
  791. X
  792. X    /* extend file length */
  793. X
  794. X    if ((lseek(fd, (length - 1), 0)) < 0)
  795. X        return -1;
  796. X
  797. X    /* write a "0" byte */
  798. X
  799. X    if ((write(fd, "", 1)) != 1)
  800. X        return -1;
  801. X    }
  802. X    else {
  803. X    /* truncate length */
  804. X
  805. X    fl.l_whence = 0;
  806. X    fl.l_len = 0;
  807. X    fl.l_start = length;
  808. X    fl.l_type = F_WRLCK;    /* write lock on file space */
  809. X
  810. X    /*
  811. X    * This relies on the UNDOCUMENTED F_FREESP argument to
  812. X    * fcntl(2), which truncates the file so that it ends at the
  813. X    * position indicated by fl.l_start.
  814. X    *
  815. X    * Will minor miracles never cease?
  816. X    */
  817. X
  818. X    if (fcntl(fd, F_FREESP, &fl) < 0)
  819. X        return -1;
  820. X
  821. X    }
  822. X
  823. X    return 0;
  824. X}
  825. X#endif /* F_FREESP */
  826. X
  827. Xint
  828. Xdo_truncate(str,arg,gimme,arglast)
  829. XSTR *str;
  830. Xregister ARG *arg;
  831. Xint gimme;
  832. Xint *arglast;
  833. X{
  834. X    register ARRAY *ary = stack;
  835. X    register int sp = arglast[0] + 1;
  836. X    off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
  837. X    int result = 1;
  838. X    STAB *tmpstab;
  839. X
  840. X#if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
  841. X#ifdef HAS_TRUNCATE
  842. X    if ((arg[1].arg_type & A_MASK) == A_WORD) {
  843. X    tmpstab = arg[1].arg_ptr.arg_stab;
  844. X    if (!stab_io(tmpstab) ||
  845. X      ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
  846. X        result = 0;
  847. X    }
  848. X    else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
  849. X    result = 0;
  850. X#else
  851. X    if ((arg[1].arg_type & A_MASK) == A_WORD) {
  852. X    tmpstab = arg[1].arg_ptr.arg_stab;
  853. X    if (!stab_io(tmpstab) ||
  854. X      chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
  855. X        result = 0;
  856. X    }
  857. X    else {
  858. X    int tmpfd;
  859. X
  860. X    if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
  861. X        result = 0;
  862. X    else {
  863. X        if (chsize(tmpfd, len) < 0)
  864. X        result = 0;
  865. X        close(tmpfd);
  866. X    }
  867. X    }
  868. X#endif
  869. X
  870. X    if (result)
  871. X    str_sset(str,&str_yes);
  872. X    else
  873. X    str_sset(str,&str_undef);
  874. X    STABSET(str);
  875. X    ary->ary_array[sp] = str;
  876. X    return sp;
  877. X#else
  878. X    fatal("truncate not implemented");
  879. X#endif
  880. X}
  881. X
  882. Xint
  883. Xlooks_like_number(str)
  884. XSTR *str;
  885. X{
  886. X    register char *s;
  887. X    register char *send;
  888. X
  889. X    if (!str->str_pok)
  890. X    return TRUE;
  891. X    s = str->str_ptr; 
  892. X    send = s + str->str_cur;
  893. X    while (isspace(*s))
  894. X    s++;
  895. X    if (s >= send)
  896. X    return FALSE;
  897. X    if (*s == '+' || *s == '-')
  898. X    s++;
  899. X    while (isdigit(*s))
  900. X    s++;
  901. X    if (s == send)
  902. X    return TRUE;
  903. X    if (*s == '.') 
  904. X    s++;
  905. X    else if (s == str->str_ptr)
  906. X    return FALSE;
  907. X    while (isdigit(*s))
  908. X    s++;
  909. X    if (s == send)
  910. X    return TRUE;
  911. X    if (*s == 'e' || *s == 'E') {
  912. X    s++;
  913. X    if (*s == '+' || *s == '-')
  914. X        s++;
  915. X    while (isdigit(*s))
  916. X        s++;
  917. X    }
  918. X    while (isspace(*s))
  919. X    s++;
  920. X    if (s >= send)
  921. X    return TRUE;
  922. X    return FALSE;
  923. X}
  924. X
  925. Xbool
  926. Xdo_print(str,fp)
  927. Xregister STR *str;
  928. XFILE *fp;
  929. X{
  930. X    register char *tmps;
  931. X
  932. X    if (!fp) {
  933. X    if (dowarn)
  934. X        warn("print to unopened file");
  935. X    return FALSE;
  936. X    }
  937. X    if (!str)
  938. X    return TRUE;
  939. X    if (ofmt &&
  940. X      ((str->str_nok && str->str_u.str_nval != 0.0)
  941. X       || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
  942. X    fprintf(fp, ofmt, str->str_u.str_nval);
  943. X    return !ferror(fp);
  944. X    }
  945. X    else {
  946. X    tmps = str_get(str);
  947. X    if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
  948. X      && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
  949. X        STR *tmpstr = str_mortal(&str_undef);
  950. X        stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
  951. X        str = tmpstr;
  952. X        tmps = str->str_ptr;
  953. X        putc('*',fp);
  954. X    }
  955. X    if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
  956. X        return FALSE;
  957. X    }
  958. X    return TRUE;
  959. X}
  960. X
  961. Xbool
  962. Xdo_aprint(arg,fp,arglast)
  963. Xregister ARG *arg;
  964. Xregister FILE *fp;
  965. Xint *arglast;
  966. X{
  967. X    register STR **st = stack->ary_array;
  968. X    register int sp = arglast[1];
  969. X    register int retval;
  970. X    register int items = arglast[2] - sp;
  971. X
  972. X    if (!fp) {
  973. X    if (dowarn)
  974. X        warn("print to unopened file");
  975. X    return FALSE;
  976. X    }
  977. X    st += ++sp;
  978. X    if (arg->arg_type == O_PRTF) {
  979. X    do_sprintf(arg->arg_ptr.arg_str,items,st);
  980. X    retval = do_print(arg->arg_ptr.arg_str,fp);
  981. X    }
  982. X    else {
  983. X    retval = (items <= 0);
  984. X    for (; items > 0; items--,st++) {
  985. X        if (retval && ofslen) {
  986. X        if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
  987. X            retval = FALSE;
  988. X            break;
  989. X        }
  990. X        }
  991. X        if (!(retval = do_print(*st, fp)))
  992. X        break;
  993. X    }
  994. X    if (retval && orslen)
  995. X        if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
  996. X        retval = FALSE;
  997. X    }
  998. X    return retval;
  999. X}
  1000. X
  1001. Xint
  1002. Xmystat(arg,str)
  1003. XARG *arg;
  1004. XSTR *str;
  1005. X{
  1006. X    STIO *stio;
  1007. X
  1008. X    laststype = O_STAT;
  1009. X    if (arg[1].arg_type & A_DONT) {
  1010. X    stio = stab_io(arg[1].arg_ptr.arg_stab);
  1011. X    if (stio && stio->ifp) {
  1012. X        statstab = arg[1].arg_ptr.arg_stab;
  1013. X        str_set(statname,"");
  1014. X        return (laststatval = fstat(fileno(stio->ifp), &statcache));
  1015. X    }
  1016. X    else {
  1017. X        if (arg[1].arg_ptr.arg_stab == defstab)
  1018. X        return laststatval;
  1019. X        if (dowarn)
  1020. X        warn("Stat on unopened file <%s>",
  1021. X          stab_name(arg[1].arg_ptr.arg_stab));
  1022. X        statstab = Nullstab;
  1023. X        str_set(statname,"");
  1024. X        return (laststatval = -1);
  1025. X    }
  1026. X    }
  1027. X    else {
  1028. X    statstab = Nullstab;
  1029. X    str_set(statname,str_get(str));
  1030. X    return (laststatval = stat(str_get(str),&statcache));
  1031. X    }
  1032. X}
  1033. X
  1034. Xint
  1035. Xmylstat(arg,str)
  1036. XARG *arg;
  1037. XSTR *str;
  1038. X{
  1039. X    if (arg[1].arg_type & A_DONT) {
  1040. X    if (arg[1].arg_ptr.arg_stab == defstab) {
  1041. X        if (laststype != O_LSTAT)
  1042. X        fatal("The stat preceding -l _ wasn't an lstat");
  1043. X        return laststatval;
  1044. X    }
  1045. X    fatal("You can't use -l on a filehandle");
  1046. X    }
  1047. X
  1048. X    laststype = O_LSTAT;
  1049. X    statstab = Nullstab;
  1050. X    str_set(statname,str_get(str));
  1051. X#ifdef HAS_LSTAT
  1052. X    return (laststatval = lstat(str_get(str),&statcache));
  1053. X#else
  1054. X    return (laststatval = stat(str_get(str),&statcache));
  1055. X#endif
  1056. X}
  1057. X
  1058. XSTR *
  1059. Xdo_fttext(arg,str)
  1060. Xregister ARG *arg;
  1061. XSTR *str;
  1062. X{
  1063. X    int i;
  1064. X    int len;
  1065. X    int odd = 0;
  1066. X    STDCHAR tbuf[512];
  1067. X    register STDCHAR *s;
  1068. X    register STIO *stio;
  1069. X
  1070. X    if (arg[1].arg_type & A_DONT) {
  1071. X    if (arg[1].arg_ptr.arg_stab == defstab) {
  1072. X        if (statstab)
  1073. X        stio = stab_io(statstab);
  1074. X        else {
  1075. X        str = statname;
  1076. X        goto really_filename;
  1077. X        }
  1078. X    }
  1079. X    else {
  1080. X        statstab = arg[1].arg_ptr.arg_stab;
  1081. X        str_set(statname,"");
  1082. X        stio = stab_io(statstab);
  1083. X    }
  1084. X    if (stio && stio->ifp) {
  1085. X#ifdef STDSTDIO
  1086. X        fstat(fileno(stio->ifp),&statcache);
  1087. X        if (stio->ifp->_cnt <= 0) {
  1088. X        i = getc(stio->ifp);
  1089. X        if (i != EOF)
  1090. X            (void)ungetc(i,stio->ifp);
  1091. X        }
  1092. X        if (stio->ifp->_cnt <= 0)    /* null file is anything */
  1093. X        return &str_yes;
  1094. X        len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
  1095. X        s = stio->ifp->_base;
  1096. X#else
  1097. X        fatal("-T and -B not implemented on filehandles\n");
  1098. X#endif
  1099. X    }
  1100. X    else {
  1101. X        if (dowarn)
  1102. X        warn("Test on unopened file <%s>",
  1103. X          stab_name(arg[1].arg_ptr.arg_stab));
  1104. X        return &str_undef;
  1105. X    }
  1106. X    }
  1107. X    else {
  1108. X    statstab = Nullstab;
  1109. X    str_set(statname,str_get(str));
  1110. X      really_filename:
  1111. X    i = open(str_get(str),0);
  1112. X    if (i < 0)
  1113. X        return &str_undef;
  1114. X    fstat(i,&statcache);
  1115. X    len = read(i,tbuf,512);
  1116. X    (void)close(i);
  1117. X    if (len <= 0)        /* null file is anything */
  1118. X        return &str_yes;
  1119. X    s = tbuf;
  1120. X    }
  1121. X
  1122. X    /* now scan s to look for textiness */
  1123. X
  1124. X    for (i = 0; i < len; i++,s++) {
  1125. X    if (!*s) {            /* null never allowed in text */
  1126. X        odd += len;
  1127. X        break;
  1128. X    }
  1129. X    else if (*s & 128)
  1130. X        odd++;
  1131. X    else if (*s < 32 &&
  1132. X      *s != '\n' && *s != '\r' && *s != '\b' &&
  1133. X      *s != '\t' && *s != '\f' && *s != 27)
  1134. X        odd++;
  1135. X    }
  1136. X
  1137. X    if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
  1138. X    return &str_no;
  1139. X    else
  1140. X    return &str_yes;
  1141. X}
  1142. X
  1143. Xbool
  1144. Xdo_aexec(really,arglast)
  1145. XSTR *really;
  1146. Xint *arglast;
  1147. X{
  1148. X    register STR **st = stack->ary_array;
  1149. X    register int sp = arglast[1];
  1150. X    register int items = arglast[2] - sp;
  1151. X    register char **a;
  1152. X    char **argv;
  1153. X    char *tmps;
  1154. X
  1155. X    if (items) {
  1156. X    New(401,argv, items+1, char*);
  1157. X    a = argv;
  1158. X    for (st += ++sp; items > 0; items--,st++) {
  1159. X        if (*st)
  1160. X        *a++ = str_get(*st);
  1161. X        else
  1162. X        *a++ = "";
  1163. X    }
  1164. X    *a = Nullch;
  1165. X#ifdef TAINT
  1166. X    if (*argv[0] != '/')    /* will execvp use PATH? */
  1167. X        taintenv();        /* testing IFS here is overkill, probably */
  1168. X#endif
  1169. X    if (really && *(tmps = str_get(really)))
  1170. X        execvp(tmps,argv);
  1171. X    else
  1172. X        execvp(argv[0],argv);
  1173. X    Safefree(argv);
  1174. X    }
  1175. X    return FALSE;
  1176. X}
  1177. X
  1178. Xstatic char **Argv = Null(char **);
  1179. Xstatic char *Cmd = Nullch;
  1180. X
  1181. Xvoid
  1182. Xdo_execfree()
  1183. X{
  1184. X    if (Argv) {
  1185. X    Safefree(Argv);
  1186. X    Argv = Null(char **);
  1187. X    }
  1188. X    if (Cmd) {
  1189. X    Safefree(Cmd);
  1190. X    Cmd = Nullch;
  1191. X    }
  1192. X}
  1193. X
  1194. Xbool
  1195. Xdo_exec(cmd)
  1196. Xchar *cmd;
  1197. X{
  1198. X    register char **a;
  1199. X    register char *s;
  1200. X    char flags[10];
  1201. X
  1202. X#ifdef TAINT
  1203. X    taintenv();
  1204. X    taintproper("Insecure dependency in exec");
  1205. X#endif
  1206. X
  1207. X    /* save an extra exec if possible */
  1208. X
  1209. X#ifdef CSH
  1210. X    if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
  1211. X    strcpy(flags,"-c");
  1212. X    s = cmd+cshlen+3;
  1213. X    if (*s == 'f') {
  1214. X        s++;
  1215. X        strcat(flags,"f");
  1216. X    }
  1217. X    if (*s == ' ')
  1218. X        s++;
  1219. X    if (*s++ == '\'') {
  1220. X        char *ncmd = s;
  1221. X
  1222. X        while (*s)
  1223. X        s++;
  1224. X        if (s[-1] == '\n')
  1225. X        *--s = '\0';
  1226. X        if (s[-1] == '\'') {
  1227. X        *--s = '\0';
  1228. X        execl(cshname,"csh", flags,ncmd,(char*)0);
  1229. X        *s = '\'';
  1230. X        return FALSE;
  1231. X        }
  1232. X    }
  1233. X    }
  1234. X#endif /* CSH */
  1235. X
  1236. X    /* see if there are shell metacharacters in it */
  1237. X
  1238. X    for (s = cmd; *s && isalpha(*s); s++) ;    /* catch VAR=val gizmo */
  1239. X    if (*s == '=')
  1240. X    goto doshell;
  1241. X    for (s = cmd; *s; s++) {
  1242. X    if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
  1243. X        if (*s == '\n' && !s[1]) {
  1244. X        *s = '\0';
  1245. X        break;
  1246. X        }
  1247. X      doshell:
  1248. X        execl("/bin/sh","sh","-c",cmd,(char*)0);
  1249. X        return FALSE;
  1250. X    }
  1251. X    }
  1252. X    New(402,Argv, (s - cmd) / 2 + 2, char*);
  1253. X    Cmd = nsavestr(cmd, s-cmd);
  1254. X    a = Argv;
  1255. X    for (s = Cmd; *s;) {
  1256. X    while (*s && isspace(*s)) s++;
  1257. X    if (*s)
  1258. X        *(a++) = s;
  1259. X    while (*s && !isspace(*s)) s++;
  1260. X    if (*s)
  1261. X        *s++ = '\0';
  1262. X    }
  1263. X    *a = Nullch;
  1264. X    if (Argv[0]) {
  1265. X    execvp(Argv[0],Argv);
  1266. X    if (errno == ENOEXEC) {        /* for system V NIH syndrome */
  1267. X        do_execfree();
  1268. X        goto doshell;
  1269. X    }
  1270. X    }
  1271. X    do_execfree();
  1272. X    return FALSE;
  1273. X}
  1274. X
  1275. X#ifdef HAS_SOCKET
  1276. Xint
  1277. Xdo_socket(stab, arglast)
  1278. XSTAB *stab;
  1279. Xint *arglast;
  1280. X{
  1281. X    register STR **st = stack->ary_array;
  1282. X    register int sp = arglast[1];
  1283. X    register STIO *stio;
  1284. X    int domain, type, protocol, fd;
  1285. X
  1286. X    if (!stab)
  1287. X    return FALSE;
  1288. X
  1289. X    stio = stab_io(stab);
  1290. X    if (!stio)
  1291. X    stio = stab_io(stab) = stio_new();
  1292. X    else if (stio->ifp)
  1293. X    do_close(stab,FALSE);
  1294. X
  1295. X    domain = (int)str_gnum(st[++sp]);
  1296. X    type = (int)str_gnum(st[++sp]);
  1297. X    protocol = (int)str_gnum(st[++sp]);
  1298. X#ifdef TAINT
  1299. X    taintproper("Insecure dependency in socket");
  1300. X#endif
  1301. X    fd = socket(domain,type,protocol);
  1302. X    if (fd < 0)
  1303. X    return FALSE;
  1304. X    stio->ifp = fdopen(fd, "r");    /* stdio gets confused about sockets */
  1305. X    stio->ofp = fdopen(fd, "w");
  1306. X    stio->type = 's';
  1307. X    if (!stio->ifp || !stio->ofp) {
  1308. X    if (stio->ifp) fclose(stio->ifp);
  1309. X    if (stio->ofp) fclose(stio->ofp);
  1310. X    if (!stio->ifp && !stio->ofp) close(fd);
  1311. X    return FALSE;
  1312. X    }
  1313. X
  1314. X    return TRUE;
  1315. X}
  1316. X
  1317. Xint
  1318. Xdo_bind(stab, arglast)
  1319. XSTAB *stab;
  1320. Xint *arglast;
  1321. X{
  1322. X    register STR **st = stack->ary_array;
  1323. X    register int sp = arglast[1];
  1324. X    register STIO *stio;
  1325. X    char *addr;
  1326. X
  1327. X    if (!stab)
  1328. X    goto nuts;
  1329. X
  1330. X    stio = stab_io(stab);
  1331. X    if (!stio || !stio->ifp)
  1332. X    goto nuts;
  1333. X
  1334. X    addr = str_get(st[++sp]);
  1335. X#ifdef TAINT
  1336. X    taintproper("Insecure dependency in bind");
  1337. X#endif
  1338. X    return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
  1339. X
  1340. Xnuts:
  1341. X    if (dowarn)
  1342. X    warn("bind() on closed fd");
  1343. X    return FALSE;
  1344. X
  1345. X}
  1346. X
  1347. Xint
  1348. Xdo_connect(stab, arglast)
  1349. XSTAB *stab;
  1350. Xint *arglast;
  1351. X{
  1352. X    register STR **st = stack->ary_array;
  1353. X    register int sp = arglast[1];
  1354. X    register STIO *stio;
  1355. X    char *addr;
  1356. X
  1357. X    if (!stab)
  1358. X    goto nuts;
  1359. X
  1360. X    stio = stab_io(stab);
  1361. X    if (!stio || !stio->ifp)
  1362. X    goto nuts;
  1363. X
  1364. X    addr = str_get(st[++sp]);
  1365. X#ifdef TAINT
  1366. X    taintproper("Insecure dependency in connect");
  1367. X#endif
  1368. X    return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
  1369. X
  1370. Xnuts:
  1371. X    if (dowarn)
  1372. X    warn("connect() on closed fd");
  1373. X    return FALSE;
  1374. X
  1375. X}
  1376. X
  1377. Xint
  1378. Xdo_listen(stab, arglast)
  1379. XSTAB *stab;
  1380. Xint *arglast;
  1381. X{
  1382. X    register STR **st = stack->ary_array;
  1383. X    register int sp = arglast[1];
  1384. X    register STIO *stio;
  1385. X    int backlog;
  1386. X
  1387. X    if (!stab)
  1388. X    goto nuts;
  1389. X
  1390. X    stio = stab_io(stab);
  1391. X    if (!stio || !stio->ifp)
  1392. X    goto nuts;
  1393. X
  1394. X    backlog = (int)str_gnum(st[++sp]);
  1395. X    return listen(fileno(stio->ifp), backlog) >= 0;
  1396. X
  1397. Xnuts:
  1398. X    if (dowarn)
  1399. X    warn("listen() on closed fd");
  1400. X    return FALSE;
  1401. X}
  1402. X
  1403. Xvoid
  1404. Xdo_accept(str, nstab, gstab)
  1405. XSTR *str;
  1406. XSTAB *nstab;
  1407. XSTAB *gstab;
  1408. X{
  1409. X    register STIO *nstio;
  1410. X    register STIO *gstio;
  1411. X    int len = sizeof buf;
  1412. X    int fd;
  1413. X
  1414. X    if (!nstab)
  1415. X    goto badexit;
  1416. X    if (!gstab)
  1417. X    goto nuts;
  1418. X
  1419. X    gstio = stab_io(gstab);
  1420. X    nstio = stab_io(nstab);
  1421. X
  1422. X    if (!gstio || !gstio->ifp)
  1423. X    goto nuts;
  1424. X    if (!nstio)
  1425. X    nstio = stab_io(nstab) = stio_new();
  1426. X    else if (nstio->ifp)
  1427. X    do_close(nstab,FALSE);
  1428. X
  1429. X    fd = accept(fileno(gstio->ifp),buf,&len);
  1430. X    if (fd < 0)
  1431. X    goto badexit;
  1432. X    nstio->ifp = fdopen(fd, "r");
  1433. X    nstio->ofp = fdopen(fd, "w");
  1434. X    nstio->type = 's';
  1435. X    if (!nstio->ifp || !nstio->ofp) {
  1436. X    if (nstio->ifp) fclose(nstio->ifp);
  1437. X    if (nstio->ofp) fclose(nstio->ofp);
  1438. X    if (!nstio->ifp && !nstio->ofp) close(fd);
  1439. X    goto badexit;
  1440. X    }
  1441. X
  1442. X    str_nset(str, buf, len);
  1443. X    return;
  1444. X
  1445. Xnuts:
  1446. X    if (dowarn)
  1447. X    warn("accept() on closed fd");
  1448. Xbadexit:
  1449. X    str_sset(str,&str_undef);
  1450. X    return;
  1451. X}
  1452. X
  1453. Xint
  1454. Xdo_shutdown(stab, arglast)
  1455. XSTAB *stab;
  1456. Xint *arglast;
  1457. X{
  1458. X    register STR **st = stack->ary_array;
  1459. X    register int sp = arglast[1];
  1460. X    register STIO *stio;
  1461. X    int how;
  1462. X
  1463. X    if (!stab)
  1464. X    goto nuts;
  1465. X
  1466. X    stio = stab_io(stab);
  1467. X    if (!stio || !stio->ifp)
  1468. X    goto nuts;
  1469. X
  1470. X    how = (int)str_gnum(st[++sp]);
  1471. X    return shutdown(fileno(stio->ifp), how) >= 0;
  1472. X
  1473. Xnuts:
  1474. X    if (dowarn)
  1475. X    warn("shutdown() on closed fd");
  1476. X    return FALSE;
  1477. X
  1478. X}
  1479. X
  1480. Xint
  1481. Xdo_sopt(optype, stab, arglast)
  1482. Xint optype;
  1483. XSTAB *stab;
  1484. Xint *arglast;
  1485. X{
  1486. X    register STR **st = stack->ary_array;
  1487. X    register int sp = arglast[1];
  1488. X    register STIO *stio;
  1489. X    int fd;
  1490. X    int lvl;
  1491. X    int optname;
  1492. X
  1493. X    if (!stab)
  1494. X    goto nuts;
  1495. X
  1496. X    stio = stab_io(stab);
  1497. X    if (!stio || !stio->ifp)
  1498. X    goto nuts;
  1499. X
  1500. X    fd = fileno(stio->ifp);
  1501. X    lvl = (int)str_gnum(st[sp+1]);
  1502. X    optname = (int)str_gnum(st[sp+2]);
  1503. X    switch (optype) {
  1504. X    case O_GSOCKOPT:
  1505. X    st[sp] = str_2mortal(str_new(257));
  1506. X    st[sp]->str_cur = 256;
  1507. X    st[sp]->str_pok = 1;
  1508. X    if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1509. X        goto nuts;
  1510. X    break;
  1511. X    case O_SSOCKOPT:
  1512. X    st[sp] = st[sp+3];
  1513. X    if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
  1514. X        goto nuts;
  1515. X    st[sp] = &str_yes;
  1516. X    break;
  1517. X    }
  1518. X    
  1519. X    return sp;
  1520. X
  1521. Xnuts:
  1522. X    if (dowarn)
  1523. X    warn("[gs]etsockopt() on closed fd");
  1524. X    st[sp] = &str_undef;
  1525. X    return sp;
  1526. X
  1527. X}
  1528. X
  1529. Xint
  1530. Xdo_getsockname(optype, stab, arglast)
  1531. Xint optype;
  1532. XSTAB *stab;
  1533. Xint *arglast;
  1534. X{
  1535. X    register STR **st = stack->ary_array;
  1536. X    register int sp = arglast[1];
  1537. X    register STIO *stio;
  1538. X    int fd;
  1539. X
  1540. X    if (!stab)
  1541. X    goto nuts;
  1542. X
  1543. X    stio = stab_io(stab);
  1544. X    if (!stio || !stio->ifp)
  1545. X    goto nuts;
  1546. X
  1547. X    st[sp] = str_2mortal(str_new(257));
  1548. X    st[sp]->str_cur = 256;
  1549. X    st[sp]->str_pok = 1;
  1550. X    fd = fileno(stio->ifp);
  1551. X    switch (optype) {
  1552. X    case O_GETSOCKNAME:
  1553. X    if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1554. X        goto nuts2;
  1555. X    break;
  1556. X    case O_GETPEERNAME:
  1557. X    if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
  1558. X        goto nuts2;
  1559. X    break;
  1560. X    }
  1561. X    
  1562. X    return sp;
  1563. X
  1564. Xnuts:
  1565. X    if (dowarn)
  1566. X    warn("get{sock,peer}name() on closed fd");
  1567. Xnuts2:
  1568. X    st[sp] = &str_undef;
  1569. X    return sp;
  1570. X
  1571. X}
  1572. X
  1573. Xint
  1574. Xdo_ghent(which,gimme,arglast)
  1575. Xint which;
  1576. Xint gimme;
  1577. Xint *arglast;
  1578. X{
  1579. X    register ARRAY *ary = stack;
  1580. X    register int sp = arglast[0];
  1581. X    register char **elem;
  1582. X    register STR *str;
  1583. X    struct hostent *gethostbyname();
  1584. X    struct hostent *gethostbyaddr();
  1585. X#ifdef HAS_GETHOSTENT
  1586. X    struct hostent *gethostent();
  1587. X#endif
  1588. X    struct hostent *hent;
  1589. X    unsigned long len;
  1590. X
  1591. X    if (gimme != G_ARRAY) {
  1592. X    astore(ary, ++sp, str_mortal(&str_undef));
  1593. X    return sp;
  1594. X    }
  1595. X
  1596. X    if (which == O_GHBYNAME) {
  1597. X    char *name = str_get(ary->ary_array[sp+1]);
  1598. X
  1599. X    hent = gethostbyname(name);
  1600. X    }
  1601. X    else if (which == O_GHBYADDR) {
  1602. X    STR *addrstr = ary->ary_array[sp+1];
  1603. X    int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
  1604. X    char *addr = str_get(addrstr);
  1605. X
  1606. X    hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
  1607. X    }
  1608. X    else
  1609. X#ifdef HAS_GETHOSTENT
  1610. X    hent = gethostent();
  1611. X#else
  1612. X    fatal("gethostent not implemented");
  1613. X#endif
  1614. X    if (hent) {
  1615. X#ifndef lint
  1616. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1617. X    str_set(str, hent->h_name);
  1618. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1619. X    for (elem = hent->h_aliases; *elem; elem++) {
  1620. X        str_cat(str, *elem);
  1621. X        if (elem[1])
  1622. X        str_ncat(str," ",1);
  1623. X    }
  1624. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1625. X    str_numset(str, (double)hent->h_addrtype);
  1626. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1627. X    len = hent->h_length;
  1628. X    str_numset(str, (double)len);
  1629. X#ifdef h_addr
  1630. X    for (elem = hent->h_addr_list; *elem; elem++) {
  1631. X        (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1632. X        str_nset(str, *elem, len);
  1633. X    }
  1634. X#else
  1635. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1636. X    str_nset(str, hent->h_addr, len);
  1637. X#endif /* h_addr */
  1638. X#else /* lint */
  1639. X    elem = Nullch;
  1640. X    elem = elem;
  1641. X    (void)astore(ary, ++sp, str_mortal(&str_no));
  1642. X#endif /* lint */
  1643. X    }
  1644. X
  1645. X    return sp;
  1646. X}
  1647. X
  1648. Xint
  1649. Xdo_gnent(which,gimme,arglast)
  1650. Xint which;
  1651. Xint gimme;
  1652. Xint *arglast;
  1653. X{
  1654. X    register ARRAY *ary = stack;
  1655. X    register int sp = arglast[0];
  1656. X    register char **elem;
  1657. X    register STR *str;
  1658. X    struct netent *getnetbyname();
  1659. X    struct netent *getnetbyaddr();
  1660. X    struct netent *getnetent();
  1661. X    struct netent *nent;
  1662. X
  1663. X    if (gimme != G_ARRAY) {
  1664. X    astore(ary, ++sp, str_mortal(&str_undef));
  1665. X    return sp;
  1666. X    }
  1667. X
  1668. X    if (which == O_GNBYNAME) {
  1669. X    char *name = str_get(ary->ary_array[sp+1]);
  1670. X
  1671. X    nent = getnetbyname(name);
  1672. X    }
  1673. X    else if (which == O_GNBYADDR) {
  1674. X    unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
  1675. X    int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
  1676. X
  1677. X    nent = getnetbyaddr((long)addr,addrtype);
  1678. X    }
  1679. X    else
  1680. X    nent = getnetent();
  1681. X
  1682. X    if (nent) {
  1683. X#ifndef lint
  1684. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1685. X    str_set(str, nent->n_name);
  1686. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1687. X    for (elem = nent->n_aliases; *elem; elem++) {
  1688. X        str_cat(str, *elem);
  1689. X        if (elem[1])
  1690. X        str_ncat(str," ",1);
  1691. X    }
  1692. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1693. X    str_numset(str, (double)nent->n_addrtype);
  1694. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1695. X    str_numset(str, (double)nent->n_net);
  1696. X#else /* lint */
  1697. X    elem = Nullch;
  1698. X    elem = elem;
  1699. X    (void)astore(ary, ++sp, str_mortal(&str_no));
  1700. X#endif /* lint */
  1701. X    }
  1702. X
  1703. X    return sp;
  1704. X}
  1705. X
  1706. Xint
  1707. Xdo_gpent(which,gimme,arglast)
  1708. Xint which;
  1709. Xint gimme;
  1710. Xint *arglast;
  1711. X{
  1712. X    register ARRAY *ary = stack;
  1713. X    register int sp = arglast[0];
  1714. X    register char **elem;
  1715. X    register STR *str;
  1716. X    struct protoent *getprotobyname();
  1717. X    struct protoent *getprotobynumber();
  1718. X    struct protoent *getprotoent();
  1719. X    struct protoent *pent;
  1720. X
  1721. X    if (gimme != G_ARRAY) {
  1722. X    astore(ary, ++sp, str_mortal(&str_undef));
  1723. X    return sp;
  1724. X    }
  1725. X
  1726. X    if (which == O_GPBYNAME) {
  1727. X    char *name = str_get(ary->ary_array[sp+1]);
  1728. X
  1729. X    pent = getprotobyname(name);
  1730. X    }
  1731. X    else if (which == O_GPBYNUMBER) {
  1732. X    int proto = (int)str_gnum(ary->ary_array[sp+1]);
  1733. X
  1734. X    pent = getprotobynumber(proto);
  1735. X    }
  1736. X    else
  1737. X    pent = getprotoent();
  1738. X
  1739. X    if (pent) {
  1740. X#ifndef lint
  1741. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1742. X    str_set(str, pent->p_name);
  1743. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1744. X    for (elem = pent->p_aliases; *elem; elem++) {
  1745. X        str_cat(str, *elem);
  1746. X        if (elem[1])
  1747. X        str_ncat(str," ",1);
  1748. X    }
  1749. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1750. X    str_numset(str, (double)pent->p_proto);
  1751. X#else /* lint */
  1752. X    elem = Nullch;
  1753. X    elem = elem;
  1754. X    (void)astore(ary, ++sp, str_mortal(&str_no));
  1755. X#endif /* lint */
  1756. X    }
  1757. X
  1758. X    return sp;
  1759. X}
  1760. X
  1761. Xint
  1762. Xdo_gsent(which,gimme,arglast)
  1763. Xint which;
  1764. Xint gimme;
  1765. Xint *arglast;
  1766. X{
  1767. X    register ARRAY *ary = stack;
  1768. X    register int sp = arglast[0];
  1769. X    register char **elem;
  1770. X    register STR *str;
  1771. X    struct servent *getservbyname();
  1772. X    struct servent *getservbynumber();
  1773. X    struct servent *getservent();
  1774. X    struct servent *sent;
  1775. X
  1776. X    if (gimme != G_ARRAY) {
  1777. X    astore(ary, ++sp, str_mortal(&str_undef));
  1778. X    return sp;
  1779. X    }
  1780. X
  1781. X    if (which == O_GSBYNAME) {
  1782. X    char *name = str_get(ary->ary_array[sp+1]);
  1783. X    char *proto = str_get(ary->ary_array[sp+2]);
  1784. X
  1785. X    if (proto && !*proto)
  1786. X        proto = Nullch;
  1787. X
  1788. X    sent = getservbyname(name,proto);
  1789. X    }
  1790. X    else if (which == O_GSBYPORT) {
  1791. X    int port = (int)str_gnum(ary->ary_array[sp+1]);
  1792. X    char *proto = str_get(ary->ary_array[sp+2]);
  1793. X
  1794. X    sent = getservbyport(port,proto);
  1795. X    }
  1796. X    else
  1797. X    sent = getservent();
  1798. X    if (sent) {
  1799. X#ifndef lint
  1800. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1801. X    str_set(str, sent->s_name);
  1802. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1803. X    for (elem = sent->s_aliases; *elem; elem++) {
  1804. X        str_cat(str, *elem);
  1805. X        if (elem[1])
  1806. X        str_ncat(str," ",1);
  1807. X    }
  1808. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1809. X#ifdef HAS_NTOHS
  1810. X    str_numset(str, (double)ntohs(sent->s_port));
  1811. X#else
  1812. X    str_numset(str, (double)(sent->s_port));
  1813. X#endif
  1814. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  1815. X    str_set(str, sent->s_proto);
  1816. X#else /* lint */
  1817. X    elem = Nullch;
  1818. X    elem = elem;
  1819. X    (void)astore(ary, ++sp, str_mortal(&str_no));
  1820. X#endif /* lint */
  1821. X    }
  1822. X
  1823. X    return sp;
  1824. X}
  1825. X
  1826. X#endif /* HAS_SOCKET */
  1827. X
  1828. X#ifdef HAS_SELECT
  1829. Xint
  1830. Xdo_select(gimme,arglast)
  1831. Xint gimme;
  1832. Xint *arglast;
  1833. X{
  1834. X    register STR **st = stack->ary_array;
  1835. X    register int sp = arglast[0];
  1836. X    register int i;
  1837. X    register int j;
  1838. X    register char *s;
  1839. X    register STR *str;
  1840. X    double value;
  1841. X    int maxlen = 0;
  1842. X    int nfound;
  1843. X    struct timeval timebuf;
  1844. X    struct timeval *tbuf = &timebuf;
  1845. X    int growsize;
  1846. X#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
  1847. X    int masksize;
  1848. X    int offset;
  1849. X    char *fd_sets[4];
  1850. X    int k;
  1851. X
  1852. X#if BYTEORDER & 0xf0000
  1853. X#define ORDERBYTE (0x88888888 - BYTEORDER)
  1854. X#else
  1855. X#define ORDERBYTE (0x4444 - BYTEORDER)
  1856. X#endif
  1857. X
  1858. X#endif
  1859. X
  1860. X    for (i = 1; i <= 3; i++) {
  1861. X    j = st[sp+i]->str_cur;
  1862. X    if (maxlen < j)
  1863. X        maxlen = j;
  1864. X    }
  1865. X
  1866. X#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
  1867. X    growsize = maxlen;        /* little endians can use vecs directly */
  1868. X#else
  1869. X#ifdef NFDBITS
  1870. X
  1871. X#ifndef NBBY
  1872. X#define NBBY 8
  1873. X#endif
  1874. X
  1875. X    masksize = NFDBITS / NBBY;
  1876. X#else
  1877. X    masksize = sizeof(long);    /* documented int, everyone seems to use long */
  1878. X#endif
  1879. X    growsize = maxlen + (masksize - (maxlen % masksize));
  1880. X    Zero(&fd_sets[0], 4, char*);
  1881. X#endif
  1882. X
  1883. X    for (i = 1; i <= 3; i++) {
  1884. X    str = st[sp+i];
  1885. X    j = str->str_len;
  1886. X    if (j < growsize) {
  1887. X        if (str->str_pok) {
  1888. X        Str_Grow(str,growsize);
  1889. X        s = str_get(str) + j;
  1890. X        while (++j <= growsize) {
  1891. X            *s++ = '\0';
  1892. X        }
  1893. X        }
  1894. X        else if (str->str_ptr) {
  1895. X        Safefree(str->str_ptr);
  1896. X        str->str_ptr = Nullch;
  1897. X        }
  1898. X    }
  1899. X#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
  1900. X    s = str->str_ptr;
  1901. X    if (s) {
  1902. X        New(403, fd_sets[i], growsize, char);
  1903. X        for (offset = 0; offset < growsize; offset += masksize) {
  1904. X        for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
  1905. X            fd_sets[i][j+offset] = s[(k % masksize) + offset];
  1906. X        }
  1907. X    }
  1908. X#endif
  1909. X    }
  1910. X    str = st[sp+4];
  1911. X    if (str->str_nok || str->str_pok) {
  1912. X    value = str_gnum(str);
  1913. X    if (value < 0.0)
  1914. X        value = 0.0;
  1915. X    timebuf.tv_sec = (long)value;
  1916. X    value -= (double)timebuf.tv_sec;
  1917. X    timebuf.tv_usec = (long)(value * 1000000.0);
  1918. X    }
  1919. X    else
  1920. X    tbuf = Null(struct timeval*);
  1921. X
  1922. X#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
  1923. X    nfound = select(
  1924. X    maxlen * 8,
  1925. X    st[sp+1]->str_ptr,
  1926. X    st[sp+2]->str_ptr,
  1927. X    st[sp+3]->str_ptr,
  1928. X    tbuf);
  1929. X#else
  1930. X    nfound = select(
  1931. X    maxlen * 8,
  1932. X    fd_sets[1],
  1933. X    fd_sets[2],
  1934. X    fd_sets[3],
  1935. X    tbuf);
  1936. X    for (i = 1; i <= 3; i++) {
  1937. X    if (fd_sets[i]) {
  1938. X        str = st[sp+i];
  1939. X        s = str->str_ptr;
  1940. X        for (offset = 0; offset < growsize; offset += masksize) {
  1941. X        for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
  1942. X            s[(k % masksize) + offset] = fd_sets[i][j+offset];
  1943. X        }
  1944. X    }
  1945. X    }
  1946. X#endif
  1947. X
  1948. X    st[++sp] = str_mortal(&str_no);
  1949. X    str_numset(st[sp], (double)nfound);
  1950. X    if (gimme == G_ARRAY && tbuf) {
  1951. X    value = (double)(timebuf.tv_sec) +
  1952. X        (double)(timebuf.tv_usec) / 1000000.0;
  1953. X    st[++sp] = str_mortal(&str_no);
  1954. X    str_numset(st[sp], value);
  1955. X    }
  1956. X    return sp;
  1957. X}
  1958. X#endif /* SELECT */
  1959. X
  1960. X#ifdef HAS_SOCKET
  1961. Xint
  1962. Xdo_spair(stab1, stab2, arglast)
  1963. XSTAB *stab1;
  1964. XSTAB *stab2;
  1965. Xint *arglast;
  1966. X{
  1967. X    register STR **st = stack->ary_array;
  1968. X    register int sp = arglast[2];
  1969. X    register STIO *stio1;
  1970. X    register STIO *stio2;
  1971. X    int domain, type, protocol, fd[2];
  1972. X
  1973. X    if (!stab1 || !stab2)
  1974. X    return FALSE;
  1975. X
  1976. X    stio1 = stab_io(stab1);
  1977. X    stio2 = stab_io(stab2);
  1978. X    if (!stio1)
  1979. X    stio1 = stab_io(stab1) = stio_new();
  1980. X    else if (stio1->ifp)
  1981. X    do_close(stab1,FALSE);
  1982. X    if (!stio2)
  1983. X    stio2 = stab_io(stab2) = stio_new();
  1984. X    else if (stio2->ifp)
  1985. X    do_close(stab2,FALSE);
  1986. X
  1987. X    domain = (int)str_gnum(st[++sp]);
  1988. X    type = (int)str_gnum(st[++sp]);
  1989. X    protocol = (int)str_gnum(st[++sp]);
  1990. X#ifdef TAINT
  1991. X    taintproper("Insecure dependency in socketpair");
  1992. X#endif
  1993. X#ifdef HAS_SOCKETPAIR
  1994. X    if (socketpair(domain,type,protocol,fd) < 0)
  1995. X    return FALSE;
  1996. X#else
  1997. X    fatal("Socketpair unimplemented");
  1998. X#endif
  1999. X    stio1->ifp = fdopen(fd[0], "r");
  2000. X    stio1->ofp = fdopen(fd[0], "w");
  2001. X    stio1->type = 's';
  2002. X    stio2->ifp = fdopen(fd[1], "r");
  2003. X    stio2->ofp = fdopen(fd[1], "w");
  2004. X    stio2->type = 's';
  2005. X    if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
  2006. X    if (stio1->ifp) fclose(stio1->ifp);
  2007. X    if (stio1->ofp) fclose(stio1->ofp);
  2008. X    if (!stio1->ifp && !stio1->ofp) close(fd[0]);
  2009. X    if (stio2->ifp) fclose(stio2->ifp);
  2010. X    if (stio2->ofp) fclose(stio2->ofp);
  2011. X    if (!stio2->ifp && !stio2->ofp) close(fd[1]);
  2012. X    return FALSE;
  2013. X    }
  2014. X
  2015. X    return TRUE;
  2016. X}
  2017. X
  2018. X#endif /* HAS_SOCKET */
  2019. X
  2020. Xint
  2021. Xdo_gpwent(which,gimme,arglast)
  2022. Xint which;
  2023. Xint gimme;
  2024. Xint *arglast;
  2025. X{
  2026. X#ifdef I_PWD
  2027. X    register ARRAY *ary = stack;
  2028. X    register int sp = arglast[0];
  2029. X    register STR *str;
  2030. X    struct passwd *getpwnam();
  2031. X    struct passwd *getpwuid();
  2032. X    struct passwd *getpwent();
  2033. X    struct passwd *pwent;
  2034. X
  2035. X    if (gimme != G_ARRAY) {
  2036. X    astore(ary, ++sp, str_mortal(&str_undef));
  2037. X    return sp;
  2038. X    }
  2039. X
  2040. X    if (which == O_GPWNAM) {
  2041. X    char *name = str_get(ary->ary_array[sp+1]);
  2042. X
  2043. X    pwent = getpwnam(name);
  2044. X    }
  2045. X    else if (which == O_GPWUID) {
  2046. X    int uid = (int)str_gnum(ary->ary_array[sp+1]);
  2047. X
  2048. X    pwent = getpwuid(uid);
  2049. X    }
  2050. X    else
  2051. X    pwent = getpwent();
  2052. X
  2053. X    if (pwent) {
  2054. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2055. X    str_set(str, pwent->pw_name);
  2056. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2057. X    str_set(str, pwent->pw_passwd);
  2058. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2059. X    str_numset(str, (double)pwent->pw_uid);
  2060. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2061. X    str_numset(str, (double)pwent->pw_gid);
  2062. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2063. X#ifdef PWCHANGE
  2064. X    str_numset(str, (double)pwent->pw_change);
  2065. X#else
  2066. X#ifdef PWQUOTA
  2067. X    str_numset(str, (double)pwent->pw_quota);
  2068. X#else
  2069. X#ifdef PWAGE
  2070. X    str_set(str, pwent->pw_age);
  2071. X#endif
  2072. X#endif
  2073. X#endif
  2074. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2075. X#ifdef PWCLASS
  2076. X    str_set(str,pwent->pw_class);
  2077. X#else
  2078. X#ifdef PWCOMMENT
  2079. X    str_set(str, pwent->pw_comment);
  2080. X#endif
  2081. X#endif
  2082. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2083. X    str_set(str, pwent->pw_gecos);
  2084. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2085. X    str_set(str, pwent->pw_dir);
  2086. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2087. X    str_set(str, pwent->pw_shell);
  2088. X#ifdef PWEXPIRE
  2089. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2090. X    str_numset(str, (double)pwent->pw_expire);
  2091. X#endif
  2092. X    }
  2093. X
  2094. X    return sp;
  2095. X#else
  2096. X    fatal("password routines not implemented");
  2097. X#endif
  2098. X}
  2099. X
  2100. Xint
  2101. Xdo_ggrent(which,gimme,arglast)
  2102. Xint which;
  2103. Xint gimme;
  2104. Xint *arglast;
  2105. X{
  2106. X#ifdef I_GRP
  2107. X    register ARRAY *ary = stack;
  2108. X    register int sp = arglast[0];
  2109. X    register char **elem;
  2110. X    register STR *str;
  2111. X    struct group *getgrnam();
  2112. X    struct group *getgrgid();
  2113. X    struct group *getgrent();
  2114. X    struct group *grent;
  2115. X
  2116. X    if (gimme != G_ARRAY) {
  2117. X    astore(ary, ++sp, str_mortal(&str_undef));
  2118. X    return sp;
  2119. X    }
  2120. X
  2121. X    if (which == O_GGRNAM) {
  2122. X    char *name = str_get(ary->ary_array[sp+1]);
  2123. X
  2124. X    grent = getgrnam(name);
  2125. X    }
  2126. X    else if (which == O_GGRGID) {
  2127. X    int gid = (int)str_gnum(ary->ary_array[sp+1]);
  2128. X
  2129. X    grent = getgrgid(gid);
  2130. X    }
  2131. X    else
  2132. X    grent = getgrent();
  2133. X
  2134. X    if (grent) {
  2135. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2136. X    str_set(str, grent->gr_name);
  2137. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2138. X    str_set(str, grent->gr_passwd);
  2139. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2140. X    str_numset(str, (double)grent->gr_gid);
  2141. X    (void)astore(ary, ++sp, str = str_mortal(&str_no));
  2142. X    for (elem = grent->gr_mem; *elem; elem++) {
  2143. X        str_cat(str, *elem);
  2144. X        if (elem[1])
  2145. X        str_ncat(str," ",1);
  2146. X    }
  2147. X    }
  2148. X
  2149. X    return sp;
  2150. X#else
  2151. X    fatal("group routines not implemented");
  2152. X#endif
  2153. X}
  2154. X
  2155. Xint
  2156. Xdo_dirop(optype,stab,gimme,arglast)
  2157. Xint optype;
  2158. XSTAB *stab;
  2159. Xint gimme;
  2160. Xint *arglast;
  2161. X{
  2162. X#if defined(DIRENT) && defined(HAS_READDIR)
  2163. X    register ARRAY *ary = stack;
  2164. X    register STR **st = ary->ary_array;
  2165. X    register int sp = arglast[1];
  2166. X    register STIO *stio;
  2167. X    long along;
  2168. X#ifndef telldir
  2169. X    long telldir();
  2170. X#endif
  2171. X    struct DIRENT *readdir();
  2172. X    register struct DIRENT *dp;
  2173. X
  2174. X    if (!stab)
  2175. X    goto nope;
  2176. X    if (!(stio = stab_io(stab)))
  2177. X    stio = stab_io(stab) = stio_new();
  2178. X    if (!stio->dirp && optype != O_OPENDIR)
  2179. X    goto nope;
  2180. X    st[sp] = &str_yes;
  2181. X    switch (optype) {
  2182. X    case O_OPENDIR:
  2183. X    if (stio->dirp)
  2184. X        closedir(stio->dirp);
  2185. X    if (!(stio->dirp = opendir(str_get(st[sp+1]))))
  2186. X        goto nope;
  2187. X    break;
  2188. X    case O_READDIR:
  2189. X    if (gimme == G_ARRAY) {
  2190. X        --sp;
  2191. X        while (dp = readdir(stio->dirp)) {
  2192. X#ifdef DIRNAMLEN
  2193. X        (void)astore(ary,++sp,
  2194. X          str_2mortal(str_make(dp->d_name,dp->d_namlen)));
  2195. X#else
  2196. X        (void)astore(ary,++sp,
  2197. X          str_2mortal(str_make(dp->d_name,0)));
  2198. X#endif
  2199. X        }
  2200. X    }
  2201. X    else {
  2202. X        if (!(dp = readdir(stio->dirp)))
  2203. X        goto nope;
  2204. X        st[sp] = str_mortal(&str_undef);
  2205. X#ifdef DIRNAMLEN
  2206. X        str_nset(st[sp], dp->d_name, dp->d_namlen);
  2207. X#else
  2208. X        str_set(st[sp], dp->d_name);
  2209. X#endif
  2210. X    }
  2211. X    break;
  2212. X#if MACH
  2213. X    case O_TELLDIR:
  2214. X    case O_SEEKDIR:
  2215. X        goto nope;
  2216. X#else
  2217. X    case O_TELLDIR:
  2218. X    st[sp] = str_mortal(&str_undef);
  2219. X    str_numset(st[sp], (double)telldir(stio->dirp));
  2220. X    break;
  2221. X    case O_SEEKDIR:
  2222. X    st[sp] = str_mortal(&str_undef);
  2223. X    along = (long)str_gnum(st[sp+1]);
  2224. X    (void)seekdir(stio->dirp,along);
  2225. X    break;
  2226. X#endif
  2227. X    case O_REWINDDIR:
  2228. X    st[sp] = str_mortal(&str_undef);
  2229. X    (void)rewinddir(stio->dirp);
  2230. X    break;
  2231. X    case O_CLOSEDIR:
  2232. X    st[sp] = str_mortal(&str_undef);
  2233. X    (void)closedir(stio->dirp);
  2234. X    stio->dirp = 0;
  2235. X    break;
  2236. X    }
  2237. X    return sp;
  2238. X
  2239. Xnope:
  2240. X    st[sp] = &str_undef;
  2241. X    return sp;
  2242. X
  2243. X#else
  2244. X    fatal("Unimplemented directory operation");
  2245. X#endif
  2246. X}
  2247. X
  2248. Xapply(type,arglast)
  2249. Xint type;
  2250. Xint *arglast;
  2251. X{
  2252. X    register STR **st = stack->ary_array;
  2253. X    register int sp = arglast[1];
  2254. X    register int items = arglast[2] - sp;
  2255. X    register int val;
  2256. X    register int val2;
  2257. X    register int tot = 0;
  2258. X    char *s;
  2259. X
  2260. X#ifdef TAINT
  2261. X    for (st += ++sp; items--; st++)
  2262. X    tainted |= (*st)->str_tainted;
  2263. X    st = stack->ary_array;
  2264. X    sp = arglast[1];
  2265. X    items = arglast[2] - sp;
  2266. X#endif
  2267. X    switch (type) {
  2268. X    case O_CHMOD:
  2269. X#ifdef TAINT
  2270. X    taintproper("Insecure dependency in chmod");
  2271. X#endif
  2272. X    if (--items > 0) {
  2273. X        tot = items;
  2274. X        val = (int)str_gnum(st[++sp]);
  2275. X        while (items--) {
  2276. X        if (chmod(str_get(st[++sp]),val))
  2277. X            tot--;
  2278. X        }
  2279. X    }
  2280. X    break;
  2281. X#ifdef HAS_CHOWN
  2282. X    case O_CHOWN:
  2283. X#ifdef TAINT
  2284. X    taintproper("Insecure dependency in chown");
  2285. X#endif
  2286. X    if (items > 2) {
  2287. X        items -= 2;
  2288. X        tot = items;
  2289. X        val = (int)str_gnum(st[++sp]);
  2290. X        val2 = (int)str_gnum(st[++sp]);
  2291. X        while (items--) {
  2292. X        if (chown(str_get(st[++sp]),val,val2))
  2293. X            tot--;
  2294. X        }
  2295. X    }
  2296. X    break;
  2297. X#endif
  2298. X#ifdef HAS_KILL
  2299. X    case O_KILL:
  2300. X#ifdef TAINT
  2301. X    taintproper("Insecure dependency in kill");
  2302. X#endif
  2303. X    if (--items > 0) {
  2304. X        tot = items;
  2305. X        s = str_get(st[++sp]);
  2306. X        if (isupper(*s)) {
  2307. X        if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
  2308. X            s += 3;
  2309. X        if (!(val = whichsig(s)))
  2310. X            fatal("Unrecognized signal name \"%s\"",s);
  2311. X        }
  2312. X        else
  2313. X        val = (int)str_gnum(st[sp]);
  2314. X        if (val < 0) {
  2315. X        val = -val;
  2316. X        while (items--) {
  2317. X            int proc = (int)str_gnum(st[++sp]);
  2318. X#ifdef HAS_KILLPG
  2319. X            if (killpg(proc,val))    /* BSD */
  2320. X#else
  2321. X            if (kill(-proc,val))    /* SYSV */
  2322. X#endif
  2323. X            tot--;
  2324. X        }
  2325. !STUFFY!FUNK!
  2326. echo " "
  2327. echo "End of kit 3 (of 36)"
  2328. cat /dev/null >kit3isdone
  2329. run=''
  2330. config=''
  2331. 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 25 26 27 28 29 30 31 32 33 34 35 36; do
  2332.     if test -f kit${iskit}isdone; then
  2333.     run="$run $iskit"
  2334.     else
  2335.     todo="$todo $iskit"
  2336.     fi
  2337. done
  2338. case $todo in
  2339.     '')
  2340.     echo "You have run all your kits.  Please read README and then type Configure."
  2341.     for combo in *:AA; do
  2342.         if test -f "$combo"; then
  2343.         realfile=`basename $combo :AA`
  2344.         cat $realfile:[A-Z][A-Z] >$realfile
  2345.         rm -rf $realfile:[A-Z][A-Z]
  2346.         fi
  2347.     done
  2348.     rm -rf kit*isdone
  2349.     chmod 755 Configure
  2350.     ;;
  2351.     *)  echo "You have run$run."
  2352.     echo "You still need to run$todo."
  2353.     ;;
  2354. esac
  2355. : Someone might mail this, so...
  2356. exit
  2357.  
  2358. exit 0 # Just in case...
  2359. -- 
  2360. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2361. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2362. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2363. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2364.