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