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

📄 simpleinit.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* simpleinit.c - poe@daimi.aau.dk *//* Version 2.0.2 *//* 1999-02-22 Arkadiusz Mi秌iewicz <misiek@pld.ORG.PL> * - added Native Language Support * 2001-01-25 Richard Gooch <rgooch@atnf.csiro.au> * - fixed bug with failed services so they may be later "reclaimed" * 2001-02-02 Richard Gooch <rgooch@atnf.csiro.au> * - fixed race when reading from pipe and reaping children * 2001-02-18 sam@quux.dropbear.id.au * - fixed bug in <get_path>: multiple INIT_PATH components did not work * 2001-02-21 Richard Gooch <rgooch@atnf.csiro.au> * - block signals in handlers, so that longjmp() doesn't kill context * 2001-02-25 Richard Gooch <rgooch@atnf.csiro.au> * - make default INIT_PATH the boot_prog (if it is a directory) - YECCH * 2002-11-20 patch from SuSE * - refuse initctl_fd if setting FD_CLOEXEC fails */#include <sys/types.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <ctype.h>#include <fcntl.h>#include <string.h>#include <signal.h>#include <pwd.h>#include <sys/file.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/sysmacros.h>#include <sys/time.h>#include <sys/ioctl.h>#include <dirent.h>#include <termios.h>#include <utmp.h>#include <setjmp.h>#include <sched.h>#ifdef SHADOW_PWD#  include <shadow.h>#endif#include "my_crypt.h"#include "pathnames.h"#include "linux_reboot.h"#include "xstrncpy.h"#include "nls.h"#include "simpleinit.h"#define CMDSIZ     150	/* max size of a line in inittab */#define NUMCMD     30	/* max number of lines in inittab */#define NUMTOK     20	/* max number of tokens in inittab command */#define PATH_SIZE  (CMDSIZ+CMDSIZ+1)#define MAX_RESPAWN_RATE  5  /*  number of respawns per 100 seconds  */#define TZFILE "/etc/TZ"char tzone[CMDSIZ];/* #define DEBUGGING *//* Define this if you want init to ignore the termcap field in inittab for   console ttys. *//* #define SPECIAL_CONSOLE_TERM */#define ever (;;)struct initline {	pid_t		pid;	char		tty[10];	char		termcap[30];	char		*toks[NUMTOK];	char		line[CMDSIZ];	struct timeval	last_start;	signed long	rate;};struct initline inittab[NUMCMD];int numcmd;int stopped = 0;	/* are we stopped */static char boot_prog[PATH_SIZE] = _PATH_RC;static char script_prefix[PATH_SIZE] = "\0";static char final_prog[PATH_SIZE] = "\0";static char init_path[PATH_SIZE] = "\0";static int caught_sigint = 0;static int no_reboot = 0;static pid_t rc_child = -1;static const char *initctl_name = "/dev/initctl";static int initctl_fd = -1;static volatile int do_longjmp = 0;static sigjmp_buf jmp_env;static void do_single (void);static int do_rc_tty (const char *path);static int process_path (const char *path, int (*func) (const char *path),			 int ignore_dangling_symlink);static int preload_file (const char *path);static int run_file (const char *path);static void spawn (int i), read_inittab (void);static void sighup_handler (int sig);static void sigtstp_handler (int sig);static void sigint_handler (int sig);static void sigchild_handler (int sig);static void sigquit_handler (int sig);static void sigterm_handler (int sig);#ifdef SET_TZstatic void set_tz (void);#endifstatic void write_wtmp (void);static pid_t mywait (int *status);static int run_command (const char *file, const char *name, pid_t pid);static void err (char *s){	int fd;		if((fd = open("/dev/console", O_WRONLY)) < 0) return;	write(fd, "init: ", 6);		write(fd, s, strlen(s));	close(fd);}static void enter_single (void){    pid_t pid;    int i;    err(_("Booting to single user mode.\n"));    if((pid = fork()) == 0) {	/* the child */	execl(_PATH_BSHELL, _PATH_BSHELL, NULL);	err(_("exec of single user shell failed\n"));    } else if(pid > 0) {	while (waitpid (pid, &i, 0) != pid)  /*  Nothing  */;    } else if(pid < 0) {	err(_("fork of single user shell failed\n"));    }    unlink(_PATH_SINGLE);}int main(int argc, char *argv[]){	int			vec, i;	int			want_single = 0;	pid_t			pid;	struct sigaction	sa;#ifdef SET_TZ	set_tz();#endif	sigfillset (&sa.sa_mask);  /*  longjmp and nested signals don't mix  */	sa.sa_flags = SA_ONESHOT;	sa.sa_handler = sigint_handler;	sigaction (SIGINT, &sa, NULL);	sa.sa_flags = 0;	sa.sa_handler = sigtstp_handler;	sigaction (SIGTSTP, &sa, NULL);	sa.sa_handler = sigterm_handler;	sigaction (SIGTERM, &sa, NULL);	sa.sa_handler = sigchild_handler;	sigaction (SIGCHLD, &sa, NULL);	sa.sa_handler = sigquit_handler;	sigaction (SIGQUIT, &sa, NULL);	setlocale(LC_ALL, "");	bindtextdomain(PACKAGE, LOCALEDIR);	textdomain(PACKAGE);	my_reboot (LINUX_REBOOT_CMD_CAD_OFF);	/*  Find script to run. Command-line overrides config file overrides	    built-in default  */	for (i = 0; i < NUMCMD; i++) inittab[i].pid = -1;	read_inittab ();	for (i = 1; i < argc; i++) {		if (strcmp (argv[i], "single") == 0)			want_single = 1;		else if (strcmp (argv[i], "-noreboot") == 0)			no_reboot = 1;		else if (strlen(script_prefix) + strlen(argv[i]) < PATH_SIZE) {			char path[PATH_SIZE];			strcpy (path, script_prefix);			strcat (path, argv[i]);			if (access (path, R_OK | X_OK) == 0)				strcpy (boot_prog, path);		}	}	if (init_path[0] == '\0')	{	    struct stat statbuf;	    if ( (stat (boot_prog, &statbuf) == 0) && S_ISDIR (statbuf.st_mode) )	    {		strcpy (init_path, boot_prog);		i = strlen (init_path);		if (init_path[i - 1] == '/') init_path[i - 1] = '\0';	    }	}	if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 ) {		mkfifo (initctl_name, S_IRUSR | S_IWUSR);		if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 )			err ( _("error opening fifo\n") );	}	if (initctl_fd >= 0 && fcntl(initctl_fd, F_SETFD, FD_CLOEXEC) != 0) {		err ( _("error setting close-on-exec on /dev/initctl") );		/* Can the fcntl ever fail?  If it does, and we leave		   the descriptor open in child processes, then any		   process on the system will be able to write to		   /dev/initctl and have us execute arbitrary commands		   as root. So let's refuse to use the fifo in this case. */		close(initctl_fd);		initctl_fd = -1;	}	if ( want_single || (access (_PATH_SINGLE, R_OK) == 0) ) do_single ();	/*If we get a SIGTSTP before multi-user mode, do nothing*/	while (stopped)		pause();	if ( do_rc_tty (boot_prog) ) do_single ();	while (stopped)  /*  Also if /etc/rc fails & we get SIGTSTP  */		pause();	write_wtmp();	/* write boottime record */#ifdef DEBUGGING	for(i = 0; i < numcmd; i++) {		char **p;		p = inittab[i].toks;		printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]);		printf("tty= %s\n", inittab[i].tty);		printf("termcap= %s\n", inittab[i].termcap);	}	exit(0);#endif	signal (SIGHUP, sighup_handler);  /* Better semantics with signal(2) */	for (i = 0; i < getdtablesize (); i++)		if (i != initctl_fd) close (i);	for(i = 0; i < numcmd; i++)		spawn(i);	if (final_prog[0] != '\0') {		switch ( fork () )		{		  case 0:   /*  Child   */		    execl (final_prog, final_prog, "start", NULL);		    err ( _("error running finalprog\n") );		    _exit (1);		    break;		  case -1:  /*  Error   */		    err ( _("error forking finalprog\n") );		    break;		  default:  /*  Parent  */		    break;		}	}	for ever {		pid = mywait (&vec);		if (pid < 1) continue;		/* clear utmp entry, and append to wtmp if possible */		{		    struct utmp *ut;		    int ut_fd, lf;		    utmpname(_PATH_UTMP);		    setutent();		    while((ut = getutent())) {			if(ut->ut_pid == pid) {			    time(&ut->ut_time);			    memset(&ut->ut_user, 0, UT_NAMESIZE);			    memset(&ut->ut_host, 0, sizeof(ut->ut_host));			    ut->ut_type = DEAD_PROCESS;			    ut->ut_pid = 0;			    ut->ut_addr = 0;			    /*endutent();*/			    pututline(ut);			    if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) {				flock(lf, LOCK_EX|LOCK_NB);				if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {				    write(ut_fd, ut, sizeof(struct utmp));				    close(ut_fd);				}				flock(lf, LOCK_UN|LOCK_NB);				close(lf);			    }			    break;			}		    }		    endutent();		}		for(i = 0; i < numcmd; i++) {			if(pid == inittab[i].pid || inittab[i].pid < 0) {				if (stopped)					inittab[i].pid = -1;				else					spawn(i);				if (pid == inittab[i].pid)					break;			}		}	}}	#define MAXTRIES 3 /* number of tries allowed when giving the password *//* * return true if singleuser mode is allowed. * If /etc/securesingle exists ask for root password, otherwise always OK. */static int check_single_ok (void){    char *pass, *rootpass = NULL;    struct passwd *pwd;    int i;    if (access (_PATH_SECURE, R_OK) != 0) return 1;    if ( ( pwd = getpwnam ("root") ) || ( pwd = getpwuid (0) ) )	rootpass = pwd->pw_passwd;    else	return 1; /* a bad /etc/passwd should not lock out */    for (i = 0; i < MAXTRIES; i++)    {	pass = getpass (_ ("Password: ") );	if (pass == NULL) continue;			if ( !strcmp (crypt (pass, rootpass), rootpass) ) return 1;	puts (_ ("\nWrong password.\n") );    }    return 0;}static void do_single (void){    char path[PATH_SIZE];    if (caught_sigint) return;    strcpy (path, script_prefix);    strcat (path, "single");    if (access (path, R_OK | X_OK) == 0)	if (do_rc_tty (path) == 0) return;    if ( check_single_ok () ) enter_single ();}   /*  End Function do_single  *//* * run boot script(s). The environment is passed to the script(s), so the RC * environment variable can be used to decide what to do. * RC may be set from LILO. * [RETURNS] 0 on success (exit status convention), otherwise error. */static int do_rc_tty (const char *path){    int status;    pid_t pid;    sigset_t ss;    if (caught_sigint) return 0;    process_path (path, preload_file, 0);    /*  Launch off a subprocess to start a new session (required for frobbing	the TTY) and capture control-C  */    switch ( rc_child = fork () )    {      case 0:   /*  Child  */	for (status = 1; status < NSIG; status++) signal (status, SIG_DFL);	sigfillset (&ss);	sigprocmask (SIG_UNBLOCK, &ss, NULL);	sigdelset (&ss, SIGINT);	sigdelset (&ss, SIGQUIT);	setsid ();	ioctl (0, TIOCSCTTY, 0);  /*  I want my control-C  */	sigsuspend (&ss);  /*  Should never return, should just be killed  */	break;             /*  No-one else is controlled by this TTY now   */      case -1:  /*  Error  */	return (1);	/*break;*/      default:  /*  Parent  */	break;    }    /*  Parent  */    process_path (path, run_file, 0);    while (1)    {	if ( ( pid = mywait (&status) ) == rc_child )	    return (WTERMSIG (status) == SIGINT) ? 0 : 1;	if (pid < 0) break;    }    kill (rc_child, SIGKILL);    while (waitpid (rc_child, NULL, 0) != rc_child)  /*  Nothing  */;    return 0;}   /*  End Function do_rc_tty  */static int process_path (const char *path, int (*func) (const char *path),			 int ignore_dangling_symlink){    struct stat statbuf;    DIR *dp;    struct dirent *de;    if (lstat (path, &statbuf) != 0)

⌨️ 快捷键说明

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