⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hush.c

📁 shell-HHARM9200.rar 华恒 AT91rm9200 中Busybox shell的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if(cur) {		if(strcmp(cur->value, value)==0) {			if(flg_export>0 && cur->flg_export==0)				cur->flg_export=flg_export;			else				result++;		} else {			if(cur->flg_read_only) {				bb_error_msg("%s: readonly variable", name);				result = -1;			} else {				if(flg_export>0 || cur->flg_export>1)					cur->flg_export=1;				free(cur->value);				cur->value = strdup(value);			}		}	} else {		cur = malloc(sizeof(struct variables));		if(!cur) {			result = -1;		} else {			cur->name = strdup(name);			if(cur->name == 0) {				free(cur);				result = -1;			} else {				struct variables *bottom = top_vars;				cur->value = strdup(value);				cur->next = 0;				cur->flg_export = flg_export;				cur->flg_read_only = 0;				while(bottom->next) bottom=bottom->next;				bottom->next = cur;			}		}	}	if(result==0 && cur->flg_export==1) {		*(value-1) = '=';		result = putenv(name);	} else {		free(name);		if(result>0)            /* equivalent to previous set */			result = 0;	}	return result;}static void unset_local_var(const char *name){	struct variables *cur;	if (name) {		for (cur = top_vars; cur; cur=cur->next) {			if(strcmp(cur->name, name)==0)				break;		}		if(cur!=0) {			struct variables *next = top_vars;			if(cur->flg_read_only) {				bb_error_msg("%s: readonly variable", name);				return;			} else {				if(cur->flg_export)					unsetenv(cur->name);				free(cur->name);				free(cur->value);				while (next->next != cur)					next = next->next;				next->next = cur->next;			}			free(cur);		}	}}static int is_assignment(const char *s){	if (s==NULL || !isalpha(*s)) return 0;	++s;	while(isalnum(*s) || *s=='_') ++s;	return *s=='=';}/* the src parameter allows us to peek forward to a possible &n syntax * for file descriptor duplication, e.g., "2>&1". * Return code is 0 normally, 1 if a syntax error is detected in src. * Resource errors (in xmalloc) cause the process to exit */static int setup_redirect(struct p_context *ctx, int fd, redir_type style,	struct in_str *input){	struct child_prog *child=ctx->child;	struct redir_struct *redir = child->redirects;	struct redir_struct *last_redir=NULL;	/* Create a new redir_struct and drop it onto the end of the linked list */	while(redir) {		last_redir=redir;		redir=redir->next;	}	redir = xmalloc(sizeof(struct redir_struct));	redir->next=NULL;	redir->word.gl_pathv=NULL;	if (last_redir) {		last_redir->next=redir;	} else {		child->redirects=redir;	}	redir->type=style;	redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ;	debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip);	/* Check for a '2>&1' type redirect */	redir->dup = redirect_dup_num(input);	if (redir->dup == -2) return 1;  /* syntax error */	if (redir->dup != -1) {		/* Erik had a check here that the file descriptor in question		 * is legit; I postpone that to "run time"		 * A "-" representation of "close me" shows up as a -3 here */		debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup);	} else {		/* We do _not_ try to open the file that src points to,		 * since we need to return and let src be expanded first.		 * Set ctx->pending_redirect, so we know what to do at the		 * end of the next parsed word.		 */		ctx->pending_redirect = redir;	}	return 0;}struct pipe *new_pipe(void) {	struct pipe *pi;	pi = xmalloc(sizeof(struct pipe));	pi->num_progs = 0;	pi->progs = NULL;	pi->next = NULL;	pi->followup = 0;  /* invalid */	return pi;}static void initialize_context(struct p_context *ctx){	ctx->pipe=NULL;	ctx->pending_redirect=NULL;	ctx->child=NULL;	ctx->list_head=new_pipe();	ctx->pipe=ctx->list_head;	ctx->w=RES_NONE;	ctx->stack=NULL;	ctx->old_flag=0;	done_command(ctx);   /* creates the memory for working child */}/* normal return is 0 * if a reserved word is found, and processed, return 1 * should handle if, then, elif, else, fi, for, while, until, do, done. * case, function, and select are obnoxious, save those for later. */int reserved_word(o_string *dest, struct p_context *ctx){	struct reserved_combo {		char *literal;		int code;		long flag;	};	/* Mostly a list of accepted follow-up reserved words.	 * FLAG_END means we are done with the sequence, and are ready	 * to turn the compound list into a command.	 * FLAG_START means the word must start a new compound list.	 */	static struct reserved_combo reserved_list[] = {		{ "if",    RES_IF,    FLAG_THEN | FLAG_START },		{ "then",  RES_THEN,  FLAG_ELIF | FLAG_ELSE | FLAG_FI },		{ "elif",  RES_ELIF,  FLAG_THEN },		{ "else",  RES_ELSE,  FLAG_FI   },		{ "fi",    RES_FI,    FLAG_END  },		{ "for",   RES_FOR,   FLAG_IN   | FLAG_START },		{ "while", RES_WHILE, FLAG_DO   | FLAG_START },		{ "until", RES_UNTIL, FLAG_DO   | FLAG_START },		{ "in",    RES_IN,    FLAG_DO   },		{ "do",    RES_DO,    FLAG_DONE },		{ "done",  RES_DONE,  FLAG_END  }	};	struct reserved_combo *r;	for (r=reserved_list;#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo)		r<reserved_list+NRES; r++) {		if (strcmp(dest->data, r->literal) == 0) {			debug_printf("found reserved word %s, code %d\n",r->literal,r->code);			if (r->flag & FLAG_START) {				struct p_context *new = xmalloc(sizeof(struct p_context));				debug_printf("push stack\n");				if (ctx->w == RES_IN || ctx->w == RES_FOR) {					syntax();					free(new);					ctx->w = RES_SNTX;					b_reset(dest);					return 1;				}				*new = *ctx;   /* physical copy */				initialize_context(ctx);				ctx->stack=new;			} else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {				syntax();				ctx->w = RES_SNTX;				b_reset(dest);				return 1;			}			ctx->w=r->code;			ctx->old_flag = r->flag;			if (ctx->old_flag & FLAG_END) {				struct p_context *old;				debug_printf("pop stack\n");				done_pipe(ctx,PIPE_SEQ);				old = ctx->stack;				old->child->group = ctx->list_head;				old->child->subshell = 0;				*ctx = *old;   /* physical copy */				free(old);			}			b_reset (dest);			return 1;		}	}	return 0;}/* normal return is 0. * Syntax or xglob errors return 1. */static int done_word(o_string *dest, struct p_context *ctx){	struct child_prog *child=ctx->child;	glob_t *glob_target;	int gr, flags = 0;	debug_printf("done_word: %s %p\n", dest->data, child);	if (dest->length == 0 && !dest->nonnull) {		debug_printf("  true null, ignored\n");		return 0;	}	if (ctx->pending_redirect) {		glob_target = &ctx->pending_redirect->word;	} else {		if (child->group) {			syntax();			return 1;  /* syntax error, groups and arglists don't mix */		}		if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {			debug_printf("checking %s for reserved-ness\n",dest->data);			if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX;		}		glob_target = &child->glob_result; 		if (child->argv) flags |= GLOB_APPEND;	}	gr = xglob(dest, flags, glob_target);	if (gr != 0) return 1;	b_reset(dest);	if (ctx->pending_redirect) {		ctx->pending_redirect=NULL;		if (glob_target->gl_pathc != 1) {			bb_error_msg("ambiguous redirect");			return 1;		}	} else {		child->argv = glob_target->gl_pathv;	}	if (ctx->w == RES_FOR) {		done_word(dest,ctx);		done_pipe(ctx,PIPE_SEQ);	}	return 0;}/* The only possible error here is out of memory, in which case * xmalloc exits. */static int done_command(struct p_context *ctx){	/* The child is really already in the pipe structure, so	 * advance the pipe counter and make a new, null child.	 * Only real trickiness here is that the uncommitted	 * child structure, to which ctx->child points, is not	 * counted in pi->num_progs. */	struct pipe *pi=ctx->pipe;	struct child_prog *prog=ctx->child;	if (prog && prog->group == NULL	         && prog->argv == NULL	         && prog->redirects == NULL) {		debug_printf("done_command: skipping null command\n");		return 0;	} else if (prog) {		pi->num_progs++;		debug_printf("done_command: num_progs incremented to %d\n",pi->num_progs);	} else {		debug_printf("done_command: initializing\n");	}	pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));	prog = pi->progs + pi->num_progs;	prog->redirects = NULL;	prog->argv = NULL;	prog->is_stopped = 0;	prog->group = NULL;	prog->glob_result.gl_pathv = NULL;	prog->family = pi;	prog->sp = 0;	ctx->child = prog;	prog->type = ctx->type;	/* but ctx->pipe and ctx->list_head remain unchanged */	return 0;}static int done_pipe(struct p_context *ctx, pipe_style type){	struct pipe *new_p;	done_command(ctx);  /* implicit closure of previous command */	debug_printf("done_pipe, type %d\n", type);	ctx->pipe->followup = type;	ctx->pipe->r_mode = ctx->w;	new_p=new_pipe();	ctx->pipe->next = new_p;	ctx->pipe = new_p;	ctx->child = NULL;	done_command(ctx);  /* set up new pipe to accept commands */	return 0;}/* peek ahead in the in_str to find out if we have a "&n" construct, * as in "2>&1", that represents duplicating a file descriptor. * returns either -2 (syntax error), -1 (no &), or the number found. */static int redirect_dup_num(struct in_str *input){	int ch, d=0, ok=0;	ch = b_peek(input);	if (ch != '&') return -1;	b_getch(input);  /* get the & */	ch=b_peek(input);	if (ch == '-') {		b_getch(input);		return -3;  /* "-" represents "close me" */	}	while (isdigit(ch)) {		d = d*10+(ch-'0');		ok=1;		b_getch(input);		ch = b_peek(input);	}	if (ok) return d;	bb_error_msg("ambiguous redirect");	return -2;}/* If a redirect is immediately preceded by a number, that number is * supposed to tell which file descriptor to redirect.  This routine * looks for such preceding numbers.  In an ideal world this routine * needs to handle all the following classes of redirects... *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo * A -1 output from this program means no valid number was found, so the * caller should use the appropriate default for this redirection. */static int redirect_opt_num(o_string *o){	int num;	if (o->length==0) return -1;	for(num=0; num<o->length; num++) {		if (!isdigit(*(o->data+num))) {			return -1;		}	}	/* reuse num (and save an int) */	num=atoi(o->data);	b_reset(o);	return num;}FILE *generate_stream_from_list(struct pipe *head){	FILE *pf;#if 1	int pid, channel[2];	if (pipe(channel)<0) bb_perror_msg_and_die("pipe");#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)	pid=fork();#else	pid=vfork();#endif	if (pid<0) {		bb_perror_msg_and_die("fork");	} else if (pid==0) {		close(channel[0]);		if (channel[1] != 1) {			dup2(channel[1],1);			close(channel[1]);		}#if 0#define SURROGATE "surrogate response"		write(1,SURROGATE,sizeof(SURROGATE));		_exit(run_list(head));#else		_exit(run_list_real(head));   /* leaks memory */#endif	}	debug_printf("forked child %d\n",pid);	close(channel[1]);	pf = fdopen(channel[0],"r");	debug_printf("pipe on FILE *%p\n",pf);#else	free_pipe_list(head,0);	pf=popen("echo surrogate response","r");	debug_printf("started fake pipe on FILE *%p\n",pf);#endif	return pf;}/* this version hacked for testing purposes *//* return code is exit status of the process that is run. */static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end){	int retcode;	o_string result=NULL_O_STRING;	struct p_context inner;	FILE *p;	struct in_str pipe_str;	initialize_context(&inner);	/* recursion to generate command */	retcode = parse_stream(&result, &inner, input, subst_end);	if (retcode != 0) return retcode;  /* syntax error or EOF */	done_word(&result, &inner);	done_pipe(&inner, PIPE_SEQ);	b_free(&result);	p=generate_stream_from_list(inner.list_head);	if (p==NULL) return 1;	mark_open(fileno(p));	setup_file_in_str(&pipe_str, p);	/* now send results of command back into original context */	retcode = parse_stream(dest, ctx, &pipe_str, '\0');	/* XXX In case of a syntax error, should we try to kill the child?	 * That would be tough to do right, so just read until EOF. */	if (retcode == 1) {		while (b_getch(&pipe_str)!=EOF) { /* discard */ };	}	debug_printf("done reading from pipe, pclose()ing\n");	/* This is the step that wait()s for the child.  Should be pretty	 * safe, since we just read an EOF from its stdout.  We could try	 * to better, by us

⌨️ 快捷键说明

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