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