3 #include "ksh_limval.h"
13 * WARNING: unreadable code, needs a rewrite
15 * if (flag&INTEGER), val.i contains integer value, and type contains base.
16 * otherwise, (val.s + type) contains string value.
17 * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting.
19 static struct tbl vtemp
;
20 static struct block
*ltemp
; /* ugly */
21 static XPtrV
*envtemp
; /* also ugly */
24 static void export
ARGS((struct tbl
*vp
, const char *val
));
25 static int special
ARGS((const char *name
));
26 static void unspecial
ARGS((const char *name
));
27 static void getspec
ARGS((struct tbl
*vp
));
28 static void setspec
ARGS((struct tbl
*vp
));
29 static void unsetspec
ARGS((struct tbl
*vp
));
30 static struct tbl
*arraysearch
ARGS((struct tbl
*, int));
33 * create a new block for function calls and simple commands
34 * assume caller has allocated and set up e->loc
40 static char *const empty
[] = {null
};
42 l
= (struct block
*) alloc(sizeof(struct block
), ATEMP
);
44 ainit(&l
->area
); /* todo: could use e->area (l->area => l->areap) */
47 l
->argv
= (char **) empty
;
49 l
->argc
= e
->loc
->argc
;
50 l
->argv
= e
->loc
->argv
;
52 l
->exit
= l
->error
= NULL
;
53 transitional_tinit(&l
->vars
, &l
->area
);
54 transitional_tinit(&l
->funs
, &l
->area
);
59 void popblock_walk(const void *nodep
, const VISIT which
, const int UNUSED(depth
)) {
60 struct tbl
*datap
, *vq
;
68 datap
= *(struct tbl
**)nodep
;
69 if (datap
->flag
& SPECIAL
) {
70 if ((vq
= global(datap
->name
))->flag
& ISSET
)
81 * pop a block handling special variables
86 struct block
*l
= e
->loc
;
88 e
->loc
= l
->next
; /* pop block */
89 twalk(l
->vars
.root
, popblock_walk
);
90 if (l
->flags
& BF_DOGETOPTS
)
91 user_opt
= l
->getopts_state
;
96 /* called by main() to initialize variable data structures */
100 static const struct {
104 { "COLUMNS", V_COLUMNS
},
106 { "OPTIND", V_OPTIND
},
108 { "TMPDIR", V_TMPDIR
},
110 { "HISTFILE", V_HISTFILE
},
111 { "HISTSIZE", V_HISTSIZE
},
114 { "EDITOR", V_EDITOR
},
115 { "VISUAL", V_VISUAL
},
119 { "MAILCHECK", V_MAILCHECK
},
120 { "MAILPATH", V_MAILPATH
},
121 { "RANDOM", V_RANDOM
},
122 { "SECONDS", V_SECONDS
},
123 { "TMOUT", V_TMOUT
},
125 { "LINENO", V_LINENO
},
131 specials_root
= NULL
;
132 for (i
= 0; names
[i
].name
; i
++) {
133 tp
= transitional_tenter((void **)&specials_root
, names
[i
].name
, APERM
);
134 tp
->flag
= DEFINED
|ISSET
;
135 tp
->type
= names
[i
].v
;
139 /* Used to calculate an array index for global()/local(). Sets *arrayp to
140 * non-zero if this is an array, sets *valp to the array index, returns
141 * the basename of the array.
144 array_index_calc(n
, arrayp
, valp
)
153 p
= skip_varname(n
, FALSE
);
154 if (p
!= n
&& *p
== '[' && (len
= array_ref_len(p
))) {
158 /* Calculate the value of the subscript */
160 tmp
= str_nsave(p
+1, len
-2, ATEMP
);
161 sub
= substitute(tmp
, 0);
163 n
= str_nsave(n
, p
- n
, ATEMP
);
164 evaluate(sub
, &rval
, KSH_UNWIND_ERROR
);
165 if (rval
< 0 || rval
> ARRAYMAX
)
166 errorf("%s: subscript out of range", n
);
174 * Search for variable, if not found create globally.
177 global(const char *n
)
179 struct block
*l
= e
->loc
;
185 /* Check to see if this is an array */
186 n
= array_index_calc(n
, &array
, &val
);
188 if (!isalpha(c
) && c
!='_') {
190 errorf("bad substitution");
197 for (c
= 0; isdigit(*n
); n
++)
200 /* setstr can't fail here */
201 setstr(vp
, l
->argv
[c
], KSH_RETURN_ERROR
);
208 vp
->flag
|= ISSET
|INTEGER
;
214 /* If no job, expand to nothing */
215 if ((vp
->val
.i
= j_async()) == 0)
216 vp
->flag
&= ~(ISSET
|INTEGER
);
225 vp
->flag
&= ~INTEGER
;
226 vp
->val
.s
= getoptions();
229 vp
->flag
&= ~(ISSET
|INTEGER
);
233 for (l
= e
->loc
; ; l
= l
->next
) {
234 vp
= transitional_tsearch(&l
->vars
.root
, n
);
237 return (arraysearch(vp
, val
));
244 vp
= transitional_tenter(&l
->vars
.root
, n
, APERM
);
246 vp
= arraysearch(vp
, val
);
254 * Search for local variable, if not found create locally.
257 local(const char *n
, bool_t copy
)
259 struct block
*l
= e
->loc
;
264 /* Check to see if this is an array */
265 n
= array_index_calc(n
, &array
, &val
);
266 if (!isalpha(*n
) && *n
!='_') {
268 vp
->flag
= DEFINED
|RDONLY
;
273 vp
= transitional_tenter(&l
->vars
.root
, n
, &l
->area
);
274 if (copy
&& !(vp
->flag
& DEFINED
)) {
275 struct block
*ll
= l
;
276 struct tbl
*vq
= (struct tbl
*) 0;
278 while ((ll
= ll
->next
) && !(vq
= transitional_tsearch(&ll
->vars
.root
, n
)))
281 vp
->flag
|= vq
->flag
& (EXPORT
|INTEGER
|RDONLY
);
282 if (vq
->flag
& INTEGER
)
284 vp
->u2
.field
= vq
->u2
.field
;
288 vp
= arraysearch(vp
, val
);
295 /* get variable string value */
297 str_val(struct tbl
*vp
)
301 if ((vp
->flag
&SPECIAL
))
303 if (!(vp
->flag
&ISSET
))
304 s
= null
; /* special to dollar() */
305 else if (!(vp
->flag
&INTEGER
)) /* string source */
306 s
= vp
->val
.s
+ vp
->type
;
307 else { /* integer source */
308 /* worst case number length is when base=2, so use BITS(long) */
309 /* minus base # number null */
310 static char strbuf
[1 + 2 + 1 + BITS(long) + 1];
311 const char *digits
= "0123456789abcdefghijklmnopqrstuvwxyz";
312 register unsigned long n
;
315 s
= strbuf
+ sizeof(strbuf
);
316 n
= (vp
->val
.i
< 0) ? -vp
->val
.i
: vp
->val
.i
;
317 base
= (vp
->type
== 0) ? 10 : vp
->type
;
321 *--s
= digits
[n
% base
];
326 *--s
= digits
[base
% 10];
328 *--s
= digits
[base
/ 10];
336 /* get variable integer value, with error checking */
339 register struct tbl
*vp
;
344 base
= getint(vp
, &num
);
346 /* XXX check calls - is error here ok by POSIX? */
347 errorf("%s: bad number", str_val(vp
));
351 /* set variable to string value */
353 setstr(struct tbl
*vq
, const char *s
, int error_ok
)
355 int no_ro_check
= error_ok
& 0x4;
357 if ((vq
->flag
& RDONLY
) && !no_ro_check
) {
358 warningf(TRUE
, "%s: is read only", vq
->name
);
363 if (!(vq
->flag
&INTEGER
)) { /* string dest */
364 if ((vq
->flag
&ALLOC
)) {
367 && s
<= vq
->val
.s
+ strlen(vq
->val
.s
))
368 internal_errorf(TRUE
,
369 "setstr: %s=%s: assigning to self",
371 afree((void*)vq
->val
.s
, vq
->areap
);
373 vq
->flag
&= ~(ISSET
|ALLOC
);
375 if ((vq
->flag
&EXPORT
))
378 vq
->val
.s
= str_save(s
, vq
->areap
);
379 if (vq
->val
.s
) /* <sjg> don't lie */
382 } else /* integer dest */
383 if (!v_evaluate(vq
, s
, error_ok
))
386 if ((vq
->flag
&SPECIAL
))
391 /* set variable to integer */
393 setint(struct tbl
*vq
, long n
)
395 if (!(vq
->flag
&INTEGER
)) {
396 struct tbl
*vp
= &vtemp
;
397 vp
->flag
= (ISSET
|INTEGER
);
401 /* setstr can't fail here */
402 setstr(vq
, str_val(vp
), KSH_RETURN_ERROR
);
406 if ((vq
->flag
&SPECIAL
))
411 getint(struct tbl
*vp
, long *nump
)
418 if (vp
->flag
&SPECIAL
)
420 /* XXX is it possible for ISSET to be set and val.s to be 0? */
421 if (!(vp
->flag
&ISSET
) || (!(vp
->flag
&INTEGER
) && vp
->val
.s
== NULL
))
423 if (vp
->flag
&INTEGER
) {
427 s
= vp
->val
.s
+ vp
->type
;
428 if (s
== NULL
) /* redundent given initial test */
434 if ((c
= *s
) == '0') {
435 /* 0 means octal, 0x means hex */
436 if((c
= *++s
) == 'x') {
444 for (c
= *s
++; c
; c
= *s
++) {
447 } else if (c
== '#') {
449 if (have_base
|| base
< 2 || base
> 36)
453 } else if (isalnum(c
) || c
=='_') {
457 c
-= 'a' - 10; /* todo: assumes ascii */
459 c
-= 'A' - 10; /* todo: assumes ascii */
461 c
= -1; /* _: force error */
462 if (c
< 0 || c
>= base
)
464 num
= num
* base
+ c
;
474 /* convert variable vq to integer variable, setting its value from vp
475 * (vq and vp may be the same)
479 register struct tbl
*vq
, *vp
;
484 if ((base
= getint(vp
, &num
)) == -1)
486 if (!(vq
->flag
& INTEGER
) && (vq
->flag
& ALLOC
)) {
488 afree(vq
->val
.s
, vq
->areap
);
491 if (vq
->type
== 0) /* default base */
493 vq
->flag
|= ISSET
|INTEGER
;
494 if (vq
->flag
&SPECIAL
)
499 #ifdef SILLY_FEATURES
512 p
= (char *) alloc(nlen
+ 1, ATEMP
);
513 memcpy(p
, s
, olen
+ 1);
517 #endif /* SILLY_FEATURES */
520 * make vp->val.s be "name=value" for quick exporting.
523 export(struct tbl
*vp
, const char *val
)
526 char *op
= (vp
->flag
&ALLOC
) ? vp
->val
.s
: NULL
;
527 int namelen
= strlen(vp
->name
);
528 int vallen
= strlen(val
) + 1;
531 xp
= (char*)alloc(namelen
+ 1 + vallen
, vp
->areap
);
532 memcpy(vp
->val
.s
= xp
, vp
->name
, namelen
);
535 vp
->type
= xp
- vp
->val
.s
; /* offset to value */
536 memcpy(xp
, val
, vallen
);
538 afree((void*)op
, vp
->areap
);
542 * lookup variable (according to (set&LOCAL)),
543 * set its attributes (INTEGER, RDONLY, EXPORT, TRACE),
544 * and optionally set its value if an assignment.
547 typeset(const char *var
, Tflag set
, Tflag clr
, int UNUSED(field
), int base
)
550 struct tbl
*vpbase
, *t
;
554 /* check for valid variable name, search for value */
555 val
= skip_varname(var
, FALSE
);
561 len
= array_ref_len(val
);
564 /* IMPORT is only used when the shell starts up and is
565 * setting up its environment. Allow only simple array
566 * references at this time since parameter/command substitution
567 * is preformed on the [expression], which would be a major
572 for (i
= 1; i
< len
- 1; i
++)
573 if (!isdigit(val
[i
]))
579 tvar
= str_nsave(var
, val
++ - var
, ATEMP
);
581 /* Importing from original envirnment: must have an = */
588 vp
= (set
&LOCAL
) ? local(tvar
, (set
& LOCAL_COPY
) ? TRUE
: FALSE
)
590 set
&= ~(LOCAL
|LOCAL_COPY
);
592 vpbase
= (vp
->flag
& ARRAY
) ? global(arrayname(var
)) : vp
;
594 /* only allow export flag to be set. at&t ksh allows any attribute to
595 * be changed, which means it can be truncated or modified
598 if ((vpbase
->flag
&RDONLY
)
599 && (val
|| clr
|| (set
& ~EXPORT
)))
600 /* XXX check calls - is error here ok by POSIX? */
601 errorf("%s: is read only", tvar
);
605 /* most calls are with set/clr == 0 */
608 /* XXX if x[0] isn't set, there will be problems: need to have
609 * one copy of attributes for arrays...
611 for (t
= vpbase
; t
; t
= t
->u
.array
) {
613 char UNINITIALIZED(*s
);
614 char UNINITIALIZED(*free_me
);
616 fake_assign
= (t
->flag
& ISSET
) && (!val
|| t
!= vp
)
617 && (((t
->flag
& INTEGER
)
619 || (!(t
->flag
& INTEGER
) && (set
& INTEGER
)));
621 if (t
->flag
& INTEGER
) {
623 free_me
= (char *) 0;
625 s
= t
->val
.s
+ t
->type
;
626 free_me
= (t
->flag
& ALLOC
) ? t
->val
.s
631 if (!(t
->flag
& INTEGER
) && (set
& INTEGER
)) {
635 t
->flag
= (t
->flag
| set
) & ~clr
;
636 /* Don't change base if assignment is to be done,
637 * in case assignment fails.
639 if ((set
& INTEGER
) && base
> 0 && (!val
|| t
!= vp
))
642 if (!setstr(t
, s
, KSH_RETURN_ERROR
)) {
643 /* Somewhat arbitrary action here:
644 * zap contents of varibale, but keep
648 if (t
->flag
& INTEGER
)
652 afree((void*) t
->val
.s
,
654 t
->flag
&= ~(ISSET
|ALLOC
);
659 afree((void *) free_me
, t
->areap
);
667 if (vp
->flag
&INTEGER
) {
668 /* do not zero base before assignment */
669 setstr(vp
, val
, KSH_UNWIND_ERROR
| 0x4);
670 /* Done after assignment to override default */
674 /* setstr can't fail (readonly check already done) */
675 setstr(vp
, val
, KSH_RETURN_ERROR
| 0x4);
678 /* only x[0] is ever exported, so use vpbase */
679 if ((vpbase
->flag
&EXPORT
) && !(vpbase
->flag
&INTEGER
)
680 && vpbase
->type
== 0)
681 export(vpbase
, (vpbase
->flag
&ISSET
) ? vpbase
->val
.s
: null
);
686 /* Unset a variable. array_ref is set if there was an array reference in
687 * the name lookup (eg, x[2]).
690 unset(struct tbl
*vp
, int array_ref
)
692 if (vp
->flag
& ALLOC
)
693 afree((void*)vp
->val
.s
, vp
->areap
);
694 if ((vp
->flag
& ARRAY
) && !array_ref
) {
697 /* Free up entire array */
698 for (a
= vp
->u
.array
; a
; ) {
701 if (tmp
->flag
& ALLOC
)
702 afree((void *) tmp
->val
.s
, tmp
->areap
);
703 afree(tmp
, tmp
->areap
);
705 vp
->u
.array
= (struct tbl
*) 0;
707 /* If foo[0] is being unset, the remainder of the array is kept... */
708 vp
->flag
&= SPECIAL
| (array_ref
? ARRAY
|DEFINED
: 0);
709 if (vp
->flag
& SPECIAL
)
710 unsetspec(vp
); /* responsible for `unspecial'ing var */
713 /* return a pointer to the first char past a legal variable name (returns the
714 * argument if there is no legal name, returns * a pointer to the terminating
715 * null if whole string is legal).
718 skip_varname(const char *s
, int aok
)
722 if (s
&& (isalpha(*s
) || *s
=='_' )) {
723 while (*++s
&& (isalnum(*s
) || *s
=='_'))
725 if (aok
&& *s
== '[' && (alen
= array_ref_len(s
)))
731 /* Return a pointer to the first character past any legal variable name. */
733 skip_wdvarname(const char *s
, int aok
)
735 if (s
[0] == CHAR
&& (isalpha(s
[1]) || s
[1]=='_')) {
738 while (s
[0] == CHAR
&& (isalnum(s
[1]) || s
[1]=='_'));
739 if (aok
&& s
[0] == CHAR
&& s
[1] == '[') {
740 /* skip possible array de-reference */
752 else if (c
== ']' && --depth
== 0) {
762 /* Check if coded string s is a variable name */
764 is_wdvarname(const char *s
, int aok
)
766 char *p
= skip_wdvarname(s
, aok
);
768 return p
!= s
&& p
[0] == EOS
;
771 /* Check if coded string s is a variable assignment */
773 is_wdvarassign(const char *s
)
775 char *p
= skip_wdvarname(s
, TRUE
);
777 return p
!= s
&& p
[0] == CHAR
&& p
[1] == '=';
780 void makeenv_walk(const void *nodep
, const VISIT which
, const int UNUSED(depth
)) {
781 struct tbl
*datap
, *vp2
;
790 datap
= *(struct tbl
**)nodep
;
791 if ((datap
->flag
&(ISSET
|EXPORT
)) == (ISSET
|EXPORT
)) {
792 /* unexport any redefined instances */
793 for (l2
= ltemp
->next
; l2
!= NULL
; l2
= l2
->next
) {
794 vp2
= transitional_tsearch(&l2
->vars
.root
, datap
->name
);
796 vp2
->flag
&= ~EXPORT
;
798 if ((datap
->flag
&INTEGER
)) {
799 /* integer to string */
801 val
= str_val(datap
);
802 datap
->flag
&= ~(INTEGER
|RDONLY
);
803 /* setstr can't fail here */
804 setstr(datap
, val
, KSH_RETURN_ERROR
);
806 XPput(*envtemp
, datap
->val
.s
);
813 * Make the exported environment from the exported names in the dictionary.
818 struct block
*l
= e
->loc
;
822 for (l
= e
->loc
; l
!= NULL
; l
= l
->next
) {
825 twalk(l
->vars
.root
, makeenv_walk
);
828 return (char **) XPclose(env
);
832 * Called after a fork in parent to bump the random number generator.
833 * Done to ensure children will not get the same random number sequence
834 * if the parent doesn't use $RANDOM.
843 * handle special variables with side effects - PATH, SECONDS.
846 /* Test if name is a special parameter */
848 special(const char *name
)
852 tp
= transitional_tsearch((void **)&specials_root
, name
);
853 return tp
&& (tp
->flag
& ISSET
) ? tp
->type
: V_NONE
;
856 /* Make a variable non-special */
858 unspecial(const char *name
)
862 tp
= transitional_tsearch((void **)&specials_root
, name
);
864 transitional_tdelete((void **)&specials_root
, tp
);
868 static time_t seconds
; /* time SECONDS last set */
870 static int user_lineno
; /* what user set $LINENO to */
874 register struct tbl
*vp
;
876 switch (special(vp
->name
)) {
879 vp
->flag
&= ~SPECIAL
;
880 /* On start up the value of SECONDS is used before seconds
881 * has been set - don't do anything in this case
882 * (see initcoms[] in main.c).
884 if (vp
->flag
& ISSET
)
885 setint(vp
, (long) (time((time_t *)0) - seconds
));
889 vp
->flag
&= ~SPECIAL
;
890 setint(vp
, (long) (rand() & 0x7fff));
896 vp
->flag
&= ~SPECIAL
;
897 setint(vp
, (long) histsize
);
902 vp
->flag
&= ~SPECIAL
;
903 setint(vp
, (long) uoptind
);
907 vp
->flag
&= ~SPECIAL
;
908 setint(vp
, (long) current_lineno
+ user_lineno
);
915 setspec(struct tbl
*vp
)
919 switch (special(vp
->name
)) {
923 path
= str_save(str_val(vp
), APERM
);
926 setctypes(s
= str_val(vp
), C_IFS
);
930 vp
->flag
&= ~SPECIAL
;
931 optind
= uoptind
= ((int) intval(vp
));
936 afree(tmpdir
, APERM
);
939 /* Use tmpdir iff it is an absolute path, is writable and
940 * searchable and is a directory...
945 if (ISABSPATH(s
) && eaccess(s
, W_OK
|X_OK
) == 0
946 && stat(s
, &statb
) == 0 && S_ISDIR(statb
.st_mode
))
947 tmpdir
= str_save(s
, APERM
);
952 vp
->flag
&= ~SPECIAL
;
953 sethistsize((int) intval(vp
));
957 sethistfile(str_val(vp
));
962 set_editmode(str_val(vp
));
965 if (!(global("VISUAL")->flag
& ISSET
))
966 set_editmode(str_val(vp
));
969 if ((x_cols
= intval(vp
)) <= MIN_COLS
)
981 vp
->flag
&= ~SPECIAL
;
986 vp
->flag
&= ~SPECIAL
;
987 srand((unsigned int)intval(vp
));
991 vp
->flag
&= ~SPECIAL
;
992 seconds
= time((time_t*) 0) - intval(vp
);
996 /* at&t ksh seems to do this (only listen if integer) */
997 if (vp
->flag
& INTEGER
)
998 ksh_tmout
= vp
->val
.i
>= 0 ? vp
->val
.i
: 0;
1002 vp
->flag
&= ~SPECIAL
;
1003 /* The -1 is because line numbering starts at 1. */
1004 user_lineno
= (unsigned int) intval(vp
) - current_lineno
- 1;
1005 vp
->flag
|= SPECIAL
;
1011 unsetspec(struct tbl
*vp
)
1013 switch (special(vp
->name
)) {
1017 path
= str_save(def_path
, APERM
);
1020 setctypes(" \t\n", C_IFS
);
1024 /* should not become unspecial */
1026 afree(tmpdir
, APERM
);
1027 tmpdir
= (char *) 0;
1041 case V_MAILCHECK
: /* at&t ksh leaves previous value in place */
1044 case V_TMOUT
: /* at&t ksh leaves previous value in place */
1046 unspecial(vp
->name
);
1049 /* at&t ksh man page says OPTIND, OPTARG and _ lose special meaning,
1050 * but OPTARG does not (still set by getopts) and _ is also still
1051 * set in various places.
1052 * Don't know what at&t does for:
1053 * MAIL, MAILPATH, HISTSIZE, HISTFILE,
1054 * Unsetting these in at&t ksh does not loose the `specialness':
1055 * no effect: IFS, COLUMNS, PATH, TMPDIR,
1062 * Search for (and possibly create) a table entry starting with
1063 * vp, indexed by val.
1066 arraysearch(struct tbl
*vp
, int val
)
1068 struct tbl
*prev
, *curr
, *new;
1070 vp
->flag
|= ARRAY
|DEFINED
;
1072 /* The table entry is always [0] */
1079 while (curr
&& curr
->index
< val
) {
1081 curr
= curr
->u
.array
;
1083 if (curr
&& curr
->index
== val
) {
1084 if (curr
->flag
&ISSET
)
1089 new = (struct tbl
*)alloc(sizeof(struct tbl
)+strlen(vp
->name
)+1, vp
->areap
);
1090 strcpy(new->name
, vp
->name
);
1091 new->flag
= vp
->flag
& ~(ALLOC
|DEFINED
|ISSET
|SPECIAL
);
1092 new->type
= vp
->type
;
1093 new->areap
= vp
->areap
;
1094 new->u2
.field
= vp
->u2
.field
;
1096 if (curr
!= new) { /* not reusing old array entry */
1097 prev
->u
.array
= new;
1098 new->u
.array
= curr
;
1103 /* Return the length of an array reference (eg, [1+2]) - cp is assumed
1104 * to point to the open bracket. Returns 0 if there is no matching closing
1108 array_ref_len(const char *cp
)
1114 while ((c
= *s
++) && (c
!= ']' || --depth
))
1123 * Make a copy of the base of an array name
1126 arrayname(const char *str
)
1130 if ((p
= strchr(str
, '[')) == 0)
1131 /* Shouldn't happen, but why worry? */
1132 return (char *) str
;
1134 return str_nsave(str
, p
- str
, ATEMP
);