home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / perl2 / part08 / text0000.txt < prev   
Encoding:
Text File  |  1989-01-05  |  48.8 KB  |  2,142 lines

  1. #! /bin/sh
  2.  
  3. # Make a new directory for the perl sources, cd to it, and run kits 1
  4. # thru 15 through sh.  When all 15 kits have been run, read README.
  5.  
  6. echo "This is perl 2.0 kit 8 (of 15).  If kit 8 is complete, the line"
  7. echo '"'"End of kit 8 (of 15)"'" will echo at the end.'
  8. echo ""
  9. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  10. mkdir eg eg/scan 2>/dev/null
  11. echo Extracting eval.c
  12. sed >eval.c <<'!STUFFY!FUNK!' -e 's/X//'
  13. X/* $Header: eval.c,v 2.0 88/06/05 00:08:48 root Exp $
  14. X *
  15. X * $Log:    eval.c,v $
  16. X * Revision 2.0  88/06/05  00:08:48  root
  17. X * Baseline version 2.0.
  18. X * 
  19. X */
  20. X
  21. X#include "EXTERN.h"
  22. X#include "perl.h"
  23. X
  24. X#include <signal.h>
  25. X#include <errno.h>
  26. X
  27. Xextern int errno;
  28. X
  29. X#ifdef VOIDSIG
  30. Xstatic void (*ihand)();
  31. Xstatic void (*qhand)();
  32. X#else
  33. Xstatic int (*ihand)();
  34. Xstatic int (*qhand)();
  35. X#endif
  36. X
  37. XARG *debarg;
  38. XSTR str_args;
  39. X
  40. XSTR *
  41. Xeval(arg,retary,sargoff)
  42. Xregister ARG *arg;
  43. XSTR ***retary;        /* where to return an array to, null if nowhere */
  44. Xint sargoff;        /* how many elements in sarg are already assigned */
  45. X{
  46. X    register STR *str;
  47. X    register int anum;
  48. X    register int optype;
  49. X    int maxarg;
  50. X    int maxsarg;
  51. X    double value;
  52. X    STR *quicksarg[5];
  53. X    register STR **sarg = quicksarg;
  54. X    register char *tmps;
  55. X    char *tmps2;
  56. X    int argflags;
  57. X    int argtype;
  58. X    union argptr argptr;
  59. X    int cushion;
  60. X    unsigned long tmplong;
  61. X    long when;
  62. X    FILE *fp;
  63. X    STR *tmpstr;
  64. X    FCMD *form;
  65. X    STAB *stab;
  66. X    ARRAY *ary;
  67. X    bool assigning = FALSE;
  68. X    double exp(), log(), sqrt(), modf();
  69. X    char *crypt(), *getenv();
  70. X
  71. X    if (!arg)
  72. X    return &str_no;
  73. X    str = arg->arg_ptr.arg_str;
  74. X    optype = arg->arg_type;
  75. X    maxsarg = maxarg = arg->arg_len;
  76. X    if (maxsarg > 3 || retary) {
  77. X    if (sargoff >= 0) {    /* array already exists, just append to it */
  78. X        cushion = 10;
  79. X        sarg = (STR **)saferealloc((char*)*retary,
  80. X          (maxsarg+sargoff+2+cushion) * sizeof(STR*)) + sargoff;
  81. X          /* Note that sarg points into the middle of the array */
  82. X    }
  83. X    else {
  84. X        sargoff = cushion = 0;
  85. X        sarg = (STR **)safemalloc((maxsarg+2) * sizeof(STR*));
  86. X    }
  87. X    }
  88. X    else
  89. X    sargoff = 0;
  90. X#ifdef DEBUGGING
  91. X    if (debug) {
  92. X    if (debug & 8) {
  93. X        deb("%s (%lx) %d args:\n",opname[optype],arg,maxarg);
  94. X    }
  95. X    debname[dlevel] = opname[optype][0];
  96. X    debdelim[dlevel++] = ':';
  97. X    }
  98. X#endif
  99. X    for (anum = 1; anum <= maxarg; anum++) {
  100. X    argflags = arg[anum].arg_flags;
  101. X    if (argflags & AF_SPECIAL)
  102. X        continue;
  103. X    argtype = arg[anum].arg_type;
  104. X    argptr = arg[anum].arg_ptr;
  105. X      re_eval:
  106. X    switch (argtype) {
  107. X    default:
  108. X        sarg[anum] = &str_no;
  109. X#ifdef DEBUGGING
  110. X        tmps = "NULL";
  111. X#endif
  112. X        break;
  113. X    case A_EXPR:
  114. X#ifdef DEBUGGING
  115. X        if (debug & 8) {
  116. X        tmps = "EXPR";
  117. X        deb("%d.EXPR =>\n",anum);
  118. X        }
  119. X#endif
  120. X        if (retary &&
  121. X          (optype == O_LIST || optype == O_ITEM2 || optype == O_ITEM3)) {
  122. X        *retary = sarg - sargoff;
  123. X        eval(argptr.arg_arg, retary, anum - 1 + sargoff);
  124. X        sarg = *retary;        /* they do realloc it... */
  125. X        argtype = maxarg - anum;    /* how many left? */
  126. X        maxsarg = (int)(str_gnum(sarg[0])) + argtype;
  127. X        sargoff = maxsarg - maxarg;
  128. X        if (argtype > 9 - cushion) {    /* we don't have room left */
  129. X            sarg = (STR **)saferealloc((char*)sarg,
  130. X              (maxsarg+2+cushion) * sizeof(STR*));
  131. X        }
  132. X        sarg += sargoff;
  133. X        }
  134. X        else
  135. X        sarg[anum] = eval(argptr.arg_arg, Null(STR***),-1);
  136. X        break;
  137. X    case A_CMD:
  138. X#ifdef DEBUGGING
  139. X        if (debug & 8) {
  140. X        tmps = "CMD";
  141. X        deb("%d.CMD (%lx) =>\n",anum,argptr.arg_cmd);
  142. X        }
  143. X#endif
  144. X        sarg[anum] = cmd_exec(argptr.arg_cmd);
  145. X        break;
  146. X    case A_STAB:
  147. X        sarg[anum] = STAB_STR(argptr.arg_stab);
  148. X#ifdef DEBUGGING
  149. X        if (debug & 8) {
  150. X        sprintf(buf,"STAB $%s",argptr.arg_stab->stab_name);
  151. X        tmps = buf;
  152. X        }
  153. X#endif
  154. X        break;
  155. X    case A_LEXPR:
  156. X#ifdef DEBUGGING
  157. X        if (debug & 8) {
  158. X        tmps = "LEXPR";
  159. X        deb("%d.LEXPR =>\n",anum);
  160. X        }
  161. X#endif
  162. X        str = eval(argptr.arg_arg,Null(STR***),-1);
  163. X        if (!str)
  164. X        fatal("panic: A_LEXPR");
  165. X        goto do_crement;
  166. X    case A_LVAL:
  167. X#ifdef DEBUGGING
  168. X        if (debug & 8) {
  169. X        sprintf(buf,"LVAL $%s",argptr.arg_stab->stab_name);
  170. X        tmps = buf;
  171. X        }
  172. X#endif
  173. X        str = STAB_STR(argptr.arg_stab);
  174. X        if (!str)
  175. X        fatal("panic: A_LVAL");
  176. X      do_crement:
  177. X        assigning = TRUE;
  178. X        if (argflags & AF_PRE) {
  179. X        if (argflags & AF_UP)
  180. X            str_inc(str);
  181. X        else
  182. X            str_dec(str);
  183. X        STABSET(str);
  184. X        sarg[anum] = str;
  185. X        str = arg->arg_ptr.arg_str;
  186. X        }
  187. X        else if (argflags & AF_POST) {
  188. X        sarg[anum] = str_static(str);
  189. X        if (argflags & AF_UP)
  190. X            str_inc(str);
  191. X        else
  192. X            str_dec(str);
  193. X        STABSET(str);
  194. X        str = arg->arg_ptr.arg_str;
  195. X        }
  196. X        else {
  197. X        sarg[anum] = str;
  198. X        }
  199. X        break;
  200. X    case A_LARYLEN:
  201. X        str = sarg[anum] =
  202. X          argptr.arg_stab->stab_array->ary_magic;
  203. X#ifdef DEBUGGING
  204. X        tmps = "LARYLEN";
  205. X#endif
  206. X        if (!str)
  207. X        fatal("panic: A_LEXPR");
  208. X        goto do_crement;
  209. X    case A_ARYLEN:
  210. X        stab = argptr.arg_stab;
  211. X        sarg[anum] = stab->stab_array->ary_magic;
  212. X        str_numset(sarg[anum],(double)(stab->stab_array->ary_fill+arybase));
  213. X#ifdef DEBUGGING
  214. X        tmps = "ARYLEN";
  215. X#endif
  216. X        break;
  217. X    case A_SINGLE:
  218. X        sarg[anum] = argptr.arg_str;
  219. X#ifdef DEBUGGING
  220. X        tmps = "SINGLE";
  221. X#endif
  222. X        break;
  223. X    case A_DOUBLE:
  224. X        (void) interp(str,str_get(argptr.arg_str));
  225. X        sarg[anum] = str;
  226. X#ifdef DEBUGGING
  227. X        tmps = "DOUBLE";
  228. X#endif
  229. X        break;
  230. X    case A_BACKTICK:
  231. X        tmps = str_get(argptr.arg_str);
  232. X        fp = popen(str_get(interp(str,tmps)),"r");
  233. X        tmpstr = str_new(80);
  234. X        str_set(str,"");
  235. X        if (fp) {
  236. X        while (str_gets(tmpstr,fp) != Nullch) {
  237. X            str_scat(str,tmpstr);
  238. X        }
  239. X        statusvalue = pclose(fp);
  240. X        }
  241. X        else
  242. X        statusvalue = -1;
  243. X        str_free(tmpstr);
  244. X
  245. X        sarg[anum] = str;
  246. X#ifdef DEBUGGING
  247. X        tmps = "BACK";
  248. X#endif
  249. X        break;
  250. X    case A_INDREAD:
  251. X        last_in_stab = stabent(str_get(STAB_STR(argptr.arg_stab)),TRUE);
  252. X        goto do_read;
  253. X    case A_GLOB:
  254. X        argflags |= AF_POST;    /* enable newline chopping */
  255. X    case A_READ:
  256. X        last_in_stab = argptr.arg_stab;
  257. X      do_read:
  258. X        fp = Nullfp;
  259. X        if (last_in_stab->stab_io) {
  260. X        fp = last_in_stab->stab_io->fp;
  261. X        if (!fp) {
  262. X            if (last_in_stab->stab_io->flags & IOF_ARGV) {
  263. X            if (last_in_stab->stab_io->flags & IOF_START) {
  264. X                last_in_stab->stab_io->flags &= ~IOF_START;
  265. X                last_in_stab->stab_io->lines = 0;
  266. X                if (alen(last_in_stab->stab_array) < 0) {
  267. X                tmpstr = str_make("-");    /* assume stdin */
  268. X                apush(last_in_stab->stab_array, tmpstr);
  269. X                }
  270. X            }
  271. X            fp = nextargv(last_in_stab);
  272. X            if (!fp)  /* Note: fp != last_in_stab->stab_io->fp */
  273. X                do_close(last_in_stab,FALSE);  /* now it does */
  274. X            }
  275. X            else if (argtype == A_GLOB) {
  276. X            (void) interp(str,str_get(last_in_stab->stab_val));
  277. X            tmps = str->str_ptr;
  278. X            if (*tmps == '!')
  279. X                sprintf(tokenbuf,"%s|",tmps+1);
  280. X            else {
  281. X                if (*tmps == ';')
  282. X                sprintf(tokenbuf, "%s", tmps+1);
  283. X                else
  284. X                sprintf(tokenbuf, "echo %s", tmps);
  285. X                strcat(tokenbuf,
  286. X                  "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
  287. X            }
  288. X            do_open(last_in_stab,tokenbuf);
  289. X            fp = last_in_stab->stab_io->fp;
  290. X            }
  291. X        }
  292. X        }
  293. X        if (!fp && dowarn)
  294. X        warn("Read on closed filehandle <%s>",last_in_stab->stab_name);
  295. X      keepgoing:
  296. X        if (!fp)
  297. X        sarg[anum] = &str_no;
  298. X        else if (!str_gets(str,fp)) {
  299. X        if (last_in_stab->stab_io->flags & IOF_ARGV) {
  300. X            fp = nextargv(last_in_stab);
  301. X            if (fp)
  302. X            goto keepgoing;
  303. X            do_close(last_in_stab,FALSE);
  304. X            last_in_stab->stab_io->flags |= IOF_START;
  305. X        }
  306. X        else if (argflags & AF_POST) {
  307. X            do_close(last_in_stab,FALSE);
  308. X        }
  309. X        if (fp == stdin) {
  310. X            clearerr(fp);
  311. X        }
  312. X        sarg[anum] = &str_no;
  313. X        if (retary) {
  314. X            maxarg = anum - 1;
  315. X            maxsarg = maxarg + sargoff;
  316. X        }
  317. X        break;
  318. X        }
  319. X        else {
  320. X        last_in_stab->stab_io->lines++;
  321. X        sarg[anum] = str;
  322. X        if (argflags & AF_POST) {
  323. X            if (str->str_cur > 0)
  324. X            str->str_cur--;
  325. X            str->str_ptr[str->str_cur] = '\0';
  326. X        }
  327. X        if (retary) {
  328. X            sarg[anum] = str_static(sarg[anum]);
  329. X            anum++;
  330. X            if (anum > maxarg) {
  331. X            maxarg = anum + anum;
  332. X            maxsarg = maxarg + sargoff;
  333. X            sarg = (STR **)saferealloc((char*)(sarg-sargoff),
  334. X              (maxsarg+2+cushion) * sizeof(STR*)) + sargoff;
  335. X            }
  336. X            goto keepgoing;
  337. X        }
  338. X        }
  339. X        if (retary) {
  340. X        maxarg = anum - 1;
  341. X        maxsarg = maxarg + sargoff;
  342. X        }
  343. X#ifdef DEBUGGING
  344. X        tmps = "READ";
  345. X#endif
  346. X        break;
  347. X    }
  348. X#ifdef DEBUGGING
  349. X    if (debug & 8)
  350. X        deb("%d.%s = '%s'\n",anum,tmps,str_peek(sarg[anum]));
  351. X#endif
  352. X    }
  353. X    switch (optype) {
  354. X    case O_ITEM:
  355. X    if (maxarg > arg->arg_len)
  356. X        goto array_return;
  357. X    if (str != sarg[1])
  358. X        str_sset(str,sarg[1]);
  359. X    STABSET(str);
  360. X    break;
  361. X    case O_ITEM2:
  362. X    if (str != sarg[--anum])
  363. X        str_sset(str,sarg[anum]);
  364. X    STABSET(str);
  365. X    break;
  366. X    case O_ITEM3:
  367. X    if (str != sarg[--anum])
  368. X        str_sset(str,sarg[anum]);
  369. X    STABSET(str);
  370. X    break;
  371. X    case O_CONCAT:
  372. X    if (str != sarg[1])
  373. X        str_sset(str,sarg[1]);
  374. X    str_scat(str,sarg[2]);
  375. X    STABSET(str);
  376. X    break;
  377. X    case O_REPEAT:
  378. X    if (str != sarg[1])
  379. X        str_sset(str,sarg[1]);
  380. X    anum = (int)str_gnum(sarg[2]);
  381. X    if (anum >= 1) {
  382. X        tmpstr = str_new(0);
  383. X        str_sset(tmpstr,str);
  384. X        while (--anum > 0)
  385. X        str_scat(str,tmpstr);
  386. X    }
  387. X    else
  388. X        str_sset(str,&str_no);
  389. X    STABSET(str);
  390. X    break;
  391. X    case O_MATCH:
  392. X    str_sset(str, do_match(arg,
  393. X      retary,sarg,&maxsarg,sargoff,cushion));
  394. X    if (retary) {
  395. X        sarg = *retary;    /* they realloc it */
  396. X        goto array_return;
  397. X    }
  398. X    STABSET(str);
  399. X    break;
  400. X    case O_NMATCH:
  401. X    str_sset(str, do_match(arg,
  402. X      retary,sarg,&maxsarg,sargoff,cushion));
  403. X    if (retary) {
  404. X        sarg = *retary;    /* they realloc it */
  405. X        goto array_return;    /* ignore negation */
  406. X    }
  407. X    str_set(str, str_true(str) ? No : Yes);
  408. X    STABSET(str);
  409. X    break;
  410. X    case O_SUBST:
  411. X    value = (double) do_subst(str, arg);
  412. X    str = arg->arg_ptr.arg_str;
  413. X    goto donumset;
  414. X    case O_NSUBST:
  415. X    str_set(arg->arg_ptr.arg_str, do_subst(str, arg) ? No : Yes);
  416. X    str = arg->arg_ptr.arg_str;
  417. X    break;
  418. X    case O_ASSIGN:
  419. X    if (arg[1].arg_flags & AF_SPECIAL)
  420. X        do_assign(str,arg,sarg);
  421. X    else {
  422. X        if (str != sarg[2])
  423. X        str_sset(str, sarg[2]);
  424. X        STABSET(str);
  425. X    }
  426. X    break;
  427. X    case O_CHOP:
  428. X    tmps = str_get(str);
  429. X    tmps += str->str_cur - (str->str_cur != 0);
  430. X    str_set(arg->arg_ptr.arg_str,tmps);    /* remember last char */
  431. X    *tmps = '\0';                /* wipe it out */
  432. X    str->str_cur = tmps - str->str_ptr;
  433. X    str->str_nok = 0;
  434. X    str = arg->arg_ptr.arg_str;
  435. X    break;
  436. X    case O_STUDY:
  437. X    value = (double)do_study(str);
  438. X    str = arg->arg_ptr.arg_str;
  439. X    goto donumset;
  440. X    case O_MULTIPLY:
  441. X    value = str_gnum(sarg[1]);
  442. X    value *= str_gnum(sarg[2]);
  443. X    goto donumset;
  444. X    case O_DIVIDE:
  445. X        if ((value = str_gnum(sarg[2])) == 0.0)
  446. X            fatal("Illegal division by zero");
  447. X    value = str_gnum(sarg[1]) / value;
  448. X    goto donumset;
  449. X    case O_MODULO:
  450. X        if ((tmplong = (unsigned long) str_gnum(sarg[2])) == 0L)
  451. X            fatal("Illegal modulus zero");
  452. X    value = str_gnum(sarg[1]);
  453. X    value = (double)(((unsigned long)value) % tmplong);
  454. X    goto donumset;
  455. X    case O_ADD:
  456. X    value = str_gnum(sarg[1]);
  457. X    value += str_gnum(sarg[2]);
  458. X    goto donumset;
  459. X    case O_SUBTRACT:
  460. X    value = str_gnum(sarg[1]);
  461. X    value -= str_gnum(sarg[2]);
  462. X    goto donumset;
  463. X    case O_LEFT_SHIFT:
  464. X    value = str_gnum(sarg[1]);
  465. X    anum = (int)str_gnum(sarg[2]);
  466. X    value = (double)(((unsigned long)value) << anum);
  467. X    goto donumset;
  468. X    case O_RIGHT_SHIFT:
  469. X    value = str_gnum(sarg[1]);
  470. X    anum = (int)str_gnum(sarg[2]);
  471. X    value = (double)(((unsigned long)value) >> anum);
  472. X    goto donumset;
  473. X    case O_LT:
  474. X    value = str_gnum(sarg[1]);
  475. X    value = (double)(value < str_gnum(sarg[2]));
  476. X    goto donumset;
  477. X    case O_GT:
  478. X    value = str_gnum(sarg[1]);
  479. X    value = (double)(value > str_gnum(sarg[2]));
  480. X    goto donumset;
  481. X    case O_LE:
  482. X    value = str_gnum(sarg[1]);
  483. X    value = (double)(value <= str_gnum(sarg[2]));
  484. X    goto donumset;
  485. X    case O_GE:
  486. X    value = str_gnum(sarg[1]);
  487. X    value = (double)(value >= str_gnum(sarg[2]));
  488. X    goto donumset;
  489. X    case O_EQ:
  490. X    value = str_gnum(sarg[1]);
  491. X    value = (double)(value == str_gnum(sarg[2]));
  492. X    goto donumset;
  493. X    case O_NE:
  494. X    value = str_gnum(sarg[1]);
  495. X    value = (double)(value != str_gnum(sarg[2]));
  496. X    goto donumset;
  497. X    case O_BIT_AND:
  498. X    value = str_gnum(sarg[1]);
  499. X    value = (double)(((unsigned long)value) &
  500. X        (unsigned long)str_gnum(sarg[2]));
  501. X    goto donumset;
  502. X    case O_XOR:
  503. X    value = str_gnum(sarg[1]);
  504. X    value = (double)(((unsigned long)value) ^
  505. X        (unsigned long)str_gnum(sarg[2]));
  506. X    goto donumset;
  507. X    case O_BIT_OR:
  508. X    value = str_gnum(sarg[1]);
  509. X    value = (double)(((unsigned long)value) |
  510. X        (unsigned long)str_gnum(sarg[2]));
  511. X    goto donumset;
  512. X    case O_AND:
  513. X    if (str_true(sarg[1])) {
  514. X        anum = 2;
  515. X        optype = O_ITEM2;
  516. X        argflags = arg[anum].arg_flags;
  517. X        argtype = arg[anum].arg_type;
  518. X        argptr = arg[anum].arg_ptr;
  519. X        maxarg = anum = 1;
  520. X        goto re_eval;
  521. X    }
  522. X    else {
  523. X        if (assigning) {
  524. X        str_sset(str, sarg[1]);
  525. X        STABSET(str);
  526. X        }
  527. X        else
  528. X        str = sarg[1];
  529. X        break;
  530. X    }
  531. X    case O_OR:
  532. X    if (str_true(sarg[1])) {
  533. X        if (assigning) {
  534. X        str_sset(str, sarg[1]);
  535. X        STABSET(str);
  536. X        }
  537. X        else
  538. X        str = sarg[1];
  539. X        break;
  540. X    }
  541. X    else {
  542. X        anum = 2;
  543. X        optype = O_ITEM2;
  544. X        argflags = arg[anum].arg_flags;
  545. X        argtype = arg[anum].arg_type;
  546. X        argptr = arg[anum].arg_ptr;
  547. X        maxarg = anum = 1;
  548. X        goto re_eval;
  549. X    }
  550. X    case O_COND_EXPR:
  551. X    anum = (str_true(sarg[1]) ? 2 : 3);
  552. X    optype = (anum == 2 ? O_ITEM2 : O_ITEM3);
  553. X    argflags = arg[anum].arg_flags;
  554. X    argtype = arg[anum].arg_type;
  555. X    argptr = arg[anum].arg_ptr;
  556. X    maxarg = anum = 1;
  557. X    goto re_eval;
  558. X    case O_COMMA:
  559. X    str = sarg[2];
  560. X    break;
  561. X    case O_NEGATE:
  562. X    value = -str_gnum(sarg[1]);
  563. X    goto donumset;
  564. X    case O_NOT:
  565. X    value = (double) !str_true(sarg[1]);
  566. X    goto donumset;
  567. X    case O_COMPLEMENT:
  568. X    value = (double) ~(long)str_gnum(sarg[1]);
  569. X    goto donumset;
  570. X    case O_SELECT:
  571. X    if (arg[1].arg_type == A_LVAL)
  572. X        defoutstab = arg[1].arg_ptr.arg_stab;
  573. X    else
  574. X        defoutstab = stabent(str_get(sarg[1]),TRUE);
  575. X    if (!defoutstab->stab_io)
  576. X        defoutstab->stab_io = stio_new();
  577. X    curoutstab = defoutstab;
  578. X    str_set(str,curoutstab->stab_io->fp ? Yes : No);
  579. X    STABSET(str);
  580. X    break;
  581. X    case O_WRITE:
  582. X    if (maxarg == 0)
  583. X        stab = defoutstab;
  584. X    else if (arg[1].arg_type == A_LVAL)
  585. X        stab = arg[1].arg_ptr.arg_stab;
  586. X    else
  587. X        stab = stabent(str_get(sarg[1]),TRUE);
  588. X    if (!stab->stab_io) {
  589. X        str_set(str, No);
  590. X        STABSET(str);
  591. X        break;
  592. X    }
  593. X    curoutstab = stab;
  594. X    fp = stab->stab_io->fp;
  595. X    debarg = arg;
  596. X    if (stab->stab_io->fmt_stab)
  597. X        form = stab->stab_io->fmt_stab->stab_form;
  598. X    else
  599. X        form = stab->stab_form;
  600. X    if (!form || !fp) {
  601. X        str_set(str, No);
  602. X        STABSET(str);
  603. X        break;
  604. X    }
  605. X    format(&outrec,form);
  606. X    do_write(&outrec,stab->stab_io);
  607. X    if (stab->stab_io->flags & IOF_FLUSH)
  608. X        fflush(fp);
  609. X    str_set(str, Yes);
  610. X    STABSET(str);
  611. X    break;
  612. X    case O_OPEN:
  613. X    if (arg[1].arg_type == A_WORD)
  614. X        stab = arg[1].arg_ptr.arg_stab;
  615. X    else
  616. X        stab = stabent(str_get(sarg[1]),TRUE);
  617. X    if (do_open(stab,str_get(sarg[2]))) {
  618. X        value = (double)forkprocess;
  619. X        stab->stab_io->lines = 0;
  620. X        goto donumset;
  621. X    }
  622. X    else
  623. X        str_set(str, No);
  624. X    STABSET(str);
  625. X    break;
  626. X    case O_TRANS:
  627. X    value = (double) do_trans(str,arg);
  628. X    str = arg->arg_ptr.arg_str;
  629. X    goto donumset;
  630. X    case O_NTRANS:
  631. X    str_set(arg->arg_ptr.arg_str, do_trans(str,arg) == 0 ? Yes : No);
  632. X    str = arg->arg_ptr.arg_str;
  633. X    break;
  634. X    case O_CLOSE:
  635. X    if (arg[1].arg_type == A_WORD)
  636. X        stab = arg[1].arg_ptr.arg_stab;
  637. X    else
  638. X        stab = stabent(str_get(sarg[1]),TRUE);
  639. X    str_set(str, do_close(stab,TRUE) ? Yes : No );
  640. X    STABSET(str);
  641. X    break;
  642. X    case O_EACH:
  643. X    str_sset(str,do_each(arg[1].arg_ptr.arg_stab->stab_hash,
  644. X      retary,sarg,&maxsarg,sargoff,cushion));
  645. X    if (retary) {
  646. X        sarg = *retary;    /* they realloc it */
  647. X        goto array_return;
  648. X    }
  649. X    STABSET(str);
  650. X    break;
  651. X    case O_VALUES:
  652. X    case O_KEYS:
  653. X    value = (double) do_kv(arg[1].arg_ptr.arg_stab->stab_hash, optype,
  654. X      retary,sarg,&maxsarg,sargoff,cushion);
  655. X    if (retary) {
  656. X        sarg = *retary;    /* they realloc it */
  657. X        goto array_return;
  658. X    }
  659. X    goto donumset;
  660. X    case O_ARRAY:
  661. X    if (maxarg == 1) {
  662. X        ary = arg[1].arg_ptr.arg_stab->stab_array;
  663. X        maxarg = ary->ary_fill;
  664. X        maxsarg = maxarg + sargoff;
  665. X        if (retary) { /* array wanted */
  666. X        sarg = (STR **)saferealloc((char*)(sarg-sargoff),
  667. X          (maxsarg+3+cushion)*sizeof(STR*)) + sargoff;
  668. X        for (anum = 0; anum <= maxarg; anum++) {
  669. X            sarg[anum+1] = str = afetch(ary,anum);
  670. X        }
  671. X        maxarg++;
  672. X        maxsarg++;
  673. X        goto array_return;
  674. X        }
  675. X        else
  676. X        str = afetch(ary,maxarg);
  677. X    }
  678. X    else
  679. X        str = afetch(arg[2].arg_ptr.arg_stab->stab_array,
  680. X        ((int)str_gnum(sarg[1])) - arybase);
  681. X    if (!str)
  682. X        str = &str_no;
  683. X    break;
  684. X    case O_DELETE:
  685. X    tmpstab = arg[2].arg_ptr.arg_stab;        /* XXX */
  686. X    str = hdelete(tmpstab->stab_hash,str_get(sarg[1]));
  687. X    if (!str)
  688. X        str = &str_no;
  689. X    break;
  690. X    case O_HASH:
  691. X    tmpstab = arg[2].arg_ptr.arg_stab;        /* XXX */
  692. X    str = hfetch(tmpstab->stab_hash,str_get(sarg[1]));
  693. X    if (!str)
  694. X        str = &str_no;
  695. X    break;
  696. X    case O_LARRAY:
  697. X    anum = ((int)str_gnum(sarg[1])) - arybase;
  698. X    str = afetch(arg[2].arg_ptr.arg_stab->stab_array,anum);
  699. X    if (!str || str == &str_no) {
  700. X        str = str_new(0);
  701. X        astore(arg[2].arg_ptr.arg_stab->stab_array,anum,str);
  702. X    }
  703. X    break;
  704. X    case O_LHASH:
  705. X    tmpstab = arg[2].arg_ptr.arg_stab;
  706. X    str = hfetch(tmpstab->stab_hash,str_get(sarg[1]));
  707. X    if (!str) {
  708. X        str = str_new(0);
  709. X        hstore(tmpstab->stab_hash,str_get(sarg[1]),str);
  710. X    }
  711. X    if (tmpstab == envstab) {    /* heavy wizardry going on here */
  712. X        str->str_link.str_magic = tmpstab;/* str is now magic */
  713. X        envname = savestr(str_get(sarg[1]));
  714. X                    /* he threw the brick up into the air */
  715. X    }
  716. X    else if (tmpstab == sigstab) {    /* same thing, only different */
  717. X        str->str_link.str_magic = tmpstab;
  718. X        signame = savestr(str_get(sarg[1]));
  719. X    }
  720. X    break;
  721. X    case O_PUSH:
  722. X    if (arg[1].arg_flags & AF_SPECIAL)
  723. X        str = do_push(arg,arg[2].arg_ptr.arg_stab->stab_array);
  724. X    else {
  725. X        str = str_new(0);        /* must copy the STR */
  726. X        str_sset(str,sarg[1]);
  727. X        apush(arg[2].arg_ptr.arg_stab->stab_array,str);
  728. X    }
  729. X    break;
  730. X    case O_POP:
  731. X    str = apop(arg[1].arg_ptr.arg_stab->stab_array);
  732. X    if (!str) {
  733. X        str = &str_no;
  734. X        break;
  735. X    }
  736. X#ifdef STRUCTCOPY
  737. X    *(arg->arg_ptr.arg_str) = *str;
  738. X#else
  739. X    bcopy((char*)str, (char*)arg->arg_ptr.arg_str, sizeof *str);
  740. X#endif
  741. X    safefree((char*)str);
  742. X    str = arg->arg_ptr.arg_str;
  743. X    break;
  744. X    case O_SHIFT:
  745. X    str = ashift(arg[1].arg_ptr.arg_stab->stab_array);
  746. X    if (!str) {
  747. X        str = &str_no;
  748. X        break;
  749. X    }
  750. X#ifdef STRUCTCOPY
  751. X    *(arg->arg_ptr.arg_str) = *str;
  752. X#else
  753. X    bcopy((char*)str, (char*)arg->arg_ptr.arg_str, sizeof *str);
  754. X#endif
  755. X    safefree((char*)str);
  756. X    str = arg->arg_ptr.arg_str;
  757. X    break;
  758. X    case O_SPLIT:
  759. X    value = (double) do_split(arg[2].arg_ptr.arg_spat,
  760. X      retary,sarg,&maxsarg,sargoff,cushion);
  761. X    if (retary) {
  762. X        sarg = *retary;    /* they realloc it */
  763. X        goto array_return;
  764. X    }
  765. X    goto donumset;
  766. X    case O_LENGTH:
  767. X    value = (double) str_len(sarg[1]);
  768. X    goto donumset;
  769. X    case O_SPRINTF:
  770. X    sarg[maxsarg+1] = Nullstr;
  771. X    do_sprintf(str,arg->arg_len,sarg);
  772. X    break;
  773. X    case O_SUBSTR:
  774. X    anum = ((int)str_gnum(sarg[2])) - arybase;
  775. X    for (tmps = str_get(sarg[1]); *tmps && anum > 0; tmps++,anum--) ;
  776. X    anum = (int)str_gnum(sarg[3]);
  777. X    if (anum >= 0 && strlen(tmps) > anum)
  778. X        str_nset(str, tmps, anum);
  779. X    else
  780. X        str_set(str, tmps);
  781. X    break;
  782. X    case O_JOIN:
  783. X    if (arg[2].arg_flags & AF_SPECIAL && arg[2].arg_type == A_EXPR)
  784. X        do_join(arg,str_get(sarg[1]),str);
  785. X    else
  786. X        ajoin(arg[2].arg_ptr.arg_stab->stab_array,str_get(sarg[1]),str);
  787. X    break;
  788. X    case O_SLT:
  789. X    tmps = str_get(sarg[1]);
  790. X    value = (double) strLT(tmps,str_get(sarg[2]));
  791. X    goto donumset;
  792. X    case O_SGT:
  793. X    tmps = str_get(sarg[1]);
  794. X    value = (double) strGT(tmps,str_get(sarg[2]));
  795. X    goto donumset;
  796. X    case O_SLE:
  797. X    tmps = str_get(sarg[1]);
  798. X    value = (double) strLE(tmps,str_get(sarg[2]));
  799. X    goto donumset;
  800. X    case O_SGE:
  801. X    tmps = str_get(sarg[1]);
  802. X    value = (double) strGE(tmps,str_get(sarg[2]));
  803. X    goto donumset;
  804. X    case O_SEQ:
  805. X    tmps = str_get(sarg[1]);
  806. X    value = (double) strEQ(tmps,str_get(sarg[2]));
  807. X    goto donumset;
  808. X    case O_SNE:
  809. X    tmps = str_get(sarg[1]);
  810. X    value = (double) strNE(tmps,str_get(sarg[2]));
  811. X    goto donumset;
  812. X    case O_SUBR:
  813. X    str_sset(str,do_subr(arg,sarg));
  814. X    STABSET(str);
  815. X    break;
  816. X    case O_SORT:
  817. X    if (maxarg <= 1)
  818. X        stab = defoutstab;
  819. X    else {
  820. X        if (arg[2].arg_type == A_WORD)
  821. X        stab = arg[2].arg_ptr.arg_stab;
  822. X        else
  823. X        stab = stabent(str_get(sarg[2]),TRUE);
  824. X        if (!stab)
  825. X        stab = defoutstab;
  826. X    }
  827. X    value = (double)do_sort(arg,stab,
  828. X      retary,sarg,&maxsarg,sargoff,cushion);
  829. X    if (retary) {
  830. X        sarg = *retary;    /* they realloc it */
  831. X        goto array_return;
  832. X    }
  833. X    goto donumset;
  834. X    case O_PRTF:
  835. X    case O_PRINT:
  836. X    if (maxarg <= 1)
  837. X        stab = defoutstab;
  838. X    else {
  839. X        if (arg[2].arg_type == A_WORD)
  840. X        stab = arg[2].arg_ptr.arg_stab;
  841. X        else
  842. X        stab = stabent(str_get(sarg[2]),TRUE);
  843. X        if (!stab)
  844. X        stab = defoutstab;
  845. X    }
  846. X    if (!stab->stab_io || !(fp = stab->stab_io->fp))
  847. X        value = 0.0;
  848. X    else {
  849. X        if (arg[1].arg_flags & AF_SPECIAL)
  850. X        value = (double)do_aprint(arg,fp);
  851. X        else {
  852. X        value = (double)do_print(sarg[1],fp);
  853. X        if (ors && optype == O_PRINT)
  854. X            fputs(ors, fp);
  855. X        }
  856. X        if (stab->stab_io->flags & IOF_FLUSH)
  857. X        fflush(fp);
  858. X    }
  859. X    goto donumset;
  860. X    case O_CHDIR:
  861. X    tmps = str_get(sarg[1]);
  862. X    if (!tmps || !*tmps)
  863. X        tmps = getenv("HOME");
  864. X    if (!tmps || !*tmps)
  865. X        tmps = getenv("LOGDIR");
  866. X    value = (double)(chdir(tmps) >= 0);
  867. X    goto donumset;
  868. X    case O_DIE:
  869. X    tmps = str_get(sarg[1]);
  870. X    if (!tmps || !*tmps)
  871. X        exit(1);
  872. X    fatal("%s",str_get(sarg[1]));
  873. X    value = 0.0;
  874. X    goto donumset;
  875. X    case O_EXIT:
  876. X    exit((int)str_gnum(sarg[1]));
  877. X    value = 0.0;
  878. X    goto donumset;
  879. X    case O_RESET:
  880. X    str_reset(str_get(sarg[1]));
  881. X    value = 1.0;
  882. X    goto donumset;
  883. X    case O_LIST:
  884. X    if (arg->arg_flags & AF_LOCAL)
  885. X        savelist(sarg,maxsarg);
  886. X    if (maxarg > 0)
  887. X        str = sarg[maxsarg];    /* unwanted list, return last item */
  888. X    else
  889. X        str = &str_no;
  890. X    if (retary)
  891. X        goto array_return;
  892. X    break;
  893. X    case O_EOF:
  894. X    if (maxarg <= 0)
  895. X        stab = last_in_stab;
  896. X    else if (arg[1].arg_type == A_WORD)
  897. X        stab = arg[1].arg_ptr.arg_stab;
  898. X    else
  899. X        stab = stabent(str_get(sarg[1]),TRUE);
  900. X    str_set(str, do_eof(stab) ? Yes : No);
  901. X    STABSET(str);
  902. X    break;
  903. X    case O_TELL:
  904. X    if (maxarg <= 0)
  905. X        stab = last_in_stab;
  906. X    else if (arg[1].arg_type == A_WORD)
  907. X        stab = arg[1].arg_ptr.arg_stab;
  908. X    else
  909. X        stab = stabent(str_get(sarg[1]),TRUE);
  910. X    value = (double)do_tell(stab);
  911. X    goto donumset;
  912. X    case O_SEEK:
  913. X    if (arg[1].arg_type == A_WORD)
  914. X        stab = arg[1].arg_ptr.arg_stab;
  915. X    else
  916. X        stab = stabent(str_get(sarg[1]),TRUE);
  917. X    value = str_gnum(sarg[2]);
  918. X    str_set(str, do_seek(stab,
  919. X      (long)value, (int)str_gnum(sarg[3]) ) ? Yes : No);
  920. X    STABSET(str);
  921. X    break;
  922. X    case O_REDO:
  923. X    case O_NEXT:
  924. X    case O_LAST:
  925. X    if (maxarg > 0) {
  926. X        tmps = str_get(sarg[1]);
  927. X        while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  928. X          strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  929. X#ifdef DEBUGGING
  930. X        if (debug & 4) {
  931. X            deb("(Skipping label #%d %s)\n",loop_ptr,
  932. X            loop_stack[loop_ptr].loop_label);
  933. X        }
  934. X#endif
  935. X        loop_ptr--;
  936. X        }
  937. X#ifdef DEBUGGING
  938. X        if (debug & 4) {
  939. X        deb("(Found label #%d %s)\n",loop_ptr,
  940. X            loop_stack[loop_ptr].loop_label);
  941. X        }
  942. X#endif
  943. X    }
  944. X    if (loop_ptr < 0)
  945. X        fatal("Bad label: %s", maxarg > 0 ? tmps : "<null>");
  946. X    longjmp(loop_stack[loop_ptr].loop_env, optype);
  947. X    case O_GOTO:/* shudder */
  948. X    goto_targ = str_get(sarg[1]);
  949. X    longjmp(top_env, 1);
  950. X    case O_INDEX:
  951. X    tmps = str_get(sarg[1]);
  952. X    if (!(tmps2 = fbminstr(tmps, tmps + sarg[1]->str_cur, sarg[2])))
  953. X        value = (double)(-1 + arybase);
  954. X    else
  955. X        value = (double)(tmps2 - tmps + arybase);
  956. X    goto donumset;
  957. X    case O_TIME:
  958. X    value = (double) time(Null(long*));
  959. X    goto donumset;
  960. X    case O_TMS:
  961. X    value = (double) do_tms(retary,sarg,&maxsarg,sargoff,cushion);
  962. X    if (retary) {
  963. X        sarg = *retary;    /* they realloc it */
  964. X        goto array_return;
  965. X    }
  966. X    goto donumset;
  967. X    case O_LOCALTIME:
  968. X    when = (long)str_gnum(sarg[1]);
  969. X    value = (double)do_time(localtime(&when),
  970. X      retary,sarg,&maxsarg,sargoff,cushion);
  971. X    if (retary) {
  972. X        sarg = *retary;    /* they realloc it */
  973. X        goto array_return;
  974. X    }
  975. X    goto donumset;
  976. X    case O_GMTIME:
  977. X    when = (long)str_gnum(sarg[1]);
  978. X    value = (double)do_time(gmtime(&when),
  979. X      retary,sarg,&maxsarg,sargoff,cushion);
  980. X    if (retary) {
  981. X        sarg = *retary;    /* they realloc it */
  982. X        goto array_return;
  983. X    }
  984. X    goto donumset;
  985. X    case O_STAT:
  986. X    value = (double) do_stat(arg,
  987. X      retary,sarg,&maxsarg,sargoff,cushion);
  988. X    if (retary) {
  989. X        sarg = *retary;    /* they realloc it */
  990. X        goto array_return;
  991. X    }
  992. X    goto donumset;
  993. X    case O_CRYPT:
  994. X#ifdef CRYPT
  995. X    tmps = str_get(sarg[1]);
  996. X    str_set(str,crypt(tmps,str_get(sarg[2])));
  997. X#else
  998. X    fatal(
  999. X      "The crypt() function is unimplemented due to excessive paranoia.");
  1000. X#endif
  1001. X    break;
  1002. X    case O_EXP:
  1003. X    value = exp(str_gnum(sarg[1]));
  1004. X    goto donumset;
  1005. X    case O_LOG:
  1006. X    value = log(str_gnum(sarg[1]));
  1007. X    goto donumset;
  1008. X    case O_SQRT:
  1009. X    value = sqrt(str_gnum(sarg[1]));
  1010. X    goto donumset;
  1011. X    case O_INT:
  1012. X    value = str_gnum(sarg[1]);
  1013. X    if (value >= 0.0)
  1014. X        modf(value,&value);
  1015. X    else {
  1016. X        modf(-value,&value);
  1017. X        value = -value;
  1018. X    }
  1019. X    goto donumset;
  1020. X    case O_ORD:
  1021. X    value = (double) *str_get(sarg[1]);
  1022. X    goto donumset;
  1023. X    case O_SLEEP:
  1024. X    tmps = str_get(sarg[1]);
  1025. X    time(&when);
  1026. X    if (!tmps || !*tmps)
  1027. X        sleep((32767<<16)+32767);
  1028. X    else
  1029. X        sleep((unsigned)atoi(tmps));
  1030. X    value = (double)when;
  1031. X    time(&when);
  1032. X    value = ((double)when) - value;
  1033. X    goto donumset;
  1034. X    case O_FLIP:
  1035. X    if (str_true(sarg[1])) {
  1036. X        str_numset(str,0.0);
  1037. X        anum = 2;
  1038. X        arg->arg_type = optype = O_FLOP;
  1039. X        arg[2].arg_flags &= ~AF_SPECIAL;
  1040. X        arg[1].arg_flags |= AF_SPECIAL;
  1041. X        argflags = arg[2].arg_flags;
  1042. X        argtype = arg[2].arg_type;
  1043. X        argptr = arg[2].arg_ptr;
  1044. X        goto re_eval;
  1045. X    }
  1046. X    str_set(str,"");
  1047. X    break;
  1048. X    case O_FLOP:
  1049. X    str_inc(str);
  1050. X    if (str_true(sarg[2])) {
  1051. X        arg->arg_type = O_FLIP;
  1052. X        arg[1].arg_flags &= ~AF_SPECIAL;
  1053. X        arg[2].arg_flags |= AF_SPECIAL;
  1054. X        str_cat(str,"E0");
  1055. X    }
  1056. X    break;
  1057. X    case O_FORK:
  1058. X    value = (double)fork();
  1059. X    goto donumset;
  1060. X    case O_WAIT:
  1061. X    ihand = signal(SIGINT, SIG_IGN);
  1062. X    qhand = signal(SIGQUIT, SIG_IGN);
  1063. X    value = (double)wait(&argflags);
  1064. X    signal(SIGINT, ihand);
  1065. X    signal(SIGQUIT, qhand);
  1066. X    statusvalue = (unsigned short)argflags;
  1067. X    goto donumset;
  1068. X    case O_SYSTEM:
  1069. X    while ((anum = vfork()) == -1) {
  1070. X        if (errno != EAGAIN) {
  1071. X        value = -1.0;
  1072. X        goto donumset;
  1073. X        }
  1074. X        sleep(5);
  1075. X    }
  1076. X    if (anum > 0) {
  1077. X        ihand = signal(SIGINT, SIG_IGN);
  1078. X        qhand = signal(SIGQUIT, SIG_IGN);
  1079. X        while ((argtype = wait(&argflags)) != anum && argtype != -1)
  1080. X        ;
  1081. X        signal(SIGINT, ihand);
  1082. X        signal(SIGQUIT, qhand);
  1083. X        statusvalue = (unsigned short)argflags;
  1084. X        if (argtype == -1)
  1085. X        value = -1.0;
  1086. X        else {
  1087. X        value = (double)((unsigned int)argflags & 0xffff);
  1088. X        }
  1089. X        goto donumset;
  1090. X    }
  1091. X    if (arg[1].arg_flags & AF_SPECIAL)
  1092. X        value = (double)do_aexec(arg);
  1093. X    else {
  1094. X        value = (double)do_exec(str_static(sarg[1]));
  1095. X    }
  1096. X    _exit(-1);
  1097. X    case O_EXEC:
  1098. X    if (arg[1].arg_flags & AF_SPECIAL)
  1099. X        value = (double)do_aexec(arg);
  1100. X    else {
  1101. X        value = (double)do_exec(str_static(sarg[1]));
  1102. X    }
  1103. X    goto donumset;
  1104. X    case O_HEX:
  1105. X    argtype = 4;
  1106. X    goto snarfnum;
  1107. X
  1108. X    case O_OCT:
  1109. X    argtype = 3;
  1110. X
  1111. X      snarfnum:
  1112. X    anum = 0;
  1113. X    tmps = str_get(sarg[1]);
  1114. X    for (;;) {
  1115. X        switch (*tmps) {
  1116. X        default:
  1117. X        goto out;
  1118. X        case '8': case '9':
  1119. X        if (argtype != 4)
  1120. X            goto out;
  1121. X        /* FALL THROUGH */
  1122. X        case '0': case '1': case '2': case '3': case '4':
  1123. X        case '5': case '6': case '7':
  1124. X        anum <<= argtype;
  1125. X        anum += *tmps++ & 15;
  1126. X        break;
  1127. X        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  1128. X        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  1129. X        if (argtype != 4)
  1130. X            goto out;
  1131. X        anum <<= 4;
  1132. X        anum += (*tmps++ & 7) + 9;
  1133. X        break;
  1134. X        case 'x':
  1135. X        argtype = 4;
  1136. X        tmps++;
  1137. X        break;
  1138. X        }
  1139. X    }
  1140. X      out:
  1141. X    value = (double)anum;
  1142. X    goto donumset;
  1143. X    case O_CHMOD:
  1144. X    case O_CHOWN:
  1145. X    case O_KILL:
  1146. X    case O_UNLINK:
  1147. X    case O_UTIME:
  1148. X    if (arg[1].arg_flags & AF_SPECIAL)
  1149. X        value = (double)apply(optype,arg,Null(STR**));
  1150. X    else {
  1151. X        sarg[2] = Nullstr;
  1152. X        value = (double)apply(optype,arg,sarg);
  1153. X    }
  1154. X    goto donumset;
  1155. X    case O_UMASK:
  1156. X    value = (double)umask((int)str_gnum(sarg[1]));
  1157. X    goto donumset;
  1158. X    case O_RENAME:
  1159. X    tmps = str_get(sarg[1]);
  1160. X#ifdef RENAME
  1161. X    value = (double)(rename(tmps,str_get(sarg[2])) >= 0);
  1162. X#else
  1163. X    tmps2 = str_get(sarg[2]);
  1164. X    if (euid || stat(tmps2,&statbuf) < 0 ||
  1165. X      (statbuf.st_mode & S_IFMT) != S_IFDIR )
  1166. X        UNLINK(tmps2);    /* avoid unlinking a directory */
  1167. X    if (!(anum = link(tmps,tmps2)))
  1168. X        anum = UNLINK(tmps);
  1169. X    value = (double)(anum >= 0);
  1170. X#endif
  1171. X    goto donumset;
  1172. X    case O_LINK:
  1173. X    tmps = str_get(sarg[1]);
  1174. X    value = (double)(link(tmps,str_get(sarg[2])) >= 0);
  1175. X    goto donumset;
  1176. X    case O_UNSHIFT:
  1177. X    ary = arg[2].arg_ptr.arg_stab->stab_array;
  1178. X    if (arg[1].arg_flags & AF_SPECIAL)
  1179. X        do_unshift(arg,ary);
  1180. X    else {
  1181. X        str = str_new(0);        /* must copy the STR */
  1182. X        str_sset(str,sarg[1]);
  1183. X        aunshift(ary,1);
  1184. X        astore(ary,0,str);
  1185. X    }
  1186. X    value = (double)(ary->ary_fill + 1);
  1187. X    break;
  1188. X    case O_DOFILE:
  1189. X    case O_EVAL:
  1190. X    str_sset(str,
  1191. X        do_eval(arg[1].arg_type != A_NULL ? sarg[1] : defstab->stab_val,
  1192. X          optype) );
  1193. X    STABSET(str);
  1194. X    break;
  1195. X
  1196. X    case O_FTRREAD:
  1197. X    argtype = 0;
  1198. X    anum = S_IREAD;
  1199. X    goto check_perm;
  1200. X    case O_FTRWRITE:
  1201. X    argtype = 0;
  1202. X    anum = S_IWRITE;
  1203. X    goto check_perm;
  1204. X    case O_FTREXEC:
  1205. X    argtype = 0;
  1206. X    anum = S_IEXEC;
  1207. X    goto check_perm;
  1208. X    case O_FTEREAD:
  1209. X    argtype = 1;
  1210. X    anum = S_IREAD;
  1211. X    goto check_perm;
  1212. X    case O_FTEWRITE:
  1213. X    argtype = 1;
  1214. X    anum = S_IWRITE;
  1215. X    goto check_perm;
  1216. X    case O_FTEEXEC:
  1217. X    argtype = 1;
  1218. X    anum = S_IEXEC;
  1219. X      check_perm:
  1220. X    str = &str_no;
  1221. X    if (mystat(arg,sarg[1]) < 0)
  1222. X        break;
  1223. X    if (cando(anum,argtype))
  1224. X        str = &str_yes;
  1225. X    break;
  1226. X
  1227. X    case O_FTIS:
  1228. X    if (mystat(arg,sarg[1]) >= 0)
  1229. X        str = &str_yes;
  1230. X    else
  1231. X        str = &str_no;
  1232. X    break;
  1233. X    case O_FTEOWNED:
  1234. X    case O_FTROWNED:
  1235. X    if (mystat(arg,sarg[1]) >= 0 &&
  1236. X      statbuf.st_uid == (optype == O_FTEOWNED ? euid : uid) )
  1237. X        str = &str_yes;
  1238. X    else
  1239. X        str = &str_no;
  1240. X    break;
  1241. X    case O_FTZERO:
  1242. X    if (mystat(arg,sarg[1]) >= 0 && !statbuf.st_size)
  1243. X        str = &str_yes;
  1244. X    else
  1245. X        str = &str_no;
  1246. X    break;
  1247. X    case O_FTSIZE:
  1248. X    if (mystat(arg,sarg[1]) >= 0 && statbuf.st_size)
  1249. X        str = &str_yes;
  1250. X    else
  1251. X        str = &str_no;
  1252. X    break;
  1253. X
  1254. X    case O_FTSOCK:
  1255. X#ifdef S_IFSOCK
  1256. X    anum = S_IFSOCK;
  1257. X    goto check_file_type;
  1258. X#else
  1259. X    str = &str_no;
  1260. X    break;
  1261. X#endif
  1262. X    case O_FTCHR:
  1263. X    anum = S_IFCHR;
  1264. X    goto check_file_type;
  1265. X    case O_FTBLK:
  1266. X    anum = S_IFBLK;
  1267. X    goto check_file_type;
  1268. X    case O_FTFILE:
  1269. X    anum = S_IFREG;
  1270. X    goto check_file_type;
  1271. X    case O_FTDIR:
  1272. X    anum = S_IFDIR;
  1273. X      check_file_type:
  1274. X    if (mystat(arg,sarg[1]) >= 0 &&
  1275. X      (statbuf.st_mode & S_IFMT) == anum )
  1276. X        str = &str_yes;
  1277. X    else
  1278. X        str = &str_no;
  1279. X    break;
  1280. X    case O_FTPIPE:
  1281. X#ifdef S_IFIFO
  1282. X    anum = S_IFIFO;
  1283. X    goto check_file_type;
  1284. X#else
  1285. X    str = &str_no;
  1286. X    break;
  1287. X#endif
  1288. X    case O_FTLINK:
  1289. X#ifdef S_IFLNK
  1290. X    if (lstat(str_get(sarg[1]),&statbuf) >= 0 &&
  1291. X      (statbuf.st_mode & S_IFMT) == S_IFLNK )
  1292. X        str = &str_yes;
  1293. X    else
  1294. X#endif
  1295. X        str = &str_no;
  1296. X    break;
  1297. X    case O_SYMLINK:
  1298. X#ifdef SYMLINK
  1299. X    tmps = str_get(sarg[1]);
  1300. X    value = (double)(symlink(tmps,str_get(sarg[2])) >= 0);
  1301. X    goto donumset;
  1302. X#else
  1303. X    fatal("Unsupported function symlink()");
  1304. X#endif
  1305. X    case O_FTSUID:
  1306. X    anum = S_ISUID;
  1307. X    goto check_xid;
  1308. X    case O_FTSGID:
  1309. X    anum = S_ISGID;
  1310. X    goto check_xid;
  1311. X    case O_FTSVTX:
  1312. X    anum = S_ISVTX;
  1313. X      check_xid:
  1314. X    if (mystat(arg,sarg[1]) >= 0 && statbuf.st_mode & anum)
  1315. X        str = &str_yes;
  1316. X    else
  1317. X        str = &str_no;
  1318. X    break;
  1319. X    case O_FTTTY:
  1320. X    if (arg[1].arg_flags & AF_SPECIAL) {
  1321. X        stab = arg[1].arg_ptr.arg_stab;
  1322. X        tmps = "";
  1323. X    }
  1324. X    else
  1325. X        stab = stabent(tmps = str_get(sarg[1]),FALSE);
  1326. X    if (stab && stab->stab_io && stab->stab_io->fp)
  1327. X        anum = fileno(stab->stab_io->fp);
  1328. X    else if (isdigit(*tmps))
  1329. X        anum = atoi(tmps);
  1330. X    else
  1331. X        anum = -1;
  1332. X    if (isatty(anum))
  1333. X        str = &str_yes;
  1334. X    else
  1335. X        str = &str_no;
  1336. X    break;
  1337. X    case O_FTTEXT:
  1338. X    case O_FTBINARY:
  1339. X    str = do_fttext(arg,sarg[1]);
  1340. X    break;
  1341. X    }
  1342. X    if (retary) {
  1343. X    sarg[1] = str;
  1344. X    maxsarg = sargoff + 1;
  1345. X    }
  1346. X#ifdef DEBUGGING
  1347. X    if (debug) {
  1348. X    dlevel--;
  1349. X    if (debug & 8)
  1350. X        deb("%s RETURNS \"%s\"\n",opname[optype],str_get(str));
  1351. X    }
  1352. X#endif
  1353. X    goto freeargs;
  1354. X
  1355. Xarray_return:
  1356. X#ifdef DEBUGGING
  1357. X    if (debug) {
  1358. X    dlevel--;
  1359. X    if (debug & 8)
  1360. X        deb("%s RETURNS ARRAY OF %d ARGS\n",opname[optype],maxsarg-sargoff);
  1361. X    }
  1362. X#endif
  1363. X    goto freeargs;
  1364. X
  1365. Xdonumset:
  1366. X    str_numset(str,value);
  1367. X    STABSET(str);
  1368. X    if (retary) {
  1369. X    sarg[1] = str;
  1370. X    maxsarg = sargoff + 1;
  1371. X    }
  1372. X#ifdef DEBUGGING
  1373. X    if (debug) {
  1374. X    dlevel--;
  1375. X    if (debug & 8)
  1376. X        deb("%s RETURNS \"%f\"\n",opname[optype],value);
  1377. X    }
  1378. X#endif
  1379. X
  1380. Xfreeargs:
  1381. X    sarg -= sargoff;
  1382. X    if (sarg != quicksarg) {
  1383. X    if (retary) {
  1384. X        sarg[0] = &str_args;
  1385. X        str_numset(sarg[0], (double)(maxsarg));
  1386. X        sarg[maxsarg+1] = Nullstr;
  1387. X        *retary = sarg;    /* up to them to free it */
  1388. X    }
  1389. X    else
  1390. X        safefree((char*)sarg);
  1391. X    }
  1392. X    return str;
  1393. X}
  1394. X
  1395. Xint
  1396. Xingroup(gid,effective)
  1397. Xint gid;
  1398. Xint effective;
  1399. X{
  1400. X    if (gid == (effective ? getegid() : getgid()))
  1401. X    return TRUE;
  1402. X#ifdef GETGROUPS
  1403. X#ifndef NGROUPS
  1404. X#define NGROUPS 32
  1405. X#endif
  1406. X    {
  1407. X    GIDTYPE gary[NGROUPS];
  1408. X    int anum;
  1409. X
  1410. X    anum = getgroups(NGROUPS,gary);
  1411. X    while (--anum >= 0)
  1412. X        if (gary[anum] == gid)
  1413. X        return TRUE;
  1414. X    }
  1415. X#endif
  1416. X    return FALSE;
  1417. X}
  1418. X
  1419. X/* Do the permissions allow some operation?  Assumes statbuf already set. */
  1420. X
  1421. Xint
  1422. Xcando(bit, effective)
  1423. Xint bit;
  1424. Xint effective;
  1425. X{
  1426. X    if ((effective ? euid : uid) == 0) {    /* root is special */
  1427. X    if (bit == S_IEXEC) {
  1428. X        if (statbuf.st_mode & 0111 ||
  1429. X          (statbuf.st_mode & S_IFMT) == S_IFDIR )
  1430. X        return TRUE;
  1431. X    }
  1432. X    else
  1433. X        return TRUE;        /* root reads and writes anything */
  1434. X    return FALSE;
  1435. X    }
  1436. X    if (statbuf.st_uid == (effective ? euid : uid) ) {
  1437. X    if (statbuf.st_mode & bit)
  1438. X        return TRUE;    /* ok as "user" */
  1439. X    }
  1440. X    else if (ingroup((int)statbuf.st_gid,effective)) {
  1441. X    if (statbuf.st_mode & bit >> 3)
  1442. X        return TRUE;    /* ok as "group" */
  1443. X    }
  1444. X    else if (statbuf.st_mode & bit >> 6)
  1445. X    return TRUE;    /* ok as "other" */
  1446. X    return FALSE;
  1447. X}
  1448. !STUFFY!FUNK!
  1449. echo Extracting util.c
  1450. sed >util.c <<'!STUFFY!FUNK!' -e 's/X//'
  1451. X/* $Header: util.c,v 2.0 88/06/05 00:15:11 root Exp $
  1452. X *
  1453. X * $Log:    util.c,v $
  1454. X * Revision 2.0  88/06/05  00:15:11  root
  1455. X * Baseline version 2.0.
  1456. X * 
  1457. X */
  1458. X
  1459. X#include "EXTERN.h"
  1460. X#include "perl.h"
  1461. X
  1462. X#define FLUSH
  1463. X
  1464. Xstatic char nomem[] = "Out of memory!\n";
  1465. X
  1466. X/* paranoid version of malloc */
  1467. X
  1468. X#ifdef DEBUGGING
  1469. Xstatic int an = 0;
  1470. X#endif
  1471. X
  1472. Xchar *
  1473. Xsafemalloc(size)
  1474. XMEM_SIZE size;
  1475. X{
  1476. X    char *ptr;
  1477. X    char *malloc();
  1478. X
  1479. X    ptr = malloc(size?size:1);    /* malloc(0) is NASTY on our system */
  1480. X#ifdef DEBUGGING
  1481. X    if (debug & 128)
  1482. X    fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
  1483. X#endif
  1484. X    if (ptr != Nullch)
  1485. X    return ptr;
  1486. X    else {
  1487. X    fputs(nomem,stdout) FLUSH;
  1488. X    exit(1);
  1489. X    }
  1490. X    /*NOTREACHED*/
  1491. X}
  1492. X
  1493. X/* paranoid version of realloc */
  1494. X
  1495. Xchar *
  1496. Xsaferealloc(where,size)
  1497. Xchar *where;
  1498. XMEM_SIZE size;
  1499. X{
  1500. X    char *ptr;
  1501. X    char *realloc();
  1502. X
  1503. X    if (!where)
  1504. X    fatal("Null realloc");
  1505. X    ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  1506. X#ifdef DEBUGGING
  1507. X    if (debug & 128) {
  1508. X    fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
  1509. X    fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
  1510. X    }
  1511. X#endif
  1512. X    if (ptr != Nullch)
  1513. X    return ptr;
  1514. X    else {
  1515. X    fputs(nomem,stdout) FLUSH;
  1516. X    exit(1);
  1517. X    }
  1518. X    /*NOTREACHED*/
  1519. X}
  1520. X
  1521. X/* safe version of free */
  1522. X
  1523. Xsafefree(where)
  1524. Xchar *where;
  1525. X{
  1526. X#ifdef DEBUGGING
  1527. X    if (debug & 128)
  1528. X    fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
  1529. X#endif
  1530. X    if (where) {
  1531. X    free(where);
  1532. X    }
  1533. X}
  1534. X
  1535. X#ifdef NOTDEF
  1536. X/* safe version of string copy */
  1537. X
  1538. Xchar *
  1539. Xsafecpy(to,from,len)
  1540. Xchar *to;
  1541. Xregister char *from;
  1542. Xregister int len;
  1543. X{
  1544. X    register char *dest = to;
  1545. X
  1546. X    if (from != Nullch) 
  1547. X    for (len--; len && (*dest++ = *from++); len--) ;
  1548. X    *dest = '\0';
  1549. X    return to;
  1550. X}
  1551. X#endif /*NOTDEF*/
  1552. X
  1553. X#ifdef undef
  1554. X/* safe version of string concatenate, with \n deletion and space padding */
  1555. X
  1556. Xchar *
  1557. Xsafecat(to,from,len)
  1558. Xchar *to;
  1559. Xregister char *from;
  1560. Xregister int len;
  1561. X{
  1562. X    register char *dest = to;
  1563. X
  1564. X    len--;                /* leave room for null */
  1565. X    if (*dest) {
  1566. X    while (len && *dest++) len--;
  1567. X    if (len) {
  1568. X        len--;
  1569. X        *(dest-1) = ' ';
  1570. X    }
  1571. X    }
  1572. X    if (from != Nullch)
  1573. X    while (len && (*dest++ = *from++)) len--;
  1574. X    if (len)
  1575. X    dest--;
  1576. X    if (*(dest-1) == '\n')
  1577. X    dest--;
  1578. X    *dest = '\0';
  1579. X    return to;
  1580. X}
  1581. X#endif
  1582. X
  1583. X/* copy a string up to some (non-backslashed) delimiter, if any */
  1584. X
  1585. Xchar *
  1586. Xcpytill(to,from,delim)
  1587. Xregister char *to, *from;
  1588. Xregister int delim;
  1589. X{
  1590. X    for (; *from; from++,to++) {
  1591. X    if (*from == '\\') {
  1592. X        if (from[1] == delim)
  1593. X        from++;
  1594. X        else if (from[1] == '\\')
  1595. X        *to++ = *from++;
  1596. X    }
  1597. X    else if (*from == delim)
  1598. X        break;
  1599. X    *to = *from;
  1600. X    }
  1601. X    *to = '\0';
  1602. X    return from;
  1603. X}
  1604. X
  1605. X/* return ptr to little string in big string, NULL if not found */
  1606. X/* This routine was donated by Corey Satten. */
  1607. X
  1608. Xchar *
  1609. Xinstr(big, little)
  1610. Xregister char *big;
  1611. Xregister char *little;
  1612. X{
  1613. X    register char *s, *x;
  1614. X    register int first = *little++;
  1615. X
  1616. X    if (!first)
  1617. X    return big;
  1618. X    while (*big) {
  1619. X    if (*big++ != first)
  1620. X        continue;
  1621. X    for (x=big,s=little; *s; /**/ ) {
  1622. X        if (!*x)
  1623. X        return Nullch;
  1624. X        if (*s++ != *x++) {
  1625. X        s--;
  1626. X        break;
  1627. X        }
  1628. X    }
  1629. X    if (!*s)
  1630. X        return big-1;
  1631. X    }
  1632. X    return Nullch;
  1633. X}
  1634. X
  1635. X#ifdef NOTDEF
  1636. Xvoid
  1637. Xbmcompile(str)
  1638. XSTR *str;
  1639. X{
  1640. X    register char *s;
  1641. X    register char *table;
  1642. X    register int i;
  1643. X    register int len = str->str_cur;
  1644. X
  1645. X    str_grow(str,len+128);
  1646. X    s = str->str_ptr;
  1647. X    table = s + len;
  1648. X    for (i = 1; i < 128; i++) {
  1649. X    table[i] = len;
  1650. X    }
  1651. X    i = 0;
  1652. X    while (*s) {
  1653. X    if (!isascii(*s))
  1654. X        return;
  1655. X    if (table[*s] == len)
  1656. X        table[*s] = i;
  1657. X    s++,i++;
  1658. X    }
  1659. X    str->str_pok |= 2;        /* deep magic */
  1660. X}
  1661. X#endif /* NOTDEF */
  1662. X
  1663. Xstatic unsigned char freq[] = {
  1664. X    1,    2,    84,    151,    154,    155,    156,    157,
  1665. X    165,    246,    250,    3,    158,    7,    18,    29,
  1666. X    40,    51,    62,    73,    85,    96,    107,    118,
  1667. X    129,    140,    147,    148,    149,    150,    152,    153,
  1668. X    255,    182,    224,    205,    174,    176,    180,    217,
  1669. X    233,    232,    236,    187,    235,    228,    234,    226,
  1670. X    222,    219,    211,    195,    188,    193,    185,    184,
  1671. X    191,    183,    201,    229,    181,    220,    194,    162,
  1672. X    163,    208,    186,    202,    200,    218,    198,    179,
  1673. X    178,    214,    166,    170,    207,    199,    209,    206,
  1674. X    204,    160,    212,    216,    215,    192,    175,    173,
  1675. X    243,    172,    161,    190,    203,    189,    164,    230,
  1676. X    167,    248,    227,    244,    242,    255,    241,    231,
  1677. X    240,    253,    169,    210,    245,    237,    249,    247,
  1678. X    239,    168,    252,    251,    254,    238,    223,    221,
  1679. X    213,    225,    177,    197,    171,    196,    159,    4,
  1680. X    5,    6,    8,    9,    10,    11,    12,    13,
  1681. X    14,    15,    16,    17,    19,    20,    21,    22,
  1682. X    23,    24,    25,    26,    27,    28,    30,    31,
  1683. X    32,    33,    34,    35,    36,    37,    38,    39,
  1684. X    41,    42,    43,    44,    45,    46,    47,    48,
  1685. X    49,    50,    52,    53,    54,    55,    56,    57,
  1686. X    58,    59,    60,    61,    63,    64,    65,    66,
  1687. X    67,    68,    69,    70,    71,    72,    74,    75,
  1688. X    76,    77,    78,    79,    80,    81,    82,    83,
  1689. X    86,    87,    88,    89,    90,    91,    92,    93,
  1690. X    94,    95,    97,    98,    99,    100,    101,    102,
  1691. X    103,    104,    105,    106,    108,    109,    110,    111,
  1692. X    112,    113,    114,    115,    116,    117,    119,    120,
  1693. X    121,    122,    123,    124,    125,    126,    127,    128,
  1694. X    130,    131,    132,    133,    134,    135,    136,    137,
  1695. X    138,    139,    141,    142,    143,    144,    145,    146
  1696. X};
  1697. X
  1698. Xvoid
  1699. Xfbmcompile(str)
  1700. XSTR *str;
  1701. X{
  1702. X    register char *s;
  1703. X    register char *table;
  1704. X    register int i;
  1705. X    register int len = str->str_cur;
  1706. X    int rarest = 0;
  1707. X    int frequency = 256;
  1708. X
  1709. X    str_grow(str,len+128);
  1710. X    table = str->str_ptr + len;        /* actually points at final '\0' */
  1711. X    s = table - 1;
  1712. X    for (i = 1; i < 128; i++) {
  1713. X    table[i] = len;
  1714. X    }
  1715. X    i = 0;
  1716. X    while (s >= str->str_ptr) {
  1717. X    if (!isascii(*s))
  1718. X        return;
  1719. X    if (table[*s] == len)
  1720. X        table[*s] = i;
  1721. X    s--,i++;
  1722. X    }
  1723. X    str->str_pok |= 2;        /* deep magic */
  1724. X
  1725. X    s = str->str_ptr;        /* deeper magic */
  1726. X    for (i = 0; i < len; i++) {
  1727. X    if (freq[s[i]] < frequency) {
  1728. X        rarest = i;
  1729. X        frequency = freq[s[i]];
  1730. X    }
  1731. X    }
  1732. X    str->str_rare = s[rarest];
  1733. X    str->str_prev = rarest;
  1734. X#ifdef DEBUGGING
  1735. X    if (debug & 512)
  1736. X    fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_prev);
  1737. X#endif
  1738. X}
  1739. X
  1740. X#ifdef NOTDEF
  1741. Xchar *
  1742. Xbminstr(big, biglen, littlestr)
  1743. Xregister char *big;
  1744. Xint biglen;
  1745. XSTR *littlestr;
  1746. X{
  1747. X    register char *s;
  1748. X    register int tmp;
  1749. X    register char *little = littlestr->str_ptr;
  1750. X    int littlelen = littlestr->str_cur;
  1751. X    register char *table = little + littlelen;
  1752. X
  1753. X    s = big + biglen - littlelen;
  1754. X    while (s >= big) {
  1755. X    if (tmp = table[*s]) {
  1756. X        s -= tmp;
  1757. X    }
  1758. X    else {
  1759. X        if (strnEQ(s,little,littlelen))
  1760. X        return s;
  1761. X        s--;
  1762. X    }
  1763. X    }
  1764. X    return Nullch;
  1765. X}
  1766. X#endif /* NOTDEF */
  1767. X
  1768. Xchar *
  1769. Xfbminstr(big, bigend, littlestr)
  1770. Xchar *big;
  1771. Xregister char *bigend;
  1772. XSTR *littlestr;
  1773. X{
  1774. X    register char *s;
  1775. X    register int tmp;
  1776. X    register int littlelen;
  1777. X    register char *little;
  1778. X    register char *table;
  1779. X    register char *olds;
  1780. X    register char *oldlittle;
  1781. X    register int min;
  1782. X    char *screaminstr();
  1783. X
  1784. X    if (littlestr->str_pok != 3)
  1785. X    return instr(big,littlestr->str_ptr);
  1786. X
  1787. X    littlelen = littlestr->str_cur;
  1788. X    table = littlestr->str_ptr + littlelen;
  1789. X    s = big + --littlelen;
  1790. X    oldlittle = little = table - 1;
  1791. X    while (s < bigend) {
  1792. X      top:
  1793. X    if (tmp = table[*s]) {
  1794. X        s += tmp;
  1795. X    }
  1796. X    else {
  1797. X        tmp = littlelen;    /* less expensive than calling strncmp() */
  1798. X        olds = s;
  1799. X        while (tmp--) {
  1800. X        if (*--s == *--little)
  1801. X            continue;
  1802. X        s = olds + 1;    /* here we pay the price for failure */
  1803. X        little = oldlittle;
  1804. X        if (s < bigend)    /* fake up continue to outer loop */
  1805. X            goto top;
  1806. X        return Nullch;
  1807. X        }
  1808. X        return s;
  1809. X    }
  1810. X    }
  1811. X    return Nullch;
  1812. X}
  1813. X
  1814. Xchar *
  1815. Xscreaminstr(bigstr, littlestr)
  1816. XSTR *bigstr;
  1817. XSTR *littlestr;
  1818. X{
  1819. X    register char *s, *x;
  1820. X    register char *big = bigstr->str_ptr;
  1821. X    register int pos;
  1822. X    register int previous;
  1823. X    register int first;
  1824. X    register char *little;
  1825. X
  1826. X    if ((pos = screamfirst[littlestr->str_rare]) < 0) 
  1827. X    return Nullch;
  1828. X    little = littlestr->str_ptr;
  1829. X    first = *little++;
  1830. X    previous = littlestr->str_prev;
  1831. X    big -= previous;
  1832. X    while (pos < previous) {
  1833. X    if (!(pos += screamnext[pos]))
  1834. X        return Nullch;
  1835. X    }
  1836. X    do {
  1837. X    if (big[pos] != first)
  1838. X        continue;
  1839. X    for (x=big+pos+1,s=little; *s; /**/ ) {
  1840. X        if (!*x)
  1841. X        return Nullch;
  1842. X        if (*s++ != *x++) {
  1843. X        s--;
  1844. X        break;
  1845. X        }
  1846. X    }
  1847. X    if (!*s)
  1848. X        return big+pos;
  1849. X    } while (pos += screamnext[pos]);
  1850. X    return Nullch;
  1851. X}
  1852. X
  1853. X/* copy a string to a safe spot */
  1854. X
  1855. Xchar *
  1856. Xsavestr(str)
  1857. Xchar *str;
  1858. X{
  1859. X    register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
  1860. X
  1861. X    (void)strcpy(newaddr,str);
  1862. X    return newaddr;
  1863. X}
  1864. X
  1865. X/* grow a static string to at least a certain length */
  1866. X
  1867. Xvoid
  1868. Xgrowstr(strptr,curlen,newlen)
  1869. Xchar **strptr;
  1870. Xint *curlen;
  1871. Xint newlen;
  1872. X{
  1873. X    if (newlen > *curlen) {        /* need more room? */
  1874. X    if (*curlen)
  1875. X        *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
  1876. X    else
  1877. X        *strptr = safemalloc((MEM_SIZE)newlen);
  1878. X    *curlen = newlen;
  1879. X    }
  1880. X}
  1881. X
  1882. Xextern int errno;
  1883. X
  1884. X/*VARARGS1*/
  1885. Xmess(pat,a1,a2,a3,a4)
  1886. Xchar *pat;
  1887. X{
  1888. X    char *s;
  1889. X
  1890. X    s = tokenbuf;
  1891. X    sprintf(s,pat,a1,a2,a3,a4);
  1892. X    s += strlen(s);
  1893. X    if (s[-1] != '\n') {
  1894. X    if (line) {
  1895. X        sprintf(s," at %s line %ld",
  1896. X          in_eval?filename:origfilename, (long)line);
  1897. X        s += strlen(s);
  1898. X    }
  1899. X    if (last_in_stab &&
  1900. X        last_in_stab->stab_io &&
  1901. X        last_in_stab->stab_io->lines ) {
  1902. X        sprintf(s,", <%s> line %ld",
  1903. X          last_in_stab == argvstab ? "" : last_in_stab->stab_name,
  1904. X          (long)last_in_stab->stab_io->lines);
  1905. X        s += strlen(s);
  1906. X    }
  1907. X    strcpy(s,".\n");
  1908. X    }
  1909. X}
  1910. X
  1911. X/*VARARGS1*/
  1912. Xfatal(pat,a1,a2,a3,a4)
  1913. Xchar *pat;
  1914. X{
  1915. X    extern FILE *e_fp;
  1916. X    extern char *e_tmpname;
  1917. X
  1918. X    mess(pat,a1,a2,a3,a4);
  1919. X    if (in_eval) {
  1920. X    str_set(stabent("@",TRUE)->stab_val,tokenbuf);
  1921. X    longjmp(eval_env,1);
  1922. X    }
  1923. X    fputs(tokenbuf,stderr);
  1924. X    fflush(stderr);
  1925. X    if (e_fp)
  1926. X    UNLINK(e_tmpname);
  1927. X    statusvalue >>= 8;
  1928. X    exit(errno?errno:(statusvalue?statusvalue:255));
  1929. X}
  1930. X
  1931. X/*VARARGS1*/
  1932. Xwarn(pat,a1,a2,a3,a4)
  1933. Xchar *pat;
  1934. X{
  1935. X    mess(pat,a1,a2,a3,a4);
  1936. X    fputs(tokenbuf,stderr);
  1937. X    fflush(stderr);
  1938. X}
  1939. X
  1940. Xstatic bool firstsetenv = TRUE;
  1941. Xextern char **environ;
  1942. X
  1943. Xvoid
  1944. Xsetenv(nam,val)
  1945. Xchar *nam, *val;
  1946. X{
  1947. X    register int i=envix(nam);        /* where does it go? */
  1948. X
  1949. X    if (!environ[i]) {            /* does not exist yet */
  1950. X    if (firstsetenv) {        /* need we copy environment? */
  1951. X        int j;
  1952. X#ifndef lint
  1953. X        char **tmpenv = (char**)    /* point our wand at memory */
  1954. X        safemalloc((i+2) * sizeof(char*));
  1955. X#else
  1956. X        char **tmpenv = Null(char **);
  1957. X#endif /* lint */
  1958. X    
  1959. X        firstsetenv = FALSE;
  1960. X        for (j=0; j<i; j++)        /* copy environment */
  1961. X        tmpenv[j] = environ[j];
  1962. X        environ = tmpenv;        /* tell exec where it is now */
  1963. X    }
  1964. X#ifndef lint
  1965. X    else
  1966. X        environ = (char**) saferealloc((char*) environ,
  1967. X        (i+2) * sizeof(char*));
  1968. X                    /* just expand it a bit */
  1969. X#endif /* lint */
  1970. X    environ[i+1] = Nullch;    /* make sure it's null terminated */
  1971. X    }
  1972. X    environ[i] = safemalloc((MEM_SIZE)(strlen(nam) + strlen(val) + 2));
  1973. X                    /* this may or may not be in */
  1974. X                    /* the old environ structure */
  1975. X    sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  1976. X}
  1977. X
  1978. Xint
  1979. Xenvix(nam)
  1980. Xchar *nam;
  1981. X{
  1982. X    register int i, len = strlen(nam);
  1983. X
  1984. X    for (i = 0; environ[i]; i++) {
  1985. X    if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  1986. X        break;            /* strnEQ must come first to avoid */
  1987. X    }                    /* potential SEGV's */
  1988. X    return i;
  1989. X}
  1990. X
  1991. X#ifdef EUNICE
  1992. Xunlnk(f)    /* unlink all versions of a file */
  1993. Xchar *f;
  1994. X{
  1995. X    int i;
  1996. X
  1997. X    for (i = 0; unlink(f) >= 0; i++) ;
  1998. X    return i ? 0 : -1;
  1999. X}
  2000. X#endif
  2001. X
  2002. X#ifndef BCOPY
  2003. X#ifndef MEMCPY
  2004. Xchar *
  2005. Xbcopy(from,to,len)
  2006. Xregister char *from;
  2007. Xregister char *to;
  2008. Xregister int len;
  2009. X{
  2010. X    char *retval = to;
  2011. X
  2012. X    while (len--)
  2013. X    *to++ = *from++;
  2014. X    return retval;
  2015. X}
  2016. X
  2017. Xchar *
  2018. Xbzero(loc,len)
  2019. Xregister char *loc;
  2020. Xregister int len;
  2021. X{
  2022. X    char *retval = loc;
  2023. X
  2024. X    while (len--)
  2025. X    *loc++ = 0;
  2026. X    return retval;
  2027. X}
  2028. X#endif
  2029. X#endif
  2030. !STUFFY!FUNK!
  2031. echo Extracting eg/scan/scan_suid
  2032. sed >eg/scan/scan_suid <<'!STUFFY!FUNK!' -e 's/X//'
  2033. X#!/usr/bin/perl -P
  2034. X
  2035. X# $Header: scan_suid,v 2.0 88/06/05 00:17:54 root Exp $
  2036. X
  2037. X# Look for new setuid root files.
  2038. X
  2039. Xchdir '/usr/adm/private/memories' || die "Can't cd.";
  2040. X
  2041. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  2042. X   $blksize,$blocks) = stat('oldsuid');
  2043. Xif ($nlink) {
  2044. X    $lasttime = $mtime;
  2045. X    $tmp = $ctime - $atime;
  2046. X    if ($tmp <= 0 || $tmp >= 10) {
  2047. X    print "WARNING: somebody has read oldsuid!\n";
  2048. X    }
  2049. X    $tmp = $ctime - $mtime;
  2050. X    if ($tmp <= 0 || $tmp >= 10) {
  2051. X    print "WARNING: somebody has modified oldsuid!!!\n";
  2052. X    }
  2053. X} else {
  2054. X    $lasttime = time - 60 * 60 * 24;    # one day ago
  2055. X}
  2056. X$thistime = time;
  2057. X
  2058. X#if defined(mc300) || defined(mc500) || defined(mc700)
  2059. Xopen(Find, 'find / -perm -04000 -print |') ||
  2060. X    die "scan_find: can't run find";
  2061. X#else
  2062. Xopen(Find, 'find / \( -fstype nfs -prune \) -o -perm -04000 -ls |') ||
  2063. X    die "scan_find: can't run find";
  2064. X#endif
  2065. X
  2066. Xopen(suid, '>newsuid.tmp');
  2067. X
  2068. Xwhile (<Find>) {
  2069. X
  2070. X#if defined(mc300) || defined(mc500) || defined(mc700)
  2071. X    $x = `/bin/ls -il $_`;
  2072. X    $_ = $x;
  2073. X    s/^ *//;
  2074. X    ($inode,$perm,$links,$owner,$group,$size,$month,$day,$time,$name)
  2075. X      = split;
  2076. X#else
  2077. X    s/^ *//;
  2078. X    ($inode,$blocks,$perm,$links,$owner,$group,$size,$month,$day,$time,$name)
  2079. X      = split;
  2080. X#endif
  2081. X
  2082. X    if ($perm =~ /[sS]/ && $owner eq 'root') {
  2083. X    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  2084. X       $blksize,$blocks) = stat($name);
  2085. X    $foo = sprintf("%10s%3s %-8s %-8s%9s %3s %2s %s %s\n",
  2086. X        $perm,$links,$owner,$group,$size,$month,$day,$name,$inode);
  2087. X    print suid $foo;
  2088. X    if ($ctime > $lasttime) {
  2089. X        if ($ctime > $thistime) {
  2090. X        print "Future file: $foo";
  2091. X        }
  2092. X        else {
  2093. X        $ct .= $foo;
  2094. X        }
  2095. X    }
  2096. X    }
  2097. X}
  2098. Xclose(suid);
  2099. X
  2100. Xprint `sort +7 -8 newsuid.tmp >newsuid 2>&1`;
  2101. X$foo = `/bin/diff oldsuid newsuid 2>&1`;
  2102. Xprint "Differences in suid info:\n",$foo if $foo;
  2103. Xprint `mv oldsuid oldoldsuid 2>&1; mv newsuid oldsuid 2>&1`;
  2104. Xprint `touch oldsuid 2>&1;sleep 2 2>&1;chmod o+w oldsuid 2>&1`;
  2105. Xprint `rm -f newsuid.tmp 2>&1`;
  2106. X
  2107. X@ct = split(/\n/,$ct);
  2108. X$ct = '';
  2109. X$* = 1;
  2110. Xwhile ($#ct >= 0) {
  2111. X    $tmp = shift(@ct);
  2112. X    unless ($foo =~ "^>.*$tmp\n") { $ct .= "$tmp\n"; }
  2113. X}
  2114. X
  2115. Xprint "Inode changed since last time:\n",$ct if $ct;
  2116. X
  2117. !STUFFY!FUNK!
  2118. echo ""
  2119. echo "End of kit 8 (of 15)"
  2120. cat /dev/null >kit8isdone
  2121. run=''
  2122. config=''
  2123. for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
  2124.     if test -f kit${iskit}isdone; then
  2125.     run="$run $iskit"
  2126.     else
  2127.     todo="$todo $iskit"
  2128.     fi
  2129. done
  2130. case $todo in
  2131.     '')
  2132.     echo "You have run all your kits.  Please read README and then type Configure."
  2133.     chmod 755 Configure
  2134.     ;;
  2135.     *)  echo "You have run$run."
  2136.     echo "You still need to run$todo."
  2137.     ;;
  2138. esac
  2139. : Someone might mail this, so...
  2140. exit
  2141.  
  2142.