summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-11-30 20:01:24 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2013-11-30 20:04:11 +0100
commitbf594040705caa900cb893c2760a2ec9d50d516b (patch)
tree7344b5782f0235cb3d968673ded5c88943ad43cf
parent2a15b495f7f9e3b7df58240e0d7bb305836ca7ac (diff)
WELCOMED-TODO
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am8
-rw-r--r--src/welcome/welcomed-greeter-proto.c117
-rw-r--r--src/welcome/welcomed-greeter-slave.c83
-rw-r--r--src/welcome/welcomed-greeter.c93
-rw-r--r--src/welcome/welcomed-greeter.h72
-rw-r--r--src/welcome/welcomed-proto.c265
-rw-r--r--src/welcome/welcomed-proto.h124
-rw-r--r--src/welcome/welcomed-session.c9
-rw-r--r--src/welcome/welcomed.c66
-rw-r--r--src/welcome/welcomed.h26
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);