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 int process(int source, int sink) 18 { 19 ssize_t ingress; 20 char command; 21 22 while ((ingress = read(source, &command, sizeof(command))) == sizeof(command)) { 23 static const char action = 'c'; 24 ssize_t rc; 25 26 switch (command) { 27 case 'D': /* Debug */ 28 sync(); 29 30 if ((rc = write(sink, &action, sizeof(action))) == sizeof(action)) 31 continue; 32 33 if (rc == -1) { 34 warn("Failed to execute command 0x%02x (%c)", 35 command, command); 36 } else { 37 warnx("Failed to execute command 0x%02x (%c): %zd", 38 command, command, rc); 39 } 40 break; 41 case 'R': 42 sync(); 43 44 if ((rc = reboot(LINUX_REBOOT_CMD_RESTART))) { 45 if (rc == -1) 46 warn("Failed to reboot BMC"); 47 else 48 warnx("Failed to reboot BMC: %zd", rc); 49 } 50 break; 51 default: 52 warnx("Unexpected command: 0x%02x (%c)", command, command); 53 } 54 } 55 56 if (ingress == -1) 57 warn("Failed to read from source"); 58 59 return ingress; 60 } 61 62 int main(int argc, char * const argv[]) 63 { 64 char devnode[PATH_MAX]; 65 char *devid; 66 int source; 67 int sink; 68 69 while (1) { 70 static struct option long_options[] = { 71 {0, 0, 0, 0}, 72 }; 73 int c; 74 75 c = getopt_long(argc, argv, "", long_options, NULL); 76 if (c == -1) 77 break; 78 } 79 80 source = 0; 81 sink = 1; 82 83 if (optind < argc) { 84 char devpath[PATH_MAX]; 85 86 strncpy(devpath, argv[optind], sizeof(devpath)); 87 devpath[PATH_MAX - 1] = '\0'; 88 devid = basename(devpath); 89 90 strncpy(devnode, "/dev/", sizeof(devnode)); 91 strncat(devnode, devid, sizeof(devnode)); 92 devnode[PATH_MAX - 1] = '\0'; 93 94 if ((source = open(devnode, O_RDONLY)) == -1) 95 err(EXIT_FAILURE, "Failed to open %s", devnode); 96 97 optind++; 98 } 99 100 if (optind < argc) { 101 if ((sink = open(argv[optind], O_WRONLY)) == -1) 102 err(EXIT_FAILURE, "Failed to open %s", argv[optind]); 103 104 optind++; 105 } 106 107 if (optind < argc) 108 err(EXIT_FAILURE, "Found %d unexpected arguments", argc - optind); 109 110 if (process(source, sink) < 0) 111 errx(EXIT_FAILURE, "Failure while processing command stream"); 112 113 return 0; 114 } 115