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

📄 hush.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
📖 第 1 页 / 共 5 页
字号:
			pi->progs[prognum].pid = 0;			if (!pi->running_progs) {				printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text);				remove_bg_job(pi);			}		} else {			/* child stopped */			pi->stopped_progs++;			pi->progs[prognum].is_stopped = 1;#if 0			/* Printing this stuff is a pain, since it tends to			 * overwrite the prompt an inconveinient moments.  So			 * don't do that.  */			if (pi->stopped_progs == pi->num_progs) {				printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);			}#endif		}	}	if (childpid == -1 && errno != ECHILD)		perror_msg("waitpid");	/* move the shell to the foreground */	/*if (interactive && tcsetpgrp(shell_terminal, getpgid(0))) */	/*	perror_msg("tcsetpgrp-2"); */	return -1;}/* Figure out our controlling tty, checking in order stderr, * stdin, and stdout.  If check_pgrp is set, also check that * we belong to the foreground process group associated with * that tty.  The value of shell_terminal is needed in order to call * tcsetpgrp(shell_terminal, ...); */void controlling_tty(int check_pgrp){	pid_t curpgrp;	if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0			&& (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0			&& (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)		goto shell_terminal_error;	if (check_pgrp && curpgrp != getpgid(0))		goto shell_terminal_error;	return;shell_terminal_error:		shell_terminal = -1;		return;}#endif/* run_pipe_real() starts all the jobs, but doesn't wait for anything * to finish.  See checkjobs(). * * return code is normally -1, when the caller has to wait for children * to finish to determine the exit status of the pipe.  If the pipe * is a simple builtin command, however, the action is done by the * time run_pipe_real returns, and the exit code is provided as the * return value. * * The input of the pipe is always stdin, the output is always * stdout.  The outpipe[] mechanism in BusyBox-0.48 lash is bogus, * because it tries to avoid running the command substitution in * subshell, when that is in fact necessary.  The subshell process * now has its stdout directed to the input of the appropriate pipe, * so this routine is noticeably simpler. */static int run_pipe_real(struct pipe *pi){	int i;#ifndef __U_BOOT__	int nextin, nextout;	int pipefds[2];				/* pipefds[0] is for reading */	struct child_prog *child;	struct built_in_command *x;	char *p;# if __GNUC__	/* Avoid longjmp clobbering */	(void) &i;	(void) &nextin;	(void) &nextout;	(void) &child;# endif#else	int nextin;	int flag = do_repeat ? CMD_FLAG_REPEAT : 0;	struct child_prog *child;	cmd_tbl_t *cmdtp;	char *p;# if __GNUC__	/* Avoid longjmp clobbering */	(void) &i;	(void) &nextin;	(void) &child;# endif#endif	/* __U_BOOT__ */	nextin = 0;#ifndef __U_BOOT__	pi->pgrp = -1;#endif	/* Check if this is a simple builtin (not part of a pipe).	 * Builtins within pipes have to fork anyway, and are handled in	 * pseudo_exec.  "echo foo | read bar" doesn't work on bash, either.	 */	if (pi->num_progs == 1) child = & (pi->progs[0]);#ifndef __U_BOOT__	if (pi->num_progs == 1 && child->group && child->subshell == 0) {		int squirrel[] = {-1, -1, -1};		int rcode;		debug_printf("non-subshell grouping\n");		setup_redirects(child, squirrel);		/* XXX could we merge code with following builtin case,		 * by creating a pseudo builtin that calls run_list_real? */		rcode = run_list_real(child->group);		restore_redirects(squirrel);#else		if (pi->num_progs == 1 && child->group) {		int rcode;		debug_printf("non-subshell grouping\n");		rcode = run_list_real(child->group);#endif		return rcode;	} else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {		for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ }		if (i!=0 && child->argv[i]==NULL) {			/* assignments, but no command: set the local environment */			for (i=0; child->argv[i]!=NULL; i++) {				/* Ok, this case is tricky.  We have to decide if this is a				 * local variable, or an already exported variable.  If it is				 * already exported, we have to export the new value.  If it is				 * not exported, we need only set this as a local variable.				 * This junk is all to decide whether or not to export this				 * variable. */				int export_me=0;				char *name, *value;				name = xstrdup(child->argv[i]);				debug_printf("Local environment set: %s\n", name);				value = strchr(name, '=');				if (value)					*value=0;#ifndef __U_BOOT__				if ( get_local_var(name)) {					export_me=1;				}#endif				free(name);				p = insert_var_value(child->argv[i]);				set_local_var(p, export_me);				if (p != child->argv[i]) free(p);			}			return EXIT_SUCCESS;   /* don't worry about errors in set_local_var() yet */		}		for (i = 0; is_assignment(child->argv[i]); i++) {			p = insert_var_value(child->argv[i]);#ifndef __U_BOOT__			putenv(strdup(p));#else			set_local_var(p, 0);#endif			if (p != child->argv[i]) {				child->sp--;				free(p);			}		}		if (child->sp) {			char * str = NULL;			str = make_string((child->argv + i));			parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);			free(str);			return last_return_code;		}#ifndef __U_BOOT__		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);#else			/* check ";", because ,example , argv consist from			 * "help;flinfo" must not execute			 */			if (strchr(child->argv[i], ';')) {				printf ("Unknown command '%s' - try 'help' or use 'run' command\n",					child->argv[i]);				return -1;			}			/* Look up command in command table */			if ((cmdtp = find_cmd(child->argv[i])) == NULL) {				printf ("Unknown command '%s' - try 'help'\n", child->argv[i]);				return -1;	/* give up after bad command */			} else {				int rcode;#if defined(CONFIG_CMD_BOOTD)	    extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);				/* avoid "bootd" recursion */				if (cmdtp->cmd == do_bootd) {					if (flag & CMD_FLAG_BOOTD) {						printf ("'bootd' recursion detected\n");						return -1;					}				else					flag |= CMD_FLAG_BOOTD;				}#endif				/* found - check max args */				if ((child->argc - i) > cmdtp->maxargs) {					printf ("Usage:\n%s\n", cmdtp->usage);					return -1;				}#endif				child->argv+=i;  /* XXX horrible hack */#ifndef __U_BOOT__				rcode = x->function(child);#else				/* OK - call function to do the command */				rcode = (cmdtp->cmd)(cmdtp, flag,child->argc-i,&child->argv[i]);				if ( !cmdtp->repeatable )					flag_repeat = 0;#endif				child->argv-=i;  /* XXX restore hack so free() can work right */#ifndef __U_BOOT__				restore_redirects(squirrel);#endif				return rcode;			}		}#ifndef __U_BOOT__	}	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 (!(child->pid = fork())) {			/* 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];	}#endif	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;#ifndef __U_BOOT__	int save_num_progs;#endif	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();#ifdef __U_BOOT__				flag_repeat = 0;#endif				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();#ifdef __U_BOOT__				flag_repeat = 0;#endif				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) {#ifdef __U_BOOT__				/* check Ctrl-C */				ctrlc();				if ((had_ctrlc())) {					return 1;				}#endif				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;#ifndef __U_BOOT__				pi->progs->glob_result.gl_pathv[0] =					pi->progs->argv[0];#endif				continue;			} else {				/* insert new value from list for variable */				if (pi->progs->argv[0])					free(pi->progs->argv[0]);				pi->progs->argv[0] = *list++;#ifndef __U_BOOT__				pi->progs->glob_result.gl_pathv[0] =					pi->progs->argv[0];#endif			}		}		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;#ifndef __U_BOOT__		save_num_progs = pi->num_progs; /* save number of programs */#endif		rcode = run_pipe_real(pi);		debug_printf("run_pipe_real returned %d\n",rcode);#ifndef __U_BOOT__		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;#else		if (rcode < -1) {			last_return_code = -rcode - 2;			return -2;	/* exit */		}		last_return_code=(rcode == 0) ? 0 : 1;#endif#ifndef __U_BOOT__		pi->num_progs = save_num_progs; /* restore number of programs */#endif		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;

⌨️ 快捷键说明

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