diff options
| author | Michael Forney <mforney@mforney.org> | 2017-02-27 09:26:59 -0800 |
|---|---|---|
| committer | Michael Forney <mforney@mforney.org> | 2017-02-27 09:28:37 -0800 |
| commit | 2513d3050282a0870eb22c8d394c4b50dca9bd1b (patch) | |
| tree | c2b0c3dde228fab6ad1b03039528a977c65457b1 /src/shutdown.c | |
| parent | 858e99ecdbb611c149434bf0381a2155ec3f3bf4 (diff) | |
Move util -> src
Diffstat (limited to 'src/shutdown.c')
| -rw-r--r-- | src/shutdown.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/shutdown.c b/src/shutdown.c new file mode 100644 index 00000000..06ff3e55 --- /dev/null +++ b/src/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; + } +} |
