1 /* $Header: util.c,v 3.0.1.9 90/10/20 02:21:01 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.9 90/10/20 02:21:01 lwall
10 * patch37: tried to take strlen of integer on systems without wait4 or waitpid
11 * patch37: unreachable return eliminated
13 * Revision 3.0.1.8 90/10/16 11:26:57 lwall
14 * patch29: added waitpid
15 * patch29: various portability fixes
16 * patch29: scripts now run at almost full speed under the debugger
18 * Revision 3.0.1.7 90/08/13 22:40:26 lwall
19 * patch28: the NSIG hack didn't work right on Xenix
20 * patch28: rename was busted on systems without rename system call
22 * Revision 3.0.1.6 90/08/09 05:44:55 lwall
23 * patch19: fixed double include of <signal.h>
24 * patch19: various MSDOS and OS/2 patches folded in
25 * patch19: open(STDOUT,"|command") left wrong descriptor attached to STDOUT
27 * Revision 3.0.1.5 90/03/27 16:35:13 lwall
28 * patch16: MSDOS support
29 * patch16: support for machines that can't cast negative floats to unsigned ints
30 * patch16: tail anchored pattern could dump if string to search was shorter
32 * Revision 3.0.1.4 90/03/01 10:26:48 lwall
33 * patch9: fbminstr() called instr() rather than ninstr()
34 * patch9: nested evals clobbered their longjmp environment
35 * patch9: piped opens returned undefined rather than 0 in child
36 * patch9: the x operator is now up to 10 times faster
38 * Revision 3.0.1.3 89/12/21 20:27:41 lwall
39 * patch7: errno may now be a macro with an lvalue
41 * Revision 3.0.1.2 89/11/17 15:46:35 lwall
42 * patch5: BZERO separate from BCOPY now
43 * patch5: byteorder now is a hex value
45 * Revision 3.0.1.1 89/11/11 05:06:13 lwall
46 * patch2: made dup2 a little better
48 * Revision 3.0 89/10/18 15:32:43 lwall
56 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
70 static char nomem[] = "Out of memory!\n";
72 /* paranoid version of malloc */
78 /* NOTE: Do not call the next three routines directly. Use the macros
79 * in handy.h, so that we can easily redefine everything to do tracking of
80 * allocated hunks back to the original New to track down any memory leaks.
96 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
100 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
104 fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
107 fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
113 fputs(nomem,stdout) FLUSH;
122 /* paranoid version of realloc */
125 saferealloc(where,size)
138 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
143 fatal("Null realloc");
144 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
148 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
149 fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
153 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
154 fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
161 fputs(nomem,stdout) FLUSH;
170 /* safe version of free */
179 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
182 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
192 #define ALIGN sizeof(long)
199 register char *where;
201 where = safemalloc(size + ALIGN);
205 return where + ALIGN;
209 safexrealloc(where,size)
213 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
225 x = where[0] + 100 * where[1];
234 for (i = 0; i < MAXXCOUNT; i++) {
235 if (xcount[i] != lastxcount[i]) {
236 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
237 lastxcount[i] = xcount[i];
242 #endif /* LEAKTEST */
244 /* copy a string up to some (non-backslashed) delimiter, if any */
247 cpytill(to,from,fromend,delim,retlen)
250 register char *fromend;
256 for (; from < fromend; from++,to++) {
258 if (from[1] == delim)
260 else if (from[1] == '\\')
263 else if (*from == delim)
268 *retlen = to - origto;
272 /* return ptr to little string in big string, NULL if not found */
273 /* This routine was donated by Corey Satten. */
278 register char *little;
280 register char *s, *x;
291 for (x=big,s=little; *s; /**/ ) {
305 /* same as instr but allow embedded nulls */
308 ninstr(big, bigend, little, lend)
310 register char *bigend;
314 register char *s, *x;
315 register int first = *little;
316 register char *littleend = lend;
318 if (!first && little > littleend)
320 bigend -= littleend - little++;
321 while (big <= bigend) {
324 for (x=big,s=little; s < littleend; /**/ ) {
336 /* reverse of the above--find last substring */
339 rninstr(big, bigend, little, lend)
345 register char *bigbeg;
346 register char *s, *x;
347 register int first = *little;
348 register char *littleend = lend;
350 if (!first && little > littleend)
353 big = bigend - (littleend - little++);
354 while (big >= bigbeg) {
357 for (x=big+2,s=little; s < littleend; /**/ ) {
369 unsigned char fold[] = {
370 0, 1, 2, 3, 4, 5, 6, 7,
371 8, 9, 10, 11, 12, 13, 14, 15,
372 16, 17, 18, 19, 20, 21, 22, 23,
373 24, 25, 26, 27, 28, 29, 30, 31,
374 32, 33, 34, 35, 36, 37, 38, 39,
375 40, 41, 42, 43, 44, 45, 46, 47,
376 48, 49, 50, 51, 52, 53, 54, 55,
377 56, 57, 58, 59, 60, 61, 62, 63,
378 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
379 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
380 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
381 'x', 'y', 'z', 91, 92, 93, 94, 95,
382 96, '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', 123, 124, 125, 126, 127,
386 128, 129, 130, 131, 132, 133, 134, 135,
387 136, 137, 138, 139, 140, 141, 142, 143,
388 144, 145, 146, 147, 148, 149, 150, 151,
389 152, 153, 154, 155, 156, 157, 158, 159,
390 160, 161, 162, 163, 164, 165, 166, 167,
391 168, 169, 170, 171, 172, 173, 174, 175,
392 176, 177, 178, 179, 180, 181, 182, 183,
393 184, 185, 186, 187, 188, 189, 190, 191,
394 192, 193, 194, 195, 196, 197, 198, 199,
395 200, 201, 202, 203, 204, 205, 206, 207,
396 208, 209, 210, 211, 212, 213, 214, 215,
397 216, 217, 218, 219, 220, 221, 222, 223,
398 224, 225, 226, 227, 228, 229, 230, 231,
399 232, 233, 234, 235, 236, 237, 238, 239,
400 240, 241, 242, 243, 244, 245, 246, 247,
401 248, 249, 250, 251, 252, 253, 254, 255
404 static unsigned char freq[] = {
405 1, 2, 84, 151, 154, 155, 156, 157,
406 165, 246, 250, 3, 158, 7, 18, 29,
407 40, 51, 62, 73, 85, 96, 107, 118,
408 129, 140, 147, 148, 149, 150, 152, 153,
409 255, 182, 224, 205, 174, 176, 180, 217,
410 233, 232, 236, 187, 235, 228, 234, 226,
411 222, 219, 211, 195, 188, 193, 185, 184,
412 191, 183, 201, 229, 181, 220, 194, 162,
413 163, 208, 186, 202, 200, 218, 198, 179,
414 178, 214, 166, 170, 207, 199, 209, 206,
415 204, 160, 212, 216, 215, 192, 175, 173,
416 243, 172, 161, 190, 203, 189, 164, 230,
417 167, 248, 227, 244, 242, 255, 241, 231,
418 240, 253, 169, 210, 245, 237, 249, 247,
419 239, 168, 252, 251, 254, 238, 223, 221,
420 213, 225, 177, 197, 171, 196, 159, 4,
421 5, 6, 8, 9, 10, 11, 12, 13,
422 14, 15, 16, 17, 19, 20, 21, 22,
423 23, 24, 25, 26, 27, 28, 30, 31,
424 32, 33, 34, 35, 36, 37, 38, 39,
425 41, 42, 43, 44, 45, 46, 47, 48,
426 49, 50, 52, 53, 54, 55, 56, 57,
427 58, 59, 60, 61, 63, 64, 65, 66,
428 67, 68, 69, 70, 71, 72, 74, 75,
429 76, 77, 78, 79, 80, 81, 82, 83,
430 86, 87, 88, 89, 90, 91, 92, 93,
431 94, 95, 97, 98, 99, 100, 101, 102,
432 103, 104, 105, 106, 108, 109, 110, 111,
433 112, 113, 114, 115, 116, 117, 119, 120,
434 121, 122, 123, 124, 125, 126, 127, 128,
435 130, 131, 132, 133, 134, 135, 136, 137,
436 138, 139, 141, 142, 143, 144, 145, 146
440 fbmcompile(str, iflag)
444 register unsigned char *s;
445 register unsigned char *table;
447 register int len = str->str_cur;
449 unsigned int frequency = 256;
451 Str_Grow(str,len+258);
453 table = (unsigned char*)(str->str_ptr + len + 1);
455 table = Null(unsigned char*);
458 for (i = 0; i < 256; i++) {
463 while (s >= (unsigned char*)(str->str_ptr))
466 if (table[*s] == len) {
469 table[*s] = table[fold[*s]] = i;
483 str->str_pok |= SP_FBM; /* deep magic */
486 s = (unsigned char*)(str->str_ptr); /* deeper magic */
488 s = Null(unsigned char*);
491 register unsigned int tmp, foldtmp;
492 str->str_pok |= SP_CASEFOLD;
493 for (i = 0; i < len; i++) {
495 foldtmp=freq[fold[s[i]]];
496 if (tmp < frequency && foldtmp < frequency) {
498 /* choose most frequent among the two */
499 frequency = (tmp > foldtmp) ? tmp : foldtmp;
504 for (i = 0; i < len; i++) {
505 if (freq[s[i]] < frequency) {
507 frequency = freq[s[i]];
511 str->str_rare = s[rarest];
512 str->str_state = rarest;
515 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
520 fbminstr(big, bigend, littlestr)
522 register unsigned char *bigend;
525 register unsigned char *s;
527 register int littlelen;
528 register unsigned char *little;
529 register unsigned char *table;
530 register unsigned char *olds;
531 register unsigned char *oldlittle;
534 if (!(littlestr->str_pok & SP_FBM))
535 return ninstr((char*)big,(char*)bigend,
536 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
539 littlelen = littlestr->str_cur;
541 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
542 if (littlelen > bigend - big)
544 little = (unsigned char*)littlestr->str_ptr;
545 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
546 big = bigend - littlelen; /* just start near end */
547 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
551 s = bigend - littlelen;
552 if (*s == *little && bcmp(s,little,littlelen)==0)
553 return (char*)s; /* how sweet it is */
554 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n') {
556 if (*s == *little && bcmp(s,little,littlelen)==0)
562 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
564 table = Null(unsigned char*);
566 if (--littlelen >= bigend - big)
569 oldlittle = little = table - 2;
570 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
573 if (tmp = table[*s]) {
575 if (bigend - s > tmp) {
580 if ((s += tmp) < bigend)
586 tmp = littlelen; /* less expensive than calling strncmp() */
589 if (*--s == *--little || fold[*s] == *little)
591 s = olds + 1; /* here we pay the price for failure */
593 if (s < bigend) /* fake up continue to outer loop */
606 if (tmp = table[*s]) {
608 if (bigend - s > tmp) {
613 if ((s += tmp) < bigend)
619 tmp = littlelen; /* less expensive than calling strncmp() */
622 if (*--s == *--little)
624 s = olds + 1; /* here we pay the price for failure */
626 if (s < bigend) /* fake up continue to outer loop */
640 screaminstr(bigstr, littlestr)
644 register unsigned char *s, *x;
645 register unsigned char *big;
647 register int previous;
649 register unsigned char *little;
650 register unsigned char *bigend;
651 register unsigned char *littleend;
653 if ((pos = screamfirst[littlestr->str_rare]) < 0)
656 little = (unsigned char *)(littlestr->str_ptr);
658 little = Null(unsigned char *);
660 littleend = little + littlestr->str_cur;
662 previous = littlestr->str_state;
664 big = (unsigned char *)(bigstr->str_ptr);
666 big = Null(unsigned char*);
668 bigend = big + bigstr->str_cur;
670 while (pos < previous) {
672 if (!(pos += screamnext[pos]))
676 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
678 if (big[pos] != first && big[pos] != fold[first])
680 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
683 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
690 return (char *)(big+pos);
696 pos += screamnext[pos] /* does this goof up anywhere? */
704 if (big[pos] != first)
706 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
716 return (char *)(big+pos);
722 pos += screamnext[pos]
731 /* copy a string to a safe spot */
737 register char *newaddr;
739 New(902,newaddr,strlen(str)+1,char);
740 (void)strcpy(newaddr,str);
744 /* same thing but with a known length */
751 register char *newaddr;
753 New(903,newaddr,len+1,char);
754 (void)bcopy(str,newaddr,len); /* might not be null terminated */
755 newaddr[len] = '\0'; /* is now */
759 /* grow a static string to at least a certain length */
762 growstr(strptr,curlen,newlen)
767 if (newlen > *curlen) { /* need more room? */
769 Renew(*strptr,newlen,char);
771 New(905,*strptr,newlen,char);
778 mess(pat,a1,a2,a3,a4)
785 (void)sprintf(s,pat,a1,a2,a3,a4);
788 if (curcmd->c_line) {
789 (void)sprintf(s," at %s line %ld",
790 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
794 stab_io(last_in_stab) &&
795 stab_io(last_in_stab)->lines ) {
796 (void)sprintf(s,", <%s> line %ld",
797 last_in_stab == argvstab ? "" : stab_name(last_in_stab),
798 (long)stab_io(last_in_stab)->lines);
801 (void)strcpy(s,".\n");
806 fatal(pat,a1,a2,a3,a4)
811 extern char *e_tmpname;
814 mess(pat,a1,a2,a3,a4);
816 str_set(stab_val(stabent("@",TRUE)),buf);
818 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
819 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
822 deb("(Skipping label #%d %s)\n",loop_ptr,
823 loop_stack[loop_ptr].loop_label);
830 deb("(Found label #%d %s)\n",loop_ptr,
831 loop_stack[loop_ptr].loop_label);
836 fatal("Bad label: %s", tmps);
838 longjmp(loop_stack[loop_ptr].loop_env, 1);
841 (void)fflush(stderr);
843 (void)UNLINK(e_tmpname);
845 exit(errno?errno:(statusvalue?statusvalue:255));
849 warn(pat,a1,a2,a3,a4)
853 mess(pat,a1,a2,a3,a4);
861 (void)fflush(stderr);
880 pat = va_arg(args, char *);
882 (void) vsprintf(s,pat,args);
886 if (curcmd->c_line) {
887 (void)sprintf(s," at %s line %ld",
888 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
892 stab_io(last_in_stab) &&
893 stab_io(last_in_stab)->lines ) {
894 (void)sprintf(s,", <%s> line %ld",
895 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
896 (long)stab_io(last_in_stab)->lines);
899 (void)strcpy(s,".\n");
909 extern char *e_tmpname;
920 str_set(stab_val(stabent("@",TRUE)),buf);
922 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
923 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
926 deb("(Skipping label #%d %s)\n",loop_ptr,
927 loop_stack[loop_ptr].loop_label);
934 deb("(Found label #%d %s)\n",loop_ptr,
935 loop_stack[loop_ptr].loop_label);
940 fatal("Bad label: %s", tmps);
942 longjmp(loop_stack[loop_ptr].loop_env, 1);
945 (void)fflush(stderr);
947 (void)UNLINK(e_tmpname);
949 exit((int)(errno?errno:(statusvalue?statusvalue:255)));
973 (void)fflush(stderr);
977 static bool firstsetenv = TRUE;
978 extern char **environ;
984 register int i=envix(nam); /* where does it go? */
988 environ[i] = environ[i+1];
993 if (!environ[i]) { /* does not exist yet */
994 if (firstsetenv) { /* need we copy environment? */
998 New(901,tmpenv, i+2, char*);
1000 for (j=0; j<i; j++) /* copy environment */
1001 tmpenv[j] = environ[j];
1002 environ = tmpenv; /* tell exec where it is now */
1005 Renew(environ, i+2, char*); /* just expand it a bit */
1006 environ[i+1] = Nullch; /* make sure it's null terminated */
1008 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
1009 /* this may or may not be in */
1010 /* the old environ structure */
1012 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
1014 /* MS-DOS requires environment variable names to be in uppercase */
1015 strcpy(environ[i],nam); strupr(environ[i],nam);
1016 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
1024 register int i, len = strlen(nam);
1026 for (i = 0; environ[i]; i++) {
1027 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
1028 break; /* strnEQ must come first to avoid */
1029 } /* potential SEGV's */
1034 unlnk(f) /* unlink all versions of a file */
1039 for (i = 0; unlink(f) >= 0; i++) ;
1048 register char *from;
1083 vsprintf(dest, pat, args)
1084 char *dest, *pat, *args;
1088 fakebuf._ptr = dest;
1089 fakebuf._cnt = 32767;
1090 fakebuf._flag = _IOWRT|_IOSTRG;
1091 _doprnt(pat, args, &fakebuf); /* what a kludge */
1092 (void)putc('\0', &fakebuf);
1096 return 0; /* perl doesn't use return value */
1102 vfprintf(fd, pat, args)
1106 _doprnt(pat, args, fd);
1107 return 0; /* wrong, but perl doesn't use the return value */
1110 #endif /* VPRINTF */
1111 #endif /* VARARGS */
1114 #if BYTEORDER != 0x4321
1119 #if (BYTEORDER & 1) == 0
1122 result = ((s & 255) << 8) + ((s >> 8) & 255);
1135 char c[sizeof(long)];
1138 #if BYTEORDER == 0x1234
1139 u.c[0] = (l >> 24) & 255;
1140 u.c[1] = (l >> 16) & 255;
1141 u.c[2] = (l >> 8) & 255;
1145 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1146 fatal("Unknown BYTEORDER\n");
1151 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1152 u.c[o & 0xf] = (l >> s) & 255;
1165 char c[sizeof(long)];
1168 #if BYTEORDER == 0x1234
1169 u.c[0] = (l >> 24) & 255;
1170 u.c[1] = (l >> 16) & 255;
1171 u.c[2] = (l >> 8) & 255;
1175 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1176 fatal("Unknown BYTEORDER\n");
1183 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1184 l |= (u.c[o & 0xf] & 255) << s;
1191 #endif /* BYTEORDER != 0x4321 */
1201 register int this, that;
1204 int doexec = strNE(cmd,"-");
1208 this = (*mode == 'w');
1210 while ((pid = (doexec?vfork():fork())) < 0) {
1211 if (errno != EAGAIN) {
1214 fatal("Can't fork");
1223 if (p[THIS] != (*mode == 'r')) {
1224 dup2(p[THIS], *mode == 'r');
1228 #if !defined(FCNTL) || !defined(F_SETFD)
1234 for (fd = 3; fd < NOFILE; fd++)
1237 do_exec(cmd); /* may or may not use the shell */
1240 if (tmpstab = stabent("$",allstabs))
1241 str_numset(STAB_STR(tmpstab),(double)getpid());
1243 hclear(pidstatus); /* we have no children */
1248 do_execfree(); /* free any memory malloced by child on vfork */
1250 if (p[that] < p[this]) {
1251 dup2(p[this], p[that]);
1255 str = afetch(fdpid,p[this],TRUE);
1256 str->str_u.str_useful = pid;
1258 return fdopen(p[this], mode);
1267 struct stat tmpstatbuf;
1269 fprintf(stderr,"%s", s);
1270 for (fd = 0; fd < 32; fd++) {
1271 if (fstat(fd,&tmpstatbuf) >= 0)
1272 fprintf(stderr," %d",fd);
1274 fprintf(stderr,"\n");
1283 #if defined(FCNTL) && defined(F_DUPFD)
1285 fcntl(oldfd, F_DUPFD, newfd);
1292 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1295 close(fdtmp[--fdx]);
1306 void (*hstat)(), (*istat)(), (*qstat)();
1308 int (*hstat)(), (*istat)(), (*qstat)();
1314 str = afetch(fdpid,fileno(ptr),TRUE);
1315 astore(fdpid,fileno(ptr),Nullstr);
1317 pid = (int)str->str_u.str_useful;
1318 hstat = signal(SIGHUP, SIG_IGN);
1319 istat = signal(SIGINT, SIG_IGN);
1320 qstat = signal(SIGQUIT, SIG_IGN);
1321 pid = wait4pid(pid, &status, 0);
1322 signal(SIGHUP, hstat);
1323 signal(SIGINT, istat);
1324 signal(SIGQUIT, qstat);
1325 return(pid < 0 ? pid : status);
1329 wait4pid(pid,statusp,flags)
1341 return wait4(pid,statusp,flags,Null(struct rusage *));
1344 return waitpid(pid,statusp,flags);
1347 sprintf(spid, "%d", pid);
1348 str = hfetch(pidstatus,spid,strlen(spid),FALSE);
1349 if (str != &str_undef) {
1350 *statusp = (int)str->str_u.str_useful;
1351 hdelete(pidstatus,spid,strlen(spid));
1358 hiterinit(pidstatus);
1359 if (entry = hiternext(pidstatus)) {
1360 pid = atoi(hiterkey(entry,statusp));
1361 str = hiterval(entry);
1362 *statusp = (int)str->str_u.str_useful;
1363 sprintf(spid, "%d", pid);
1364 hdelete(pidstatus,spid,strlen(spid));
1369 fatal("Can't do waitpid with flags");
1375 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1376 pidgone(result,*statusp);
1390 #if defined(WAIT4) || defined(WAITPID)
1395 sprintf(spid, "%d", pid);
1396 str = hfetch(pidstatus,spid,strlen(spid),TRUE);
1397 str->str_u.str_useful = status;
1404 register unsigned char *s1;
1405 register unsigned char *s2;
1411 if (tmp = *s1++ - *s2++)
1419 repeatcpy(to,from,len,count)
1421 register char *from;
1426 register char *frombase = from;
1434 while (count-- > 0) {
1435 for (todo = len; todo > 0; todo--) {
1442 #ifndef CASTNEGFLOAT
1450 return (unsigned long)f;
1452 return (unsigned long)along;
1462 char *fa = rindex(a,'/');
1463 char *fb = rindex(b,'/');
1464 struct stat tmpstatbuf1;
1465 struct stat tmpstatbuf2;
1467 #define MAXPATHLEN 1024
1469 char tmpbuf[MAXPATHLEN+1];
1484 strncpy(tmpbuf, a, fa - a);
1485 if (stat(tmpbuf, &tmpstatbuf1) < 0)
1490 strncpy(tmpbuf, b, fb - b);
1491 if (stat(tmpbuf, &tmpstatbuf2) < 0)
1493 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1494 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1496 #endif /* !RENAME */