1 /* $Header: util.c,v 3.0.1.11 91/01/11 18:33:10 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.11 91/01/11 18:33:10 lwall
10 * patch42: die could exit with 0 value on some machines
11 * patch42: Configure checks typecasting behavior better
13 * Revision 3.0.1.10 90/11/10 02:19:28 lwall
14 * patch38: random cleanup
15 * patch38: sequence of s/^x//; s/x$//; could screw up malloc
17 * Revision 3.0.1.9 90/10/20 02:21:01 lwall
18 * patch37: tried to take strlen of integer on systems without wait4 or waitpid
19 * patch37: unreachable return eliminated
21 * Revision 3.0.1.8 90/10/16 11:26:57 lwall
22 * patch29: added waitpid
23 * patch29: various portability fixes
24 * patch29: scripts now run at almost full speed under the debugger
26 * Revision 3.0.1.7 90/08/13 22:40:26 lwall
27 * patch28: the NSIG hack didn't work right on Xenix
28 * patch28: rename was busted on systems without rename system call
30 * Revision 3.0.1.6 90/08/09 05:44:55 lwall
31 * patch19: fixed double include of <signal.h>
32 * patch19: various MSDOS and OS/2 patches folded in
33 * patch19: open(STDOUT,"|command") left wrong descriptor attached to STDOUT
35 * Revision 3.0.1.5 90/03/27 16:35:13 lwall
36 * patch16: MSDOS support
37 * patch16: support for machines that can't cast negative floats to unsigned ints
38 * patch16: tail anchored pattern could dump if string to search was shorter
40 * Revision 3.0.1.4 90/03/01 10:26:48 lwall
41 * patch9: fbminstr() called instr() rather than ninstr()
42 * patch9: nested evals clobbered their longjmp environment
43 * patch9: piped opens returned undefined rather than 0 in child
44 * patch9: the x operator is now up to 10 times faster
46 * Revision 3.0.1.3 89/12/21 20:27:41 lwall
47 * patch7: errno may now be a macro with an lvalue
49 * Revision 3.0.1.2 89/11/17 15:46:35 lwall
50 * patch5: BZERO separate from BCOPY now
51 * patch5: byteorder now is a hex value
53 * Revision 3.0.1.1 89/11/11 05:06:13 lwall
54 * patch2: made dup2 a little better
56 * Revision 3.0 89/10/18 15:32:43 lwall
64 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
78 static char nomem[] = "Out of memory!\n";
80 /* paranoid version of malloc */
86 /* NOTE: Do not call the next three routines directly. Use the macros
87 * in handy.h, so that we can easily redefine everything to do tracking of
88 * allocated hunks back to the original New to track down any memory leaks.
104 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
110 fatal("panic: malloc");
112 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
116 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
119 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
125 fputs(nomem,stderr) FLUSH;
134 /* paranoid version of realloc */
137 saferealloc(where,size)
150 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
155 fatal("Null realloc");
158 fatal("panic: realloc");
160 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
164 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
165 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
169 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
170 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
177 fputs(nomem,stderr) FLUSH;
186 /* safe version of free */
195 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
198 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
208 #define ALIGN sizeof(long)
215 register char *where;
217 where = safemalloc(size + ALIGN);
221 return where + ALIGN;
225 safexrealloc(where,size)
229 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
241 x = where[0] + 100 * where[1];
250 for (i = 0; i < MAXXCOUNT; i++) {
251 if (xcount[i] != lastxcount[i]) {
252 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
253 lastxcount[i] = xcount[i];
258 #endif /* LEAKTEST */
260 /* copy a string up to some (non-backslashed) delimiter, if any */
263 cpytill(to,from,fromend,delim,retlen)
266 register char *fromend;
272 for (; from < fromend; from++,to++) {
274 if (from[1] == delim)
276 else if (from[1] == '\\')
279 else if (*from == delim)
284 *retlen = to - origto;
288 /* return ptr to little string in big string, NULL if not found */
289 /* This routine was donated by Corey Satten. */
294 register char *little;
296 register char *s, *x;
307 for (x=big,s=little; *s; /**/ ) {
321 /* same as instr but allow embedded nulls */
324 ninstr(big, bigend, little, lend)
326 register char *bigend;
330 register char *s, *x;
331 register int first = *little;
332 register char *littleend = lend;
334 if (!first && little > littleend)
336 bigend -= littleend - little++;
337 while (big <= bigend) {
340 for (x=big,s=little; s < littleend; /**/ ) {
352 /* reverse of the above--find last substring */
355 rninstr(big, bigend, little, lend)
361 register char *bigbeg;
362 register char *s, *x;
363 register int first = *little;
364 register char *littleend = lend;
366 if (!first && little > littleend)
369 big = bigend - (littleend - little++);
370 while (big >= bigbeg) {
373 for (x=big+2,s=little; s < littleend; /**/ ) {
385 unsigned char fold[] = {
386 0, 1, 2, 3, 4, 5, 6, 7,
387 8, 9, 10, 11, 12, 13, 14, 15,
388 16, 17, 18, 19, 20, 21, 22, 23,
389 24, 25, 26, 27, 28, 29, 30, 31,
390 32, 33, 34, 35, 36, 37, 38, 39,
391 40, 41, 42, 43, 44, 45, 46, 47,
392 48, 49, 50, 51, 52, 53, 54, 55,
393 56, 57, 58, 59, 60, 61, 62, 63,
394 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
395 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
396 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
397 'x', 'y', 'z', 91, 92, 93, 94, 95,
398 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
399 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
400 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
401 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
402 128, 129, 130, 131, 132, 133, 134, 135,
403 136, 137, 138, 139, 140, 141, 142, 143,
404 144, 145, 146, 147, 148, 149, 150, 151,
405 152, 153, 154, 155, 156, 157, 158, 159,
406 160, 161, 162, 163, 164, 165, 166, 167,
407 168, 169, 170, 171, 172, 173, 174, 175,
408 176, 177, 178, 179, 180, 181, 182, 183,
409 184, 185, 186, 187, 188, 189, 190, 191,
410 192, 193, 194, 195, 196, 197, 198, 199,
411 200, 201, 202, 203, 204, 205, 206, 207,
412 208, 209, 210, 211, 212, 213, 214, 215,
413 216, 217, 218, 219, 220, 221, 222, 223,
414 224, 225, 226, 227, 228, 229, 230, 231,
415 232, 233, 234, 235, 236, 237, 238, 239,
416 240, 241, 242, 243, 244, 245, 246, 247,
417 248, 249, 250, 251, 252, 253, 254, 255
420 static unsigned char freq[] = {
421 1, 2, 84, 151, 154, 155, 156, 157,
422 165, 246, 250, 3, 158, 7, 18, 29,
423 40, 51, 62, 73, 85, 96, 107, 118,
424 129, 140, 147, 148, 149, 150, 152, 153,
425 255, 182, 224, 205, 174, 176, 180, 217,
426 233, 232, 236, 187, 235, 228, 234, 226,
427 222, 219, 211, 195, 188, 193, 185, 184,
428 191, 183, 201, 229, 181, 220, 194, 162,
429 163, 208, 186, 202, 200, 218, 198, 179,
430 178, 214, 166, 170, 207, 199, 209, 206,
431 204, 160, 212, 216, 215, 192, 175, 173,
432 243, 172, 161, 190, 203, 189, 164, 230,
433 167, 248, 227, 244, 242, 255, 241, 231,
434 240, 253, 169, 210, 245, 237, 249, 247,
435 239, 168, 252, 251, 254, 238, 223, 221,
436 213, 225, 177, 197, 171, 196, 159, 4,
437 5, 6, 8, 9, 10, 11, 12, 13,
438 14, 15, 16, 17, 19, 20, 21, 22,
439 23, 24, 25, 26, 27, 28, 30, 31,
440 32, 33, 34, 35, 36, 37, 38, 39,
441 41, 42, 43, 44, 45, 46, 47, 48,
442 49, 50, 52, 53, 54, 55, 56, 57,
443 58, 59, 60, 61, 63, 64, 65, 66,
444 67, 68, 69, 70, 71, 72, 74, 75,
445 76, 77, 78, 79, 80, 81, 82, 83,
446 86, 87, 88, 89, 90, 91, 92, 93,
447 94, 95, 97, 98, 99, 100, 101, 102,
448 103, 104, 105, 106, 108, 109, 110, 111,
449 112, 113, 114, 115, 116, 117, 119, 120,
450 121, 122, 123, 124, 125, 126, 127, 128,
451 130, 131, 132, 133, 134, 135, 136, 137,
452 138, 139, 141, 142, 143, 144, 145, 146
456 fbmcompile(str, iflag)
460 register unsigned char *s;
461 register unsigned char *table;
463 register int len = str->str_cur;
465 unsigned int frequency = 256;
467 Str_Grow(str,len+258);
469 table = (unsigned char*)(str->str_ptr + len + 1);
471 table = Null(unsigned char*);
474 for (i = 0; i < 256; i++) {
479 while (s >= (unsigned char*)(str->str_ptr))
482 if (table[*s] == len) {
485 table[*s] = table[fold[*s]] = i;
499 str->str_pok |= SP_FBM; /* deep magic */
502 s = (unsigned char*)(str->str_ptr); /* deeper magic */
504 s = Null(unsigned char*);
507 register unsigned int tmp, foldtmp;
508 str->str_pok |= SP_CASEFOLD;
509 for (i = 0; i < len; i++) {
511 foldtmp=freq[fold[s[i]]];
512 if (tmp < frequency && foldtmp < frequency) {
514 /* choose most frequent among the two */
515 frequency = (tmp > foldtmp) ? tmp : foldtmp;
520 for (i = 0; i < len; i++) {
521 if (freq[s[i]] < frequency) {
523 frequency = freq[s[i]];
527 str->str_rare = s[rarest];
528 str->str_state = rarest;
531 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
536 fbminstr(big, bigend, littlestr)
538 register unsigned char *bigend;
541 register unsigned char *s;
543 register int littlelen;
544 register unsigned char *little;
545 register unsigned char *table;
546 register unsigned char *olds;
547 register unsigned char *oldlittle;
550 if (!(littlestr->str_pok & SP_FBM))
551 return ninstr((char*)big,(char*)bigend,
552 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
555 littlelen = littlestr->str_cur;
557 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
558 if (littlelen > bigend - big)
560 little = (unsigned char*)littlestr->str_ptr;
561 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
562 big = bigend - littlelen; /* just start near end */
563 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
567 s = bigend - littlelen;
568 if (*s == *little && bcmp(s,little,littlelen)==0)
569 return (char*)s; /* how sweet it is */
570 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
573 if (*s == *little && bcmp(s,little,littlelen)==0)
579 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
581 table = Null(unsigned char*);
583 if (--littlelen >= bigend - big)
586 oldlittle = little = table - 2;
587 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
590 if (tmp = table[*s]) {
592 if (bigend - s > tmp) {
597 if ((s += tmp) < bigend)
603 tmp = littlelen; /* less expensive than calling strncmp() */
606 if (*--s == *--little || fold[*s] == *little)
608 s = olds + 1; /* here we pay the price for failure */
610 if (s < bigend) /* fake up continue to outer loop */
623 if (tmp = table[*s]) {
625 if (bigend - s > tmp) {
630 if ((s += tmp) < bigend)
636 tmp = littlelen; /* less expensive than calling strncmp() */
639 if (*--s == *--little)
641 s = olds + 1; /* here we pay the price for failure */
643 if (s < bigend) /* fake up continue to outer loop */
657 screaminstr(bigstr, littlestr)
661 register unsigned char *s, *x;
662 register unsigned char *big;
664 register int previous;
666 register unsigned char *little;
667 register unsigned char *bigend;
668 register unsigned char *littleend;
670 if ((pos = screamfirst[littlestr->str_rare]) < 0)
673 little = (unsigned char *)(littlestr->str_ptr);
675 little = Null(unsigned char *);
677 littleend = little + littlestr->str_cur;
679 previous = littlestr->str_state;
681 big = (unsigned char *)(bigstr->str_ptr);
683 big = Null(unsigned char*);
685 bigend = big + bigstr->str_cur;
687 while (pos < previous) {
689 if (!(pos += screamnext[pos]))
693 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
695 if (big[pos] != first && big[pos] != fold[first])
697 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
700 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
707 return (char *)(big+pos);
713 pos += screamnext[pos] /* does this goof up anywhere? */
721 if (big[pos] != first)
723 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
733 return (char *)(big+pos);
739 pos += screamnext[pos]
748 /* copy a string to a safe spot */
754 register char *newaddr;
756 New(902,newaddr,strlen(str)+1,char);
757 (void)strcpy(newaddr,str);
761 /* same thing but with a known length */
768 register char *newaddr;
770 New(903,newaddr,len+1,char);
771 (void)bcopy(str,newaddr,len); /* might not be null terminated */
772 newaddr[len] = '\0'; /* is now */
776 /* grow a static string to at least a certain length */
779 growstr(strptr,curlen,newlen)
784 if (newlen > *curlen) { /* need more room? */
786 Renew(*strptr,newlen,char);
788 New(905,*strptr,newlen,char);
795 mess(pat,a1,a2,a3,a4)
802 (void)sprintf(s,pat,a1,a2,a3,a4);
805 if (curcmd->c_line) {
806 (void)sprintf(s," at %s line %ld",
807 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
811 stab_io(last_in_stab) &&
812 stab_io(last_in_stab)->lines ) {
813 (void)sprintf(s,", <%s> line %ld",
814 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
815 (long)stab_io(last_in_stab)->lines);
818 (void)strcpy(s,".\n");
823 fatal(pat,a1,a2,a3,a4)
828 extern char *e_tmpname;
831 mess(pat,a1,a2,a3,a4);
833 str_set(stab_val(stabent("@",TRUE)),buf);
835 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
836 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
839 deb("(Skipping label #%d %s)\n",loop_ptr,
840 loop_stack[loop_ptr].loop_label);
847 deb("(Found label #%d %s)\n",loop_ptr,
848 loop_stack[loop_ptr].loop_label);
853 fatal("Bad label: %s", tmps);
855 longjmp(loop_stack[loop_ptr].loop_env, 1);
858 (void)fflush(stderr);
860 (void)UNLINK(e_tmpname);
862 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
866 warn(pat,a1,a2,a3,a4)
870 mess(pat,a1,a2,a3,a4);
878 (void)fflush(stderr);
897 pat = va_arg(args, char *);
899 (void) vsprintf(s,pat,args);
903 if (curcmd->c_line) {
904 (void)sprintf(s," at %s line %ld",
905 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
909 stab_io(last_in_stab) &&
910 stab_io(last_in_stab)->lines ) {
911 (void)sprintf(s,", <%s> line %ld",
912 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
913 (long)stab_io(last_in_stab)->lines);
916 (void)strcpy(s,".\n");
926 extern char *e_tmpname;
937 str_set(stab_val(stabent("@",TRUE)),buf);
939 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
940 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
943 deb("(Skipping label #%d %s)\n",loop_ptr,
944 loop_stack[loop_ptr].loop_label);
951 deb("(Found label #%d %s)\n",loop_ptr,
952 loop_stack[loop_ptr].loop_label);
957 fatal("Bad label: %s", tmps);
959 longjmp(loop_stack[loop_ptr].loop_env, 1);
962 (void)fflush(stderr);
964 (void)UNLINK(e_tmpname);
966 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
990 (void)fflush(stderr);
994 static bool firstsetenv = TRUE;
995 extern char **environ;
1001 register int i=envix(nam); /* where does it go? */
1004 while (environ[i]) {
1005 environ[i] = environ[i+1];
1010 if (!environ[i]) { /* does not exist yet */
1011 if (firstsetenv) { /* need we copy environment? */
1015 New(901,tmpenv, i+2, char*);
1016 firstsetenv = FALSE;
1017 for (j=0; j<i; j++) /* copy environment */
1018 tmpenv[j] = environ[j];
1019 environ = tmpenv; /* tell exec where it is now */
1022 Renew(environ, i+2, char*); /* just expand it a bit */
1023 environ[i+1] = Nullch; /* make sure it's null terminated */
1025 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
1026 /* this may or may not be in */
1027 /* the old environ structure */
1029 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
1031 /* MS-DOS requires environment variable names to be in uppercase */
1032 strcpy(environ[i],nam); strupr(environ[i],nam);
1033 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
1041 register int i, len = strlen(nam);
1043 for (i = 0; environ[i]; i++) {
1044 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
1045 break; /* strnEQ must come first to avoid */
1046 } /* potential SEGV's */
1051 unlnk(f) /* unlink all versions of a file */
1056 for (i = 0; unlink(f) >= 0; i++) ;
1065 register char *from;
1100 vsprintf(dest, pat, args)
1101 char *dest, *pat, *args;
1105 fakebuf._ptr = dest;
1106 fakebuf._cnt = 32767;
1107 fakebuf._flag = _IOWRT|_IOSTRG;
1108 _doprnt(pat, args, &fakebuf); /* what a kludge */
1109 (void)putc('\0', &fakebuf);
1113 return 0; /* perl doesn't use return value */
1119 vfprintf(fd, pat, args)
1123 _doprnt(pat, args, fd);
1124 return 0; /* wrong, but perl doesn't use the return value */
1127 #endif /* VPRINTF */
1128 #endif /* VARARGS */
1131 #if BYTEORDER != 0x4321
1136 #if (BYTEORDER & 1) == 0
1139 result = ((s & 255) << 8) + ((s >> 8) & 255);
1152 char c[sizeof(long)];
1155 #if BYTEORDER == 0x1234
1156 u.c[0] = (l >> 24) & 255;
1157 u.c[1] = (l >> 16) & 255;
1158 u.c[2] = (l >> 8) & 255;
1162 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1163 fatal("Unknown BYTEORDER\n");
1168 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1169 u.c[o & 0xf] = (l >> s) & 255;
1182 char c[sizeof(long)];
1185 #if BYTEORDER == 0x1234
1186 u.c[0] = (l >> 24) & 255;
1187 u.c[1] = (l >> 16) & 255;
1188 u.c[2] = (l >> 8) & 255;
1192 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1193 fatal("Unknown BYTEORDER\n");
1200 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1201 l |= (u.c[o & 0xf] & 255) << s;
1208 #endif /* BYTEORDER != 0x4321 */
1218 register int this, that;
1221 int doexec = strNE(cmd,"-");
1225 this = (*mode == 'w');
1227 while ((pid = (doexec?vfork():fork())) < 0) {
1228 if (errno != EAGAIN) {
1231 fatal("Can't fork");
1240 if (p[THIS] != (*mode == 'r')) {
1241 dup2(p[THIS], *mode == 'r');
1245 #if !defined(FCNTL) || !defined(F_SETFD)
1251 for (fd = 3; fd < NOFILE; fd++)
1254 do_exec(cmd); /* may or may not use the shell */
1257 if (tmpstab = stabent("$",allstabs))
1258 str_numset(STAB_STR(tmpstab),(double)getpid());
1260 hclear(pidstatus); /* we have no children */
1265 do_execfree(); /* free any memory malloced by child on vfork */
1267 if (p[that] < p[this]) {
1268 dup2(p[this], p[that]);
1272 str = afetch(fdpid,p[this],TRUE);
1273 str->str_u.str_useful = pid;
1275 return fdopen(p[this], mode);
1284 struct stat tmpstatbuf;
1286 fprintf(stderr,"%s", s);
1287 for (fd = 0; fd < 32; fd++) {
1288 if (fstat(fd,&tmpstatbuf) >= 0)
1289 fprintf(stderr," %d",fd);
1291 fprintf(stderr,"\n");
1300 #if defined(FCNTL) && defined(F_DUPFD)
1302 fcntl(oldfd, F_DUPFD, newfd);
1309 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1312 close(fdtmp[--fdx]);
1323 void (*hstat)(), (*istat)(), (*qstat)();
1325 int (*hstat)(), (*istat)(), (*qstat)();
1331 str = afetch(fdpid,fileno(ptr),TRUE);
1332 astore(fdpid,fileno(ptr),Nullstr);
1334 pid = (int)str->str_u.str_useful;
1335 hstat = signal(SIGHUP, SIG_IGN);
1336 istat = signal(SIGINT, SIG_IGN);
1337 qstat = signal(SIGQUIT, SIG_IGN);
1338 pid = wait4pid(pid, &status, 0);
1339 signal(SIGHUP, hstat);
1340 signal(SIGINT, istat);
1341 signal(SIGQUIT, qstat);
1342 return(pid < 0 ? pid : status);
1346 wait4pid(pid,statusp,flags)
1358 return wait4(pid,statusp,flags,Null(struct rusage *));
1361 return waitpid(pid,statusp,flags);
1364 sprintf(spid, "%d", pid);
1365 str = hfetch(pidstatus,spid,strlen(spid),FALSE);
1366 if (str != &str_undef) {
1367 *statusp = (int)str->str_u.str_useful;
1368 hdelete(pidstatus,spid,strlen(spid));
1375 hiterinit(pidstatus);
1376 if (entry = hiternext(pidstatus)) {
1377 pid = atoi(hiterkey(entry,statusp));
1378 str = hiterval(entry);
1379 *statusp = (int)str->str_u.str_useful;
1380 sprintf(spid, "%d", pid);
1381 hdelete(pidstatus,spid,strlen(spid));
1386 fatal("Can't do waitpid with flags");
1391 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1392 pidgone(result,*statusp);
1406 #if defined(WAIT4) || defined(WAITPID)
1411 sprintf(spid, "%d", pid);
1412 str = hfetch(pidstatus,spid,strlen(spid),TRUE);
1413 str->str_u.str_useful = status;
1420 register unsigned char *s1;
1421 register unsigned char *s2;
1427 if (tmp = *s1++ - *s2++)
1435 repeatcpy(to,from,len,count)
1437 register char *from;
1442 register char *frombase = from;
1450 while (count-- > 0) {
1451 for (todo = len; todo > 0; todo--) {
1458 #ifndef CASTNEGFLOAT
1466 # define BIGDOUBLE 2147483648.0
1468 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1471 return (unsigned long)f;
1473 return (unsigned long)along;
1483 char *fa = rindex(a,'/');
1484 char *fb = rindex(b,'/');
1485 struct stat tmpstatbuf1;
1486 struct stat tmpstatbuf2;
1488 #define MAXPATHLEN 1024
1490 char tmpbuf[MAXPATHLEN+1];
1505 strncpy(tmpbuf, a, fa - a);
1506 if (stat(tmpbuf, &tmpstatbuf1) < 0)
1511 strncpy(tmpbuf, b, fb - b);
1512 if (stat(tmpbuf, &tmpstatbuf2) < 0)
1514 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1515 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1517 #endif /* !RENAME */