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

📄 shutdown.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* shutdown.c - shutdown a Linux system * Initially written by poe@daimi.aau.dk  * Currently maintained at ftp://ftp.daimi.aau.dk/pub/Software/Linux/ *//* * Modified by jrs@world.std.com to try to exec "umount -a" and if * that doesn't work, then umount filesystems ourselves in reverse * order.  The old-way was in forward order.  Also if the device * field of the mtab does not start with a "/" then give umount * the mount point instead.  This is needed for the nfs and proc * filesystems and yet is compatible with older systems. * * We also use the mntent library interface to read the mtab file * instead of trying to parse it directly and no longer give a * warning about not being able to umount the root. * * The reason "umount -a" should be tried first is because it may do * special processing for some filesystems (such as informing an * nfs server about nfs umounts) that we don't want to cope with here. *//* * Various changes and additions to resemble SunOS 4 shutdown/reboot/halt(8) * more closely by Scott Telford (s.telford@ed.ac.uk) 93/05/18. * (I butchered Scotts patches somewhat. - poe) * * Changes by Richard Gooch <rgooch@atnf.csiro.au> (butchered by aeb) * introducing shutdown.conf. * * 1999-02-22 Arkadiusz Mi秌iewicz <misiek@pld.ORG.PL> * - added Native Language Support * * 2000-03-02 Richard Gooch <rgooch@atnf.csiro.au> * - pause forever if (pid == 1) and send SIGQUIT to pid = 1 * * 2000-11-04 Richard Gooch <rgooch@atnf.csiro.au> * - continue reaping if (pid == 1) * * 2000-11-06 Richard Gooch <rgooch@atnf.csiro.au> * - shut down "finalprog" from /etc/inittab * - kill normal user (non-root and non-daemon) processes first with SIGTERM * * 2000-11-08 Richard Gooch <rgooch@atnf.csiro.au> * - rollback services * - do not unmount devfs (otherwise get harmless but annoying messages) * - created syncwait() for faster shutting down * - kill getty processes * 2001-05-12 Richard Gooch <rgooch@atnf.csiro.au> * - unblock all signals (sigmask from simpleinit(8) stopped sleep(3)) * - close all files */#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <utmp.h>#include <time.h>#include <string.h>#include <ctype.h>#include <signal.h>#include <errno.h>#include <sys/param.h>#include <termios.h>#include <mntent.h>#include <sys/mount.h>#include <sys/wait.h>#include <syslog.h>#include <sys/resource.h>#include <sys/types.h>#include <dirent.h>#include <sys/stat.h>#include <sys/utsname.h>#include "linux_reboot.h"#include "pathnames.h"#include "xstrncpy.h"#include "nls.h"static void usage(void), int_handler(int), write_user(struct utmp *);static void wall(void), write_wtmp(void), unmount_disks(void);static void unmount_disks_ourselves(void);static void swap_off(void), do_halt(char *);static void kill_mortals (int sig);static void stop_finalprog (void);static void syncwait (int timeval);char	*prog;		/* name of the program */int	opt_reboot;	/* true if -r option or reboot command */int	timeout;	/* number of seconds to shutdown */int	opt_quiet;	/* true if no message is wanted */int	opt_fast;	/* true if fast boot */char	message[90];	/* reason for shutdown if any... */int	opt_single = 0; /* true is we want to boot singleuser */char	*whom;		/* who is shutting the system down */int	opt_msgset = 0; /* message set on command line */			/* change 1 to 0 if no file is to be used by default */int	opt_use_config_file = 1;	/* read _PATH_SHUTDOWN_CONF */char	halt_action[256];		/* to find out what to do upon halt *//* #define DEBUGGING */#define WR(s) write(fd, s, strlen(s))#define WRCRLF	write(fd, "\r\n", 2)#define ERRSTRING strerror(errno)voidusage(void){	fprintf(stderr,		_("Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n"));	exit(1);}static voidmy_puts(char *s){	/* Use a fresh stdout after forking */	freopen(_PATH_CONSOLE, "w", stdout);	puts(s);	fflush(stdout);}void int_handler(int sig){	unlink(_PATH_NOLOGIN);	signal(SIGINT, SIG_DFL);	my_puts(_("Shutdown process aborted"));	exit(1);}static intiswhitespace(int a) {	return (a == ' ' || a == '\t');}intmain(int argc, char *argv[]){	int c, i, fd;	char *ptr;	i = getdtablesize ();	for (fd = 3; fd < i; fd++) close (fd);	if (getpid () == 1)	{	    for (fd = 0; fd < 3; fd++) close (fd);	    while (1) wait (NULL);  /*  Grim reaper never stops  */	}	sigsetmask (0); /*  simpleinit(8) blocks all signals: undo for ALRM  */	for (i = 1; i < NSIG; i++) signal (i, SIG_DFL);        setlocale(LC_ALL, "");        bindtextdomain(PACKAGE, LOCALEDIR);        textdomain(PACKAGE);#ifndef DEBUGGING	if(setreuid (0, 0)) {		fprintf(stderr, _("%s: Only root can shut a system down.\n"),			argv[0]);		exit(1);	}#endif	if(*argv[0] == '-') argv[0]++;	/* allow shutdown as login shell */	prog = argv[0];	if((ptr = strrchr(argv[0], '/'))) prog = ++ptr;	/* All names (halt, reboot, fasthalt, fastboot, shutdown)	   refer to the same program with the same options,	   only the defaults differ. */	if(!strcmp("halt", prog)) {		opt_reboot = 0;		opt_quiet = 1;		opt_fast = 0;		timeout = 0;	} else if(!strcmp("fasthalt", prog)) {		opt_reboot = 0;		opt_quiet = 1;		opt_fast = 1;		timeout = 0;	} else if(!strcmp("reboot", prog)) {		opt_reboot = 1;		opt_quiet = 1;		opt_fast = 0;		timeout = 0;	} else if(!strcmp("fastboot", prog)) {		opt_reboot = 1;		opt_quiet = 1;		opt_fast = 1;		timeout = 0;	} else {		/* defaults */		opt_reboot = 0;		opt_quiet = 0;		opt_fast = 0;		timeout = 2*60;	}			c = 0;	while(++c < argc) {		if(argv[c][0] == '-') {			for(i = 1; argv[c][i]; i++) {				switch(argv[c][i]) {				case 'C':					opt_use_config_file = 1;					break;				case 'h': 					opt_reboot = 0;					break;				case 'r':					opt_reboot = 1;					break;				case 'f':					opt_fast = 1;					break;				case 'q':					opt_quiet = 1;					break;				case 's':					opt_single = 1;					break;				    				default:					usage();				}			}		} else if(!strcmp("now", argv[c])) {			timeout = 0;		} else if(argv[c][0] == '+') {			timeout = 60 * atoi(&argv[c][1]);		} else if (isdigit(argv[c][0])) {			char *colon;			int hour = 0;			int minute = 0;			time_t tics;			struct tm *tt;			int now, then;							if((colon = strchr(argv[c], ':'))) {				*colon = '\0';				hour = atoi(argv[c]);				minute = atoi(++colon);			} else usage();							(void) time(&tics);			tt = localtime(&tics);							now = 3600 * tt->tm_hour + 60 * tt->tm_min;			then = 3600 * hour + 60 * minute;			timeout = then - now;			if(timeout < 0) {				fprintf(stderr, _("That must be tomorrow, "					          "can't you wait till then?\n"));				exit(1);			}		} else {			xstrncpy(message, argv[c], sizeof(message));			opt_msgset = 1;		}	}	halt_action[0] = 0;	/* No doubt we shall want to extend this some day	   and register a series of commands to be executed	   at various points during the shutdown sequence,	   and to define the number of milliseconds to sleep, etc. */	if (opt_use_config_file) {		char line[256], *p;		FILE *fp;		/*  Read and parse the config file */		halt_action[0] = '\0';		if ((fp = fopen (_PATH_SHUTDOWN_CONF, "r")) != NULL) {			if (fgets (line, sizeof(line), fp) != NULL &&			    strncasecmp (line, "HALT_ACTION", 11) == 0 &&			    iswhitespace(line[11])) {				p = index(line, '\n');				if (p)					*p = 0;		/* strip final '\n' */				p = line+11;				while(iswhitespace(*p))					p++;				strcpy(halt_action, p);			}			fclose (fp);		}	}	if(!opt_quiet && !opt_msgset) {		/* now ask for message, gets() is insecure */		int cnt = sizeof(message)-1;		char *ptr;				printf("Why? "); fflush(stdout);				ptr = message;		while(--cnt >= 0 && (*ptr = getchar()) && *ptr != '\n') { 			ptr++;		}		*ptr = '\0';	} else if (!opt_msgset) {		strcpy(message, _("for maintenance; bounce, bounce"));	}#ifdef DEBUGGING	printf(_("timeout = %d, quiet = %d, reboot = %d\n"),		timeout, opt_quiet, opt_reboot);#endif		/* so much for option-processing, now begin termination... */	if(!(whom = getlogin()) || !*whom) whom = "ghost";	if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */	setpriority(PRIO_PROCESS, 0, PRIO_MIN);	signal(SIGINT,  int_handler);	signal(SIGHUP,  int_handler);	signal(SIGQUIT, int_handler);	signal(SIGTERM, int_handler);	chdir("/");	if(timeout > 5*60) {		sleep(timeout - 5*60);		timeout = 5*60;	}		if((fd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT, 0644)) >= 0) {		/* keep xgettext happy and leave \r\n outside strings */		WRCRLF;		WR(_("The system is being shut down within 5 minutes"));		WRCRLF;		write(fd, message, strlen(message));		WRCRLF;		WR(_("Login is therefore prohibited."));		WRCRLF;		close(fd);	}		signal(SIGPIPE, SIG_IGN);	if(timeout > 0) {		wall();		sleep(timeout);	}	timeout = 0;	wall();	sleep(3);	/* now there's no turning back... */	signal(SIGINT,  SIG_IGN);	/* do syslog message... */	openlog(prog, LOG_CONS, LOG_AUTH);	if (opt_reboot)		syslog(LOG_NOTICE, _("rebooted by %s: %s"), 		       whom, message);	else		syslog(LOG_NOTICE, _("halted by %s: %s"), 		       whom, message);	closelog();	if(opt_fast)		if((fd = open("/fastboot", O_WRONLY|O_CREAT, 0644)) >= 0)			close(fd);	kill(1, SIGTSTP);	/* tell init not to spawn more getty's */	write_wtmp();	if(opt_single)		if((fd = open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)) >= 0)

⌨️ 快捷键说明

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