15155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: var.c,v 1.34 2007/10/15 02:16:35 deraadt Exp $	*/
25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
55155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Thorsten Glaser <tg@mirbsd.org>
65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices
85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission
95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un-
105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify,
115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence.
125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor
155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event
165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect,
175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out
185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such
195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out
205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended.
215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h"
245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(__OpenBSD__)
265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <sys/sysctl.h>
275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra__RCSID("$MirOS: src/bin/mksh/var.c,v 1.132 2011/09/07 15:24:22 tg Exp $");
305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*-
325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Variables
335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * WARNING: unreadable code, needs a rewrite
355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if (flag&INTEGER), val.i contains integer value, and type contains base.
375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * otherwise, (val.s + type) contains string value.
385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting.
395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
4003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct tbl vtemp;
425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct table specials;
4303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic uint32_t lcg_state = 5381;
4403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *formatstr(struct tbl *, const char *);
465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void exportprep(struct tbl *, const char *);
475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int special(const char *);
485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void unspecial(const char *);
495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void getspec(struct tbl *);
505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void setspec(struct tbl *);
515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void unsetspec(struct tbl *);
525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int getint(struct tbl *, mksh_ari_t *, bool);
535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *array_index_calc(const char *, bool *, uint32_t *);
545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * create a new block for function calls and simple commands
575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * assume caller has allocated and set up e->loc
585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querunewblock(void)
615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l;
635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	static const char *empty[] = { null };
645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l = alloc(sizeof(struct block), ATEMP);
665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->flags = 0;
6703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* TODO: could use e->area (l->area => l->areap) */
6803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ainit(&l->area);
695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!e->loc) {
705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		l->argc = 0;
715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		l->argv = empty;
725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		l->argc = e->loc->argc;
745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		l->argv = e->loc->argv;
755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->exit = l->error = NULL;
7703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ktinit(&l->area, &l->vars, 0);
7803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ktinit(&l->area, &l->funs, 0);
795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->next = e->loc;
805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	e->loc = l;
815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * pop a block handling special variables
855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupopblock(void)
885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
8903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ssize_t i;
905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l = e->loc;
915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp, **vpp = l->vars.tbls, *vq;
925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* pop block */
9403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	e->loc = l->next;
9503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
9603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	i = 1 << (l->vars.tshift);
9703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (--i >= 0)
985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL)) {
995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((vq = global(vp->name))->flag & ISSET)
1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				setspec(vq);
1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				unsetspec(vq);
1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (l->flags & BF_DOGETOPTS)
1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		user_opt = l->getopts_state;
1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afreeall(&l->area);
1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(l, ATEMP);
1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* called by main() to initialise variable data structures */
1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define VARSPEC_DEFNS
1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "var_spec.h"
1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruenum var_specs {
1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define VARSPEC_ENUMS
1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "var_spec.h"
1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	V_MAX
1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* this is biased with -1 relative to VARSPEC_ENUMS */
1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char * const initvar_names[] = {
1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define VARSPEC_ITEMS
1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "var_spec.h"
1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinitvar(void)
1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i = 0;
1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *tp;
1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ktinit(APERM, &specials,
13303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    /* currently 12 specials -> 80% of 16 (2^4) */
13403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    4);
1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (i < V_MAX - 1) {
1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tp = ktenter(&specials, initvar_names[i],
1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    hash(initvar_names[i]));
1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tp->flag = DEFINED|ISSET;
1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tp->type = ++i;
1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* common code for several functions below */
14403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic struct block *
14503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravarsearch(struct block *l, struct tbl **vpp, const char *vn, uint32_t h)
14603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
14703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	register struct tbl *vp;
14803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
14903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (l) {
15003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra varsearch_loop:
15103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((vp = ktsearch(&l->vars, vn, h)) != NULL)
15203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto varsearch_out;
15303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (l->next != NULL) {
15403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			l = l->next;
15503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto varsearch_loop;
15603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
15703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
15803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vp = NULL;
15903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra varsearch_out:
16003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	*vpp = vp;
16103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (l);
16203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
16303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
16403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
16503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Used to calculate an array index for global()/local(). Sets *arrayp
16603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * to true if this is an array, sets *valp to the array index, returns
1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the basename of the array.
1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *
1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruarray_index_calc(const char *n, bool *arrayp, uint32_t *valp)
1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *p;
17303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t len;
1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *ap = NULL;
1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*arrayp = false;
1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru redo_from_ref:
1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p = skip_varname(n, false);
17903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (set_refflag == SRF_NOP && (p != n) && ksh_isalphx(n[0])) {
1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *vp;
1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *vn;
1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strndupx(vn, n, p - n, ATEMP);
1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* check if this is a reference */
18503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		varsearch(e->loc, &vp, vn, hash(vn));
1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(vn, ATEMP);
1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vp && (vp->flag & (DEFINED|ASSOC|ARRAY)) ==
1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (DEFINED|ASSOC)) {
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char *cp;
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* gotcha! */
1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			cp = shf_smprintf("%s%s", str_val(vp), p);
1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(ap, ATEMP);
1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			n = ap = cp;
1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto redo_from_ref;
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (p != n && *p == '[' && (len = array_ref_len(p))) {
2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *sub, *tmp;
2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		mksh_ari_t rval;
2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
20303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* calculate the value of the subscript */
2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*arrayp = true;
2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strndupx(tmp, p + 1, len - 2, ATEMP);
2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sub = substitute(tmp, 0);
2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(tmp, ATEMP);
2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strndupx(n, n, p - n, ATEMP);
2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		evaluate(sub, &rval, KSH_UNWIND_ERROR, true);
2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*valp = (uint32_t)rval;
2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(sub, ATEMP);
2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (n);
2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Search for variable, if not found create globally.
2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl *
2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruglobal(const char *n)
2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l = e->loc;
2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp;
2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c;
2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool array;
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	uint32_t h, val;
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Check to see if this is an array */
2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	n = array_index_calc(n, &array, &val);
2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	h = hash(n);
2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	c = n[0];
2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!ksh_isalphx(c)) {
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (array)
2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			errorf("bad substitution");
2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp = &vtemp;
2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag = DEFINED;
2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->type = 0;
2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->areap = ATEMP;
2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*vp->name = c;
2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ksh_isdigit(c)) {
2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (c = 0; ksh_isdigit(*n); n++)
2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = c*10 + *n-'0';
2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (c <= l->argc)
2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* setstr can't fail here */
2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				setstr(vp, l->argv[c], KSH_RETURN_ERROR);
2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->flag |= RDONLY;
2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (vp);
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag |= RDONLY;
2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (n[1] != '\0')
2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (vp);
2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag |= ISSET|INTEGER;
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (c) {
2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '$':
2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->val.i = kshpid;
2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '!':
25803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* if no job, expand to nothing */
2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((vp->val.i = j_async()) == 0)
2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				vp->flag &= ~(ISSET|INTEGER);
2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->val.i = exstat;
2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '#':
2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->val.i = l->argc;
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '-':
2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->flag &= ~INTEGER;
2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->val.s = getoptions();
2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->flag &= ~(ISSET|INTEGER);
2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (vp);
2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
27703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	l = varsearch(e->loc, &vp, n, h);
27803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (vp != NULL)
27903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (array ? arraysearch(vp, val) : vp);
2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp = ktenter(&l->vars, n, h);
2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (array)
2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp = arraysearch(vp, val);
2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag |= DEFINED;
2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (special(n))
2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag |= SPECIAL;
2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (vp);
2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Search for local variable, if not found create locally.
2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl *
2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querulocal(const char *n, bool copy)
2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l = e->loc;
2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp;
2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool array;
2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	uint32_t h, val;
2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
30003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* check to see if this is an array */
3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	n = array_index_calc(n, &array, &val);
3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	h = hash(n);
3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!ksh_isalphx(*n)) {
3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp = &vtemp;
3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag = DEFINED|RDONLY;
3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->type = 0;
3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->areap = ATEMP;
3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (vp);
3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp = ktenter(&l->vars, n, h);
3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (copy && !(vp->flag & DEFINED)) {
31203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		struct tbl *vq;
3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		varsearch(l->next, &vq, n, h);
31503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (vq != NULL) {
3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->flag |= vq->flag &
3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (EXPORT | INTEGER | RDONLY | LJUST | RJUST |
3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ZEROFIL | LCASEV | UCASEV_AL | INT_U | INT_L);
3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vq->flag & INTEGER)
3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				vp->type = vq->type;
3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->u2.field = vq->u2.field;
3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (array)
3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp = arraysearch(vp, val);
3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag |= DEFINED;
3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (special(n))
3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag |= SPECIAL;
3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (vp);
3305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* get variable string value */
3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar *
3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustr_val(struct tbl *vp)
3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *s;
3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((vp->flag&SPECIAL))
3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		getspec(vp);
3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(vp->flag&ISSET))
34103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* special to dollar() */
34203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		s = null;
34303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if (!(vp->flag&INTEGER))
34403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* string source */
3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = vp->val.s + vp->type;
34603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else {
34703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* integer source */
34803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		mksh_uari_t n;
34903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		int base;
35003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/**
35103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * worst case number length is when base == 2:
35203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 *	1 (minus) + 2 (base, up to 36) + 1 ('#') +
35303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 *	number of bits in the mksh_uari_t + 1 (NUL)
35403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 */
3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char strbuf[1 + 2 + 1 + 8 * sizeof(mksh_uari_t) + 1];
3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		const char *digits = (vp->flag & UCASEV_AL) ?
3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    digits_uc : digits_lc;
3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = strbuf + sizeof(strbuf);
3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vp->flag & INT_U)
3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			n = vp->val.u;
3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			n = (vp->val.i < 0) ? -vp->val.i : vp->val.i;
3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		base = (vp->type == 0) ? 10 : vp->type;
3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
36603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (base == 1 && n == 0)
36703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			base = 2;
3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (base == 1) {
3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			size_t sz = 1;
3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*(s = strbuf) = '1';
3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s[1] = '#';
3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!UTFMODE || ((n & 0xFF80) == 0xEF80))
3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* OPTU-16 -> raw octet */
3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s[2] = n & 0xFF;
3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				sz = utf_wctomb(s + 2, n);
3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s[2 + sz] = '\0';
3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*--s = '\0';
3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			do {
3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*--s = digits[n % base];
3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				n /= base;
3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} while (n != 0);
3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (base != 10) {
3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*--s = '#';
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*--s = digits[base % 10];
3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (base >= 10)
3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					*--s = digits[base / 10];
3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!(vp->flag & INT_U) && vp->val.i < 0)
3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*--s = '-';
3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
39403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (vp->flag & (RJUST|LJUST))
39503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* case already dealt with */
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s = formatstr(vp, s);
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(s, s, ATEMP);
3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (s);
4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* set variable to string value */
4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetstr(struct tbl *vq, const char *s, int error_ok)
4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *salloc = NULL;
4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int no_ro_check = error_ok & 0x4;
4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	error_ok &= ~0x4;
4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((vq->flag & RDONLY) && !no_ro_check) {
41203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		warningf(true, "%s: %s", vq->name, "is read only");
4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!error_ok)
41403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			errorfxz(2);
4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
41703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!(vq->flag&INTEGER)) {
41803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* string dest */
4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((vq->flag&ALLOC)) {
4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* debugging */
4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (s >= vq->val.s &&
4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    s <= vq->val.s + strlen(vq->val.s))
4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				internal_errorf(
4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    "setstr: %s=%s: assigning to self",
4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    vq->name, s);
4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(vq->val.s, vq->areap);
4275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vq->flag &= ~(ISSET|ALLOC);
4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vq->type = 0;
4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s && (vq->flag & (UCASEV_AL|LCASEV|LJUST|RJUST)))
4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s = salloc = formatstr(vq, s);
4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((vq->flag&EXPORT))
4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			exportprep(vq, s);
4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else {
4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(vq->val.s, s, vq->areap);
4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vq->flag |= ALLOC;
4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
43803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else {
43903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* integer dest */
4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!v_evaluate(vq, s, error_ok, true))
4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vq->flag |= ISSET;
4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((vq->flag&SPECIAL))
4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setspec(vq);
4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(salloc, ATEMP);
4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (1);
4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* set variable to integer */
4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetint(struct tbl *vq, mksh_ari_t n)
4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(vq->flag&INTEGER)) {
4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *vp = &vtemp;
4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag = (ISSET|INTEGER);
4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->type = 0;
4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->areap = ATEMP;
4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->val.i = n;
4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* setstr can't fail here */
4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setstr(vq, str_val(vp), KSH_RETURN_ERROR);
4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vq->val.i = n;
4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vq->flag |= ISSET;
4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((vq->flag&SPECIAL))
4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setspec(vq);
4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetint(struct tbl *vp, mksh_ari_t *nump, bool arith)
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *s;
4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int c, base, neg;
4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool have_base = false;
4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t num;
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (vp->flag&SPECIAL)
4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		getspec(vp);
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* XXX is it possible for ISSET to be set and val.s to be 0? */
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL))
4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (-1);
4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (vp->flag&INTEGER) {
4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*nump = vp->val.i;
4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (vp->type);
4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s = vp->val.s + vp->type;
4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	base = 10;
4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	num = 0;
4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	neg = 0;
4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (arith && *s == '0' && *(s+1)) {
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s++;
4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*s == 'x' || *s == 'X') {
4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s++;
4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			base = 16;
4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (vp->flag & ZEROFIL) {
4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*s == '0')
4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s++;
4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			base = 8;
5005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		have_base = true;
5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (c = *s++; c ; c = *s++) {
5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '-') {
5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			neg++;
5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (c == '#') {
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			base = (int)num;
5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (have_base || base < 1 || base > 36)
5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (-1);
5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (base == 1) {
5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				unsigned int wc;
5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!UTFMODE)
5145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					wc = *(unsigned char *)s;
5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else if (utf_mbtowc(&wc, s) == (size_t)-1)
5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* OPTU-8 -> OPTU-16 */
5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/*
5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * (with a twist: 1#\uEF80 converts
5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * the same as 1#\x80 does, thus is
5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * not round-tripping correctly XXX)
5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 */
5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					wc = 0xEF00 + *(unsigned char *)s;
5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*nump = (mksh_ari_t)wc;
5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			num = 0;
5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			have_base = true;
5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (ksh_isdigit(c))
5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c -= '0';
5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else if (ksh_islower(c))
5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c -= 'a' - 10;
5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else if (ksh_isupper(c))
5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			c -= 'A' - 10;
5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (-1);
5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c < 0 || c >= base)
5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (-1);
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		num = num * base + c;
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (neg)
5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		num = -num;
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*nump = num;
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (base);
5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
54703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
54803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * convert variable vq to integer variable, setting its value from vp
5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (vq and vp may be the same)
5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl *
5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetint_v(struct tbl *vq, struct tbl *vp, bool arith)
5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int base;
5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t num;
5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((base = getint(vp, &num, arith)) == -1)
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (NULL);
55903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	setint_n(vq, num);
56003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (vq->type == 0)
56103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* default base */
56203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vq->type = base;
56303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (vq);
56403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
56503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
56603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* convert variable vq to integer variable, setting its value to num */
56703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
56803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasetint_n(struct tbl *vq, mksh_ari_t num)
56903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(vq->flag & INTEGER) && (vq->flag & ALLOC)) {
5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vq->flag &= ~ALLOC;
57203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vq->type = 0;
5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(vq->val.s, vq->areap);
5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vq->val.i = num;
5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vq->flag |= ISSET|INTEGER;
5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (vq->flag&SPECIAL)
5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setspec(vq);
5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *
5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruformatstr(struct tbl *vp, const char *s)
5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int olen, nlen;
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *p, *q;
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	size_t psiz;
5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
58803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	olen = (int)utf_mbswidth(s);
5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (vp->flag & (RJUST|LJUST)) {
59103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!vp->u2.field)
59203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* default field width */
5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->u2.field = olen;
5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		nlen = vp->u2.field;
5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		nlen = olen;
5975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p = alloc((psiz = nlen * /* MB_LEN_MAX */ 3 + 1), ATEMP);
5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (vp->flag & (RJUST|LJUST)) {
6005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int slen = olen, i = 0;
6015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vp->flag & RJUST) {
6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			const char *qq = s;
6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int n = 0;
6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (i < slen)
6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				i += utf_widthadj(qq, &qq);
6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* strip trailing spaces (AT&T uses qq[-1] == ' ') */
6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (qq > s && ksh_isspace(qq[-1])) {
6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				--qq;
6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				--slen;
6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vp->flag & ZEROFIL && vp->flag & INTEGER) {
6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (s[1] == '#')
6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					n = 2;
6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else if (s[2] == '#')
6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					n = 3;
6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (vp->u2.field <= n)
6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					n = 0;
6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (n) {
6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				memcpy(p, s, n);
6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s += n;
6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (slen > vp->u2.field)
6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				slen -= utf_widthadj(s, &s);
6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vp->u2.field - slen)
6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				memset(p + n, (vp->flag & ZEROFIL) ? '0' : ' ',
6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    vp->u2.field - slen);
6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			slen -= n;
6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_snprintf(p + vp->u2.field - slen,
6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    psiz - (vp->u2.field - slen),
6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    "%.*s", slen, s);
6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* strip leading spaces/zeros */
6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (ksh_isspace(*s))
6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s++;
6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vp->flag & ZEROFIL)
6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (*s == '0')
6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s++;
6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_snprintf(p, nlen + 1, "%-*.*s",
6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				vp->u2.field, vp->u2.field, s);
6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		memcpy(p, s, strlen(s) + 1);
6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (vp->flag & UCASEV_AL) {
6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (q = p; *q; q++)
6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*q = ksh_toupper(*q);
6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (vp->flag & LCASEV) {
6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (q = p; *q; q++)
6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*q = ksh_tolower(*q);
6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (p);
6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * make vp->val.s be "name=value" for quick exporting.
6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruexportprep(struct tbl *vp, const char *val)
6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *xp;
6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
66603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t namelen, vallen;
66703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
66803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	namelen = strlen(vp->name);
66903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vallen = strlen(val) + 1;
6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag |= ALLOC;
67203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* since name+val are both in memory this can go unchecked */
6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	xp = alloc(namelen + 1 + vallen, vp->areap);
6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	memcpy(vp->val.s = xp, vp->name, namelen);
6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	xp += namelen;
6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*xp++ = '=';
67703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* offset to value */
67803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vp->type = xp - vp->val.s;
6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	memcpy(xp, val, vallen);
6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (op != NULL)
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(op, vp->areap);
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
68503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * lookup variable (according to (set&LOCAL)), set its attributes
68603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * (INTEGER, RDONLY, EXPORT, TRACE, LJUST, RJUST, ZEROFIL, LCASEV,
68703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * UCASEV_AL), and optionally set its value if an assignment.
6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl *
69003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condratypeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp;
6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vpbase, *t;
6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *tvar;
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *val;
69603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t len;
69703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool vappend = false;
6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* check for valid variable name, search for value */
7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	val = skip_varname(var, false);
7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (val == var)
7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (NULL);
7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mkssert(var != NULL);
7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mkssert(*var != 0);
7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*val == '[') {
70603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (set_refflag != SRF_NOP)
70703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			errorf("%s: %s", var,
70803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "reference variable can't be an array");
7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		len = array_ref_len(val);
7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (len == 0)
7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (NULL);
71203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
71303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * IMPORT is only used when the shell starts up and is
7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * setting up its environment. Allow only simple array
71503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * references at this time since parameter/command
71603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * substitution is preformed on the [expression] which
71703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * would be a major security hole.
7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (set & IMPORT) {
72003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			size_t i;
72103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (i = 1; i < len - 1; i++)
7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!ksh_isdigit(val[i]))
7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (NULL);
7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val += len;
7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
72803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (val[0] == '=' || (val[0] == '+' && val[1] == '=')) {
72903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		strndupx(tvar, var, val - var, ATEMP);
73003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (*val++ == '+') {
73103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++val;
73203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			vappend = true;
73303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
73403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else {
73503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* importing from original environment: must have an = */
7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (set & IMPORT)
7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (NULL);
7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strdupx(tvar, var, ATEMP);
7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = NULL;
74003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* handle foo[*] => foo (whole array) mapping for R39b */
7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		len = strlen(tvar);
74203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (len > 3 && tvar[len - 3] == '[' && tvar[len - 2] == '*' &&
74303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    tvar[len - 1] == ']')
74403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			tvar[len - 3] = '\0';
7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
74703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (set_refflag == SRF_ENABLE) {
74803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		const char *qval;
74903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
75003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* bail out on 'nameref foo+=bar' */
75103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (vappend)
75203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			errorfz();
75303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* find value if variable already exists */
75403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((qval = val) == NULL) {
75503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			varsearch(e->loc, &vp, tvar, hash(tvar));
75603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (vp != NULL)
75703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				qval = str_val(vp);
75803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
75903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* silently ignore 'nameref foo=foo' */
76003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (qval != NULL && !strcmp(qval, tvar)) {
76103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			afree(tvar, ATEMP);
76203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (&vtemp);
76303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
76403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
76503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
76603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* prevent typeset from creating a local PATH/ENV/SHELL */
7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (Flag(FRESTRICTED) && (strcmp(tvar, "PATH") == 0 ||
7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    strcmp(tvar, "ENV") == 0 || strcmp(tvar, "SHELL") == 0))
76903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		errorf("%s: %s", tvar, "restricted");
7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
77103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vp = (set&LOCAL) ? local(tvar, tobool(set & LOCAL_COPY)) :
7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    global(tvar);
77303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (set_refflag == SRF_DISABLE && (vp->flag & (ARRAY|ASSOC)) == ASSOC)
7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag &= ~ASSOC;
77503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if (set_refflag == SRF_ENABLE) {
7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vp->flag & ARRAY) {
7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct tbl *a, *tmp;
7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
77903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* free up entire array */
7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (a = vp->u.array; a; ) {
7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				tmp = a;
7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				a = a->u.array;
7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (tmp->flag & ALLOC)
7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					afree(tmp->val.s, tmp->areap);
7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(tmp, tmp->areap);
7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->u.array = NULL;
7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp->flag &= ~ARRAY;
7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag |= ASSOC;
7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	set &= ~(LOCAL|LOCAL_COPY);
7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
79703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
79803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * only allow export flag to be set; AT&T ksh allows any
79903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * attribute to be changed which means it can be truncated or
80003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * modified (-L/-R/-Z/-i)
8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
8025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((vpbase->flag&RDONLY) &&
8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (val || clr || (set & ~EXPORT)))
8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* XXX check calls - is error here ok by POSIX? */
80503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		errorfx(2, "%s: %s", tvar, "is read only");
8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(tvar, ATEMP);
8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* most calls are with set/clr == 0 */
8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (set | clr) {
8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bool ok = true;
8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
81203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
81303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * XXX if x[0] isn't set, there will be problems: need
81403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * to have one copy of attributes for arrays...
8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (t = vpbase; t; t = t->u.array) {
8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bool fake_assign;
8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char *s = NULL;
8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char *free_me = NULL;
8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fake_assign = (t->flag & ISSET) && (!val || t != vp) &&
8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ((set & (UCASEV_AL|LCASEV|LJUST|RJUST|ZEROFIL)) ||
8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ((t->flag & INTEGER) && (clr & INTEGER)) ||
8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (!(t->flag & INTEGER) && (set & INTEGER)));
8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (fake_assign) {
8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (t->flag & INTEGER) {
8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s = str_val(t);
8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					free_me = NULL;
8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s = t->val.s + t->type;
8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					free_me = (t->flag & ALLOC) ? t->val.s :
8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    NULL;
8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				t->flag &= ~ALLOC;
8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!(t->flag & INTEGER) && (set & INTEGER)) {
8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				t->type = 0;
8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				t->flag &= ~ALLOC;
8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t->flag = (t->flag | set) & ~clr;
84103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
84203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * Don't change base if assignment is to be
84303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * done, in case assignment fails.
8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((set & INTEGER) && base > 0 && (!val || t != vp))
8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				t->type = base;
8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (set & (LJUST|RJUST|ZEROFIL))
8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				t->u2.field = field;
8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (fake_assign) {
8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!setstr(t, s, KSH_RETURN_ERROR)) {
85103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/*
85203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * Somewhat arbitrary action
85303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * here: zap contents of
85403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * variable, but keep the flag
85503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * settings.
8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 */
8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ok = false;
8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (t->flag & INTEGER)
8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						t->flag &= ~ISSET;
8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else {
8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (t->flag & ALLOC)
8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							afree(t->val.s, t->areap);
8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						t->flag &= ~(ISSET|ALLOC);
8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						t->type = 0;
8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (free_me)
8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					afree(free_me, t->areap);
8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!ok)
8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			errorfz();
8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (val != NULL) {
87603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		char *tval;
87703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
87803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (vappend) {
87903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			tval = shf_smprintf("%s%s", str_val(vp), val);
88003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			val = tval;
88103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
88203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			tval = NULL;
88303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vp->flag&INTEGER) {
8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* do not zero base before assignment */
8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			setstr(vp, val, KSH_UNWIND_ERROR | 0x4);
88703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* done after assignment to override default */
8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (base > 0)
8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				vp->type = base;
8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* setstr can't fail (readonly check already done) */
8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			setstr(vp, val, KSH_RETURN_ERROR | 0x4);
89303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
89403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (tval != NULL)
89503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			afree(tval, ATEMP);
8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* only x[0] is ever exported, so use vpbase */
8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((vpbase->flag&EXPORT) && !(vpbase->flag&INTEGER) &&
9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    vpbase->type == 0)
9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		exportprep(vpbase, (vpbase->flag&ISSET) ? vpbase->val.s : null);
9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (vp);
9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/**
9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Unset a variable. The flags can be:
9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * |1	= tear down entire array
9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * |2	= keep attributes, only unset content
9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruunset(struct tbl *vp, int flags)
9135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (vp->flag & ALLOC)
9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(vp->val.s, vp->areap);
9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((vp->flag & ARRAY) && (flags & 1)) {
9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *a, *tmp;
9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
91903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* free up entire array */
9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (a = vp->u.array; a; ) {
9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tmp = a;
9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			a = a->u.array;
9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (tmp->flag & ALLOC)
9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(tmp->val.s, tmp->areap);
9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(tmp, tmp->areap);
9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->u.array = NULL;
9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (flags & 2) {
9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag &= ~(ALLOC|ISSET);
9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
93303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* if foo[0] is being unset, the remainder of the array is kept... */
9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag &= SPECIAL | ((flags & 1) ? 0 : ARRAY|DEFINED);
9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (vp->flag & SPECIAL)
93603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* responsible for 'unspecial'ing var */
93703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		unsetspec(vp);
9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
94003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
94103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Return a pointer to the first char past a legal variable name
94203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * (returns the argument if there is no legal name, returns a pointer to
94303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * the terminating NUL if whole string is legal).
9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst char *
9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruskip_varname(const char *s, int aok)
9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
94803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t alen;
9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (s && ksh_isalphx(*s)) {
9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (*++s && ksh_isalnux(*s))
9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (aok && *s == '[' && (alen = array_ref_len(s)))
9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s += alen;
9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (s);
9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Return a pointer to the first character past any legal variable name */
9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst char *
9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruskip_wdvarname(const char *s,
96203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra    /* skip array de-reference? */
96303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra    bool aok)
9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (s[0] == CHAR && ksh_isalphx(s[1])) {
9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		do {
9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s += 2;
9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} while (s[0] == CHAR && ksh_isalnux(s[1]));
9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (aok && s[0] == CHAR && s[1] == '[') {
9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* skip possible array de-reference */
9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			const char *p = s;
9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char c;
9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int depth = 0;
9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
97503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (/* CONSTCOND */ 1) {
9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (p[0] != CHAR)
9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = p[1];
9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				p += 2;
9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == '[')
9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					depth++;
9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else if (c == ']' && --depth == 0) {
9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s = p;
9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (s);
9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Check if coded string s is a variable name */
9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
99403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrais_wdvarname(const char *s, bool aok)
9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *p = skip_wdvarname(s, aok);
9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (p != s && p[0] == EOS);
9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Check if coded string s is a variable assignment */
10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruis_wdvarassign(const char *s)
10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *p = skip_wdvarname(s, true);
10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
100703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (p != s && p[0] == CHAR &&
100803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    (p[1] == '=' || (p[1] == '+' && p[2] == CHAR && p[3] == '=')));
10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Make the exported environment from the exported names in the dictionary.
10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar **
10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querumakenv(void)
10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
101703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ssize_t i;
10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l;
10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XPtrV denv;
10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp, **vpp;
10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XPinit(denv, 64);
102303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	for (l = e->loc; l != NULL; l = l->next) {
102403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vpp = l->vars.tbls;
102503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = 1 << (l->vars.tshift);
102603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (--i >= 0)
10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((vp = *vpp++) != NULL &&
10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) {
10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				struct block *l2;
10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				struct tbl *vp2;
10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				uint32_t h = hash(vp->name);
10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* unexport any redefined instances */
10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				for (l2 = l->next; l2 != NULL; l2 = l2->next) {
10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					vp2 = ktsearch(&l2->vars, vp->name, h);
10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (vp2 != NULL)
10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						vp2->flag &= ~EXPORT;
10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((vp->flag&INTEGER)) {
10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* integer to string */
10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char *val;
10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					val = str_val(vp);
10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					vp->flag &= ~(INTEGER|RDONLY|SPECIAL);
10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* setstr can't fail here */
10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					setstr(vp, val, KSH_RETURN_ERROR);
10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				XPput(denv, vp->val.s);
10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
104903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XPput(denv, NULL);
10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return ((char **)XPclose(denv));
10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * handle special variables with side effects - PATH, SECONDS.
10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Test if name is a special parameter */
10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruspecial(const char *name)
10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *tp;
10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp = ktsearch(&specials, name, hash(name));
10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (tp && (tp->flag & ISSET) ? tp->type : V_NONE);
10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Make a variable non-special */
10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruunspecial(const char *name)
10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *tp;
10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp = ktsearch(&specials, name, hash(name));
10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (tp)
10765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ktdelete(tp);
10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic time_t seconds;		/* time SECONDS last set */
10805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int user_lineno;		/* what user set $LINENO to */
10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetspec(struct tbl *vp)
10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	register mksh_ari_t i;
10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int st;
10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch ((st = special(vp->name))) {
10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_SECONDS:
10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * On start up the value of SECONDS is used before
10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * it has been set - don't do anything in this case
10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * (see initcoms[] in main.c).
10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vp->flag & ISSET) {
10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct timeval tv;
10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			gettimeofday(&tv, NULL);
10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			i = tv.tv_sec - seconds;
11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return;
11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_RANDOM:
11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * this is the same Linear Congruential PRNG as Borland
11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * C/C++ allegedly uses in its built-in rand() function
11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
110803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = ((lcg_state = 22695477 * lcg_state + 1) >> 16) & 0x7FFF;
11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_HISTSIZE:
11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = histsize;
11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_OPTIND:
11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = user_opt.uoptind;
11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_LINENO:
11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = current_lineno + user_lineno;
11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_COLUMNS:
11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_LINES:
11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * Do NOT export COLUMNS/LINES. Many applications
11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * check COLUMNS/LINES before checking ws.ws_col/row,
11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * so if the app is started with C/L in the environ
11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * and the window is then resized, the app won't
11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * see the change cause the environ doesn't change.
11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		change_winsz();
11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = st == V_COLUMNS ? x_cols : x_lins;
11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	default:
11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* do nothing, do not touch vp at all */
11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag &= ~SPECIAL;
113603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	setint_n(vp, i);
11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag |= SPECIAL;
11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetspec(struct tbl *vp)
11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t i;
11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *s;
11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int st;
11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch ((st = special(vp->name))) {
11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_PATH:
11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (path)
11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(path, APERM);
11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = str_val(vp);
11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strdupx(path, s, APERM);
115303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* clear tracked aliases */
115403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		flushcom(true);
11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_IFS:
11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setctypes(s = str_val(vp), C_IFS);
11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ifs0 = *s;
11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_TMPDIR:
11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (tmpdir) {
11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(tmpdir, APERM);
11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tmpdir = NULL;
11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
116503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
116603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Use tmpdir iff it is an absolute path, is writable
116703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * and searchable and is a directory...
11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{
11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct stat statb;
11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s = str_val(vp);
117303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* LINTED use of access */
11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (s[0] == '/' && access(s, W_OK|X_OK) == 0 &&
11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    stat(s, &statb) == 0 && S_ISDIR(statb.st_mode))
11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strdupx(tmpdir, s, APERM);
11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
117803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return;
11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_HISTFILE:
11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sethistfile(str_val(vp));
118203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return;
11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* common sub-cases */
11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_OPTIND:
11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_HISTSIZE:
11885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_COLUMNS:
11895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_LINES:
11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_RANDOM:
11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_SECONDS:
11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_LINENO:
119303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case V_TMOUT:
11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag &= ~SPECIAL;
119503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (getint(vp, &i, false) == -1) {
119603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			s = str_val(vp);
119703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (st != V_RANDOM)
119803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				errorf("%s: %s: %s", vp->name, "bad number", s);
119903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			i = hash(s);
120003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp->flag |= SPECIAL;
12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	default:
12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* do nothing, do not touch vp at all */
12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* process the singular parts of the common cases */
12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (st) {
12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_OPTIND:
12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		getopts_reset((int)i);
12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_HISTSIZE:
12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sethistsize((int)i);
12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_COLUMNS:
12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (i >= MIN_COLS)
12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			x_cols = i;
12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_LINES:
12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (i >= MIN_LINS)
12235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			x_lins = i;
12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_RANDOM:
12265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * mksh R39d+ no longer has the traditional repeatability
12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * of $RANDOM sequences, but always retains state
12295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
123003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rndset((long)i);
12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_SECONDS:
12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{
12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct timeval tv;
12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			gettimeofday(&tv, NULL);
12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			seconds = tv.tv_sec - i;
12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_LINENO:
12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* The -1 is because line numbering starts at 1. */
12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		user_lineno = (unsigned int)i - current_lineno - 1;
12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
124403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case V_TMOUT:
124503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ksh_tmout = i >= 0 ? i : 0;
124603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruunsetspec(struct tbl *vp)
12525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (special(vp->name)) {
12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_PATH:
12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (path)
12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(path, APERM);
12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strdupx(path, def_path, APERM);
125803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* clear tracked aliases */
125903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		flushcom(true);
12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_IFS:
12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setctypes(" \t\n", C_IFS);
12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ifs0 = ' ';
12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_TMPDIR:
12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* should not become unspecial */
12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (tmpdir) {
12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(tmpdir, APERM);
12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tmpdir = NULL;
12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_LINENO:
12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_RANDOM:
12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case V_SECONDS:
127503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case V_TMOUT:
127603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* AT&T ksh leaves previous value in place */
12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		unspecial(vp->name);
12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * AT&T ksh man page says OPTIND, OPTARG and _ lose special
12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * meaning, but OPTARG does not (still set by getopts) and _ is
12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * also still set in various places. Don't know what AT&T does
12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * for HISTSIZE, HISTFILE. Unsetting these in AT&T ksh does not
12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * loose the 'specialness': IFS, COLUMNS, PATH, TMPDIR
12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Search for (and possibly create) a table entry starting with
12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * vp, indexed by val.
12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
129403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastruct tbl *
12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruarraysearch(struct tbl *vp, uint32_t val)
12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *prev, *curr, *news;
12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	size_t len;
12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag = (vp->flag | (ARRAY|DEFINED)) & ~ASSOC;
130103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* the table entry is always [0] */
13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (val == 0)
13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (vp);
13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	prev = vp;
13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	curr = vp->u.array;
13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (curr && curr->ua.index < val) {
13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		prev = curr;
13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		curr = curr->u.array;
13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (curr && curr->ua.index == val) {
13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (curr->flag&ISSET)
13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (curr);
13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		news = curr;
13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		news = NULL;
13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!news) {
131703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		len = strlen(vp->name);
131803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		checkoktoadd(len, 1 + offsetof(struct tbl, name[0]));
131903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		news = alloc(offsetof(struct tbl, name[0]) + ++len, vp->areap);
13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		memcpy(news->name, vp->name, len);
13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	news->flag = (vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL)) | AINDEX;
13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	news->type = vp->type;
13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	news->areap = vp->areap;
13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	news->u2.field = vp->u2.field;
13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	news->ua.index = val;
13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
132803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (curr != news) {
132903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* not reusing old array entry */
13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		prev->u.array = news;
13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		news->u.array = curr;
13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (news);
13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
133603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
133703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Return the length of an array reference (eg, [1+2]) - cp is assumed
133803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * to point to the open bracket. Returns 0 if there is no matching
133903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * closing bracket.
13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
134103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasize_t
13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruarray_ref_len(const char *cp)
13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *s = cp;
134503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char c;
13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int depth = 0;
13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((c = *s++) && (c != ']' || --depth))
13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (c == '[')
13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			depth++;
13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!c)
13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (s - cp);
13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Make a copy of the base of an array name
13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar *
13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruarrayname(const char *str)
13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *p;
13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *rv;
13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((p = cstrchr(str, '[')) == 0)
13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Shouldn't happen, but why worry? */
13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strdupx(rv, str, ATEMP);
13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strndupx(rv, str, p - str, ATEMP);
13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* set (or overwrite, if reset) the array variable var to the values in vals */
13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querumksh_uari_t
13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruset_array(const char *var, bool reset, const char **vals)
13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp, *vq;
137903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	mksh_uari_t i = 0, j = 0;
13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *ccp;
13815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
138203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *cp = NULL;
138303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t n;
13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* to get local array, use "typeset foo; set -A foo" */
138703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_SMALL
138803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	n = strlen(var);
138903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (n > 0 && var[n - 1] == '+') {
139003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* append mode */
139103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		reset = false;
139203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		strndupx(cp, var, n - 1, ATEMP);
139303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
139403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define CPORVAR	(cp ? cp : var)
139503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else
139603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define CPORVAR	var
139703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
139803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vp = global(CPORVAR);
13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Note: AT&T ksh allows set -A but not set +A of a read-only var */
14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((vp->flag&RDONLY))
140203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		errorfx(2, "%s: %s", CPORVAR, "is read only");
14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* This code is quite non-optimal */
14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (reset)
14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* trash existing values and attributes */
14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		unset(vp, 1);
140703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
140803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * TODO: would be nice for assignment to completely succeed or
14095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * completely fail. Only really effects integer arrays:
14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * evaluation of some of vals[] may fail...
14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
141303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (cp != NULL) {
141403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* find out where to set when appending */
141503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		for (vq = vp; vq; vq = vq->u.array) {
141603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (!(vq->flag & ISSET))
141703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				continue;
141803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (arrayindex(vq) >= j)
141903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				j = arrayindex(vq) + 1;
142003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
142103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		afree(cp, ATEMP);
142203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((ccp = vals[i])) {
14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*ccp == '[') {
14275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int level = 0;
14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*ccp) {
14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*ccp == ']' && --level == 0)
14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*ccp == '[')
14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					++level;
14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				++ccp;
14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*ccp == ']' && level == 0 && ccp[1] == '=') {
14375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strndupx(cp, vals[i] + 1, ccp - (vals[i] + 1),
14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    ATEMP);
14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				evaluate(substitute(cp, 0), (mksh_ari_t *)&j,
14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    KSH_UNWIND_ERROR, true);
14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(cp, ATEMP);
14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ccp += 2;
14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ccp = vals[i];
14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vq = arraysearch(vp, j);
14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* would be nice to deal with errors here... (see above) */
14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setstr(vq, ccp, KSH_RETURN_ERROR);
14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i++;
14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		j++;
14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (i);
14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchange_winsz(void)
14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (x_lins < 0) {
14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* first time initialisation */
14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef TIOCGWINSZ
14645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (tty_fd < 0)
14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* non-FTALKING, try to get an fd anyway */
146603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			tty_init(true, false);
14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		x_cols = -1;
14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef TIOCGWINSZ
14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* check if window size has changed */
14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (tty_fd >= 0) {
14745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct winsize ws;
14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ioctl(tty_fd, TIOCGWINSZ, &ws) >= 0) {
14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ws.ws_col)
14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				x_cols = ws.ws_col;
14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ws.ws_row)
14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				x_lins = ws.ws_row;
14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* bounds check for sane values, use defaults otherwise */
14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (x_cols < MIN_COLS)
14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		x_cols = 80;
14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (x_lins < MIN_LINS)
14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		x_lins = 24;
14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef SIGWINCH
14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	got_winch = 0;
14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruuint32_t
149703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrahash(const void *s)
14985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
149903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	register uint32_t h;
150003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
150103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZATInit(h);
150203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZATUpdateString(h, s);
150303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZATFinish(h);
150403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (h);
150503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
150603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
150703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
150803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrarndset(long v)
150903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
151003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	register uint32_t h;
151103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
151203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZATInit(h);
151303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZATUpdateMem(h, &lcg_state, sizeof(lcg_state));
151403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZATUpdateMem(h, &v, sizeof(v));
151503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
151603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
151703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
151803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * either we have very chap entropy get and push available,
151903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * with malloc() pulling in this code already anyway, or the
152003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * user requested us to use the old functions
152103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 */
152203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	lcg_state = h;
152303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZAATFinish(lcg_state);
152403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if defined(arc4random_pushb_fast)
152503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	arc4random_pushb_fast(&lcg_state, sizeof(lcg_state));
152603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	lcg_state = arc4random();
152703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else
152803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	lcg_state = arc4random_pushb(&lcg_state, sizeof(lcg_state));
152903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
153003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZATUpdateMem(h, &lcg_state, sizeof(lcg_state));
153103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
153303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	NZAATFinish(h);
153403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	lcg_state = h;
15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1536