1 /* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1980, 1986, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)reboot.c 8.1 (Berkeley) 06/05/93"; 16 #endif /* not lint */ 17 18 #include <sys/reboot.h> 19 #include <signal.h> 20 #include <pwd.h> 21 #include <errno.h> 22 #include <syslog.h> 23 #include <unistd.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 void err __P((const char *fmt, ...)); 29 void usage __P((void)); 30 31 int dohalt; 32 33 int 34 main(argc, argv) 35 int argc; 36 char *argv[]; 37 { 38 register int i; 39 struct passwd *pw; 40 int ch, howto, lflag, nflag, qflag, sverrno; 41 char *p, *user; 42 43 if (!strcmp((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) { 44 dohalt = 1; 45 howto = RB_HALT; 46 } else 47 howto = 0; 48 lflag = nflag = qflag = 0; 49 while ((ch = getopt(argc, argv, "lnq")) != EOF) 50 switch(ch) { 51 case 'l': /* Undocumented; used by shutdown. */ 52 lflag = 1; 53 break; 54 case 'n': 55 nflag = 1; 56 howto |= RB_NOSYNC; 57 break; 58 case 'q': 59 qflag = 1; 60 break; 61 case '?': 62 default: 63 usage(); 64 } 65 argc -= optind; 66 argv += optind; 67 68 if (geteuid()) 69 err("%s", strerror(EPERM)); 70 71 if (qflag) { 72 reboot(howto); 73 err("%s", strerror(errno)); 74 } 75 76 /* Log the reboot. */ 77 if (!lflag) { 78 if ((user = getlogin()) == NULL) 79 user = (pw = getpwuid(getuid())) ? 80 pw->pw_name : "???"; 81 if (dohalt) { 82 openlog("halt", 0, LOG_AUTH | LOG_CONS); 83 syslog(LOG_CRIT, "halted by %s", user); 84 } else { 85 openlog("reboot", 0, LOG_AUTH | LOG_CONS); 86 syslog(LOG_CRIT, "rebooted by %s", user); 87 } 88 } 89 logwtmp("~", "shutdown", ""); 90 91 /* 92 * Do a sync early on, so disks start transfers while we're off 93 * killing processes. Don't worry about writes done before the 94 * processes die, the reboot system call syncs the disks. 95 */ 96 if (!nflag) 97 sync(); 98 99 /* Just stop init -- if we fail, we'll restart it. */ 100 if (kill(1, SIGTSTP) == -1) 101 err("SIGTSTP init: %s", strerror(errno)); 102 103 /* Ignore the SIGHUP we get when our parent shell dies. */ 104 (void)signal(SIGHUP, SIG_IGN); 105 106 /* Send a SIGTERM first, a chance to save the buffers. */ 107 if (kill(-1, SIGTERM) == -1) 108 err("SIGTERM processes: %s", strerror(errno)); 109 110 /* 111 * After the processes receive the signal, start the rest of the 112 * buffers on their way. Wait 5 seconds between the SIGTERM and 113 * the SIGKILL to give everybody a chance. 114 */ 115 sleep(2); 116 if (!nflag) 117 sync(); 118 sleep(3); 119 120 for (i = 1;; ++i) { 121 if (kill(-1, SIGKILL) == -1) { 122 if (errno == ESRCH) 123 break; 124 goto restart; 125 } 126 if (i > 5) { 127 (void)fprintf(stderr, 128 "WARNING: some process(es) wouldn't die\n"); 129 break; 130 } 131 (void)sleep(2 * i); 132 } 133 134 reboot(howto); 135 /* FALLTHROUGH */ 136 137 restart: 138 sverrno = errno; 139 err("%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "", 140 strerror(sverrno)); 141 /* NOTREACHED */ 142 } 143 144 void 145 usage() 146 { 147 (void)fprintf(stderr, "usage: %s [-nq]\n", dohalt ? "halt" : "reboot"); 148 exit(1); 149 } 150 151 #if __STDC__ 152 #include <stdarg.h> 153 #else 154 #include <varargs.h> 155 #endif 156 157 void 158 #if __STDC__ 159 err(const char *fmt, ...) 160 #else 161 err(fmt, va_alist) 162 char *fmt; 163 va_dcl 164 #endif 165 { 166 va_list ap; 167 #if __STDC__ 168 va_start(ap, fmt); 169 #else 170 va_start(ap); 171 #endif 172 (void)fprintf(stderr, "%s: ", dohalt ? "halt" : "reboot"); 173 (void)vfprintf(stderr, fmt, ap); 174 va_end(ap); 175 (void)fprintf(stderr, "\n"); 176 exit(1); 177 /* NOTREACHED */ 178 } 179