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

📄 hush.c

📁 为samsung2410 ARM移植的busybox工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
			}		}	}	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) perror_msg_and_die("pipe");			nextout = pipefds[1];		} else {			nextout=1;			pipefds[0] = -1;		}		/* XXX test for failed fork()? */#if !defined(__UCLIBC__) || defined(__UCLIBC_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){	int rcode=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;	for (;pi;pi=pi->next) {		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) continue;		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) continue;		if (pi->num_progs == 0) continue;		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)					perror_msg("tcsetpgrp-3");				rcode = checkjobs(pi);				/* move the shell to the foreground */				if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)					perror_msg("tcsetpgrp-4");			} else {				rcode = checkjobs(pi);			}			debug_printf("checkjobs returned %d\n",rcode);		}		last_return_code=rcode;		if ( rmode == RES_IF || rmode == RES_ELIF )			next_if_code=rcode;  /* can be overwritten a number of times */		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)		error_msg_and_die("out of memory during glob");	if (gr != 0) { /* GLOB_ABORTED ? */		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;	}	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) {				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) {				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;

⌨️ 快捷键说明

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