1 /* $RCSfile: util.c,v $$Revision: 4.0.1.6 $$Date: 92/06/11 21:18:47 $
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.6 92/06/11 21:18:47 lwall
10 * patch34: boneheaded typo in my_bcopy()
12 * Revision 4.0.1.5 92/06/08 16:08:37 lwall
13 * patch20: removed implicit int declarations on functions
14 * patch20: Perl now distinguishes overlapped copies from non-overlapped
15 * patch20: fixed confusion between a *var's real name and its effective name
16 * patch20: bcopy() and memcpy() now tested for overlap safety
17 * patch20: added Atari ST portability
19 * Revision 4.0.1.4 91/11/11 16:48:54 lwall
20 * patch19: study was busted by 4.018
21 * patch19: added little-endian pack/unpack options
23 * Revision 4.0.1.3 91/11/05 19:18:26 lwall
24 * patch11: safe malloc code now integrated into Perl's malloc when possible
25 * patch11: index("little", "longer string") could visit faraway places
26 * patch11: warn '-' x 10000 dumped core
27 * patch11: forked exec on non-existent program now issues a warning
29 * Revision 4.0.1.2 91/06/07 12:10:42 lwall
30 * patch4: new copyright notice
31 * patch4: made some allowances for "semi-standard" C
32 * patch4: index() could blow up searching for null string
33 * patch4: taintchecks could improperly modify parent in vfork()
34 * patch4: exec would close files even if you cleared close-on-exec flag
36 * Revision 4.0.1.1 91/04/12 09:19:25 lwall
37 * patch1: random cleanup in cpp namespace
39 * Revision 4.0 91/03/20 01:56:39 lwall
48 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
64 # include <sys/file.h>
71 static char nomem[] = "Out of memory!\n";
73 /* paranoid version of malloc */
79 /* NOTE: Do not call the next three routines directly. Use the macros
80 * in handy.h, so that we can easily redefine everything to do tracking of
81 * allocated hunks back to the original New to track down any memory leaks.
95 #endif /* ! STANDARD_C */
99 fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
105 fatal("panic: malloc");
107 ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
109 # if !(defined(I286) || defined(atarist))
111 fprintf(stderr,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
114 fprintf(stderr,"0x%lx: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
122 fputs(nomem,stderr) FLUSH;
131 /* paranoid version of realloc */
134 saferealloc(where,size)
145 #endif /* ! STANDARD_C */
149 fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
154 fatal("Null realloc");
157 fatal("panic: realloc");
159 ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
161 # if !(defined(I286) || defined(atarist))
163 fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
164 fprintf(stderr,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
168 fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
169 fprintf(stderr,"0x%lx: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
178 fputs(nomem,stderr) FLUSH;
187 /* safe version of free */
194 # if !(defined(I286) || defined(atarist))
196 fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
199 fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
208 #endif /* !safemalloc */
212 #define ALIGN sizeof(long)
219 register char *where;
221 where = safemalloc(size + ALIGN);
225 return where + ALIGN;
229 safexrealloc(where,size)
233 return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
245 x = where[0] + 100 * where[1];
255 for (i = 0; i < MAXXCOUNT; i++) {
256 if (xcount[i] > lastxcount[i]) {
257 fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
258 lastxcount[i] = xcount[i];
263 #endif /* LEAKTEST */
265 /* copy a string up to some (non-backslashed) delimiter, if any */
268 cpytill(to,from,fromend,delim,retlen)
271 register char *fromend;
277 for (; from < fromend; from++,to++) {
279 if (from[1] == delim)
281 else if (from[1] == '\\')
284 else if (*from == delim)
289 *retlen = to - origto;
293 /* return ptr to little string in big string, NULL if not found */
294 /* This routine was donated by Corey Satten. */
299 register char *little;
301 register char *s, *x;
312 for (x=big,s=little; *s; /**/ ) {
326 /* same as instr but allow embedded nulls */
329 ninstr(big, bigend, little, lend)
331 register char *bigend;
335 register char *s, *x;
336 register int first = *little;
337 register char *littleend = lend;
339 if (!first && little > littleend)
341 if (bigend - big < littleend - little)
343 bigend -= littleend - little++;
344 while (big <= bigend) {
347 for (x=big,s=little; s < littleend; /**/ ) {
359 /* reverse of the above--find last substring */
362 rninstr(big, bigend, little, lend)
368 register char *bigbeg;
369 register char *s, *x;
370 register int first = *little;
371 register char *littleend = lend;
373 if (!first && little > littleend)
376 big = bigend - (littleend - little++);
377 while (big >= bigbeg) {
380 for (x=big+2,s=little; s < littleend; /**/ ) {
392 unsigned char fold[] = {
393 0, 1, 2, 3, 4, 5, 6, 7,
394 8, 9, 10, 11, 12, 13, 14, 15,
395 16, 17, 18, 19, 20, 21, 22, 23,
396 24, 25, 26, 27, 28, 29, 30, 31,
397 32, 33, 34, 35, 36, 37, 38, 39,
398 40, 41, 42, 43, 44, 45, 46, 47,
399 48, 49, 50, 51, 52, 53, 54, 55,
400 56, 57, 58, 59, 60, 61, 62, 63,
401 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
402 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
403 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
404 'x', 'y', 'z', 91, 92, 93, 94, 95,
405 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
406 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
407 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
408 'X', 'Y', 'Z', 123, 124, 125, 126, 127,
409 128, 129, 130, 131, 132, 133, 134, 135,
410 136, 137, 138, 139, 140, 141, 142, 143,
411 144, 145, 146, 147, 148, 149, 150, 151,
412 152, 153, 154, 155, 156, 157, 158, 159,
413 160, 161, 162, 163, 164, 165, 166, 167,
414 168, 169, 170, 171, 172, 173, 174, 175,
415 176, 177, 178, 179, 180, 181, 182, 183,
416 184, 185, 186, 187, 188, 189, 190, 191,
417 192, 193, 194, 195, 196, 197, 198, 199,
418 200, 201, 202, 203, 204, 205, 206, 207,
419 208, 209, 210, 211, 212, 213, 214, 215,
420 216, 217, 218, 219, 220, 221, 222, 223,
421 224, 225, 226, 227, 228, 229, 230, 231,
422 232, 233, 234, 235, 236, 237, 238, 239,
423 240, 241, 242, 243, 244, 245, 246, 247,
424 248, 249, 250, 251, 252, 253, 254, 255
427 static unsigned char freq[] = {
428 1, 2, 84, 151, 154, 155, 156, 157,
429 165, 246, 250, 3, 158, 7, 18, 29,
430 40, 51, 62, 73, 85, 96, 107, 118,
431 129, 140, 147, 148, 149, 150, 152, 153,
432 255, 182, 224, 205, 174, 176, 180, 217,
433 233, 232, 236, 187, 235, 228, 234, 226,
434 222, 219, 211, 195, 188, 193, 185, 184,
435 191, 183, 201, 229, 181, 220, 194, 162,
436 163, 208, 186, 202, 200, 218, 198, 179,
437 178, 214, 166, 170, 207, 199, 209, 206,
438 204, 160, 212, 216, 215, 192, 175, 173,
439 243, 172, 161, 190, 203, 189, 164, 230,
440 167, 248, 227, 244, 242, 255, 241, 231,
441 240, 253, 169, 210, 245, 237, 249, 247,
442 239, 168, 252, 251, 254, 238, 223, 221,
443 213, 225, 177, 197, 171, 196, 159, 4,
444 5, 6, 8, 9, 10, 11, 12, 13,
445 14, 15, 16, 17, 19, 20, 21, 22,
446 23, 24, 25, 26, 27, 28, 30, 31,
447 32, 33, 34, 35, 36, 37, 38, 39,
448 41, 42, 43, 44, 45, 46, 47, 48,
449 49, 50, 52, 53, 54, 55, 56, 57,
450 58, 59, 60, 61, 63, 64, 65, 66,
451 67, 68, 69, 70, 71, 72, 74, 75,
452 76, 77, 78, 79, 80, 81, 82, 83,
453 86, 87, 88, 89, 90, 91, 92, 93,
454 94, 95, 97, 98, 99, 100, 101, 102,
455 103, 104, 105, 106, 108, 109, 110, 111,
456 112, 113, 114, 115, 116, 117, 119, 120,
457 121, 122, 123, 124, 125, 126, 127, 128,
458 130, 131, 132, 133, 134, 135, 136, 137,
459 138, 139, 141, 142, 143, 144, 145, 146
463 fbmcompile(str, iflag)
467 register unsigned char *s;
468 register unsigned char *table;
469 register unsigned int i;
470 register unsigned int len = str->str_cur;
472 unsigned int frequency = 256;
474 Str_Grow(str,len+258);
476 table = (unsigned char*)(str->str_ptr + len + 1);
478 table = Null(unsigned char*);
481 for (i = 0; i < 256; i++) {
486 while (s >= (unsigned char*)(str->str_ptr))
489 if (table[*s] == len) {
492 table[*s] = table[fold[*s]] = i;
506 str->str_pok |= SP_FBM; /* deep magic */
509 s = (unsigned char*)(str->str_ptr); /* deeper magic */
511 s = Null(unsigned char*);
514 register unsigned int tmp, foldtmp;
515 str->str_pok |= SP_CASEFOLD;
516 for (i = 0; i < len; i++) {
518 foldtmp=freq[fold[s[i]]];
519 if (tmp < frequency && foldtmp < frequency) {
521 /* choose most frequent among the two */
522 frequency = (tmp > foldtmp) ? tmp : foldtmp;
527 for (i = 0; i < len; i++) {
528 if (freq[s[i]] < frequency) {
530 frequency = freq[s[i]];
534 str->str_rare = s[rarest];
535 str->str_state = rarest;
538 fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
543 fbminstr(big, bigend, littlestr)
545 register unsigned char *bigend;
548 register unsigned char *s;
550 register int littlelen;
551 register unsigned char *little;
552 register unsigned char *table;
553 register unsigned char *olds;
554 register unsigned char *oldlittle;
557 if (!(littlestr->str_pok & SP_FBM)) {
558 if (!littlestr->str_ptr)
560 return ninstr((char*)big,(char*)bigend,
561 littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
565 littlelen = littlestr->str_cur;
567 if (littlestr->str_pok & SP_TAIL && !multiline) { /* tail anchored? */
568 if (littlelen > bigend - big)
570 little = (unsigned char*)littlestr->str_ptr;
571 if (littlestr->str_pok & SP_CASEFOLD) { /* oops, fake it */
572 big = bigend - littlelen; /* just start near end */
573 if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
577 s = bigend - littlelen;
578 if (*s == *little && bcmp(s,little,littlelen)==0)
579 return (char*)s; /* how sweet it is */
580 else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
583 if (*s == *little && bcmp(s,little,littlelen)==0)
589 table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
591 table = Null(unsigned char*);
593 if (--littlelen >= bigend - big)
596 oldlittle = little = table - 2;
597 if (littlestr->str_pok & SP_CASEFOLD) { /* case insensitive? */
601 if (tmp = table[*s]) {
603 if (bigend - s > tmp) {
608 if ((s += tmp) < bigend)
614 tmp = littlelen; /* less expensive than calling strncmp() */
617 if (*--s == *--little || fold[*s] == *little)
619 s = olds + 1; /* here we pay the price for failure */
621 if (s < bigend) /* fake up continue to outer loop */
635 if (tmp = table[*s]) {
637 if (bigend - s > tmp) {
642 if ((s += tmp) < bigend)
648 tmp = littlelen; /* less expensive than calling strncmp() */
651 if (*--s == *--little)
653 s = olds + 1; /* here we pay the price for failure */
655 if (s < bigend) /* fake up continue to outer loop */
669 screaminstr(bigstr, littlestr)
673 register unsigned char *s, *x;
674 register unsigned char *big;
676 register int previous;
678 register unsigned char *little;
679 register unsigned char *bigend;
680 register unsigned char *littleend;
682 if ((pos = screamfirst[littlestr->str_rare]) < 0)
685 little = (unsigned char *)(littlestr->str_ptr);
687 little = Null(unsigned char *);
689 littleend = little + littlestr->str_cur;
691 previous = littlestr->str_state;
693 big = (unsigned char *)(bigstr->str_ptr);
695 big = Null(unsigned char*);
697 bigend = big + bigstr->str_cur;
698 while (pos < previous) {
700 if (!(pos += screamnext[pos]))
705 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
707 if (big[pos-previous] != first && big[pos-previous] != fold[first])
709 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
712 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
719 return (char *)(big+pos-previous);
725 pos += screamnext[pos] /* does this goof up anywhere? */
733 if (big[pos-previous] != first)
735 for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
745 return (char *)(big+pos-previous);
751 pos += screamnext[pos]
757 #else /* !POINTERRIGOR */
759 if (littlestr->str_pok & SP_CASEFOLD) { /* case insignificant? */
761 if (big[pos] != first && big[pos] != fold[first])
763 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
766 if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
773 return (char *)(big+pos);
779 pos += screamnext[pos] /* does this goof up anywhere? */
787 if (big[pos] != first)
789 for (x=big+pos+1,s=little; s < littleend; /**/ ) {
799 return (char *)(big+pos);
805 pos += screamnext[pos]
811 #endif /* POINTERRIGOR */
815 /* copy a string to a safe spot */
821 register char *newaddr;
823 New(902,newaddr,strlen(str)+1,char);
824 (void)strcpy(newaddr,str);
828 /* same thing but with a known length */
835 register char *newaddr;
837 New(903,newaddr,len+1,char);
838 Copy(str,newaddr,len,char); /* might not be null terminated */
839 newaddr[len] = '\0'; /* is now */
843 /* grow a static string to at least a certain length */
846 growstr(strptr,curlen,newlen)
851 if (newlen > *curlen) { /* need more room? */
853 Renew(*strptr,newlen,char);
855 New(905,*strptr,newlen,char);
863 mess(pat,a1,a2,a3,a4)
868 int usermess = strEQ(pat,"%s");
873 tmpstr = str_mortal(&str_undef);
874 str_set(tmpstr, (char*)a1);
875 *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
878 (void)sprintf(s,pat,a1,a2,a3,a4);
883 if (curcmd->c_line) {
884 (void)sprintf(s," at %s line %ld",
885 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
889 stab_io(last_in_stab) &&
890 stab_io(last_in_stab)->lines ) {
891 (void)sprintf(s,", <%s> line %ld",
892 last_in_stab == argvstab ? "" : stab_ename(last_in_stab),
893 (long)stab_io(last_in_stab)->lines);
896 (void)strcpy(s,".\n");
898 str_cat(tmpstr,buf+1);
901 return tmpstr->str_ptr;
907 void fatal(pat,a1,a2,a3,a4)
912 extern char *e_tmpname;
916 message = mess(pat,a1,a2,a3,a4);
918 str_set(stab_val(stabent("@",TRUE)),message);
920 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
921 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
924 deb("(Skipping label #%d %s)\n",loop_ptr,
925 loop_stack[loop_ptr].loop_label);
932 deb("(Found label #%d %s)\n",loop_ptr,
933 loop_stack[loop_ptr].loop_label);
938 fatal("Bad label: %s", tmps);
940 longjmp(loop_stack[loop_ptr].loop_env, 1);
942 fputs(message,stderr);
943 (void)fflush(stderr);
945 (void)UNLINK(e_tmpname);
947 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
951 void warn(pat,a1,a2,a3,a4)
957 message = mess(pat,a1,a2,a3,a4);
958 fputs(message,stderr);
965 (void)fflush(stderr);
988 pat = va_arg(args, char *);
991 usermess = strEQ(pat, "%s");
993 tmpstr = str_mortal(&str_undef);
994 str_set(tmpstr, va_arg(args, char *));
995 *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
998 (void) vsprintf(s,pat,args);
1002 if (s[-1] != '\n') {
1003 if (curcmd->c_line) {
1004 (void)sprintf(s," at %s line %ld",
1005 stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
1009 stab_io(last_in_stab) &&
1010 stab_io(last_in_stab)->lines ) {
1011 (void)sprintf(s,", <%s> line %ld",
1012 last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
1013 (long)stab_io(last_in_stab)->lines);
1016 (void)strcpy(s,".\n");
1018 str_cat(tmpstr,buf+1);
1022 return tmpstr->str_ptr;
1028 void fatal(va_alist)
1033 extern char *e_tmpname;
1042 message = mess(args);
1045 str_set(stab_val(stabent("@",TRUE)),message);
1047 while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
1048 strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
1051 deb("(Skipping label #%d %s)\n",loop_ptr,
1052 loop_stack[loop_ptr].loop_label);
1059 deb("(Found label #%d %s)\n",loop_ptr,
1060 loop_stack[loop_ptr].loop_label);
1065 fatal("Bad label: %s", tmps);
1067 longjmp(loop_stack[loop_ptr].loop_env, 1);
1069 fputs(message,stderr);
1070 (void)fflush(stderr);
1072 (void)UNLINK(e_tmpname);
1074 exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
1089 message = mess(args);
1092 fputs(message,stderr);
1099 (void)fflush(stderr);
1107 register int i=envix(nam); /* where does it go? */
1109 if (environ == origenviron) { /* need we copy environment? */
1115 for (max = i; environ[max]; max++) ;
1116 New(901,tmpenv, max+2, char*);
1117 for (j=0; j<max; j++) /* copy environment */
1118 tmpenv[j] = savestr(environ[j]);
1119 tmpenv[max] = Nullch;
1120 environ = tmpenv; /* tell exec where it is now */
1123 while (environ[i]) {
1124 environ[i] = environ[i+1];
1129 if (!environ[i]) { /* does not exist yet */
1130 Renew(environ, i+2, char*); /* just expand it a bit */
1131 environ[i+1] = Nullch; /* make sure it's null terminated */
1134 Safefree(environ[i]);
1135 New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
1137 (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
1139 /* MS-DOS requires environment variable names to be in uppercase */
1140 /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
1141 * some utilities and applications may break because they only look
1142 * for upper case strings. (Fixed strupr() bug here.)]
1144 strcpy(environ[i],nam); strupr(environ[i]);
1145 (void)sprintf(environ[i] + strlen(nam),"=%s",val);
1153 register int i, len = strlen(nam);
1155 for (i = 0; environ[i]; i++) {
1156 if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
1157 break; /* strnEQ must come first to avoid */
1158 } /* potential SEGV's */
1164 unlnk(f) /* unlink all versions of a file */
1169 for (i = 0; unlink(f) >= 0; i++) ;
1174 #if !defined(HAS_BCOPY) || !defined(SAFE_BCOPY)
1176 my_bcopy(from,to,len)
1177 register char *from;
1183 if (from - to >= 0) {
1191 *(--to) = *(--from);
1197 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
1213 my_memcmp(s1,s2,len)
1214 register unsigned char *s1;
1215 register unsigned char *s2;
1221 if (tmp = *s1++ - *s2++)
1226 #endif /* HAS_MEMCMP */
1236 vsprintf(dest, pat, args)
1237 char *dest, *pat, *args;
1241 fakebuf._ptr = dest;
1242 fakebuf._cnt = 32767;
1246 fakebuf._flag = _IOWRT|_IOSTRG;
1247 _doprnt(pat, args, &fakebuf); /* what a kludge */
1248 (void)putc('\0', &fakebuf);
1252 return 0; /* perl doesn't use return value */
1258 vfprintf(fd, pat, args)
1262 _doprnt(pat, args, fd);
1263 return 0; /* wrong, but perl doesn't use the return value */
1266 #endif /* HAS_VPRINTF */
1267 #endif /* I_VARARGS */
1270 * I think my_swap(), htonl() and ntohl() have never been used.
1271 * perl.h contains last-chance references to my_swap(), my_htonl()
1272 * and my_ntohl(). I presume these are the intended functions;
1273 * but htonl() and ntohl() have the wrong names. There are no
1274 * functions my_htonl() and my_ntohl() defined anywhere.
1278 #if BYTEORDER != 0x4321
1283 #if (BYTEORDER & 1) == 0
1286 result = ((s & 255) << 8) + ((s >> 8) & 255);
1299 char c[sizeof(long)];
1302 #if BYTEORDER == 0x1234
1303 u.c[0] = (l >> 24) & 255;
1304 u.c[1] = (l >> 16) & 255;
1305 u.c[2] = (l >> 8) & 255;
1309 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1310 fatal("Unknown BYTEORDER\n");
1315 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1316 u.c[o & 0xf] = (l >> s) & 255;
1329 char c[sizeof(long)];
1332 #if BYTEORDER == 0x1234
1333 u.c[0] = (l >> 24) & 255;
1334 u.c[1] = (l >> 16) & 255;
1335 u.c[2] = (l >> 8) & 255;
1339 #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
1340 fatal("Unknown BYTEORDER\n");
1347 for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
1348 l |= (u.c[o & 0xf] & 255) << s;
1355 #endif /* BYTEORDER != 0x4321 */
1359 * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
1360 * If these functions are defined,
1361 * the BYTEORDER is neither 0x1234 nor 0x4321.
1362 * However, this is not assumed.
1366 #define HTOV(name,type) \
1373 char c[sizeof(type)]; \
1377 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1378 u.c[i] = (n >> s) & 0xFF; \
1383 #define VTOH(name,type) \
1390 char c[sizeof(type)]; \
1396 for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
1397 n += (u.c[i] & 0xFF) << s; \
1402 #if defined(HAS_HTOVS) && !defined(htovs)
1405 #if defined(HAS_HTOVL) && !defined(htovl)
1408 #if defined(HAS_VTOHS) && !defined(vtohs)
1411 #if defined(HAS_VTOHL) && !defined(vtohl)
1422 register int this, that;
1425 int doexec = strNE(cmd,"-");
1429 this = (*mode == 'w');
1434 taintproper("Insecure dependency in exec");
1437 while ((pid = (doexec?vfork():fork())) < 0) {
1438 if (errno != EAGAIN) {
1441 fatal("Can't fork");
1450 if (p[THIS] != (*mode == 'r')) {
1451 dup2(p[THIS], *mode == 'r');
1455 #if !defined(HAS_FCNTL) || !defined(F_SETFD)
1461 for (fd = maxsysfd + 1; fd < NOFILE; fd++)
1464 do_exec(cmd); /* may or may not use the shell */
1465 warn("Can't exec \"%s\": %s", cmd, strerror(errno));
1469 if (tmpstab = stabent("$",allstabs))
1470 str_numset(STAB_STR(tmpstab),(double)getpid());
1472 hclear(pidstatus, FALSE); /* we have no children */
1477 do_execfree(); /* free any memory malloced by child on vfork */
1479 if (p[that] < p[this]) {
1480 dup2(p[this], p[that]);
1484 str = afetch(fdpid,p[this],TRUE);
1485 str->str_u.str_useful = pid;
1487 return fdopen(p[this], mode);
1497 return popen(cmd, mode);
1501 #endif /* !DOSISH */
1508 struct stat tmpstatbuf;
1510 fprintf(stderr,"%s", s);
1511 for (fd = 0; fd < 32; fd++) {
1512 if (fstat(fd,&tmpstatbuf) >= 0)
1513 fprintf(stderr," %d",fd);
1515 fprintf(stderr,"\n");
1524 #if defined(HAS_FCNTL) && defined(F_DUPFD)
1526 fcntl(oldfd, F_DUPFD, newfd);
1535 while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
1538 close(fdtmp[--fdx]);
1549 void (*hstat)(), (*istat)(), (*qstat)();
1551 int (*hstat)(), (*istat)(), (*qstat)();
1557 str = afetch(fdpid,fileno(ptr),TRUE);
1558 pid = (int)str->str_u.str_useful;
1559 astore(fdpid,fileno(ptr),Nullstr);
1562 if(kill(pid, 0) < 0) { return(pid); } /* HOM 12/23/91 */
1564 hstat = signal(SIGHUP, SIG_IGN);
1565 istat = signal(SIGINT, SIG_IGN);
1566 qstat = signal(SIGQUIT, SIG_IGN);
1567 pid = wait4pid(pid, &status, 0);
1568 signal(SIGHUP, hstat);
1569 signal(SIGINT, istat);
1570 signal(SIGQUIT, qstat);
1571 return(pid < 0 ? pid : status);
1575 wait4pid(pid,statusp,flags)
1580 #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
1589 return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
1592 return waitpid(pid,statusp,flags);
1595 sprintf(spid, "%d", pid);
1596 str = hfetch(pidstatus,spid,strlen(spid),FALSE);
1597 if (str != &str_undef) {
1598 *statusp = (int)str->str_u.str_useful;
1599 hdelete(pidstatus,spid,strlen(spid));
1606 hiterinit(pidstatus);
1607 if (entry = hiternext(pidstatus)) {
1608 pid = atoi(hiterkey(entry,statusp));
1609 str = hiterval(pidstatus,entry);
1610 *statusp = (int)str->str_u.str_useful;
1611 sprintf(spid, "%d", pid);
1612 hdelete(pidstatus,spid,strlen(spid));
1617 fatal("Can't do waitpid with flags");
1619 while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
1620 pidgone(result,*statusp);
1628 #endif /* !DOSISH */
1636 #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
1641 sprintf(spid, "%d", pid);
1642 str = hfetch(pidstatus,spid,strlen(spid),TRUE);
1643 str->str_u.str_useful = status;
1659 repeatcpy(to,from,len,count)
1661 register char *from;
1666 register char *frombase = from;
1674 while (count-- > 0) {
1675 for (todo = len; todo > 0; todo--) {
1682 #ifndef CASTNEGFLOAT
1690 # define BIGDOUBLE 2147483648.0
1692 return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
1695 return (unsigned long)f;
1697 return (unsigned long)along;
1707 char *fa = rindex(a,'/');
1708 char *fb = rindex(b,'/');
1709 struct stat tmpstatbuf1;
1710 struct stat tmpstatbuf2;
1712 #define MAXPATHLEN 1024
1714 char tmpbuf[MAXPATHLEN+1];
1729 strncpy(tmpbuf, a, fa - a);
1730 if (stat(tmpbuf, &tmpstatbuf1) < 0)
1735 strncpy(tmpbuf, b, fb - b);
1736 if (stat(tmpbuf, &tmpstatbuf2) < 0)
1738 return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
1739 tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
1741 #endif /* !HAS_RENAME */
1744 scanoct(start, len, retlen)
1749 register char *s = start;
1750 register unsigned long retval = 0;
1752 while (len-- && *s >= '0' && *s <= '7') {
1754 retval |= *s++ - '0';
1756 *retlen = s - start;
1761 scanhex(start, len, retlen)
1766 register char *s = start;
1767 register unsigned long retval = 0;
1770 while (len-- && *s && (tmp = index(hexdigit, *s))) {
1772 retval |= (tmp - hexdigit) & 15;
1775 *retlen = s - start;