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

📄 shutdown.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 2 页
字号:
			close(fd);			sync();	signal(SIGTERM, SIG_IGN);	if(fork() > 0) sleep(1000); /* the parent will die soon... */	setpgrp();		/* so the shell wont kill us in the fall */#ifndef DEBUGGING	/* a gentle kill of all other processes except init */	kill_mortals (SIGTERM);	for (fd = 0; fd < 3; fd++) close (fd);	stop_finalprog ();	sleep (1);                    /*  Time for saves to start           */	kill (1, SIGTERM);            /*  Tell init to kill spawned gettys  */	usleep (100000);              /*  Wait for gettys to die            */	my_puts ("");                 /*  Get past the login prompt         */	system ("/sbin/initctl -r");  /*  Roll back services                */	syncwait (1);	my_puts ("Sending SIGTERM to all remaining processes...");	kill (-1, SIGTERM);	sleep (2);                    /*  Default 2, some people need 5     */	kill (-1, SIGKILL);           /*  Now use brute force...            */	/* turn off accounting */	acct(NULL);#endif	/* RedHat and SuSE like to remove /etc/nologin.	   Perhaps the usual sequence is	      touch nologin; shutdown -h; fiddle with hardware;	      boot; fiddle with software; rm nologin	   and removing it here will be counterproductive.	   Let us see whether people complain. */	unlink(_PATH_NOLOGIN);	/*  Tell init(8) to exec so that the old inode may be freed cleanly if	    required. Need to sleep before remounting root read-only  */	kill (1, SIGQUIT);	sleep (1);	/* Time for processes to die and close files */	syncwait (2);	/* remove swap files and partitions using swapoff */	swap_off();	/* unmount disks... */	unmount_disks();	syncwait (1);	if(opt_reboot) {		my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */		my_puts(_("\nWhy am I still alive after reboot?"));	} else {		my_puts(_("\nNow you can turn off the power..."));		/* allow C-A-D now, faith@cs.unc.edu, re-fixed 8-Jul-96 */		my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */		sleep (1);  /*  Wait for devices to finish writing to media  */		do_halt(halt_action);	}	/* NOTREACHED */	exit(0); /* to quiet gcc */}/*** end of main() ***/voiddo_halt(char *action) {	if (strcasecmp (action, "power_off") == 0) {		printf(_("Calling kernel power-off facility...\n"));		fflush(stdout);		my_reboot(LINUX_REBOOT_CMD_POWER_OFF);		printf(_("Error powering off\t%s\n"), ERRSTRING);		fflush(stdout);		sleep (2);	} else	/* This should be improved; e.g. Mike Jagdis wants "/sbin/mdstop -a" */	/* Maybe we should also fork and wait */	if (action[0] == '/') {		printf(_("Executing the program \"%s\" ...\n"), action);		fflush(stdout);		execl(action, action, NULL);		printf(_("Error executing\t%s\n"), ERRSTRING);		fflush(stdout);		sleep (2);	}	my_reboot(LINUX_REBOOT_CMD_HALT); /* RB_HALT_SYSTEM */}voidwrite_user(struct utmp *ut){	int fd;	int minutes, hours;	char term[40] = {'/','d','e','v','/',0};	char msg[100];	minutes = timeout / 60;	hours = minutes / 60;	minutes %= 60;	(void) strncat(term, ut->ut_line, sizeof(ut->ut_line));	/* try not to get stuck on a mangled ut_line entry... */	if((fd = open(term, O_WRONLY|O_NONBLOCK)) < 0)	        return;	msg[0] = '\007';	/* gettext crashes on \a */	sprintf(msg+1, _("URGENT: broadcast message from %s:"), whom);	WRCRLF;	WR(msg);	WRCRLF;	if (hours > 1)		sprintf(msg, _("System going down in %d hours %d minutes"),			hours, minutes);	else if (hours == 1)		sprintf(msg, _("System going down in 1 hour %d minutes"),			minutes);	else if (minutes > 1)		sprintf(msg, _("System going down in %d minutes\n"),			minutes);	else if (minutes == 1)		sprintf(msg, _("System going down in 1 minute\n"));	else		sprintf(msg, _("System going down IMMEDIATELY!\n"));	WR(msg);	WRCRLF;	sprintf(msg, _("\t... %s ...\n"), message);	WR(msg);	WRCRLF;	close(fd);}voidwall(void){	/* write to all users, that the system is going down. */	struct utmp *ut;			utmpname(_PATH_UTMP);	setutent();		while((ut = getutent())) {		if(ut->ut_type == USER_PROCESS)			write_user(ut);	}	endutent();}voidwrite_wtmp(void){	/* write in wtmp that we are dying */	int fd;	struct utmp ut;		memset((char *)&ut, 0, sizeof(ut));	strcpy(ut.ut_line, "~");	memcpy(ut.ut_name, "shutdown", sizeof(ut.ut_name));	time(&ut.ut_time);	ut.ut_type = BOOT_TIME;		if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0644)) >= 0) {		write(fd, (char *)&ut, sizeof(ut));		close(fd);	}}voidswap_off(void){	/* swapoff esp. swap FILES so the underlying partition can be	   unmounted. It you don't have swapoff(1) or use mount to	   add swapspace, this may not be necessary, but I guess it	   won't hurt */	int pid;	int result;	int status;	sync();	if ((pid = fork()) < 0) {		my_puts(_("Cannot fork for swapoff. Shrug!"));		return;	}	if (!pid) {		execl("/sbin/swapoff", SWAPOFF_ARGS, NULL);		execl("/etc/swapoff", SWAPOFF_ARGS, NULL);		execl("/bin/swapoff", SWAPOFF_ARGS, NULL);		execlp("swapoff", SWAPOFF_ARGS, NULL);		my_puts(_("Cannot exec swapoff, "			  "hoping umount will do the trick."));		exit(0);	}	while ((result = wait(&status)) != -1 && result != pid)		;}voidunmount_disks(void){	/* better to use umount directly because it may be smarter than us */	int pid;	int result;	int status;	sync();	if ((pid = fork()) < 0) {		my_puts(_("Cannot fork for umount, trying manually."));		unmount_disks_ourselves();		return;	}	if (!pid) {		execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL);		/* need my_printf instead of my_puts here */		freopen(_PATH_CONSOLE, "w", stdout);		printf(_("Cannot exec %s, trying umount.\n"), _PATH_UMOUNT);		fflush(stdout);		execlp("umount", UMOUNT_ARGS, NULL);		my_puts(_("Cannot exec umount, giving up on umount."));		exit(0);	}	while ((result = wait(&status)) != -1 && result != pid)		;	my_puts(_("Unmounting any remaining filesystems..."));	unmount_disks_ourselves();}voidunmount_disks_ourselves(void){	/* unmount all disks */	FILE *mtab;	struct mntent *mnt;	char *mntlist[128];	int i;	int n;	char *filesys;		sync();	if (!(mtab = setmntent(_PATH_MTAB, "r"))) {		my_puts("shutdown: Cannot open " _PATH_MTAB ".");		return;	}	n = 0;	while (n < 100 && (mnt = getmntent(mtab))) {		/*		 * Neil Phillips: trying to unmount temporary / kernel		 * filesystems is pointless and may cause error messages;		 * /dev can be a ramfs managed by udev.		 */		if (strcmp(mnt->mnt_type, "devfs") == 0 ||		    strcmp(mnt->mnt_type, "proc") == 0 ||		    strcmp(mnt->mnt_type, "sysfs") == 0 ||		    strcmp(mnt->mnt_type, "ramfs") == 0 ||		    strcmp(mnt->mnt_type, "tmpfs") == 0 ||		    strcmp(mnt->mnt_type, "devpts") == 0)			continue;		mntlist[n++] = strdup(mnt->mnt_dir);	}	endmntent(mtab);	/* we are careful to do this in reverse order of the mtab file */	for (i = n - 1; i >= 0; i--) {		filesys = mntlist[i];#ifdef DEBUGGING		printf("umount %s\n", filesys);#else		if (umount(mntlist[i]) < 0)			printf(_("shutdown: Couldn't umount %s: %s\n"),			       filesys, ERRSTRING);#endif	}}static void kill_mortals (int sig){    int npids = 0;    int index = 0;    int pid;    struct stat statbuf;    DIR *dp;    struct dirent *de;    pid_t *pids = NULL;    char path[256];    if ( ( dp = opendir ("/proc") ) == NULL ) return;    while ( ( de = readdir (dp) ) != NULL )    {	if ( !isdigit (de->d_name[0]) ) continue;	pid = atoi (de->d_name);	sprintf (path, "/proc/%d", pid);	if (stat (path, &statbuf) != 0) continue;	if (statbuf.st_uid < 100) continue;	if (index <= npids)	{	    pids = realloc (pids, npids + 16384);	    if (pids == NULL) return;	    npids += 16384;	}	pids[index++] = pid;    }    fputs ("Sending SIGTERM to mortals...", stderr);    for (--index; index >= 0; --index) kill (pids[index], sig);    free (pids);    closedir (dp);}   /*  End Function kill_mortals  */static void stop_finalprog (void){    char *p1, *p2;    FILE *fp;    char line[256];    if ( ( fp = fopen (_PATH_INITTAB, "r") ) == NULL ) return;    while (fgets (line, 256, fp) != NULL)    {	pid_t pid;	line[strlen (line) - 1] = '\0';	p1 = line;	while ( isspace (*p1) ) ++p1;	if (strncmp (p1, "finalprog", 9) != 0) continue;	if ( ( p1 = strchr (p1 + 9, '=') ) == NULL ) continue;	for (++p1; isspace (*p1); ++p1);	if (*p1 == '\0') continue;	for (p2 = p1; !isspace (*p2); ++p2);	*p2 = '\0';	switch ( pid = fork () )	{	  case 0:   /*  Child   */	    execl (p1, p1, "stop", NULL);	    break;	  case -1:  /*  Error   */	    break;	  default:  /*  Parent  */	    waitpid (pid, NULL, 0);	    break;	}	fclose (fp);	return;    }    fclose (fp);}   /*  End Function stop_finalprog  */static void syncwait (int timeval){    static int do_wait = 0;    static int first_time = 1;    sync ();    /*  Kernel version 1.3.20 and after are supposed to wait automatically  */    if (first_time)    {	struct utsname uts;	first_time = 0;	uname (&uts);	if (uts.release[0] < '2') do_wait = 1;    }    if (do_wait) sleep (timeval);}   /*  End Function syncwait  */

⌨️ 快捷键说明

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