systemctl: add /dev/initctl fallback

This commit is contained in:
Lennart Poettering 2010-06-18 04:44:53 +02:00
parent 55293c152a
commit eb22ac37f3
5 changed files with 95 additions and 11 deletions

4
fixme
View file

@ -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:

View file

@ -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;
}

View file

@ -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");
}

View file

@ -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))

View file

@ -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);