GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/var.c Lines: 486 603 80.6 %
Date: 2017-11-07 Branches: 342 489 69.9 %

Line Branch Exec Source
1
/*	$OpenBSD: var.c,v 1.59 2017/08/30 17:08:45 jca Exp $	*/
2
3
#include <sys/stat.h>
4
5
#include <ctype.h>
6
#include <errno.h>
7
#include <limits.h>
8
#include <stdlib.h>
9
#include <string.h>
10
#include <time.h>
11
#include <unistd.h>
12
13
#include "sh.h"
14
15
/*
16
 * Variables
17
 *
18
 * WARNING: unreadable code, needs a rewrite
19
 *
20
 * if (flag&INTEGER), val.i contains integer value, and type contains base.
21
 * otherwise, (val.s + type) contains string value.
22
 * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting.
23
 */
24
static	struct tbl vtemp;
25
static	struct table specials;
26
static char	*formatstr(struct tbl *, const char *);
27
static void	export(struct tbl *, const char *);
28
static int	special(const char *);
29
static void	unspecial(const char *);
30
static void	getspec(struct tbl *);
31
static void	setspec(struct tbl *);
32
static void	unsetspec(struct tbl *);
33
static struct tbl *arraysearch(struct tbl *, int);
34
35
/*
36
 * create a new block for function calls and simple commands
37
 * assume caller has allocated and set up genv->loc
38
 */
39
void
40
newblock(void)
41
{
42
	struct block *l;
43
	static char *const empty[] = {null};
44
45
17207152
	l = alloc(sizeof(struct block), ATEMP);
46
8603576
	l->flags = 0;
47
8603576
	ainit(&l->area); /* todo: could use genv->area (l->area => l->areap) */
48
8603576
	if (!genv->loc) {
49
217770
		l->argc = 0;
50
		l->argv = (char **) empty;
51
217770
	} else {
52
8385806
		l->argc = genv->loc->argc;
53
8385806
		l->argv = genv->loc->argv;
54
	}
55
8603576
	l->exit = l->error = NULL;
56
8603576
	ktinit(&l->vars, &l->area, 0);
57
8603576
	ktinit(&l->funs, &l->area, 0);
58
8603576
	l->next = genv->loc;
59
8603576
	genv->loc = l;
60
8603576
}
61
62
/*
63
 * pop a block handling special variables
64
 */
65
void
66
popblock(void)
67
{
68
16699176
	struct block *l = genv->loc;
69
8349588
	struct tbl *vp, **vpp = l->vars.tbls, *vq;
70
	int i;
71
72
8349588
	genv->loc = l->next;	/* pop block */
73
18183968
	for (i = l->vars.size; --i >= 0; )
74

1898673
		if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL)) {
75
61376
			if ((vq = global(vp->name))->flag & ISSET)
76
61326
				setspec(vq);
77
			else
78
50
				unsetspec(vq);
79
		}
80
8349588
	if (l->flags & BF_DOGETOPTS)
81
4932
		user_opt = l->getopts_state;
82
8349588
	afreeall(&l->area);
83
8349588
	afree(l, ATEMP);
84
8349588
}
85
86
/* called by main() to initialize variable data structures */
87
void
88
initvar(void)
89
{
90
	static const struct {
91
		const char *name;
92
		int v;
93
	} names[] = {
94
		{ "COLUMNS",		V_COLUMNS },
95
		{ "IFS",		V_IFS },
96
		{ "OPTIND",		V_OPTIND },
97
		{ "PATH",		V_PATH },
98
		{ "POSIXLY_CORRECT",	V_POSIXLY_CORRECT },
99
		{ "TMPDIR",		V_TMPDIR },
100
#ifdef HISTORY
101
		{ "HISTCONTROL",	V_HISTCONTROL },
102
		{ "HISTFILE",		V_HISTFILE },
103
		{ "HISTSIZE",		V_HISTSIZE },
104
#endif /* HISTORY */
105
#ifdef EDIT
106
		{ "EDITOR",		V_EDITOR },
107
		{ "VISUAL",		V_VISUAL },
108
#endif /* EDIT */
109
		{ "MAIL",		V_MAIL },
110
		{ "MAILCHECK",		V_MAILCHECK },
111
		{ "MAILPATH",		V_MAILPATH },
112
		{ "RANDOM",		V_RANDOM },
113
		{ "SECONDS",		V_SECONDS },
114
		{ "TMOUT",		V_TMOUT },
115
		{ "LINENO",		V_LINENO },
116
		{ NULL,	0 }
117
	};
118
	int i;
119
	struct tbl *tp;
120
121
435540
	ktinit(&specials, APERM, 32); /* must be 2^n (currently 17 specials) */
122
8275260
	for (i = 0; names[i].name; i++) {
123
3919860
		tp = ktenter(&specials, names[i].name, hash(names[i].name));
124
3919860
		tp->flag = DEFINED|ISSET;
125
3919860
		tp->type = names[i].v;
126
	}
127
217770
}
128
129
/* Used to calculate an array index for global()/local().  Sets *arrayp to
130
 * non-zero if this is an array, sets *valp to the array index, returns
131
 * the basename of the array.
132
 */
133
static const char *
134
array_index_calc(const char *n, bool *arrayp, int *valp)
135
{
136
	const char *p;
137
	int len;
138
139
75468148
	*arrayp = false;
140
37734074
	p = skip_varname(n, false);
141

71329831
	if (p != n && *p == '[' && (len = array_ref_len(p))) {
142
		char *sub, *tmp;
143
685
		long rval;
144
145
		/* Calculate the value of the subscript */
146
685
		*arrayp = true;
147
685
		tmp = str_nsave(p+1, len-2, ATEMP);
148
685
		sub = substitute(tmp, 0);
149
685
		afree(tmp, ATEMP);
150
685
		n = str_nsave(n, p - n, ATEMP);
151
685
		evaluate(sub, &rval, KSH_UNWIND_ERROR, true);
152
685
		if (rval < 0 || rval > INT_MAX)
153
			errorf("%s: subscript %ld out of range", n, rval);
154
685
		*valp = rval;
155
685
		afree(sub, ATEMP);
156
685
	}
157
37734074
	return n;
158
}
159
160
/*
161
 * Search for variable, if not found create globally.
162
 */
163
struct tbl *
164
global(const char *n)
165
{
166
70238404
	struct block *l = genv->loc;
167
	struct tbl *vp;
168
	long	 num;
169
	int c;
170
	unsigned int h;
171
35119202
	bool	 array;
172
35119202
	int	 val;
173
174
	/* Check to see if this is an array */
175
35119202
	n = array_index_calc(n, &array, &val);
176
35119202
	h = hash(n);
177
35119202
	c = (unsigned char)n[0];
178
35119202
	if (!letter(c)) {
179
4139002
		if (array)
180
			errorf("bad substitution");
181
		vp = &vtemp;
182
4139002
		vp->flag = DEFINED;
183
4139002
		vp->type = 0;
184
4139002
		vp->areap = ATEMP;
185
4139002
		*vp->name = c;
186
4139002
		if (digit(c)) {
187
3486555
			errno = 0;
188
3486555
			num = strtol(n, NULL, 10);
189

6973110
			if (errno == 0 && num <= l->argc)
190
				/* setstr can't fail here */
191
3330068
				setstr(vp, l->argv[num], KSH_RETURN_ERROR);
192
3486555
			vp->flag |= RDONLY;
193
3486555
			return vp;
194
		}
195
652447
		vp->flag |= RDONLY;
196
652447
		if (n[1] != '\0')
197
			return vp;
198
652447
		vp->flag |= ISSET|INTEGER;
199

652447
		switch (c) {
200
		case '$':
201
48063
			vp->val.i = kshpid;
202
48063
			break;
203
		case '!':
204
			/* If no job, expand to nothing */
205
1767
			if ((vp->val.i = j_async()) == 0)
206
				vp->flag &= ~(ISSET|INTEGER);
207
			break;
208
		case '?':
209
343598
			vp->val.i = exstat;
210
343598
			break;
211
		case '#':
212
258207
			vp->val.i = l->argc;
213
258207
			break;
214
		case '-':
215
60
			vp->flag &= ~INTEGER;
216
60
			vp->val.s = getoptions();
217
60
			break;
218
		default:
219
752
			vp->flag &= ~(ISSET|INTEGER);
220
752
		}
221
652447
		return vp;
222
	}
223
53054398
	for (l = genv->loc; ; l = l->next) {
224
53054398
		vp = ktsearch(&l->vars, n, h);
225
53054398
		if (vp != NULL) {
226
22550954
			if (array)
227
446
				return arraysearch(vp, val);
228
			else
229
22550508
				return vp;
230
		}
231
30503444
		if (l->next == NULL)
232
			break;
233
	}
234
8429246
	vp = ktenter(&l->vars, n, h);
235
8429246
	if (array)
236
114
		vp = arraysearch(vp, val);
237
8429246
	vp->flag |= DEFINED;
238
8429246
	if (special(n))
239
1332981
		vp->flag |= SPECIAL;
240
8429246
	return vp;
241
35119202
}
242
243
/*
244
 * Search for local variable, if not found create locally.
245
 */
246
struct tbl *
247
local(const char *n, bool copy)
248
{
249
2614872
	struct block *l = genv->loc;
250
	struct tbl *vp;
251
	unsigned int h;
252
2614872
	bool	 array;
253
2614872
	int	 val;
254
255
	/* Check to see if this is an array */
256
2614872
	n = array_index_calc(n, &array, &val);
257
2614872
	h = hash(n);
258
2614872
	if (!letter(*n)) {
259
		vp = &vtemp;
260
		vp->flag = DEFINED|RDONLY;
261
		vp->type = 0;
262
		vp->areap = ATEMP;
263
		return vp;
264
	}
265
2614872
	vp = ktenter(&l->vars, n, h);
266

2684021
	if (copy && !(vp->flag & DEFINED)) {
267
		struct block *ll = l;
268
		struct tbl *vq = NULL;
269
270

358949
		while ((ll = ll->next) && !(vq = ktsearch(&ll->vars, n, h)))
271
			;
272
69149
		if (vq) {
273
61455
			vp->flag |= vq->flag &
274
			    (EXPORT | INTEGER | RDONLY | LJUST | RJUST |
275
			    ZEROFIL | LCASEV | UCASEV_AL | INT_U | INT_L);
276
61455
			if (vq->flag & INTEGER)
277
				vp->type = vq->type;
278
61455
			vp->u2.field = vq->u2.field;
279
61455
		}
280
69149
	}
281
2614872
	if (array)
282
125
		vp = arraysearch(vp, val);
283
2614872
	vp->flag |= DEFINED;
284
2614872
	if (special(n))
285
1371022
		vp->flag |= SPECIAL;
286
2614872
	return vp;
287
2614872
}
288
289
/* get variable string value */
290
char *
291
str_val(struct tbl *vp)
292
{
293
	char *s;
294
295
44901840
	if ((vp->flag&SPECIAL))
296
2120507
		getspec(vp);
297
22450920
	if (!(vp->flag&ISSET))
298
2059506
		s = null;		/* special to dollar() */
299
20391414
	else if (!(vp->flag&INTEGER))	/* string source */
300
18953284
		s = vp->val.s + vp->type;
301
	else {				/* integer source */
302
		/* worst case number length is when base=2, so use BITS(long) */
303
		/* minus base #     number    null */
304
1438130
		char strbuf[1 + 2 + 1 + BITS(long) + 1];
305
1438130
		const char *digits = (vp->flag & UCASEV_AL) ?
306
		    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" :
307
		    "0123456789abcdefghijklmnopqrstuvwxyz";
308
		unsigned long n;
309
		int base;
310
311
1438130
		s = strbuf + sizeof(strbuf);
312
1438130
		if (vp->flag & INT_U)
313
			n = (unsigned long) vp->val.i;
314
		else
315
1438130
			n = (vp->val.i < 0) ? -vp->val.i : vp->val.i;
316
3113959
		base = (vp->type == 0) ? 10 : vp->type;
317

2876260
		if (base < 2 || base > strlen(digits))
318
			base = 10;
319
320
1438130
		*--s = '\0';
321
1438130
		do {
322
3594846
			*--s = digits[n % base];
323
3594846
			n /= base;
324
3594846
		} while (n != 0);
325
1438130
		if (base != 10) {
326
325
			*--s = '#';
327
325
			*--s = digits[base % 10];
328
325
			if (base >= 10)
329
				*--s = digits[base / 10];
330
		}
331

2876260
		if (!(vp->flag & INT_U) && vp->val.i < 0)
332
25
			*--s = '-';
333
1438130
		if (vp->flag & (RJUST|LJUST)) /* case already dealt with */
334
			s = formatstr(vp, s);
335
		else
336
1438130
			s = str_save(s, ATEMP);
337
1438130
	}
338
22450920
	return s;
339
}
340
341
/* get variable integer value, with error checking */
342
long
343
intval(struct tbl *vp)
344
{
345
2622490
	long num;
346
	int base;
347
348
1311245
	base = getint(vp, &num, false);
349
1311245
	if (base == -1)
350
		/* XXX check calls - is error here ok by POSIX? */
351
		errorf("%s: bad number", str_val(vp));
352
2622490
	return num;
353
1311245
}
354
355
/* set variable to string value */
356
int
357
setstr(struct tbl *vq, const char *s, int error_ok)
358
{
359
	const char *fs = NULL;
360
41249582
	int no_ro_check = error_ok & KSH_IGNORE_RDONLY;
361
20624791
	error_ok &= ~KSH_IGNORE_RDONLY;
362
20624791
	if ((vq->flag & RDONLY) && !no_ro_check) {
363
		warningf(true, "%s: is read only", vq->name);
364
		if (!error_ok)
365
			errorf(NULL);
366
		return 0;
367
	}
368
20624791
	if (!(vq->flag&INTEGER)) { /* string dest */
369
19532541
		if ((vq->flag&ALLOC)) {
370
			/* debugging */
371

12503105
			if (s >= vq->val.s &&
372
4250560
			    s <= vq->val.s + strlen(vq->val.s))
373
				internal_errorf(true,
374
				    "setstr: %s=%s: assigning to self",
375
				    vq->name, s);
376
8252545
			afree(vq->val.s, vq->areap);
377
8252545
		}
378
19532541
		vq->flag &= ~(ISSET|ALLOC);
379
19532541
		vq->type = 0;
380

39065082
		if (s && (vq->flag & (UCASEV_AL|LCASEV|LJUST|RJUST)))
381
43776
			fs = s = formatstr(vq, s);
382
19532541
		if ((vq->flag&EXPORT))
383
5679064
			export(vq, s);
384
		else {
385
13853477
			vq->val.s = str_save(s, vq->areap);
386
13853477
			vq->flag |= ALLOC;
387
		}
388
	} else {		/* integer dest */
389
1092125
		if (!v_evaluate(vq, s, error_ok, true))
390
			return 0;
391
	}
392
20624666
	vq->flag |= ISSET;
393
20624666
	if ((vq->flag&SPECIAL))
394
1920982
		setspec(vq);
395
20624666
	afree((void *)fs, ATEMP);
396
20624666
	return 1;
397
20624666
}
398
399
/* set variable to integer */
400
void
401
setint(struct tbl *vq, long int n)
402
{
403
1109342
	if (!(vq->flag&INTEGER)) {
404
		struct tbl *vp = &vtemp;
405
548796
		vp->flag = (ISSET|INTEGER);
406
548796
		vp->type = 0;
407
548796
		vp->areap = ATEMP;
408
548796
		vp->val.i = n;
409
		/* setstr can't fail here */
410
548796
		setstr(vq, str_val(vp), KSH_RETURN_ERROR);
411
548796
	} else
412
5875
		vq->val.i = n;
413
554671
	vq->flag |= ISSET;
414
554671
	if ((vq->flag&SPECIAL))
415
4350
		setspec(vq);
416
554671
}
417
418
int
419
getint(struct tbl *vp, long int *nump, bool arith)
420
{
421
	char *s;
422
	int c;
423
	int base, neg;
424
	int have_base = 0;
425
	long num;
426
427
5987231
	if (vp->flag&SPECIAL)
428
13646
		getspec(vp);
429
	/* XXX is it possible for ISSET to be set and val.s to be 0? */
430

14430841
	if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL))
431
		return -1;
432
5987231
	if (vp->flag&INTEGER) {
433
3530852
		*nump = vp->val.i;
434
3530852
		return vp->type;
435
	}
436
2456379
	s = vp->val.s + vp->type;
437
2456379
	if (s == NULL)	/* redundant given initial test */
438
		s = null;
439
	base = 10;
440
	num = 0;
441
	neg = 0;
442

4454041
	if (arith && *s == '0' && *(s+1)) {
443
25
		s++;
444

50
		if (*s == 'x' || *s == 'X') {
445
			s++;
446
			base = 16;
447
25
		} else if (vp->flag & ZEROFIL) {
448
			while (*s == '0')
449
				s++;
450
		} else
451
			base = 8;
452
		have_base++;
453
25
	}
454
13307370
	for (c = (unsigned char)*s++; c ; c = (unsigned char)*s++) {
455
4197381
		if (c == '-') {
456
			neg++;
457
4197381
		} else if (c == '#') {
458
300
			base = (int) num;
459
300
			if (have_base || base < 2 || base > 36)
460
50
				return -1;
461
			num = 0;
462
			have_base = 1;
463

8394412
		} else if (letnum(c)) {
464
4197081
			if (isdigit(c))
465
4197081
				c -= '0';
466
			else if (islower(c))
467
				c -= 'a' - 10; /* todo: assumes ascii */
468
			else if (isupper(c))
469
				c -= 'A' - 10; /* todo: assumes ascii */
470
			else
471
				c = -1; /* _: force error */
472

8394162
			if (c < 0 || c >= base)
473
25
				return -1;
474
4197056
			num = num * base + c;
475
		} else
476
			return -1;
477
	}
478
2456304
	if (neg)
479
		num = -num;
480
2456304
	*nump = num;
481
2456304
	return base;
482
5987231
}
483
484
/* convert variable vq to integer variable, setting its value from vp
485
 * (vq and vp may be the same)
486
 */
487
struct tbl *
488
setint_v(struct tbl *vq, struct tbl *vp, bool arith)
489
{
490
	int base;
491
4667286
	long num;
492
493
4667286
	if ((base = getint(vp, &num, arith)) == -1)
494
75
		return NULL;
495

6890444
	if (!(vq->flag & INTEGER) && (vq->flag & ALLOC)) {
496
		vq->flag &= ~ALLOC;
497
		afree(vq->val.s, vq->areap);
498
	}
499
4667211
	vq->val.i = num;
500
4667211
	if (vq->type == 0) /* default base */
501
4431597
		vq->type = base;
502
4667211
	vq->flag |= ISSET|INTEGER;
503
4667211
	if (vq->flag&SPECIAL)
504
873330
		setspec(vq);
505
4667211
	return vq;
506
4667286
}
507
508
static char *
509
formatstr(struct tbl *vp, const char *s)
510
{
511
	int olen, nlen;
512
	char *p, *q;
513
514
87552
	olen = strlen(s);
515
516
43776
	if (vp->flag & (RJUST|LJUST)) {
517
		if (!vp->u2.field)	/* default field width */
518
			vp->u2.field = olen;
519
		nlen = vp->u2.field;
520
	} else
521
		nlen = olen;
522
523
43776
	p = alloc(nlen + 1, ATEMP);
524
43776
	if (vp->flag & (RJUST|LJUST)) {
525
		int slen;
526
527
		if (vp->flag & RJUST) {
528
			const char *q = s + olen;
529
			/* strip trailing spaces (at&t ksh uses q[-1] == ' ') */
530
			while (q > s && isspace((unsigned char)q[-1]))
531
				--q;
532
			slen = q - s;
533
			if (slen > vp->u2.field) {
534
				s += slen - vp->u2.field;
535
				slen = vp->u2.field;
536
			}
537
			shf_snprintf(p, nlen + 1,
538
				((vp->flag & ZEROFIL) && digit(*s)) ?
539
					  "%0*s%.*s" : "%*s%.*s",
540
				vp->u2.field - slen, null, slen, s);
541
		} else {
542
			/* strip leading spaces/zeros */
543
			while (isspace((unsigned char)*s))
544
				s++;
545
			if (vp->flag & ZEROFIL)
546
				while (*s == '0')
547
					s++;
548
			shf_snprintf(p, nlen + 1, "%-*.*s",
549
				vp->u2.field, vp->u2.field, s);
550
		}
551
	} else
552
43776
		memcpy(p, s, olen + 1);
553
554
43776
	if (vp->flag & UCASEV_AL) {
555
		for (q = p; *q; q++)
556
			if (islower((unsigned char)*q))
557
				*q = toupper((unsigned char)*q);
558
43776
	} else if (vp->flag & LCASEV) {
559
1101948
		for (q = p; *q; q++)
560
507198
			if (isupper((unsigned char)*q))
561
				*q = tolower((unsigned char)*q);
562
	}
563
564
43776
	return p;
565
}
566
567
/*
568
 * make vp->val.s be "name=value" for quick exporting.
569
 */
570
static void
571
export(struct tbl *vp, const char *val)
572
{
573
	char *xp;
574
17310562
	char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
575
5756496
	int namelen = strlen(vp->name);
576
5756496
	int vallen = strlen(val) + 1;
577
578
5756496
	vp->flag |= ALLOC;
579
5756496
	xp = alloc(namelen + 1 + vallen, vp->areap);
580
5756496
	memcpy(vp->val.s = xp, vp->name, namelen);
581
5756496
	xp += namelen;
582
5756496
	*xp++ = '=';
583
5756496
	vp->type = xp - vp->val.s; /* offset to value */
584
5756496
	memcpy(xp, val, vallen);
585
5756496
	afree(op, vp->areap);
586
5756496
}
587
588
/*
589
 * lookup variable (according to (set&LOCAL)),
590
 * set its attributes (INTEGER, RDONLY, EXPORT, TRACE, LJUST, RJUST, ZEROFIL,
591
 * LCASEV, UCASEV_AL), and optionally set its value if an assignment.
592
 */
593
struct tbl *
594
typeset(const char *var, int set, int clr, int field, int base)
595
{
596
	struct tbl *vp;
597
	struct tbl *vpbase, *t;
598
	char *tvar;
599
	const char *val;
600
601
	/* check for valid variable name, search for value */
602
31102996
	val = skip_varname(var, false);
603
15551498
	if (val == var)
604
		return NULL;
605
15551498
	if (*val == '[') {
606
		int len;
607
608
523
		len = array_ref_len(val);
609
523
		if (len == 0)
610
			return NULL;
611
		/* IMPORT is only used when the shell starts up and is
612
		 * setting up its environment.  Allow only simple array
613
		 * references at this time since parameter/command substitution
614
		 * is preformed on the [expression], which would be a major
615
		 * security hole.
616
		 */
617
523
		if (set & IMPORT) {
618
			int i;
619
			for (i = 1; i < len - 1; i++)
620
				if (!digit(val[i]))
621
					return NULL;
622
		}
623
523
		val += len;
624
523
	}
625
15551498
	if (*val == '=')
626
13894265
		tvar = str_nsave(var, val++ - var, ATEMP);
627
	else {
628
		/* Importing from original environment: must have an = */
629
1657233
		if (set & IMPORT)
630
			return NULL;
631
		tvar = (char *) var;
632
		val = NULL;
633
	}
634
635
	/* Prevent typeset from creating a local PATH/ENV/SHELL */
636

15562998
	if (Flag(FRESTRICTED) && (strcmp(tvar, "PATH") == 0 ||
637
11500
	    strcmp(tvar, "ENV") == 0 || strcmp(tvar, "SHELL") == 0))
638
		errorf("%s: restricted", tvar);
639
640
46654494
	vp = (set&LOCAL) ? local(tvar, (set & LOCAL_COPY) ? true : false) :
641
12936927
	    global(tvar);
642
15551498
	set &= ~(LOCAL|LOCAL_COPY);
643
644
46654494
	vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
645
646
	/* only allow export flag to be set.  at&t ksh allows any attribute to
647
	 * be changed, which means it can be truncated or modified
648
	 * (-L/-R/-Z/-i).
649
	 */
650

15551498
	if ((vpbase->flag&RDONLY) &&
651
33
	    (val || clr || (set & ~EXPORT)))
652
		/* XXX check calls - is error here ok by POSIX? */
653
		errorf("%s: is read only", tvar);
654
15551465
	if (val)
655
13894232
		afree(tvar, ATEMP);
656
657
	/* most calls are with set/clr == 0 */
658
15551465
	if (set | clr) {
659
		int ok = 1;
660
		/* XXX if x[0] isn't set, there will be problems: need to have
661
		 * one copy of attributes for arrays...
662
		 */
663
30547838
		for (t = vpbase; t; t = t->u.array) {
664
			int fake_assign;
665
			int error_ok = KSH_RETURN_ERROR;
666
			char *s = NULL;
667
			char *free_me = NULL;
668
669

17115951
			fake_assign = (t->flag & ISSET) && (!val || t != vp) &&
670
1177197
			    ((set & (UCASEV_AL|LCASEV|LJUST|RJUST|ZEROFIL)) ||
671

1177247
			    ((t->flag & INTEGER) && (clr & INTEGER)) ||
672
2354344
			    (!(t->flag & INTEGER) && (set & INTEGER)));
673
7637022
			if (fake_assign) {
674
217820
				if (t->flag & INTEGER) {
675
					s = str_val(t);
676
					free_me = NULL;
677
				} else {
678
217820
					s = t->val.s + t->type;
679
653460
					free_me = (t->flag & ALLOC) ? t->val.s :
680
					    NULL;
681
				}
682
217820
				t->flag &= ~ALLOC;
683
217820
			}
684

15273869
			if (!(t->flag & INTEGER) && (set & INTEGER)) {
685
1307745
				t->type = 0;
686
1307745
				t->flag &= ~ALLOC;
687
1307745
			}
688

15274044
			if (!(t->flag & RDONLY) && (set & RDONLY)) {
689
				/* allow var to be initialized read-only */
690
				error_ok |= KSH_IGNORE_RDONLY;
691
444857
			}
692
7637022
			t->flag = (t->flag | set) & ~clr;
693
			/* Don't change base if assignment is to be done,
694
			 * in case assignment fails.
695
			 */
696

7637497
			if ((set & INTEGER) && base > 0 && (!val || t != vp))
697
75
				t->type = base;
698
7637022
			if (set & (LJUST|RJUST|ZEROFIL))
699
				t->u2.field = field;
700
7637022
			if (fake_assign) {
701
217820
				if (!setstr(t, s, error_ok)) {
702
					/* Somewhat arbitrary action here:
703
					 * zap contents of variable, but keep
704
					 * the flag settings.
705
					 */
706
					ok = 0;
707
					if (t->flag & INTEGER)
708
						t->flag &= ~ISSET;
709
					else {
710
						if (t->flag & ALLOC)
711
							afree(t->val.s, t->areap);
712
						t->flag &= ~(ISSET|ALLOC);
713
						t->type = 0;
714
					}
715
				}
716
217820
				afree(free_me, t->areap);
717
217820
			}
718
		}
719
7636897
		if (!ok)
720
		    errorf(NULL);
721
7636897
	}
722
723
15551465
	if (val != NULL) {
724
13894232
		if (vp->flag&INTEGER) {
725
			/* do not zero base before assignment */
726
874230
			setstr(vp, val, KSH_UNWIND_ERROR | KSH_IGNORE_RDONLY);
727
			/* Done after assignment to override default */
728
874230
			if (base > 0)
729
175
				vp->type = base;
730
		} else
731
			/* setstr can't fail (readonly check already done) */
732
13019877
			setstr(vp, val, KSH_RETURN_ERROR | KSH_IGNORE_RDONLY);
733
	}
734
735
	/* only x[0] is ever exported, so use vpbase */
736

27880021
	if ((vpbase->flag&EXPORT) && !(vpbase->flag&INTEGER) &&
737
6164328
	    vpbase->type == 0)
738
195938
		export(vpbase, (vpbase->flag&ISSET) ? vpbase->val.s : null);
739
740
15551340
	return vp;
741
15551340
}
742
743
/* Unset a variable.  array_ref is set if there was an array reference in
744
 * the name lookup (eg, x[2]).
745
 */
746
void
747
unset(struct tbl *vp, int array_ref)
748
{
749
271228
	if (vp->flag & ALLOC)
750
51294
		afree(vp->val.s, vp->areap);
751
135614
	if ((vp->flag & ARRAY) && !array_ref) {
752
		struct tbl *a, *tmp;
753
754
		/* Free up entire array */
755
1224
		for (a = vp->u.array; a; ) {
756
			tmp = a;
757
561
			a = a->u.array;
758
561
			if (tmp->flag & ALLOC)
759
561
				afree(tmp->val.s, tmp->areap);
760
561
			afree(tmp, tmp->areap);
761
		}
762
51
		vp->u.array = NULL;
763
51
	}
764
	/* If foo[0] is being unset, the remainder of the array is kept... */
765
135614
	vp->flag &= SPECIAL | (array_ref ? ARRAY|DEFINED : 0);
766
135614
	if (vp->flag & SPECIAL)
767
5489
		unsetspec(vp);	/* responsible for `unspecial'ing var */
768
135614
}
769
770
/* return a pointer to the first char past a legal variable name (returns the
771
 * argument if there is no legal name, returns * a pointer to the terminating
772
 * null if whole string is legal).
773
 */
774
char *
775
skip_varname(const char *s, int aok)
776
{
777
	int alen;
778
779

160010373
	if (s && letter(*s)) {
780

636807783
		while (*++s && letnum(*s))
781
			;
782

49198965
		if (aok && *s == '[' && (alen = array_ref_len(s)))
783
			s += alen;
784
	}
785
53336791
	return (char *) s;
786
}
787
788
/* Return a pointer to the first character past any legal variable name.  */
789
char *
790
skip_wdvarname(const char *s,
791
    int aok)				/* skip array de-reference? */
792
{
793

57623360
	if (s[0] == CHAR && letter(s[1])) {
794
		do {
795
114965903
			s += 2;
796

222464424
		} while (s[0] == CHAR && letnum(s[1]));
797

40065029
		if (aok && s[0] == CHAR && s[1] == '[') {
798
			/* skip possible array de-reference */
799
			const char *p = s;
800
			char c;
801
			int depth = 0;
802
803
823
			while (1) {
804
6794
				if (p[0] != CHAR)
805
					break;
806
6794
				c = p[1];
807
6794
				p += 2;
808
6794
				if (c == '[')
809
1243
					depth++;
810

6794
				else if (c == ']' && --depth == 0) {
811
					s = p;
812
823
					break;
813
				}
814
			}
815
823
		}
816
	}
817
19606823
	return (char *) s;
818
}
819
820
/* Check if coded string s is a variable name */
821
int
822
is_wdvarname(const char *s, int aok)
823
{
824
658172
	char *p = skip_wdvarname(s, aok);
825
826
824729
	return p != s && p[0] == EOS;
827
}
828
829
/* Check if coded string s is a variable assignment */
830
int
831
is_wdvarassign(const char *s)
832
{
833
38555474
	char *p = skip_wdvarname(s, true);
834
835

60864763
	return p != s && p[0] == CHAR && p[1] == '=';
836
}
837
838
/*
839
 * Make the exported environment from the exported names in the dictionary.
840
 */
841
char **
842
makenv(void)
843
{
844
	struct block *l;
845
	XPtrV env;
846
	struct tbl *vp, **vpp;
847
	int i;
848
849
	XPinit(env, 64);
850
	for (l = genv->loc; l != NULL; l = l->next)
851
		for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; )
852
			if ((vp = *vpp++) != NULL &&
853
			    (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) {
854
				struct block *l2;
855
				struct tbl *vp2;
856
				unsigned int h = hash(vp->name);
857
858
				/* unexport any redefined instances */
859
				for (l2 = l->next; l2 != NULL; l2 = l2->next) {
860
					vp2 = ktsearch(&l2->vars, vp->name, h);
861
					if (vp2 != NULL)
862
						vp2->flag &= ~EXPORT;
863
				}
864
				if ((vp->flag&INTEGER)) {
865
					/* integer to string */
866
					char *val;
867
					val = str_val(vp);
868
					vp->flag &= ~(INTEGER|RDONLY);
869
					/* setstr can't fail here */
870
					setstr(vp, val, KSH_RETURN_ERROR);
871
				}
872
				XPput(env, vp->val.s);
873
			}
874
	XPput(env, NULL);
875
	return (char **) XPclose(env);
876
}
877
878
/*
879
 * Called after a fork in parent to bump the random number generator.
880
 * Done to ensure children will not get the same random number sequence
881
 * if the parent doesn't use $RANDOM.
882
 */
883
void
884
change_random(void)
885
{
886
14250836
	rand();
887
7125418
}
888
889
/*
890
 * handle special variables with side effects - PATH, SECONDS.
891
 */
892
893
/* Test if name is a special parameter */
894
static int
895
special(const char *name)
896
{
897
	struct tbl *tp;
898
899
32087596
	tp = ktsearch(&specials, name, hash(name));
900

47494212
	return tp && (tp->flag & ISSET) ? tp->type : V_NONE;
901
}
902
903
/* Make a variable non-special */
904
static void
905
unspecial(const char *name)
906
{
907
	struct tbl *tp;
908
909
100
	tp = ktsearch(&specials, name, hash(name));
910
50
	if (tp)
911
50
		ktdelete(tp);
912
50
}
913
914
static	time_t	seconds;		/* time SECONDS last set */
915
static	int	user_lineno;		/* what user set $LINENO to */
916
917
static void
918
getspec(struct tbl *vp)
919
{
920

4814077
	switch (special(vp->name)) {
921
	case V_SECONDS:
922
217997
		vp->flag &= ~SPECIAL;
923
		/* On start up the value of SECONDS is used before seconds
924
		 * has been set - don't do anything in this case
925
		 * (see initcoms[] in main.c).
926
		 */
927
217997
		if (vp->flag & ISSET)
928
227
			setint(vp, (long)(time(NULL) - seconds)); /* XXX 2038 */
929
		vp->flag |= SPECIAL;
930
217997
		break;
931
	case V_RANDOM:
932
4400
		vp->flag &= ~SPECIAL;
933
4400
		setint(vp, (long) (rand() & 0x7fff));
934
		vp->flag |= SPECIAL;
935
4400
		break;
936
#ifdef HISTORY
937
	case V_HISTSIZE:
938
		vp->flag &= ~SPECIAL;
939
		setint(vp, (long) histsize);
940
		vp->flag |= SPECIAL;
941
		break;
942
#endif /* HISTORY */
943
	case V_OPTIND:
944
1248
		vp->flag &= ~SPECIAL;
945
1248
		setint(vp, (long) user_opt.uoptind);
946
		vp->flag |= SPECIAL;
947
1248
		break;
948
	case V_LINENO:
949
322126
		vp->flag &= ~SPECIAL;
950
322126
		setint(vp, (long) current_lineno + user_lineno);
951
		vp->flag |= SPECIAL;
952
322126
		break;
953
	}
954
2679924
}
955
956
static void
957
setspec(struct tbl *vp)
958
{
959
	char *s;
960
961




8579939
	switch (special(vp->name)) {
962
	case V_PATH:
963
435827
		afree(path, APERM);
964
435827
		path = str_save(str_val(vp), APERM);
965
435827
		flushcom(1);	/* clear tracked aliases */
966
435827
		break;
967
	case V_IFS:
968
430410
		setctypes(s = str_val(vp), C_IFS);
969
430410
		ifs0 = *s;
970
430410
		break;
971
	case V_OPTIND:
972
435590
		vp->flag &= ~SPECIAL;
973
435590
		getopts_reset((int) intval(vp));
974
435590
		vp->flag |= SPECIAL;
975
435590
		break;
976
	case V_POSIXLY_CORRECT:
977
43
		change_flag(FPOSIX, OF_SPECIAL, 1);
978
43
		break;
979
	case V_TMPDIR:
980
528
		afree(tmpdir, APERM);
981
528
		tmpdir = NULL;
982
		/* Use tmpdir iff it is an absolute path, is writable and
983
		 * searchable and is a directory...
984
		 */
985
		{
986
528
			struct stat statb;
987
988
528
			s = str_val(vp);
989

1584
			if (s[0] == '/' && access(s, W_OK|X_OK) == 0 &&
990
1056
			    stat(s, &statb) == 0 && S_ISDIR(statb.st_mode))
991
528
				tmpdir = str_save(s, APERM);
992
528
		}
993
528
		break;
994
#ifdef HISTORY
995
	case V_HISTCONTROL:
996
75
		sethistcontrol(str_val(vp));
997
75
		break;
998
	case V_HISTSIZE:
999
50
		vp->flag &= ~SPECIAL;
1000
50
		sethistsize((int) intval(vp));
1001
50
		vp->flag |= SPECIAL;
1002
50
		break;
1003
	case V_HISTFILE:
1004
8875
		sethistfile(str_val(vp));
1005
8875
		break;
1006
#endif /* HISTORY */
1007
#ifdef EDIT
1008
	case V_VISUAL:
1009
8267
		set_editmode(str_val(vp));
1010
8267
		break;
1011
	case V_EDITOR:
1012
8225
		if (!(global("VISUAL")->flag & ISSET))
1013
5500
			set_editmode(str_val(vp));
1014
		break;
1015
	case V_COLUMNS:
1016
		{
1017
8700
			long l;
1018
1019
8700
			if (getint(vp, &l, false) == -1) {
1020
				x_cols = MIN_COLS;
1021
				break;
1022
			}
1023
17400
			if (l <= MIN_COLS || l > INT_MAX)
1024
				x_cols = MIN_COLS;
1025
			else
1026
8700
				x_cols = l;
1027
17400
		}
1028
		break;
1029
#endif /* EDIT */
1030
	case V_MAIL:
1031
212228
		mbset(str_val(vp));
1032
212228
		break;
1033
	case V_MAILPATH:
1034
		mpset(str_val(vp));
1035
		break;
1036
	case V_MAILCHECK:
1037
435540
		vp->flag &= ~SPECIAL;
1038
435540
		mcset(intval(vp));
1039
435540
		vp->flag |= SPECIAL;
1040
435540
		break;
1041
	case V_RANDOM:
1042
4475
		vp->flag &= ~SPECIAL;
1043
4475
		srand_deterministic((unsigned int)intval(vp));
1044
4475
		vp->flag |= SPECIAL;
1045
4475
		break;
1046
	case V_SECONDS:
1047
435540
		vp->flag &= ~SPECIAL;
1048
435540
		seconds = time(NULL) - intval(vp); /* XXX 2038 */
1049
435540
		vp->flag |= SPECIAL;
1050
435540
		break;
1051
	case V_TMOUT:
1052
		/* at&t ksh seems to do this (only listen if integer) */
1053
435540
		if (vp->flag & INTEGER)
1054
1306620
			ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0;
1055
		break;
1056
	case V_LINENO:
1057
50
		vp->flag &= ~SPECIAL;
1058
		/* The -1 is because line numbering starts at 1. */
1059
50
		user_lineno = (unsigned int) intval(vp) - current_lineno - 1;
1060
50
		vp->flag |= SPECIAL;
1061
50
		break;
1062
	}
1063
2859988
}
1064
1065
static void
1066
unsetspec(struct tbl *vp)
1067
{
1068



16608
	switch (special(vp->name)) {
1069
	case V_PATH:
1070
		afree(path, APERM);
1071
		path = str_save(def_path, APERM);
1072
		flushcom(1);	/* clear tracked aliases */
1073
		break;
1074
	case V_IFS:
1075
		setctypes(" \t\n", C_IFS);
1076
		ifs0 = ' ';
1077
		break;
1078
	case V_TMPDIR:
1079
		/* should not become unspecial */
1080
50
		afree(tmpdir, APERM);
1081
50
		tmpdir = NULL;
1082
50
		break;
1083
	case V_MAIL:
1084
3068
		mbset(NULL);
1085
3068
		break;
1086
	case V_MAILPATH:
1087
2362
		mpset(NULL);
1088
2362
		break;
1089
#ifdef HISTORY
1090
	case V_HISTCONTROL:
1091
		sethistcontrol(NULL);
1092
		break;
1093
#endif
1094
	case V_LINENO:
1095
	case V_MAILCHECK:	/* at&t ksh leaves previous value in place */
1096
	case V_RANDOM:
1097
	case V_SECONDS:
1098
	case V_TMOUT:		/* at&t ksh leaves previous value in place */
1099
50
		unspecial(vp->name);
1100
50
		break;
1101
1102
	  /* at&t ksh man page says OPTIND, OPTARG and _ lose special meaning,
1103
	   * but OPTARG does not (still set by getopts) and _ is also still
1104
	   * set in various places.
1105
	   * Don't know what at&t does for:
1106
	   *		MAIL, MAILPATH, HISTSIZE, HISTFILE,
1107
	   * Unsetting these in at&t ksh does not loose the `specialness':
1108
	   *    no effect: IFS, COLUMNS, PATH, TMPDIR,
1109
	   *		VISUAL, EDITOR,
1110
	   * pdkshisms: no effect:
1111
	   *		POSIXLY_CORRECT (use set +o posix instead)
1112
	   */
1113
	}
1114
5539
}
1115
1116
/*
1117
 * Search for (and possibly create) a table entry starting with
1118
 * vp, indexed by val.
1119
 */
1120
static struct tbl *
1121
arraysearch(struct tbl *vp, int val)
1122
{
1123
	struct tbl *prev, *curr, *new;
1124
114870
	size_t namelen = strlen(vp->name) + 1;
1125
1126
57435
	vp->flag |= ARRAY|DEFINED;
1127
57435
	vp->index = 0;
1128
	/* The table entry is always [0] */
1129
57435
	if (val == 0)
1130
50107
		return vp;
1131
	prev = vp;
1132
7328
	curr = vp->u.array;
1133

155286
	while (curr && curr->index < val) {
1134
		prev = curr;
1135
33260
		curr = curr->u.array;
1136
	}
1137

7590
	if (curr && curr->index == val) {
1138
162
		if (curr->flag&ISSET)
1139
162
			return curr;
1140
		else
1141
			new = curr;
1142
	} else
1143
14332
		new = alloc(sizeof(struct tbl) + namelen,
1144
7166
		    vp->areap);
1145
7166
	strlcpy(new->name, vp->name, namelen);
1146
7166
	new->flag = vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL);
1147
7166
	new->type = vp->type;
1148
7166
	new->areap = vp->areap;
1149
7166
	new->u2.field = vp->u2.field;
1150
7166
	new->index = val;
1151
7166
	if (curr != new) {		/* not reusing old array entry */
1152
7166
		prev->u.array = new;
1153
7166
		new->u.array = curr;
1154
7166
	}
1155
7166
	return new;
1156
57435
}
1157
1158
/* Return the length of an array reference (eg, [1+2]) - cp is assumed
1159
 * to point to the open bracket.  Returns 0 if there is no matching closing
1160
 * bracket.
1161
 */
1162
int
1163
array_ref_len(const char *cp)
1164
{
1165
	const char *s = cp;
1166
	int c;
1167
	int depth = 0;
1168
1169

25920
	while ((c = *s++) && (c != ']' || --depth))
1170
6144
		if (c == '[')
1171
1448
			depth++;
1172
1208
	if (!c)
1173
		return 0;
1174
1208
	return s - cp;
1175
1208
}
1176
1177
/*
1178
 * Make a copy of the base of an array name
1179
 */
1180
char *
1181
arrayname(const char *str)
1182
{
1183
	const char *p;
1184
1185
12610
	if ((p = strchr(str, '[')) == 0)
1186
		/* Shouldn't happen, but why worry? */
1187
		return (char *) str;
1188
1189
6305
	return str_nsave(str, p - str, ATEMP);
1190
6305
}
1191
1192
/* Set (or overwrite, if !reset) the array variable var to the values in vals.
1193
 */
1194
void
1195
set_array(const char *var, int reset, char **vals)
1196
{
1197
	struct tbl *vp, *vq;
1198
	int i;
1199
1200
	/* to get local array, use "typeset foo; set -A foo" */
1201
100086
	vp = global(var);
1202
1203
	/* Note: at&t ksh allows set -A but not set +A of a read-only var */
1204
50043
	if ((vp->flag&RDONLY))
1205
		errorf("%s: is read only", var);
1206
	/* This code is quite non-optimal */
1207
50043
	if (reset > 0)
1208
		/* trash existing values and attributes */
1209
50043
		unset(vp, 0);
1210
	/* todo: would be nice for assignment to completely succeed or
1211
	 * completely fail.  Only really effects integer arrays:
1212
	 * evaluation of some of vals[] may fail...
1213
	 */
1214
213586
	for (i = 0; vals[i]; i++) {
1215
56750
		vq = arraysearch(vp, i);
1216
		/* would be nice to deal with errors here... (see above) */
1217
56750
		setstr(vq, vals[i], KSH_RETURN_ERROR);
1218
	}
1219
50043
}