aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaranm@exherbo.org> 2008-01-15 16:59:58 +0000
committerAvatar Ciaran McCreesh <ciaranm@exherbo.org> 2008-01-15 16:59:58 +0000
commitcf5ba5870387c1c28880848260a4312fee4f4888 (patch)
tree193b9bd99f4510c4d59d3d50bca5c5c08804f11c
downloadannie-cf5ba5870387c1c28880848260a4312fee4f4888.tar.gz
annie-cf5ba5870387c1c28880848260a4312fee4f4888.tar.xz
Initial import of annie
-rw-r--r--Makefile11
-rw-r--r--halt.c91
2 files changed, 102 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ef45702
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+all : halt
+
+halt.o : halt.c
+ $(CC) $(CFLAGS) -c -std=c99 -W -Wall -D_GNU_SOURCE halt.c -o halt.o
+
+halt : halt.o
+ $(CC) $(CFLAGS) -o halt halt.o
+
+clean :
+ rm -f *~ halt *.o
+
diff --git a/halt.c b/halt.c
new file mode 100644
index 0000000..da2fa06
--- /dev/null
+++ b/halt.c
@@ -0,0 +1,91 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/reboot.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <signal.h>
+
+bool is_pid(const char * const c)
+{
+ for (const char * q = c ; *q ; ++q)
+ if (*q < '0' || *q > '9')
+ return false;
+
+ return true;
+}
+
+void kill_everybody(const int sig)
+{
+ DIR * const dirh = opendir("/proc");
+ if (! dirh)
+ {
+ perror("Couldn't opendir /proc");
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "Sending signal %d to: ", sig);
+ const struct dirent * dp;
+ while (((dp = readdir(dirh))))
+ {
+ if (! is_pid(dp->d_name))
+ continue;
+
+ const pid_t pid = atoi(dp->d_name);
+ if (1 == pid || getpid() == pid)
+ continue;
+
+ fprintf(stderr, "%d ", pid);
+ kill(pid, sig);
+ }
+ closedir(dirh);
+ fprintf(stderr, "\n");
+}
+
+void remount_root_ro()
+{
+ fprintf(stderr, "Remounting / read-only");
+ if (0 != mount("none", "/", "none", MS_RDONLY | MS_REMOUNT, ""))
+ {
+ perror("Couldn't remount / read-only");
+ exit(EXIT_FAILURE);
+ }
+}
+
+void sync_filesystems()
+{
+ fprintf(stderr, "Syncing filesystems");
+ sync();
+ sleep(1);
+ sync();
+}
+
+void power_off()
+{
+ fprintf(stderr, "Rebooting");
+ if (0 != reboot(RB_POWER_OFF))
+ {
+ perror("Couldn't call reboot syscall");
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc __attribute__((unused)), char * argv [] __attribute__((unused)))
+{
+ kill_everybody(SIGTERM);
+ sleep(1);
+ kill_everybody(SIGKILL);
+ sleep(1);
+ remount_root_ro();
+ sync_filesystems();
+ power_off();
+ return EXIT_SUCCESS;
+}
+