1 /* $RCSfile: util.c,v $$Revision: 4.0.1.5 $$Date: 92/06/08 16:08:37 $
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.5 92/06/08 16:08:37 lwall
10 * patch20: removed implicit int declarations on functions
11 * patch20: Perl now distinguishes overlapped copies from non-overlapped
12 * patch20: fixed confusion between a *var's real name and its effective name
13 * patch20: bcopy() and memcpy() now tested for overlap safety
14 * patch20: added Atari ST portability
16 * Revision 4.0.1.4 91/11/11 16:48:54 lwall
17 * patch19: study was busted by 4.018
18 * patch19: added little-endian pack/unpack options
20 * Revision 4.0.1.3 91/11/05 19:18:26 lwall
21 * patch11: safe malloc code now integrated into Perl's malloc when possible
22 * patch11: index("little", "longer string") could visit faraway places
23 * patch11: warn '-' x 10000 dumped core
24 * patch11: forked exec on non-existent program now issues a warning
26 * Revision 4.0.1.2 91/06/07 12:10:42 lwall
27 * patch4: new copyright notice
28 * patch4: made some allowances for "semi-standard" C
29 * patch4: index() could blow up searching for null string
30 * patch4: taintchecks could improperly modify parent in vfork()
31 * patch4: exec would close files even if you cleared close-on-exec flag
33 * Revision 4.0.1.1 91/04/12 09:19:25 lwall
34 * patch1: random cleanup in cpp namespace
36 * Revision 4.0 91/03/20 01:56:39 lwall
45 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
61 # include <sys/file.h>
68 static char nomem[] = "Out of memory!\n";
70 /* paranoid version of malloc */
76 /* NOTE: Do not call the next three routines directly. Use the macros
77 * in handy.h, so that we can easily redefine everything to do tracking of
78 * allocated hunks back to the original New to track down any memory leaks.
92 #endif /* ! STANDARD_C */
96 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
102 fatal("panic: malloc");
104 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
106 # if !(defined(I286) || defined(atarist))
108 fprintf(stderr,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
111 fprintf(stderr,"0x%lx: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
119 fputs(nomem,stderr) FLUSH;
128 /* paranoid version of realloc */
131 saferealloc(where,size)
142 #endif /* ! STANDARD_C */
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 */
158 # if !(defined(I286) || defined(atarist))
160 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
161 fprintf(stderr,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
165 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
166 fprintf(stderr,"0x%lx: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
175 fputs(nomem,stderr) FLUSH;
184 /* safe version of free */
191 # if !(defined(I286) || defined(atarist))
193 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
196 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
205 #endif /* !safemalloc */
209 #define ALIGN sizeof(long)
216 register char *where;
218 where = safemalloc(size + ALIGN);
222 return where + ALIGN;
226 safexrealloc(where,size)
230 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
242 x = where[0] + 100 * where[1];
252 for (i = 0; i < MAXXCOUNT; i++) {
253 if (xcount[i] > lastxcount[i]) {
254 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
255 lastxcount[i] = xcount[i];
260 #endif /* LEAKTEST */
262 /* copy a string up to some (non-backslashed) delimiter, if any */
265 cpytill(to,from,fromend,delim,retlen)
268 register char *fromend;
274 for (; from < fromend; from++,to++) {
276 if (from[1] == delim)
278 else if (from[1] == '\\')
281 else if (*from == delim)
286 *retlen = to - origto;
290 /* return ptr to little string in big string, NULL if not found */
291 /* This routine was donated by Corey Satten. */
296 register char *little;
298 register char *s, *x;
309 for (x=big,s=little; *s; /**/ ) {
323 /* same as instr but allow embedded nulls */
326 ninstr(big, bigend, little, lend)
328 register char *bigend;
332 register char *s, *x;
333 register int first = *little;
334 register char *littleend = lend;
336 if (!first && little > littleend)
338 if (bigend - big < littleend - little)
340 bigend -= littleend - little++;
341 while (big <= bigend) {
344 for (x=big,s=little; s < littleend; /**/ ) {
356 /* reverse of the above--find last substring */
359 rninstr(big, bigend, little, lend)
365 register char *bigbeg;
366 register char *s, *x;
367 register int first = *little;
368 register char *littleend = lend;
370 if (!first && little > littleend)
373 big = bigend - (littleend - little++);
374 while (big >= bigbeg) {
377 for (x=big+2,s=little; s < littleend; /**/ ) {
389 unsigned char fold[] = {
390 0, 1, 2, 3, 4, 5, 6, 7,
391 8, 9, 10, 11, 12, 13, 14, 15,
392 16, 17, 18, 19, 20, 21, 22, 23,
393 24, 25, 26, 27, 28, 29, 30, 31,
394 32, 33, 34, 35, 36, 37, 38, 39,
395 40, 41, 42, 43, 44, 45, 46, 47,
396 48, 49, 50, 51, 52, 53, 54, 55,
397 56, 57, 58, 59, 60, 61, 62, 63,
398 64, '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', 91, 92, 93, 94, 95,
402 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
403 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
404 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
405 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
406 128, 129, 130, 131, 132, 133, 134, 135,
407 136, 137, 138, 139, 140, 141, 142, 143,
408 144, 145, 146, 147, 148, 149, 150, 151,
409 152, 153, 154, 155, 156, 157, 158, 159,
410 160, 161, 162, 163, 164, 165, 166, 167,
411 168, 169, 170, 171, 172, 173, 174, 175,
412 176, 177, 178, 179, 180, 181, 182, 183,
413 184, 185, 186, 187, 188, 189, 190, 191,
414 192, 193, 194, 195, 196, 197, 198, 199,
415 200, 201, 202, 203, 204, 205, 206, 207,
416 208, 209, 210, 211, 212, 213, 214, 215,
417 216, 217, 218, 219, 220, 221, 222, 223,
418 224, 225, 226, 227, 228, 229, 230, 231,
419 232, 233, 234, 235, 236, 237, 238, 239,
420 240, 241, 242, 243, 244, 245, 246, 247,
421 248, 249, 250, 251, 252, 253, 254, 255
424 static unsigned char freq[] = {
425 1, 2, 84, 151, 154, 155, 156, 157,
426 165, 246, 250, 3, 158, 7, 18, 29,
427 40, 51, 62, 73, 85, 96, 107, 118,
428 129, 140, 147, 148, 149, 150, 152, 153,
429 255, 182, 224, 205, 174, 176, 180, 217,
430 233, 232, 236, 187, 235, 228, 234, 226,
431 222, 219, 211, 195, 188, 193, 185, 184,
432 191, 183, 201, 229, 181, 220, 194, 162,
433 163, 208, 186, 202, 200, 218, 198, 179,
434 178, 214, 166, 170, 207, 199, 209, 206,
435 204, 160, 212, 216, 215, 192, 175, 173,
436 243, 172, 161, 190, 203, 189, 164, 230,
437 167, 248, 227, 244, 242, 255, 241, 231,
438 240, 253, 169, 210, 245, 237, 249, 247,
439 239, 168, 252, 251, 254, 238, 223, 221,
440 213, 225, 177, 197, 171, 196, 159, 4,
441 5, 6, 8, 9, 10, 11, 12, 13,
442 14, 15, 16, 17, 19, 20, 21, 22,
443 23, 24, 25, 26, 27, 28, 30, 31,
444 32, 33, 34, 35, 36, 37, 38, 39,
445 41, 42, 43, 44, 45, 46, 47, 48,
446 49, 50, 52, 53, 54, 55, 56, 57,
447 58, 59, 60, 61, 63, 64, 65, 66,
448 67, 68, 69, 70, 71, 72, 74, 75,
449 76, 77, 78, 79, 80, 81, 82, 83,
450 86, 87, 88, 89, 90, 91, 92, 93,
451 94, 95, 97, 98, 99, 100, 101, 102,
452 103, 104, 105, 106, 108, 109, 110, 111,
453 112, 113, 114, 115, 116, 117, 119, 120,
454 121, 122, 123, 124, 125, 126, 127, 128,
455 130, 131, 132, 133, 134, 135, 136, 137,
456 138, 139, 141, 142, 143, 144, 145, 146
460 fbmcompile(str, iflag)
464 register unsigned char *s;
465 register unsigned char *table;
466 register unsigned int i;
467 register unsigned int len = str->str_cur;
469 unsigned int frequency = 256;
471 Str_Grow(str,len+258);
473 table = (unsigned char*)(str->str_ptr + len + 1);
475 table = Null(unsigned char*);
478 for (i = 0; i < 256; i++) {
483 while (s >= (unsigned char*)(str->str_ptr))
486 if (table[*s] == len) {
489 table[*s] = table[fold[*s]] = i;
503 str->str_pok |= SP_FBM; /* deep magic */
506 s = (unsigned char*)(str->str_ptr); /* deeper magic */
508 s = Null(unsigned char*);
511 register unsigned int tmp, foldtmp;
512 str->str_pok |= SP_CASEFOLD;
513 for (i = 0; i < len; i++) {
515 foldtmp=freq[fold[s[i]]];
516 if (tmp < frequency && foldtmp < frequency) {
518 /* choose most frequent among the two */
519 frequency = (tmp > foldtmp) ? tmp : foldtmp;
524 for (i = 0; i < len; i++) {
525 if (freq[s[i]] < frequency) {
527 frequency = freq[s[i]];
531 str->str_rare = s[rarest];
532 str->str_state = rarest;
535 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
540 fbminstr(big, bigend, littlestr)
542 register unsigned char *bigend;
545 register unsigned char *s;
547 register int littlelen;
548 register unsigned char *little;
549 register unsigned char *table;
550 register unsigned char *olds;
551 register unsigned char *oldlittle;
554 if (!(littlestr->str_pok & SP_FBM)) {
555 if (!littlestr->str_ptr)
557 return ninstr((char*)big,(char*)bigend,
558 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
562 littlelen = littlestr->str_cur;
564 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
565 if (littlelen > bigend - big)
567 little = (unsigned char*)littlestr->str_ptr;
568 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
569 big = bigend - littlelen; /* just start near end */
570 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
574 s = bigend - littlelen;
575 if (*s == *little && bcmp(s,little,littlelen)==0)
576 return (char*)s; /* how sweet it is */
577 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
580 if (*s == *little && bcmp(s,little,littlelen)==0)
586 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
588 table = Null(unsigned char*);
590 if (--littlelen >= bigend - big)
593 oldlittle = little = table - 2;
594 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
598 if (tmp = table[*s]) {
600 if (bigend - s > tmp) {
605 if ((s += tmp) < bigend)
611 tmp = littlelen; /* less expensive than calling strncmp() */
614 if (*--s == *--little || fold[*s] == *little)
616 s = olds + 1; /* here we pay the price for failure */
618 if (s < bigend) /* fake up continue to outer loop */
632 if (tmp = table[*s]) {
634 if (bigend - s > tmp) {
639 if ((s += tmp) < bigend)
645 tmp = littlelen; /* less expensive than calling strncmp() */
648 if (*--s == *--little)
650 s = olds + 1; /* here we pay the price for failure */
652 if (s < bigend) /* fake up continue to outer loop */
666 screaminstr(bigstr, littlestr)
670 register unsigned char *s, *x;
671 register unsigned char *big;
673 register int previous;
675 register unsigned char *little;
676 register unsigned char *bigend;
677 register unsigned char *littleend;
679 if ((pos = screamfirst[littlestr->str_rare]) < 0)
682 little = (unsigned char *)(littlestr->str_ptr);
684 little = Null(unsigned char *);
686 littleend = little + littlestr->str_cur;
688 previous = littlestr->str_state;
690 big = (unsigned char *)(bigstr->str_ptr);
692 big = Null(unsigned char*);
694 bigend = big + bigstr->str_cur;
695 while (pos < previous) {
697 if (!(pos += screamnext[pos]))
702 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
704 if (big[pos-previous] != first && big[pos-previous] != fold[first])
706 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
709 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
716 return (char *)(big+pos-previous);
722 pos += screamnext[pos] /* does this goof up anywhere? */
730 if (big[pos-previous] != first)
732 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
742 return (char *)(big+pos-previous);
748 pos += screamnext[pos]
754 #else /* !POINTERRIGOR */
756 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
758 if (big[pos] != first && big[pos] != fold[first])
760 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
763 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
770 return (char *)(big+pos);
776 pos += screamnext[pos] /* does this goof up anywhere? */
784 if (big[pos] != first)
786 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
796 return (char *)(big+pos);
802 pos += screamnext[pos]
808 #endif /* POINTERRIGOR */
812 /* copy a string to a safe spot */
818 register char *newaddr;
820 New(902,newaddr,strlen(str)+1,char);
821 (void)strcpy(newaddr,str);
825 /* same thing but with a known length */
832 register char *newaddr;
834 New(903,newaddr,len+1,char);
835 Copy(str,newaddr,len,char); /* might not be null terminated */
836 newaddr[len] = '\0'; /* is now */
840 /* grow a static string to at least a certain length */
843 growstr(strptr,curlen,newlen)
848 if (newlen > *curlen) { /* need more room? */
850 Renew(*strptr,newlen,char);
852 New(905,*strptr,newlen,char);
860 mess(pat,a1,a2,a3,a4)
865 int usermess = strEQ(pat,"%s");
870 tmpstr = str_mortal(&str_undef);
871 str_set(tmpstr, (char*)a1);
872 *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
875 (void)sprintf(s,pat,a1,a2,a3,a4);
880 if (curcmd->c_line) {
881 (void)sprintf(s," at %s line %ld",
882 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
886 stab_io(last_in_stab) &&
887 stab_io(last_in_stab)->lines ) {
888 (void)sprintf(s,", <%s> line %ld",
889 last_in_stab == argvstab ? "" : stab_ename(last_in_stab),
890 (long)stab_io(last_in_stab)->lines);
893 (void)strcpy(s,".\n");
895 str_cat(tmpstr,buf+1);
898 return tmpstr->str_ptr;
904 void fatal(pat,a1,a2,a3,a4)
909 extern char *e_tmpname;
913 message = mess(pat,a1,a2,a3,a4);
915 str_set(stab_val(stabent("@",TRUE)),message);
917 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
918 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
921 deb("(Skipping label #%d %s)\n",loop_ptr,
922 loop_stack[loop_ptr].loop_label);
929 deb("(Found label #%d %s)\n",loop_ptr,
930 loop_stack[loop_ptr].loop_label);
935 fatal("Bad label: %s", tmps);
937 longjmp(loop_stack[loop_ptr].loop_env, 1);
939 fputs(message,stderr);
940 (void)fflush(stderr);
942 (void)UNLINK(e_tmpname);
944 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
948 void warn(pat,a1,a2,a3,a4)
954 message = mess(pat,a1,a2,a3,a4);
955 fputs(message,stderr);
962 (void)fflush(stderr);
985 pat = va_arg(args, char *);
988 usermess = strEQ(pat, "%s");
990 tmpstr = str_mortal(&str_undef);
991 str_set(tmpstr, va_arg(args, char *));
992 *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
995 (void) vsprintf(s,pat,args);
1000 if (curcmd->c_line) {
1001 (void)sprintf(s," at %s line %ld",
1002 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
1006 stab_io(last_in_stab) &&
1007 stab_io(last_in_stab)->lines ) {
1008 (void)sprintf(s,", <%s> line %ld",
1009 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
1010 (long)stab_io(last_in_stab)->lines);
1013 (void)strcpy(s,".\n");
1015 str_cat(tmpstr,buf+1);
1019 return tmpstr->str_ptr;
1025 void fatal(va_alist)
1030 extern char *e_tmpname;
1039 message = mess(args);
1042 str_set(stab_val(stabent("@",TRUE)),message);
1044 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
1045 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
1048 deb("(Skipping label #%d %s)\n",loop_ptr,
1049 loop_stack[loop_ptr].loop_label);
1056 deb("(Found label #%d %s)\n",loop_ptr,
1057 loop_stack[loop_ptr].loop_label);
1062 fatal("Bad label: %s", tmps);
1064 longjmp(loop_stack[loop_ptr].loop_env, 1);
1066 fputs(message,stderr);
1067 (void)fflush(stderr);
1069 (void)UNLINK(e_tmpname);
1071 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
1086 message = mess(args);
1089 fputs(message,stderr);
1096 (void)fflush(stderr);
1104 register int i=envix(nam); /* where does it go? */
1106 if (environ == origenviron) { /* need we copy environment? */
1112 for (max = i; environ[max]; max++) ;
1113 New(901,tmpenv, max+2, char*);
1114 for (j=0; j<max; j++) /* copy environment */
1115 tmpenv[j] = savestr(environ[j]);
1116 tmpenv[max] = Nullch;
1117 environ = tmpenv; /* tell exec where it is now */
1120 while (environ[i]) {
1121 environ[i] = environ[i+1];
1126 if (!environ[i]) { /* does not exist yet */
1127 Renew(environ, i+2, char*); /* just expand it a bit */
1128 environ[i+1] = Nullch; /* make sure it's null terminated */
1131 Safefree(environ[i]);
1132 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
1134 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
1136 /* MS-DOS requires environment variable names to be in uppercase */
1137 /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
1138 * some utilities and applications may break because they only look
1139 * for upper case strings. (Fixed strupr() bug here.)]
1141 strcpy(environ[i],nam); strupr(environ[i]);
1142 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
1150 register int i, len = strlen(nam);
1152 for (i = 0; environ[i]; i++) {
1153 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
1154 break; /* strnEQ must come first to avoid */
1155 } /* potential SEGV's */
1161 unlnk(f) /* unlink all versions of a file */
1166 for (i = 0; unlink(f) >= 0; i++) ;
1171 #if !defined(HAS_BCOPY) || !defined(SAFE_BCOPY)
1173 my_bcopy(from,to,len)
1174 register char *from;
1180 if (from - to >= 0) {
1194 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
1210 my_memcmp(s1,s2,len)
1211 register unsigned char *s1;
1212 register unsigned char *s2;
1218 if (tmp = *s1++ - *s2++)
1223 #endif /* HAS_MEMCMP */
1233 vsprintf(dest, pat, args)
1234 char *dest, *pat, *args;
1238 fakebuf._ptr = dest;
1239 fakebuf._cnt = 32767;
1243 fakebuf._flag = _IOWRT|_IOSTRG;
1244 _doprnt(pat, args, &fakebuf); /* what a kludge */
1245 (void)putc('\0', &fakebuf);
1249 return 0; /* perl doesn't use return value */
1255 vfprintf(fd, pat, args)
1259 _doprnt(pat, args, fd);
1260 return 0; /* wrong, but perl doesn't use the return value */
1263 #endif /* HAS_VPRINTF */
1264 #endif /* I_VARARGS */
1267 * I think my_swap(), htonl() and ntohl() have never been used.
1268 * perl.h contains last-chance references to my_swap(), my_htonl()
1269 * and my_ntohl(). I presume these are the intended functions;
1270 * but htonl() and ntohl() have the wrong names. There are no
1271 * functions my_htonl() and my_ntohl() defined anywhere.
1275 #if BYTEORDER != 0x4321
1280 #if (BYTEORDER & 1) == 0
1283 result = ((s & 255) << 8) + ((s >> 8) & 255);
1296 char c[sizeof(long)];
1299 #if BYTEORDER == 0x1234
1300 u.c[0] = (l >> 24) & 255;
1301 u.c[1] = (l >> 16) & 255;
1302 u.c[2] = (l >> 8) & 255;
1306 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1307 fatal("Unknown BYTEORDER\n");
1312 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1313 u.c[o & 0xf] = (l >> s) & 255;
1326 char c[sizeof(long)];
1329 #if BYTEORDER == 0x1234
1330 u.c[0] = (l >> 24) & 255;
1331 u.c[1] = (l >> 16) & 255;
1332 u.c[2] = (l >> 8) & 255;
1336 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1337 fatal("Unknown BYTEORDER\n");
1344 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1345 l |= (u.c[o & 0xf] & 255) << s;
1352 #endif /* BYTEORDER != 0x4321 */
1356 * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
1357 * If these functions are defined,
1358 * the BYTEORDER is neither 0x1234 nor 0x4321.
1359 * However, this is not assumed.
1363 #define HTOV(name,type) \
1370 char c[sizeof(type)]; \
1374 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1375 u.c[i] = (n >> s) & 0xFF; \
1380 #define VTOH(name,type) \
1387 char c[sizeof(type)]; \
1393 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1394 n += (u.c[i] & 0xFF) << s; \
1399 #if defined(HAS_HTOVS) && !defined(htovs)
1402 #if defined(HAS_HTOVL) && !defined(htovl)
1405 #if defined(HAS_VTOHS) && !defined(vtohs)
1408 #if defined(HAS_VTOHL) && !defined(vtohl)
1419 register int this, that;
1422 int doexec = strNE(cmd,"-");
1426 this = (*mode == 'w');
1431 taintproper("Insecure dependency in exec");
1434 while ((pid = (doexec?vfork():fork())) < 0) {
1435 if (errno != EAGAIN) {
1438 fatal("Can't fork");
1447 if (p[THIS] != (*mode == 'r')) {
1448 dup2(p[THIS], *mode == 'r');
1452 #if !defined(HAS_FCNTL) || !defined(F_SETFD)
1458 for (fd = maxsysfd + 1; fd < NOFILE; fd++)
1461 do_exec(cmd); /* may or may not use the shell */
1462 warn("Can't exec \"%s\": %s", cmd, strerror(errno));
1466 if (tmpstab = stabent("$",allstabs))
1467 str_numset(STAB_STR(tmpstab),(double)getpid());
1469 hclear(pidstatus, FALSE); /* we have no children */
1474 do_execfree(); /* free any memory malloced by child on vfork */
1476 if (p[that] < p[this]) {
1477 dup2(p[this], p[that]);
1481 str = afetch(fdpid,p[this],TRUE);
1482 str->str_u.str_useful = pid;
1484 return fdopen(p[this], mode);
1494 return popen(cmd, mode);
1498 #endif /* !DOSISH */
1505 struct stat tmpstatbuf;
1507 fprintf(stderr,"%s", s);
1508 for (fd = 0; fd < 32; fd++) {
1509 if (fstat(fd,&tmpstatbuf) >= 0)
1510 fprintf(stderr," %d",fd);
1512 fprintf(stderr,"\n");
1521 #if defined(HAS_FCNTL) && defined(F_DUPFD)
1523 fcntl(oldfd, F_DUPFD, newfd);
1532 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1535 close(fdtmp[--fdx]);
1546 void (*hstat)(), (*istat)(), (*qstat)();
1548 int (*hstat)(), (*istat)(), (*qstat)();
1554 str = afetch(fdpid,fileno(ptr),TRUE);
1555 pid = (int)str->str_u.str_useful;
1556 astore(fdpid,fileno(ptr),Nullstr);
1559 if(kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */
1561 hstat = signal(SIGHUP, SIG_IGN);
1562 istat = signal(SIGINT, SIG_IGN);
1563 qstat = signal(SIGQUIT, SIG_IGN);
1564 pid = wait4pid(pid, &status, 0);
1565 signal(SIGHUP, hstat);
1566 signal(SIGINT, istat);
1567 signal(SIGQUIT, qstat);
1568 return(pid < 0 ? pid : status);
1572 wait4pid(pid,statusp,flags)
1577 #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
1586 return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
1589 return waitpid(pid,statusp,flags);
1592 sprintf(spid, "%d", pid);
1593 str = hfetch(pidstatus,spid,strlen(spid),FALSE);
1594 if (str != &str_undef) {
1595 *statusp = (int)str->str_u.str_useful;
1596 hdelete(pidstatus,spid,strlen(spid));
1603 hiterinit(pidstatus);
1604 if (entry = hiternext(pidstatus)) {
1605 pid = atoi(hiterkey(entry,statusp));
1606 str = hiterval(pidstatus,entry);
1607 *statusp = (int)str->str_u.str_useful;
1608 sprintf(spid, "%d", pid);
1609 hdelete(pidstatus,spid,strlen(spid));
1614 fatal("Can't do waitpid with flags");
1616 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1617 pidgone(result,*statusp);
1625 #endif /* !DOSISH */
1633 #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
1638 sprintf(spid, "%d", pid);
1639 str = hfetch(pidstatus,spid,strlen(spid),TRUE);
1640 str->str_u.str_useful = status;
1656 repeatcpy(to,from,len,count)
1658 register char *from;
1663 register char *frombase = from;
1671 while (count-- > 0) {
1672 for (todo = len; todo > 0; todo--) {
1679 #ifndef CASTNEGFLOAT
1687 # define BIGDOUBLE 2147483648.0
1689 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1692 return (unsigned long)f;
1694 return (unsigned long)along;
1704 char *fa = rindex(a,'/');
1705 char *fb = rindex(b,'/');
1706 struct stat tmpstatbuf1;
1707 struct stat tmpstatbuf2;
1709 #define MAXPATHLEN 1024
1711 char tmpbuf[MAXPATHLEN+1];
1726 strncpy(tmpbuf, a, fa - a);
1727 if (stat(tmpbuf, &tmpstatbuf1) < 0)
1732 strncpy(tmpbuf, b, fb - b);
1733 if (stat(tmpbuf, &tmpstatbuf2) < 0)
1735 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1736 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1738 #endif /* !HAS_RENAME */
1741 scanoct(start, len, retlen)
1746 register char *s = start;
1747 register unsigned long retval = 0;
1749 while (len-- && *s >= '0' && *s <= '7') {
1751 retval |= *s++ - '0';
1753 *retlen = s - start;
1758 scanhex(start, len, retlen)
1763 register char *s = start;
1764 register unsigned long retval = 0;
1767 while (len-- && *s && (tmp = index(hexdigit, *s))) {
1769 retval |= (tmp - hexdigit) & 15;
1772 *retlen = s - start;