1 /* $Header: util.c,v 3.0.1.10 90/11/10 02:19:28 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.10 90/11/10 02:19:28 lwall
10 * patch38: random cleanup
11 * patch38: sequence of s/^x//; s/x$//; could screw up malloc
13 * Revision 3.0.1.9 90/10/20 02:21:01 lwall
14 * patch37: tried to take strlen of integer on systems without wait4 or waitpid
15 * patch37: unreachable return eliminated
17 * Revision 3.0.1.8 90/10/16 11:26:57 lwall
18 * patch29: added waitpid
19 * patch29: various portability fixes
20 * patch29: scripts now run at almost full speed under the debugger
22 * Revision 3.0.1.7 90/08/13 22:40:26 lwall
23 * patch28: the NSIG hack didn't work right on Xenix
24 * patch28: rename was busted on systems without rename system call
26 * Revision 3.0.1.6 90/08/09 05:44:55 lwall
27 * patch19: fixed double include of <signal.h>
28 * patch19: various MSDOS and OS/2 patches folded in
29 * patch19: open(STDOUT,"|command") left wrong descriptor attached to STDOUT
31 * Revision 3.0.1.5 90/03/27 16:35:13 lwall
32 * patch16: MSDOS support
33 * patch16: support for machines that can't cast negative floats to unsigned ints
34 * patch16: tail anchored pattern could dump if string to search was shorter
36 * Revision 3.0.1.4 90/03/01 10:26:48 lwall
37 * patch9: fbminstr() called instr() rather than ninstr()
38 * patch9: nested evals clobbered their longjmp environment
39 * patch9: piped opens returned undefined rather than 0 in child
40 * patch9: the x operator is now up to 10 times faster
42 * Revision 3.0.1.3 89/12/21 20:27:41 lwall
43 * patch7: errno may now be a macro with an lvalue
45 * Revision 3.0.1.2 89/11/17 15:46:35 lwall
46 * patch5: BZERO separate from BCOPY now
47 * patch5: byteorder now is a hex value
49 * Revision 3.0.1.1 89/11/11 05:06:13 lwall
50 * patch2: made dup2 a little better
52 * Revision 3.0 89/10/18 15:32:43 lwall
60 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
74 static char nomem[] = "Out of memory!\n";
76 /* paranoid version of malloc */
82 /* NOTE: Do not call the next three routines directly. Use the macros
83 * in handy.h, so that we can easily redefine everything to do tracking of
84 * allocated hunks back to the original New to track down any memory leaks.
100 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
106 fatal("panic: malloc");
108 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
112 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
115 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
121 fputs(nomem,stderr) FLUSH;
130 /* paranoid version of realloc */
133 saferealloc(where,size)
146 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
151 fatal("Null realloc");
154 fatal("panic: realloc");
156 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
160 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
161 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
165 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
166 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
173 fputs(nomem,stderr) FLUSH;
182 /* safe version of free */
191 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
194 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
204 #define ALIGN sizeof(long)
211 register char *where;
213 where = safemalloc(size + ALIGN);
217 return where + ALIGN;
221 safexrealloc(where,size)
225 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
237 x = where[0] + 100 * where[1];
246 for (i = 0; i < MAXXCOUNT; i++) {
247 if (xcount[i] != lastxcount[i]) {
248 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
249 lastxcount[i] = xcount[i];
254 #endif /* LEAKTEST */
256 /* copy a string up to some (non-backslashed) delimiter, if any */
259 cpytill(to,from,fromend,delim,retlen)
262 register char *fromend;
268 for (; from < fromend; from++,to++) {
270 if (from[1] == delim)
272 else if (from[1] == '\\')
275 else if (*from == delim)
280 *retlen = to - origto;
284 /* return ptr to little string in big string, NULL if not found */
285 /* This routine was donated by Corey Satten. */
290 register char *little;
292 register char *s, *x;
303 for (x=big,s=little; *s; /**/ ) {
317 /* same as instr but allow embedded nulls */
320 ninstr(big, bigend, little, lend)
322 register char *bigend;
326 register char *s, *x;
327 register int first = *little;
328 register char *littleend = lend;
330 if (!first && little > littleend)
332 bigend -= littleend - little++;
333 while (big <= bigend) {
336 for (x=big,s=little; s < littleend; /**/ ) {
348 /* reverse of the above--find last substring */
351 rninstr(big, bigend, little, lend)
357 register char *bigbeg;
358 register char *s, *x;
359 register int first = *little;
360 register char *littleend = lend;
362 if (!first && little > littleend)
365 big = bigend - (littleend - little++);
366 while (big >= bigbeg) {
369 for (x=big+2,s=little; s < littleend; /**/ ) {
381 unsigned char fold[] = {
382 0, 1, 2, 3, 4, 5, 6, 7,
383 8, 9, 10, 11, 12, 13, 14, 15,
384 16, 17, 18, 19, 20, 21, 22, 23,
385 24, 25, 26, 27, 28, 29, 30, 31,
386 32, 33, 34, 35, 36, 37, 38, 39,
387 40, 41, 42, 43, 44, 45, 46, 47,
388 48, 49, 50, 51, 52, 53, 54, 55,
389 56, 57, 58, 59, 60, 61, 62, 63,
390 64, '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', 91, 92, 93, 94, 95,
394 96, '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', 123, 124, 125, 126, 127,
398 128, 129, 130, 131, 132, 133, 134, 135,
399 136, 137, 138, 139, 140, 141, 142, 143,
400 144, 145, 146, 147, 148, 149, 150, 151,
401 152, 153, 154, 155, 156, 157, 158, 159,
402 160, 161, 162, 163, 164, 165, 166, 167,
403 168, 169, 170, 171, 172, 173, 174, 175,
404 176, 177, 178, 179, 180, 181, 182, 183,
405 184, 185, 186, 187, 188, 189, 190, 191,
406 192, 193, 194, 195, 196, 197, 198, 199,
407 200, 201, 202, 203, 204, 205, 206, 207,
408 208, 209, 210, 211, 212, 213, 214, 215,
409 216, 217, 218, 219, 220, 221, 222, 223,
410 224, 225, 226, 227, 228, 229, 230, 231,
411 232, 233, 234, 235, 236, 237, 238, 239,
412 240, 241, 242, 243, 244, 245, 246, 247,
413 248, 249, 250, 251, 252, 253, 254, 255
416 static unsigned char freq[] = {
417 1, 2, 84, 151, 154, 155, 156, 157,
418 165, 246, 250, 3, 158, 7, 18, 29,
419 40, 51, 62, 73, 85, 96, 107, 118,
420 129, 140, 147, 148, 149, 150, 152, 153,
421 255, 182, 224, 205, 174, 176, 180, 217,
422 233, 232, 236, 187, 235, 228, 234, 226,
423 222, 219, 211, 195, 188, 193, 185, 184,
424 191, 183, 201, 229, 181, 220, 194, 162,
425 163, 208, 186, 202, 200, 218, 198, 179,
426 178, 214, 166, 170, 207, 199, 209, 206,
427 204, 160, 212, 216, 215, 192, 175, 173,
428 243, 172, 161, 190, 203, 189, 164, 230,
429 167, 248, 227, 244, 242, 255, 241, 231,
430 240, 253, 169, 210, 245, 237, 249, 247,
431 239, 168, 252, 251, 254, 238, 223, 221,
432 213, 225, 177, 197, 171, 196, 159, 4,
433 5, 6, 8, 9, 10, 11, 12, 13,
434 14, 15, 16, 17, 19, 20, 21, 22,
435 23, 24, 25, 26, 27, 28, 30, 31,
436 32, 33, 34, 35, 36, 37, 38, 39,
437 41, 42, 43, 44, 45, 46, 47, 48,
438 49, 50, 52, 53, 54, 55, 56, 57,
439 58, 59, 60, 61, 63, 64, 65, 66,
440 67, 68, 69, 70, 71, 72, 74, 75,
441 76, 77, 78, 79, 80, 81, 82, 83,
442 86, 87, 88, 89, 90, 91, 92, 93,
443 94, 95, 97, 98, 99, 100, 101, 102,
444 103, 104, 105, 106, 108, 109, 110, 111,
445 112, 113, 114, 115, 116, 117, 119, 120,
446 121, 122, 123, 124, 125, 126, 127, 128,
447 130, 131, 132, 133, 134, 135, 136, 137,
448 138, 139, 141, 142, 143, 144, 145, 146
452 fbmcompile(str, iflag)
456 register unsigned char *s;
457 register unsigned char *table;
459 register int len = str->str_cur;
461 unsigned int frequency = 256;
463 Str_Grow(str,len+258);
465 table = (unsigned char*)(str->str_ptr + len + 1);
467 table = Null(unsigned char*);
470 for (i = 0; i < 256; i++) {
475 while (s >= (unsigned char*)(str->str_ptr))
478 if (table[*s] == len) {
481 table[*s] = table[fold[*s]] = i;
495 str->str_pok |= SP_FBM; /* deep magic */
498 s = (unsigned char*)(str->str_ptr); /* deeper magic */
500 s = Null(unsigned char*);
503 register unsigned int tmp, foldtmp;
504 str->str_pok |= SP_CASEFOLD;
505 for (i = 0; i < len; i++) {
507 foldtmp=freq[fold[s[i]]];
508 if (tmp < frequency && foldtmp < frequency) {
510 /* choose most frequent among the two */
511 frequency = (tmp > foldtmp) ? tmp : foldtmp;
516 for (i = 0; i < len; i++) {
517 if (freq[s[i]] < frequency) {
519 frequency = freq[s[i]];
523 str->str_rare = s[rarest];
524 str->str_state = rarest;
527 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
532 fbminstr(big, bigend, littlestr)
534 register unsigned char *bigend;
537 register unsigned char *s;
539 register int littlelen;
540 register unsigned char *little;
541 register unsigned char *table;
542 register unsigned char *olds;
543 register unsigned char *oldlittle;
546 if (!(littlestr->str_pok & SP_FBM))
547 return ninstr((char*)big,(char*)bigend,
548 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
551 littlelen = littlestr->str_cur;
553 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
554 if (littlelen > bigend - big)
556 little = (unsigned char*)littlestr->str_ptr;
557 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
558 big = bigend - littlelen; /* just start near end */
559 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
563 s = bigend - littlelen;
564 if (*s == *little && bcmp(s,little,littlelen)==0)
565 return (char*)s; /* how sweet it is */
566 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
569 if (*s == *little && bcmp(s,little,littlelen)==0)
575 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
577 table = Null(unsigned char*);
579 if (--littlelen >= bigend - big)
582 oldlittle = little = table - 2;
583 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 */
619 if (tmp = table[*s]) {
621 if (bigend - s > tmp) {
626 if ((s += tmp) < bigend)
632 tmp = littlelen; /* less expensive than calling strncmp() */
635 if (*--s == *--little)
637 s = olds + 1; /* here we pay the price for failure */
639 if (s < bigend) /* fake up continue to outer loop */
653 screaminstr(bigstr, littlestr)
657 register unsigned char *s, *x;
658 register unsigned char *big;
660 register int previous;
662 register unsigned char *little;
663 register unsigned char *bigend;
664 register unsigned char *littleend;
666 if ((pos = screamfirst[littlestr->str_rare]) < 0)
669 little = (unsigned char *)(littlestr->str_ptr);
671 little = Null(unsigned char *);
673 littleend = little + littlestr->str_cur;
675 previous = littlestr->str_state;
677 big = (unsigned char *)(bigstr->str_ptr);
679 big = Null(unsigned char*);
681 bigend = big + bigstr->str_cur;
683 while (pos < previous) {
685 if (!(pos += screamnext[pos]))
689 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
691 if (big[pos] != first && big[pos] != fold[first])
693 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
696 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
703 return (char *)(big+pos);
709 pos += screamnext[pos] /* does this goof up anywhere? */
717 if (big[pos] != first)
719 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
729 return (char *)(big+pos);
735 pos += screamnext[pos]
744 /* copy a string to a safe spot */
750 register char *newaddr;
752 New(902,newaddr,strlen(str)+1,char);
753 (void)strcpy(newaddr,str);
757 /* same thing but with a known length */
764 register char *newaddr;
766 New(903,newaddr,len+1,char);
767 (void)bcopy(str,newaddr,len); /* might not be null terminated */
768 newaddr[len] = '\0'; /* is now */
772 /* grow a static string to at least a certain length */
775 growstr(strptr,curlen,newlen)
780 if (newlen > *curlen) { /* need more room? */
782 Renew(*strptr,newlen,char);
784 New(905,*strptr,newlen,char);
791 mess(pat,a1,a2,a3,a4)
798 (void)sprintf(s,pat,a1,a2,a3,a4);
801 if (curcmd->c_line) {
802 (void)sprintf(s," at %s line %ld",
803 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
807 stab_io(last_in_stab) &&
808 stab_io(last_in_stab)->lines ) {
809 (void)sprintf(s,", <%s> line %ld",
810 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
811 (long)stab_io(last_in_stab)->lines);
814 (void)strcpy(s,".\n");
819 fatal(pat,a1,a2,a3,a4)
824 extern char *e_tmpname;
827 mess(pat,a1,a2,a3,a4);
829 str_set(stab_val(stabent("@",TRUE)),buf);
831 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
832 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
835 deb("(Skipping label #%d %s)\n",loop_ptr,
836 loop_stack[loop_ptr].loop_label);
843 deb("(Found label #%d %s)\n",loop_ptr,
844 loop_stack[loop_ptr].loop_label);
849 fatal("Bad label: %s", tmps);
851 longjmp(loop_stack[loop_ptr].loop_env, 1);
854 (void)fflush(stderr);
856 (void)UNLINK(e_tmpname);
858 exit(errno?errno:(statusvalue?statusvalue:255));
862 warn(pat,a1,a2,a3,a4)
866 mess(pat,a1,a2,a3,a4);
874 (void)fflush(stderr);
893 pat = va_arg(args, char *);
895 (void) vsprintf(s,pat,args);
899 if (curcmd->c_line) {
900 (void)sprintf(s," at %s line %ld",
901 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
905 stab_io(last_in_stab) &&
906 stab_io(last_in_stab)->lines ) {
907 (void)sprintf(s,", <%s> line %ld",
908 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
909 (long)stab_io(last_in_stab)->lines);
912 (void)strcpy(s,".\n");
922 extern char *e_tmpname;
933 str_set(stab_val(stabent("@",TRUE)),buf);
935 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
936 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
939 deb("(Skipping label #%d %s)\n",loop_ptr,
940 loop_stack[loop_ptr].loop_label);
947 deb("(Found label #%d %s)\n",loop_ptr,
948 loop_stack[loop_ptr].loop_label);
953 fatal("Bad label: %s", tmps);
955 longjmp(loop_stack[loop_ptr].loop_env, 1);
958 (void)fflush(stderr);
960 (void)UNLINK(e_tmpname);
962 exit((int)(errno?errno:(statusvalue?statusvalue:255)));
986 (void)fflush(stderr);
990 static bool firstsetenv = TRUE;
991 extern char **environ;
997 register int i=envix(nam); /* where does it go? */
1000 while (environ[i]) {
1001 environ[i] = environ[i+1];
1006 if (!environ[i]) { /* does not exist yet */
1007 if (firstsetenv) { /* need we copy environment? */
1011 New(901,tmpenv, i+2, char*);
1012 firstsetenv = FALSE;
1013 for (j=0; j<i; j++) /* copy environment */
1014 tmpenv[j] = environ[j];
1015 environ = tmpenv; /* tell exec where it is now */
1018 Renew(environ, i+2, char*); /* just expand it a bit */
1019 environ[i+1] = Nullch; /* make sure it's null terminated */
1021 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
1022 /* this may or may not be in */
1023 /* the old environ structure */
1025 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
1027 /* MS-DOS requires environment variable names to be in uppercase */
1028 strcpy(environ[i],nam); strupr(environ[i],nam);
1029 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
1037 register int i, len = strlen(nam);
1039 for (i = 0; environ[i]; i++) {
1040 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
1041 break; /* strnEQ must come first to avoid */
1042 } /* potential SEGV's */
1047 unlnk(f) /* unlink all versions of a file */
1052 for (i = 0; unlink(f) >= 0; i++) ;
1061 register char *from;
1096 vsprintf(dest, pat, args)
1097 char *dest, *pat, *args;
1101 fakebuf._ptr = dest;
1102 fakebuf._cnt = 32767;
1103 fakebuf._flag = _IOWRT|_IOSTRG;
1104 _doprnt(pat, args, &fakebuf); /* what a kludge */
1105 (void)putc('\0', &fakebuf);
1109 return 0; /* perl doesn't use return value */
1115 vfprintf(fd, pat, args)
1119 _doprnt(pat, args, fd);
1120 return 0; /* wrong, but perl doesn't use the return value */
1123 #endif /* VPRINTF */
1124 #endif /* VARARGS */
1127 #if BYTEORDER != 0x4321
1132 #if (BYTEORDER & 1) == 0
1135 result = ((s & 255) << 8) + ((s >> 8) & 255);
1148 char c[sizeof(long)];
1151 #if BYTEORDER == 0x1234
1152 u.c[0] = (l >> 24) & 255;
1153 u.c[1] = (l >> 16) & 255;
1154 u.c[2] = (l >> 8) & 255;
1158 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1159 fatal("Unknown BYTEORDER\n");
1164 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1165 u.c[o & 0xf] = (l >> s) & 255;
1178 char c[sizeof(long)];
1181 #if BYTEORDER == 0x1234
1182 u.c[0] = (l >> 24) & 255;
1183 u.c[1] = (l >> 16) & 255;
1184 u.c[2] = (l >> 8) & 255;
1188 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1189 fatal("Unknown BYTEORDER\n");
1196 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1197 l |= (u.c[o & 0xf] & 255) << s;
1204 #endif /* BYTEORDER != 0x4321 */
1214 register int this, that;
1217 int doexec = strNE(cmd,"-");
1221 this = (*mode == 'w');
1223 while ((pid = (doexec?vfork():fork())) < 0) {
1224 if (errno != EAGAIN) {
1227 fatal("Can't fork");
1236 if (p[THIS] != (*mode == 'r')) {
1237 dup2(p[THIS], *mode == 'r');
1241 #if !defined(FCNTL) || !defined(F_SETFD)
1247 for (fd = 3; fd < NOFILE; fd++)
1250 do_exec(cmd); /* may or may not use the shell */
1253 if (tmpstab = stabent("$",allstabs))
1254 str_numset(STAB_STR(tmpstab),(double)getpid());
1256 hclear(pidstatus); /* we have no children */
1261 do_execfree(); /* free any memory malloced by child on vfork */
1263 if (p[that] < p[this]) {
1264 dup2(p[this], p[that]);
1268 str = afetch(fdpid,p[this],TRUE);
1269 str->str_u.str_useful = pid;
1271 return fdopen(p[this], mode);
1280 struct stat tmpstatbuf;
1282 fprintf(stderr,"%s", s);
1283 for (fd = 0; fd < 32; fd++) {
1284 if (fstat(fd,&tmpstatbuf) >= 0)
1285 fprintf(stderr," %d",fd);
1287 fprintf(stderr,"\n");
1296 #if defined(FCNTL) && defined(F_DUPFD)
1298 fcntl(oldfd, F_DUPFD, newfd);
1305 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1308 close(fdtmp[--fdx]);
1319 void (*hstat)(), (*istat)(), (*qstat)();
1321 int (*hstat)(), (*istat)(), (*qstat)();
1327 str = afetch(fdpid,fileno(ptr),TRUE);
1328 astore(fdpid,fileno(ptr),Nullstr);
1330 pid = (int)str->str_u.str_useful;
1331 hstat = signal(SIGHUP, SIG_IGN);
1332 istat = signal(SIGINT, SIG_IGN);
1333 qstat = signal(SIGQUIT, SIG_IGN);
1334 pid = wait4pid(pid, &status, 0);
1335 signal(SIGHUP, hstat);
1336 signal(SIGINT, istat);
1337 signal(SIGQUIT, qstat);
1338 return(pid < 0 ? pid : status);
1342 wait4pid(pid,statusp,flags)
1354 return wait4(pid,statusp,flags,Null(struct rusage *));
1357 return waitpid(pid,statusp,flags);
1360 sprintf(spid, "%d", pid);
1361 str = hfetch(pidstatus,spid,strlen(spid),FALSE);
1362 if (str != &str_undef) {
1363 *statusp = (int)str->str_u.str_useful;
1364 hdelete(pidstatus,spid,strlen(spid));
1371 hiterinit(pidstatus);
1372 if (entry = hiternext(pidstatus)) {
1373 pid = atoi(hiterkey(entry,statusp));
1374 str = hiterval(entry);
1375 *statusp = (int)str->str_u.str_useful;
1376 sprintf(spid, "%d", pid);
1377 hdelete(pidstatus,spid,strlen(spid));
1382 fatal("Can't do waitpid with flags");
1387 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1388 pidgone(result,*statusp);
1402 #if defined(WAIT4) || defined(WAITPID)
1407 sprintf(spid, "%d", pid);
1408 str = hfetch(pidstatus,spid,strlen(spid),TRUE);
1409 str->str_u.str_useful = status;
1416 register unsigned char *s1;
1417 register unsigned char *s2;
1423 if (tmp = *s1++ - *s2++)
1431 repeatcpy(to,from,len,count)
1433 register char *from;
1438 register char *frombase = from;
1446 while (count-- > 0) {
1447 for (todo = len; todo > 0; todo--) {
1454 #ifndef CASTNEGFLOAT
1462 # define BIGDOUBLE 2147483648.0
1464 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1467 return (unsigned long)f;
1469 return (unsigned long)along;
1479 char *fa = rindex(a,'/');
1480 char *fb = rindex(b,'/');
1481 struct stat tmpstatbuf1;
1482 struct stat tmpstatbuf2;
1484 #define MAXPATHLEN 1024
1486 char tmpbuf[MAXPATHLEN+1];
1501 strncpy(tmpbuf, a, fa - a);
1502 if (stat(tmpbuf, &tmpstatbuf1) < 0)
1507 strncpy(tmpbuf, b, fb - b);
1508 if (stat(tmpbuf, &tmpstatbuf2) < 0)
1510 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1511 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1513 #endif /* !RENAME */