/* * halt.c: A halt/poweroff/reboot wrapper for Artix Linux * Based on halt.c from void-runit * * Copyright (C) 2018 Muhammad Herdiansyah * (C) 2018 Artix Linux Developers * * To see the license terms of this program, see COPYING */ #include #include #include #include #include #include extern char *__progname; typedef enum {NOOP, REBOOT, POWEROFF, WRITE_ONLY} action_type; typedef enum {OPENRC, RUNIT} initsys; const char* get_init() { char *name = (char *)calloc(1024,sizeof(char)); if(name) { sprintf(name, "/proc/1/cmdline"); FILE *f = fopen(name, "r"); if (f) { size_t size; size = fread(name, sizeof(char), 1024, f); if (size > 0) { if ('\n' == name[size-1]) name[size-1]='\0'; } fclose(f); } } return name; } int main(int argc, char *argv[]) { if (getuid() != 0) errx(1, "You must be root to do that!"); int do_sync = 1; int do_force = 0; int write_only = 0; int opt; action_type action = NOOP; initsys init; const char *initfile = get_init(); char openrc_options[50]; if (strcmp(initfile, "runit") == 0) init = RUNIT; else init = OPENRC; if (strcmp(__progname, "reboot") == 0) action = REBOOT; else if (strcmp(__progname, "halt") == 0 || strcmp(__progname, "poweroff") == 0 || strcmp(__progname, "shutdown") == 0) action = POWEROFF; else warnx("No default behavior, needs to be called as halt/reboot/poweroff/shutdown."); while ((opt = getopt(argc, argv, "dfhinw")) != -1) switch (opt) { case 'n': do_sync = 0; strcat(openrc_options, "--no-write"); break; case 'w': if (init == RUNIT) action = NOOP; else action = WRITE_ONLY; do_sync = 0; break; case 'd': strcat(openrc_options, "--no-write"); break; case 'h': case 'i': break; case 'f': do_force = 1; break; default: errx(1, "Usage: %s [-n] [-f]", __progname); } if (do_sync) sync(); switch (action) { case POWEROFF: if (do_force) reboot(RB_POWER_OFF); else switch (init) { case RUNIT: execl("/usr/bin/runit-init", "init", "0", (char*)0); break; case OPENRC: execl("/usr/bin/openrc-shutdown", "openrc-shutdown", "--poweroff", "now", openrc_options, (char*)0); break; } err(1, "poweroff failed"); break; case REBOOT: if (do_force) reboot(RB_AUTOBOOT); else switch(init) { case RUNIT: execl("/usr/bin/runit-init", "init", "6", (char*)0); break; case OPENRC: execl("/usr/bin/openrc-shutdown", "openrc-shutdown", "--reboot", "now", openrc_options, (char*)0); break; } err(1, "reboot failed"); break; case WRITE_ONLY: /* only applicable for OpenRC */ execl("/usr/bin/openrc-shutdown", "openrc-shutdown", "--write-only", (char*)0); case NOOP: break; } return 0; }