1 /* shutdown.c - shutdown a Linux system
2 * Initially written by poe@daimi.aau.dk
3 * Currently maintained at ftp://ftp.daimi.aau.dk/pub/Software/Linux/
7 * Modified by jrs@world.std.com to try to exec "umount -a" and if
8 * that doesn't work, then umount filesystems ourselves in reverse
9 * order. The old-way was in forward order. Also if the device
10 * field of the mtab does not start with a "/" then give umount
11 * the mount point instead. This is needed for the nfs and proc
12 * filesystems and yet is compatible with older systems.
14 * We also use the mntent library interface to read the mtab file
15 * instead of trying to parse it directly and no longer give a
16 * warning about not being able to umount the root.
18 * The reason "umount -a" should be tried first is because it may do
19 * special processing for some filesystems (such as informing an
20 * nfs server about nfs umounts) that we don't want to cope with here.
24 * Various changes and additions to resemble SunOS 4 shutdown/reboot/halt(8)
25 * more closely by Scott Telford (s.telford@ed.ac.uk) 93/05/18.
26 * (I butchered Scotts patches somewhat. - poe)
28 * Changes by Richard Gooch <rgooch@atnf.csiro.au> (butchered by aeb)
29 * introducing shutdown.conf.
31 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
32 * - added Native Language Support
34 * 2000-03-02 Richard Gooch <rgooch@atnf.csiro.au>
35 * - pause forever if (pid == 1) and send SIGQUIT to pid = 1
37 * 2000-11-04 Richard Gooch <rgooch@atnf.csiro.au>
38 * - continue reaping if (pid == 1)
40 * 2000-11-06 Richard Gooch <rgooch@atnf.csiro.au>
41 * - shut down "finalprog" from /etc/inittab
42 * - kill normal user (non-root and non-daemon) processes first with SIGTERM
44 * 2000-11-08 Richard Gooch <rgooch@atnf.csiro.au>
46 * - do not unmount devfs (otherwise get harmless but annoying messages)
47 * - created syncwait() for faster shutting down
48 * - kill getty processes
49 * 2001-05-12 Richard Gooch <rgooch@atnf.csiro.au>
50 * - unblock all signals (sigmask from simpleinit(8) stopped sleep(3))
64 #include <sys/param.h>
67 #include <sys/mount.h>
70 #include <sys/resource.h>
71 #include <sys/types.h>
74 #include <sys/utsname.h>
75 #include "linux_reboot.h"
76 #include "pathnames.h"
80 static void usage(void), int_handler(int), write_user(struct utmp *);
81 static void wall(void), write_wtmp(void), unmount_disks(void);
82 static void unmount_disks_ourselves(void);
83 static void swap_off(void), do_halt(char *);
84 static void kill_mortals (int sig);
85 static void stop_finalprog (void);
86 static void syncwait (int timeval);
89 char *prog; /* name of the program */
90 int opt_reboot; /* true if -r option or reboot command */
91 int timeout; /* number of seconds to shutdown */
92 int opt_quiet; /* true if no message is wanted */
93 int opt_fast; /* true if fast boot */
94 char message[90]; /* reason for shutdown if any... */
95 int opt_single = 0; /* true is we want to boot singleuser */
96 char *whom; /* who is shutting the system down */
97 int opt_msgset = 0; /* message set on command line */
98 /* change 1 to 0 if no file is to be used by default */
99 int opt_use_config_file = 1; /* read _PATH_SHUTDOWN_CONF */
100 char halt_action[256]; /* to find out what to do upon halt */
102 /* #define DEBUGGING */
104 #define WR(s) write(fd, s, strlen(s))
105 #define WRCRLF write(fd, "\r\n", 2)
106 #define ERRSTRING strerror(errno)
108 #define UMOUNT_ARGS "umount", "-a", "-t", "nodevfs"
109 #define SWAPOFF_ARGS "swapoff", "-a"
115 _("Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n"));
122 /* Use a fresh stdout after forking */
123 freopen(_PATH_CONSOLE, "w", stdout);
131 unlink(_PATH_NOLOGIN);
132 signal(SIGINT, SIG_DFL);
133 my_puts(_("Shutdown process aborted"));
138 iswhitespace(int a) {
139 return (a == ' ' || a == '\t');
143 main(int argc, char *argv[])
148 i = getdtablesize ();
149 for (fd = 3; fd < i; fd++) close (fd);
152 for (fd = 0; fd < 3; fd++) close (fd);
153 while (1) wait (NULL); /* Grim reaper never stops */
155 sigsetmask (0); /* simpleinit(8) blocks all signals: undo for ALRM */
156 for (i = 1; i < NSIG; i++) signal (i, SIG_DFL);
158 setlocale(LC_ALL, "");
159 bindtextdomain(PACKAGE, LOCALEDIR);
163 if(setreuid (0, 0)) {
164 fprintf(stderr, _("%s: Only root can shut a system down.\n"),
170 if(*argv[0] == '-') argv[0]++; /* allow shutdown as login shell */
172 if((ptr = strrchr(argv[0], '/'))) prog = ++ptr;
174 /* All names (halt, reboot, fasthalt, fastboot, shutdown)
175 refer to the same program with the same options,
176 only the defaults differ. */
177 if(!strcmp("halt", prog)) {
182 } else if(!strcmp("fasthalt", prog)) {
187 } else if(!strcmp("reboot", prog)) {
192 } else if(!strcmp("fastboot", prog)) {
207 if(argv[c][0] == '-') {
208 for(i = 1; argv[c][i]; i++) {
211 opt_use_config_file = 1;
233 } else if(!strcmp("now", argv[c])) {
235 } else if(argv[c][0] == '+') {
236 timeout = 60 * atoi(&argv[c][1]);
237 } else if (isdigit(argv[c][0])) {
245 if((colon = strchr(argv[c], ':'))) {
247 hour = atoi(argv[c]);
248 minute = atoi(++colon);
252 tt = localtime(&tics);
254 now = 3600 * tt->tm_hour + 60 * tt->tm_min;
255 then = 3600 * hour + 60 * minute;
256 timeout = then - now;
258 fprintf(stderr, _("That must be tomorrow, "
259 "can't you wait till then?\n"));
263 xstrncpy(message, argv[c], sizeof(message));
270 /* No doubt we shall want to extend this some day
271 and register a series of commands to be executed
272 at various points during the shutdown sequence,
273 and to define the number of milliseconds to sleep, etc. */
274 if (opt_use_config_file) {
278 /* Read and parse the config file */
279 halt_action[0] = '\0';
280 if ((fp = fopen (_PATH_SHUTDOWN_CONF, "r")) != NULL) {
281 if (fgets (line, sizeof(line), fp) != NULL &&
282 strncasecmp (line, "HALT_ACTION", 11) == 0 &&
283 iswhitespace(line[11])) {
284 p = strchr(line, '\n');
286 *p = 0; /* strip final '\n' */
288 while(iswhitespace(*p))
290 strcpy(halt_action, p);
296 if(!opt_quiet && !opt_msgset) {
297 /* now ask for message, gets() is insecure */
298 int cnt = sizeof(message)-1;
301 printf("Why? "); fflush(stdout);
304 while(--cnt >= 0 && (*ptr = getchar()) && *ptr != '\n') {
308 } else if (!opt_msgset) {
309 strcpy(message, _("for maintenance; bounce, bounce"));
313 printf("timeout = %d, quiet = %d, reboot = %d\n",
314 timeout, opt_quiet, opt_reboot);
317 /* so much for option-processing, now begin termination... */
318 if(!(whom = getlogin()) || !*whom) whom = "ghost";
319 if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */
321 setpriority(PRIO_PROCESS, 0, PRIO_MIN);
322 signal(SIGINT, int_handler);
323 signal(SIGHUP, int_handler);
324 signal(SIGQUIT, int_handler);
325 signal(SIGTERM, int_handler);
330 sleep(timeout - 5*60);
335 if((fd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT, 0644)) >= 0) {
336 /* keep xgettext happy and leave \r\n outside strings */
338 WR(_("The system is being shut down within 5 minutes"));
340 write(fd, message, strlen(message));
342 WR(_("Login is therefore prohibited."));
347 signal(SIGPIPE, SIG_IGN);
358 /* now there's no turning back... */
359 signal(SIGINT, SIG_IGN);
361 /* do syslog message... */
362 openlog(prog, LOG_CONS, LOG_AUTH);
364 syslog(LOG_NOTICE, _("rebooted by %s: %s"),
367 syslog(LOG_NOTICE, _("halted by %s: %s"),
372 if((fd = open("/fastboot", O_WRONLY|O_CREAT, 0644)) >= 0)
375 kill(1, SIGTSTP); /* tell init not to spawn more getty's */
378 if((fd = open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)) >= 0)
383 signal(SIGTERM, SIG_IGN);
384 if(fork() > 0) sleep(1000); /* the parent will die soon... */
385 setpgrp(); /* so the shell wont kill us in the fall */
388 /* a gentle kill of all other processes except init */
389 kill_mortals (SIGTERM);
390 for (fd = 0; fd < 3; fd++) close (fd);
392 sleep (1); /* Time for saves to start */
393 kill (1, SIGTERM); /* Tell init to kill spawned gettys */
394 usleep (100000); /* Wait for gettys to die */
395 my_puts (""); /* Get past the login prompt */
396 system ("/sbin/initctl -r"); /* Roll back services */
398 my_puts ("Sending SIGTERM to all remaining processes...");
400 sleep (2); /* Default 2, some people need 5 */
402 kill (-1, SIGKILL); /* Now use brute force... */
404 /* turn off accounting */
407 /* RedHat and SuSE like to remove /etc/nologin.
408 Perhaps the usual sequence is
409 touch nologin; shutdown -h; fiddle with hardware;
410 boot; fiddle with software; rm nologin
411 and removing it here will be counterproductive.
412 Let us see whether people complain. */
413 unlink(_PATH_NOLOGIN);
415 /* Tell init(8) to exec so that the old inode may be freed cleanly if
416 required. Need to sleep before remounting root read-only */
419 sleep (1); /* Time for processes to die and close files */
422 /* remove swap files and partitions using swapoff */
425 /* unmount disks... */
430 my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */
431 my_puts(_("\nWhy am I still alive after reboot?"));
433 my_puts(_("\nNow you can turn off the power..."));
435 /* allow C-A-D now, faith@cs.unc.edu, re-fixed 8-Jul-96 */
436 my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */
437 sleep (1); /* Wait for devices to finish writing to media */
438 do_halt(halt_action);
441 exit(0); /* to quiet gcc */
444 /*** end of main() ***/
447 do_halt(char *action) {
448 if (strcasecmp (action, "power_off") == 0) {
449 printf(_("Calling kernel power-off facility...\n"));
451 my_reboot(LINUX_REBOOT_CMD_POWER_OFF);
452 printf(_("Error powering off\t%s\n"), ERRSTRING);
457 /* This should be improved; e.g. Mike Jagdis wants "/sbin/mdstop -a" */
458 /* Maybe we should also fork and wait */
459 if (action[0] == '/') {
460 printf(_("Executing the program \"%s\" ...\n"), action);
462 execl(action, action, NULL);
463 printf(_("Error executing\t%s\n"), ERRSTRING);
468 my_reboot(LINUX_REBOOT_CMD_HALT); /* RB_HALT_SYSTEM */
472 write_user(struct utmp *ut)
476 char term[40] = {'/','d','e','v','/',0};
479 minutes = timeout / 60;
480 hours = minutes / 60;
483 (void) strncat(term, ut->ut_line, sizeof(ut->ut_line));
485 /* try not to get stuck on a mangled ut_line entry... */
486 if((fd = open(term, O_WRONLY|O_NONBLOCK)) < 0)
489 msg[0] = '\007'; /* gettext crashes on \a */
490 sprintf(msg+1, _("URGENT: broadcast message from %s:"), whom);
496 sprintf(msg, _("System going down in %d hours %d minutes"),
499 sprintf(msg, _("System going down in 1 hour %d minutes"),
501 else if (minutes > 1)
502 sprintf(msg, _("System going down in %d minutes\n"),
504 else if (minutes == 1)
505 sprintf(msg, _("System going down in 1 minute\n"));
507 sprintf(msg, _("System going down IMMEDIATELY!\n"));
512 sprintf(msg, _("\t... %s ...\n"), message);
522 /* write to all users, that the system is going down. */
525 utmpname(_PATH_UTMP);
528 while((ut = getutent())) {
529 if(ut->ut_type == USER_PROCESS)
538 /* write in wtmp that we are dying */
542 memset((char *)&ut, 0, sizeof(ut));
543 strcpy(ut.ut_line, "~");
544 memcpy(ut.ut_name, "shutdown", sizeof(ut.ut_name));
547 ut.ut_type = BOOT_TIME;
549 if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0644)) >= 0) {
550 write(fd, (char *)&ut, sizeof(ut));
558 /* swapoff esp. swap FILES so the underlying partition can be
559 unmounted. It you don't have swapoff(1) or use mount to
560 add swapspace, this may not be necessary, but I guess it
568 if ((pid = fork()) < 0) {
569 my_puts(_("Cannot fork for swapoff. Shrug!"));
573 execl("/sbin/swapoff", SWAPOFF_ARGS, NULL);
574 execl("/etc/swapoff", SWAPOFF_ARGS, NULL);
575 execl("/bin/swapoff", SWAPOFF_ARGS, NULL);
576 execlp("swapoff", SWAPOFF_ARGS, NULL);
577 my_puts(_("Cannot exec swapoff, "
578 "hoping umount will do the trick."));
581 while ((result = wait(&status)) != -1 && result != pid)
588 /* better to use umount directly because it may be smarter than us */
595 if ((pid = fork()) < 0) {
596 my_puts(_("Cannot fork for umount, trying manually."));
597 unmount_disks_ourselves();
601 execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL);
603 /* need my_printf instead of my_puts here */
604 freopen(_PATH_CONSOLE, "w", stdout);
605 printf(_("Cannot exec %s, trying umount.\n"), _PATH_UMOUNT);
608 execlp("umount", UMOUNT_ARGS, NULL);
609 my_puts(_("Cannot exec umount, giving up on umount."));
612 while ((result = wait(&status)) != -1 && result != pid)
614 my_puts(_("Unmounting any remaining filesystems..."));
615 unmount_disks_ourselves();
619 unmount_disks_ourselves(void)
621 /* unmount all disks */
631 if (!(mtab = setmntent(_PATH_MOUNTED, "r"))) {
632 my_puts("shutdown: Cannot open " _PATH_MOUNTED ".");
636 while (n < 100 && (mnt = getmntent(mtab))) {
638 * Neil Phillips: trying to unmount temporary / kernel
639 * filesystems is pointless and may cause error messages;
640 * /dev can be a ramfs managed by udev.
642 if (strcmp(mnt->mnt_type, "devfs") == 0 ||
643 strcmp(mnt->mnt_type, "proc") == 0 ||
644 strcmp(mnt->mnt_type, "sysfs") == 0 ||
645 strcmp(mnt->mnt_type, "ramfs") == 0 ||
646 strcmp(mnt->mnt_type, "tmpfs") == 0 ||
647 strcmp(mnt->mnt_type, "devpts") == 0)
649 mntlist[n++] = strdup(mnt->mnt_dir);
653 /* we are careful to do this in reverse order of the mtab file */
655 for (i = n - 1; i >= 0; i--) {
656 filesys = mntlist[i];
658 printf("umount %s\n", filesys);
660 if (umount(mntlist[i]) < 0)
661 printf(_("shutdown: Couldn't umount %s: %s\n"),
667 static void kill_mortals (int sig)
678 if ( ( dp = opendir ("/proc") ) == NULL ) return;
679 while ( ( de = readdir (dp) ) != NULL )
681 if ( !isdigit (de->d_name[0]) ) continue;
682 pid = atoi (de->d_name);
683 sprintf (path, "/proc/%d", pid);
684 if (stat (path, &statbuf) != 0) continue;
685 if (statbuf.st_uid < 100) continue;
688 pids = realloc (pids, npids + 16384);
689 if (pids == NULL) return;
694 fputs ("Sending SIGTERM to mortals...", stderr);
695 for (--index; index >= 0; --index) kill (pids[index], sig);
698 } /* End Function kill_mortals */
700 static void stop_finalprog (void)
706 if ( ( fp = fopen (_PATH_INITTAB, "r") ) == NULL ) return;
707 while (fgets (line, 256, fp) != NULL)
711 line[strlen (line) - 1] = '\0';
713 while ( isspace (*p1) ) ++p1;
714 if (strncmp (p1, "finalprog", 9) != 0) continue;
715 if ( ( p1 = strchr (p1 + 9, '=') ) == NULL ) continue;
716 for (++p1; isspace (*p1); ++p1);
717 if (*p1 == '\0') continue;
718 for (p2 = p1; !isspace (*p2); ++p2);
720 switch ( pid = fork () )
723 execl (p1, p1, "stop", NULL);
727 default: /* Parent */
728 waitpid (pid, NULL, 0);
735 } /* End Function stop_finalprog */
737 static void syncwait (int timeval)
739 static int do_wait = 0;
740 static int first_time = 1;
743 /* Kernel version 1.3.20 and after are supposed to wait automatically */
750 if (uts.release[0] < '2') do_wait = 1;
752 if (do_wait) sleep (timeval);
753 } /* End Function syncwait */