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

📄 init.c

📁 手机嵌入式Linux下可用的busybox源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			}			cmd[i] = NULL;		}		cmdpath = cmd[0];		/*		   Interactive shells want to see a dash in argv[0].  This		   typically is handled by login, argv will be setup this 		   way if a dash appears at the front of the command path 		   (like "-/bin/sh").		 */		if (*cmdpath == '-') {			/* skip over the dash */			++cmdpath;			/* find the last component in the command pathname */			s = get_last_path_component(cmdpath);			/* make a new argv[0] */			if ((cmd[0] = malloc(strlen(s)+2)) == NULL) {				message(LOG | CONSOLE, "malloc failed");				cmd[0] = cmdpath;			} else {				cmd[0][0] = '-';				strcpy(cmd[0]+1, s);			}		}		if (a->action & ASKFIRST) {			/*			 * Save memory by not exec-ing anything large (like a shell)			 * before the user wants it. This is critical if swap is not			 * enabled and the system has low memory. Generally this will			 * be run on the second virtual console, and the first will			 * be allowed to start a shell or whatever an init script 			 * specifies.			 */			messageND(LOG, "Waiting for enter to start '%s' (pid %d, terminal %s)\n",					cmdpath, getpid(), a->terminal);			fflush(stdout);			write(fileno(stdout), press_enter, sizeof(press_enter) - 1);			getc(stdin);		}		/* Log the process name and args */		messageND(LOG, "Starting pid %d, console %s: '%s'\n",				getpid(), a->terminal, cmdpath);#if defined BB_FEATURE_INIT_COREDUMPS		if (stat (CORE_ENABLE_FLAG_FILE, &sb) == 0) {			struct rlimit limit;			limit.rlim_cur = RLIM_INFINITY;			limit.rlim_max = RLIM_INFINITY;			setrlimit(RLIMIT_CORE, &limit);		}#endif		/* Now run it.  The new program will take over this PID, 		 * so nothing further in init.c should be run. */		execve(cmdpath, cmd, environment);		/* We're still here?  Some error happened. */		message(LOG | CONSOLE, "\rBummer, could not run '%s': %s\n", cmdpath,				strerror(errno));		_exit(-1);	}	sigprocmask(SIG_SETMASK, &omask, NULL);	return pid;}static int waitfor(struct init_action *a){	int pid; 	int status, wpid;	pid = run(a);	while (1) {		wpid = wait(&status);		if (wpid > 0 && wpid != pid) {			continue;		}		if (wpid == pid)			break;	}	return wpid;}/* Run all commands of a particular type */static void run_actions(int action){	struct init_action *a, *tmp;	for (a = init_action_list; a; a = tmp) {		tmp = a->next;		if (a->action == action) {			if (a->action & (SYSINIT|WAIT|CTRLALTDEL|SHUTDOWN|RESTART)) {				waitfor(a);				delete_init_action(a);			} else if (a->action & ONCE) {				run(a);				delete_init_action(a);			} else if (a->action & (RESPAWN|ASKFIRST)) {				/* Only run stuff with pid==0.  If they have				 * a pid, that means it is still running */				if (a->pid == 0) {					a->pid = run(a);				}			}		}	}}#ifndef DEBUG_INITstatic void shutdown_system(void){	sigset_t block_signals;	/* run everything to be run at "shutdown".  This is done _prior_	 * to killing everything, in case people wish to use scripts to	 * shut things down gracefully... */	run_actions(SHUTDOWN);	/* first disable all our signals */	sigemptyset(&block_signals);	sigaddset(&block_signals, SIGHUP);	sigaddset(&block_signals, SIGCHLD);	sigaddset(&block_signals, SIGUSR1);	sigaddset(&block_signals, SIGUSR2);	sigaddset(&block_signals, SIGINT);	sigaddset(&block_signals, SIGTERM);	sigaddset(&block_signals, SIGCONT);	sigaddset(&block_signals, SIGSTOP);	sigaddset(&block_signals, SIGTSTP);	sigprocmask(SIG_BLOCK, &block_signals, NULL);	/* Allow Ctrl-Alt-Del to reboot system. */	init_reboot(RB_ENABLE_CAD);	message(CONSOLE|LOG, "\n\rThe system is going down NOW !!\n");	sync();	/* Send signals to every process _except_ pid 1 */	message(CONSOLE|LOG, "\rSending SIGTERM to all processes.\n");	kill(-1, SIGTERM);	sleep(1);	sync();	message(CONSOLE|LOG, "\rSending SIGKILL to all processes.\n");	kill(-1, SIGKILL);	sleep(1);	sync();	if (kernelVersion > 0 && kernelVersion <= KERNEL_VERSION(2,2,11)) {		/* bdflush, kupdate not needed for kernels >2.2.11 */		bdflush(1, 0);		sync();	}}static void exec_signal(int sig){	struct init_action *a, *tmp;	sigset_t unblock_signals;		for (a = init_action_list; a; a = tmp) {		tmp = a->next;		if (a->action & RESTART) {			shutdown_system();			/* unblock all signals, blocked in shutdown_system() */			sigemptyset(&unblock_signals);			sigaddset(&unblock_signals, SIGHUP);			sigaddset(&unblock_signals, SIGCHLD);			sigaddset(&unblock_signals, SIGUSR1);			sigaddset(&unblock_signals, SIGUSR2);			sigaddset(&unblock_signals, SIGINT);			sigaddset(&unblock_signals, SIGTERM);			sigaddset(&unblock_signals, SIGCONT);			sigaddset(&unblock_signals, SIGSTOP);			sigaddset(&unblock_signals, SIGTSTP);			sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);			message(CONSOLE|LOG, "\rTrying to re-exec %s\n", a->command);			execl(a->command, a->command, NULL);				message(CONSOLE|LOG, "\rexec of '%s' failed: %s\n", 				a->command, strerror(errno));			sync();			sleep(2);			init_reboot(RB_HALT_SYSTEM);			loop_forever();		}	}}static void halt_signal(int sig){	shutdown_system();	message(CONSOLE|LOG,#if #cpu(s390)			/* Seems the s390 console is Wierd(tm). */			"\rThe system is halted. You may reboot now.\n"#else			"\rThe system is halted. Press Reset or turn off power\n"#endif		   );	sync();	/* allow time for last message to reach serial console */	sleep(2);	if (sig == SIGUSR2 && kernelVersion >= KERNEL_VERSION(2,2,0))		init_reboot(RB_POWER_OFF);	else		init_reboot(RB_HALT_SYSTEM);	loop_forever();}static void reboot_signal(int sig){	shutdown_system();	message(CONSOLE|LOG, "\rPlease stand by while rebooting the system.\n");	sync();	/* allow time for last message to reach serial console */	sleep(2);	init_reboot(RB_AUTOBOOT);	loop_forever();}static void ctrlaltdel_signal(int sig){	run_actions(CTRLALTDEL);}/* The SIGSTOP & SIGTSTP handler */static void stop_handler(int sig){	int saved_errno = errno;	got_cont = 0;	while(!got_cont) pause();	got_cont = 0;	errno = saved_errno;}/* The SIGCONT handler */ static void cont_handler(int sig){	got_cont = 1;}#endif							/* ! DEBUG_INIT */static void new_init_action(int action, char *command, char *cons){	struct init_action *new_action, *a;	if (*cons == '\0')		cons = console;	/* do not run entries if console device is not available */	if (access(cons, R_OK|W_OK))		return;	if (strcmp(cons, "/dev/null") == 0 && (action & ASKFIRST))		return;	new_action = calloc((size_t) (1), sizeof(struct init_action));	if (!new_action) {		message(LOG | CONSOLE, "\rMemory allocation failure\n");		loop_forever();	}	/* Append to the end of the list */	for (a = init_action_list; a && a->next; a = a->next) ;	if (a) {		a->next = new_action;	} else {		init_action_list = new_action;	}	strcpy(new_action->command, command);	new_action->action = action;	strcpy(new_action->terminal, cons);	new_action->pid = 0;//    message(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n",//      new_action->command, new_action->action, new_action->terminal);}static void delete_init_action(struct init_action * action){	struct init_action *a, *b = NULL;	for (a = init_action_list; a; b = a, a = a->next) {		if (a == action) {			if (b == NULL) {				init_action_list = a->next;			} else {				b->next = a->next;			}			free(a);			break;		}	}}/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, * then parse_inittab() simply adds in some default * actions(i.e., runs INIT_SCRIPT and then starts a pair  * of "askfirst" shells).  If BB_FEATURE_USE_INITTAB  * _is_ defined, but /etc/inittab is missing, this  * results in the same set of default behaviors. * */static void parse_inittab(void){#ifdef BB_FEATURE_USE_INITTAB	FILE *file;	char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE], tmpConsole[INIT_BUFFS_SIZE];	char *id, *runlev, *action, *command, *eol;	const struct init_action_type *a = actions;	int foundIt;	file = fopen(INITTAB, "r");	if (file == NULL) {		/* No inittab file -- set up some default behavior */#endif		/* Reboot on Ctrl-Alt-Del */		new_init_action(CTRLALTDEL, "/sbin/reboot", console);		/* Umount all filesystems on halt/reboot */		new_init_action(SHUTDOWN, "/bin/umount -a -r", console);#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)		/* Swapoff on halt/reboot */		new_init_action(SHUTDOWN, "/sbin/swapoff -a", console);#endif		/* Prepare to restart init when a HUP is received */		new_init_action(RESTART, "/sbin/init", console);		/* Askfirst shell on tty1-4 */		new_init_action(ASKFIRST, LOGIN_SHELL, console);		new_init_action(ASKFIRST, LOGIN_SHELL, VC_2);		new_init_action(ASKFIRST, LOGIN_SHELL, VC_3);		new_init_action(ASKFIRST, LOGIN_SHELL, VC_4);		/* sysinit */		new_init_action(SYSINIT, INIT_SCRIPT, console);		return;#ifdef BB_FEATURE_USE_INITTAB	}	while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {		foundIt = FALSE;		/* Skip leading spaces */		for (id = buf; *id == ' ' || *id == '\t'; id++);		/* Skip the line if it's a comment */		if (*id == '#' || *id == '\n')			continue;		/* Trim the trailing \n */		eol = strrchr(id, '\n');		if (eol != NULL)			*eol = '\0';		/* Keep a copy around for posterity's sake (and error msgs) */		strcpy(lineAsRead, buf);		/* Separate the ID field from the runlevels */		runlev = strchr(id, ':');		if (runlev == NULL || *(runlev + 1) == '\0') {			message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead);			continue;		} else {			*runlev = '\0';			++runlev;		}		/* Separate the runlevels from the action */		action = strchr(runlev, ':');		if (action == NULL || *(action + 1) == '\0') {			message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead);			continue;		} else {			*action = '\0';			++action;		}		/* Separate the action from the command */		command = strchr(action, ':');		if (command == NULL || *(command + 1) == '\0') {			message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead);			continue;		} else {			*command = '\0';			++command;		}		/* Ok, now process it */		a = actions;		while (a->name != 0) {			if (strcmp(a->name, action) == 0) {				if (*id != '\0') {					strcpy(tmpConsole, "/dev/");					strncat(tmpConsole, id, INIT_BUFFS_SIZE-6);					id = tmpConsole;				}				new_init_action(a->action, command, id);				foundIt = TRUE;			}			a++;		}		if (foundIt == TRUE)			continue;		else {			/* Choke on an unknown action */			message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead);		}	}	fclose(file);	return;#endif /* BB_FEATURE_USE_INITTAB */}extern int init_main(int argc, char **argv){	struct init_action *a;	pid_t wpid;	int status;	if (argc > 1 && !strcmp(argv[1], "-q")) {		/* don't assume init's pid == 1 */		long *pid = find_pid_by_name("init");		if (!pid || *pid<=0) {			pid = find_pid_by_name("linuxrc");			if (!pid || *pid<=0)				error_msg_and_die("no process killed");		}		kill(*pid, SIGHUP);		exit(0);	}#ifndef DEBUG_INIT	/* Expect to be invoked as init with PID=1 or be invoked as linuxrc */	if (getpid() != 1#ifdef BB_FEATURE_LINUXRC			&& strstr(applet_name, "linuxrc") == NULL#endif	                  )	{			show_usage();	}	/* Set up sig handlers  -- be sure to	 * clear all of these in run() */	signal(SIGHUP,  exec_signal);	signal(SIGUSR1, halt_signal);	signal(SIGUSR2, halt_signal);	signal(SIGINT,  ctrlaltdel_signal);	signal(SIGTERM, reboot_signal);	signal(SIGCONT, cont_handler);	signal(SIGSTOP, stop_handler);	signal(SIGTSTP, stop_handler);	/* Turn off rebooting via CTL-ALT-DEL -- we get a 	 * SIGINT on CAD so we can shut things down gracefully... */	init_reboot(RB_DISABLE_CAD);#endif	/* Figure out what kernel this is running */	kernelVersion = get_kernel_revision();	/* Figure out where the default console should be */	console_init();	/* Close whatever files are open, and reset the console. */	close(0);	close(1);	close(2);	if(device_open(console, O_RDWR|O_NOCTTY)==0) {	set_term(0);		close(0);	}	chdir("/");	setsid();	/* Make sure PATH is set to something sane */	putenv("PATH="_PATH_STDPATH);	/* Hello world */	message(MAYBE_CONSOLE|LOG, "\rinit started:  %s\n", full_version);	/* Make sure there is enough memory to do something useful. */	check_memory();	/* Check if we are supposed to be in single user mode */	if (argc > 1 && (!strcmp(argv[1], "single") ||					 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {		/* Ask first then start a shell on tty2-4 */		new_init_action(ASKFIRST, LOGIN_SHELL, VC_2);		new_init_action(ASKFIRST, LOGIN_SHELL, VC_3);		new_init_action(ASKFIRST, LOGIN_SHELL, VC_4);		/* Start a shell on tty1 */		new_init_action(RESPAWN, LOGIN_SHELL, console);	} else {		/* Not in single user mode -- see what inittab says */		/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined,		 * then parse_inittab() simply adds in some default		 * actions(i.e., runs INIT_SCRIPT and then starts a pair 		 * of "askfirst" shells */		parse_inittab();	}	/* Make the command line just say "init"  -- thats all, nothing else */	fixup_argv(argc, argv, "init");	/* Now run everything that needs to be run */	/* First run the sysinit command */	run_actions(SYSINIT);	/* Next run anything that wants to block */	run_actions(WAIT);	/* Next run anything to be run only once */	run_actions(ONCE);	/* If there is nothing else to do, stop */	if (init_action_list == NULL) {		message(LOG | CONSOLE, "\rNo more tasks for init -- sleeping forever.\n");		loop_forever();	}	/* Now run the looping stuff for the rest of forever */	while (1) {		/* run the respawn stuff */		run_actions(RESPAWN);		/* run the askfirst stuff */		run_actions(ASKFIRST);		/* Don't consume all CPU time -- sleep a bit */		sleep(1);		/* Wait for a child process to exit */		wpid = wait(&status);		while (wpid > 0) {			/* Find out who died and clean up their corpse */			for (a = init_action_list; a; a = a->next) {				if (a->pid == wpid) {					/* Set the pid to 0 so that the process gets					 * restarted by run_actions() */					a->pid = 0;					message(LOG, "Process '%s' (pid %d) exited.  "							"Scheduling it for restart.\n", a->command, wpid);				}			}			/* see if anyone else is waiting to be reaped */			wpid = waitpid (-1, &status, WNOHANG);		}	}}/*Local Variables:c-file-style: "linux"c-basic-offset: 4tab-width: 4End:*/

⌨️ 快捷键说明

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