home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / PERL4036.ZIP / util.c < prev    next >
C/C++ Source or Header  |  1993-02-26  |  36KB  |  1,778 lines

  1. /* $RCSfile: util.c,v $$Revision: 4.0.1.6 $$Date: 92/06/11 21:18:47 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    util.c,v $
  9.  * Revision 4.0.1.6  92/06/11  21:18:47  lwall
  10.  * patch34: boneheaded typo in my_bcopy()
  11.  * 
  12.  * Revision 4.0.1.5  92/06/08  16:08:37  lwall
  13.  * patch20: removed implicit int declarations on functions
  14.  * patch20: Perl now distinguishes overlapped copies from non-overlapped
  15.  * patch20: fixed confusion between a *var's real name and its effective name
  16.  * patch20: bcopy() and memcpy() now tested for overlap safety
  17.  * patch20: added Atari ST portability
  18.  * 
  19.  * Revision 4.0.1.4  91/11/11  16:48:54  lwall
  20.  * patch19: study was busted by 4.018
  21.  * patch19: added little-endian pack/unpack options
  22.  * 
  23.  * Revision 4.0.1.3  91/11/05  19:18:26  lwall
  24.  * patch11: safe malloc code now integrated into Perl's malloc when possible
  25.  * patch11: index("little", "longer string") could visit faraway places
  26.  * patch11: warn '-' x 10000 dumped core
  27.  * patch11: forked exec on non-existent program now issues a warning
  28.  * 
  29.  * Revision 4.0.1.2  91/06/07  12:10:42  lwall
  30.  * patch4: new copyright notice
  31.  * patch4: made some allowances for "semi-standard" C
  32.  * patch4: index() could blow up searching for null string
  33.  * patch4: taintchecks could improperly modify parent in vfork()
  34.  * patch4: exec would close files even if you cleared close-on-exec flag
  35.  * 
  36.  * Revision 4.0.1.1  91/04/12  09:19:25  lwall
  37.  * patch1: random cleanup in cpp namespace
  38.  * 
  39.  * Revision 4.0  91/03/20  01:56:39  lwall
  40.  * 4.0 baseline.
  41.  * 
  42.  */
  43. /*SUPPRESS 112*/
  44.  
  45. #include "EXTERN.h"
  46. #include "perl.h"
  47.  
  48. #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  49. #include <signal.h>
  50. #endif
  51.  
  52. #ifdef I_VFORK
  53. #  include <vfork.h>
  54. #endif
  55.  
  56. #ifdef I_VARARGS
  57. #  include <varargs.h>
  58. #endif
  59.  
  60. #ifdef I_FCNTL
  61. #  include <fcntl.h>
  62. #endif
  63. #ifdef I_SYS_FILE
  64. #  include <sys/file.h>
  65. #endif
  66.  
  67. #define FLUSH
  68.  
  69. #ifndef safemalloc
  70.  
  71. static char nomem[] = "Out of memory!\n";
  72.  
  73. /* paranoid version of malloc */
  74.  
  75. #ifdef DEBUGGING
  76. static int an = 0;
  77. #endif
  78.  
  79. /* NOTE:  Do not call the next three routines directly.  Use the macros
  80.  * in handy.h, so that we can easily redefine everything to do tracking of
  81.  * allocated hunks back to the original New to track down any memory leaks.
  82.  */
  83.  
  84. char *
  85. safemalloc(size)
  86. #ifdef MSDOS
  87. unsigned long size;
  88. #else
  89. MEM_SIZE size;
  90. #endif /* MSDOS */
  91. {
  92.     char *ptr;
  93. #ifndef STANDARD_C
  94.     char *malloc();
  95. #endif /* ! STANDARD_C */
  96.  
  97. #ifdef MSDOS
  98.     if (size > 0xffff) {
  99.         fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
  100.         exit(1);
  101.     }
  102. #endif /* MSDOS */
  103. #ifdef DEBUGGING
  104.     if ((long)size < 0)
  105.     fatal("panic: malloc");
  106. #endif
  107.     ptr = malloc(size?size:1);    /* malloc(0) is NASTY on our system */
  108. #ifdef DEBUGGING
  109. #  if !(defined(I286) || defined(atarist))
  110.     if (debug & 128)
  111.     fprintf(stderr,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
  112. #  else
  113.     if (debug & 128)
  114.     fprintf(stderr,"0x%lx: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
  115. #  endif
  116. #endif
  117.     if (ptr != Nullch)
  118.     return ptr;
  119.     else if (nomemok)
  120.     return Nullch;
  121.     else {
  122.     fputs(nomem,stderr) FLUSH;
  123.     exit(1);
  124.     }
  125.     /*NOTREACHED*/
  126. #ifdef lint
  127.     return ptr;
  128. #endif
  129. }
  130.  
  131. /* paranoid version of realloc */
  132.  
  133. char *
  134. saferealloc(where,size)
  135. char *where;
  136. #ifndef MSDOS
  137. MEM_SIZE size;
  138. #else
  139. unsigned long size;
  140. #endif /* MSDOS */
  141. {
  142.     char *ptr;
  143. #ifndef STANDARD_C
  144.     char *realloc();
  145. #endif /* ! STANDARD_C */
  146.  
  147. #ifdef MSDOS
  148.     if (size > 0xffff) {
  149.         fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
  150.         exit(1);
  151.     }
  152. #endif /* MSDOS */
  153.     if (!where)
  154.     fatal("Null realloc");
  155. #ifdef DEBUGGING
  156.     if ((long)size < 0)
  157.     fatal("panic: realloc");
  158. #endif
  159.     ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  160. #ifdef DEBUGGING
  161. #  if !(defined(I286) || defined(atarist))
  162.     if (debug & 128) {
  163.     fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
  164.     fprintf(stderr,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
  165.     }
  166. #  else
  167.     if (debug & 128) {
  168.     fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
  169.     fprintf(stderr,"0x%lx: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
  170.     }
  171. #  endif
  172. #endif
  173.     if (ptr != Nullch)
  174.     return ptr;
  175.     else if (nomemok)
  176.     return Nullch;
  177.     else {
  178.     fputs(nomem,stderr) FLUSH;
  179.     exit(1);
  180.     }
  181.     /*NOTREACHED*/
  182. #ifdef lint
  183.     return ptr;
  184. #endif
  185. }
  186.  
  187. /* safe version of free */
  188.  
  189. void
  190. safefree(where)
  191. char *where;
  192. {
  193. #ifdef DEBUGGING
  194. #  if !(defined(I286) || defined(atarist))
  195.     if (debug & 128)
  196.     fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
  197. #  else
  198.     if (debug & 128)
  199.     fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
  200. #  endif
  201. #endif
  202.     if (where) {
  203.     /*SUPPRESS 701*/
  204.     free(where);
  205.     }
  206. }
  207.  
  208. #endif /* !safemalloc */
  209.  
  210. #ifdef LEAKTEST
  211.  
  212. #define ALIGN sizeof(long)
  213.  
  214. char *
  215. safexmalloc(x,size)
  216. int x;
  217. MEM_SIZE size;
  218. {
  219.     register char *where;
  220.  
  221.     where = safemalloc(size + ALIGN);
  222.     xcount[x]++;
  223.     where[0] = x % 100;
  224.     where[1] = x / 100;
  225.     return where + ALIGN;
  226. }
  227.  
  228. char *
  229. safexrealloc(where,size)
  230. char *where;
  231. MEM_SIZE size;
  232. {
  233.     return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
  234. }
  235.  
  236. void
  237. safexfree(where)
  238. char *where;
  239. {
  240.     int x;
  241.  
  242.     if (!where)
  243.     return;
  244.     where -= ALIGN;
  245.     x = where[0] + 100 * where[1];
  246.     xcount[x]--;
  247.     safefree(where);
  248. }
  249.  
  250. static void
  251. xstat()
  252. {
  253.     register int i;
  254.  
  255.     for (i = 0; i < MAXXCOUNT; i++) {
  256.     if (xcount[i] > lastxcount[i]) {
  257.         fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
  258.         lastxcount[i] = xcount[i];
  259.     }
  260.     }
  261. }
  262.  
  263. #endif /* LEAKTEST */
  264.  
  265. /* copy a string up to some (non-backslashed) delimiter, if any */
  266.  
  267. char *
  268. cpytill(to,from,fromend,delim,retlen)
  269. register char *to;
  270. register char *from;
  271. register char *fromend;
  272. register int delim;
  273. int *retlen;
  274. {
  275.     char *origto = to;
  276.  
  277.     for (; from < fromend; from++,to++) {
  278.     if (*from == '\\') {
  279.         if (from[1] == delim)
  280.         from++;
  281.         else if (from[1] == '\\')
  282.         *to++ = *from++;
  283.     }
  284.     else if (*from == delim)
  285.         break;
  286.     *to = *from;
  287.     }
  288.     *to = '\0';
  289.     *retlen = to - origto;
  290.     return from;
  291. }
  292.  
  293. /* return ptr to little string in big string, NULL if not found */
  294. /* This routine was donated by Corey Satten. */
  295.  
  296. char *
  297. instr(big, little)
  298. register char *big;
  299. register char *little;
  300. {
  301.     register char *s, *x;
  302.     register int first;
  303.  
  304.     if (!little)
  305.     return big;
  306.     first = *little++;
  307.     if (!first)
  308.     return big;
  309.     while (*big) {
  310.     if (*big++ != first)
  311.         continue;
  312.     for (x=big,s=little; *s; /**/ ) {
  313.         if (!*x)
  314.         return Nullch;
  315.         if (*s++ != *x++) {
  316.         s--;
  317.         break;
  318.         }
  319.     }
  320.     if (!*s)
  321.         return big-1;
  322.     }
  323.     return Nullch;
  324. }
  325.  
  326. /* same as instr but allow embedded nulls */
  327.  
  328. char *
  329. ninstr(big, bigend, little, lend)
  330. register char *big;
  331. register char *bigend;
  332. char *little;
  333. char *lend;
  334. {
  335.     register char *s, *x;
  336.     register int first = *little;
  337.     register char *littleend = lend;
  338.  
  339.     if (!first && little > littleend)
  340.     return big;
  341.     if (bigend - big < littleend - little)
  342.     return Nullch;
  343.     bigend -= littleend - little++;
  344.     while (big <= bigend) {
  345.     if (*big++ != first)
  346.         continue;
  347.     for (x=big,s=little; s < littleend; /**/ ) {
  348.         if (*s++ != *x++) {
  349.         s--;
  350.         break;
  351.         }
  352.     }
  353.     if (s >= littleend)
  354.         return big-1;
  355.     }
  356.     return Nullch;
  357. }
  358.  
  359. /* reverse of the above--find last substring */
  360.  
  361. char *
  362. rninstr(big, bigend, little, lend)
  363. register char *big;
  364. char *bigend;
  365. char *little;
  366. char *lend;
  367. {
  368.     register char *bigbeg;
  369.     register char *s, *x;
  370.     register int first = *little;
  371.     register char *littleend = lend;
  372.  
  373.     if (!first && little > littleend)
  374.     return bigend;
  375.     bigbeg = big;
  376.     big = bigend - (littleend - little++);
  377.     while (big >= bigbeg) {
  378.     if (*big-- != first)
  379.         continue;
  380.     for (x=big+2,s=little; s < littleend; /**/ ) {
  381.         if (*s++ != *x++) {
  382.         s--;
  383.         break;
  384.         }
  385.     }
  386.     if (s >= littleend)
  387.         return big+1;
  388.     }
  389.     return Nullch;
  390. }
  391.  
  392. unsigned char fold[] = {
  393.     0,    1,    2,    3,    4,    5,    6,    7,
  394.     8,    9,    10,    11,    12,    13,    14,    15,
  395.     16,    17,    18,    19,    20,    21,    22,    23,
  396.     24,    25,    26,    27,    28,    29,    30,    31,
  397.     32,    33,    34,    35,    36,    37,    38,    39,
  398.     40,    41,    42,    43,    44,    45,    46,    47,
  399.     48,    49,    50,    51,    52,    53,    54,    55,
  400.     56,    57,    58,    59,    60,    61,    62,    63,
  401.     64,    'a',    'b',    'c',    'd',    'e',    'f',    'g',
  402.     'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',
  403.     'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
  404.     'x',    'y',    'z',    91,    92,    93,    94,    95,
  405.     96,    'A',    'B',    'C',    'D',    'E',    'F',    'G',
  406.     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
  407.     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
  408.     'X',    'Y',    'Z',    123,    124,    125,    126,    127,
  409.     128,    129,    130,    131,    132,    133,    134,    135,
  410.     136,    137,    138,    139,    140,    141,    142,    143,
  411.     144,    145,    146,    147,    148,    149,    150,    151,
  412.     152,    153,    154,    155,    156,    157,    158,    159,
  413.     160,    161,    162,    163,    164,    165,    166,    167,
  414.     168,    169,    170,    171,    172,    173,    174,    175,
  415.     176,    177,    178,    179,    180,    181,    182,    183,
  416.     184,    185,    186,    187,    188,    189,    190,    191,
  417.     192,    193,    194,    195,    196,    197,    198,    199,
  418.     200,    201,    202,    203,    204,    205,    206,    207,
  419.     208,    209,    210,    211,    212,    213,    214,    215,
  420.     216,    217,    218,    219,    220,    221,    222,    223,    
  421.     224,    225,    226,    227,    228,    229,    230,    231,
  422.     232,    233,    234,    235,    236,    237,    238,    239,
  423.     240,    241,    242,    243,    244,    245,    246,    247,
  424.     248,    249,    250,    251,    252,    253,    254,    255
  425. };
  426.  
  427. static unsigned char freq[] = {
  428.     1,    2,    84,    151,    154,    155,    156,    157,
  429.     165,    246,    250,    3,    158,    7,    18,    29,
  430.     40,    51,    62,    73,    85,    96,    107,    118,
  431.     129,    140,    147,    148,    149,    150,    152,    153,
  432.     255,    182,    224,    205,    174,    176,    180,    217,
  433.     233,    232,    236,    187,    235,    228,    234,    226,
  434.     222,    219,    211,    195,    188,    193,    185,    184,
  435.     191,    183,    201,    229,    181,    220,    194,    162,
  436.     163,    208,    186,    202,    200,    218,    198,    179,
  437.     178,    214,    166,    170,    207,    199,    209,    206,
  438.     204,    160,    212,    216,    215,    192,    175,    173,
  439.     243,    172,    161,    190,    203,    189,    164,    230,
  440.     167,    248,    227,    244,    242,    255,    241,    231,
  441.     240,    253,    169,    210,    245,    237,    249,    247,
  442.     239,    168,    252,    251,    254,    238,    223,    221,
  443.     213,    225,    177,    197,    171,    196,    159,    4,
  444.     5,    6,    8,    9,    10,    11,    12,    13,
  445.     14,    15,    16,    17,    19,    20,    21,    22,
  446.     23,    24,    25,    26,    27,    28,    30,    31,
  447.     32,    33,    34,    35,    36,    37,    38,    39,
  448.     41,    42,    43,    44,    45,    46,    47,    48,
  449.     49,    50,    52,    53,    54,    55,    56,    57,
  450.     58,    59,    60,    61,    63,    64,    65,    66,
  451.     67,    68,    69,    70,    71,    72,    74,    75,
  452.     76,    77,    78,    79,    80,    81,    82,    83,
  453.     86,    87,    88,    89,    90,    91,    92,    93,
  454.     94,    95,    97,    98,    99,    100,    101,    102,
  455.     103,    104,    105,    106,    108,    109,    110,    111,
  456.     112,    113,    114,    115,    116,    117,    119,    120,
  457.     121,    122,    123,    124,    125,    126,    127,    128,
  458.     130,    131,    132,    133,    134,    135,    136,    137,
  459.     138,    139,    141,    142,    143,    144,    145,    146
  460. };
  461.  
  462. void
  463. fbmcompile(str, iflag)
  464. STR *str;
  465. int iflag;
  466. {
  467.     register unsigned char *s;
  468.     register unsigned char *table;
  469.     register unsigned int i;
  470.     register unsigned int len = str->str_cur;
  471.     int rarest = 0;
  472.     unsigned int frequency = 256;
  473.  
  474.     Str_Grow(str,len+258);
  475. #ifndef lint
  476.     table = (unsigned char*)(str->str_ptr + len + 1);
  477. #else
  478.     table = Null(unsigned char*);
  479. #endif
  480.     s = table - 2;
  481.     for (i = 0; i < 256; i++) {
  482.     table[i] = len;
  483.     }
  484.     i = 0;
  485. #ifndef lint
  486.     while (s >= (unsigned char*)(str->str_ptr))
  487. #endif
  488.     {
  489.     if (table[*s] == len) {
  490. #ifndef pdp11
  491.         if (iflag)
  492.         table[*s] = table[fold[*s]] = i;
  493. #else
  494.         if (iflag) {
  495.         int j;
  496.         j = fold[*s];
  497.         table[j] = i;
  498.         table[*s] = i;
  499.         }
  500. #endif /* pdp11 */
  501.         else
  502.         table[*s] = i;
  503.     }
  504.     s--,i++;
  505.     }
  506.     str->str_pok |= SP_FBM;        /* deep magic */
  507.  
  508. #ifndef lint
  509.     s = (unsigned char*)(str->str_ptr);        /* deeper magic */
  510. #else
  511.     s = Null(unsigned char*);
  512. #endif
  513.     if (iflag) {
  514.     register unsigned int tmp, foldtmp;
  515.     str->str_pok |= SP_CASEFOLD;
  516.     for (i = 0; i < len; i++) {
  517.         tmp=freq[s[i]];
  518.         foldtmp=freq[fold[s[i]]];
  519.         if (tmp < frequency && foldtmp < frequency) {
  520.         rarest = i;
  521.         /* choose most frequent among the two */
  522.         frequency = (tmp > foldtmp) ? tmp : foldtmp;
  523.         }
  524.     }
  525.     }
  526.     else {
  527.     for (i = 0; i < len; i++) {
  528.         if (freq[s[i]] < frequency) {
  529.         rarest = i;
  530.         frequency = freq[s[i]];
  531.         }
  532.     }
  533.     }
  534.     str->str_rare = s[rarest];
  535.     str->str_state = rarest;
  536. #ifdef DEBUGGING
  537.     if (debug & 512)
  538.     fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
  539. #endif
  540. }
  541.  
  542. char *
  543. fbminstr(big, bigend, littlestr)
  544. unsigned char *big;
  545. register unsigned char *bigend;
  546. STR *littlestr;
  547. {
  548.     register unsigned char *s;
  549.     register int tmp;
  550.     register int littlelen;
  551.     register unsigned char *little;
  552.     register unsigned char *table;
  553.     register unsigned char *olds;
  554.     register unsigned char *oldlittle;
  555.  
  556. #ifndef lint
  557.     if (!(littlestr->str_pok & SP_FBM)) {
  558.     if (!littlestr->str_ptr)
  559.         return (char*)big;
  560.     return ninstr((char*)big,(char*)bigend,
  561.         littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
  562.     }
  563. #endif
  564.  
  565.     littlelen = littlestr->str_cur;
  566. #ifndef lint
  567.     if (littlestr->str_pok & SP_TAIL && !multiline) {    /* tail anchored? */
  568.     if (littlelen > bigend - big)
  569.         return Nullch;
  570.     little = (unsigned char*)littlestr->str_ptr;
  571.     if (littlestr->str_pok & SP_CASEFOLD) {    /* oops, fake it */
  572.         big = bigend - littlelen;        /* just start near end */
  573.         if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
  574.         big--;
  575.     }
  576.     else {
  577.         s = bigend - littlelen;
  578.         if (*s == *little && bcmp(s,little,littlelen)==0)
  579.         return (char*)s;        /* how sweet it is */
  580.         else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
  581.           && s > big) {
  582.             s--;
  583.         if (*s == *little && bcmp(s,little,littlelen)==0)
  584.             return (char*)s;
  585.         }
  586.         return Nullch;
  587.     }
  588.     }
  589.     table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
  590. #else
  591.     table = Null(unsigned char*);
  592. #endif
  593.     if (--littlelen >= bigend - big)
  594.     return Nullch;
  595.     s = big + littlelen;
  596.     oldlittle = little = table - 2;
  597.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insensitive? */
  598.     if (s < bigend) {
  599.       top1:
  600.         /*SUPPRESS 560*/
  601.         if (tmp = table[*s]) {
  602. #ifdef POINTERRIGOR
  603.         if (bigend - s > tmp) {
  604.             s += tmp;
  605.             goto top1;
  606.         }
  607. #else
  608.         if ((s += tmp) < bigend)
  609.             goto top1;
  610. #endif
  611.         return Nullch;
  612.         }
  613.         else {
  614.         tmp = littlelen;    /* less expensive than calling strncmp() */
  615.         olds = s;
  616.         while (tmp--) {
  617.             if (*--s == *--little || fold[*s] == *little)
  618.             continue;
  619.             s = olds + 1;    /* here we pay the price for failure */
  620.             little = oldlittle;
  621.             if (s < bigend)    /* fake up continue to outer loop */
  622.             goto top1;
  623.             return Nullch;
  624.         }
  625. #ifndef lint
  626.         return (char *)s;
  627. #endif
  628.         }
  629.     }
  630.     }
  631.     else {
  632.     if (s < bigend) {
  633.       top2:
  634.         /*SUPPRESS 560*/
  635.         if (tmp = table[*s]) {
  636. #ifdef POINTERRIGOR
  637.         if (bigend - s > tmp) {
  638.             s += tmp;
  639.             goto top2;
  640.         }
  641. #else
  642.         if ((s += tmp) < bigend)
  643.             goto top2;
  644. #endif
  645.         return Nullch;
  646.         }
  647.         else {
  648.         tmp = littlelen;    /* less expensive than calling strncmp() */
  649.         olds = s;
  650.         while (tmp--) {
  651.             if (*--s == *--little)
  652.             continue;
  653.             s = olds + 1;    /* here we pay the price for failure */
  654.             little = oldlittle;
  655.             if (s < bigend)    /* fake up continue to outer loop */
  656.             goto top2;
  657.             return Nullch;
  658.         }
  659. #ifndef lint
  660.         return (char *)s;
  661. #endif
  662.         }
  663.     }
  664.     }
  665.     return Nullch;
  666. }
  667.  
  668. char *
  669. screaminstr(bigstr, littlestr)
  670. STR *bigstr;
  671. STR *littlestr;
  672. {
  673.     register unsigned char *s, *x;
  674.     register unsigned char *big;
  675.     register int pos;
  676.     register int previous;
  677.     register int first;
  678.     register unsigned char *little;
  679.     register unsigned char *bigend;
  680.     register unsigned char *littleend;
  681.  
  682.     if ((pos = screamfirst[littlestr->str_rare]) < 0) 
  683.     return Nullch;
  684. #ifndef lint
  685.     little = (unsigned char *)(littlestr->str_ptr);
  686. #else
  687.     little = Null(unsigned char *);
  688. #endif
  689.     littleend = little + littlestr->str_cur;
  690.     first = *little++;
  691.     previous = littlestr->str_state;
  692. #ifndef lint
  693.     big = (unsigned char *)(bigstr->str_ptr);
  694. #else
  695.     big = Null(unsigned char*);
  696. #endif
  697.     bigend = big + bigstr->str_cur;
  698.     while (pos < previous) {
  699. #ifndef lint
  700.     if (!(pos += screamnext[pos]))
  701. #endif
  702.         return Nullch;
  703.     }
  704. #ifdef POINTERRIGOR
  705.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  706.     do {
  707.         if (big[pos-previous] != first && big[pos-previous] != fold[first])
  708.         continue;
  709.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  710.         if (x >= bigend)
  711.             return Nullch;
  712.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  713.             s--;
  714.             break;
  715.         }
  716.         }
  717.         if (s == littleend)
  718. #ifndef lint
  719.         return (char *)(big+pos-previous);
  720. #else
  721.         return Nullch;
  722. #endif
  723.     } while (
  724. #ifndef lint
  725.         pos += screamnext[pos]    /* does this goof up anywhere? */
  726. #else
  727.         pos += screamnext[0]
  728. #endif
  729.         );
  730.     }
  731.     else {
  732.     do {
  733.         if (big[pos-previous] != first)
  734.         continue;
  735.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  736.         if (x >= bigend)
  737.             return Nullch;
  738.         if (*s++ != *x++) {
  739.             s--;
  740.             break;
  741.         }
  742.         }
  743.         if (s == littleend)
  744. #ifndef lint
  745.         return (char *)(big+pos-previous);
  746. #else
  747.         return Nullch;
  748. #endif
  749.     } while (
  750. #ifndef lint
  751.         pos += screamnext[pos]
  752. #else
  753.         pos += screamnext[0]
  754. #endif
  755.         );
  756.     }
  757. #else /* !POINTERRIGOR */
  758.     big -= previous;
  759.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  760.     do {
  761.         if (big[pos] != first && big[pos] != fold[first])
  762.         continue;
  763.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  764.         if (x >= bigend)
  765.             return Nullch;
  766.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  767.             s--;
  768.             break;
  769.         }
  770.         }
  771.         if (s == littleend)
  772. #ifndef lint
  773.         return (char *)(big+pos);
  774. #else
  775.         return Nullch;
  776. #endif
  777.     } while (
  778. #ifndef lint
  779.         pos += screamnext[pos]    /* does this goof up anywhere? */
  780. #else
  781.         pos += screamnext[0]
  782. #endif
  783.         );
  784.     }
  785.     else {
  786.     do {
  787.         if (big[pos] != first)
  788.         continue;
  789.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  790.         if (x >= bigend)
  791.             return Nullch;
  792.         if (*s++ != *x++) {
  793.             s--;
  794.             break;
  795.         }
  796.         }
  797.         if (s == littleend)
  798. #ifndef lint
  799.         return (char *)(big+pos);
  800. #else
  801.         return Nullch;
  802. #endif
  803.     } while (
  804. #ifndef lint
  805.         pos += screamnext[pos]
  806. #else
  807.         pos += screamnext[0]
  808. #endif
  809.         );
  810.     }
  811. #endif /* POINTERRIGOR */
  812.     return Nullch;
  813. }
  814.  
  815. /* copy a string to a safe spot */
  816.  
  817. char *
  818. savestr(str)
  819. char *str;
  820. {
  821.     register char *newaddr;
  822.  
  823.     New(902,newaddr,strlen(str)+1,char);
  824.     (void)strcpy(newaddr,str);
  825.     return newaddr;
  826. }
  827.  
  828. /* same thing but with a known length */
  829.  
  830. char *
  831. nsavestr(str, len)
  832. char *str;
  833. register int len;
  834. {
  835.     register char *newaddr;
  836.  
  837.     New(903,newaddr,len+1,char);
  838.     Copy(str,newaddr,len,char);        /* might not be null terminated */
  839.     newaddr[len] = '\0';        /* is now */
  840.     return newaddr;
  841. }
  842.  
  843. /* grow a static string to at least a certain length */
  844.  
  845. void
  846. growstr(strptr,curlen,newlen)
  847. char **strptr;
  848. int *curlen;
  849. int newlen;
  850. {
  851.     if (newlen > *curlen) {        /* need more room? */
  852.     if (*curlen)
  853.         Renew(*strptr,newlen,char);
  854.     else
  855.         New(905,*strptr,newlen,char);
  856.     *curlen = newlen;
  857.     }
  858. }
  859.  
  860. #ifndef I_VARARGS
  861. /*VARARGS1*/
  862. char *
  863. mess(pat,a1,a2,a3,a4)
  864. char *pat;
  865. long a1, a2, a3, a4;
  866. {
  867.     char *s;
  868.     int usermess = strEQ(pat,"%s");
  869.     STR *tmpstr;
  870.  
  871.     s = buf;
  872.     if (usermess) {
  873.     tmpstr = str_mortal(&str_undef);
  874.     str_set(tmpstr, (char*)a1);
  875.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  876.     }
  877.     else {
  878.     (void)sprintf(s,pat,a1,a2,a3,a4);
  879.     s += strlen(s);
  880.     }
  881.  
  882.     if (s[-1] != '\n') {
  883.     if (curcmd->c_line) {
  884.         (void)sprintf(s," at %s line %ld",
  885.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  886.         s += strlen(s);
  887.     }
  888.     if (last_in_stab &&
  889.         stab_io(last_in_stab) &&
  890.         stab_io(last_in_stab)->lines ) {
  891.         (void)sprintf(s,", <%s> line %ld",
  892.           last_in_stab == argvstab ? "" : stab_ename(last_in_stab),
  893.           (long)stab_io(last_in_stab)->lines);
  894.         s += strlen(s);
  895.     }
  896.     (void)strcpy(s,".\n");
  897.     if (usermess)
  898.         str_cat(tmpstr,buf+1);
  899.     }
  900.     if (usermess)
  901.     return tmpstr->str_ptr;
  902.     else
  903.     return buf;
  904. }
  905.  
  906. /*VARARGS1*/
  907. void fatal(pat,a1,a2,a3,a4)
  908. char *pat;
  909. long a1, a2, a3, a4;
  910. {
  911.     extern FILE *e_fp;
  912.     extern char *e_tmpname;
  913.     char *tmps;
  914.     char *message;
  915.  
  916.     message = mess(pat,a1,a2,a3,a4);
  917.     if (in_eval) {
  918.     str_set(stab_val(stabent("@",TRUE)),message);
  919.     tmps = "_EVAL_";
  920.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  921.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  922. #ifdef DEBUGGING
  923.         if (debug & 4) {
  924.         deb("(Skipping label #%d %s)\n",loop_ptr,
  925.             loop_stack[loop_ptr].loop_label);
  926.         }
  927. #endif
  928.         loop_ptr--;
  929.     }
  930. #ifdef DEBUGGING
  931.     if (debug & 4) {
  932.         deb("(Found label #%d %s)\n",loop_ptr,
  933.         loop_stack[loop_ptr].loop_label);
  934.     }
  935. #endif
  936.     if (loop_ptr < 0) {
  937.         in_eval = 0;
  938.         fatal("Bad label: %s", tmps);
  939.     }
  940.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  941.     }
  942.     fputs(message,stderr);
  943.     (void)fflush(stderr);
  944.     if (e_fp)
  945.     (void)UNLINK(e_tmpname);
  946.     statusvalue >>= 8;
  947.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  948. }
  949.  
  950. /*VARARGS1*/
  951. void warn(pat,a1,a2,a3,a4)
  952. char *pat;
  953. long a1, a2, a3, a4;
  954. {
  955.     char *message;
  956.  
  957.     message = mess(pat,a1,a2,a3,a4);
  958.     fputs(message,stderr);
  959. #ifdef LEAKTEST
  960. #ifdef DEBUGGING
  961.     if (debug & 4096)
  962.     xstat();
  963. #endif
  964. #endif
  965.     (void)fflush(stderr);
  966. }
  967. #else
  968. /*VARARGS0*/
  969. char *
  970. mess(args)
  971. va_list args;
  972. {
  973.     char *pat;
  974.     char *s;
  975.     STR *tmpstr;
  976.     int usermess;
  977. #ifndef HAS_VPRINTF
  978. #ifdef CHARVSPRINTF
  979.     char *vsprintf();
  980. #else
  981.     int vsprintf();
  982. #endif
  983. #endif
  984.  
  985. #ifdef lint
  986.     pat = Nullch;
  987. #else
  988.     pat = va_arg(args, char *);
  989. #endif
  990.     s = buf;
  991.     usermess = strEQ(pat, "%s");
  992.     if (usermess) {
  993.     tmpstr = str_mortal(&str_undef);
  994.     str_set(tmpstr, va_arg(args, char *));
  995.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  996.     }
  997.     else {
  998.     (void) vsprintf(s,pat,args);
  999.     s += strlen(s);
  1000.     }
  1001.  
  1002.     if (s[-1] != '\n') {
  1003.     if (curcmd->c_line) {
  1004.         (void)sprintf(s," at %s line %ld",
  1005.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  1006.         s += strlen(s);
  1007.     }
  1008.     if (last_in_stab &&
  1009.         stab_io(last_in_stab) &&
  1010.         stab_io(last_in_stab)->lines ) {
  1011.         (void)sprintf(s,", <%s> line %ld",
  1012.           last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
  1013.           (long)stab_io(last_in_stab)->lines);
  1014.         s += strlen(s);
  1015.     }
  1016.     (void)strcpy(s,".\n");
  1017.     if (usermess)
  1018.         str_cat(tmpstr,buf+1);
  1019.     }
  1020.  
  1021.     if (usermess)
  1022.     return tmpstr->str_ptr;
  1023.     else
  1024.     return buf;
  1025. }
  1026.  
  1027. /*VARARGS0*/
  1028. void fatal(va_alist)
  1029. va_dcl
  1030. {
  1031.     va_list args;
  1032.     extern FILE *e_fp;
  1033.     extern char *e_tmpname;
  1034.     char *tmps;
  1035.     char *message;
  1036.  
  1037. #ifndef lint
  1038.     va_start(args);
  1039. #else
  1040.     args = 0;
  1041. #endif
  1042.     message = mess(args);
  1043.     va_end(args);
  1044.     if (in_eval) {
  1045.     str_set(stab_val(stabent("@",TRUE)),message);
  1046.     tmps = "_EVAL_";
  1047.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  1048.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  1049. #ifdef DEBUGGING
  1050.         if (debug & 4) {
  1051.         deb("(Skipping label #%d %s)\n",loop_ptr,
  1052.             loop_stack[loop_ptr].loop_label);
  1053.         }
  1054. #endif
  1055.         loop_ptr--;
  1056.     }
  1057. #ifdef DEBUGGING
  1058.     if (debug & 4) {
  1059.         deb("(Found label #%d %s)\n",loop_ptr,
  1060.         loop_stack[loop_ptr].loop_label);
  1061.     }
  1062. #endif
  1063.     if (loop_ptr < 0) {
  1064.         in_eval = 0;
  1065.         fatal("Bad label: %s", tmps);
  1066.     }
  1067.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  1068.     }
  1069.     fputs(message,stderr);
  1070.     (void)fflush(stderr);
  1071.     if (e_fp)
  1072.     (void)UNLINK(e_tmpname);
  1073.     statusvalue >>= 8;
  1074.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  1075. }
  1076.  
  1077. /*VARARGS0*/
  1078. void warn(va_alist)
  1079. va_dcl
  1080. {
  1081.     va_list args;
  1082.     char *message;
  1083.  
  1084. #ifndef lint
  1085.     va_start(args);
  1086. #else
  1087.     args = 0;
  1088. #endif
  1089.     message = mess(args);
  1090.     va_end(args);
  1091.  
  1092.     fputs(message,stderr);
  1093. #ifdef LEAKTEST
  1094. #ifdef DEBUGGING
  1095.     if (debug & 4096)
  1096.     xstat();
  1097. #endif
  1098. #endif
  1099.     (void)fflush(stderr);
  1100. }
  1101. #endif
  1102.  
  1103. void
  1104. my_setenv(nam,val)
  1105. char *nam, *val;
  1106. {
  1107.     register int i=envix(nam);        /* where does it go? */
  1108.  
  1109.     if (environ == origenviron) {    /* need we copy environment? */
  1110.     int j;
  1111.     int max;
  1112.     char **tmpenv;
  1113.  
  1114.     /*SUPPRESS 530*/
  1115.     for (max = i; environ[max]; max++) ;
  1116.     New(901,tmpenv, max+2, char*);
  1117.     for (j=0; j<max; j++)        /* copy environment */
  1118.         tmpenv[j] = savestr(environ[j]);
  1119.     tmpenv[max] = Nullch;
  1120.     environ = tmpenv;        /* tell exec where it is now */
  1121.     }
  1122.     if (!val) {
  1123.     while (environ[i]) {
  1124.         environ[i] = environ[i+1];
  1125.         i++;
  1126.     }
  1127.     return;
  1128.     }
  1129.     if (!environ[i]) {            /* does not exist yet */
  1130.     Renew(environ, i+2, char*);    /* just expand it a bit */
  1131.     environ[i+1] = Nullch;    /* make sure it's null terminated */
  1132.     }
  1133.     else
  1134.     Safefree(environ[i]);
  1135.     New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
  1136. #ifndef DOSISH
  1137.     (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  1138. #else
  1139.     /* MS-DOS requires environment variable names to be in uppercase */
  1140.     /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
  1141.      * some utilities and applications may break because they only look
  1142.      * for upper case strings. (Fixed strupr() bug here.)]
  1143.      */
  1144.     strcpy(environ[i],nam); strupr(environ[i]);
  1145.     (void)sprintf(environ[i] + strlen(nam),"=%s",val);
  1146. #endif /* MSDOS */
  1147. }
  1148.  
  1149. int
  1150. envix(nam)
  1151. char *nam;
  1152. {
  1153.     register int i, len = strlen(nam);
  1154.  
  1155.     for (i = 0; environ[i]; i++) {
  1156.     if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  1157.         break;            /* strnEQ must come first to avoid */
  1158.     }                    /* potential SEGV's */
  1159.     return i;
  1160. }
  1161.  
  1162. #ifdef EUNICE
  1163. int
  1164. unlnk(f)    /* unlink all versions of a file */
  1165. char *f;
  1166. {
  1167.     int i;
  1168.  
  1169.     for (i = 0; unlink(f) >= 0; i++) ;
  1170.     return i ? 0 : -1;
  1171. }
  1172. #endif
  1173.  
  1174. #if !defined(HAS_BCOPY) || !defined(SAFE_BCOPY)
  1175. char *
  1176. my_bcopy(from,to,len)
  1177. register char *from;
  1178. register char *to;
  1179. register int len;
  1180. {
  1181.     char *retval = to;
  1182.  
  1183.     if (from - to >= 0) {
  1184.     while (len--)
  1185.         *to++ = *from++;
  1186.     }
  1187.     else {
  1188.     to += len;
  1189.     from += len;
  1190.     while (len--)
  1191.         *(--to) = *(--from);
  1192.     }
  1193.     return retval;
  1194. }
  1195. #endif
  1196.  
  1197. #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
  1198. char *
  1199. my_bzero(loc,len)
  1200. register char *loc;
  1201. register int len;
  1202. {
  1203.     char *retval = loc;
  1204.  
  1205.     while (len--)
  1206.     *loc++ = 0;
  1207.     return retval;
  1208. }
  1209. #endif
  1210.  
  1211. #ifndef HAS_MEMCMP
  1212. int
  1213. my_memcmp(s1,s2,len)
  1214. register unsigned char *s1;
  1215. register unsigned char *s2;
  1216. register int len;
  1217. {
  1218.     register int tmp;
  1219.  
  1220.     while (len--) {
  1221.     if (tmp = *s1++ - *s2++)
  1222.         return tmp;
  1223.     }
  1224.     return 0;
  1225. }
  1226. #endif /* HAS_MEMCMP */
  1227.  
  1228. #ifdef I_VARARGS
  1229. #ifndef HAS_VPRINTF
  1230.  
  1231. #ifdef CHARVSPRINTF
  1232. char *
  1233. #else
  1234. int
  1235. #endif
  1236. vsprintf(dest, pat, args)
  1237. char *dest, *pat, *args;
  1238. {
  1239.     FILE fakebuf;
  1240.  
  1241.     fakebuf._ptr = dest;
  1242.     fakebuf._cnt = 32767;
  1243. #ifndef _IOSTRG
  1244. #define _IOSTRG 0
  1245. #endif
  1246.     fakebuf._flag = _IOWRT|_IOSTRG;
  1247.     _doprnt(pat, args, &fakebuf);    /* what a kludge */
  1248.     (void)putc('\0', &fakebuf);
  1249. #ifdef CHARVSPRINTF
  1250.     return(dest);
  1251. #else
  1252.     return 0;        /* perl doesn't use return value */
  1253. #endif
  1254. }
  1255.  
  1256. #ifdef DEBUGGING
  1257. int
  1258. vfprintf(fd, pat, args)
  1259. FILE *fd;
  1260. char *pat, *args;
  1261. {
  1262.     _doprnt(pat, args, fd);
  1263.     return 0;        /* wrong, but perl doesn't use the return value */
  1264. }
  1265. #endif
  1266. #endif /* HAS_VPRINTF */
  1267. #endif /* I_VARARGS */
  1268.  
  1269. /*
  1270.  * I think my_swap(), htonl() and ntohl() have never been used.
  1271.  * perl.h contains last-chance references to my_swap(), my_htonl()
  1272.  * and my_ntohl().  I presume these are the intended functions;
  1273.  * but htonl() and ntohl() have the wrong names.  There are no
  1274.  * functions my_htonl() and my_ntohl() defined anywhere.
  1275.  * -DWS
  1276.  */
  1277. #ifdef MYSWAP
  1278. #if BYTEORDER != 0x4321
  1279. short
  1280. my_swap(s)
  1281. short s;
  1282. {
  1283. #if (BYTEORDER & 1) == 0
  1284.     short result;
  1285.  
  1286.     result = ((s & 255) << 8) + ((s >> 8) & 255);
  1287.     return result;
  1288. #else
  1289.     return s;
  1290. #endif
  1291. }
  1292.  
  1293. long
  1294. htonl(l)
  1295. register long l;
  1296. {
  1297.     union {
  1298.     long result;
  1299.     char c[sizeof(long)];
  1300.     } u;
  1301.  
  1302. #if BYTEORDER == 0x1234
  1303.     u.c[0] = (l >> 24) & 255;
  1304.     u.c[1] = (l >> 16) & 255;
  1305.     u.c[2] = (l >> 8) & 255;
  1306.     u.c[3] = l & 255;
  1307.     return u.result;
  1308. #else
  1309. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1310.     fatal("Unknown BYTEORDER\n");
  1311. #else
  1312.     register int o;
  1313.     register int s;
  1314.  
  1315.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1316.     u.c[o & 0xf] = (l >> s) & 255;
  1317.     }
  1318.     return u.result;
  1319. #endif
  1320. #endif
  1321. }
  1322.  
  1323. long
  1324. ntohl(l)
  1325. register long l;
  1326. {
  1327.     union {
  1328.     long l;
  1329.     char c[sizeof(long)];
  1330.     } u;
  1331.  
  1332. #if BYTEORDER == 0x1234
  1333.     u.c[0] = (l >> 24) & 255;
  1334.     u.c[1] = (l >> 16) & 255;
  1335.     u.c[2] = (l >> 8) & 255;
  1336.     u.c[3] = l & 255;
  1337.     return u.l;
  1338. #else
  1339. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1340.     fatal("Unknown BYTEORDER\n");
  1341. #else
  1342.     register int o;
  1343.     register int s;
  1344.  
  1345.     u.l = l;
  1346.     l = 0;
  1347.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1348.     l |= (u.c[o & 0xf] & 255) << s;
  1349.     }
  1350.     return l;
  1351. #endif
  1352. #endif
  1353. }
  1354.  
  1355. #endif /* BYTEORDER != 0x4321 */
  1356. #endif /* MYSWAP */
  1357.  
  1358. /*
  1359.  * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
  1360.  * If these functions are defined,
  1361.  * the BYTEORDER is neither 0x1234 nor 0x4321.
  1362.  * However, this is not assumed.
  1363.  * -DWS
  1364.  */
  1365.  
  1366. #define HTOV(name,type)                        \
  1367.     type                            \
  1368.     name (n)                        \
  1369.     register type n;                    \
  1370.     {                            \
  1371.         union {                        \
  1372.         type value;                    \
  1373.         char c[sizeof(type)];                \
  1374.         } u;                        \
  1375.         register int i;                    \
  1376.         register int s;                    \
  1377.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1378.         u.c[i] = (n >> s) & 0xFF;            \
  1379.         }                            \
  1380.         return u.value;                    \
  1381.     }
  1382.  
  1383. #define VTOH(name,type)                        \
  1384.     type                            \
  1385.     name (n)                        \
  1386.     register type n;                    \
  1387.     {                            \
  1388.         union {                        \
  1389.         type value;                    \
  1390.         char c[sizeof(type)];                \
  1391.         } u;                        \
  1392.         register int i;                    \
  1393.         register int s;                    \
  1394.         u.value = n;                    \
  1395.         n = 0;                        \
  1396.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1397.         n += (u.c[i] & 0xFF) << s;            \
  1398.         }                            \
  1399.         return n;                        \
  1400.     }
  1401.  
  1402. #if defined(HAS_HTOVS) && !defined(htovs)
  1403. HTOV(htovs,short)
  1404. #endif
  1405. #if defined(HAS_HTOVL) && !defined(htovl)
  1406. HTOV(htovl,long)
  1407. #endif
  1408. #if defined(HAS_VTOHS) && !defined(vtohs)
  1409. VTOH(vtohs,short)
  1410. #endif
  1411. #if defined(HAS_VTOHL) && !defined(vtohl)
  1412. VTOH(vtohl,long)
  1413. #endif
  1414.  
  1415. #ifndef DOSISH
  1416. FILE *
  1417. mypopen(cmd,mode)
  1418. char    *cmd;
  1419. char    *mode;
  1420. {
  1421.     int p[2];
  1422.     register int this, that;
  1423.     register int pid;
  1424.     STR *str;
  1425.     int doexec = strNE(cmd,"-");
  1426.  
  1427.     if (pipe(p) < 0)
  1428.     return Nullfp;
  1429.     this = (*mode == 'w');
  1430.     that = !this;
  1431. #ifdef TAINT
  1432.     if (doexec) {
  1433.     taintenv();
  1434.     taintproper("Insecure dependency in exec");
  1435.     }
  1436. #endif
  1437.     while ((pid = (doexec?vfork():fork())) < 0) {
  1438.     if (errno != EAGAIN) {
  1439.         close(p[this]);
  1440.         if (!doexec)
  1441.         fatal("Can't fork");
  1442.         return Nullfp;
  1443.     }
  1444.     sleep(5);
  1445.     }
  1446.     if (pid == 0) {
  1447. #define THIS that
  1448. #define THAT this
  1449.     close(p[THAT]);
  1450.     if (p[THIS] != (*mode == 'r')) {
  1451.         dup2(p[THIS], *mode == 'r');
  1452.         close(p[THIS]);
  1453.     }
  1454.     if (doexec) {
  1455. #if !defined(HAS_FCNTL) || !defined(F_SETFD)
  1456.         int fd;
  1457.  
  1458. #ifndef NOFILE
  1459. #define NOFILE 20
  1460. #endif
  1461.         for (fd = maxsysfd + 1; fd < NOFILE; fd++)
  1462.         close(fd);
  1463. #endif
  1464.         do_exec(cmd);    /* may or may not use the shell */
  1465.         warn("Can't exec \"%s\": %s", cmd, strerror(errno));
  1466.         _exit(1);
  1467.     }
  1468.     /*SUPPRESS 560*/
  1469.     if (tmpstab = stabent("$",allstabs))
  1470.         str_numset(STAB_STR(tmpstab),(double)getpid());
  1471.     forkprocess = 0;
  1472.     hclear(pidstatus, FALSE);    /* we have no children */
  1473.     return Nullfp;
  1474. #undef THIS
  1475. #undef THAT
  1476.     }
  1477.     do_execfree();    /* free any memory malloced by child on vfork */
  1478.     close(p[that]);
  1479.     if (p[that] < p[this]) {
  1480.     dup2(p[this], p[that]);
  1481.     close(p[this]);
  1482.     p[this] = p[that];
  1483.     }
  1484.     str = afetch(fdpid,p[this],TRUE);
  1485.     str->str_u.str_useful = pid;
  1486.     forkprocess = pid;
  1487.     return fdopen(p[this], mode);
  1488. }
  1489. #else
  1490. #if defined(atarist) || defined(__EMX__)
  1491. FILE *popen();
  1492. FILE *
  1493. mypopen(cmd,mode)
  1494. char    *cmd;
  1495. char    *mode;
  1496. {
  1497.     return popen(cmd, mode);
  1498. }
  1499. #endif
  1500.  
  1501. #endif /* !DOSISH */
  1502.  
  1503. #ifdef NOTDEF
  1504. dumpfds(s)
  1505. char *s;
  1506. {
  1507.     int fd;
  1508.     struct stat tmpstatbuf;
  1509.  
  1510.     fprintf(stderr,"%s", s);
  1511.     for (fd = 0; fd < 32; fd++) {
  1512.     if (fstat(fd,&tmpstatbuf) >= 0)
  1513.         fprintf(stderr," %d",fd);
  1514.     }
  1515.     fprintf(stderr,"\n");
  1516. }
  1517. #endif
  1518.  
  1519. #ifndef HAS_DUP2
  1520. dup2(oldfd,newfd)
  1521. int oldfd;
  1522. int newfd;
  1523. {
  1524. #if defined(HAS_FCNTL) && defined(F_DUPFD)
  1525.     close(newfd);
  1526.     fcntl(oldfd, F_DUPFD, newfd);
  1527. #else
  1528.     int fdtmp[256];
  1529.     int fdx = 0;
  1530.     int fd;
  1531.  
  1532.     if (oldfd == newfd)
  1533.     return 0;
  1534.     close(newfd);
  1535.     while ((fd = dup(oldfd)) != newfd)    /* good enough for low fd's */
  1536.     fdtmp[fdx++] = fd;
  1537.     while (fdx > 0)
  1538.     close(fdtmp[--fdx]);
  1539. #endif
  1540. }
  1541. #endif
  1542.  
  1543. #ifndef DOSISH
  1544. int
  1545. mypclose(ptr)
  1546. FILE *ptr;
  1547. {
  1548. #ifdef VOIDSIG
  1549.     void (*hstat)(), (*istat)(), (*qstat)();
  1550. #else
  1551.     int (*hstat)(), (*istat)(), (*qstat)();
  1552. #endif
  1553.     int status;
  1554.     STR *str;
  1555.     int pid;
  1556.  
  1557.     str = afetch(fdpid,fileno(ptr),TRUE);
  1558.     pid = (int)str->str_u.str_useful;
  1559.     astore(fdpid,fileno(ptr),Nullstr);
  1560.     fclose(ptr);
  1561. #ifdef UTS
  1562.     if(kill(pid, 0) < 0) { return(pid); }   /* HOM 12/23/91 */
  1563. #endif
  1564.     hstat = signal(SIGHUP, SIG_IGN);
  1565.     istat = signal(SIGINT, SIG_IGN);
  1566.     qstat = signal(SIGQUIT, SIG_IGN);
  1567.     pid = wait4pid(pid, &status, 0);
  1568.     signal(SIGHUP, hstat);
  1569.     signal(SIGINT, istat);
  1570.     signal(SIGQUIT, qstat);
  1571.     return(pid < 0 ? pid : status);
  1572. }
  1573.  
  1574. int
  1575. wait4pid(pid,statusp,flags)
  1576. int pid;
  1577. int *statusp;
  1578. int flags;
  1579. {
  1580. #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
  1581.     int result;
  1582.     STR *str;
  1583.     char spid[16];
  1584. #endif
  1585.  
  1586.     if (!pid)
  1587.     return -1;
  1588. #ifdef HAS_WAIT4
  1589.     return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
  1590. #else
  1591. #ifdef HAS_WAITPID
  1592.     return waitpid(pid,statusp,flags);
  1593. #else
  1594.     if (pid > 0) {
  1595.     sprintf(spid, "%d", pid);
  1596.     str = hfetch(pidstatus,spid,strlen(spid),FALSE);
  1597.     if (str != &str_undef) {
  1598.         *statusp = (int)str->str_u.str_useful;
  1599.         hdelete(pidstatus,spid,strlen(spid));
  1600.         return pid;
  1601.     }
  1602.     }
  1603.     else {
  1604.     HENT *entry;
  1605.  
  1606.     hiterinit(pidstatus);
  1607.     if (entry = hiternext(pidstatus)) {
  1608.         pid = atoi(hiterkey(entry,statusp));
  1609.         str = hiterval(pidstatus,entry);
  1610.         *statusp = (int)str->str_u.str_useful;
  1611.         sprintf(spid, "%d", pid);
  1612.         hdelete(pidstatus,spid,strlen(spid));
  1613.         return pid;
  1614.     }
  1615.     }
  1616.     if (flags)
  1617.     fatal("Can't do waitpid with flags");
  1618.     else {
  1619.     while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
  1620.         pidgone(result,*statusp);
  1621.     if (result < 0)
  1622.         *statusp = -1;
  1623.     }
  1624.     return result;
  1625. #endif
  1626. #endif
  1627. }
  1628. #endif /* !DOSISH */
  1629.  
  1630. void
  1631. /*SUPPRESS 590*/
  1632. pidgone(pid,status)
  1633. int pid;
  1634. int status;
  1635. {
  1636. #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
  1637. #else
  1638.     register STR *str;
  1639.     char spid[16];
  1640.  
  1641.     sprintf(spid, "%d", pid);
  1642.     str = hfetch(pidstatus,spid,strlen(spid),TRUE);
  1643.     str->str_u.str_useful = status;
  1644. #endif
  1645.     return;
  1646. }
  1647.  
  1648. #if defined(atarist) || defined(__EMX__)
  1649. int pclose();
  1650. int
  1651. mypclose(ptr)
  1652. FILE *ptr;
  1653. {
  1654.     return pclose(ptr);
  1655. }
  1656. #endif
  1657.  
  1658. void
  1659. repeatcpy(to,from,len,count)
  1660. register char *to;
  1661. register char *from;
  1662. int len;
  1663. register int count;
  1664. {
  1665.     register int todo;
  1666.     register char *frombase = from;
  1667.  
  1668.     if (len == 1) {
  1669.     todo = *from;
  1670.     while (count-- > 0)
  1671.         *to++ = todo;
  1672.     return;
  1673.     }
  1674.     while (count-- > 0) {
  1675.     for (todo = len; todo > 0; todo--) {
  1676.         *to++ = *from++;
  1677.     }
  1678.     from = frombase;
  1679.     }
  1680. }
  1681.  
  1682. #ifndef CASTNEGFLOAT
  1683. unsigned long
  1684. castulong(f)
  1685. double f;
  1686. {
  1687.     long along;
  1688.  
  1689. #if CASTFLAGS & 2
  1690. #   define BIGDOUBLE 2147483648.0
  1691.     if (f >= BIGDOUBLE)
  1692.     return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
  1693. #endif
  1694.     if (f >= 0.0)
  1695.     return (unsigned long)f;
  1696.     along = (long)f;
  1697.     return (unsigned long)along;
  1698. }
  1699. #endif
  1700.  
  1701. #ifndef HAS_RENAME
  1702. int
  1703. same_dirent(a,b)
  1704. char *a;
  1705. char *b;
  1706. {
  1707.     char *fa = rindex(a,'/');
  1708.     char *fb = rindex(b,'/');
  1709.     struct stat tmpstatbuf1;
  1710.     struct stat tmpstatbuf2;
  1711. #ifndef MAXPATHLEN
  1712. #define MAXPATHLEN 1024
  1713. #endif
  1714.     char tmpbuf[MAXPATHLEN+1];
  1715.  
  1716.     if (fa)
  1717.     fa++;
  1718.     else
  1719.     fa = a;
  1720.     if (fb)
  1721.     fb++;
  1722.     else
  1723.     fb = b;
  1724.     if (strNE(a,b))
  1725.     return FALSE;
  1726.     if (fa == a)
  1727.     strcpy(tmpbuf,".");
  1728.     else
  1729.     strncpy(tmpbuf, a, fa - a);
  1730.     if (stat(tmpbuf, &tmpstatbuf1) < 0)
  1731.     return FALSE;
  1732.     if (fb == b)
  1733.     strcpy(tmpbuf,".");
  1734.     else
  1735.     strncpy(tmpbuf, b, fb - b);
  1736.     if (stat(tmpbuf, &tmpstatbuf2) < 0)
  1737.     return FALSE;
  1738.     return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
  1739.        tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
  1740. }
  1741. #endif /* !HAS_RENAME */
  1742.  
  1743. unsigned long
  1744. scanoct(start, len, retlen)
  1745. char *start;
  1746. int len;
  1747. int *retlen;
  1748. {
  1749.     register char *s = start;
  1750.     register unsigned long retval = 0;
  1751.  
  1752.     while (len-- && *s >= '0' && *s <= '7') {
  1753.     retval <<= 3;
  1754.     retval |= *s++ - '0';
  1755.     }
  1756.     *retlen = s - start;
  1757.     return retval;
  1758. }
  1759.  
  1760. unsigned long
  1761. scanhex(start, len, retlen)
  1762. char *start;
  1763. int len;
  1764. int *retlen;
  1765. {
  1766.     register char *s = start;
  1767.     register unsigned long retval = 0;
  1768.     char *tmp;
  1769.  
  1770.     while (len-- && *s && (tmp = index(hexdigit, *s))) {
  1771.     retval <<= 4;
  1772.     retval |= (tmp - hexdigit) & 15;
  1773.     s++;
  1774.     }
  1775.     *retlen = s - start;
  1776.     return retval;
  1777. }
  1778.