#include #include #include #include #include #include #include #include #include #include extern char *__progname; typedef enum {NOOP, HALT, REBOOT, POWEROFF} action_type; #ifndef OUR_WTMP #define OUR_WTMP "/var/log/wtmp" #endif void write_wtmp(int boot) { int fd; if ((fd = open(OUR_WTMP, O_WRONLY|O_APPEND)) < 0) return; struct utmp utmp = {0}; struct utsname uname_buf; struct timeval tv; gettimeofday(&tv, 0); utmp.ut_tv.tv_sec = tv.tv_sec; utmp.ut_tv.tv_usec = tv.tv_usec; utmp.ut_type = boot ? BOOT_TIME : RUN_LVL; strncpy(utmp.ut_name, boot ? "reboot" : "shutdown", sizeof(utmp.ut_name)); strncpy(utmp.ut_id , "~~", sizeof(utmp.ut_id)); strncpy(utmp.ut_line, boot ? "~" : "~~", sizeof(utmp.ut_line)); if (uname(&uname_buf) == 0) strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host)); write(fd, (char *)&utmp, sizeof(utmp)); close(fd); } int main(int argc, char *argv[]) { int do_sync = 1; int do_force = 0; int do_wtmp = 1; int opt; action_type action = NOOP; if (strcmp(__progname, "halt") == 0) action = HALT; else if (strcmp(__progname, "reboot") == 0) action = REBOOT; else if (strcmp(__progname, "poweroff") == 0) action = POWEROFF; else warnx("no default behavior, needs to be called as halt/reboot/poweroff."); while ((opt = getopt(argc, argv, "dfhinwB")) != -1) switch (opt) { case 'n': do_sync = 0; break; case 'w': action = NOOP; do_sync = 0; break; case 'd': do_wtmp = 0; break; case 'h': case 'i': /* silently ignored. */ break; case 'f': do_force = 1; break; case 'B': write_wtmp(1); return 0; default: errx(1, "Usage: %s [-n] [-f] [-d] [-w] [-B]", __progname); } if (do_wtmp) write_wtmp(0); if (do_sync) sync(); switch (action) { case HALT: if (do_force) reboot(RB_HALT_SYSTEM); else execl("/bin/runit-init", "init", "0", (char*)0); err(1, "halt failed"); break; case POWEROFF: if (do_force) reboot(RB_POWER_OFF); else execl("/bin/runit-init", "init", "0", (char*)0); err(1, "poweroff failed"); break; case REBOOT: if (do_force) reboot(RB_AUTOBOOT); else execl("/bin/runit-init", "init", "6", (char*)0); err(1, "reboot failed"); break; case NOOP: break; } return 0; }