1 /* $RCSfile: util.c,v $$Revision: 4.0.1.4 $$Date: 91/11/11 16:48:54 $
3 * Copyright (c) 1991, Larry Wall
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.
9 * Revision 4.0.1.4 91/11/11 16:48:54 lwall
10 * patch19: study was busted by 4.018
11 * patch19: added little-endian pack/unpack options
13 * Revision 4.0.1.3 91/11/05 19:18:26 lwall
14 * patch11: safe malloc code now integrated into Perl's malloc when possible
15 * patch11: index("little", "longer string") could visit faraway places
16 * patch11: warn '-' x 10000 dumped core
17 * patch11: forked exec on non-existent program now issues a warning
19 * Revision 4.0.1.2 91/06/07 12:10:42 lwall
20 * patch4: new copyright notice
21 * patch4: made some allowances for "semi-standard" C
22 * patch4: index() could blow up searching for null string
23 * patch4: taintchecks could improperly modify parent in vfork()
24 * patch4: exec would close files even if you cleared close-on-exec flag
26 * Revision 4.0.1.1 91/04/12 09:19:25 lwall
27 * patch1: random cleanup in cpp namespace
29 * Revision 4.0 91/03/20 01:56:39 lwall
38 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
54 # include <sys/file.h>
61 static char nomem[] = "Out of memory!\n";
63 /* paranoid version of malloc */
69 /* NOTE: Do not call the next three routines directly. Use the macros
70 * in handy.h, so that we can easily redefine everything to do tracking of
71 * allocated hunks back to the original New to track down any memory leaks.
85 #endif /* ! STANDARD_C */
89 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
95 fatal("panic: malloc");
97 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
101 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
104 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
110 fputs(nomem,stderr) FLUSH;
119 /* paranoid version of realloc */
122 saferealloc(where,size)
133 #endif /* ! STANDARD_C */
137 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
142 fatal("Null realloc");
145 fatal("panic: realloc");
147 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
151 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
152 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
156 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
157 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
164 fputs(nomem,stderr) FLUSH;
173 /* safe version of free */
182 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
185 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
194 #endif /* !safemalloc */
198 #define ALIGN sizeof(long)
205 register char *where;
207 where = safemalloc(size + ALIGN);
211 return where + ALIGN;
215 safexrealloc(where,size)
219 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
231 x = where[0] + 100 * where[1];
240 for (i = 0; i < MAXXCOUNT; i++) {
241 if (xcount[i] > lastxcount[i]) {
242 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
243 lastxcount[i] = xcount[i];
248 #endif /* LEAKTEST */
250 /* copy a string up to some (non-backslashed) delimiter, if any */
253 cpytill(to,from,fromend,delim,retlen)
256 register char *fromend;
262 for (; from < fromend; from++,to++) {
264 if (from[1] == delim)
266 else if (from[1] == '\\')
269 else if (*from == delim)
274 *retlen = to - origto;
278 /* return ptr to little string in big string, NULL if not found */
279 /* This routine was donated by Corey Satten. */
284 register char *little;
286 register char *s, *x;
297 for (x=big,s=little; *s; /**/ ) {
311 /* same as instr but allow embedded nulls */
314 ninstr(big, bigend, little, lend)
316 register char *bigend;
320 register char *s, *x;
321 register int first = *little;
322 register char *littleend = lend;
324 if (!first && little > littleend)
326 if (bigend - big < littleend - little)
328 bigend -= littleend - little++;
329 while (big <= bigend) {
332 for (x=big,s=little; s < littleend; /**/ ) {
344 /* reverse of the above--find last substring */
347 rninstr(big, bigend, little, lend)
353 register char *bigbeg;
354 register char *s, *x;
355 register int first = *little;
356 register char *littleend = lend;
358 if (!first && little > littleend)
361 big = bigend - (littleend - little++);
362 while (big >= bigbeg) {
365 for (x=big+2,s=little; s < littleend; /**/ ) {
377 unsigned char fold[] = {
378 0, 1, 2, 3, 4, 5, 6, 7,
379 8, 9, 10, 11, 12, 13, 14, 15,
380 16, 17, 18, 19, 20, 21, 22, 23,
381 24, 25, 26, 27, 28, 29, 30, 31,
382 32, 33, 34, 35, 36, 37, 38, 39,
383 40, 41, 42, 43, 44, 45, 46, 47,
384 48, 49, 50, 51, 52, 53, 54, 55,
385 56, 57, 58, 59, 60, 61, 62, 63,
386 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
387 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
388 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
389 'x', 'y', 'z', 91, 92, 93, 94, 95,
390 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
391 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
392 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
393 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
394 128, 129, 130, 131, 132, 133, 134, 135,
395 136, 137, 138, 139, 140, 141, 142, 143,
396 144, 145, 146, 147, 148, 149, 150, 151,
397 152, 153, 154, 155, 156, 157, 158, 159,
398 160, 161, 162, 163, 164, 165, 166, 167,
399 168, 169, 170, 171, 172, 173, 174, 175,
400 176, 177, 178, 179, 180, 181, 182, 183,
401 184, 185, 186, 187, 188, 189, 190, 191,
402 192, 193, 194, 195, 196, 197, 198, 199,
403 200, 201, 202, 203, 204, 205, 206, 207,
404 208, 209, 210, 211, 212, 213, 214, 215,
405 216, 217, 218, 219, 220, 221, 222, 223,
406 224, 225, 226, 227, 228, 229, 230, 231,
407 232, 233, 234, 235, 236, 237, 238, 239,
408 240, 241, 242, 243, 244, 245, 246, 247,
409 248, 249, 250, 251, 252, 253, 254, 255
412 static unsigned char freq[] = {
413 1, 2, 84, 151, 154, 155, 156, 157,
414 165, 246, 250, 3, 158, 7, 18, 29,
415 40, 51, 62, 73, 85, 96, 107, 118,
416 129, 140, 147, 148, 149, 150, 152, 153,
417 255, 182, 224, 205, 174, 176, 180, 217,
418 233, 232, 236, 187, 235, 228, 234, 226,
419 222, 219, 211, 195, 188, 193, 185, 184,
420 191, 183, 201, 229, 181, 220, 194, 162,
421 163, 208, 186, 202, 200, 218, 198, 179,
422 178, 214, 166, 170, 207, 199, 209, 206,
423 204, 160, 212, 216, 215, 192, 175, 173,
424 243, 172, 161, 190, 203, 189, 164, 230,
425 167, 248, 227, 244, 242, 255, 241, 231,
426 240, 253, 169, 210, 245, 237, 249, 247,
427 239, 168, 252, 251, 254, 238, 223, 221,
428 213, 225, 177, 197, 171, 196, 159, 4,
429 5, 6, 8, 9, 10, 11, 12, 13,
430 14, 15, 16, 17, 19, 20, 21, 22,
431 23, 24, 25, 26, 27, 28, 30, 31,
432 32, 33, 34, 35, 36, 37, 38, 39,
433 41, 42, 43, 44, 45, 46, 47, 48,
434 49, 50, 52, 53, 54, 55, 56, 57,
435 58, 59, 60, 61, 63, 64, 65, 66,
436 67, 68, 69, 70, 71, 72, 74, 75,
437 76, 77, 78, 79, 80, 81, 82, 83,
438 86, 87, 88, 89, 90, 91, 92, 93,
439 94, 95, 97, 98, 99, 100, 101, 102,
440 103, 104, 105, 106, 108, 109, 110, 111,
441 112, 113, 114, 115, 116, 117, 119, 120,
442 121, 122, 123, 124, 125, 126, 127, 128,
443 130, 131, 132, 133, 134, 135, 136, 137,
444 138, 139, 141, 142, 143, 144, 145, 146
448 fbmcompile(str, iflag)
452 register unsigned char *s;
453 register unsigned char *table;
454 register unsigned int i;
455 register unsigned int len = str->str_cur;
457 unsigned int frequency = 256;
459 Str_Grow(str,len+258);
461 table = (unsigned char*)(str->str_ptr + len + 1);
463 table = Null(unsigned char*);
466 for (i = 0; i < 256; i++) {
471 while (s >= (unsigned char*)(str->str_ptr))
474 if (table[*s] == len) {
477 table[*s] = table[fold[*s]] = i;
491 str->str_pok |= SP_FBM; /* deep magic */
494 s = (unsigned char*)(str->str_ptr); /* deeper magic */
496 s = Null(unsigned char*);
499 register unsigned int tmp, foldtmp;
500 str->str_pok |= SP_CASEFOLD;
501 for (i = 0; i < len; i++) {
503 foldtmp=freq[fold[s[i]]];
504 if (tmp < frequency && foldtmp < frequency) {
506 /* choose most frequent among the two */
507 frequency = (tmp > foldtmp) ? tmp : foldtmp;
512 for (i = 0; i < len; i++) {
513 if (freq[s[i]] < frequency) {
515 frequency = freq[s[i]];
519 str->str_rare = s[rarest];
520 str->str_state = rarest;
523 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
528 fbminstr(big, bigend, littlestr)
530 register unsigned char *bigend;
533 register unsigned char *s;
535 register int littlelen;
536 register unsigned char *little;
537 register unsigned char *table;
538 register unsigned char *olds;
539 register unsigned char *oldlittle;
542 if (!(littlestr->str_pok & SP_FBM)) {
543 if (!littlestr->str_ptr)
545 return ninstr((char*)big,(char*)bigend,
546 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
550 littlelen = littlestr->str_cur;
552 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
553 if (littlelen > bigend - big)
555 little = (unsigned char*)littlestr->str_ptr;
556 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
557 big = bigend - littlelen; /* just start near end */
558 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
562 s = bigend - littlelen;
563 if (*s == *little && bcmp(s,little,littlelen)==0)
564 return (char*)s; /* how sweet it is */
565 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
568 if (*s == *little && bcmp(s,little,littlelen)==0)
574 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
576 table = Null(unsigned char*);
578 if (--littlelen >= bigend - big)
581 oldlittle = little = table - 2;
582 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
586 if (tmp = table[*s]) {
588 if (bigend - s > tmp) {
593 if ((s += tmp) < bigend)
599 tmp = littlelen; /* less expensive than calling strncmp() */
602 if (*--s == *--little || fold[*s] == *little)
604 s = olds + 1; /* here we pay the price for failure */
606 if (s < bigend) /* fake up continue to outer loop */
620 if (tmp = table[*s]) {
622 if (bigend - s > tmp) {
627 if ((s += tmp) < bigend)
633 tmp = littlelen; /* less expensive than calling strncmp() */
636 if (*--s == *--little)
638 s = olds + 1; /* here we pay the price for failure */
640 if (s < bigend) /* fake up continue to outer loop */
654 screaminstr(bigstr, littlestr)
658 register unsigned char *s, *x;
659 register unsigned char *big;
661 register int previous;
663 register unsigned char *little;
664 register unsigned char *bigend;
665 register unsigned char *littleend;
667 if ((pos = screamfirst[littlestr->str_rare]) < 0)
670 little = (unsigned char *)(littlestr->str_ptr);
672 little = Null(unsigned char *);
674 littleend = little + littlestr->str_cur;
676 previous = littlestr->str_state;
678 big = (unsigned char *)(bigstr->str_ptr);
680 big = Null(unsigned char*);
682 bigend = big + bigstr->str_cur;
683 while (pos < previous) {
685 if (!(pos += screamnext[pos]))
690 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
692 if (big[pos-previous] != first && big[pos-previous] != fold[first])
694 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
697 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
704 return (char *)(big+pos-previous);
710 pos += screamnext[pos] /* does this goof up anywhere? */
718 if (big[pos-previous] != first)
720 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
730 return (char *)(big+pos-previous);
736 pos += screamnext[pos]
742 #else /* !POINTERRIGOR */
744 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
746 if (big[pos] != first && big[pos] != fold[first])
748 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
751 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
758 return (char *)(big+pos);
764 pos += screamnext[pos] /* does this goof up anywhere? */
772 if (big[pos] != first)
774 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
784 return (char *)(big+pos);
790 pos += screamnext[pos]
796 #endif /* POINTERRIGOR */
800 /* copy a string to a safe spot */
806 register char *newaddr;
808 New(902,newaddr,strlen(str)+1,char);
809 (void)strcpy(newaddr,str);
813 /* same thing but with a known length */
820 register char *newaddr;
822 New(903,newaddr,len+1,char);
823 (void)bcopy(str,newaddr,len); /* might not be null terminated */
824 newaddr[len] = '\0'; /* is now */
828 /* grow a static string to at least a certain length */
831 growstr(strptr,curlen,newlen)
836 if (newlen > *curlen) { /* need more room? */
838 Renew(*strptr,newlen,char);
840 New(905,*strptr,newlen,char);
847 mess(pat,a1,a2,a3,a4)
852 int usermess = strEQ(pat,"%s");
857 tmpstr = str_mortal(&str_undef);
858 str_set(tmpstr, (char*)a1);
859 *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
862 (void)sprintf(s,pat,a1,a2,a3,a4);
867 if (curcmd->c_line) {
868 (void)sprintf(s," at %s line %ld",
869 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
873 stab_io(last_in_stab) &&
874 stab_io(last_in_stab)->lines ) {
875 (void)sprintf(s,", <%s> line %ld",
876 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
877 (long)stab_io(last_in_stab)->lines);
880 (void)strcpy(s,".\n");
882 str_cat(tmpstr,buf+1);
885 return tmpstr->str_ptr;
891 fatal(pat,a1,a2,a3,a4)
896 extern char *e_tmpname;
900 message = mess(pat,a1,a2,a3,a4);
902 str_set(stab_val(stabent("@",TRUE)),message);
904 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
905 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
908 deb("(Skipping label #%d %s)\n",loop_ptr,
909 loop_stack[loop_ptr].loop_label);
916 deb("(Found label #%d %s)\n",loop_ptr,
917 loop_stack[loop_ptr].loop_label);
922 fatal("Bad label: %s", tmps);
924 longjmp(loop_stack[loop_ptr].loop_env, 1);
926 fputs(message,stderr);
927 (void)fflush(stderr);
929 (void)UNLINK(e_tmpname);
931 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
935 warn(pat,a1,a2,a3,a4)
941 message = mess(pat,a1,a2,a3,a4);
942 fputs(message,stderr);
949 (void)fflush(stderr);
972 pat = va_arg(args, char *);
975 usermess = strEQ(pat, "%s");
977 tmpstr = str_mortal(&str_undef);
978 str_set(tmpstr, va_arg(args, char *));
979 *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
982 (void) vsprintf(s,pat,args);
987 if (curcmd->c_line) {
988 (void)sprintf(s," at %s line %ld",
989 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
993 stab_io(last_in_stab) &&
994 stab_io(last_in_stab)->lines ) {
995 (void)sprintf(s,", <%s> line %ld",
996 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
997 (long)stab_io(last_in_stab)->lines);
1000 (void)strcpy(s,".\n");
1002 str_cat(tmpstr,buf+1);
1006 return tmpstr->str_ptr;
1017 extern char *e_tmpname;
1026 message = mess(args);
1029 str_set(stab_val(stabent("@",TRUE)),message);
1031 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
1032 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
1035 deb("(Skipping label #%d %s)\n",loop_ptr,
1036 loop_stack[loop_ptr].loop_label);
1043 deb("(Found label #%d %s)\n",loop_ptr,
1044 loop_stack[loop_ptr].loop_label);
1049 fatal("Bad label: %s", tmps);
1051 longjmp(loop_stack[loop_ptr].loop_env, 1);
1053 fputs(message,stderr);
1054 (void)fflush(stderr);
1056 (void)UNLINK(e_tmpname);
1058 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
1073 message = mess(args);
1076 fputs(message,stderr);
1083 (void)fflush(stderr);
1091 register int i=envix(nam); /* where does it go? */
1093 if (environ == origenviron) { /* need we copy environment? */
1099 for (max = i; environ[max]; max++) ;
1100 New(901,tmpenv, max+2, char*);
1101 for (j=0; j<max; j++) /* copy environment */
1102 tmpenv[j] = savestr(environ[j]);
1103 tmpenv[max] = Nullch;
1104 environ = tmpenv; /* tell exec where it is now */
1107 while (environ[i]) {
1108 environ[i] = environ[i+1];
1113 if (!environ[i]) { /* does not exist yet */
1114 Renew(environ, i+2, char*); /* just expand it a bit */
1115 environ[i+1] = Nullch; /* make sure it's null terminated */
1118 Safefree(environ[i]);
1119 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
1121 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
1123 /* MS-DOS requires environment variable names to be in uppercase */
1124 /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
1125 * some utilities and applications may break because they only look
1126 * for upper case strings. (Fixed strupr() bug here.)]
1128 strcpy(environ[i],nam); strupr(environ[i]);
1129 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
1137 register int i, len = strlen(nam);
1139 for (i = 0; environ[i]; i++) {
1140 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
1141 break; /* strnEQ must come first to avoid */
1142 } /* potential SEGV's */
1147 unlnk(f) /* unlink all versions of a file */
1152 for (i = 0; unlink(f) >= 0; i++) ;
1161 register char *from;
1196 vsprintf(dest, pat, args)
1197 char *dest, *pat, *args;
1201 fakebuf._ptr = dest;
1202 fakebuf._cnt = 32767;
1206 fakebuf._flag = _IOWRT|_IOSTRG;
1207 _doprnt(pat, args, &fakebuf); /* what a kludge */
1208 (void)putc('\0', &fakebuf);
1212 return 0; /* perl doesn't use return value */
1218 vfprintf(fd, pat, args)
1222 _doprnt(pat, args, fd);
1223 return 0; /* wrong, but perl doesn't use the return value */
1226 #endif /* HAS_VPRINTF */
1227 #endif /* I_VARARGS */
1230 * I think my_swap(), htonl() and ntohl() have never been used.
1231 * perl.h contains last-chance references to my_swap(), my_htonl()
1232 * and my_ntohl(). I presume these are the intended functions;
1233 * but htonl() and ntohl() have the wrong names. There are no
1234 * functions my_htonl() and my_ntohl() defined anywhere.
1238 #if BYTEORDER != 0x4321
1243 #if (BYTEORDER & 1) == 0
1246 result = ((s & 255) << 8) + ((s >> 8) & 255);
1259 char c[sizeof(long)];
1262 #if BYTEORDER == 0x1234
1263 u.c[0] = (l >> 24) & 255;
1264 u.c[1] = (l >> 16) & 255;
1265 u.c[2] = (l >> 8) & 255;
1269 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1270 fatal("Unknown BYTEORDER\n");
1275 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1276 u.c[o & 0xf] = (l >> s) & 255;
1289 char c[sizeof(long)];
1292 #if BYTEORDER == 0x1234
1293 u.c[0] = (l >> 24) & 255;
1294 u.c[1] = (l >> 16) & 255;
1295 u.c[2] = (l >> 8) & 255;
1299 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1300 fatal("Unknown BYTEORDER\n");
1307 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1308 l |= (u.c[o & 0xf] & 255) << s;
1315 #endif /* BYTEORDER != 0x4321 */
1319 * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
1320 * If these functions are defined,
1321 * the BYTEORDER is neither 0x1234 nor 0x4321.
1322 * However, this is not assumed.
1326 #define HTOV(name,type) \
1333 char c[sizeof(type)]; \
1337 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1338 u.c[i] = (n >> s) & 0xFF; \
1343 #define VTOH(name,type) \
1350 char c[sizeof(type)]; \
1356 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1357 n += (u.c[i] & 0xFF) << s; \
1362 #if defined(HAS_HTOVS) && !defined(htovs)
1365 #if defined(HAS_HTOVL) && !defined(htovl)
1368 #if defined(HAS_VTOHS) && !defined(vtohs)
1371 #if defined(HAS_VTOHL) && !defined(vtohl)
1382 register int this, that;
1385 int doexec = strNE(cmd,"-");
1389 this = (*mode == 'w');
1394 taintproper("Insecure dependency in exec");
1397 while ((pid = (doexec?vfork():fork())) < 0) {
1398 if (errno != EAGAIN) {
1401 fatal("Can't fork");
1410 if (p[THIS] != (*mode == 'r')) {
1411 dup2(p[THIS], *mode == 'r');
1415 #if !defined(HAS_FCNTL) || !defined(F_SETFD)
1421 for (fd = maxsysfd + 1; fd < NOFILE; fd++)
1424 do_exec(cmd); /* may or may not use the shell */
1425 warn("Can't exec \"%s\": %s", cmd, strerror(errno));
1429 if (tmpstab = stabent("$",allstabs))
1430 str_numset(STAB_STR(tmpstab),(double)getpid());
1432 hclear(pidstatus, FALSE); /* we have no children */
1437 do_execfree(); /* free any memory malloced by child on vfork */
1439 if (p[that] < p[this]) {
1440 dup2(p[this], p[that]);
1444 str = afetch(fdpid,p[this],TRUE);
1445 str->str_u.str_useful = pid;
1447 return fdopen(p[this], mode);
1456 struct stat tmpstatbuf;
1458 fprintf(stderr,"%s", s);
1459 for (fd = 0; fd < 32; fd++) {
1460 if (fstat(fd,&tmpstatbuf) >= 0)
1461 fprintf(stderr," %d",fd);
1463 fprintf(stderr,"\n");
1472 #if defined(HAS_FCNTL) && defined(F_DUPFD)
1474 fcntl(oldfd, F_DUPFD, newfd);
1483 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1486 close(fdtmp[--fdx]);
1497 void (*hstat)(), (*istat)(), (*qstat)();
1499 int (*hstat)(), (*istat)(), (*qstat)();
1505 str = afetch(fdpid,fileno(ptr),TRUE);
1506 pid = (int)str->str_u.str_useful;
1507 astore(fdpid,fileno(ptr),Nullstr);
1509 hstat = signal(SIGHUP, SIG_IGN);
1510 istat = signal(SIGINT, SIG_IGN);
1511 qstat = signal(SIGQUIT, SIG_IGN);
1512 pid = wait4pid(pid, &status, 0);
1513 signal(SIGHUP, hstat);
1514 signal(SIGINT, istat);
1515 signal(SIGQUIT, qstat);
1516 return(pid < 0 ? pid : status);
1520 wait4pid(pid,statusp,flags)
1525 #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
1534 return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
1537 return waitpid(pid,statusp,flags);
1540 sprintf(spid, "%d", pid);
1541 str = hfetch(pidstatus,spid,strlen(spid),FALSE);
1542 if (str != &str_undef) {
1543 *statusp = (int)str->str_u.str_useful;
1544 hdelete(pidstatus,spid,strlen(spid));
1551 hiterinit(pidstatus);
1552 if (entry = hiternext(pidstatus)) {
1553 pid = atoi(hiterkey(entry,statusp));
1554 str = hiterval(entry);
1555 *statusp = (int)str->str_u.str_useful;
1556 sprintf(spid, "%d", pid);
1557 hdelete(pidstatus,spid,strlen(spid));
1562 fatal("Can't do waitpid with flags");
1564 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1565 pidgone(result,*statusp);
1579 #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
1584 sprintf(spid, "%d", pid);
1585 str = hfetch(pidstatus,spid,strlen(spid),TRUE);
1586 str->str_u.str_useful = status;
1594 register unsigned char *s1;
1595 register unsigned char *s2;
1601 if (tmp = *s1++ - *s2++)
1606 #endif /* HAS_MEMCMP */
1609 repeatcpy(to,from,len,count)
1611 register char *from;
1616 register char *frombase = from;
1624 while (count-- > 0) {
1625 for (todo = len; todo > 0; todo--) {
1632 #ifndef CASTNEGFLOAT
1640 # define BIGDOUBLE 2147483648.0
1642 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1645 return (unsigned long)f;
1647 return (unsigned long)along;
1657 char *fa = rindex(a,'/');
1658 char *fb = rindex(b,'/');
1659 struct stat tmpstatbuf1;
1660 struct stat tmpstatbuf2;
1662 #define MAXPATHLEN 1024
1664 char tmpbuf[MAXPATHLEN+1];
1679 strncpy(tmpbuf, a, fa - a);
1680 if (stat(tmpbuf, &tmpstatbuf1) < 0)
1685 strncpy(tmpbuf, b, fb - b);
1686 if (stat(tmpbuf, &tmpstatbuf2) < 0)
1688 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1689 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1691 #endif /* !HAS_RENAME */
1694 scanoct(start, len, retlen)
1699 register char *s = start;
1700 register unsigned long retval = 0;
1702 while (len-- && *s >= '0' && *s <= '7') {
1704 retval |= *s++ - '0';
1706 *retlen = s - start;
1711 scanhex(start, len, retlen)
1716 register char *s = start;
1717 register unsigned long retval = 0;
1720 while (len-- && *s && (tmp = index(hexdigit, *s))) {
1722 retval |= (tmp - hexdigit) & 15;
1725 *retlen = s - start;