diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-11-30 20:01:24 +0100 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2013-11-30 20:04:11 +0100 |
commit | bf594040705caa900cb893c2760a2ec9d50d516b (patch) | |
tree | 7344b5782f0235cb3d968673ded5c88943ad43cf | |
parent | 2a15b495f7f9e3b7df58240e0d7bb305836ca7ac (diff) |
WELCOMED-TODO
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 8 | ||||
-rw-r--r-- | src/welcome/welcomed-greeter-proto.c | 117 | ||||
-rw-r--r-- | src/welcome/welcomed-greeter-slave.c | 83 | ||||
-rw-r--r-- | src/welcome/welcomed-greeter.c | 93 | ||||
-rw-r--r-- | src/welcome/welcomed-greeter.h | 72 | ||||
-rw-r--r-- | src/welcome/welcomed-proto.c | 265 | ||||
-rw-r--r-- | src/welcome/welcomed-proto.h | 124 | ||||
-rw-r--r-- | src/welcome/welcomed-session.c | 9 | ||||
-rw-r--r-- | src/welcome/welcomed.c | 66 | ||||
-rw-r--r-- | src/welcome/welcomed.h | 26 |
11 files changed, 543 insertions, 321 deletions
diff --git a/.gitignore b/.gitignore index 4950d9656..2331d9a6b 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,7 @@ /systemd-update-utmp /systemd-user-sessions /systemd-vconsole-setup +/systemd-welcomed /tags /test-boot-timestamp /test-bus-chat diff --git a/Makefile.am b/Makefile.am index 9aa151537..670ae2884 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3979,19 +3979,21 @@ systemd_welcomed_SOURCES = \ src/welcome/welcomed.c \ src/welcome/welcomed-greeter.h \ src/welcome/welcomed-greeter.c \ - src/welcome/welcomed-greeter-proto.c \ src/welcome/welcomed-greeter-screen.c \ src/welcome/welcomed-greeter-slave.c \ src/welcome/welcomed-greeter-view.c \ + src/welcome/welcomed-proto.h \ + src/welcome/welcomed-proto.c \ src/welcome/welcomed-session.c systemd_welcomed_CFLAGS = \ $(AM_CFLAGS) systemd_welcomed_LDADD = \ - libsystemd-bus.la \ - libsystemd-daemon.la \ + libsystemd-bus-internal.la \ + libsystemd-daemon-internal.la \ libsystemd-gfx.la \ + libsystemd-login-internal.la \ libsystemd-shared.la endif diff --git a/src/welcome/welcomed-greeter-proto.c b/src/welcome/welcomed-greeter-proto.c deleted file mode 100644 index 2353c3343..000000000 --- a/src/welcome/welcomed-greeter-proto.c +++ /dev/null @@ -1,117 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 David Herrmann <dh.herrmann@gmail.com> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <errno.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> - -#include "log.h" -#include "macro.h" -#include "sd-event.h" -#include "util.h" -#include "welcomed.h" -#include "welcomed-greeter.h" - -static void greeter_proto_push(GreeterProto *p, GreeterMessage *msg) { - msg->next = NULL; - *p->out_last = msg; - p->out_last = &msg->next; - - msg->next = *p->out_last; - msg->next = p->out_last; - p->out_last = -} - -static GreeterMessage *greeter_proto_pop(GreeterProto *p) { - GreeterMessage *msg; - - msg = p->out_first; - if (!msg) - return NULL; - - p->out_first = msg->next; - if (!msg->next) - p->out_last = &p->out_first; - - return msg; -} - -static int greeter_proto_io_fn(sd_event_source *src, int fd, uint32_t mask, void *data) { - return 0; -} - -static int greeter_proto_idle_fn(sd_event_source *src, void *data) { - return 0; -} - -int greeter_proto_new(int comm, - sd_event *event, - greeter_proto_t proto_fn, - void *data, - GreeterProto **out) { - GreeterProto *p; - int r; - - p = calloc(1, sizeof(*p)); - if (!p) - goto oom; - - p->out_last = &p->out_first; - p->comm = comm; - p->event = sd_event_ref(event); - p->proto_fn = proto_fn; - p->data = data; - - r = sd_event_add_io(event, - comm, - EPOLLHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLET, - greeter_proto_io_fn, - p, - &p->comm_source); - if (r < 0) { - log_error("proto: cannot add comm-source: %d", r); - goto error; - } - - *out = p; - return 0; - -oom: - r = log_oom(); -error: - greeter_proto_free(p); - return r; -} - -void greeter_proto_free(GreeterProto *p) { - if (!p) - return; - - sd_event_source_unref(p->comm_source); - sd_event_unref(p->event); - free(p); -} - -void greeter_proto_send(GreeterProto *p, GreeterMessage *msg) { - msg->next = *p->out_last; - *p->out_last = msg; -} diff --git a/src/welcome/welcomed-greeter-slave.c b/src/welcome/welcomed-greeter-slave.c index 315719afa..afe161a9b 100644 --- a/src/welcome/welcomed-greeter-slave.c +++ b/src/welcome/welcomed-greeter-slave.c @@ -29,10 +29,17 @@ #include "macro.h" #include "sd-event.h" #include "util.h" -#include "welcomed.h" #include "welcomed-greeter.h" +#include "welcomed-proto.h" -static void greeter_slave_proto_fn(GreeterProto *p, GreeterMessage *msg, void *data) { +static void greeter_slave_proto_fn(Proto *p, ProtoMessage *msg, void *data) { + GreeterSlave *s = data; + + if (!msg) { + log_notice("greeter: HUP on parent, exiting.."); + sd_event_request_quit(s->event); + return; + } } static int greeter_slave_signal_fn(sd_event_source *src, const struct signalfd_siginfo *ssi, void *data) { @@ -44,19 +51,7 @@ static int greeter_slave_signal_fn(sd_event_source *src, const struct signalfd_s return 0; } -static void greeter_slave_free(GreeterSlave *s) { - unsigned int i; - - if (!s) - return; - - for (i = 0; s->sigs[i]; ++i) - sd_event_source_unref(s->sigs[i]); - sd_event_unref(s->event); - free(s); -} - -static int greeter_slave_new(const char *seat, int comm, GreeterSlave **out) { +int greeter_slave_new(const char *seat, int comm, GreeterSlave **out) { static const int sigs[] = { SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGPIPE, SIGCHLD, 0 }; @@ -92,7 +87,7 @@ static int greeter_slave_new(const char *seat, int comm, GreeterSlave **out) { } sigprocmask(SIG_BLOCK, &mask, NULL); - r = greeter_proto_new(comm, s->event, greeter_slave_proto_fn, s, &s->proto); + r = proto_new(comm, s->event, greeter_slave_proto_fn, s, &s->proto); if (r < 0) goto error; @@ -106,50 +101,22 @@ error: return r; } -static int greeter_slave_run(GreeterSlave *s) { - return sd_event_loop(s->event); -} - -int greeter_slave_spawn(const char *seat) { - int r, comm[2]; - GreeterSlave *s; - - r = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, comm); - if (r < 0) { - r = -errno; - log_error("cannot create comm-sockets: %m"); - return r; - } - - r = fork(); - if (r < 0) { - r = -errno; - log_error("cannot fork greeter process: %m"); - close_nointr_nofail(comm[0]); - close_nointr_nofail(comm[1]); - return r; - } else if (!r) { - close_nointr_nofail(comm[0]); - - /* TODO: do we wanna call log_close()/log_open() here? - * Currently, we share the log with our parent. Not sure - * whether that works with all the log backends. */ - - r = greeter_slave_new(seat, comm[1], &s); - if (r < 0) { - log_error("greeter: setup failed: %d", r); - } else { - r = greeter_slave_run(s); - if (r < 0) - log_error("greeter: runtime failure: %d", r); +void greeter_slave_free(GreeterSlave *s) { + unsigned int i; - greeter_slave_free(s); - } + if (!s) + return; - close_nointr_nofail(comm[1]); - _exit(r); + if (s->proto) { + proto_flush(s->proto); + proto_free(s->proto); } + for (i = 0; s->sigs[i]; ++i) + sd_event_source_unref(s->sigs[i]); + sd_event_unref(s->event); + free(s); +} - close_nointr_nofail(comm[1]); - return comm[0]; +int greeter_slave_run(GreeterSlave *s) { + return sd_event_loop(s->event); } diff --git a/src/welcome/welcomed-greeter.c b/src/welcome/welcomed-greeter.c index 27c8721f3..daba97e26 100644 --- a/src/welcome/welcomed-greeter.c +++ b/src/welcome/welcomed-greeter.c @@ -25,6 +25,8 @@ #include <stdbool.h> #include <stdlib.h> #include <string.h> +#include <sys/socket.h> +#include <sys/types.h> #include <unistd.h> #include "def.h" @@ -36,52 +38,47 @@ #include "welcomed.h" #include "welcomed-greeter.h" -static void greeter_proto_fn(GreeterProto *p, GreeterMessage *msg, void *data) { -} - -int greeter_new(int comm, Manager *m, Greeter **out) { - Greeter *g; - int r; - - g = calloc(1, sizeof(*g)); - if (!g) - goto oom; - - g->m = m; - - r = greeter_proto_new(comm, m->event, greeter_proto_fn, g, &g->proto); - if (r < 0) - goto error; - - *out = g; - return 0; - -oom: - r = log_oom(); -error: - greeter_free(g); - return r; -} - -void greeter_free(Greeter *g) { - if (!g) - return; - - greeter_stop(g); - greeter_proto_free(g->proto); - free(g); -} - -void greeter_start(Greeter *g, const char *auto_session, const char *auto_user) { - if (g->running) - return; - - g->running = 1; -} - -void greeter_stop(Greeter *g) { - if (!g->running) - return; - - g->running = 0; +int greeter_spawn(const char *seat) { + int r, comm[2]; + GreeterSlave *s; + + /* we use MSG_DONTWAIT if required, so no SOCK_NONBLOCK here */ + r = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, comm); + if (r < 0) { + r = -errno; + log_error("cannot create comm-sockets: %m"); + return r; + } + + r = fork(); + if (r < 0) { + r = -errno; + log_error("cannot fork greeter process: %m"); + close_nointr_nofail(comm[0]); + close_nointr_nofail(comm[1]); + return r; + } else if (!r) { + close_nointr_nofail(comm[0]); + + /* TODO: do we wanna call log_close()/log_open() here? + * Currently, we share the log with our parent. Not sure + * whether that works with all the log backends. */ + + r = greeter_slave_new(seat, comm[1], &s); + if (r < 0) { + log_error("greeter: setup failed: %d", r); + } else { + r = greeter_slave_run(s); + if (r < 0) + log_error("greeter: runtime failure: %d", r); + + greeter_slave_free(s); + } + + close_nointr_nofail(comm[1]); + _exit(r); + } + + close_nointr_nofail(comm[1]); + return comm[0]; } diff --git a/src/welcome/welcomed-greeter.h b/src/welcome/welcomed-greeter.h index 599e0049a..a86f3e6a1 100644 --- a/src/welcome/welcomed-greeter.h +++ b/src/welcome/welcomed-greeter.h @@ -28,32 +28,16 @@ #include "list.h" #include "sd-event.h" #include "sd-gfx.h" +#include "welcomed-proto.h" -#define GREETER_ENTRY_MAX 512 - -typedef struct GreeterMessage GreeterMessage; -typedef struct GreeterProto GreeterProto; typedef struct GreeterSlave GreeterSlave; typedef struct GreeterView GreeterView; typedef struct GreeterScreen GreeterScreen; -typedef void (*greeter_proto_t) (GreeterProto *p, GreeterMessage *m, void *data); - -struct GreeterProto { - int comm; - sd_event *event; - sd_event_source *comm_source; - greeter_proto_t proto_fn; - void *data; - - GreeterMessage *out_first; - GreeterMessage **out_last; -}; - struct GreeterSlave { sd_event *event; sd_event_source *sigs[_NSIG]; - GreeterProto *proto; + Proto *proto; const char *seat; }; @@ -63,13 +47,13 @@ struct GreeterView { unsigned long age_cnt; - char username[GREETER_ENTRY_MAX]; + char username[PROTO_ENTRY_MAX]; unsigned long username_age; - char password[GREETER_ENTRY_MAX]; + char password[PROTO_ENTRY_MAX]; unsigned long password_age; - char message[GREETER_ENTRY_MAX]; + char message[PROTO_ENTRY_MAX]; unsigned long message_age; }; @@ -80,51 +64,11 @@ struct GreeterScreen { unsigned long fb_age[2]; }; -/* greeter protocol */ - -enum { - GREETER_START, - GREETER_STOP, - GREETER_LOGIN, - GREETER_SHOW_MESSAGE, -}; - -enum { - GREETER_MSG_SUCCESS, - GREETER_MSG_INTERNAL_ERROR, - GREETER_MSG_INVALID_USERNAME, - GREETER_MSG_WRONG_PASSWORD, -}; - -struct GreeterMessage { - GreeterMessage *next; - unsigned int type; - - union { - struct GreeterMessageLogin { - char name[GREETER_ENTRY_MAX]; - char password[GREETER_ENTRY_MAX]; - } login; - struct GreeterMessageShowMessage { - unsigned int msgid; - } show_message; - }; -}; - -/* greeter proto */ - -int greeter_proto_new(int comm, - sd_event *event, - greeter_proto_t proto_fn, - void *data, - GreeterProto **out); -void greeter_proto_free(GreeterProto *p); - -void greeter_proto_send(GreeterProto *p, GreeterMessage *msg); - /* greeter slave */ -int greeter_slave_spawn(const char *seat); +int greeter_slave_new(const char *seat, int comm, GreeterSlave **out); +void greeter_slave_free(GreeterSlave *s); +int greeter_slave_run(GreeterSlave *s); /* greeter view */ diff --git a/src/welcome/welcomed-proto.c b/src/welcome/welcomed-proto.c new file mode 100644 index 000000000..0e2f16298 --- /dev/null +++ b/src/welcome/welcomed-proto.c @@ -0,0 +1,265 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 David Herrmann <dh.herrmann@gmail.com> + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/types.h> + +#include "log.h" +#include "macro.h" +#include "sd-event.h" +#include "util.h" +#include "welcomed.h" +#include "welcomed-proto.h" + +static void proto_push(Proto *p, ProtoMessage *msg) { + msg->next = NULL; + *p->out_last = msg; + p->out_last = &msg->next; +} + +static ProtoMessage *proto_pop(Proto *p) { + ProtoMessage *msg; + + if (!p->out_first) + return NULL; + + msg = p->out_first; + p->out_first = msg->next; + if (!p->out_first) + p->out_last = &p->out_first; + + return msg; +} + +static ProtoMessage *proto_peek(Proto *p) { + return p->out_first; +} + +static void proto_notify(Proto *p, ProtoMessage *msg) { + if (p->event_fn) + p->event_fn(p, msg, p->data); +} + +static void proto_hup(Proto *p) { + proto_notify(p, NULL); +} + +static int proto_read(Proto *p, int flags, ProtoMessage **out) { + ProtoMessage *msg, buf = { }; + ssize_t r; + +try_again: + r = recv(p->comm, &buf, sizeof(buf), MSG_NOSIGNAL | flags); + if (r < 0) { + r = -errno; + if (r != -EAGAIN) + p->hup = true; + return r; + } else if (!r) { + p->hup = true; + return -EAGAIN; + } else if (r < (ssize_t)PROTO_MESSAGE_SIZE_MIN) { + log_warning("proto: message with invalid size received"); + goto try_again; + } + + msg = proto_message_new(r, 0); + if (!msg) { + sd_event_source_set_enabled(p->idle_source, SD_EVENT_ONESHOT); + return log_oom(); + } + + memcpy(msg, &buf, r); + + *out = msg; + return 0; +} + +static int proto_read_many(Proto *p) { + ProtoMessage *msg; + int r; + + /* Always try reading, don't test for HUP. In case a write() failed and + * caused a HUP, there might still be pending data that we want. */ + + do { + r = proto_read(p, MSG_DONTWAIT, &msg); + if (r >= 0) { + proto_notify(p, msg); + proto_message_free(msg); + } + } while (r >= 0); + + return (r == -EAGAIN) ? 0 : r; +} + +static int proto_write(Proto *p, ProtoMessage *msg, int flags) { + ssize_t r; + + r = send(p->comm, msg, msg->size, MSG_NOSIGNAL | flags); + if (r < 0) { + r = -errno; + if (r != -EAGAIN) + p->hup = true; + + return r; + } + + return 0; +} + +static int proto_write_many(Proto *p) { + ProtoMessage *msg; + int r = 0; + + /* If there's a HUP we have no reason to try writing more data.. */ + if (p->hup) + return -EPIPE; + + while ((msg = proto_peek(p))) { + r = proto_write(p, msg, MSG_DONTWAIT); + if (r < 0) { + if (r == -EAGAIN) + r = 0; + break; + } + + msg = proto_pop(p); + proto_message_free(msg); + } + + return r; +} + +static void proto_io(Proto *p, uint32_t mask) { + if (p->hup) + return; + + if (mask & EPOLLOUT) + proto_write_many(p); + + if (mask & EPOLLIN) + proto_read_many(p); + + if (mask & (EPOLLHUP | EPOLLERR)) + p->hup = true; + + if (p->hup) { + sd_event_source_set_enabled(p->idle_source, SD_EVENT_OFF); + sd_event_source_set_enabled(p->comm_source, SD_EVENT_OFF); + proto_hup(p); + } +} + +static int proto_io_fn(sd_event_source *src, int fd, uint32_t mask, void *data) { + proto_io(data, mask); + return 0; +} + +static int proto_idle_fn(sd_event_source *src, void *data) { + proto_io(data, EPOLLOUT); + return 0; +} + +int proto_new(int comm, + sd_event *event, + proto_event_t event_fn, + void *data, + Proto **out) { + Proto *p; + int r; + + p = calloc(1, sizeof(*p)); + if (!p) + goto oom; + + p->out_last = &p->out_first; + p->comm = comm; + p->event = sd_event_ref(event); + p->event_fn = event_fn; + p->data = data; + + r = sd_event_add_io(event, + comm, + EPOLLHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLET, + proto_io_fn, + p, + &p->comm_source); + if (r < 0) + goto error; + + r = sd_event_add_defer(event, proto_idle_fn, p, &p->idle_source); + if (r < 0) + goto error; + + sd_event_source_set_enabled(p->idle_source, SD_EVENT_OFF); + + *out = p; + return 0; + +oom: + r = log_oom(); +error: + proto_free(p); + log_error("proto: cannot create proto object: %d", r); + return r; +} + +void proto_free(Proto *p) { + ProtoMessage *msg; + + if (!p) + return; + + while ((msg = proto_pop(p))) + proto_message_free(msg); + + sd_event_source_unref(p->idle_source); + sd_event_source_unref(p->comm_source); + sd_event_unref(p->event); + free(p); +} + +void proto_send(Proto *p, ProtoMessage *msg) { + if (p->hup) { + proto_message_free(msg); + } else { + proto_push(p, msg); + sd_event_source_set_enabled(p->idle_source, SD_EVENT_ONESHOT); + } +} + +void proto_flush(Proto *p) { + ProtoMessage *msg; + int r = p->hup ? -EPIPE : 0; + + while ((msg = proto_pop(p))) { + /* try a synchronous write; no MSG_DONTWAIT */ + if (r >= 0) + r = proto_write(p, msg, 0); + + proto_message_free(msg); + } +} diff --git a/src/welcome/welcomed-proto.h b/src/welcome/welcomed-proto.h new file mode 100644 index 000000000..7fd41a134 --- /dev/null +++ b/src/welcome/welcomed-proto.h @@ -0,0 +1,124 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 David Herrmann <dh.herrmann@gmail.com> + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#pragma once + +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> +#include <sys/types.h> + +#include "macro.h" +#include "sd-event.h" +#include "sd-gfx.h" +#include "util.h" + +#define PROTO_ENTRY_MAX 512 + +typedef struct Proto Proto; +typedef struct ProtoMessage ProtoMessage; + +typedef void (*proto_event_t) (Proto *p, ProtoMessage *m, void *data); + +struct Proto { + int comm; + sd_event *event; + sd_event_source *comm_source; + sd_event_source *idle_source; + proto_event_t event_fn; + void *data; + + ProtoMessage *out_first; + ProtoMessage **out_last; + + bool hup : 1; +}; + +/* protocol */ + +enum { + PROTO_START, + PROTO_STOP, + PROTO_LOGIN, + PROTO_SHOW_MESSAGE, +}; + +enum { + PROTO_MSG_SUCCESS, + PROTO_MSG_INTERNAL_ERROR, + PROTO_MSG_INVALID_USERNAME, + PROTO_MSG_WRONG_PASSWORD, +}; + +struct ProtoMessage { + ProtoMessage *next; + size_t size; + unsigned int type; + + union { + int dummy; + struct ProtoMessageLogin { + char name[PROTO_ENTRY_MAX]; + char password[PROTO_ENTRY_MAX]; + } login; + struct ProtoMessageShowMessage { + unsigned int msgid; + } show_message; + }; +}; + +#define PROTO_MESSAGE_SIZE_MIN offsetof(ProtoMessage, dummy) + +static inline ProtoMessage *proto_message_new(size_t size, unsigned int type) { + ProtoMessage *msg; + + size = MIN(size, PROTO_MESSAGE_SIZE_MIN); + msg = calloc(1, size); + if (!msg) + return NULL; + + msg->size = size; + msg->type = type; + return msg; +} + +static inline void proto_message_free(ProtoMessage *msg) { + free(msg); +} + +#define proto_message_new_name(_name, _type) proto_message_new(sizeof(((ProtoMessage*)0)->_name), (_type)) + +#define proto_message_new_start() proto_message_new(0, PROTO_START) +#define proto_message_new_stop() proto_message_new(0, PROTO_STOP) +#define proto_message_new_login() proto_message_new_name(login, PROTO_LOGIN) +#define proto_message_new_show_message() proto_message_new_show_message(show_message, PROTO_SHOW_MESSAGE) + +/* proto helper */ + +int proto_new(int comm, + sd_event *event, + proto_event_t event_fn, + void *data, + Proto **out); +void proto_free(Proto *p); + +void proto_send(Proto *p, ProtoMessage *msg); +void proto_flush(Proto *p); diff --git a/src/welcome/welcomed-session.c b/src/welcome/welcomed-session.c index b117bbf8a..7a1e0b81d 100644 --- a/src/welcome/welcomed-session.c +++ b/src/welcome/welcomed-session.c @@ -26,7 +26,12 @@ #include "log.h" #include "macro.h" -#include "sd-event.h" #include "util.h" #include "welcomed.h" -#include "welcomed-greeter.h" + +int session_spawn(const char *seat, + const char *session, + const char *username, + const char *password) { + return 0; +} diff --git a/src/welcome/welcomed.c b/src/welcome/welcomed.c index 017219419..e3ea0d0ac 100644 --- a/src/welcome/welcomed.c +++ b/src/welcome/welcomed.c @@ -39,14 +39,42 @@ #include "sd-bus.h" #include "sd-daemon.h" #include "sd-event.h" +#include "sd-login.h" #include "util.h" #include "welcomed.h" -#include "welcomed-greeter.h" static const char *arg_seat; static const char *arg_auto_session; static const char *arg_auto_user; +static void manager_proto_fn(Proto *p, ProtoMessage *msg, void *data) { + Manager *m = data; + + if (!msg) { + log_error("HUP on greeter slave, exiting.."); + sd_event_request_quit(m->event); + return; + } +} + +static void manager_start(Manager *m) { + if (m->running) + return; + + log_info("Seat gained graphics-support; spawning greeter"); + + m->running = 1; +} + +static void manager_stop(Manager *m) { + if (!m->running) + return; + + log_info("Seat lost graphics-support; stopping greeter"); + + m->running = 0; +} + static int manager_adjust_state(Manager *m, bool sync) { _cleanup_bus_message_unref_ sd_bus_message *rep = NULL; _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL; @@ -82,13 +110,10 @@ static int manager_adjust_state(Manager *m, bool sync) { m->can_graphical = v; } - if (m->can_graphical && !m->greeter->running) { - log_info("Seat gained graphics-support; spawning greeter"); - greeter_start(m->greeter, arg_auto_session, arg_auto_user); - } else if (!m->can_graphical && m->greeter->running) { - log_info("Seat lost graphics-support; stopping greeter"); - greeter_stop(m->greeter); - } + if (m->can_graphical) + manager_start(m); + else if (!m->can_graphical) + manager_stop(m); return 0; @@ -133,7 +158,12 @@ static void manager_free(Manager *m) { if (!m) return; - greeter_free(m->greeter); + manager_stop(m); + + if (m->proto) { + proto_flush(m->proto); + proto_free(m->proto); + } sd_bus_unref(m->bus); for (i = 0; m->sigs[i]; ++i) sd_event_source_unref(m->sigs[i]); @@ -157,6 +187,7 @@ static int manager_new(int comm, Manager **out) { goto oom; m->seat = arg_seat; + m->auto_done = !arg_auto_user; r = sd_event_default(&m->event); if (r < 0) { @@ -214,7 +245,7 @@ static int manager_new(int comm, Manager **out) { goto error; } - r = greeter_new(comm, m, &m->greeter); + r = proto_new(comm, m->event, manager_proto_fn, m, &m->proto); if (r < 0) goto error; @@ -266,7 +297,7 @@ static int parse_argv(int argc, char *argv[]) { { "auto-user", required_argument, NULL, ARG_AUTO_USER }, {} }; - int c; + int c, r; assert(argc >= 0); assert(argv); @@ -303,6 +334,14 @@ static int parse_argv(int argc, char *argv[]) { if (!arg_seat) { log_error("No seat specified via --seat=NAME."); return -EINVAL; + } else { + r = sd_seat_can_multi_session(arg_seat); + if (r < 0) { + log_error("Invalid seat: %s", arg_seat); + return r; + } else if (!r) { + log_warning("Multi-session not supported on seat %s", arg_seat); + } } if (isempty(arg_auto_session)) @@ -331,7 +370,7 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; /* fork off greeter-slave early so it has a clean environment */ - comm = greeter_slave_spawn(arg_seat); + comm = greeter_spawn(arg_seat); if (comm < 0) goto finish; @@ -346,8 +385,7 @@ int main(int argc, char *argv[]) { finish: sd_notify(false, "STATUS=Shutting down..."); - if (m) - manager_free(m); + manager_free(m); if (comm >= 0) close_nointr(comm); diff --git a/src/welcome/welcomed.h b/src/welcome/welcomed.h index cd879b88e..c8c95a350 100644 --- a/src/welcome/welcomed.h +++ b/src/welcome/welcomed.h @@ -28,10 +28,9 @@ #include "list.h" #include "sd-bus.h" #include "sd-event.h" -#include "welcomed-greeter.h" +#include "welcomed-proto.h" typedef struct Manager Manager; -typedef struct Greeter Greeter; struct Manager { sd_event *event; @@ -41,23 +40,20 @@ struct Manager { const char *seat; char *seat_path; - Greeter *greeter; + Proto *proto; bool can_graphical : 1; -}; - -struct Greeter { - Manager *m; - GreeterProto *proto; - - unsigned int running : 1; - unsigned int auto_done : 1; + bool running : 1; + bool auto_done : 1; }; /* greeter */ -int greeter_new(int comm, Manager *m, Greeter **out); -void greeter_free(Greeter *g); +int greeter_spawn(const char *seat); + +/* session */ -void greeter_start(Greeter *g, const char *auto_session, const char *auto_user); -void greeter_stop(Greeter *g); +int session_spawn(const char *seat, + const char *session, + const char *username, + const char *password); |