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