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

📄 lash.c

📁 shell-HHARM9200.rar 华恒 AT91rm9200 中Busybox shell的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
					return 1;				}				prog->redirects[i].filename = buf;				while (*chptr && !isspace(*chptr))					*buf++ = *chptr++;				src = chptr - 1;	/* we src++ later */				prog->argv[argc_l] = ++buf;				break;			case '|':			/* pipe */				/* finish this command */				if (*prog->argv[argc_l] || saw_quote)					argc_l++;				if (!argc_l) {					bb_error_msg("empty command in pipe");					free_job(job);					job->num_progs=0;					return 1;				}				prog->argv[argc_l] = NULL;				/* and start the next */				job->num_progs++;				job->progs = xrealloc(job->progs,									  sizeof(*job->progs) * job->num_progs);				prog = job->progs + (job->num_progs - 1);				prog->num_redirects = 0;				prog->redirects = NULL;				prog->is_stopped = 0;				prog->family = job;				argc_l = 0;				argv_alloced = 5;				prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);				prog->argv[0] = ++buf;				src++;				while (*src && isspace(*src))					src++;				if (!*src) {					bb_error_msg("empty command in pipe");					free_job(job);					job->num_progs=0;					return 1;				}				src--;			/* we'll ++ it at the end of the loop */				break;#endif#ifdef CONFIG_LASH_JOB_CONTROL			case '&':			/* background */				*inbg = 1;#endif			case ';':			/* multiple commands */				done = 1;				return_command = *command_ptr + (src - *command_ptr) + 1;				break;			case '\\':				src++;				if (!*src) {					bb_error_msg("character expected after \\");					free_job(job);					return 1;				}				if (*src == '*' || *src == '[' || *src == ']'					|| *src == '?') *buf++ = '\\';				/* fallthrough */			default:				*buf++ = *src;			}		src++;	}	if (*prog->argv[argc_l] || saw_quote) {		argc_l++;	}	if (!argc_l) {		free_job(job);		return 0;	}	prog->argv[argc_l] = NULL;	if (!return_command) {		job->text = xmalloc(strlen(*command_ptr) + 1);		strcpy(job->text, *command_ptr);	} else {		/* This leaves any trailing spaces, which is a bit sloppy */		count = return_command - *command_ptr;		job->text = xmalloc(count + 1);		strncpy(job->text, *command_ptr, count);		job->text[count] = '\0';	}	*command_ptr = return_command;	return 0;}/* Run the child_prog, no matter what kind of command it uses. */static int pseudo_exec(struct child_prog *child){	struct built_in_command *x;#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL	char *name;#endif	/* Check if the command matches any of the non-forking builtins.	 * Depending on context, this might be redundant.  But it's	 * easier to waste a few CPU cycles than it is to figure out	 * if this is one of those cases.	 */	for (x = bltins; x->cmd; x++) {		if (strcmp(child->argv[0], x->cmd) == 0 ) {			_exit(x->function(child));		}	}	/* Check if the command matches any of the forking builtins. */	for (x = bltins_forking; x->cmd; x++) {		if (strcmp(child->argv[0], x->cmd) == 0) {			bb_applet_name=x->cmd;			_exit (x->function(child));		}	}#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL	/* Check if the command matches any busybox internal	 * commands ("applets") here.  Following discussions from	 * November 2000 on busybox@busybox.net, don't use	 * bb_get_last_path_component().  This way explicit (with	 * slashes) filenames will never be interpreted as an	 * applet, just like with builtins.  This way the user can	 * override an applet with an explicit filename reference.	 * The only downside to this change is that an explicit	 * /bin/foo invocation will fork and exec /bin/foo, even if	 * /bin/foo is a symlink to busybox.	 */	name = child->argv[0];	{	    char** argv_l=child->argv;	    int argc_l;	    for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++);	    optind = 1;	    run_applet_by_name(name, argc_l, child->argv);	}#endif	execvp(child->argv[0], child->argv);	/* Do not use bb_perror_msg_and_die() here, since we must not	 * call exit() but should call _exit() instead */	fprintf(stderr, "%s: %m\n", child->argv[0]);	_exit(EXIT_FAILURE);}static void insert_job(struct job *newjob, int inbg){	struct job *thejob;	struct jobset *j_list=newjob->job_list;	/* find the ID for thejob to use */	newjob->jobid = 1;	for (thejob = j_list->head; thejob; thejob = thejob->next)		if (thejob->jobid >= newjob->jobid)			newjob->jobid = thejob->jobid + 1;	/* add thejob to the list of running jobs */	if (!j_list->head) {		thejob = j_list->head = xmalloc(sizeof(*thejob));	} else {		for (thejob = j_list->head; thejob->next; thejob = thejob->next) /* nothing */;		thejob->next = xmalloc(sizeof(*thejob));		thejob = thejob->next;	}	*thejob = *newjob;   /* physically copy the struct job */	thejob->next = NULL;	thejob->running_progs = thejob->num_progs;	thejob->stopped_progs = 0;#ifdef CONFIG_LASH_JOB_CONTROL	if (inbg) {		/* we don't wait for background thejobs to return -- append it		   to the list of backgrounded thejobs and leave it alone */		printf("[%d] %d\n", thejob->jobid,			   newjob->progs[newjob->num_progs - 1].pid);		last_jobid = newjob->jobid;		last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;	} else {		newjob->job_list->fg = thejob;		/* move the new process group into the foreground */		/* suppress messages when run from /linuxrc mag@sysgo.de */		if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY)			bb_perror_msg("tcsetpgrp");	}#endif}static int run_command(struct job *newjob, int inbg, int outpipe[2]){	/* struct job *thejob; */	int i;	int nextin, nextout;	int pipefds[2];				/* pipefd[0] is for reading */	struct built_in_command *x;	struct child_prog *child;	nextin = 0, nextout = 1;	for (i = 0; i < newjob->num_progs; i++) {		child = & (newjob->progs[i]);		if ((i + 1) < newjob->num_progs) {			if (pipe(pipefds)<0) bb_perror_msg_and_die("pipe");			nextout = pipefds[1];		} else {			if (outpipe[1]!=-1) {				nextout = outpipe[1];			} else {				nextout = 1;			}		}		/* Check if the command matches any non-forking builtins,		 * but only if this is a simple command.		 * Non-forking builtins within pipes have to fork anyway,		 * and are handled in pseudo_exec.  "echo foo | read bar"		 * is doomed to failure, and doesn't work on bash, either.		 */		if (newjob->num_progs == 1) {			for (x = bltins; x->cmd; x++) {				if (strcmp(child->argv[0], x->cmd) == 0 ) {					int rcode;					int squirrel[] = {-1, -1, -1};					setup_redirects(child, squirrel);					rcode = x->function(child);					restore_redirects(squirrel);					return rcode;				}			}		}#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(SIGTSTP, SIG_DFL);			signal(SIGTTIN, SIG_DFL);			signal(SIGTTOU, SIG_DFL);			signal(SIGCHLD, SIG_DFL);			close_all();			if (outpipe[1]!=-1) {				close(outpipe[0]);			}			if (nextin != 0) {				dup2(nextin, 0);				close(nextin);			}			if (nextout != 1) {				dup2(nextout, 1);				dup2(nextout, 2);  /* Really? */				close(nextout);				close(pipefds[0]);			}			/* explicit redirects override pipes */			setup_redirects(child,NULL);			pseudo_exec(child);		}		if (outpipe[1]!=-1) {			close(outpipe[1]);		}		/* put our child in the process group whose leader is the		   first process in this pipe */		setpgid(child->pid, newjob->progs[0].pid);		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];	}	newjob->pgrp = newjob->progs[0].pid;	insert_job(newjob, inbg);	return 0;}static int busy_loop(FILE * input){	char *command;	char *next_command = NULL;	struct job newjob;	int i;	int inbg;	int status;#ifdef CONFIG_LASH_JOB_CONTROL	pid_t  parent_pgrp;	/* save current owner of TTY so we can restore it on exit */	parent_pgrp = tcgetpgrp(shell_terminal);#endif	newjob.job_list = &job_list;	newjob.job_context = DEFAULT_CONTEXT;	command = (char *) xcalloc(BUFSIZ, sizeof(char));	while (1) {		if (!job_list.fg) {			/* no job is in the foreground */			/* see if any background processes have exited */			checkjobs(&job_list);			if (!next_command) {				if (get_command(input, command))					break;				next_command = command;			}			if (! expand_arguments(next_command)) {				free(command);				command = (char *) xcalloc(BUFSIZ, sizeof(char));				next_command = NULL;				continue;			}			if (!parse_command(&next_command, &newjob, &inbg) &&				newjob.num_progs) {				int pipefds[2] = {-1,-1};				debug_printf( "job=%p fed to run_command by busy_loop()'\n",						&newjob);				run_command(&newjob, inbg, pipefds);			}			else {				free(command);				command = (char *) xcalloc(BUFSIZ, sizeof(char));				next_command = NULL;			}		} else {			/* a job is running in the foreground; wait for it */			i = 0;			while (!job_list.fg->progs[i].pid ||				   job_list.fg->progs[i].is_stopped == 1) i++;			if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0) {				if (errno != ECHILD) {					bb_perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid);				}			}			if (WIFEXITED(status) || WIFSIGNALED(status)) {				/* the child exited */				job_list.fg->running_progs--;				job_list.fg->progs[i].pid = 0;				last_return_code=WEXITSTATUS(status);				if (!job_list.fg->running_progs) {					/* child exited */					remove_job(&job_list, job_list.fg);					job_list.fg = NULL;				}			}#ifdef CONFIG_LASH_JOB_CONTROL			else {				/* the child was stopped */				job_list.fg->stopped_progs++;				job_list.fg->progs[i].is_stopped = 1;				if (job_list.fg->stopped_progs == job_list.fg->running_progs) {					printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,						   "Stopped", job_list.fg->text);					job_list.fg = NULL;				}			}			if (!job_list.fg) {				/* move the shell to the foreground */				/* suppress messages when run from /linuxrc mag@sysgo.de */				if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)					bb_perror_msg("tcsetpgrp");			}#endif		}	}	free(command);#ifdef CONFIG_LASH_JOB_CONTROL	/* return controlling TTY back to parent process group before exiting */	if (tcsetpgrp(shell_terminal, parent_pgrp) && errno != ENOTTY)		bb_perror_msg("tcsetpgrp");#endif	/* return exit status if called with "-c" */	if (input == NULL && WIFEXITED(status))		return WEXITSTATUS(status);	return 0;}#ifdef CONFIG_FEATURE_CLEAN_UPvoid free_memory(void){	if (cwd && cwd!=bb_msg_unknown) {		free((char*)cwd);	}	if (local_pending_command)		free(local_pending_command);	if (job_list.fg && !job_list.fg->running_progs) {		remove_job(&job_list, job_list.fg);	}}#endif#ifdef CONFIG_LASH_JOB_CONTROL/* Make sure we have a controlling tty.  If we get started under a job * aware app (like bash for example), make sure we are now in charge so * we don't fight over who gets the foreground */static void setup_job_control(void){	int status;	pid_t shell_pgrp;	/* Loop until we are in the foreground.  */	while ((status = tcgetpgrp (shell_terminal)) >= 0) {		if (status == (shell_pgrp = getpgrp ())) {			break;		}		kill (- shell_pgrp, SIGTTIN);	}	/* Ignore interactive and job-control signals.  */	signal(SIGINT, SIG_IGN);	signal(SIGQUIT, SIG_IGN);	signal(SIGTSTP, SIG_IGN);	signal(SIGTTIN, SIG_IGN);	signal(SIGTTOU, SIG_IGN);	signal(SIGCHLD, SIG_IGN);	/* Put ourselves in our own process group.  */	setsid();	shell_pgrp = getpid ();	setpgid (shell_pgrp, shell_pgrp);	/* Grab control of the terminal.  */	tcsetpgrp(shell_terminal, shell_pgrp);}#elsestatic inline void setup_job_control(void){}#endifint lash_main(int argc_l, char **argv_l){	int opt, interactive=FALSE;	FILE *input = stdin;	argc = argc_l;	argv = argv_l;	/* These variables need re-initializing when recursing */	last_jobid = 0;	local_pending_command = NULL;	close_me_head = NULL;	job_list.head = NULL;	job_list.fg = NULL;	last_return_code=1;	if (argv[0] && argv[0][0] == '-') {		FILE *prof_input;		prof_input = fopen("/etc/profile", "r");		if (prof_input) {			int tmp_fd = fileno(prof_input);			mark_open(tmp_fd);			/* Now run the file */			busy_loop(prof_input);			fclose(prof_input);			mark_closed(tmp_fd);		}	}	while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {		switch (opt) {			case 'c':				input = NULL;				if (local_pending_command != 0)					bb_error_msg_and_die("multiple -c arguments");				local_pending_command = bb_xstrdup(argv[optind]);				optind++;				argv = argv+optind;				break;			case 'i':				interactive = TRUE;				break;			default:				bb_show_usage();		}	}	/* A shell is interactive if the `-i' flag was given, or if all of	 * the following conditions are met:	 *	  no -c command	 *    no arguments remaining or the -s flag given	 *    standard input is a terminal	 *    standard output is a terminal	 *    Refer to Posix.2, the description of the `sh' utility. */	if (argv[optind]==NULL && input==stdin &&			isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {		interactive=TRUE;	}	setup_job_control();	if (interactive==TRUE) {		//printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);		/* Looks like they want an interactive shell */#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET		printf( "\n\n" BB_BANNER " Built-in shell (lash)\n");		printf( "Enter 'help' for a list of built-in commands.\n\n");#endif	} else if (local_pending_command==NULL) {		//printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);		input = bb_xfopen(argv[optind], "r");		mark_open(fileno(input));  /* be lazy, never mark this closed */	}	/* initialize the cwd -- this is never freed...*/	cwd = xgetcwd(0);	if (!cwd)		cwd = bb_msg_unknown;#ifdef CONFIG_FEATURE_CLEAN_UP	atexit(free_memory);#endif#ifdef CONFIG_FEATURE_COMMAND_EDITING	cmdedit_set_initial_prompt();#else	PS1 = NULL;#endif	return (busy_loop(input));}

⌨️ 快捷键说明

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