diff options
| author | Michael Forney <mforney@mforney.org> | 2016-12-10 01:09:50 -0800 |
|---|---|---|
| committer | Michael Forney <mforney@mforney.org> | 2016-12-10 12:05:02 -0800 |
| commit | f5b8ae3d94ccc876fd8aa75a8837cae7feccd9da (patch) | |
| tree | ec2c91d781e77597bb2a974f2752101d004cbee8 /util | |
| parent | 80fa7ed8020c775d80654c7704d3d2ffa020fbd1 (diff) | |
Add shutdown utility for rc.shutdown
Diffstat (limited to 'util')
| -rw-r--r-- | util/gen.rc | 7 | ||||
| -rw-r--r-- | util/shutdown.c | 87 |
2 files changed, 93 insertions, 1 deletions
diff --git a/util/gen.rc b/util/gen.rc index 4dcbd052..aa7c175c 100644 --- a/util/gen.rc +++ b/util/gen.rc @@ -1,5 +1,10 @@ set srcdir '$dir' -cflags -Wall -Wextra '-std=c11' -pedantic +cflags\ + -Wall -Wextra -Wno-unused-parameter -pedantic\ + '-std=c11' exe perms-hook perms-hook.c file libexec/oasis/perms-hook '$outdir'/perms-hook 755 + +exe shutdown shutdown.c +file libexec/oasis/shutdown '$outdir'/shutdown 755 diff --git a/util/shutdown.c b/util/shutdown.c new file mode 100644 index 00000000..06ff3e55 --- /dev/null +++ b/util/shutdown.c @@ -0,0 +1,87 @@ +/* See LICENSE file for copyright and license details. */ +#define _XOPEN_SOURCE 700 +#include <errno.h> +#include <mntent.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdnoreturn.h> +#include <string.h> +#include <sys/mount.h> +#include <sys/reboot.h> +#include <unistd.h> + +static noreturn void +usage() +{ + fprintf(stderr, "usage: shutdown [-hpr]\n"); + exit(2); +} + +int +main(int argc, char *argv[]) +{ + FILE *fp; + char **dirs = NULL; + size_t n = 0; + struct mntent *mnt; + int cmd = RB_POWER_OFF; + + while (*++argv && (*argv)[0] == '-' && (*argv)[1]) { + switch ((*argv)[1]) { + case 'h': + cmd = RB_HALT_SYSTEM; + break; + case 'p': + cmd = RB_POWER_OFF; + break; + case 'r': + cmd = RB_AUTOBOOT; + break; + default: + usage(); + } + } + if (*argv) + usage(); + + if (getsid(0) != getpid()) { + fprintf(stderr, "must be session leader\n"); + return 1; + } + + sync(); + kill(-1, SIGTERM); + sleep(2); + kill(-1, SIGKILL); + + sync(); + fp = setmntent("/proc/mounts", "r"); + if (!fp) { + perror("setmntent"); + goto reboot; + } + while ((mnt = getmntent(fp))) { + if (!(dirs = realloc(dirs, ++n * sizeof(*dirs)))) { + perror("realloc"); + break; + } + if (!(dirs[n - 1] = strdup(mnt->mnt_dir))) { + perror("strdup"); + break; + } + } + endmntent(fp); + while (n) { + if (umount(dirs[--n]) < 0) + fprintf(stderr, "umount %s: %s\n", dirs[n], strerror(errno)); + free(dirs[n]); + } + free(dirs); + +reboot: + if (reboot(cmd) < 0) { + perror("reboot"); + return 1; + } +} |
