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