1 /* $RCSfile: str.c,v $$Revision: 4.0.1.3 $$Date: 91/06/10 01:27:54 $
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.3 91/06/10 01:27:54 lwall
10 * patch10: $) and $| incorrectly handled in run-time patterns
12 * Revision 4.0.1.2 91/06/07 11:58:13 lwall
13 * patch4: new copyright notice
14 * patch4: taint check on undefined string could cause core dump
16 * Revision 4.0.1.1 91/04/12 09:15:30 lwall
17 * patch1: fixed undefined environ problem
18 * patch1: substr($ENV{"PATH"},0,0) = "/foo:" didn't modify environment
19 * patch1: $foo .= <BAR> could cause core dump for certain lengths of $foo
21 * Revision 4.0 91/03/20 01:39:55 lwall
36 tainted |= str->str_tainted;
38 return str->str_pok ? str->str_ptr : str_2ptr(str);
42 /* dlb ... guess we have a "crippled cc".
43 * dlb the following functions are usually macros.
50 if (*Str->str_ptr > '0' ||
52 (Str->str_cur && *Str->str_ptr != '0'))
57 return (Str->str_u.str_nval != 0.0);
67 tainted |= Str->str_tainted;
70 return Str->str_u.str_nval;
74 /* dlb ... end of crutch */
85 register char *s = str->str_ptr;
88 if (newlen >= 0x10000) {
89 fprintf(stderr, "Allocation too large: %lx\n", newlen);
93 if (str->str_state == SS_INCR) { /* data before str_ptr? */
94 str->str_len += str->str_u.str_useful;
95 str->str_ptr -= str->str_u.str_useful;
96 str->str_u.str_useful = 0L;
97 bcopy(s, str->str_ptr, str->str_cur+1);
99 str->str_state = SS_NORM; /* normal again */
100 if (newlen > str->str_len)
101 newlen += 10 * (newlen - str->str_cur); /* avoid copy each time */
103 if (newlen > str->str_len) { /* need more room? */
105 Renew(s,newlen,char);
107 New(703,s,newlen,char);
109 str->str_len = newlen;
119 str->str_pok = 0; /* invalidate pointer */
120 if (str->str_state == SS_INCR)
123 str->str_u.str_nval = num;
124 str->str_state = SS_NORM;
125 str->str_nok = 1; /* validate number */
127 str->str_tainted = tainted;
143 olderrno = errno; /* some Xenix systems wipe out errno here */
144 #if defined(scs) && defined(ns32000)
145 gcvt(str->str_u.str_nval,20,s);
148 if (str->str_u.str_nval == 0.0)
152 (void)sprintf(s,"%.20g",str->str_u.str_nval);
162 if (str == &str_undef)
165 warn("Use of uninitialized variable");
170 str->str_cur = s - str->str_ptr;
174 fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
185 if (str->str_state == SS_INCR)
186 Str_Grow(str,0); /* just force copy down */
187 str->str_state = SS_NORM;
188 if (str->str_len && str->str_pok)
189 str->str_u.str_nval = atof(str->str_ptr);
191 if (str == &str_undef)
194 warn("Use of uninitialized variable");
195 str->str_u.str_nval = 0.0;
200 fprintf(stderr,"0x%lx num(%g)\n",str,str->str_u.str_nval);
202 return str->str_u.str_nval;
205 /* Note: str_sset() should not be called with a source string that needs
206 * be reused, since it may destroy the source string if it is marked
216 tainted |= sstr->str_tainted;
218 if (sstr == dstr || dstr == &str_undef)
221 dstr->str_pok = dstr->str_nok = 0;
222 else if (sstr->str_pok) {
225 * Check to see if we can just swipe the string. If so, it's a
226 * possible small lose on short strings, but a big win on long ones.
227 * It might even be a win on short strings if dstr->str_ptr
228 * has to be allocated and sstr->str_ptr has to be freed.
231 if (sstr->str_pok & SP_TEMP) { /* slated for free anyway? */
233 if (dstr->str_state == SS_INCR)
234 dstr->str_ptr -= dstr->str_u.str_useful;
235 Safefree(dstr->str_ptr);
237 dstr->str_ptr = sstr->str_ptr;
238 dstr->str_len = sstr->str_len;
239 dstr->str_cur = sstr->str_cur;
240 dstr->str_state = sstr->str_state;
241 dstr->str_pok = sstr->str_pok & ~SP_TEMP;
243 dstr->str_tainted = sstr->str_tainted;
245 sstr->str_ptr = Nullch;
247 sstr->str_pok = 0; /* wipe out any weird flags */
248 sstr->str_state = 0; /* so sstr frees uneventfully */
250 else { /* have to copy actual string */
252 if (dstr->str_state == SS_INCR) {
256 str_nset(dstr,sstr->str_ptr,sstr->str_cur);
258 if (dstr->str_nok = sstr->str_nok)
259 dstr->str_u.str_nval = sstr->str_u.str_nval;
262 dstr->str_u = sstr->str_u;
264 dstr->str_u.str_nval = sstr->str_u.str_nval;
266 if (dstr->str_cur == sizeof(STBP)) {
267 char *tmps = dstr->str_ptr;
269 if (*tmps == 'S' && bcmp(tmps,"StB",4) == 0) {
270 if (!dstr->str_magic) {
271 dstr->str_magic = str_smake(sstr->str_magic);
272 dstr->str_magic->str_rare = 'X';
278 else if (sstr->str_nok)
279 str_numset(dstr,sstr->str_u.str_nval);
281 if (dstr->str_state == SS_INCR)
282 Str_Grow(dstr,0); /* just force copy down */
285 dstr->str_u = sstr->str_u;
287 dstr->str_u.str_nval = sstr->str_u.str_nval;
289 dstr->str_pok = dstr->str_nok = 0;
293 str_nset(str,ptr,len)
298 if (str == &str_undef)
300 STR_GROW(str, len + 1);
302 (void)bcopy(ptr,str->str_ptr,len);
304 *(str->str_ptr+str->str_cur) = '\0';
305 str->str_nok = 0; /* invalidate number */
306 str->str_pok = 1; /* validate pointer */
308 str->str_tainted = tainted;
318 if (str == &str_undef)
323 STR_GROW(str, len + 1);
324 (void)bcopy(ptr,str->str_ptr,len+1);
326 str->str_nok = 0; /* invalidate number */
327 str->str_pok = 1; /* validate pointer */
329 str->str_tainted = tainted;
333 str_chop(str,ptr) /* like set but assuming ptr is in str */
337 register STRLEN delta;
339 if (!ptr || !(str->str_pok))
341 delta = ptr - str->str_ptr;
342 str->str_len -= delta;
343 str->str_cur -= delta;
344 str->str_ptr += delta;
345 if (str->str_state == SS_INCR)
346 str->str_u.str_useful += delta;
348 str->str_u.str_useful = delta;
349 str->str_state = SS_INCR;
351 str->str_nok = 0; /* invalidate number */
352 str->str_pok = 1; /* validate pointer (and unstudy str) */
355 str_ncat(str,ptr,len)
360 if (str == &str_undef)
364 STR_GROW(str, str->str_cur + len + 1);
365 (void)bcopy(ptr,str->str_ptr+str->str_cur,len);
367 *(str->str_ptr+str->str_cur) = '\0';
368 str->str_nok = 0; /* invalidate number */
369 str->str_pok = 1; /* validate pointer */
371 str->str_tainted |= tainted;
382 tainted |= sstr->str_tainted;
384 if (!(sstr->str_pok))
385 (void)str_2ptr(sstr);
387 str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
396 if (str == &str_undef)
403 STR_GROW(str, str->str_cur + len + 1);
404 (void)bcopy(ptr,str->str_ptr+str->str_cur,len+1);
406 str->str_nok = 0; /* invalidate number */
407 str->str_pok = 1; /* validate pointer */
409 str->str_tainted |= tainted;
414 str_append_till(str,from,fromend,delim,keeplist)
417 register char *fromend;
424 if (str == &str_undef)
428 len = fromend - from;
429 STR_GROW(str, str->str_cur + len + 1);
430 str->str_nok = 0; /* invalidate number */
431 str->str_pok = 1; /* validate pointer */
432 to = str->str_ptr+str->str_cur;
433 for (; from < fromend; from++,to++) {
434 if (*from == '\\' && from+1 < fromend && delim != '\\') {
436 if (from[1] == delim || from[1] == '\\')
441 else if (from[1] && index(keeplist,from[1]))
446 else if (*from == delim)
451 str->str_cur = to - str->str_ptr;
468 freestrroot = str->str_magic;
469 str->str_magic = Nullstr;
470 str->str_state = SS_NORM;
473 Newz(700+x,str,1,STR);
476 STR_GROW(str, len + 1);
481 str_magic(str, stab, how, name, namlen)
488 if (str == &str_undef || str->str_magic)
490 str->str_magic = Str_new(75,namlen);
491 str = str->str_magic;
492 str->str_u.str_stab = stab;
495 str_nset(str,name,namlen);
499 str_insert(bigstr,offset,len,little,littlelen)
508 register char *midend;
509 register char *bigend;
512 if (bigstr == &str_undef)
515 bigstr->str_pok = SP_VALID; /* disable possible screamer */
518 if (i > 0) { /* string might grow */
519 STR_GROW(bigstr, bigstr->str_cur + i + 1);
520 big = bigstr->str_ptr;
521 mid = big + offset + len;
522 midend = bigend = big + bigstr->str_cur;
525 while (midend > mid) /* shove everything down */
526 *--bigend = *--midend;
527 (void)bcopy(little,big+offset,littlelen);
528 bigstr->str_cur += i;
533 (void)bcopy(little,bigstr->str_ptr+offset,len);
538 big = bigstr->str_ptr;
541 bigend = big + bigstr->str_cur;
544 fatal("panic: str_insert");
546 if (mid - big > bigend - midend) { /* faster to shorten from end */
548 (void)bcopy(little, mid, littlelen);
553 (void)bcopy(midend, mid, i);
557 bigstr->str_cur = mid - big;
559 else if (i = mid - big) { /* faster from front */
562 str_chop(bigstr,midend-i);
567 (void)bcopy(little, mid, littlelen);
569 else if (littlelen) {
571 str_chop(bigstr,midend);
572 (void)bcopy(little,midend,littlelen);
575 str_chop(bigstr,midend);
580 /* make str point to what nstr did */
583 str_replace(str,nstr)
587 if (str == &str_undef)
589 if (str->str_state == SS_INCR)
590 Str_Grow(str,0); /* just force copy down */
591 if (nstr->str_state == SS_INCR)
594 Safefree(str->str_ptr);
595 str->str_ptr = nstr->str_ptr;
596 str->str_len = nstr->str_len;
597 str->str_cur = nstr->str_cur;
598 str->str_pok = nstr->str_pok;
599 str->str_nok = nstr->str_nok;
601 str->str_u = nstr->str_u;
603 str->str_u.str_nval = nstr->str_u.str_nval;
606 str->str_tainted = nstr->str_tainted;
609 str_free(nstr->str_magic);
617 if (!str || str == &str_undef)
619 if (str->str_state) {
620 if (str->str_state == SS_FREE) /* already freed */
622 if (str->str_state == SS_INCR && !(str->str_pok & 2)) {
623 str->str_ptr -= str->str_u.str_useful;
624 str->str_len += str->str_u.str_useful;
628 str_free(str->str_magic);
629 str->str_magic = freestrroot;
632 Safefree(str->str_ptr);
633 str->str_ptr = Nullch;
635 if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
636 arg_free(str->str_u.str_args);
640 if (str->str_len > 127) { /* next user not likely to want more */
641 Safefree(str->str_ptr); /* so give it back to malloc */
642 str->str_ptr = Nullch;
646 str->str_ptr[0] = '\0';
648 if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
649 arg_free(str->str_u.str_args);
653 str->str_state = SS_FREE;
655 str->str_tainted = 0;
658 #endif /* LEAKTEST */
679 if (!str1 || str1 == &str_undef)
680 return (str2 == Nullstr || str2 == &str_undef || !str2->str_cur);
681 if (!str2 || str2 == &str_undef)
682 return !str1->str_cur;
685 (void)str_2ptr(str1);
687 (void)str_2ptr(str2);
689 if (str1->str_cur != str2->str_cur)
692 return !bcmp(str1->str_ptr, str2->str_ptr, str1->str_cur);
701 if (!str1 || str1 == &str_undef)
702 return (str2 == Nullstr || str2 == &str_undef || !str2->str_cur)?0:-1;
703 if (!str2 || str2 == &str_undef)
704 return str1->str_cur != 0;
707 (void)str_2ptr(str1);
709 (void)str_2ptr(str2);
711 if (str1->str_cur < str2->str_cur) {
712 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
713 return retval < 0 ? -1 : 1;
717 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
718 return retval < 0 ? -1 : 1;
719 else if (str1->str_cur == str2->str_cur)
726 str_gets(str,fp,append)
731 register char *bp; /* we're going to steal some values */
732 register int cnt; /* from the stdio struct and put EVERYTHING */
733 register STDCHAR *ptr; /* in the innermost loop into registers */
734 register int newline = rschar;/* (assuming >= 6 registers) */
739 if (str == &str_undef)
741 #ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */
742 cnt = fp->_cnt; /* get count into register */
743 str->str_nok = 0; /* invalidate number */
744 str->str_pok = 1; /* validate pointer */
745 if (str->str_len <= cnt + 1) { /* make sure we have the room */
746 if (cnt > 80 && str->str_len > append) {
747 shortbuffered = cnt - str->str_len + append + 1;
748 cnt -= shortbuffered;
752 STR_GROW(str, append+cnt+2);/* (remembering cnt can be -1) */
757 bp = str->str_ptr + append; /* move these two too to registers */
761 while (--cnt >= 0) { /* this */ /* eat */
762 if ((*bp++ = *ptr++) == newline) /* really */ /* dust */
763 goto thats_all_folks; /* screams */ /* sed :-) */
766 if (shortbuffered) { /* oh well, must extend */
769 bpx = bp - str->str_ptr; /* prepare for possible relocation */
771 STR_GROW(str, str->str_len + append + cnt + 2);
772 bp = str->str_ptr + bpx; /* reconstitute our pointer */
776 fp->_cnt = cnt; /* deregisterize cnt and ptr */
778 i = _filbuf(fp); /* get more characters */
780 ptr = fp->_ptr; /* reregisterize cnt and ptr */
782 bpx = bp - str->str_ptr; /* prepare for possible relocation */
784 STR_GROW(str, bpx + cnt + 2);
785 bp = str->str_ptr + bpx; /* reconstitute our pointer */
787 if (i == newline) { /* all done for now? */
789 goto thats_all_folks;
791 else if (i == EOF) /* all done for ever? */
792 goto thats_really_all_folks;
793 *bp++ = i; /* now go back to screaming loop */
797 if (rslen > 1 && (bp - str->str_ptr < rslen || bcmp(bp - rslen, rs, rslen)))
798 goto screamer; /* go back to the fray */
799 thats_really_all_folks:
801 cnt += shortbuffered;
802 fp->_cnt = cnt; /* put these back or we're in trouble */
805 str->str_cur = bp - str->str_ptr; /* set length */
807 #else /* !STDSTDIO */ /* The big, slow, and stupid way */
810 static char buf[8192];
811 char * bpe = buf + sizeof(buf) - 3;
815 while ((i = getc(fp)) != EOF && (*bp++ = i) != newline && bp < bpe) ;
822 if (i != EOF /* joy */
828 (str->str_cur < rslen
830 bcmp(str->str_ptr + str->str_cur - rslen, rs, rslen)
841 #endif /* STDSTDIO */
843 return str->str_cur - append ? str->str_ptr : Nullch;
852 CMD *oldcurcmd = curcmd;
853 int oldperldb = perldb;
857 str_sset(linestr,str);
859 oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
860 bufend = bufptr + linestr->str_cur;
861 if (++loop_ptr >= loop_max) {
863 Renew(loop_stack, loop_max, struct loop);
865 loop_stack[loop_ptr].loop_label = "_EVAL_";
866 loop_stack[loop_ptr].loop_sp = 0;
869 deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
872 if (setjmp(loop_stack[loop_ptr].loop_env)) {
876 fatal("%s\n",stab_val(stabent("@",TRUE))->str_ptr);
880 char *tmps = loop_stack[loop_ptr].loop_label;
881 deb("(Popping label #%d %s)\n",loop_ptr,
888 curcmd->c_line = oldcurcmd->c_line;
893 if (retval || error_count)
894 fatal("Invalid component in string or format");
897 if (cmd->c_type != C_EXPR || cmd->c_next || arg->arg_type != O_LIST)
898 fatal("panic: error in parselist %d %x %d", cmd->c_type,
899 cmd->c_next, arg ? arg->arg_type : -1);
909 register char *s = str_get(src);
910 register char *send = s + src->str_cur;
915 register int brackets;
921 toparse = Str_new(76,0);
925 str_nset(toparse,"",0);
928 if (*s == '\\' && s[1] && index("$@[{\\]}lLuUE",s[1])) {
929 str_ncat(str, t, s - t);
932 str_ncat(str, "$c", 2);
933 sawcase = (*s != 'E');
936 if (*nointrp && s+1 < send)
937 if (*s != '@' && (*s != '$' || index(nointrp,s[1])))
939 str_ncat(str, "$b", 2);
945 else if (*s == '$' && s+1 < send && *nointrp && index(nointrp,s[1])) {
946 str_ncat(str, t, s - t);
947 str_ncat(str, "$b", 2);
952 else if ((*s == '@' || *s == '$') && s+1 < send) {
955 if (*s == '$' && s[1] == '#' && (isalpha(s[2]) || s[2] == '_'))
957 s = scanident(s,send,tokenbuf);
959 (!(stab = stabent(tokenbuf,FALSE)) ||
960 (*s == '{' ? !stab_xhash(stab) : !stab_xarray(stab)) )) {
963 continue; /* grandfather @ from old scripts */
965 str_ncat(str,"$a",2);
966 str_ncat(toparse,",",1);
967 if (t[1] != '{' && (*s == '[' || *s == '{' /* }} */ ) &&
968 (stab = stabent(tokenbuf,FALSE)) &&
969 ((*s == '[') ? (stab_xarray(stab) != 0) : (stab_xhash(stab) != 0)) ) {
991 s = cpytill(tokenbuf,s+1,send,*s,&len);
993 fatal("Unterminated string");
998 } while (brackets > 0 && s < send);
1000 fatal("Unmatched brackets in string");
1001 if (*nointrp) { /* we're in a regular expression */
1003 if (*d == '{' && s[-1] == '}') { /* maybe {n,m} */
1005 if (isdigit(*d)) { /* matches /^{\d,?\d*}$/ */
1011 s = checkpoint; /* Is {n,m}! Backoff! */
1014 else if (*d == '[' && s[-1] == ']') { /* char class? */
1015 int weight = 2; /* let's weigh the evidence */
1017 unsigned char un_char = 0, last_un_char;
1019 Zero(seen,256,char);
1023 else if (d[1] == '$')
1025 if (isdigit(d[1])) {
1027 if (isdigit(d[2]) && !d[3])
1033 for (d++; d < s; d++) {
1034 last_un_char = un_char;
1035 un_char = (unsigned char)*d;
1039 weight -= seen[un_char] * 10;
1040 if (isalpha(d[1]) || isdigit(d[1]) ||
1042 d = scanident(d,s,tokenbuf);
1043 if (stabent(tokenbuf,FALSE))
1048 else if (*d == '$' && d[1] &&
1049 index("[#!%*<>()-=",d[1])) {
1050 if (!d[2] || /*{*/ index("])} =",d[2]))
1059 if (index("wds",d[1]))
1061 else if (seen['\''] || seen['"'])
1063 else if (index("rnftb",d[1]))
1065 else if (isdigit(d[1])) {
1067 while (d[1] && isdigit(d[1]))
1075 if (last_un_char < (unsigned char) d[1]
1077 if (index("aA01! ",last_un_char))
1079 if (index("zZ79~",d[1]))
1085 if (isalpha(*d) && d[1] && isalpha(d[1])) {
1087 if (yylex() != WORD)
1091 if (un_char == last_un_char + 1)
1093 weight -= seen[un_char];
1100 fprintf(stderr,"[%s] weight %d\n",
1101 checkpoint+1,weight);
1104 if (weight >= 0) /* probably a character class */
1110 str_ncat(toparse, "join($\",", 8);
1111 if (t[1] == '{' && s[-1] == '}') {
1112 str_ncat(toparse, t, 1);
1113 str_ncat(toparse, t+2, s - t - 3);
1116 str_ncat(toparse, t, s - t);
1118 str_ncat(toparse, ")", 1);
1124 str_ncat(str,t,s-t);
1126 str_ncat(str, "$cE", 3);
1127 if (toparse->str_ptr && *toparse->str_ptr == ',') {
1128 *toparse->str_ptr = '(';
1129 str_ncat(toparse,",$$);",5);
1130 str->str_u.str_args = parselist(toparse);
1131 str->str_u.str_args->arg_len--; /* ignore $$ reference */
1134 str->str_u.str_args = Nullarg;
1136 str->str_pok |= SP_INTRP;
1138 str_replace(src,str);
1149 register char *send;
1150 register STR **elem;
1157 if (str == &str_undef)
1159 if (!(src->str_pok & SP_INTRP)) {
1160 int oldsave = savestack->ary_fill;
1162 (void)savehptr(&curstash);
1163 curstash = curcmd->c_stash; /* so stabent knows right package */
1165 restorelist(oldsave);
1167 s = src->str_ptr; /* assumed valid since str_pok set */
1169 send = s + src->str_cur;
1171 if (src->str_u.str_args) {
1172 (void)eval(src->str_u.str_args,G_ARRAY,sp);
1173 /* Assuming we have correct # of args */
1174 elem = stack->ary_array + sp;
1179 if (*s == '$' && s+1 < send) {
1181 str_ncat(str,t,s-t);
1184 fatal("panic: unknown interp cookie\n");
1187 str_scat(str,*++elem);
1190 str_ncat(str,++s,1);
1193 if (docase && str->str_cur >= docase) {
1194 char *b = str->str_ptr + --docase;
1197 lcase(b, str->str_ptr + str->str_cur);
1199 ucase(b, str->str_ptr + str->str_cur);
1201 if (u) /* note that l & u are independent of L & U */
1207 docase = str->str_cur + 1;
1226 docase = L = U = l = u = 0;
1237 str_ncat(str,t,s-t);
1243 register char *send;
1246 if (isascii(*s) && islower(*s))
1254 register char *send;
1257 if (isascii(*s) && isupper(*s))
1269 if (!str || str == &str_undef)
1272 str->str_u.str_nval += 1.0;
1276 if (!str->str_pok || !*str->str_ptr) {
1277 str->str_u.str_nval = 1.0;
1283 while (isalpha(*d)) d++;
1284 while (isdigit(*d)) d++;
1286 str_numset(str,atof(str->str_ptr) + 1.0); /* punt */
1290 while (d >= str->str_ptr) {
1300 *(d--) -= 'z' - 'a' + 1;
1303 /* oh,oh, the number grew */
1304 STR_GROW(str, str->str_cur + 2);
1306 for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
1318 if (!str || str == &str_undef)
1321 str->str_u.str_nval -= 1.0;
1325 if (!str->str_pok) {
1326 str->str_u.str_nval = -1.0;
1330 str_numset(str,atof(str->str_ptr) - 1.0);
1333 /* Make a string that will exist for the duration of the expression
1334 * evaluation. Actually, it may have to last longer than that, but
1335 * hopefully cmd_exec won't free it until it has been assigned to a
1336 * permanent location. */
1338 static long tmps_size = -1;
1344 register STR *str = Str_new(78,0);
1346 str_sset(str,oldstr);
1347 if (++tmps_max > tmps_size) {
1348 tmps_size = tmps_max;
1349 if (!(tmps_size & 127)) {
1351 Renew(tmps_list, tmps_size + 128, STR*);
1353 New(702,tmps_list, 128, STR*);
1356 tmps_list[tmps_max] = str;
1358 str->str_pok |= SP_TEMP;
1362 /* same thing without the copying */
1368 if (str == &str_undef)
1370 if (++tmps_max > tmps_size) {
1371 tmps_size = tmps_max;
1372 if (!(tmps_size & 127)) {
1374 Renew(tmps_list, tmps_size + 128, STR*);
1376 New(704,tmps_list, 128, STR*);
1379 tmps_list[tmps_max] = str;
1381 str->str_pok |= SP_TEMP;
1390 register STR *str = Str_new(79,0);
1394 str_nset(str,s,len);
1402 register STR *str = Str_new(80,0);
1408 /* make an exact duplicate of old */
1414 register STR *new = Str_new(81,0);
1418 if (old->str_state == SS_FREE) {
1419 warn("semi-panic: attempt to dup freed string");
1422 if (old->str_state == SS_INCR && !(old->str_pok & 2))
1425 Safefree(new->str_ptr);
1426 Copy(old,new,1,STR);
1428 new->str_ptr = nsavestr(old->str_ptr,old->str_len);
1429 new->str_pok &= ~SP_TEMP;
1438 register HENT *entry;
1439 register STAB *stab;
1442 register SPAT *spat;
1445 if (!*s) { /* reset ?? searches */
1446 for (spat = stash->tbl_spatroot;
1448 spat = spat->spat_next) {
1449 spat->spat_flags &= ~SPAT_USED;
1454 /* reset variables */
1456 if (!stash->tbl_array)
1464 for ( ; i <= max; i++) {
1465 for (entry = stash->tbl_array[i];
1467 entry = entry->hent_next) {
1468 stab = (STAB*)entry->hent_val;
1469 str = stab_val(stab);
1473 str->str_tainted = tainted;
1475 if (str->str_ptr != Nullch)
1476 str->str_ptr[0] = '\0';
1477 if (stab_xarray(stab)) {
1478 aclear(stab_xarray(stab));
1480 if (stab_xhash(stab)) {
1481 hclear(stab_xhash(stab), FALSE);
1482 if (stab == envstab)
1483 environ[0] = Nullch;
1496 fprintf(stderr,"%s %d %d %d\n",s,tainted,uid, euid);
1498 if (tainted && (!euid || euid != uid || egid != gid)) {
1508 register STR *envstr;
1510 envstr = hfetch(stab_hash(envstab),"PATH",4,FALSE);
1511 if (envstr == &str_undef || envstr->str_tainted) {
1513 if (envstr->str_tainted == 2)
1514 taintproper("Insecure directory in PATH");
1516 taintproper("Insecure PATH");
1518 envstr = hfetch(stab_hash(envstab),"IFS",3,FALSE);
1519 if (envstr != &str_undef && envstr->str_tainted) {
1521 taintproper("Insecure IFS");