1 /* $RCSfile: str.c,v $$Revision: 4.0.1.1 $$Date: 91/04/12 09:15:30 $
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 4.0.1.1 91/04/12 09:15:30 lwall
10 * patch1: fixed undefined environ problem
11 * patch1: substr($ENV{"PATH"},0,0) = "/foo:" didn't modify environment
12 * patch1: $foo .= <BAR> could cause core dump for certain lengths of $foo
14 * Revision 4.0 91/03/20 01:39:55 lwall
29 tainted |= str->str_tainted;
31 return str->str_pok ? str->str_ptr : str_2ptr(str);
35 /* dlb ... guess we have a "crippled cc".
36 * dlb the following functions are usually macros.
43 if (*Str->str_ptr > '0' ||
45 (Str->str_cur && *Str->str_ptr != '0'))
50 return (Str->str_u.str_nval != 0.0);
60 tainted |= Str->str_tainted;
63 return Str->str_u.str_nval;
67 /* dlb ... end of crutch */
78 register char *s = str->str_ptr;
81 if (newlen >= 0x10000) {
82 fprintf(stderr, "Allocation too large: %lx\n", newlen);
86 if (str->str_state == SS_INCR) { /* data before str_ptr? */
87 str->str_len += str->str_u.str_useful;
88 str->str_ptr -= str->str_u.str_useful;
89 str->str_u.str_useful = 0L;
90 bcopy(s, str->str_ptr, str->str_cur+1);
92 str->str_state = SS_NORM; /* normal again */
93 if (newlen > str->str_len)
94 newlen += 10 * (newlen - str->str_cur); /* avoid copy each time */
96 if (newlen > str->str_len) { /* need more room? */
100 New(703,s,newlen,char);
102 str->str_len = newlen;
112 str->str_pok = 0; /* invalidate pointer */
113 if (str->str_state == SS_INCR)
116 str->str_u.str_nval = num;
117 str->str_state = SS_NORM;
118 str->str_nok = 1; /* validate number */
120 str->str_tainted = tainted;
136 olderrno = errno; /* some Xenix systems wipe out errno here */
137 #if defined(scs) && defined(ns32000)
138 gcvt(str->str_u.str_nval,20,s);
141 if (str->str_u.str_nval == 0.0)
145 (void)sprintf(s,"%.20g",str->str_u.str_nval);
155 if (str == &str_undef)
158 warn("Use of uninitialized variable");
163 str->str_cur = s - str->str_ptr;
167 fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
178 if (str->str_state == SS_INCR)
179 Str_Grow(str,0); /* just force copy down */
180 str->str_state = SS_NORM;
181 if (str->str_len && str->str_pok)
182 str->str_u.str_nval = atof(str->str_ptr);
184 if (str == &str_undef)
187 warn("Use of uninitialized variable");
188 str->str_u.str_nval = 0.0;
193 fprintf(stderr,"0x%lx num(%g)\n",str,str->str_u.str_nval);
195 return str->str_u.str_nval;
198 /* Note: str_sset() should not be called with a source string that needs
199 * be reused, since it may destroy the source string if it is marked
209 tainted |= sstr->str_tainted;
211 if (sstr == dstr || dstr == &str_undef)
214 dstr->str_pok = dstr->str_nok = 0;
215 else if (sstr->str_pok) {
218 * Check to see if we can just swipe the string. If so, it's a
219 * possible small lose on short strings, but a big win on long ones.
220 * It might even be a win on short strings if dstr->str_ptr
221 * has to be allocated and sstr->str_ptr has to be freed.
224 if (sstr->str_pok & SP_TEMP) { /* slated for free anyway? */
226 if (dstr->str_state == SS_INCR)
227 dstr->str_ptr -= dstr->str_u.str_useful;
228 Safefree(dstr->str_ptr);
230 dstr->str_ptr = sstr->str_ptr;
231 dstr->str_len = sstr->str_len;
232 dstr->str_cur = sstr->str_cur;
233 dstr->str_state = sstr->str_state;
234 dstr->str_pok = sstr->str_pok & ~SP_TEMP;
236 dstr->str_tainted = sstr->str_tainted;
238 sstr->str_ptr = Nullch;
240 sstr->str_pok = 0; /* wipe out any weird flags */
241 sstr->str_state = 0; /* so sstr frees uneventfully */
243 else { /* have to copy actual string */
245 if (dstr->str_state == SS_INCR) {
249 str_nset(dstr,sstr->str_ptr,sstr->str_cur);
251 if (dstr->str_nok = sstr->str_nok)
252 dstr->str_u.str_nval = sstr->str_u.str_nval;
255 dstr->str_u = sstr->str_u;
257 dstr->str_u.str_nval = sstr->str_u.str_nval;
259 if (dstr->str_cur == sizeof(STBP)) {
260 char *tmps = dstr->str_ptr;
262 if (*tmps == 'S' && bcmp(tmps,"StB",4) == 0) {
263 if (!dstr->str_magic) {
264 dstr->str_magic = str_smake(sstr->str_magic);
265 dstr->str_magic->str_rare = 'X';
271 else if (sstr->str_nok)
272 str_numset(dstr,sstr->str_u.str_nval);
274 if (dstr->str_state == SS_INCR)
275 Str_Grow(dstr,0); /* just force copy down */
278 dstr->str_u = sstr->str_u;
280 dstr->str_u.str_nval = sstr->str_u.str_nval;
282 dstr->str_pok = dstr->str_nok = 0;
286 str_nset(str,ptr,len)
291 if (str == &str_undef)
293 STR_GROW(str, len + 1);
295 (void)bcopy(ptr,str->str_ptr,len);
297 *(str->str_ptr+str->str_cur) = '\0';
298 str->str_nok = 0; /* invalidate number */
299 str->str_pok = 1; /* validate pointer */
301 str->str_tainted = tainted;
311 if (str == &str_undef)
316 STR_GROW(str, len + 1);
317 (void)bcopy(ptr,str->str_ptr,len+1);
319 str->str_nok = 0; /* invalidate number */
320 str->str_pok = 1; /* validate pointer */
322 str->str_tainted = tainted;
326 str_chop(str,ptr) /* like set but assuming ptr is in str */
330 register STRLEN delta;
332 if (!ptr || !(str->str_pok))
334 delta = ptr - str->str_ptr;
335 str->str_len -= delta;
336 str->str_cur -= delta;
337 str->str_ptr += delta;
338 if (str->str_state == SS_INCR)
339 str->str_u.str_useful += delta;
341 str->str_u.str_useful = delta;
342 str->str_state = SS_INCR;
344 str->str_nok = 0; /* invalidate number */
345 str->str_pok = 1; /* validate pointer (and unstudy str) */
348 str_ncat(str,ptr,len)
353 if (str == &str_undef)
357 STR_GROW(str, str->str_cur + len + 1);
358 (void)bcopy(ptr,str->str_ptr+str->str_cur,len);
360 *(str->str_ptr+str->str_cur) = '\0';
361 str->str_nok = 0; /* invalidate number */
362 str->str_pok = 1; /* validate pointer */
364 str->str_tainted |= tainted;
373 tainted |= sstr->str_tainted;
377 if (!(sstr->str_pok))
378 (void)str_2ptr(sstr);
380 str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
389 if (str == &str_undef)
396 STR_GROW(str, str->str_cur + len + 1);
397 (void)bcopy(ptr,str->str_ptr+str->str_cur,len+1);
399 str->str_nok = 0; /* invalidate number */
400 str->str_pok = 1; /* validate pointer */
402 str->str_tainted |= tainted;
407 str_append_till(str,from,fromend,delim,keeplist)
410 register char *fromend;
417 if (str == &str_undef)
421 len = fromend - from;
422 STR_GROW(str, str->str_cur + len + 1);
423 str->str_nok = 0; /* invalidate number */
424 str->str_pok = 1; /* validate pointer */
425 to = str->str_ptr+str->str_cur;
426 for (; from < fromend; from++,to++) {
427 if (*from == '\\' && from+1 < fromend && delim != '\\') {
429 if (from[1] == delim || from[1] == '\\')
434 else if (from[1] && index(keeplist,from[1]))
439 else if (*from == delim)
444 str->str_cur = to - str->str_ptr;
461 freestrroot = str->str_magic;
462 str->str_magic = Nullstr;
463 str->str_state = SS_NORM;
466 Newz(700+x,str,1,STR);
469 STR_GROW(str, len + 1);
474 str_magic(str, stab, how, name, namlen)
481 if (str == &str_undef || str->str_magic)
483 str->str_magic = Str_new(75,namlen);
484 str = str->str_magic;
485 str->str_u.str_stab = stab;
488 str_nset(str,name,namlen);
492 str_insert(bigstr,offset,len,little,littlelen)
501 register char *midend;
502 register char *bigend;
505 if (bigstr == &str_undef)
508 bigstr->str_pok = SP_VALID; /* disable possible screamer */
511 if (i > 0) { /* string might grow */
512 STR_GROW(bigstr, bigstr->str_cur + i + 1);
513 big = bigstr->str_ptr;
514 mid = big + offset + len;
515 midend = bigend = big + bigstr->str_cur;
518 while (midend > mid) /* shove everything down */
519 *--bigend = *--midend;
520 (void)bcopy(little,big+offset,littlelen);
521 bigstr->str_cur += i;
526 (void)bcopy(little,bigstr->str_ptr+offset,len);
531 big = bigstr->str_ptr;
534 bigend = big + bigstr->str_cur;
537 fatal("panic: str_insert");
539 if (mid - big > bigend - midend) { /* faster to shorten from end */
541 (void)bcopy(little, mid, littlelen);
546 (void)bcopy(midend, mid, i);
550 bigstr->str_cur = mid - big;
552 else if (i = mid - big) { /* faster from front */
555 str_chop(bigstr,midend-i);
560 (void)bcopy(little, mid, littlelen);
562 else if (littlelen) {
564 str_chop(bigstr,midend);
565 (void)bcopy(little,midend,littlelen);
568 str_chop(bigstr,midend);
573 /* make str point to what nstr did */
576 str_replace(str,nstr)
580 if (str == &str_undef)
582 if (str->str_state == SS_INCR)
583 Str_Grow(str,0); /* just force copy down */
584 if (nstr->str_state == SS_INCR)
587 Safefree(str->str_ptr);
588 str->str_ptr = nstr->str_ptr;
589 str->str_len = nstr->str_len;
590 str->str_cur = nstr->str_cur;
591 str->str_pok = nstr->str_pok;
592 str->str_nok = nstr->str_nok;
594 str->str_u = nstr->str_u;
596 str->str_u.str_nval = nstr->str_u.str_nval;
599 str->str_tainted = nstr->str_tainted;
602 str_free(nstr->str_magic);
610 if (!str || str == &str_undef)
612 if (str->str_state) {
613 if (str->str_state == SS_FREE) /* already freed */
615 if (str->str_state == SS_INCR && !(str->str_pok & 2)) {
616 str->str_ptr -= str->str_u.str_useful;
617 str->str_len += str->str_u.str_useful;
621 str_free(str->str_magic);
622 str->str_magic = freestrroot;
625 Safefree(str->str_ptr);
626 str->str_ptr = Nullch;
628 if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
629 arg_free(str->str_u.str_args);
633 if (str->str_len > 127) { /* next user not likely to want more */
634 Safefree(str->str_ptr); /* so give it back to malloc */
635 str->str_ptr = Nullch;
639 str->str_ptr[0] = '\0';
641 if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
642 arg_free(str->str_u.str_args);
646 str->str_state = SS_FREE;
648 str->str_tainted = 0;
651 #endif /* LEAKTEST */
672 if (!str1 || str1 == &str_undef)
673 return (str2 == Nullstr || str2 == &str_undef || !str2->str_cur);
674 if (!str2 || str2 == &str_undef)
675 return !str1->str_cur;
678 (void)str_2ptr(str1);
680 (void)str_2ptr(str2);
682 if (str1->str_cur != str2->str_cur)
685 return !bcmp(str1->str_ptr, str2->str_ptr, str1->str_cur);
694 if (!str1 || str1 == &str_undef)
695 return (str2 == Nullstr || str2 == &str_undef || !str2->str_cur)?0:-1;
696 if (!str2 || str2 == &str_undef)
697 return str1->str_cur != 0;
700 (void)str_2ptr(str1);
702 (void)str_2ptr(str2);
704 if (str1->str_cur < str2->str_cur) {
705 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
706 return retval < 0 ? -1 : 1;
710 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
711 return retval < 0 ? -1 : 1;
712 else if (str1->str_cur == str2->str_cur)
719 str_gets(str,fp,append)
724 register char *bp; /* we're going to steal some values */
725 register int cnt; /* from the stdio struct and put EVERYTHING */
726 register STDCHAR *ptr; /* in the innermost loop into registers */
727 register int newline = rschar;/* (assuming >= 6 registers) */
732 if (str == &str_undef)
734 #ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */
735 cnt = fp->_cnt; /* get count into register */
736 str->str_nok = 0; /* invalidate number */
737 str->str_pok = 1; /* validate pointer */
738 if (str->str_len <= cnt + 1) { /* make sure we have the room */
739 if (cnt > 80 && str->str_len > append) {
740 shortbuffered = cnt - str->str_len + append + 1;
741 cnt -= shortbuffered;
745 STR_GROW(str, append+cnt+2);/* (remembering cnt can be -1) */
750 bp = str->str_ptr + append; /* move these two too to registers */
754 while (--cnt >= 0) { /* this */ /* eat */
755 if ((*bp++ = *ptr++) == newline) /* really */ /* dust */
756 goto thats_all_folks; /* screams */ /* sed :-) */
759 if (shortbuffered) { /* oh well, must extend */
762 bpx = bp - str->str_ptr; /* prepare for possible relocation */
764 STR_GROW(str, str->str_len + append + cnt + 2);
765 bp = str->str_ptr + bpx; /* reconstitute our pointer */
769 fp->_cnt = cnt; /* deregisterize cnt and ptr */
771 i = _filbuf(fp); /* get more characters */
773 ptr = fp->_ptr; /* reregisterize cnt and ptr */
775 bpx = bp - str->str_ptr; /* prepare for possible relocation */
777 STR_GROW(str, bpx + cnt + 2);
778 bp = str->str_ptr + bpx; /* reconstitute our pointer */
780 if (i == newline) { /* all done for now? */
782 goto thats_all_folks;
784 else if (i == EOF) /* all done for ever? */
785 goto thats_really_all_folks;
786 *bp++ = i; /* now go back to screaming loop */
790 if (rslen > 1 && (bp - str->str_ptr < rslen || bcmp(bp - rslen, rs, rslen)))
791 goto screamer; /* go back to the fray */
792 thats_really_all_folks:
794 cnt += shortbuffered;
795 fp->_cnt = cnt; /* put these back or we're in trouble */
798 str->str_cur = bp - str->str_ptr; /* set length */
800 #else /* !STDSTDIO */ /* The big, slow, and stupid way */
803 static char buf[8192];
804 char * bpe = buf + sizeof(buf) - 3;
808 while ((i = getc(fp)) != EOF && (*bp++ = i) != newline && bp < bpe) ;
815 if (i != EOF /* joy */
821 (str->str_cur < rslen
823 bcmp(str->str_ptr + str->str_cur - rslen, rs, rslen)
834 #endif /* STDSTDIO */
836 return str->str_cur - append ? str->str_ptr : Nullch;
845 CMD *oldcurcmd = curcmd;
846 int oldperldb = perldb;
850 str_sset(linestr,str);
852 oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
853 bufend = bufptr + linestr->str_cur;
854 if (++loop_ptr >= loop_max) {
856 Renew(loop_stack, loop_max, struct loop);
858 loop_stack[loop_ptr].loop_label = "_EVAL_";
859 loop_stack[loop_ptr].loop_sp = 0;
862 deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
865 if (setjmp(loop_stack[loop_ptr].loop_env)) {
869 fatal("%s\n",stab_val(stabent("@",TRUE))->str_ptr);
873 char *tmps = loop_stack[loop_ptr].loop_label;
874 deb("(Popping label #%d %s)\n",loop_ptr,
881 curcmd->c_line = oldcurcmd->c_line;
886 if (retval || error_count)
887 fatal("Invalid component in string or format");
890 if (cmd->c_type != C_EXPR || cmd->c_next || arg->arg_type != O_LIST)
891 fatal("panic: error in parselist %d %x %d", cmd->c_type,
892 cmd->c_next, arg ? arg->arg_type : -1);
902 register char *s = str_get(src);
903 register char *send = s + src->str_cur;
908 register int brackets;
914 toparse = Str_new(76,0);
918 str_nset(toparse,"",0);
921 if (*s == '\\' && s[1] && index("$@[{\\]}lLuUE",s[1])) {
922 str_ncat(str, t, s - t);
925 str_ncat(str, "$c", 2);
926 sawcase = (*s != 'E');
929 if (*nointrp && s+1 < send)
930 if (*s != '@' && (*s != '$' || index(nointrp,s[1])))
932 str_ncat(str, "$b", 2);
938 else if ((*s == '@' || (*s == '$' && !index(nointrp,s[1]))) &&
942 if (*s == '$' && s[1] == '#' && (isalpha(s[2]) || s[2] == '_'))
944 s = scanident(s,send,tokenbuf);
946 (!(stab = stabent(tokenbuf,FALSE)) ||
947 (*s == '{' ? !stab_xhash(stab) : !stab_xarray(stab)) )) {
950 continue; /* grandfather @ from old scripts */
952 str_ncat(str,"$a",2);
953 str_ncat(toparse,",",1);
954 if (t[1] != '{' && (*s == '[' || *s == '{' /* }} */ ) &&
955 (stab = stabent(tokenbuf,FALSE)) &&
956 ((*s == '[') ? (stab_xarray(stab) != 0) : (stab_xhash(stab) != 0)) ) {
978 s = cpytill(tokenbuf,s+1,send,*s,&len);
980 fatal("Unterminated string");
985 } while (brackets > 0 && s < send);
987 fatal("Unmatched brackets in string");
988 if (*nointrp) { /* we're in a regular expression */
990 if (*d == '{' && s[-1] == '}') { /* maybe {n,m} */
992 if (isdigit(*d)) { /* matches /^{\d,?\d*}$/ */
998 s = checkpoint; /* Is {n,m}! Backoff! */
1001 else if (*d == '[' && s[-1] == ']') { /* char class? */
1002 int weight = 2; /* let's weigh the evidence */
1004 unsigned char un_char = 0, last_un_char;
1006 Zero(seen,256,char);
1010 else if (d[1] == '$')
1012 if (isdigit(d[1])) {
1014 if (isdigit(d[2]) && !d[3])
1020 for (d++; d < s; d++) {
1021 last_un_char = un_char;
1022 un_char = (unsigned char)*d;
1026 weight -= seen[un_char] * 10;
1027 if (isalpha(d[1]) || isdigit(d[1]) ||
1029 d = scanident(d,s,tokenbuf);
1030 if (stabent(tokenbuf,FALSE))
1035 else if (*d == '$' && d[1] &&
1036 index("[#!%*<>()-=",d[1])) {
1037 if (!d[2] || /*{*/ index("])} =",d[2]))
1046 if (index("wds",d[1]))
1048 else if (seen['\''] || seen['"'])
1050 else if (index("rnftb",d[1]))
1052 else if (isdigit(d[1])) {
1054 while (d[1] && isdigit(d[1]))
1062 if (last_un_char < (unsigned char) d[1]
1064 if (index("aA01! ",last_un_char))
1066 if (index("zZ79~",d[1]))
1072 if (isalpha(*d) && d[1] && isalpha(d[1])) {
1074 if (yylex() != WORD)
1078 if (un_char == last_un_char + 1)
1080 weight -= seen[un_char];
1087 fprintf(stderr,"[%s] weight %d\n",
1088 checkpoint+1,weight);
1091 if (weight >= 0) /* probably a character class */
1097 str_ncat(toparse, "join($\",", 8);
1098 if (t[1] == '{' && s[-1] == '}') {
1099 str_ncat(toparse, t, 1);
1100 str_ncat(toparse, t+2, s - t - 3);
1103 str_ncat(toparse, t, s - t);
1105 str_ncat(toparse, ")", 1);
1111 str_ncat(str,t,s-t);
1113 str_ncat(str, "$cE", 3);
1114 if (toparse->str_ptr && *toparse->str_ptr == ',') {
1115 *toparse->str_ptr = '(';
1116 str_ncat(toparse,",$$);",5);
1117 str->str_u.str_args = parselist(toparse);
1118 str->str_u.str_args->arg_len--; /* ignore $$ reference */
1121 str->str_u.str_args = Nullarg;
1123 str->str_pok |= SP_INTRP;
1125 str_replace(src,str);
1136 register char *send;
1137 register STR **elem;
1144 if (str == &str_undef)
1146 if (!(src->str_pok & SP_INTRP)) {
1147 int oldsave = savestack->ary_fill;
1149 (void)savehptr(&curstash);
1150 curstash = curcmd->c_stash; /* so stabent knows right package */
1152 restorelist(oldsave);
1154 s = src->str_ptr; /* assumed valid since str_pok set */
1156 send = s + src->str_cur;
1158 if (src->str_u.str_args) {
1159 (void)eval(src->str_u.str_args,G_ARRAY,sp);
1160 /* Assuming we have correct # of args */
1161 elem = stack->ary_array + sp;
1166 if (*s == '$' && s+1 < send) {
1168 str_ncat(str,t,s-t);
1171 str_scat(str,*++elem);
1174 str_ncat(str,++s,1);
1177 if (docase && str->str_cur >= docase) {
1178 char *b = str->str_ptr + --docase;
1181 lcase(b, str->str_ptr + str->str_cur);
1183 ucase(b, str->str_ptr + str->str_cur);
1185 if (u) /* note that l & u are independent of L & U */
1191 docase = str->str_cur + 1;
1210 docase = L = U = l = u = 0;
1221 str_ncat(str,t,s-t);
1227 register char *send;
1230 if (isascii(*s) && islower(*s))
1238 register char *send;
1241 if (isascii(*s) && isupper(*s))
1253 if (!str || str == &str_undef)
1256 str->str_u.str_nval += 1.0;
1260 if (!str->str_pok || !*str->str_ptr) {
1261 str->str_u.str_nval = 1.0;
1267 while (isalpha(*d)) d++;
1268 while (isdigit(*d)) d++;
1270 str_numset(str,atof(str->str_ptr) + 1.0); /* punt */
1274 while (d >= str->str_ptr) {
1284 *(d--) -= 'z' - 'a' + 1;
1287 /* oh,oh, the number grew */
1288 STR_GROW(str, str->str_cur + 2);
1290 for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
1302 if (!str || str == &str_undef)
1305 str->str_u.str_nval -= 1.0;
1309 if (!str->str_pok) {
1310 str->str_u.str_nval = -1.0;
1314 str_numset(str,atof(str->str_ptr) - 1.0);
1317 /* Make a string that will exist for the duration of the expression
1318 * evaluation. Actually, it may have to last longer than that, but
1319 * hopefully cmd_exec won't free it until it has been assigned to a
1320 * permanent location. */
1322 static long tmps_size = -1;
1328 register STR *str = Str_new(78,0);
1330 str_sset(str,oldstr);
1331 if (++tmps_max > tmps_size) {
1332 tmps_size = tmps_max;
1333 if (!(tmps_size & 127)) {
1335 Renew(tmps_list, tmps_size + 128, STR*);
1337 New(702,tmps_list, 128, STR*);
1340 tmps_list[tmps_max] = str;
1342 str->str_pok |= SP_TEMP;
1346 /* same thing without the copying */
1352 if (str == &str_undef)
1354 if (++tmps_max > tmps_size) {
1355 tmps_size = tmps_max;
1356 if (!(tmps_size & 127)) {
1358 Renew(tmps_list, tmps_size + 128, STR*);
1360 New(704,tmps_list, 128, STR*);
1363 tmps_list[tmps_max] = str;
1365 str->str_pok |= SP_TEMP;
1374 register STR *str = Str_new(79,0);
1378 str_nset(str,s,len);
1386 register STR *str = Str_new(80,0);
1392 /* make an exact duplicate of old */
1398 register STR *new = Str_new(81,0);
1402 if (old->str_state == SS_FREE) {
1403 warn("semi-panic: attempt to dup freed string");
1406 if (old->str_state == SS_INCR && !(old->str_pok & 2))
1409 Safefree(new->str_ptr);
1410 Copy(old,new,1,STR);
1412 new->str_ptr = nsavestr(old->str_ptr,old->str_len);
1413 new->str_pok &= ~SP_TEMP;
1422 register HENT *entry;
1423 register STAB *stab;
1426 register SPAT *spat;
1429 if (!*s) { /* reset ?? searches */
1430 for (spat = stash->tbl_spatroot;
1432 spat = spat->spat_next) {
1433 spat->spat_flags &= ~SPAT_USED;
1438 /* reset variables */
1440 if (!stash->tbl_array)
1448 for ( ; i <= max; i++) {
1449 for (entry = stash->tbl_array[i];
1451 entry = entry->hent_next) {
1452 stab = (STAB*)entry->hent_val;
1453 str = stab_val(stab);
1457 str->str_tainted = tainted;
1459 if (str->str_ptr != Nullch)
1460 str->str_ptr[0] = '\0';
1461 if (stab_xarray(stab)) {
1462 aclear(stab_xarray(stab));
1464 if (stab_xhash(stab)) {
1465 hclear(stab_xhash(stab), FALSE);
1466 if (stab == envstab)
1467 environ[0] = Nullch;
1480 fprintf(stderr,"%s %d %d %d\n",s,tainted,uid, euid);
1482 if (tainted && (!euid || euid != uid || egid != gid)) {
1492 register STR *envstr;
1494 envstr = hfetch(stab_hash(envstab),"PATH",4,FALSE);
1495 if (envstr == &str_undef || envstr->str_tainted) {
1497 if (envstr->str_tainted == 2)
1498 taintproper("Insecure directory in PATH");
1500 taintproper("Insecure PATH");
1502 envstr = hfetch(stab_hash(envstab),"IFS",3,FALSE);
1503 if (envstr != &str_undef && envstr->str_tainted) {
1505 taintproper("Insecure IFS");