summary refs log tree commit diff
path: root/bin/dash/src/var.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/dash/src/var.c')
-rw-r--r--bin/dash/src/var.c676
1 files changed, 0 insertions, 676 deletions
diff --git a/bin/dash/src/var.c b/bin/dash/src/var.c
deleted file mode 100644
index ca9504ef..00000000
--- a/bin/dash/src/var.c
+++ /dev/null
@@ -1,676 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1997-2005
- *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_PATHS_H
-#include <paths.h>
-#endif
-
-/*
- * Shell variables.
- */
-
-#include "shell.h"
-#include "output.h"
-#include "expand.h"
-#include "nodes.h"	/* for other headers */
-#include "exec.h"
-#include "syntax.h"
-#include "options.h"
-#include "mail.h"
-#include "var.h"
-#include "memalloc.h"
-#include "error.h"
-#include "mystring.h"
-#include "parser.h"
-#include "show.h"
-#ifndef SMALL
-#include "myhistedit.h"
-#endif
-#include "system.h"
-
-
-#define VTABSIZE 39
-
-
-struct localvar_list {
-	struct localvar_list *next;
-	struct localvar *lv;
-};
-
-MKINIT struct localvar_list *localvar_stack;
-
-const char defpathvar[] =
-	"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
-char defifsvar[] = "IFS= \t\n";
-MKINIT char defoptindvar[] = "OPTIND=1";
-
-int lineno;
-char linenovar[sizeof("LINENO=")+sizeof(int)*CHAR_BIT/3+1] = "LINENO=";
-
-/* Some macros in var.h depend on the order, add new variables to the end. */
-struct var varinit[] = {
-#if ATTY
-	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY\0",	0 },
-#endif
-	{ 0,	VSTRFIXED|VTEXTFIXED,		defifsvar,	0 },
-	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL\0",	changemail },
-	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH\0",	changemail },
-	{ 0,	VSTRFIXED|VTEXTFIXED,		defpathvar,	changepath },
-	{ 0,	VSTRFIXED|VTEXTFIXED,		"PS1=$ ",	0 },
-	{ 0,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",	0 },
-	{ 0,	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",	0 },
-	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"RPS1\0",	0 },
-	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"RPS2\0",	0 },
-	{ 0,	VSTRFIXED|VTEXTFIXED,		defoptindvar,	getoptsreset },
-#ifdef WITH_LINENO
-	{ 0,	VSTRFIXED|VTEXTFIXED,		linenovar,	0 },
-#endif
-#ifndef SMALL
-	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM\0",	0 },
-	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE\0",	sethistsize },
-#endif
-};
-
-STATIC struct var *vartab[VTABSIZE];
-
-STATIC struct var **hashvar(const char *);
-STATIC int vpcmp(const void *, const void *);
-STATIC struct var **findvar(struct var **, const char *);
-
-/*
- * Initialize the varable symbol tables and import the environment
- */
-
-#ifdef mkinit
-INCLUDE <unistd.h>
-INCLUDE <sys/types.h>
-INCLUDE <sys/stat.h>
-INCLUDE "cd.h"
-INCLUDE "output.h"
-INCLUDE "var.h"
-MKINIT char **environ;
-INIT {
-	char **envp;
-	static char ppid[32] = "PPID=";
-	const char *p;
-	struct stat64 st1, st2;
-
-	initvar();
-	for (envp = environ ; *envp ; envp++) {
-		p = endofname(*envp);
-		if (p != *envp && *p == '=') {
-			setvareq(*envp, VEXPORT|VTEXTFIXED);
-		}
-	}
-
-	setvareq(defifsvar, VTEXTFIXED);
-	setvareq(defoptindvar, VTEXTFIXED);
-
-	fmtstr(ppid + 5, sizeof(ppid) - 5, "%ld", (long) getppid());
-	setvareq(ppid, VTEXTFIXED);
-
-	p = lookupvar("PWD");
-	if (p)
-		if (*p != '/' || stat64(p, &st1) || stat64(".", &st2) ||
-		    st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
-			p = 0;
-	setpwd(p, 0);
-}
-
-RESET {
-	unwindlocalvars(0);
-}
-#endif
-
-
-/*
- * This routine initializes the builtin variables.  It is called when the
- * shell is initialized.
- */
-
-void
-initvar(void)
-{
-	struct var *vp;
-	struct var *end;
-	struct var **vpp;
-
-	vp = varinit;
-	end = vp + sizeof(varinit) / sizeof(varinit[0]);
-	do {
-		vpp = hashvar(vp->text);
-		vp->next = *vpp;
-		*vpp = vp;
-	} while (++vp < end);
-	/*
-	 * PS1 depends on uid
-	 */
-	if (!geteuid())
-		vps1.text = "PS1=# ";
-}
-
-/*
- * Set the value of a variable.  The flags argument is ored with the
- * flags of the variable.  If val is NULL, the variable is unset.
- */
-
-struct var *setvar(const char *name, const char *val, int flags)
-{
-	char *p, *q;
-	size_t namelen;
-	char *nameeq;
-	size_t vallen;
-	struct var *vp;
-
-	q = endofname(name);
-	p = strchrnul(q, '=');
-	namelen = p - name;
-	if (!namelen || p != q)
-		sh_error("%.*s: bad variable name", namelen, name);
-	vallen = 0;
-	if (val == NULL) {
-		flags |= VUNSET;
-	} else {
-		vallen = strlen(val);
-	}
-	INTOFF;
-	p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
-	if (val) {
-		*p++ = '=';
-		p = mempcpy(p, val, vallen);
-	}
-	*p = '\0';
-	vp = setvareq(nameeq, flags | VNOSAVE);
-	INTON;
-
-	return vp;
-}
-
-/*
- * Set the given integer as the value of a variable.  The flags argument is
- * ored with the flags of the variable.
- */
-
-intmax_t setvarint(const char *name, intmax_t val, int flags)
-{
-	int len = max_int_length(sizeof(val));
-	char buf[len];
-
-	fmtstr(buf, len, "%" PRIdMAX, val);
-	setvar(name, buf, flags);
-	return val;
-}
-
-
-
-/*
- * Same as setvar except that the variable and value are passed in
- * the first argument as name=value.  Since the first argument will
- * be actually stored in the table, it should not be a string that
- * will go away.
- * Called with interrupts off.
- */
-
-struct var *setvareq(char *s, int flags)
-{
-	struct var *vp, **vpp;
-
-	vpp = hashvar(s);
-	flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
-	vpp = findvar(vpp, s);
-	vp = *vpp;
-	if (vp) {
-		if (vp->flags & VREADONLY) {
-			const char *n;
-
-			if (flags & VNOSAVE)
-				free(s);
-			n = vp->text;
-			sh_error("%.*s: is read only", strchrnul(n, '=') - n,
-				 n);
-		}
-
-		if (flags & VNOSET)
-			goto out;
-
-		if (vp->func && (flags & VNOFUNC) == 0)
-			(*vp->func)(strchrnul(s, '=') + 1);
-
-		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
-			ckfree(vp->text);
-
-		if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) |
-		     (vp->flags & VSTRFIXED)) == VUNSET) {
-			*vpp = vp->next;
-			ckfree(vp);
-out_free:
-			if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
-				ckfree(s);
-			goto out;
-		}
-
-		flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
-	} else {
-		if (flags & VNOSET)
-			goto out;
-		if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
-			goto out_free;
-		/* not found */
-		vp = ckmalloc(sizeof (*vp));
-		vp->next = *vpp;
-		vp->func = NULL;
-		*vpp = vp;
-	}
-	if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
-		s = savestr(s);
-	vp->text = s;
-	vp->flags = flags;
-
-out:
-	return vp;
-}
-
-/*
- * Find the value of a variable.  Returns NULL if not set.
- */
-
-char *
-lookupvar(const char *name)
-{
-	struct var *v;
-
-	if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
-#ifdef WITH_LINENO
-		if (v == &vlineno && v->text == linenovar) {
-			fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
-		}
-#endif
-		return strchrnul(v->text, '=') + 1;
-	}
-	return NULL;
-}
-
-intmax_t lookupvarint(const char *name)
-{
-	return atomax(lookupvar(name) ?: nullstr, 0);
-}
-
-
-
-/*
- * Generate a list of variables satisfying the given conditions.
- */
-
-char **
-listvars(int on, int off, char ***end)
-{
-	struct var **vpp;
-	struct var *vp;
-	char **ep;
-	int mask;
-
-	STARTSTACKSTR(ep);
-	vpp = vartab;
-	mask = on | off;
-	do {
-		for (vp = *vpp ; vp ; vp = vp->next)
-			if ((vp->flags & mask) == on) {
-				if (ep == stackstrend())
-					ep = growstackstr();
-				*ep++ = (char *) vp->text;
-			}
-	} while (++vpp < vartab + VTABSIZE);
-	if (ep == stackstrend())
-		ep = growstackstr();
-	if (end)
-		*end = ep;
-	*ep++ = NULL;
-	return grabstackstr(ep);
-}
-
-
-
-/*
- * POSIX requires that 'set' (but not export or readonly) output the
- * variables in lexicographic order - by the locale's collating order (sigh).
- * Maybe we could keep them in an ordered balanced binary tree
- * instead of hashed lists.
- * For now just roll 'em through qsort for printing...
- */
-
-int
-showvars(const char *prefix, int on, int off)
-{
-	const char *sep;
-	char **ep, **epend;
-
-	ep = listvars(on, off, &epend);
-	qsort(ep, epend - ep, sizeof(char *), vpcmp);
-
-	sep = *prefix ? spcstr : prefix;
-
-	for (; ep < epend; ep++) {
-		const char *p;
-		const char *q;
-
-		p = strchrnul(*ep, '=');
-		q = nullstr;
-		if (*p)
-			q = single_quote(++p);
-
-		out1fmt("%s%s%.*s%s\n", prefix, sep, (int)(p - *ep), *ep, q);
-	}
-
-	return 0;
-}
-
-
-
-/*
- * The export and readonly commands.
- */
-
-int
-exportcmd(int argc, char **argv)
-{
-	struct var *vp;
-	char *name;
-	const char *p;
-	char **aptr;
-	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
-	int notp;
-
-	notp = nextopt("p") - 'p';
-	if (notp && ((name = *(aptr = argptr)))) {
-		do {
-			if ((p = strchr(name, '=')) != NULL) {
-				p++;
-			} else {
-				if ((vp = *findvar(hashvar(name), name))) {
-					vp->flags |= flag;
-					continue;
-				}
-			}
-			setvar(name, p, flag);
-		} while ((name = *++aptr) != NULL);
-	} else {
-		showvars(argv[0], flag, 0);
-	}
-	return 0;
-}
-
-
-/*
- * The "local" command.
- */
-
-int
-localcmd(int argc, char **argv)
-{
-	char *name;
-
-	if (!localvar_stack)
-		sh_error("not in a function");
-
-	argv = argptr;
-	while ((name = *argv++) != NULL) {
-		mklocal(name, 0);
-	}
-	return 0;
-}
-
-
-/*
- * Make a variable a local variable.  When a variable is made local, it's
- * value and flags are saved in a localvar structure.  The saved values
- * will be restored when the shell function returns.  We handle the name
- * "-" as a special case.
- */
-
-void mklocal(char *name, int flags)
-{
-	struct localvar *lvp;
-	struct var **vpp;
-	struct var *vp;
-
-	INTOFF;
-	lvp = ckmalloc(sizeof (struct localvar));
-	if (name[0] == '-' && name[1] == '\0') {
-		char *p;
-		p = ckmalloc(sizeof(optlist));
-		lvp->text = memcpy(p, optlist, sizeof(optlist));
-		vp = NULL;
-	} else {
-		char *eq;
-
-		vpp = hashvar(name);
-		vp = *findvar(vpp, name);
-		eq = strchr(name, '=');
-		if (vp == NULL) {
-			if (eq)
-				vp = setvareq(name, VSTRFIXED | flags);
-			else
-				vp = setvar(name, NULL, VSTRFIXED | flags);
-			lvp->flags = VUNSET;
-		} else {
-			lvp->text = vp->text;
-			lvp->flags = vp->flags;
-			vp->flags |= VSTRFIXED|VTEXTFIXED;
-			if (eq)
-				setvareq(name, flags);
-		}
-	}
-	lvp->vp = vp;
-	lvp->next = localvar_stack->lv;
-	localvar_stack->lv = lvp;
-	INTON;
-}
-
-
-/*
- * Called after a function returns.
- * Interrupts must be off.
- */
-
-static void
-poplocalvars(void)
-{
-	struct localvar_list *ll;
-	struct localvar *lvp, *next;
-	struct var *vp;
-
-	INTOFF;
-	ll = localvar_stack;
-	localvar_stack = ll->next;
-
-	next = ll->lv;
-	ckfree(ll);
-
-	while ((lvp = next) != NULL) {
-		next = lvp->next;
-		vp = lvp->vp;
-		TRACE(("poplocalvar %s\n", vp ? vp->text : "-"));
-		if (vp == NULL) {	/* $- saved */
-			memcpy(optlist, lvp->text, sizeof(optlist));
-			ckfree(lvp->text);
-			optschanged();
-		} else if (lvp->flags == VUNSET) {
-			vp->flags &= ~(VSTRFIXED|VREADONLY);
-			unsetvar(vp->text);
-		} else {
-			if (vp->func)
-				(*vp->func)(strchrnul(lvp->text, '=') + 1);
-			if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
-				ckfree(vp->text);
-			vp->flags = lvp->flags;
-			vp->text = lvp->text;
-		}
-		ckfree(lvp);
-	}
-	INTON;
-}
-
-
-/*
- * Create a new localvar environment.
- */
-struct localvar_list *pushlocalvars(int push)
-{
-	struct localvar_list *ll;
-	struct localvar_list *top;
-
-	top = localvar_stack;
-	if (!push)
-		goto out;
-
-	INTOFF;
-	ll = ckmalloc(sizeof(*ll));
-	ll->lv = NULL;
-	ll->next = top;
-	localvar_stack = ll;
-	INTON;
-
-out:
-	return top;
-}
-
-
-void unwindlocalvars(struct localvar_list *stop)
-{
-	while (localvar_stack != stop)
-		poplocalvars();
-}
-
-
-/*
- * The unset builtin command.  We unset the function before we unset the
- * variable to allow a function to be unset when there is a readonly variable
- * with the same name.
- */
-
-int
-unsetcmd(int argc, char **argv)
-{
-	char **ap;
-	int i;
-	int flag = 0;
-
-	while ((i = nextopt("vf")) != '\0') {
-		flag = i;
-	}
-
-	for (ap = argptr; *ap ; ap++) {
-		if (flag != 'f') {
-			unsetvar(*ap);
-			continue;
-		}
-		if (flag != 'v')
-			unsetfunc(*ap);
-	}
-	return 0;
-}
-
-
-/*
- * Unset the specified variable.
- */
-
-void unsetvar(const char *s)
-{
-	setvar(s, 0, 0);
-}
-
-
-
-/*
- * Find the appropriate entry in the hash table from the name.
- */
-
-STATIC struct var **
-hashvar(const char *p)
-{
-	unsigned int hashval;
-
-	hashval = ((unsigned char) *p) << 4;
-	while (*p && *p != '=')
-		hashval += (unsigned char) *p++;
-	return &vartab[hashval % VTABSIZE];
-}
-
-
-
-/*
- * Compares two strings up to the first = or '\0'.  The first
- * string must be terminated by '='; the second may be terminated by
- * either '=' or '\0'.
- */
-
-int
-varcmp(const char *p, const char *q)
-{
-	int c, d;
-
-	while ((c = *p) == (d = *q)) {
-		if (!c || c == '=')
-			goto out;
-		p++;
-		q++;
-	}
-	if (c == '=')
-		c = 0;
-	if (d == '=')
-		d = 0;
-out:
-	return c - d;
-}
-
-STATIC int
-vpcmp(const void *a, const void *b)
-{
-	return varcmp(*(const char **)a, *(const char **)b);
-}
-
-STATIC struct var **
-findvar(struct var **vpp, const char *name)
-{
-	for (; *vpp; vpp = &(*vpp)->next) {
-		if (varequal((*vpp)->text, name)) {
-			break;
-		}
-	}
-	return vpp;
-}