diff options
| -rw-r--r-- | fixme | 4 | ||||
| -rw-r--r-- | src/automount.c | 2 | ||||
| -rw-r--r-- | src/systemctl.c | 41 | ||||
| -rw-r--r-- | src/util.c | 56 | ||||
| -rw-r--r-- | src/util.h | 3 | 
5 files changed, 95 insertions, 11 deletions
| @@ -69,9 +69,7 @@  * install must understand templates -* shutdown must be able to do wall - -* upstart/initctl fallback in systemctl +* upstart fallback in systemctl  Regularly: diff --git a/src/automount.c b/src/automount.c index 3d85605fb4..262a47da4e 100644 --- a/src/automount.c +++ b/src/automount.c @@ -708,7 +708,7 @@ static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {                  goto fail;          } -        if ((l = loop_read(a->pipe_fd, &packet, sizeof(packet))) != sizeof(packet)) { +        if ((l = loop_read(a->pipe_fd, &packet, sizeof(packet), true)) != sizeof(packet)) {                  log_error("Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");                  goto fail;          } diff --git a/src/systemctl.c b/src/systemctl.c index a41d7ea8bd..ec92504f42 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -28,6 +28,7 @@  #include <sys/ioctl.h>  #include <termios.h>  #include <unistd.h> +#include <fcntl.h>  #include <dbus/dbus.h> @@ -37,6 +38,7 @@  #include "set.h"  #include "utmp-wtmp.h"  #include "special.h" +#include "initreq.h"  static const char *arg_type = NULL;  static bool arg_all = false; @@ -1897,8 +1899,40 @@ static int talk_upstart(DBusConnection *bus) {  }  static int talk_initctl(void) { -        log_error("Talking initctl"); -        return 0; + +        static const char table[_ACTION_MAX] = { +                [ACTION_HALT] =      '0', +                [ACTION_POWEROFF] =  '0', +                [ACTION_REBOOT] =    '6', +                [ACTION_RUNLEVEL2] = '2', +                [ACTION_RUNLEVEL3] = '3', +                [ACTION_RUNLEVEL4] = '4', +                [ACTION_RUNLEVEL5] = '5', +                [ACTION_RESCUE] =    '1' +        }; + +        struct init_request request; +        int r, fd; + +        if (!table[arg_action]) +                return 0; + +        zero(request); +        request.magic = INIT_MAGIC; +        request.sleeptime = 0; +        request.cmd = INIT_CMD_RUNLVL; +        request.runlevel = table[arg_action]; + +        if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) +                return -errno; + +        r = loop_write(fd, &request, sizeof(request), false) != sizeof(request); +        close_nointr_nofail(fd); + +        if (r < 0) +                return errno ? -errno : -EIO; + +        return 1;  }  static int systemctl_main(DBusConnection *bus, int argc, char *argv[]) { @@ -2148,6 +2182,7 @@ int main(int argc, char*argv[]) {          case ACTION_RUNLEVEL5:          case ACTION_RESCUE:          case ACTION_EMERGENCY: +        case ACTION_DEFAULT:                  retval = start_with_fallback(bus) < 0;                  break; @@ -2156,6 +2191,8 @@ int main(int argc, char*argv[]) {                  retval = reload_with_fallback(bus) < 0;                  break; +        case ACTION_INVALID: +        case ACTION_RUNLEVEL:          default:                  assert_not_reached("Unknown action");          } diff --git a/src/util.c b/src/util.c index 0988675f09..2363ea27b2 100644 --- a/src/util.c +++ b/src/util.c @@ -1964,7 +1964,7 @@ int close_pipe(int p[]) {          return a < 0 ? a : b;  } -ssize_t loop_read(int fd, void *buf, size_t nbytes) { +ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {          uint8_t *p;          ssize_t n = 0; @@ -1978,10 +1978,10 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes) {                  if ((k = read(fd, p, nbytes)) <= 0) { -                        if (errno == EINTR) +                        if (k < 0 && errno == EINTR)                                  continue; -                        if (errno == EAGAIN) { +                        if (k < 0 && errno == EAGAIN && do_poll) {                                  struct pollfd pollfd;                                  zero(pollfd); @@ -2012,6 +2012,54 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes) {          return n;  } +ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { +        const uint8_t *p; +        ssize_t n = 0; + +        assert(fd >= 0); +        assert(buf); + +        p = buf; + +        while (nbytes > 0) { +                ssize_t k; + +                if ((k = write(fd, p, nbytes)) <= 0) { + +                        if (k < 0 && errno == EINTR) +                                continue; + +                        if (k < 0 && errno == EAGAIN && do_poll) { +                                struct pollfd pollfd; + +                                zero(pollfd); +                                pollfd.fd = fd; +                                pollfd.events = POLLOUT; + +                                if (poll(&pollfd, 1, -1) < 0) { +                                        if (errno == EINTR) +                                                continue; + +                                        return n > 0 ? n : -errno; +                                } + +                                if (pollfd.revents != POLLOUT) +                                        return n > 0 ? n : -EIO; + +                                continue; +                        } + +                        return n > 0 ? n : (k < 0 ? -errno : 0); +                } + +                p += k; +                nbytes -= k; +                n += k; +        } + +        return n; +} +  int path_is_mount_point(const char *t) {          struct stat a, b;          char *copy; @@ -2182,7 +2230,7 @@ unsigned long long random_ull(void) {          if ((fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY)) < 0)                  goto fallback; -        r = loop_read(fd, &ull, sizeof(ull)); +        r = loop_read(fd, &ull, sizeof(ull), true);          close_nointr_nofail(fd);          if (r != sizeof(ull)) diff --git a/src/util.h b/src/util.h index e371f0b9e5..14c28597ec 100644 --- a/src/util.h +++ b/src/util.h @@ -246,7 +246,8 @@ int sigaction_many(const struct sigaction *sa, ...);  int close_pipe(int p[]); -ssize_t loop_read(int fd, void *buf, size_t nbytes); +ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll); +ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll);  int path_is_mount_point(const char *path); | 
