📄 shutdown.c
字号:
*/void shutdown(char *halttype){ char *args[8]; int argp = 0; int do_halt = (down_level[0] == '0'); /* Warn for the last time */ warn(0); if (dontshut) { hardsleep(1); stopit(0); } openlog("shutdown", LOG_PID, LOG_USER); if (do_halt) syslog(LOG_NOTICE, "shutting down for system halt"); else syslog(LOG_NOTICE, "shutting down for system reboot"); closelog(); /* See if we have to do it ourself. */ if (doself) fastdown(); /* Create the arguments for init. */ args[argp++] = INIT; if (sltime) { args[argp++] = "-t"; args[argp++] = sltime; } args[argp++] = down_level; args[argp] = (char *)NULL; unlink(SDPID); unlink(NOLOGIN); /* Now execute init to change runlevel. */ sync(); init_setenv("INIT_HALT", halttype); execv(INIT, args); /* Oops - failed. */ fprintf(stderr, "\rshutdown: cannot execute %s\r\n", INIT); unlink(FASTBOOT); unlink(FORCEFSCK); init_setenv("INIT_HALT", NULL); openlog("shutdown", LOG_PID, LOG_USER); syslog(LOG_NOTICE, "shutdown failed"); closelog(); exit(1);}/* * returns if a warning is to be sent for wt */static int needwarning(int wt){ int ret; if (wt < 10) ret = 1; else if (wt < 60) ret = (wt % 15 == 0); else if (wt < 180) ret = (wt % 30 == 0); else ret = (wt % 60 == 0); return ret;}/* * Main program. * Process the options and do the final countdown. */int main(int argc, char **argv){ FILE *fp; extern int getopt(); extern int optind; struct sigaction sa; struct tm *lt; struct stat st; struct utmp *ut; time_t t; uid_t realuid; char *halttype; char *downusers[32]; char buf[128]; char term[UT_LINESIZE + 6]; char *sp; char *when = NULL; int c, i, wt; int hours, mins; int didnolog = 0; int cancel = 0; int useacl = 0; int pid = 0; int user_ok = 0; /* We can be installed setuid root (executable for a special group) */ realuid = getuid(); setuid(geteuid()); if (getuid() != 0) { fprintf(stderr, "shutdown: you must be root to do that!\n"); exit(1); } strcpy(down_level, "1"); halttype = NULL; /* Process the options. */ while((c = getopt(argc, argv, "HPacqkrhnfFyt:g:i:")) != EOF) { switch(c) { case 'H': halttype = "HALT"; break; case 'P': halttype = "POWERDOWN"; break; case 'a': /* Access control. */ useacl = 1; break; case 'c': /* Cancel an already running shutdown. */ cancel = 1; break; case 'k': /* Don't really shutdown, only warn.*/ dontshut = 1; break; case 'r': /* Automatic reboot */ down_level[0] = '6'; break; case 'h': /* Halt after shutdown */ down_level[0] = '0'; break; case 'f': /* Don't perform fsck after next boot */ fastboot = 1; break; case 'F': /* Force fsck after next boot */ forcefsck = 1; break; case 'n': /* Don't switch runlevels. */ doself = 1; break; case 't': /* Delay between TERM and KILL */ sltime = optarg; break; case 'y': /* Ignored for sysV compatibility */ break; case 'g': /* sysv style to specify time. */ when = optarg; break; case 'i': /* Level to go to. */ if (!strchr("0156aAbBcCsS", optarg[0])) { fprintf(stderr, "shutdown: `%s': bad runlevel\n", optarg); exit(1); } down_level[0] = optarg[0]; break; default: usage(); break; } } /* Do we need to use the shutdown.allow file ? */ if (useacl && (fp = fopen(SDALLOW, "r")) != NULL) { /* Read /etc/shutdown.allow. */ i = 0; while(fgets(buf, 128, fp)) { if (buf[0] == '#' || buf[0] == '\n') continue; if (i > 31) continue; for(sp = buf; *sp; sp++) if (*sp == '\n') *sp = 0; downusers[i++] = strdup(buf); } if (i < 32) downusers[i] = 0; fclose(fp); /* Now walk through /var/run/utmp to find logged in users. */ while(!user_ok && (ut = getutent()) != NULL) { /* See if this is a user process on a VC. */ if (ut->ut_type != USER_PROCESS) continue; sprintf(term, "/dev/%.*s", UT_LINESIZE, ut->ut_line); if (stat(term, &st) < 0) continue;#ifdef major /* glibc */ if (major(st.st_rdev) != 4 || minor(st.st_rdev) > 63) continue;#else if ((st.st_rdev & 0xFFC0) != 0x0400) continue;#endif /* Root is always OK. */ if (strcmp(ut->ut_user, "root") == 0) { user_ok++; break; } /* See if this is an allowed user. */ for(i = 0; i < 32 && downusers[i]; i++) if (!strncmp(downusers[i], ut->ut_user, UT_NAMESIZE)) { user_ok++; break; } } endutent(); /* See if user was allowed. */ if (!user_ok) { if ((fp = fopen(CONSOLE, "w")) != NULL) { fprintf(fp, "\rshutdown: no authorized users " "logged in.\r\n"); fclose(fp); } exit(1); } } /* Read pid of running shutdown from a file */ if ((fp = fopen(SDPID, "r")) != NULL) { fscanf(fp, "%d", &pid); fclose(fp); } /* Read remaining words, skip time if needed. */ message[0] = 0; for(c = optind + (!cancel && !when); c < argc; c++) { if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN) break; strcat(message, argv[c]); strcat(message, " "); } if (message[0]) strcat(message, "\r\n"); /* See if we want to run or cancel. */ if (cancel) { if (pid <= 0) { fprintf(stderr, "shutdown: cannot find pid " "of running shutdown.\n"); exit(1); } init_setenv("INIT_HALT", NULL); if (kill(pid, SIGINT) < 0) { fprintf(stderr, "shutdown: not running.\n"); exit(1); } if (message[0]) wall(message, 1, 0); exit(0); } /* Check syntax. */ if (when == NULL) { if (optind == argc) usage(); when = argv[optind++]; } /* See if we are already running. */ if (pid > 0 && kill(pid, 0) == 0) { fprintf(stderr, "\rshutdown: already running.\r\n"); exit(1); } /* Extra check. */ if (doself && down_level[0] != '0' && down_level[0] != '6') { fprintf(stderr, "shutdown: can use \"-n\" for halt or reboot only.\r\n"); exit(1); } /* Tell users what we're gonna do. */ switch(down_level[0]) { case '0': strcpy(newstate, "for system halt"); break; case '6': strcpy(newstate, "for reboot"); break; case '1': strcpy(newstate, "to maintenance mode"); break; default: sprintf(newstate, "to runlevel %s", down_level); break; } /* Create a new PID file. */ unlink(SDPID); umask(022); if ((fp = fopen(SDPID, "w")) != NULL) { fprintf(fp, "%d\n", getpid()); fclose(fp); } else if (errno != EROFS) fprintf(stderr, "shutdown: warning: cannot open %s\n", SDPID); /* * Catch some common signals. */ signal(SIGQUIT, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); memset(&sa, 0, sizeof(sa)); sa.sa_handler = stopit; sigaction(SIGINT, &sa, NULL); /* Go to the root directory */ chdir("/"); if (fastboot) close(open(FASTBOOT, O_CREAT | O_RDWR, 0644)); if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644)); /* Alias now and take care of old '+mins' notation. */ if (!strcmp(when, "now")) strcpy(when, "0"); if (when[0] == '+') when++; /* Decode shutdown time. */ for (sp = when; *sp; sp++) { if (*sp != ':' && (*sp < '0' || *sp > '9')) usage(); } if (strchr(when, ':') == NULL) { /* Time in minutes. */ wt = atoi(when); if (wt == 0 && when[0] != '0') usage(); } else { /* Time in hh:mm format. */ if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage(); if (hours > 23 || mins > 59) usage(); time(&t); lt = localtime(&t); wt = (60*hours + mins) - (60*lt->tm_hour + lt->tm_min); if (wt < 0) wt += 1440; } /* Shutdown NOW if time == 0 */ if (wt == 0) shutdown(halttype); /* Give warnings on regular intervals and finally shutdown. */ if (wt < 15 && !needwarning(wt)) warn(wt); while(wt) { if (wt <= 5 && !didnolog) { donologin(wt); didnolog++; } if (needwarning(wt)) warn(wt); hardsleep(60); wt--; } shutdown(halttype); return 0; /* Never happens */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -