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

📄 hush.c

📁 shell-HHARM9200.rar 华恒 AT91rm9200 中Busybox shell的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			str = make_string((child->argv + i));			parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);			free(str);			return last_return_code;		}		for (x = bltins; x->cmd; x++) {			if (strcmp(child->argv[i], x->cmd) == 0 ) {				int squirrel[] = {-1, -1, -1};				int rcode;				if (x->function == builtin_exec && child->argv[i+1]==NULL) {					debug_printf("magic exec\n");					setup_redirects(child,NULL);					return EXIT_SUCCESS;				}				debug_printf("builtin inline %s\n", child->argv[0]);				/* XXX setup_redirects acts on file descriptors, not FILEs.				 * This is perfect for work that comes after exec().				 * Is it really safe for inline use?  Experimentally,				 * things seem to work with glibc. */				setup_redirects(child, squirrel);				child->argv+=i;  /* XXX horrible hack */				rcode = x->function(child);				child->argv-=i;  /* XXX restore hack so free() can work right */				restore_redirects(squirrel);				return rcode;			}		}	}	for (i = 0; i < pi->num_progs; i++) {		child = & (pi->progs[i]);		/* pipes are inserted between pairs of commands */		if ((i + 1) < pi->num_progs) {			if (pipe(pipefds)<0) bb_perror_msg_and_die("pipe");			nextout = pipefds[1];		} else {			nextout=1;			pipefds[0] = -1;		}		/* XXX test for failed fork()? */#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)		if (!(child->pid = fork()))#else		if (!(child->pid = vfork()))#endif		{			/* Set the handling for job control signals back to the default.  */			signal(SIGINT, SIG_DFL);			signal(SIGQUIT, SIG_DFL);			signal(SIGTERM, SIG_DFL);			signal(SIGTSTP, SIG_DFL);			signal(SIGTTIN, SIG_DFL);			signal(SIGTTOU, SIG_DFL);			signal(SIGCHLD, SIG_DFL);			close_all();			if (nextin != 0) {				dup2(nextin, 0);				close(nextin);			}			if (nextout != 1) {				dup2(nextout, 1);				close(nextout);			}			if (pipefds[0]!=-1) {				close(pipefds[0]);  /* opposite end of our output pipe */			}			/* Like bash, explicit redirects override pipes,			 * and the pipe fd is available for dup'ing. */			setup_redirects(child,NULL);			if (interactive && pi->followup!=PIPE_BG) {				/* If we (the child) win the race, put ourselves in the process				 * group whose leader is the first process in this pipe. */				if (pi->pgrp < 0) {					pi->pgrp = getpid();				}				if (setpgid(0, pi->pgrp) == 0) {					tcsetpgrp(2, pi->pgrp);				}			}			pseudo_exec(child);		}		/* put our child in the process group whose leader is the		   first process in this pipe */		if (pi->pgrp < 0) {			pi->pgrp = child->pid;		}		/* Don't check for errors.  The child may be dead already,		 * in which case setpgid returns error code EACCES. */		setpgid(child->pid, pi->pgrp);		if (nextin != 0)			close(nextin);		if (nextout != 1)			close(nextout);		/* If there isn't another process, nextin is garbage		   but it doesn't matter */		nextin = pipefds[0];	}	return -1;}static int run_list_real(struct pipe *pi){	char *save_name = NULL;	char **list = NULL;	char **save_list = NULL;	struct pipe *rpipe;	int flag_rep = 0;	int save_num_progs;	int rcode=0, flag_skip=1;	int flag_restore = 0;	int if_code=0, next_if_code=0;  /* need double-buffer to handle elif */	reserved_style rmode, skip_more_in_this_rmode=RES_XXXX;	/* check syntax for "for" */	for (rpipe = pi; rpipe; rpipe = rpipe->next) {		if ((rpipe->r_mode == RES_IN ||		    rpipe->r_mode == RES_FOR) &&		    (rpipe->next == NULL)) {				syntax();				return 1;		}		if ((rpipe->r_mode == RES_IN &&			(rpipe->next->r_mode == RES_IN &&			rpipe->next->progs->argv != NULL))||			(rpipe->r_mode == RES_FOR &&			rpipe->next->r_mode != RES_IN)) {				syntax();				return 1;		}	}	for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) {		if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL ||			pi->r_mode == RES_FOR) {				flag_restore = 0;				if (!rpipe) {					flag_rep = 0;					rpipe = pi;				}		}		rmode = pi->r_mode;		debug_printf("rmode=%d  if_code=%d  next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode);		if (rmode == skip_more_in_this_rmode && flag_skip) {			if (pi->followup == PIPE_SEQ) flag_skip=0;			continue;		}		flag_skip = 1;		skip_more_in_this_rmode = RES_XXXX;		if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code;		if (rmode == RES_THEN &&  if_code) continue;		if (rmode == RES_ELSE && !if_code) continue;		if (rmode == RES_ELIF && !if_code) break;		if (rmode == RES_FOR && pi->num_progs) {			if (!list) {				/* if no variable values after "in" we skip "for" */				if (!pi->next->progs->argv) continue;				/* create list of variable values */				list = make_list_in(pi->next->progs->argv,					pi->progs->argv[0]);				save_list = list;				save_name = pi->progs->argv[0];				pi->progs->argv[0] = NULL;				flag_rep = 1;			}			if (!(*list)) {				free(pi->progs->argv[0]);				free(save_list);				list = NULL;				flag_rep = 0;				pi->progs->argv[0] = save_name;				pi->progs->glob_result.gl_pathv[0] =					pi->progs->argv[0];				continue;			} else {				/* insert new value from list for variable */				if (pi->progs->argv[0])					free(pi->progs->argv[0]);				pi->progs->argv[0] = *list++;				pi->progs->glob_result.gl_pathv[0] =					pi->progs->argv[0];			}		}		if (rmode == RES_IN) continue;		if (rmode == RES_DO) {			if (!flag_rep) continue;		}			if ((rmode == RES_DONE)) {			if (flag_rep) {				flag_restore = 1;			} else {				rpipe = NULL;			}		}		if (pi->num_progs == 0) continue;		save_num_progs = pi->num_progs; /* save number of programs */		rcode = run_pipe_real(pi);		debug_printf("run_pipe_real returned %d\n",rcode);		if (rcode!=-1) {			/* We only ran a builtin: rcode was set by the return value			 * of run_pipe_real(), and we don't need to wait for anything. */		} else if (pi->followup==PIPE_BG) {			/* XXX check bash's behavior with nontrivial pipes */			/* XXX compute jobid */			/* XXX what does bash do with attempts to background builtins? */			insert_bg_job(pi);			rcode = EXIT_SUCCESS;		} else {			if (interactive) {				/* move the new process group into the foreground */				if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)					bb_perror_msg("tcsetpgrp-3");				rcode = checkjobs(pi);				/* move the shell to the foreground */				if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)					bb_perror_msg("tcsetpgrp-4");			} else {				rcode = checkjobs(pi);			}			debug_printf("checkjobs returned %d\n",rcode);		}		last_return_code=rcode;		pi->num_progs = save_num_progs; /* restore number of programs */		if ( rmode == RES_IF || rmode == RES_ELIF )			next_if_code=rcode;  /* can be overwritten a number of times */		if (rmode == RES_WHILE)			flag_rep = !last_return_code;		if (rmode == RES_UNTIL)			flag_rep = last_return_code;		if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||		     (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )			skip_more_in_this_rmode=rmode;		checkjobs(NULL);	}	return rcode;}/* broken, of course, but OK for testing */static char *indenter(int i){	static char blanks[]="                                    ";	return &blanks[sizeof(blanks)-i-1];}/* return code is the exit status of the pipe */static int free_pipe(struct pipe *pi, int indent){	char **p;	struct child_prog *child;	struct redir_struct *r, *rnext;	int a, i, ret_code=0;	char *ind = indenter(indent);	if (pi->stopped_progs > 0)		return ret_code;	final_printf("%s run pipe: (pid %d)\n",ind,getpid());	for (i=0; i<pi->num_progs; i++) {		child = &pi->progs[i];		final_printf("%s  command %d:\n",ind,i);		if (child->argv) {			for (a=0,p=child->argv; *p; a++,p++) {				final_printf("%s   argv[%d] = %s\n",ind,a,*p);			}			globfree(&child->glob_result);			child->argv=NULL;		} else if (child->group) {			final_printf("%s   begin group (subshell:%d)\n",ind, child->subshell);			ret_code = free_pipe_list(child->group,indent+3);			final_printf("%s   end group\n",ind);		} else {			final_printf("%s   (nil)\n",ind);		}		for (r=child->redirects; r; r=rnext) {			final_printf("%s   redirect %d%s", ind, r->fd, redir_table[r->type].descrip);			if (r->dup == -1) {				/* guard against the case >$FOO, where foo is unset or blank */				if (r->word.gl_pathv) {					final_printf(" %s\n", *r->word.gl_pathv);					globfree(&r->word);				}			} else {				final_printf("&%d\n", r->dup);			}			rnext=r->next;			free(r);		}		child->redirects=NULL;	}	free(pi->progs);   /* children are an array, they get freed all at once */	pi->progs=NULL;	return ret_code;}static int free_pipe_list(struct pipe *head, int indent){	int rcode=0;   /* if list has no members */	struct pipe *pi, *next;	char *ind = indenter(indent);	for (pi=head; pi; pi=next) {		final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);		rcode = free_pipe(pi, indent);		final_printf("%s pipe followup code %d\n", ind, pi->followup);		next=pi->next;		pi->next=NULL;		free(pi);	}	return rcode;}/* Select which version we will use */static int run_list(struct pipe *pi){	int rcode=0;	if (fake_mode==0) {		rcode = run_list_real(pi);	}	/* free_pipe_list has the side effect of clearing memory	 * In the long run that function can be merged with run_list_real,	 * but doing that now would hobble the debugging effort. */	free_pipe_list(pi,0);	return rcode;}/* The API for glob is arguably broken.  This routine pushes a non-matching * string into the output structure, removing non-backslashed backslashes. * If someone can prove me wrong, by performing this function within the * original glob(3) api, feel free to rewrite this routine into oblivion. * Return code (0 vs. GLOB_NOSPACE) matches glob(3). * XXX broken if the last character is '\\', check that before calling. */static int globhack(const char *src, int flags, glob_t *pglob){	int cnt=0, pathc;	const char *s;	char *dest;	for (cnt=1, s=src; s && *s; s++) {		if (*s == '\\') s++;		cnt++;	}	dest = malloc(cnt);	if (!dest) return GLOB_NOSPACE;	if (!(flags & GLOB_APPEND)) {		pglob->gl_pathv=NULL;		pglob->gl_pathc=0;		pglob->gl_offs=0;		pglob->gl_offs=0;	}	pathc = ++pglob->gl_pathc;	pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv));	if (pglob->gl_pathv == NULL) return GLOB_NOSPACE;	pglob->gl_pathv[pathc-1]=dest;	pglob->gl_pathv[pathc]=NULL;	for (s=src; s && *s; s++, dest++) {		if (*s == '\\') s++;		*dest = *s;	}	*dest='\0';	return 0;}/* XXX broken if the last character is '\\', check that before calling */static int glob_needed(const char *s){	for (; *s; s++) {		if (*s == '\\') s++;		if (strchr("*[?",*s)) return 1;	}	return 0;}#if 0static void globprint(glob_t *pglob){	int i;	debug_printf("glob_t at %p:\n", pglob);	debug_printf("  gl_pathc=%d  gl_pathv=%p  gl_offs=%d  gl_flags=%d\n",		pglob->gl_pathc, pglob->gl_pathv, pglob->gl_offs, pglob->gl_flags);	for (i=0; i<pglob->gl_pathc; i++)		debug_printf("pglob->gl_pathv[%d] = %p = %s\n", i,			pglob->gl_pathv[i], pglob->gl_pathv[i]);}#endifstatic int xglob(o_string *dest, int flags, glob_t *pglob){	int gr; 	/* short-circuit for null word */	/* we can code this better when the debug_printf's are gone */ 	if (dest->length == 0) { 		if (dest->nonnull) { 			/* bash man page calls this an "explicit" null */ 			gr = globhack(dest->data, flags, pglob); 			debug_printf("globhack returned %d\n",gr); 		} else {			return 0;		} 	} else if (glob_needed(dest->data)) {		gr = glob(dest->data, flags, NULL, pglob);		debug_printf("glob returned %d\n",gr);		if (gr == GLOB_NOMATCH) {			/* quote removal, or more accurately, backslash removal */			gr = globhack(dest->data, flags, pglob);			debug_printf("globhack returned %d\n",gr);		}	} else {		gr = globhack(dest->data, flags, pglob);		debug_printf("globhack returned %d\n",gr);	}	if (gr == GLOB_NOSPACE)		bb_error_msg_and_die("out of memory during glob");	if (gr != 0) { /* GLOB_ABORTED ? */		bb_error_msg("glob(3) error %d",gr);	}	/* globprint(glob_target); */	return gr;}/* This is used to get/check local shell variables */static char *get_local_var(const char *s){	struct variables *cur;	if (!s)		return NULL;	for (cur = top_vars; cur; cur=cur->next)		if(strcmp(cur->name, s)==0)			return cur->value;	return NULL;}/* This is used to set local shell variables   flg_export==0 if only local (not exporting) variable   flg_export==1 if "new" exporting environ   flg_export>1  if current startup environ (not call putenv()) */static int set_local_var(const char *s, int flg_export){	char *name, *value;	int result=0;	struct variables *cur;	name=strdup(s);	/* Assume when we enter this function that we are already in	 * NAME=VALUE format.  So the first order of business is to	 * split 's' on the '=' into 'name' and 'value' */	value = strchr(name, '=');	if (value==0 && ++value==0) {		free(name);		return -1;	}	*value++ = 0;	for(cur = top_vars; cur; cur = cur->next) {		if(strcmp(cur->name, name)==0)			break;	}

⌨️ 快捷键说明

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