1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright (C) 2021 IBM Corp. 3 4 #include <err.h> 5 #include <fcntl.h> 6 #include <getopt.h> 7 #include <libgen.h> 8 #include <limits.h> 9 #include <linux/reboot.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/reboot.h> 13 #include <sys/stat.h> 14 #include <sys/types.h> 15 #include <unistd.h> 16 17 static void process_debug(int sink) 18 { 19 static const char action = 'c'; 20 ssize_t rc; 21 22 sync(); 23 24 if ((rc = write(sink, &action, sizeof(action))) == sizeof(action)) 25 return; 26 27 if (rc == -1) { 28 warn("Failed to execute debug command"); 29 } else { 30 warnx("Failed to execute debug command: %zd", rc); 31 } 32 } 33 34 static void process_reboot(int sink __attribute__((unused))) 35 { 36 ssize_t rc; 37 38 sync(); 39 40 if ((rc = reboot(LINUX_REBOOT_CMD_RESTART))) { 41 if (rc == -1) 42 warn("Failed to reboot BMC"); 43 else 44 warnx("Failed to reboot BMC: %zd", rc); 45 } 46 } 47 48 static int process(int source, int sink) 49 { 50 ssize_t ingress; 51 char command; 52 53 while ((ingress = read(source, &command, sizeof(command))) == sizeof(command)) { 54 switch (command) { 55 case 'D': 56 process_debug(sink); 57 break; 58 case 'R': 59 process_reboot(sink); 60 break; 61 default: 62 warnx("Unexpected command: 0x%02x (%c)", command, command); 63 } 64 } 65 66 if (ingress == -1) 67 warn("Failed to read from source"); 68 69 return ingress; 70 } 71 72 int main(int argc, char * const argv[]) 73 { 74 char devnode[PATH_MAX]; 75 char *devid; 76 int source; 77 int sink; 78 79 while (1) { 80 static struct option long_options[] = { 81 {0, 0, 0, 0}, 82 }; 83 int c; 84 85 c = getopt_long(argc, argv, "", long_options, NULL); 86 if (c == -1) 87 break; 88 } 89 90 source = 0; 91 sink = 1; 92 93 if (optind < argc) { 94 char devpath[PATH_MAX]; 95 96 strncpy(devpath, argv[optind], sizeof(devpath)); 97 devpath[PATH_MAX - 1] = '\0'; 98 devid = basename(devpath); 99 100 strncpy(devnode, "/dev/", sizeof(devnode)); 101 strncat(devnode, devid, sizeof(devnode)); 102 devnode[PATH_MAX - 1] = '\0'; 103 104 if ((source = open(devnode, O_RDONLY)) == -1) 105 err(EXIT_FAILURE, "Failed to open %s", devnode); 106 107 optind++; 108 } 109 110 if (optind < argc) { 111 if ((sink = open(argv[optind], O_WRONLY)) == -1) 112 err(EXIT_FAILURE, "Failed to open %s", argv[optind]); 113 114 optind++; 115 } 116 117 if (optind < argc) 118 err(EXIT_FAILURE, "Found %d unexpected arguments", argc - optind); 119 120 if (process(source, sink) < 0) 121 errx(EXIT_FAILURE, "Failure while processing command stream"); 122 123 return 0; 124 } 125