diff options
author | William Hubbs <w.d.hubbs@gmail.com> | 2022-04-06 10:51:55 -0500 |
---|---|---|
committer | William Hubbs <w.d.hubbs@gmail.com> | 2022-04-06 10:51:55 -0500 |
commit | 391d12db48754861b5cecac92ee3321597ee02c1 (patch) | |
tree | b42fad5a31ca342de7b7ecf1fb78784194c1400c /src/rc/openrc-shutdown.c | |
parent | 0efc1b133e4182bd53cde78153bd8b5cc2e99448 (diff) | |
download | openrc-391d12db48754861b5cecac92ee3321597ee02c1.tar.xz |
migrate fully to meson build system
- drop old build system
- move shared include and source files to common directory
- drop "rc-" prefix from shared include and source files
- move executable-specific code to individual directories under src
- adjust top-level .gitignore file for new build system
This closes #489.
Diffstat (limited to 'src/rc/openrc-shutdown.c')
-rw-r--r-- | src/rc/openrc-shutdown.c | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/src/rc/openrc-shutdown.c b/src/rc/openrc-shutdown.c deleted file mode 100644 index 750946f5..00000000 --- a/src/rc/openrc-shutdown.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * openrc-shutdown.c - * If you are using OpenRC's provided init, this will shut down or - * reboot your system. - * - * This is based on code written by James Hammons <jlhamm@acm.org>, so - * I would like to publically thank him for his work. - */ - -/* - * Copyright 2017 The OpenRC Authors. - * See the Authors file at the top-level directory of this distribution and - * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS - * - * This file is part of OpenRC. It is subject to the license terms in - * the LICENSE file found in the top-level directory of this - * distribution and at https://github.com/OpenRC/openrc/blob/HEAD/LICENSE - * This file may not be copied, modified, propagated, or distributed - * except according to the terms contained in the LICENSE file. - */ - -#include <getopt.h> -#include <signal.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/utsname.h> - -#include "broadcast.h" -#include "einfo.h" -#include "rc.h" -#include "helpers.h" -#include "rc-misc.h" -#include "rc-sysvinit.h" -#include "rc-wtmp.h" -#include "_usage.h" - -const char *applet = NULL; -const char *extraopts = NULL; -const char getoptstring[] = "cdDfFHKpRrsw" getoptstring_COMMON; -const struct option longopts[] = { - { "cancel", no_argument, NULL, 'c'}, - { "no-write", no_argument, NULL, 'd'}, - { "dry-run", no_argument, NULL, 'D'}, - { "halt", no_argument, NULL, 'H'}, - { "kexec", no_argument, NULL, 'K'}, - { "poweroff", no_argument, NULL, 'p'}, - { "reexec", no_argument, NULL, 'R'}, - { "reboot", no_argument, NULL, 'r'}, - { "single", no_argument, NULL, 's'}, - { "write-only", no_argument, NULL, 'w'}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "cancel a pending shutdown", - "do not write wtmp record", - "print actions instead of executing them", - "halt the system", - "reboot the system using kexec", - "power off the system", - "re-execute init (use after upgrading)", - "reboot the system", - "single user mode", - "write wtmp boot record and exit", - longopts_help_COMMON -}; -const char *usagestring = "" \ - "Usage: openrc-shutdown -c | --cancel\n" \ - " or: openrc-shutdown -R | --reexec\n" \ - " or: openrc-shutdown -w | --write-only\n" \ - " or: openrc-shutdown -H | --halt time\n" \ - " or: openrc-shutdown -K | --kexec time\n" \ - " or: openrc-shutdown -p | --poweroff time\n" \ - " or: openrc-shutdown -r | --reboot time\n" \ - " or: openrc-shutdown -s | --single time"; -const char *exclusive = "Select one of " - "--cancel, --halt, --kexec, --poweroff, --reexec, --reboot, --single or \n" - "--write-only"; -const char *nologin_file = RC_SYSCONFDIR"/nologin"; -const char *shutdown_pid = "/run/openrc-shutdown.pid"; - -static bool do_cancel = false; -static bool do_dryrun = false; -static bool do_halt = false; -static bool do_kexec = false; -static bool do_poweroff = false; -static bool do_reboot = false; -static bool do_reexec = false; -static bool do_single = false; -static bool do_wtmp = true; -static bool do_wtmp_only = false; - -static void cancel_shutdown(void) -{ - pid_t pid; - - pid = get_pid(applet, shutdown_pid); - if (pid <= 0) - eerrorx("%s: Unable to cancel shutdown", applet); - - if (kill(pid, SIGTERM) != -1) - einfo("%s: shutdown canceled", applet); - else - eerrorx("%s: Unable to cancel shutdown", applet); -} - -/* - * Create the nologin file. - */ -static void create_nologin(int mins) -{ - FILE *fp; - time_t t; - - time(&t); - t += 60 * mins; - - if ((fp = fopen(nologin_file, "w")) != NULL) { - fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t)); - fclose(fp); - } -} - -/* - * Send a command to our init - */ -static void send_cmd(const char *cmd) -{ - FILE *fifo; - size_t ignored; - - if (do_dryrun) { - einfo("Would send %s to init", cmd); - return; - } - if (do_wtmp && (do_halt || do_kexec || do_reboot || do_poweroff)) - log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~"); - fifo = fopen(RC_INIT_FIFO, "w"); - if (!fifo) { - perror("fopen"); - return; - } - - ignored = fwrite(cmd, 1, strlen(cmd), fifo); - if (ignored != strlen(cmd)) - printf("Error writing to init fifo\n"); - fclose(fifo); -} - -/* - * sleep without being interrupted. - * The idea for this code came from sysvinit. - */ -static void sleep_no_interrupt(int seconds) -{ - struct timespec duration; - struct timespec remaining; - - duration.tv_sec = seconds; - duration.tv_nsec = 0; - - while (nanosleep(&duration, &remaining) < 0 && errno == EINTR) - duration = remaining; -} - -static void stop_shutdown(int sig) -{ - (void) sig; - unlink(nologin_file); - unlink(shutdown_pid); -einfo("Shutdown canceled"); -exit(0); -} - -int main(int argc, char **argv) -{ - char *ch = NULL; - int opt; - int cmd_count = 0; - int hour = 0; - int min = 0; - int shutdown_delay = 0; - struct sigaction sa; - struct tm *lt; - time_t tv; - bool need_warning = false; - char *msg = NULL; - char *state = NULL; - char *time_arg = NULL; - FILE *fp; - - applet = basename_c(argv[0]); - while ((opt = getopt_long(argc, argv, getoptstring, - longopts, (int *) 0)) != -1) - { - switch (opt) { - case 'c': - do_cancel = true; - cmd_count++; - break; - case 'd': - do_wtmp = false; - break; - case 'D': - do_dryrun = true; - break; - case 'H': - do_halt = true; - xasprintf(&state, "%s", "halt"); - cmd_count++; - break; - case 'K': - do_kexec = true; - xasprintf(&state, "%s", "reboot"); - cmd_count++; - break; - case 'p': - do_poweroff = true; - xasprintf(&state, "%s", "power off"); - cmd_count++; - break; - case 'R': - do_reexec = true; - cmd_count++; - break; - case 'r': - do_reboot = true; - xasprintf(&state, "%s", "reboot"); - cmd_count++; - break; - case 's': - do_single = true; - xasprintf(&state, "%s", "go down for maintenance"); - cmd_count++; - break; - case 'w': - do_wtmp_only = true; - cmd_count++; - break; - case_RC_COMMON_GETOPT - } - } - if (geteuid() != 0) - eerrorx("%s: you must be root\n", applet); - if (cmd_count != 1) { - eerror("%s: %s\n", applet, exclusive); - usage(EXIT_FAILURE); - } - - if (do_cancel) { - cancel_shutdown(); - exit(EXIT_SUCCESS); - } else if (do_reexec) { - send_cmd("reexec"); - exit(EXIT_SUCCESS); - } else if (do_wtmp_only) { - log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~"); - exit(EXIT_SUCCESS); - } - - if (optind >= argc) { - eerror("%s: No shutdown time specified", applet); - usage(EXIT_FAILURE); - } - time_arg = argv[optind]; - if (*time_arg == '+') - time_arg++; - if (strcasecmp(time_arg, "now") == 0) - strcpy(time_arg, "0"); - for (ch=time_arg; *ch; ch++) - if ((*ch < '0' || *ch > '9') && *ch != ':') { - eerror("%s: invalid time %s", applet, time_arg); - usage(EXIT_FAILURE); - } - if (strchr(time_arg, ':')) { - if ((sscanf(time_arg, "%2d:%2d", &hour, &min) != 2) || - (hour > 23) || (min > 59)) { - eerror("%s: invalid time %s", applet, time_arg); - usage(EXIT_FAILURE); - } - time(&tv); - lt = localtime(&tv); - shutdown_delay = (hour * 60 + min) - (lt->tm_hour * 60 + lt->tm_min); - if (shutdown_delay < 0) - shutdown_delay += 1440; - } else { - shutdown_delay = atoi(time_arg); - } - - fp = fopen(shutdown_pid, "w"); - if (!fp) - eerrorx("%s: fopen `%s': %s", applet, shutdown_pid, strerror(errno)); - fprintf(fp, "%d\n", getpid()); - fclose(fp); - - openlog(applet, LOG_PID, LOG_DAEMON); - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = stop_shutdown; - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - while (shutdown_delay > 0) { - need_warning = false; - if (shutdown_delay > 180) - need_warning = (shutdown_delay % 60 == 0); - else if (shutdown_delay > 60) - need_warning = (shutdown_delay % 30 == 0); - else if (shutdown_delay > 10) - need_warning = (shutdown_delay % 15 == 0); - else - need_warning = true; - if (shutdown_delay <= 5) - create_nologin(shutdown_delay); - if (need_warning) { - xasprintf(&msg, "\rThe system will %s in %d minutes\r\n", - state, shutdown_delay); - broadcast(msg); - free(msg); - } - sleep_no_interrupt(60); - shutdown_delay--; - } - xasprintf(&msg, "\rThe system will %s now\r\n", state); - broadcast(msg); - syslog(LOG_NOTICE, "The system will %s now", state); - unlink(nologin_file); - unlink(shutdown_pid); - if (do_halt) { - if (exists("/run/initctl")) { - sysvinit_setenv("INIT_HALT", "HALT"); - sysvinit_runlevel('0'); - } else - send_cmd("halt"); - } else if (do_kexec) - send_cmd("kexec"); - else if (do_poweroff) { - if (exists("/run/initctl")) { - sysvinit_setenv("INIT_HALT", "POWEROFF"); - sysvinit_runlevel('0'); - } else - send_cmd("poweroff"); - } else if (do_reboot) { - if (exists("/run/initctl")) - sysvinit_runlevel('6'); - else - send_cmd("reboot"); - } else if (do_single) { - if (exists("/run/initctl")) - sysvinit_runlevel('S'); - else - send_cmd("single"); - } - return 0; -} |