var.c

来自「Android 一些工具」· C语言 代码 · 共 826 行 · 第 1/2 页

C
826
字号
/*	$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $	*//*- * Copyright (c) 1991, 1993 *	The Regents of the University of California.  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 <sys/cdefs.h>#ifndef lint#if 0static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";#else__RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $");#endif#endif /* not lint */#include <unistd.h>#include <stdlib.h>#include <paths.h>/* * Shell variables. */#include "shell.h"#include "output.h"#include "expand.h"#include "nodes.h"	/* for other headers */#include "eval.h"	/* defines cmdenviron */#include "exec.h"#include "syntax.h"#include "options.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#ifdef SMALL#define VTABSIZE 39#else#define VTABSIZE 517#endifstruct varinit {	struct var *var;	int flags;	const char *text;	void (*func)(const char *);};#if ATTYstruct var vatty;#endif#ifdef WITH_HISTORYstruct var vhistsize;struct var vterm;#endifstruct var vifs;struct var vmpath;struct var vpath;struct var vps1;struct var vps2;struct var vps4;struct var vvers;struct var voptind;const struct varinit varinit[] = {#if ATTY	{ &vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",	  NULL },#endif#ifdef WITH_HISTORY	{ &vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",	  sethistsize },#endif	{ &vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n",	  NULL },	{ &vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",	  NULL },	{ &vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=" _PATH_DEFPATH,	  changepath },	/*	 * vps1 depends on uid	 */	{ &vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",	  NULL },	{ &vps4,	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",	  NULL },#ifdef WITH_HISTORY	{ &vterm,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM=",	  setterm },#endif	{ &voptind,	VSTRFIXED|VTEXTFIXED|VNOFUNC,	"OPTIND=1",	  getoptsreset },	{ NULL,	0,				NULL,	  NULL }};struct var *vartab[VTABSIZE];STATIC int strequal(const char *, const char *);STATIC struct var *find_var(const char *, struct var ***, int *);/* * Initialize the varable symbol tables and import the environment */#ifdef mkinitINCLUDE "var.h"MKINIT char **environ;INIT {	char **envp;	initvar();	for (envp = environ ; *envp ; envp++) {		if (strchr(*envp, '=')) {			setvareq(*envp, VEXPORT|VTEXTFIXED);		}	}}#endif/* * This routine initializes the builtin variables.  It is called when the * shell is initialized and again when a shell procedure is spawned. */voidinitvar(void){	const struct varinit *ip;	struct var *vp;	struct var **vpp;	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {		if (find_var(ip->text, &vpp, &vp->name_len) != NULL)			continue;		vp->next = *vpp;		*vpp = vp;		vp->text = strdup(ip->text);		vp->flags = ip->flags;		vp->func = ip->func;	}	/*	 * PS1 depends on uid	 */	if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {		vps1.next = *vpp;		*vpp = &vps1;		vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");		vps1.flags = VSTRFIXED|VTEXTFIXED;	}}/* * Safe version of setvar, returns 1 on success 0 on failure. */intsetvarsafe(const char *name, const char *val, int flags){	struct jmploc jmploc;	struct jmploc *volatile savehandler = handler;	int err = 0;#ifdef __GNUC__	(void) &err;#endif	if (setjmp(jmploc.loc))		err = 1;	else {		handler = &jmploc;		setvar(name, val, flags);	}	handler = savehandler;	return err;}/* * 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. */voidsetvar(const char *name, const char *val, int flags){	const char *p;	const char *q;	char *d;	int len;	int namelen;	char *nameeq;	int isbad;	isbad = 0;	p = name;	if (! is_name(*p))		isbad = 1;	p++;	for (;;) {		if (! is_in_name(*p)) {			if (*p == '\0' || *p == '=')				break;			isbad = 1;		}		p++;	}	namelen = p - name;	if (isbad)		error("%.*s: bad variable name", namelen, name);	len = namelen + 2;		/* 2 is space for '=' and '\0' */	if (val == NULL) {		flags |= VUNSET;	} else {		len += strlen(val);	}	d = nameeq = ckmalloc(len);	q = name;	while (--namelen >= 0)		*d++ = *q++;	*d++ = '=';	*d = '\0';	if (val)		scopy(val, d);	setvareq(nameeq, flags);}/* * 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. */voidsetvareq(char *s, int flags){	struct var *vp, **vpp;	int nlen;	if (aflag)		flags |= VEXPORT;	vp = find_var(s, &vpp, &nlen);	if (vp != NULL) {		if (vp->flags & VREADONLY)			error("%.*s: is read only", vp->name_len, s);		if (flags & VNOSET)			return;		INTOFF;		if (vp->func && (flags & VNOFUNC) == 0)			(*vp->func)(s + vp->name_len + 1);		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)			ckfree(vp->text);		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);		vp->flags |= flags & ~VNOFUNC;		vp->text = s;		INTON;		return;	}	/* not found */	if (flags & VNOSET)		return;	vp = ckmalloc(sizeof (*vp));	vp->flags = flags & ~VNOFUNC;	vp->text = s;	vp->name_len = nlen;	vp->next = *vpp;	vp->func = NULL;	*vpp = vp;}/* * Process a linked list of variable assignments. */voidlistsetvar(struct strlist *list, int flags){	struct strlist *lp;	INTOFF;	for (lp = list ; lp ; lp = lp->next) {		setvareq(savestr(lp->text), flags);	}	INTON;}voidlistmklocal(struct strlist *list, int flags){	struct strlist *lp;	for (lp = list ; lp ; lp = lp->next)		mklocal(lp->text, flags);}/* * Find the value of a variable.  Returns NULL if not set. */char *lookupvar(const char *name){	struct var *v;	v = find_var(name, NULL, NULL);	if (v == NULL || v->flags & VUNSET)		return NULL;	return v->text + v->name_len + 1;}/* * Search the environment of a builtin command.  If the second argument * is nonzero, return the value of a variable even if it hasn't been * exported. */char *bltinlookup(const char *name, int doall){	struct strlist *sp;	struct var *v;	for (sp = cmdenviron ; sp ; sp = sp->next) {		if (strequal(sp->text, name))			return strchr(sp->text, '=') + 1;	}	v = find_var(name, NULL, NULL);	if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT)))		return NULL;	return v->text + v->name_len + 1;}/* * Generate a list of exported variables.  This routine is used to construct * the third argument to execve when executing a program. */char **environment(void){	int nenv;	struct var **vpp;	struct var *vp;	char **env;	char **ep;	nenv = 0;	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {		for (vp = *vpp ; vp ; vp = vp->next)			if (vp->flags & VEXPORT)				nenv++;	}	ep = env = stalloc((nenv + 1) * sizeof *env);	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {		for (vp = *vpp ; vp ; vp = vp->next)			if (vp->flags & VEXPORT)				*ep++ = vp->text;	}	*ep = NULL;	return env;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?