1 /* $RCSfile: util.c,v $$Revision: 4.0.1.3 $$Date: 91/11/05 19:18:26 $
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.3 91/11/05 19:18:26 lwall
10 * patch11: safe malloc code now integrated into Perl's malloc when possible
11 * patch11: index("little", "longer string") could visit faraway places
12 * patch11: warn '-' x 10000 dumped core
13 * patch11: forked exec on non-existent program now issues a warning
15 * Revision 4.0.1.2 91/06/07 12:10:42 lwall
16 * patch4: new copyright notice
17 * patch4: made some allowances for "semi-standard" C
18 * patch4: index() could blow up searching for null string
19 * patch4: taintchecks could improperly modify parent in vfork()
20 * patch4: exec would close files even if you cleared close-on-exec flag
22 * Revision 4.0.1.1 91/04/12 09:19:25 lwall
23 * patch1: random cleanup in cpp namespace
25 * Revision 4.0 91/03/20 01:56:39 lwall
34 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
50 # include <sys/file.h>
57 static char nomem[] = "Out of memory!\n";
59 /* paranoid version of malloc */
65 /* NOTE: Do not call the next three routines directly. Use the macros
66 * in handy.h, so that we can easily redefine everything to do tracking of
67 * allocated hunks back to the original New to track down any memory leaks.
81 #endif /* ! STANDARD_C */
85 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
91 fatal("panic: malloc");
93 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
97 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
100 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
106 fputs(nomem,stderr) FLUSH;
115 /* paranoid version of realloc */
118 saferealloc(where,size)
129 #endif /* ! STANDARD_C */
133 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
138 fatal("Null realloc");
141 fatal("panic: realloc");
143 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
147 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
148 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
152 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
153 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
160 fputs(nomem,stderr) FLUSH;
169 /* safe version of free */
178 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
181 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
190 #endif /* !safemalloc */
194 #define ALIGN sizeof(long)
201 register char *where;
203 where = safemalloc(size + ALIGN);
207 return where + ALIGN;
211 safexrealloc(where,size)
215 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
227 x = where[0] + 100 * where[1];
236 for (i = 0; i < MAXXCOUNT; i++) {
237 if (xcount[i] > lastxcount[i]) {
238 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
239 lastxcount[i] = xcount[i];
244 #endif /* LEAKTEST */
246 /* copy a string up to some (non-backslashed) delimiter, if any */
249 cpytill(to,from,fromend,delim,retlen)
252 register char *fromend;
258 for (; from < fromend; from++,to++) {
260 if (from[1] == delim)
262 else if (from[1] == '\\')
265 else if (*from == delim)
270 *retlen = to - origto;
274 /* return ptr to little string in big string, NULL if not found */
275 /* This routine was donated by Corey Satten. */
280 register char *little;
282 register char *s, *x;
293 for (x=big,s=little; *s; /**/ ) {
307 /* same as instr but allow embedded nulls */
310 ninstr(big, bigend, little, lend)
312 register char *bigend;
316 register char *s, *x;
317 register int first = *little;
318 register char *littleend = lend;
320 if (!first && little > littleend)
322 if (bigend - big < littleend - little)
324 bigend -= littleend - little++;
325 while (big <= bigend) {
328 for (x=big,s=little; s < littleend; /**/ ) {
340 /* reverse of the above--find last substring */
343 rninstr(big, bigend, little, lend)
349 register char *bigbeg;
350 register char *s, *x;
351 register int first = *little;
352 register char *littleend = lend;
354 if (!first && little > littleend)
357 big = bigend - (littleend - little++);
358 while (big >= bigbeg) {
361 for (x=big+2,s=little; s < littleend; /**/ ) {
373 unsigned char fold[] = {
374 0, 1, 2, 3, 4, 5, 6, 7,
375 8, 9, 10, 11, 12, 13, 14, 15,
376 16, 17, 18, 19, 20, 21, 22, 23,
377 24, 25, 26, 27, 28, 29, 30, 31,
378 32, 33, 34, 35, 36, 37, 38, 39,
379 40, 41, 42, 43, 44, 45, 46, 47,
380 48, 49, 50, 51, 52, 53, 54, 55,
381 56, 57, 58, 59, 60, 61, 62, 63,
382 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
383 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
384 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
385 'x', 'y', 'z', 91, 92, 93, 94, 95,
386 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
387 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
388 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
389 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
390 128, 129, 130, 131, 132, 133, 134, 135,
391 136, 137, 138, 139, 140, 141, 142, 143,
392 144, 145, 146, 147, 148, 149, 150, 151,
393 152, 153, 154, 155, 156, 157, 158, 159,
394 160, 161, 162, 163, 164, 165, 166, 167,
395 168, 169, 170, 171, 172, 173, 174, 175,
396 176, 177, 178, 179, 180, 181, 182, 183,
397 184, 185, 186, 187, 188, 189, 190, 191,
398 192, 193, 194, 195, 196, 197, 198, 199,
399 200, 201, 202, 203, 204, 205, 206, 207,
400 208, 209, 210, 211, 212, 213, 214, 215,
401 216, 217, 218, 219, 220, 221, 222, 223,
402 224, 225, 226, 227, 228, 229, 230, 231,
403 232, 233, 234, 235, 236, 237, 238, 239,
404 240, 241, 242, 243, 244, 245, 246, 247,
405 248, 249, 250, 251, 252, 253, 254, 255
408 static unsigned char freq[] = {
409 1, 2, 84, 151, 154, 155, 156, 157,
410 165, 246, 250, 3, 158, 7, 18, 29,
411 40, 51, 62, 73, 85, 96, 107, 118,
412 129, 140, 147, 148, 149, 150, 152, 153,
413 255, 182, 224, 205, 174, 176, 180, 217,
414 233, 232, 236, 187, 235, 228, 234, 226,
415 222, 219, 211, 195, 188, 193, 185, 184,
416 191, 183, 201, 229, 181, 220, 194, 162,
417 163, 208, 186, 202, 200, 218, 198, 179,
418 178, 214, 166, 170, 207, 199, 209, 206,
419 204, 160, 212, 216, 215, 192, 175, 173,
420 243, 172, 161, 190, 203, 189, 164, 230,
421 167, 248, 227, 244, 242, 255, 241, 231,
422 240, 253, 169, 210, 245, 237, 249, 247,
423 239, 168, 252, 251, 254, 238, 223, 221,
424 213, 225, 177, 197, 171, 196, 159, 4,
425 5, 6, 8, 9, 10, 11, 12, 13,
426 14, 15, 16, 17, 19, 20, 21, 22,
427 23, 24, 25, 26, 27, 28, 30, 31,
428 32, 33, 34, 35, 36, 37, 38, 39,
429 41, 42, 43, 44, 45, 46, 47, 48,
430 49, 50, 52, 53, 54, 55, 56, 57,
431 58, 59, 60, 61, 63, 64, 65, 66,
432 67, 68, 69, 70, 71, 72, 74, 75,
433 76, 77, 78, 79, 80, 81, 82, 83,
434 86, 87, 88, 89, 90, 91, 92, 93,
435 94, 95, 97, 98, 99, 100, 101, 102,
436 103, 104, 105, 106, 108, 109, 110, 111,
437 112, 113, 114, 115, 116, 117, 119, 120,
438 121, 122, 123, 124, 125, 126, 127, 128,
439 130, 131, 132, 133, 134, 135, 136, 137,
440 138, 139, 141, 142, 143, 144, 145, 146
444 fbmcompile(str, iflag)
448 register unsigned char *s;
449 register unsigned char *table;
450 register unsigned int i;
451 register unsigned int len = str->str_cur;
453 unsigned int frequency = 256;
455 Str_Grow(str,len+258);
457 table = (unsigned char*)(str->str_ptr + len + 1);
459 table = Null(unsigned char*);
462 for (i = 0; i < 256; i++) {
467 while (s >= (unsigned char*)(str->str_ptr))
470 if (table[*s] == len) {
473 table[*s] = table[fold[*s]] = i;
487 str->str_pok |= SP_FBM; /* deep magic */
490 s = (unsigned char*)(str->str_ptr); /* deeper magic */
492 s = Null(unsigned char*);
495 register unsigned int tmp, foldtmp;
496 str->str_pok |= SP_CASEFOLD;
497 for (i = 0; i < len; i++) {
499 foldtmp=freq[fold[s[i]]];
500 if (tmp < frequency && foldtmp < frequency) {
502 /* choose most frequent among the two */
503 frequency = (tmp > foldtmp) ? tmp : foldtmp;
508 for (i = 0; i < len; i++) {
509 if (freq[s[i]] < frequency) {
511 frequency = freq[s[i]];
515 str->str_rare = s[rarest];
516 str->str_state = rarest;
519 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
524 fbminstr(big, bigend, littlestr)
526 register unsigned char *bigend;
529 register unsigned char *s;
531 register int littlelen;
532 register unsigned char *little;
533 register unsigned char *table;
534 register unsigned char *olds;
535 register unsigned char *oldlittle;
538 if (!(littlestr->str_pok & SP_FBM)) {
539 if (!littlestr->str_ptr)
541 return ninstr((char*)big,(char*)bigend,
542 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
546 littlelen = littlestr->str_cur;
548 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
549 if (littlelen > bigend - big)
551 little = (unsigned char*)littlestr->str_ptr;
552 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
553 big = bigend - littlelen; /* just start near end */
554 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
558 s = bigend - littlelen;
559 if (*s == *little && bcmp(s,little,littlelen)==0)
560 return (char*)s; /* how sweet it is */
561 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
564 if (*s == *little && bcmp(s,little,littlelen)==0)
570 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
572 table = Null(unsigned char*);
574 if (--littlelen >= bigend - big)
577 oldlittle = little = table - 2;
578 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
582 if (tmp = table[*s]) {
584 if (bigend - s > tmp) {
589 if ((s += tmp) < bigend)
595 tmp = littlelen; /* less expensive than calling strncmp() */
598 if (*--s == *--little || fold[*s] == *little)
600 s = olds + 1; /* here we pay the price for failure */
602 if (s < bigend) /* fake up continue to outer loop */
616 if (tmp = table[*s]) {
618 if (bigend - s > tmp) {
623 if ((s += tmp) < bigend)
629 tmp = littlelen; /* less expensive than calling strncmp() */
632 if (*--s == *--little)
634 s = olds + 1; /* here we pay the price for failure */
636 if (s < bigend) /* fake up continue to outer loop */
650 screaminstr(bigstr, littlestr)
654 register unsigned char *s, *x;
655 register unsigned char *big;
657 register int previous;
659 register unsigned char *little;
660 register unsigned char *bigend;
661 register unsigned char *littleend;
663 if ((pos = screamfirst[littlestr->str_rare]) < 0)
666 little = (unsigned char *)(littlestr->str_ptr);
668 little = Null(unsigned char *);
670 littleend = little + littlestr->str_cur;
672 previous = littlestr->str_state;
674 big = (unsigned char *)(bigstr->str_ptr);
676 big = Null(unsigned char*);
678 bigend = big + bigstr->str_cur;
679 while (pos < previous) {
681 if (!(pos += screamnext[pos]))
686 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
689 while (big[pos-previous] != first && big[pos-previous] != fold[first]
690 && (pos += screamnext[pos]) )
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? */
719 while (big[pos-previous] != first && (pos += screamnext[pos]))
723 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
733 return (char *)(big+pos-previous);
739 pos += screamnext[pos]
745 #else /* !POINTERRIGOR */
747 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
750 while (big[pos] != first && big[pos] != fold[first]
751 && (pos += screamnext[pos]) )
755 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
758 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
765 return (char *)(big+pos);
771 pos += screamnext[pos] /* does this goof up anywhere? */
780 while (big[pos] != first && (pos += screamnext[pos]))
784 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
794 return (char *)(big+pos);
800 pos += screamnext[pos]
806 #endif /* POINTERRIGOR */
810 /* copy a string to a safe spot */
816 register char *newaddr;
818 New(902,newaddr,strlen(str)+1,char);
819 (void)strcpy(newaddr,str);
823 /* same thing but with a known length */
830 register char *newaddr;
832 New(903,newaddr,len+1,char);
833 (void)bcopy(str,newaddr,len); /* might not be null terminated */
834 newaddr[len] = '\0'; /* is now */
838 /* grow a static string to at least a certain length */
841 growstr(strptr,curlen,newlen)
846 if (newlen > *curlen) { /* need more room? */
848 Renew(*strptr,newlen,char);
850 New(905,*strptr,newlen,char);
857 mess(pat,a1,a2,a3,a4)
862 int usermess = strEQ(pat,"%s");
867 tmpstr = str_mortal(&str_undef);
868 str_set(tmpstr, (char*)a1);
869 *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
872 (void)sprintf(s,pat,a1,a2,a3,a4);
877 if (curcmd->c_line) {
878 (void)sprintf(s," at %s line %ld",
879 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
883 stab_io(last_in_stab) &&
884 stab_io(last_in_stab)->lines ) {
885 (void)sprintf(s,", <%s> line %ld",
886 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
887 (long)stab_io(last_in_stab)->lines);
890 (void)strcpy(s,".\n");
892 str_cat(tmpstr,buf+1);
895 return tmpstr->str_ptr;
901 fatal(pat,a1,a2,a3,a4)
906 extern char *e_tmpname;
910 message = mess(pat,a1,a2,a3,a4);
912 str_set(stab_val(stabent("@",TRUE)),message);
914 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
915 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
918 deb("(Skipping label #%d %s)\n",loop_ptr,
919 loop_stack[loop_ptr].loop_label);
926 deb("(Found label #%d %s)\n",loop_ptr,
927 loop_stack[loop_ptr].loop_label);
932 fatal("Bad label: %s", tmps);
934 longjmp(loop_stack[loop_ptr].loop_env, 1);
936 fputs(message,stderr);
937 (void)fflush(stderr);
939 (void)UNLINK(e_tmpname);
941 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
945 warn(pat,a1,a2,a3,a4)
951 message = mess(pat,a1,a2,a3,a4);
952 fputs(message,stderr);
959 (void)fflush(stderr);
982 pat = va_arg(args, char *);
985 usermess = strEQ(pat, "%s");
987 tmpstr = str_mortal(&str_undef);
988 str_set(tmpstr, va_arg(args, char *));
989 *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
992 (void) vsprintf(s,pat,args);
997 if (curcmd->c_line) {
998 (void)sprintf(s," at %s line %ld",
999 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
1003 stab_io(last_in_stab) &&
1004 stab_io(last_in_stab)->lines ) {
1005 (void)sprintf(s,", <%s> line %ld",
1006 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
1007 (long)stab_io(last_in_stab)->lines);
1010 (void)strcpy(s,".\n");
1012 str_cat(tmpstr,buf+1);
1016 return tmpstr->str_ptr;
1027 extern char *e_tmpname;
1036 message = mess(args);
1039 str_set(stab_val(stabent("@",TRUE)),message);
1041 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
1042 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
1045 deb("(Skipping label #%d %s)\n",loop_ptr,
1046 loop_stack[loop_ptr].loop_label);
1053 deb("(Found label #%d %s)\n",loop_ptr,
1054 loop_stack[loop_ptr].loop_label);
1059 fatal("Bad label: %s", tmps);
1061 longjmp(loop_stack[loop_ptr].loop_env, 1);
1063 fputs(message,stderr);
1064 (void)fflush(stderr);
1066 (void)UNLINK(e_tmpname);
1068 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
1083 message = mess(args);
1086 fputs(message,stderr);
1093 (void)fflush(stderr);
1101 register int i=envix(nam); /* where does it go? */
1103 if (environ == origenviron) { /* need we copy environment? */
1109 for (max = i; environ[max]; max++) ;
1110 New(901,tmpenv, max+2, char*);
1111 for (j=0; j<max; j++) /* copy environment */
1112 tmpenv[j] = savestr(environ[j]);
1113 tmpenv[max] = Nullch;
1114 environ = tmpenv; /* tell exec where it is now */
1117 while (environ[i]) {
1118 environ[i] = environ[i+1];
1123 if (!environ[i]) { /* does not exist yet */
1124 Renew(environ, i+2, char*); /* just expand it a bit */
1125 environ[i+1] = Nullch; /* make sure it's null terminated */
1128 Safefree(environ[i]);
1129 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
1131 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
1133 /* MS-DOS requires environment variable names to be in uppercase */
1134 /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
1135 * some utilities and applications may break because they only look
1136 * for upper case strings. (Fixed strupr() bug here.)]
1138 strcpy(environ[i],nam); strupr(environ[i]);
1139 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
1147 register int i, len = strlen(nam);
1149 for (i = 0; environ[i]; i++) {
1150 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
1151 break; /* strnEQ must come first to avoid */
1152 } /* potential SEGV's */
1157 unlnk(f) /* unlink all versions of a file */
1162 for (i = 0; unlink(f) >= 0; i++) ;
1171 register char *from;
1206 vsprintf(dest, pat, args)
1207 char *dest, *pat, *args;
1211 fakebuf._ptr = dest;
1212 fakebuf._cnt = 32767;
1216 fakebuf._flag = _IOWRT|_IOSTRG;
1217 _doprnt(pat, args, &fakebuf); /* what a kludge */
1218 (void)putc('\0', &fakebuf);
1222 return 0; /* perl doesn't use return value */
1228 vfprintf(fd, pat, args)
1232 _doprnt(pat, args, fd);
1233 return 0; /* wrong, but perl doesn't use the return value */
1236 #endif /* HAS_VPRINTF */
1237 #endif /* I_VARARGS */
1240 #if BYTEORDER != 0x4321
1245 #if (BYTEORDER & 1) == 0
1248 result = ((s & 255) << 8) + ((s >> 8) & 255);
1261 char c[sizeof(long)];
1264 #if BYTEORDER == 0x1234
1265 u.c[0] = (l >> 24) & 255;
1266 u.c[1] = (l >> 16) & 255;
1267 u.c[2] = (l >> 8) & 255;
1271 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1272 fatal("Unknown BYTEORDER\n");
1277 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1278 u.c[o & 0xf] = (l >> s) & 255;
1291 char c[sizeof(long)];
1294 #if BYTEORDER == 0x1234
1295 u.c[0] = (l >> 24) & 255;
1296 u.c[1] = (l >> 16) & 255;
1297 u.c[2] = (l >> 8) & 255;
1301 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1302 fatal("Unknown BYTEORDER\n");
1309 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1310 l |= (u.c[o & 0xf] & 255) << s;
1317 #endif /* BYTEORDER != 0x4321 */
1318 #endif /* HAS_HTONS */
1327 register int this, that;
1330 int doexec = strNE(cmd,"-");
1334 this = (*mode == 'w');
1339 taintproper("Insecure dependency in exec");
1342 while ((pid = (doexec?vfork():fork())) < 0) {
1343 if (errno != EAGAIN) {
1346 fatal("Can't fork");
1355 if (p[THIS] != (*mode == 'r')) {
1356 dup2(p[THIS], *mode == 'r');
1360 #if !defined(HAS_FCNTL) || !defined(F_SETFD)
1366 for (fd = maxsysfd + 1; fd < NOFILE; fd++)
1369 do_exec(cmd); /* may or may not use the shell */
1370 warn("Can't exec \"%s\": %s", cmd, strerror(errno));
1374 if (tmpstab = stabent("$",allstabs))
1375 str_numset(STAB_STR(tmpstab),(double)getpid());
1377 hclear(pidstatus, FALSE); /* we have no children */
1382 do_execfree(); /* free any memory malloced by child on vfork */
1384 if (p[that] < p[this]) {
1385 dup2(p[this], p[that]);
1389 str = afetch(fdpid,p[this],TRUE);
1390 str->str_u.str_useful = pid;
1392 return fdopen(p[this], mode);
1401 struct stat tmpstatbuf;
1403 fprintf(stderr,"%s", s);
1404 for (fd = 0; fd < 32; fd++) {
1405 if (fstat(fd,&tmpstatbuf) >= 0)
1406 fprintf(stderr," %d",fd);
1408 fprintf(stderr,"\n");
1417 #if defined(HAS_FCNTL) && defined(F_DUPFD)
1419 fcntl(oldfd, F_DUPFD, newfd);
1428 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1431 close(fdtmp[--fdx]);
1442 void (*hstat)(), (*istat)(), (*qstat)();
1444 int (*hstat)(), (*istat)(), (*qstat)();
1450 str = afetch(fdpid,fileno(ptr),TRUE);
1451 pid = (int)str->str_u.str_useful;
1452 astore(fdpid,fileno(ptr),Nullstr);
1454 hstat = signal(SIGHUP, SIG_IGN);
1455 istat = signal(SIGINT, SIG_IGN);
1456 qstat = signal(SIGQUIT, SIG_IGN);
1457 pid = wait4pid(pid, &status, 0);
1458 signal(SIGHUP, hstat);
1459 signal(SIGINT, istat);
1460 signal(SIGQUIT, qstat);
1461 return(pid < 0 ? pid : status);
1465 wait4pid(pid,statusp,flags)
1470 #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
1479 return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
1482 return waitpid(pid,statusp,flags);
1485 sprintf(spid, "%d", pid);
1486 str = hfetch(pidstatus,spid,strlen(spid),FALSE);
1487 if (str != &str_undef) {
1488 *statusp = (int)str->str_u.str_useful;
1489 hdelete(pidstatus,spid,strlen(spid));
1496 hiterinit(pidstatus);
1497 if (entry = hiternext(pidstatus)) {
1498 pid = atoi(hiterkey(entry,statusp));
1499 str = hiterval(entry);
1500 *statusp = (int)str->str_u.str_useful;
1501 sprintf(spid, "%d", pid);
1502 hdelete(pidstatus,spid,strlen(spid));
1507 fatal("Can't do waitpid with flags");
1509 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1510 pidgone(result,*statusp);
1524 #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
1529 sprintf(spid, "%d", pid);
1530 str = hfetch(pidstatus,spid,strlen(spid),TRUE);
1531 str->str_u.str_useful = status;
1539 register unsigned char *s1;
1540 register unsigned char *s2;
1546 if (tmp = *s1++ - *s2++)
1551 #endif /* HAS_MEMCMP */
1554 repeatcpy(to,from,len,count)
1556 register char *from;
1561 register char *frombase = from;
1569 while (count-- > 0) {
1570 for (todo = len; todo > 0; todo--) {
1577 #ifndef CASTNEGFLOAT
1585 # define BIGDOUBLE 2147483648.0
1587 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1590 return (unsigned long)f;
1592 return (unsigned long)along;
1602 char *fa = rindex(a,'/');
1603 char *fb = rindex(b,'/');
1604 struct stat tmpstatbuf1;
1605 struct stat tmpstatbuf2;
1607 #define MAXPATHLEN 1024
1609 char tmpbuf[MAXPATHLEN+1];
1624 strncpy(tmpbuf, a, fa - a);
1625 if (stat(tmpbuf, &tmpstatbuf1) < 0)
1630 strncpy(tmpbuf, b, fb - b);
1631 if (stat(tmpbuf, &tmpstatbuf2) < 0)
1633 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1634 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1636 #endif /* !HAS_RENAME */
1639 scanoct(start, len, retlen)
1644 register char *s = start;
1645 register unsigned long retval = 0;
1647 while (len-- && *s >= '0' && *s <= '7') {
1649 retval |= *s++ - '0';
1651 *retlen = s - start;
1656 scanhex(start, len, retlen)
1661 register char *s = start;
1662 register unsigned long retval = 0;
1665 while (len-- && *s && (tmp = index(hexdigit, *s))) {
1667 retval |= (tmp - hexdigit) & 15;
1670 *retlen = s - start;