summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/plymouth-ctrl.h65
-rw-r--r--lib/Makemodule.am1
-rw-r--r--lib/plymouth-ctrl.c147
-rw-r--r--login-utils/sulogin.c44
-rw-r--r--term-utils/agetty.c48
5 files changed, 223 insertions, 82 deletions
diff --git a/include/plymouth-ctrl.h b/include/plymouth-ctrl.h
new file mode 100644
index 000000000..e1df363eb
--- /dev/null
+++ b/include/plymouth-ctrl.h
@@ -0,0 +1,65 @@
+/*
+ * plymouth-ctrl.h Header file for communcations with plymouthd
+ *
+ * Copyright (c) 2016 SUSE Linux GmbH, All rights reserved.
+ * Copyright (c) 2016 Werner Fink <werner@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Author: Werner Fink <werner@suse.de>
+ */
+
+/*
+ * Taken from plymouth 0.9.0 src/ply-boot-protocol.h
+ */
+
+#ifndef UTIL_LINUX_PLYMOUTH_CTRL_H
+#define UTIL_LINUX_PLYMOUTH_CTRL_H
+
+#define PLYMOUTH_SOCKET_PATH "\0/org/freedesktop/plymouthd"
+#define ANSWER_TYP '\x2'
+#define ANSWER_ENQ '\x5'
+#define ANSWER_ACK '\x6'
+#define ANSWER_MLT '\t'
+#define ANSWER_NCK '\x15'
+
+#define MAGIC_PRG_STOP 'A'
+#define MAGIC_PRG_CONT 'a'
+#define MAGIC_UPDATE 'U'
+#define MAGIC_SYS_UPDATE 'u'
+#define MAGIC_SYS_INIT 'S'
+#define MAGIC_DEACTIVATE 'D'
+#define MAGIC_REACTIVATE 'r'
+#define MAGIC_SHOW_SPLASH '$'
+#define MAGIC_HIDE_SPLASH 'H'
+#define MAGIC_CHMOD 'C'
+#define MAGIC_CHROOT 'R'
+#define MAGIC_ACTIVE_VT 'V'
+#define MAGIC_QUESTION 'W'
+#define MAGIC_SHOW_MSG 'M'
+#define MAGIC_HIDE_MSG 'm'
+#define MAGIC_KEYSTROKE 'K'
+#define MAGIC_KEYSTROKE_RM 'L'
+#define MAGIC_PING 'P'
+#define MAGIC_QUIT 'Q'
+#define MAGIC_CACHED_PWD 'c'
+#define MAGIC_ASK_PWD '*'
+#define MAGIC_DETAILS '!'
+
+#define PLYMOUTH_TERMIOS_FLAGS_DELAY 30
+extern int plymouth_command(int cmd, ...);
+
+#endif /* UTIL_LINUX_PLYMOUTH_CTRL_H */
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index 092d54e74..b2172db13 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -16,6 +16,7 @@ libcommon_la_SOURCES = \
lib/md5.c \
lib/pager.c \
lib/path.c \
+ lib/plymouth-ctrl.c \
lib/randutils.c \
lib/setproctitle.c \
lib/strutils.c \
diff --git a/lib/plymouth-ctrl.c b/lib/plymouth-ctrl.c
new file mode 100644
index 000000000..2a1b2ce3e
--- /dev/null
+++ b/lib/plymouth-ctrl.c
@@ -0,0 +1,147 @@
+/*
+ * plymouth-ctrl.c Simply communcations with plymouthd
+ * to avoid forked sub processes and/or
+ * misssed plymouth send commands tool
+ * due a plymouthd replacment.
+ *
+ * Copyright (c) 2016 SUSE Linux GmbH, All rights reserved.
+ * Copyright (c) 2016 Werner Fink <werner@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Author: Werner Fink <werner@suse.de>
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "all-io.h"
+#include "c.h"
+#include "nls.h"
+#include "plymouth-ctrl.h"
+
+static int can_read(int fd, const long timeout)
+{
+ struct pollfd fds = {
+ .fd = fd,
+ .events = POLLIN|POLLPRI,
+ .revents = 0,
+ };
+ int ret;
+
+ do {
+ ret = poll(&fds, 1, timeout);
+ } while ((ret < 0) && (errno == EINTR));
+
+ return (ret == 1) && (fds.revents & (POLLIN|POLLPRI));
+}
+
+static int open_un_socket_and_connect(void)
+{
+ struct sockaddr_un su = { /* The abstract UNIX socket of plymouth */
+ .sun_family = AF_UNIX,
+ .sun_path = PLYMOUTH_SOCKET_PATH,
+ };
+ const int one = 1;
+ int fd, ret;
+
+ fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (fd < 0) {
+ warnx(_("can not open UNIX socket"));
+ goto err;
+ }
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, (socklen_t)sizeof(one));
+ if (ret < 0) {
+ warnx(_("can not set option for UNIX socket"));
+ close(fd);
+ fd = -1;
+ goto err;
+ }
+
+ /*
+ * Please note that the PLYMOUTH_SOCKET_PATH has a
+ * leading NULL byte to mark it as an abstract socket
+ */
+ ret = connect(fd, &su, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(su.sun_path+1));
+ if (ret < 0) {
+ if (errno != ECONNREFUSED)
+ warnx(_("can not connect on UNIX socket"));
+ close(fd);
+ fd = -1;
+ goto err;
+ }
+err:
+ return fd;
+}
+
+int plymouth_command(int cmd, ...)
+{
+ uint8_t answer[2], command[2];
+ struct sigaction sp, op;
+ int fdsock = -1, ret = 0;
+
+ sigemptyset (&sp.sa_mask);
+ sp.sa_handler = SIG_IGN;
+ sp.sa_flags = SA_RESTART;
+ sigaction(SIGPIPE, &sp, &op);
+
+ /*
+ * The plymouthd does read at least two bytes.
+ */
+ command[1] = '\0';
+ switch (cmd) {
+ case MAGIC_PING:
+ fdsock = open_un_socket_and_connect();
+ if (fdsock >= 0) {
+ command[0] = cmd;
+ write_all(fdsock, command, sizeof(command));
+ }
+ break;
+ case MAGIC_QUIT:
+ fdsock = open_un_socket_and_connect();
+ if (fdsock >= 0) {
+ command[0] = cmd;
+ write_all(fdsock, command, sizeof(command));
+ }
+ break;
+ default:
+ warnx(_("the plymouth request %c is not implemented"), cmd);
+ case '?':
+ goto err;
+ }
+
+ answer[0] = '\0';
+ if (fdsock >= 0) {
+ if (can_read(fdsock, 1000))
+ read_all(fdsock, (char *) &answer[0], sizeof(answer));
+ close(fdsock);
+ }
+ sigaction(SIGPIPE, &op, NULL);
+ ret = (answer[0] == ANSWER_ACK) ? 1 : 0;
+err:
+ return ret;
+}
+
diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index 601d38caf..8d6e65229 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -58,6 +58,7 @@
#include "closestream.h"
#include "nls.h"
#include "pathnames.h"
+#include "plymouth-ctrl.h"
#include "strutils.h"
#include "ttyutils.h"
#include "sulogin-consoles.h"
@@ -92,42 +93,6 @@ static int locked_account_password(const char *passwd)
return 0;
}
-#ifdef TIOCGLCKTRMIOS
-/*
- * For the case plymouth is found on this system
- */
-static int plymouth_command(const char* arg)
-{
- const char *cmd = "/usr/bin/plymouth";
- static int has_plymouth = 1;
- pid_t pid;
-
- if (!has_plymouth)
- return 127;
-
- pid = fork();
- if (!pid) {
- int fd = open("/dev/null", O_RDWR);
- if (fd < 0)
- exit(127);
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- if (fd > 2)
- close(fd);
- execl(cmd, cmd, arg, (char *) NULL);
- exit(127);
- } else if (pid > 0) {
- int status;
- waitpid(pid, &status, 0);
- if (status == 127)
- has_plymouth = 0;
- return status;
- }
- return 1;
-}
-#endif
-
/*
* Fix the tty modes and set reasonable defaults.
*/
@@ -138,8 +103,9 @@ static void tcinit(struct console *con)
struct termios lock;
int fd = con->fd;
#ifdef TIOCGLCKTRMIOS
- int i = (plymouth_command("--ping")) ? 20 : 0;
-
+ int i = (plymouth_command(MAGIC_PING)) ? PLYMOUTH_TERMIOS_FLAGS_DELAY : 0;
+ if (i)
+ plymouth_command(MAGIC_QUIT);
while (i-- > 0) {
/*
* With plymouth the termios flags become changed after this
@@ -150,8 +116,6 @@ static void tcinit(struct console *con)
break;
if (!lock.c_iflag && !lock.c_oflag && !lock.c_cflag && !lock.c_lflag)
break;
- if (i == 15 && plymouth_command("quit") != 0)
- break;
sleep(1);
}
memset(&lock, 0, sizeof(struct termios));
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index 6d610c608..ab82fdbc8 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -41,6 +41,7 @@
#include "all-io.h"
#include "nls.h"
#include "pathnames.h"
+#include "plymouth-ctrl.h"
#include "c.h"
#include "widechar.h"
#include "ttyutils.h"
@@ -138,9 +139,6 @@ static int inotify_fd = AGETTY_RELOAD_FDNONE;
static int netlink_fd = AGETTY_RELOAD_FDNONE;
#endif
-#define AGETTY_PLYMOUTH "/usr/bin/plymouth"
-#define AGETTY_PLYMOUTH_FDFILE "/dev/null"
-
/*
* When multiple baud rates are specified on the command line, the first one
* we will try is the first one specified.
@@ -309,7 +307,6 @@ static void log_warn (const char *, ...)
static ssize_t append(char *dest, size_t len, const char *sep, const char *src);
static void check_username (const char* nm);
static void login_options_to_argv(char *argv[], int *argc, char *str, char *username);
-static int plymouth_command(const char* arg);
static void reload_agettys(void);
/* Fake hostname for ut_host specified on command line. */
@@ -1180,8 +1177,9 @@ static void termio_init(struct options *op, struct termios *tp)
struct winsize ws;
struct termios lock;
#ifdef TIOCGLCKTRMIOS
- int i = (plymouth_command("--ping") == 0) ? 30 : 0;
-
+ int i = (plymouth_command(MAGIC_PING) == 0) ? PLYMOUTH_TERMIOS_FLAGS_DELAY : 0;
+ if (i)
+ plymouth_command(MAGIC_QUIT);
while (i-- > 0) {
/*
* Even with TTYReset=no it seems with systemd or plymouth
@@ -1194,8 +1192,6 @@ static void termio_init(struct options *op, struct termios *tp)
if (!lock.c_iflag && !lock.c_oflag && !lock.c_cflag && !lock.c_lflag)
break;
debug("termios locked\n");
- if (i == 15 && plymouth_command("quit") != 0)
- break;
sleep(1);
}
memset(&lock, 0, sizeof(struct termios));
@@ -1725,7 +1721,9 @@ static void print_issue_file(struct options *op, struct termios *tp)
/* Show login prompt, optionally preceded by /etc/issue contents. */
static void do_prompt(struct options *op, struct termios *tp)
{
+#ifdef AGETTY_RELOAD
again:
+#endif
print_issue_file(op, tp);
if (op->flags & F_LOGINPAUSE) {
@@ -2596,40 +2594,6 @@ err:
log_err(_("checkname failed: %m"));
}
-/*
- * For the case plymouth is found on this system
- */
-static int plymouth_command(const char* arg)
-{
- static int has_plymouth = 1;
- pid_t pid;
-
- if (!has_plymouth)
- return 127;
-
- pid = fork();
- if (!pid) {
- int fd = open(AGETTY_PLYMOUTH_FDFILE, O_RDWR);
-
- if (fd < 0)
- err(EXIT_FAILURE,_("cannot open %s"),
- AGETTY_PLYMOUTH_FDFILE);
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- close(fd);
- execl(AGETTY_PLYMOUTH, AGETTY_PLYMOUTH, arg, (char *) NULL);
- exit(127);
- } else if (pid > 0) {
- int status;
- waitpid(pid, &status, 0);
- if (status == 127)
- has_plymouth = 0;
- return status;
- }
- return 1;
-}
-
static void reload_agettys(void)
{
#ifdef AGETTY_RELOAD