Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */ 2 : 3 : #include <fcntl.h> 4 : #include <sys/stat.h> 5 : #include <sys/types.h> 6 : 7 : #include "fd-util.h" 8 : #include "initreq.h" 9 : #include "io-util.h" 10 : #include "parse-util.h" 11 : #include "strv.h" 12 : #include "sysv-compat.h" 13 : 14 : #if HAVE_SYSV_COMPAT 15 0 : int talk_initctl(char rl) { 16 : struct init_request request; 17 0 : _cleanup_close_ int fd = -1; 18 : const char *p; 19 : int r; 20 : 21 : /* Try to switch to the specified SysV runlevel. Returns == 0 if the operation does not apply on this 22 : * system, and > 0 on success. */ 23 : 24 0 : if (rl == 0) 25 0 : return 0; 26 : 27 0 : FOREACH_STRING(p, "/run/initctl", "/dev/initctl") { 28 0 : fd = open(p, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); 29 0 : if (fd >= 0 || errno != ENOENT) 30 : break; 31 : } 32 0 : if (fd < 0) { 33 0 : if (errno == ENOENT) 34 0 : return 0; 35 : 36 0 : return log_error_errno(errno, "Failed to open initctl fifo: %m"); 37 : } 38 : 39 0 : request = (struct init_request) { 40 : .magic = INIT_MAGIC, 41 : .sleeptime = 0, 42 : .cmd = INIT_CMD_RUNLVL, 43 : .runlevel = rl, 44 : }; 45 : 46 0 : r = loop_write(fd, &request, sizeof(request), false); 47 0 : if (r < 0) 48 0 : return log_error_errno(r, "Failed to write to %s: %m", p); 49 : 50 0 : return 1; 51 : } 52 : #endif 53 : 54 0 : int parse_shutdown_time_spec(const char *t, usec_t *ret) { 55 0 : assert(t); 56 0 : assert(ret); 57 : 58 0 : if (streq(t, "now")) 59 0 : *ret = 0; 60 0 : else if (!strchr(t, ':')) { 61 : uint64_t u; 62 : 63 0 : if (safe_atou64(t, &u) < 0) 64 0 : return -EINVAL; 65 : 66 0 : *ret = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u; 67 : } else { 68 0 : char *e = NULL; 69 : long hour, minute; 70 0 : struct tm tm = {}; 71 : time_t s; 72 : usec_t n; 73 : 74 0 : errno = 0; 75 0 : hour = strtol(t, &e, 10); 76 0 : if (errno > 0 || *e != ':' || hour < 0 || hour > 23) 77 0 : return -EINVAL; 78 : 79 0 : minute = strtol(e+1, &e, 10); 80 0 : if (errno > 0 || *e != 0 || minute < 0 || minute > 59) 81 0 : return -EINVAL; 82 : 83 0 : n = now(CLOCK_REALTIME); 84 0 : s = (time_t) (n / USEC_PER_SEC); 85 : 86 0 : assert_se(localtime_r(&s, &tm)); 87 : 88 0 : tm.tm_hour = (int) hour; 89 0 : tm.tm_min = (int) minute; 90 0 : tm.tm_sec = 0; 91 : 92 0 : s = mktime(&tm); 93 0 : assert(s >= 0); 94 : 95 0 : *ret = (usec_t) s * USEC_PER_SEC; 96 : 97 0 : while (*ret <= n) 98 0 : *ret += USEC_PER_DAY; 99 : } 100 : 101 0 : return 0; 102 : }