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

📄 init.c

📁 为samsung2410 ARM移植的busybox工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vi: set sw=4 ts=4: *//* * Mini init implementation for busybox * * * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. * Adjusted by so many folks, it's impossible to keep track. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *//* Turn this on to disable all the dangerous    rebooting stuff when debugging.#define DEBUG_INIT*/#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <paths.h>#include <signal.h>#include <stdarg.h>#include <string.h>#include <termios.h>#include <unistd.h>#include <limits.h>#include <sys/fcntl.h>#include <sys/ioctl.h>#include <sys/mount.h>#include <sys/types.h>#include <sys/wait.h>#include "busybox.h"#ifdef BB_SYSLOGD# include <sys/syslog.h>#endif/* From <linux/vt.h> */struct vt_stat {	unsigned short v_active;        /* active vt */	unsigned short v_signal;        /* signal to send */	unsigned short v_state;         /* vt bitmask */};static const int VT_GETSTATE = 0x5603;  /* get global vt state info *//* From <linux/serial.h> */struct serial_struct {	int     type;	int     line;	int     port;	int     irq;	int     flags;	int     xmit_fifo_size;	int     custom_divisor;	int     baud_base;	unsigned short  close_delay;	char    reserved_char[2];	int     hub6;	unsigned short  closing_wait; /* time to wait before closing */	unsigned short  closing_wait2; /* no longer used... */	int     reserved[4];};#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__)   #include <sys/reboot.h>  #define init_reboot(magic) reboot(magic)#else  #define init_reboot(magic) reboot(0xfee1dead, 672274793, magic)#endif#ifndef RB_HALT_SYSTEMstatic const int RB_HALT_SYSTEM = 0xcdef0123;static const int RB_ENABLE_CAD = 0x89abcdef;static const int RB_DISABLE_CAD = 0;#define RB_POWER_OFF    0x4321fedcstatic const int RB_AUTOBOOT = 0x01234567;#endif#ifndef _PATH_STDPATH#define _PATH_STDPATH	"/usr/bin:/bin:/usr/sbin:/sbin"#endif#if defined BB_FEATURE_INIT_COREDUMPS/* * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called  * before processes are spawned to set core file size as unlimited. * This is for debugging only.  Don't use this is production, unless * you want core dumps lying about.... */#define CORE_ENABLE_FLAG_FILE "/.init_enable_core"#include <sys/resource.h>#include <sys/time.h>#endif#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))#if __GNU_LIBRARY__ > 5	#include <sys/kdaemon.h>#else	extern int bdflush (int func, long int data);#endif#define SHELL        "/bin/sh"	     /* Default shell */#define LOGIN_SHELL  "-" SHELL	     /* Default login shell */#define INITTAB      "/etc/inittab"  /* inittab file location */#ifndef INIT_SCRIPT#define INIT_SCRIPT  "/etc/init.d/rcS"   /* Default sysinit script. */#endif#define MAXENV	16		/* Number of env. vars *///static const int MAXENV = 16;	/* Number of env. vars */static const int LOG = 0x1;static const int CONSOLE = 0x2;#if defined BB_FEATURE_EXTRA_QUIETstatic const int MAYBE_CONSOLE = 0x0;#else#define MAYBE_CONSOLE	CONSOLE#endif/* Allowed init action types */typedef enum {	SYSINIT = 1,	RESPAWN,	ASKFIRST,	WAIT,	ONCE,	CTRLALTDEL,	SHUTDOWN} initActionEnum;/* A mapping between "inittab" action name strings and action type codes. */typedef struct initActionType {	const char *name;	initActionEnum action;} initActionType;static const struct initActionType actions[] = {	{"sysinit", SYSINIT},	{"respawn", RESPAWN},	{"askfirst", ASKFIRST},	{"wait", WAIT},	{"once", ONCE},	{"ctrlaltdel", CTRLALTDEL},	{"shutdown", SHUTDOWN},	{0, 0}};/* Set up a linked list of initActions, to be read from inittab */typedef struct initActionTag initAction;struct initActionTag {	pid_t pid;	char process[256];	char console[256];	initAction *nextPtr;	initActionEnum action;};static initAction *initActionList = NULL;static char *secondConsole = VC_2;static char *thirdConsole  = VC_3;static char *fourthConsole = VC_4;static char *log           = VC_5;static int  kernelVersion  = 0;static char termType[32]   = "TERM=linux";static char console[32]    = _PATH_CONSOLE;static void delete_initAction(initAction * action);static void loop_forever(){	while (1)		sleep (1);}/* Print a message to the specified device. * Device may be bitwise-or'd from LOG | CONSOLE */#ifdef DEBUG_INITstatic inline messageND(int device, char *fmt, ...) { }#else #define messageND message#endifstatic void message(int device, char *fmt, ...)		   __attribute__ ((format (printf, 2, 3)));static void message(int device, char *fmt, ...){	va_list arguments;	int fd;#ifdef BB_SYSLOGD	/* Log the message to syslogd */	if (device & LOG) {		char msg[1024];		va_start(arguments, fmt);		vsnprintf(msg, sizeof(msg), fmt, arguments);		va_end(arguments);		openlog(applet_name, 0, LOG_USER);		syslog(LOG_USER|LOG_INFO, msg);		closelog();	}#else	static int log_fd = -1;	/* Take full control of the log tty, and never close it.	 * It's mine, all mine!  Muhahahaha! */	if (log_fd < 0) {		if (log == NULL) {			/* don't even try to log, because there is no such console */			log_fd = -2;			/* log to main console instead */			device = CONSOLE;		} else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) {			log_fd = -2;			fprintf(stderr, "Bummer, can't write to log on %s!\n", log);			log = NULL;			device = CONSOLE;		}	}	if ((device & LOG) && (log_fd >= 0)) {		va_start(arguments, fmt);		vdprintf(log_fd, fmt, arguments);		va_end(arguments);	}#endif	if (device & CONSOLE) {		/* Always send console messages to /dev/console so people will see them. */		if (			(fd =			 device_open(_PATH_CONSOLE,						 O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) {			va_start(arguments, fmt);			vdprintf(fd, fmt, arguments);			va_end(arguments);			close(fd);		} else {			fprintf(stderr, "Bummer, can't print: ");			va_start(arguments, fmt);			vfprintf(stderr, fmt, arguments);			va_end(arguments);		}	}}/* Set terminal settings to reasonable defaults */static void set_term(int fd){	struct termios tty;	tcgetattr(fd, &tty);	/* set control chars */	tty.c_cc[VINTR]  = 3;	/* C-c */	tty.c_cc[VQUIT]  = 28;	/* C-\ */	tty.c_cc[VERASE] = 127; /* C-? */	tty.c_cc[VKILL]  = 21;	/* C-u */	tty.c_cc[VEOF]   = 4;	/* C-d */	tty.c_cc[VSTART] = 17;	/* C-q */	tty.c_cc[VSTOP]  = 19;	/* C-s */	tty.c_cc[VSUSP]  = 26;	/* C-z */	/* use line dicipline 0 */	tty.c_line = 0;	/* Make it be sane */	tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;	tty.c_cflag |= CREAD|HUPCL|CLOCAL;	/* input modes */	tty.c_iflag = ICRNL | IXON | IXOFF;	/* output modes */	tty.c_oflag = OPOST | ONLCR;	/* local modes */	tty.c_lflag =		ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;	tcsetattr(fd, TCSANOW, &tty);}/* How much memory does this machine have?   Units are kBytes to avoid overflow on 4GB machines */static int check_free_memory(){	struct sysinfo info;	unsigned int result, u, s=10;	if (sysinfo(&info) != 0) {		perror_msg("Error checking free memory");		return -1;	}	/* Kernels 2.0.x and 2.2.x return info.mem_unit==0 with values in bytes.	 * Kernels 2.4.0 return info.mem_unit in bytes. */	u = info.mem_unit;	if (u==0) u=1;	while ( (u&1) == 0 && s > 0 ) { u>>=1; s--; }	result = (info.totalram>>s) + (info.totalswap>>s);	result = result*u;	if (result < 0) result = INT_MAX;	return result;}static void console_init(){	int fd;	int tried_devcons = 0;	int tried_vtprimary = 0;	struct vt_stat vt;	struct serial_struct sr;	char *s;	if ((s = getenv("TERM")) != NULL) {		snprintf(termType, sizeof(termType) - 1, "TERM=%s", s);	}	if ((s = getenv("CONSOLE")) != NULL) {		safe_strncpy(console, s, sizeof(console));	}#if #cpu(sparc)	/* sparc kernel supports console=tty[ab] parameter which is also 	 * passed to init, so catch it here */	else if ((s = getenv("console")) != NULL) {		/* remap tty[ab] to /dev/ttyS[01] */		if (strcmp(s, "ttya") == 0)			safe_strncpy(console, SC_0, sizeof(console));		else if (strcmp(s, "ttyb") == 0)			safe_strncpy(console, SC_1, sizeof(console));	}#endif	else {		/* 2.2 kernels: identify the real console backend and try to use it */		if (ioctl(0, TIOCGSERIAL, &sr) == 0) {			/* this is a serial console */			snprintf(console, sizeof(console) - 1, SC_FORMAT, sr.line);		} else if (ioctl(0, VT_GETSTATE, &vt) == 0) {			/* this is linux virtual tty */			snprintf(console, sizeof(console) - 1, VC_FORMAT, vt.v_active);		} else {			safe_strncpy(console, _PATH_CONSOLE, sizeof(console));			tried_devcons++;		}	}	while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) {		/* Can't open selected console -- try /dev/console */		if (!tried_devcons) {			tried_devcons++;			safe_strncpy(console, _PATH_CONSOLE, sizeof(console));			continue;		}		/* Can't open selected console -- try vt1 */		if (!tried_vtprimary) {			tried_vtprimary++;			safe_strncpy(console, VC_1, sizeof(console));			continue;		}		break;	}	if (fd < 0) {		/* Perhaps we should panic here? */		safe_strncpy(console, "/dev/null", sizeof(console));	} else {		/* check for serial console and disable logging to tty5 & running a		   * shell to tty2-4 */		if (ioctl(0, TIOCGSERIAL, &sr) == 0) {			log = NULL;			secondConsole = NULL;			thirdConsole = NULL;			fourthConsole = NULL;			/* Force the TERM setting to vt102 for serial console --			 * iff TERM is set to linux (the default) */			if (strcmp( termType, "TERM=linux" ) == 0)				safe_strncpy(termType, "TERM=vt102", sizeof(termType));			message(LOG | CONSOLE,					"serial console detected.  Disabling virtual terminals.\n");		}		close(fd);	}	message(LOG, "console=%s\n", console);}	static void fixup_argv(int argc, char **argv, char *new_argv0){	int len;	/* Fix up argv[0] to be certain we claim to be init */	len = strlen(argv[0]);	memset(argv[0], 0, len);	safe_strncpy(argv[0], new_argv0, len + 1);	/* Wipe argv[1]-argv[N] so they don't clutter the ps listing */	len = 1;	while (argc > len) {		memset(argv[len], 0, strlen(argv[len]));		len++;	}}static pid_t run(char *command, char *terminal, int get_enter){	int i, j;	int fd;	pid_t pid;	char *tmpCmd, *s;	char *cmd[255], *cmdpath;	char buf[255];	struct stat sb;	static const char press_enter[] =#ifdef CUSTOMIZED_BANNER#include CUSTOMIZED_BANNER#endif		"\nPlease press Enter to activate this console. ";	char *environment[MAXENV+1] = {		termType,		"HOME=/",		"PATH=" _PATH_STDPATH,		"SHELL=" SHELL,		"USER=root",		NULL	};	/* inherit environment to the child, merging our values -andy */	for (i=0; environ[i]; i++) {		for (j=0; environment[j]; j++) {			s = strchr(environment[j], '=');			if (!strncmp(environ[i], environment[j], s - environment[j]))				break;		}		if (!environment[j]) {			environment[j++] = environ[i];			environment[j] = NULL;		}	}#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)	if ((pid = fork()) == 0) #else	if ((pid = vfork()) == 0) #endif	{		/* Clean up */		ioctl(0, TIOCNOTTY, 0);		close(0);		close(1);		close(2);		setsid();		/* Reset signal handlers set for parent process */		signal(SIGUSR1, SIG_DFL);		signal(SIGUSR2, SIG_DFL);		signal(SIGINT, SIG_DFL);		signal(SIGTERM, SIG_DFL);		signal(SIGHUP, SIG_DFL);		if ((fd = device_open(terminal, O_RDWR)) < 0) {			if (stat(terminal, &sb) != 0) {				message(LOG | CONSOLE, "device '%s' does not exist.\n",						terminal);				exit(1);			}			message(LOG | CONSOLE, "Bummer, can't open %s\n", terminal);			exit(1);		}		dup2(fd, 0);		dup2(fd, 1);		dup2(fd, 2);		ioctl(0, TIOCSCTTY, 1);		tcsetpgrp(0, getpgrp());		set_term(0);		/* See if any special /bin/sh requiring characters are present */		if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {			cmd[0] = SHELL;			cmd[1] = "-c";			strcpy(buf, "exec ");			safe_strncpy(buf + sizeof("exec "), command, 					sizeof(buf) - sizeof("exec "));			cmd[2] = buf;			cmd[3] = NULL;		} else {			/* Convert command (char*) into cmd (char**, one word per string) */			safe_strncpy(buf, command, sizeof(buf));			s = buf;			for (tmpCmd = buf, i = 0;					(tmpCmd = strsep(&s, " \t")) != NULL;) {				if (*tmpCmd != '\0') {					cmd[i] = tmpCmd;					tmpCmd++;					i++;				}			}			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").		 */

⌨️ 快捷键说明

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