|
|
@@ -0,0 +1,105 @@
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <fcntl.h>
|
|
|
+#include <string.h>
|
|
|
+#include <errno.h>
|
|
|
+#include <sys/reboot.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <sys/wait.h>
|
|
|
+
|
|
|
+#define DEV_PATH "/dev/power"
|
|
|
+#define BUFFER_SIZE 2
|
|
|
+
|
|
|
+void execute_command(const char *cmd) {
|
|
|
+ pid_t pid = fork();
|
|
|
+ if (pid == -1) {
|
|
|
+ perror("fork failed");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pid == 0) {
|
|
|
+ execl("/bin/sh", "sh", "-c", cmd, NULL);
|
|
|
+ perror("execl failed");
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+ } else {
|
|
|
+ int status;
|
|
|
+ waitpid(pid, &status, 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void reboot_system() {
|
|
|
+ printf("reboot command received, system rebooting...\n");
|
|
|
+ sync();
|
|
|
+ execute_command("reboot");
|
|
|
+}
|
|
|
+
|
|
|
+void shutdown_system() {
|
|
|
+ printf("shutdown command received, system shutting down...\n");
|
|
|
+ sync();
|
|
|
+ execute_command("shutdown -h now");
|
|
|
+}
|
|
|
+
|
|
|
+int main() {
|
|
|
+ int fd;
|
|
|
+ char buf[BUFFER_SIZE];
|
|
|
+ ssize_t nread;
|
|
|
+
|
|
|
+ fd = open(DEV_PATH, O_RDONLY);
|
|
|
+ if (fd == -1) {
|
|
|
+ fprintf(stderr, "cannot open device node %s: %s\n",
|
|
|
+ DEV_PATH, strerror(errno));
|
|
|
+ fprintf(stderr, "please ensure:\n");
|
|
|
+ fprintf(stderr, "1. device node /dev/power exists\n");
|
|
|
+ fprintf(stderr, "2. sufficient permissions to access\n");
|
|
|
+ fprintf(stderr, "3. kernel driver is loaded\n");
|
|
|
+ return EXIT_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("monitoring %s, waiting for commands...\n", DEV_PATH);
|
|
|
+ printf("'r' -> reboot system\n");
|
|
|
+ printf("'p' -> graceful shutdown\n");
|
|
|
+ printf("press Ctrl+C to exit\n\n");
|
|
|
+
|
|
|
+ while (1) {
|
|
|
+ nread = read(fd, buf, sizeof(buf) - 1);
|
|
|
+
|
|
|
+ if (nread == -1) {
|
|
|
+ if (errno == EINTR) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ perror("read device node failed");
|
|
|
+ break;
|
|
|
+ } else if (nread == 0) {
|
|
|
+ printf("device node closed, exiting\n");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ buf[nread] = '\0';
|
|
|
+
|
|
|
+ for (int i = 0; i < nread; i++) {
|
|
|
+ char ch = buf[i];
|
|
|
+
|
|
|
+ switch (ch) {
|
|
|
+ case 'r':
|
|
|
+ case 'R':
|
|
|
+ printf("detected character '%c'\n", ch);
|
|
|
+ reboot_system();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'p':
|
|
|
+ case 'P':
|
|
|
+ printf("detected character '%c'\n", ch);
|
|
|
+ shutdown_system();
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ printf("unknown character: '%c' (ASCII: %d)\n", ch, ch);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ close(fd);
|
|
|
+ return EXIT_SUCCESS;
|
|
|
+}
|