|
|
05ad79 |
From f720781671c9f5421fb8101dd3bcf7b56efca131 Mon Sep 17 00:00:00 2001
|
|
|
05ad79 |
From: Karel Zak <kzak@redhat.com>
|
|
|
05ad79 |
Date: Mon, 20 Aug 2018 14:56:08 +0200
|
|
|
05ad79 |
Subject: [PATCH 178/178] sulogin: backport RHEL-8 version
|
|
|
05ad79 |
|
|
|
05ad79 |
The new version is more robust and it does not use mmap()-ed shared
|
|
|
05ad79 |
memory between sulogins instances. It also provides some fallbacks for
|
|
|
05ad79 |
s390 machines.
|
|
|
05ad79 |
|
|
|
05ad79 |
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1616264
|
|
|
05ad79 |
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
|
05ad79 |
---
|
|
|
05ad79 |
configure.ac | 1 +
|
|
|
05ad79 |
include/c.h | 4 +
|
|
|
05ad79 |
login-utils/sulogin-consoles.c | 116 +++++++++++++------
|
|
|
05ad79 |
login-utils/sulogin.c | 253 +++++++++++++++++++++++++++--------------
|
|
|
05ad79 |
4 files changed, 252 insertions(+), 122 deletions(-)
|
|
|
05ad79 |
|
|
|
05ad79 |
diff --git a/configure.ac b/configure.ac
|
|
|
05ad79 |
index d561e01d0..3f07df495 100644
|
|
|
05ad79 |
--- a/configure.ac
|
|
|
05ad79 |
+++ b/configure.ac
|
|
|
05ad79 |
@@ -218,6 +218,7 @@ AC_CHECK_HEADERS([ \
|
|
|
05ad79 |
sys/prctl.h \
|
|
|
05ad79 |
sys/queue.h \
|
|
|
05ad79 |
sys/resource.h \
|
|
|
05ad79 |
+ sys/sysmacros.h \
|
|
|
05ad79 |
sys/socket.h \
|
|
|
05ad79 |
sys/sockio.h \
|
|
|
05ad79 |
sys/stat.h \
|
|
|
05ad79 |
diff --git a/include/c.h b/include/c.h
|
|
|
05ad79 |
index 124035ea5..51d439297 100644
|
|
|
05ad79 |
--- a/include/c.h
|
|
|
05ad79 |
+++ b/include/c.h
|
|
|
05ad79 |
@@ -19,6 +19,10 @@
|
|
|
05ad79 |
# include <err.h>
|
|
|
05ad79 |
#endif
|
|
|
05ad79 |
|
|
|
05ad79 |
+#ifdef HAVE_SYS_SYSMACROS_H
|
|
|
05ad79 |
+# include <sys/sysmacros.h> /* for major, minor */
|
|
|
05ad79 |
+#endif
|
|
|
05ad79 |
+
|
|
|
05ad79 |
#ifndef HAVE_USLEEP
|
|
|
05ad79 |
# include <time.h>
|
|
|
05ad79 |
#endif
|
|
|
05ad79 |
diff --git a/login-utils/sulogin-consoles.c b/login-utils/sulogin-consoles.c
|
|
|
05ad79 |
index 07af33a6d..2c0eed3a4 100644
|
|
|
05ad79 |
--- a/login-utils/sulogin-consoles.c
|
|
|
05ad79 |
+++ b/login-utils/sulogin-consoles.c
|
|
|
05ad79 |
@@ -36,8 +36,9 @@
|
|
|
05ad79 |
# include <linux/serial.h>
|
|
|
05ad79 |
# include <linux/major.h>
|
|
|
05ad79 |
#endif
|
|
|
05ad79 |
-#include <fcntl.h>
|
|
|
05ad79 |
#include <dirent.h>
|
|
|
05ad79 |
+#include <errno.h>
|
|
|
05ad79 |
+#include <fcntl.h>
|
|
|
05ad79 |
#include <unistd.h>
|
|
|
05ad79 |
|
|
|
05ad79 |
#ifdef USE_SULOGIN_EMERGENCY_MOUNT
|
|
|
05ad79 |
@@ -74,7 +75,7 @@ static int consoles_debug;
|
|
|
05ad79 |
} while (0)
|
|
|
05ad79 |
|
|
|
05ad79 |
static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
|
|
|
05ad79 |
-dbgprint(const char *mesg, ...)
|
|
|
05ad79 |
+dbgprint(const char * const mesg, ...)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
va_list ap;
|
|
|
05ad79 |
va_start(ap, mesg);
|
|
|
05ad79 |
@@ -112,7 +113,7 @@ void emergency_do_mounts(void)
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
if (stat("/", &rt) != 0) {
|
|
|
05ad79 |
- warn("can not get file status of root file system\n");
|
|
|
05ad79 |
+ warn("cannot get file status of root file system\n");
|
|
|
05ad79 |
return;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
@@ -150,17 +151,19 @@ void emergency_do_mounts(void) { }
|
|
|
05ad79 |
* the caller has to free the result
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
static __attribute__((__nonnull__))
|
|
|
05ad79 |
-char *oneline(const char *file)
|
|
|
05ad79 |
+char *oneline(const char * const file)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
FILE *fp;
|
|
|
05ad79 |
char *ret = NULL;
|
|
|
05ad79 |
- size_t len = 0;
|
|
|
05ad79 |
+ size_t dummy = 0;
|
|
|
05ad79 |
+ ssize_t len;
|
|
|
05ad79 |
|
|
|
05ad79 |
DBG(dbgprint("reading %s", file));
|
|
|
05ad79 |
|
|
|
05ad79 |
- if (!(fp = fopen(file, "re")))
|
|
|
05ad79 |
+ if (!(fp = fopen(file, "r" UL_CLOEXECSTR)))
|
|
|
05ad79 |
return NULL;
|
|
|
05ad79 |
- if (getline(&ret, &len, fp) >= 0) {
|
|
|
05ad79 |
+ len = getline(&ret, &dummy, fp);
|
|
|
05ad79 |
+ if (len >= 0) {
|
|
|
05ad79 |
char *nl;
|
|
|
05ad79 |
|
|
|
05ad79 |
if (len)
|
|
|
05ad79 |
@@ -179,7 +182,7 @@ char *oneline(const char *file)
|
|
|
05ad79 |
* /sys/class/tty, the caller has to free the result.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
static __attribute__((__malloc__))
|
|
|
05ad79 |
-char *actattr(const char *tty)
|
|
|
05ad79 |
+char *actattr(const char * const tty)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
char *ret, *path;
|
|
|
05ad79 |
|
|
|
05ad79 |
@@ -198,7 +201,7 @@ char *actattr(const char *tty)
|
|
|
05ad79 |
* /sys/class/tty.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
static
|
|
|
05ad79 |
-dev_t devattr(const char *tty)
|
|
|
05ad79 |
+dev_t devattr(const char * const tty)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
dev_t dev = 0;
|
|
|
05ad79 |
char *path, *value;
|
|
|
05ad79 |
@@ -223,42 +226,77 @@ dev_t devattr(const char *tty)
|
|
|
05ad79 |
#endif /* __linux__ */
|
|
|
05ad79 |
|
|
|
05ad79 |
/*
|
|
|
05ad79 |
- * Search below /dev for the characer device in `dev_t comparedev' variable.
|
|
|
05ad79 |
+ * Search below /dev for the character device in `dev_t comparedev' variable.
|
|
|
05ad79 |
+ * Note that realpath(3) is used here to avoid not existent devices due the
|
|
|
05ad79 |
+ * strdup(3) used in our canonicalize_path()!
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
static
|
|
|
05ad79 |
#ifdef __GNUC__
|
|
|
05ad79 |
__attribute__((__nonnull__,__malloc__,__hot__))
|
|
|
05ad79 |
#endif
|
|
|
05ad79 |
-char* scandev(DIR *dir, dev_t comparedev)
|
|
|
05ad79 |
+char* scandev(DIR *dir, const dev_t comparedev)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
+ char path[PATH_MAX];
|
|
|
05ad79 |
char *name = NULL;
|
|
|
05ad79 |
- struct dirent *dent;
|
|
|
05ad79 |
- int fd;
|
|
|
05ad79 |
+ const struct dirent *dent;
|
|
|
05ad79 |
+ int len, fd;
|
|
|
05ad79 |
|
|
|
05ad79 |
DBG(dbgprint("scanning /dev for %u:%u", major(comparedev), minor(comparedev)));
|
|
|
05ad79 |
|
|
|
05ad79 |
+ /*
|
|
|
05ad79 |
+ * Try udev links on character devices first.
|
|
|
05ad79 |
+ */
|
|
|
05ad79 |
+ if ((len = snprintf(path, sizeof(path),
|
|
|
05ad79 |
+ "/dev/char/%u:%u", major(comparedev), minor(comparedev))) > 0 &&
|
|
|
05ad79 |
+ (size_t)len < sizeof(path)) {
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ name = realpath(path, NULL);
|
|
|
05ad79 |
+ if (name)
|
|
|
05ad79 |
+ goto out;
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
+
|
|
|
05ad79 |
fd = dirfd(dir);
|
|
|
05ad79 |
rewinddir(dir);
|
|
|
05ad79 |
while ((dent = readdir(dir))) {
|
|
|
05ad79 |
- char path[PATH_MAX];
|
|
|
05ad79 |
struct stat st;
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+#ifdef _DIRENT_HAVE_D_TYPE
|
|
|
05ad79 |
+ if (dent->d_type != DT_UNKNOWN && dent->d_type != DT_CHR)
|
|
|
05ad79 |
+ continue;
|
|
|
05ad79 |
+#endif
|
|
|
05ad79 |
if (fstatat(fd, dent->d_name, &st, 0) < 0)
|
|
|
05ad79 |
continue;
|
|
|
05ad79 |
if (!S_ISCHR(st.st_mode))
|
|
|
05ad79 |
continue;
|
|
|
05ad79 |
if (comparedev != st.st_rdev)
|
|
|
05ad79 |
continue;
|
|
|
05ad79 |
- if ((size_t)snprintf(path, sizeof(path), "/dev/%s", dent->d_name) >= sizeof(path))
|
|
|
05ad79 |
+ if ((len = snprintf(path, sizeof(path), "/dev/%s", dent->d_name)) < 0 ||
|
|
|
05ad79 |
+ (size_t)len >= sizeof(path))
|
|
|
05ad79 |
continue;
|
|
|
05ad79 |
-#ifdef USE_SULOGIN_EMERGENCY_MOUNT
|
|
|
05ad79 |
- if (emergency_flags & MNT_DEVTMPFS)
|
|
|
05ad79 |
- mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev);
|
|
|
05ad79 |
-#endif
|
|
|
05ad79 |
|
|
|
05ad79 |
- name = canonicalize_path(path);
|
|
|
05ad79 |
- break;
|
|
|
05ad79 |
+ name = realpath(path, NULL);
|
|
|
05ad79 |
+ if (name)
|
|
|
05ad79 |
+ goto out;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
+#ifdef USE_SULOGIN_EMERGENCY_MOUNT
|
|
|
05ad79 |
+ /*
|
|
|
05ad79 |
+ * There was no /dev mounted hence and no device was found hence we create our own.
|
|
|
05ad79 |
+ */
|
|
|
05ad79 |
+ if (!name && (emergency_flags & MNT_DEVTMPFS)) {
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ if ((len = snprintf(path, sizeof(path),
|
|
|
05ad79 |
+ "/dev/tmp-%u:%u", major(comparedev), minor(comparedev))) < 0 ||
|
|
|
05ad79 |
+ (size_t)len >= sizeof(path))
|
|
|
05ad79 |
+ goto out;
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ if (mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev) < 0 && errno != EEXIST)
|
|
|
05ad79 |
+ goto out;
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ name = realpath(path, NULL);
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
+#endif
|
|
|
05ad79 |
+out:
|
|
|
05ad79 |
return name;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
@@ -273,12 +311,12 @@ char* scandev(DIR *dir, dev_t comparedev)
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
static
|
|
|
05ad79 |
#ifdef __GNUC__
|
|
|
05ad79 |
-__attribute__((__nonnull__,__hot__))
|
|
|
05ad79 |
+__attribute__((__hot__))
|
|
|
05ad79 |
#endif
|
|
|
05ad79 |
-int append_console(struct list_head *consoles, const char *name)
|
|
|
05ad79 |
+int append_console(struct list_head *consoles, const char * const name)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
struct console *restrict tail;
|
|
|
05ad79 |
- struct console *last = NULL;
|
|
|
05ad79 |
+ const struct console *last = NULL;
|
|
|
05ad79 |
|
|
|
05ad79 |
DBG(dbgprint("appenging %s", name));
|
|
|
05ad79 |
|
|
|
05ad79 |
@@ -300,7 +338,7 @@ int append_console(struct list_head *consoles, const char *name)
|
|
|
05ad79 |
tail->flags = 0;
|
|
|
05ad79 |
tail->fd = -1;
|
|
|
05ad79 |
tail->id = last ? last->id + 1 : 0;
|
|
|
05ad79 |
- tail->pid = 0;
|
|
|
05ad79 |
+ tail->pid = -1;
|
|
|
05ad79 |
memset(&tail->tio, 0, sizeof(tail->tio));
|
|
|
05ad79 |
|
|
|
05ad79 |
return 0;
|
|
|
05ad79 |
@@ -319,11 +357,11 @@ static int detect_consoles_from_proc(struct list_head *consoles)
|
|
|
05ad79 |
char fbuf[16 + 1];
|
|
|
05ad79 |
DIR *dir = NULL;
|
|
|
05ad79 |
FILE *fc = NULL;
|
|
|
05ad79 |
- int maj, min, rc = 1;
|
|
|
05ad79 |
+ int maj, min, rc = 1, matches;
|
|
|
05ad79 |
|
|
|
05ad79 |
DBG(dbgprint("trying /proc"));
|
|
|
05ad79 |
|
|
|
05ad79 |
- fc = fopen("/proc/consoles", "re");
|
|
|
05ad79 |
+ fc = fopen("/proc/consoles", "r" UL_CLOEXECSTR);
|
|
|
05ad79 |
if (!fc) {
|
|
|
05ad79 |
rc = 2;
|
|
|
05ad79 |
goto done;
|
|
|
05ad79 |
@@ -332,10 +370,12 @@ static int detect_consoles_from_proc(struct list_head *consoles)
|
|
|
05ad79 |
if (!dir)
|
|
|
05ad79 |
goto done;
|
|
|
05ad79 |
|
|
|
05ad79 |
- while (fscanf(fc, "%*s %*s (%16[^)]) %d:%d", fbuf, &maj, &min) == 3) {
|
|
|
05ad79 |
+ while ((matches = fscanf(fc, "%*s %*s (%16[^)]) %d:%d", fbuf, &maj, &min)) >= 1) {
|
|
|
05ad79 |
char *name;
|
|
|
05ad79 |
dev_t comparedev;
|
|
|
05ad79 |
|
|
|
05ad79 |
+ if (matches != 3)
|
|
|
05ad79 |
+ continue;
|
|
|
05ad79 |
if (!strchr(fbuf, 'E'))
|
|
|
05ad79 |
continue;
|
|
|
05ad79 |
comparedev = makedev(maj, min);
|
|
|
05ad79 |
@@ -509,7 +549,7 @@ done:
|
|
|
05ad79 |
|
|
|
05ad79 |
#ifdef TIOCGDEV
|
|
|
05ad79 |
static int detect_consoles_from_tiocgdev(struct list_head *consoles,
|
|
|
05ad79 |
- int fallback,
|
|
|
05ad79 |
+ const int fallback,
|
|
|
05ad79 |
const char *device)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
unsigned int devnum;
|
|
|
05ad79 |
@@ -579,7 +619,7 @@ done:
|
|
|
05ad79 |
* Returns 1 if stdout and stderr should be reconnected and 0
|
|
|
05ad79 |
* otherwise or less than zero on error.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
-int detect_consoles(const char *device, int fallback, struct list_head *consoles)
|
|
|
05ad79 |
+int detect_consoles(const char *device, const int fallback, struct list_head *consoles)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
int fd, reconnect = 0, rc;
|
|
|
05ad79 |
dev_t comparedev = 0;
|
|
|
05ad79 |
@@ -587,7 +627,7 @@ int detect_consoles(const char *device, int fallback, struct list_head *consoles
|
|
|
05ad79 |
consoles_debug = getenv("CONSOLES_DEBUG") ? 1 : 0;
|
|
|
05ad79 |
|
|
|
05ad79 |
if (!device || !*device)
|
|
|
05ad79 |
- fd = dup(fallback);
|
|
|
05ad79 |
+ fd = fallback >= 0 ? dup(fallback) : - 1;
|
|
|
05ad79 |
else {
|
|
|
05ad79 |
fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
|
|
|
05ad79 |
reconnect = 1;
|
|
|
05ad79 |
@@ -602,6 +642,14 @@ int detect_consoles(const char *device, int fallback, struct list_head *consoles
|
|
|
05ad79 |
struct stat st;
|
|
|
05ad79 |
#ifdef TIOCGDEV
|
|
|
05ad79 |
unsigned int devnum;
|
|
|
05ad79 |
+#endif
|
|
|
05ad79 |
+#ifdef __GNU__
|
|
|
05ad79 |
+ /*
|
|
|
05ad79 |
+ * The Hurd always gives st_rdev as 0, which causes this
|
|
|
05ad79 |
+ * method to select the first terminal it finds.
|
|
|
05ad79 |
+ */
|
|
|
05ad79 |
+ close(fd);
|
|
|
05ad79 |
+ goto fallback;
|
|
|
05ad79 |
#endif
|
|
|
05ad79 |
DBG(dbgprint("trying device/fallback file descriptor"));
|
|
|
05ad79 |
|
|
|
05ad79 |
@@ -670,7 +718,7 @@ int detect_consoles(const char *device, int fallback, struct list_head *consoles
|
|
|
05ad79 |
#ifdef __linux__
|
|
|
05ad79 |
console:
|
|
|
05ad79 |
/*
|
|
|
05ad79 |
- * Detection of devices used for Linux system consolei using
|
|
|
05ad79 |
+ * Detection of devices used for Linux system console using
|
|
|
05ad79 |
* the /proc/consoles API with kernel 2.6.38 and higher.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
rc = detect_consoles_from_proc(consoles);
|
|
|
05ad79 |
@@ -754,8 +802,7 @@ int main(int argc, char *argv[])
|
|
|
05ad79 |
{
|
|
|
05ad79 |
char *name = NULL;
|
|
|
05ad79 |
int fd, re;
|
|
|
05ad79 |
- LIST_HEAD(consoles);
|
|
|
05ad79 |
- struct list_head *p;
|
|
|
05ad79 |
+ struct list_head *p, consoles;
|
|
|
05ad79 |
|
|
|
05ad79 |
if (argc == 2) {
|
|
|
05ad79 |
name = argv[1];
|
|
|
05ad79 |
@@ -768,6 +815,7 @@ int main(int argc, char *argv[])
|
|
|
05ad79 |
if (!name)
|
|
|
05ad79 |
errx(EXIT_FAILURE, "usage: %s [<tty>]\n", program_invocation_short_name);
|
|
|
05ad79 |
|
|
|
05ad79 |
+ INIT_LIST_HEAD(&consoles);
|
|
|
05ad79 |
re = detect_consoles(name, fd, &consoles);
|
|
|
05ad79 |
|
|
|
05ad79 |
list_for_each(p, &consoles) {
|
|
|
05ad79 |
diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
|
|
|
05ad79 |
index dd73a1c50..4620ed2da 100644
|
|
|
05ad79 |
--- a/login-utils/sulogin.c
|
|
|
05ad79 |
+++ b/login-utils/sulogin.c
|
|
|
05ad79 |
@@ -56,8 +56,12 @@
|
|
|
05ad79 |
|
|
|
05ad79 |
#include "c.h"
|
|
|
05ad79 |
#include "closestream.h"
|
|
|
05ad79 |
+#include "env.h"
|
|
|
05ad79 |
#include "nls.h"
|
|
|
05ad79 |
#include "pathnames.h"
|
|
|
05ad79 |
+#ifdef USE_PLYMOUTH_SUPPORT
|
|
|
05ad79 |
+# include "plymouth-ctrl.h"
|
|
|
05ad79 |
+#endif
|
|
|
05ad79 |
#include "strutils.h"
|
|
|
05ad79 |
#include "ttyutils.h"
|
|
|
05ad79 |
#include "sulogin-consoles.h"
|
|
|
05ad79 |
@@ -66,13 +70,12 @@
|
|
|
05ad79 |
static unsigned int timeout;
|
|
|
05ad79 |
static int profile;
|
|
|
05ad79 |
static volatile uint32_t openfd; /* Remember higher file descriptors */
|
|
|
05ad79 |
-static volatile uint32_t *usemask;
|
|
|
05ad79 |
|
|
|
05ad79 |
-struct sigaction saved_sigint;
|
|
|
05ad79 |
-struct sigaction saved_sigtstp;
|
|
|
05ad79 |
-struct sigaction saved_sigquit;
|
|
|
05ad79 |
-struct sigaction saved_sighup;
|
|
|
05ad79 |
-struct sigaction saved_sigchld;
|
|
|
05ad79 |
+static struct sigaction saved_sigint;
|
|
|
05ad79 |
+static struct sigaction saved_sigtstp;
|
|
|
05ad79 |
+static struct sigaction saved_sigquit;
|
|
|
05ad79 |
+static struct sigaction saved_sighup;
|
|
|
05ad79 |
+static struct sigaction saved_sigchld;
|
|
|
05ad79 |
|
|
|
05ad79 |
static volatile sig_atomic_t alarm_rised;
|
|
|
05ad79 |
static volatile sig_atomic_t sigchild;
|
|
|
05ad79 |
@@ -81,7 +84,12 @@ static volatile sig_atomic_t sigchild;
|
|
|
05ad79 |
# define IUCLC 0
|
|
|
05ad79 |
#endif
|
|
|
05ad79 |
|
|
|
05ad79 |
-static int locked_account_password(const char *passwd)
|
|
|
05ad79 |
+#ifndef WEXITED
|
|
|
05ad79 |
+# warning "WEXITED is missing, sulogin may not work as expected"
|
|
|
05ad79 |
+# define WEXITED 0
|
|
|
05ad79 |
+#endif
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+static int locked_account_password(const char * const passwd)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
if (passwd && (*passwd == '*' || *passwd == '!'))
|
|
|
05ad79 |
return 1;
|
|
|
05ad79 |
@@ -93,10 +101,29 @@ static int locked_account_password(const char *passwd)
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
static void tcinit(struct console *con)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
- int mode = 0, flags = 0;
|
|
|
05ad79 |
+ int flags = 0, mode = 0;
|
|
|
05ad79 |
struct termios *tio = &con->tio;
|
|
|
05ad79 |
- int fd = con->fd;
|
|
|
05ad79 |
-
|
|
|
05ad79 |
+ const int fd = con->fd;
|
|
|
05ad79 |
+#ifdef USE_PLYMOUTH_SUPPORT
|
|
|
05ad79 |
+ struct termios lock;
|
|
|
05ad79 |
+ int i = (plymouth_command(MAGIC_PING)) ? PLYMOUTH_TERMIOS_FLAGS_DELAY : 0;
|
|
|
05ad79 |
+ if (i)
|
|
|
05ad79 |
+ plymouth_command(MAGIC_QUIT);
|
|
|
05ad79 |
+ while (i-- > 0) {
|
|
|
05ad79 |
+ /*
|
|
|
05ad79 |
+ * With plymouth the termios flags become changed after this
|
|
|
05ad79 |
+ * function had changed the termios.
|
|
|
05ad79 |
+ */
|
|
|
05ad79 |
+ memset(&lock, 0, sizeof(struct termios));
|
|
|
05ad79 |
+ if (ioctl(fd, TIOCGLCKTRMIOS, &lock) < 0)
|
|
|
05ad79 |
+ break;
|
|
|
05ad79 |
+ if (!lock.c_iflag && !lock.c_oflag && !lock.c_cflag && !lock.c_lflag)
|
|
|
05ad79 |
+ break;
|
|
|
05ad79 |
+ sleep(1);
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
+ memset(&lock, 0, sizeof(struct termios));
|
|
|
05ad79 |
+ ioctl(fd, TIOCSLCKTRMIOS, &lock);
|
|
|
05ad79 |
+#endif
|
|
|
05ad79 |
errno = 0;
|
|
|
05ad79 |
|
|
|
05ad79 |
if (tcgetattr(fd, tio) < 0) {
|
|
|
05ad79 |
@@ -189,20 +216,23 @@ setattr:
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
static void tcfinal(struct console *con)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
- struct termios *tio;
|
|
|
05ad79 |
- int fd;
|
|
|
05ad79 |
+ struct termios *tio = &con->tio;
|
|
|
05ad79 |
+ const int fd = con->fd;
|
|
|
05ad79 |
|
|
|
05ad79 |
if ((con->flags & CON_SERIAL) == 0) {
|
|
|
05ad79 |
- setenv("TERM", "linux", 1);
|
|
|
05ad79 |
+ xsetenv("TERM", "linux", 1);
|
|
|
05ad79 |
return;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
- if (con->flags & CON_NOTTY)
|
|
|
05ad79 |
+ if (con->flags & CON_NOTTY) {
|
|
|
05ad79 |
+ xsetenv("TERM", "dumb", 1);
|
|
|
05ad79 |
return;
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
|
|
|
05ad79 |
- setenv("TERM", "vt102", 1);
|
|
|
05ad79 |
- tio = &con->tio;
|
|
|
05ad79 |
- fd = con->fd;
|
|
|
05ad79 |
-
|
|
|
05ad79 |
+#if defined (__s390__) || defined (__s390x__)
|
|
|
05ad79 |
+ xsetenv("TERM", "dumb", 1);
|
|
|
05ad79 |
+#else
|
|
|
05ad79 |
+ xsetenv("TERM", "vt102", 1);
|
|
|
05ad79 |
+#endif
|
|
|
05ad79 |
tio->c_iflag |= (IXON | IXOFF);
|
|
|
05ad79 |
tio->c_lflag |= (ICANON | ISIG | ECHO|ECHOE|ECHOK|ECHOKE);
|
|
|
05ad79 |
tio->c_oflag |= OPOST;
|
|
|
05ad79 |
@@ -237,11 +267,11 @@ static void tcfinal(struct console *con)
|
|
|
05ad79 |
break;
|
|
|
05ad79 |
case 1: /* odd parity */
|
|
|
05ad79 |
tio->c_cflag |= PARODD;
|
|
|
05ad79 |
- /* fall through */
|
|
|
05ad79 |
+ /* fallthrough */
|
|
|
05ad79 |
case 2: /* even parity */
|
|
|
05ad79 |
tio->c_cflag |= PARENB;
|
|
|
05ad79 |
tio->c_iflag |= (INPCK | ISTRIP);
|
|
|
05ad79 |
- /* fall through */
|
|
|
05ad79 |
+ /* fallthrough */
|
|
|
05ad79 |
case (1 | 2): /* no parity bit */
|
|
|
05ad79 |
tio->c_cflag &= ~CSIZE;
|
|
|
05ad79 |
tio->c_cflag |= CS7;
|
|
|
05ad79 |
@@ -466,7 +496,7 @@ static struct passwd *getrootpwent(int try_manually)
|
|
|
05ad79 |
warnx(_("%s: no entry for root"), _PATH_SHADOW_PASSWD);
|
|
|
05ad79 |
*pwd.pw_passwd = '\0';
|
|
|
05ad79 |
}
|
|
|
05ad79 |
- /* locked accont passwords are valid too */
|
|
|
05ad79 |
+ /* locked account passwords are valid too */
|
|
|
05ad79 |
if (!locked_account_password(pwd.pw_passwd) && !valid(pwd.pw_passwd)) {
|
|
|
05ad79 |
warnx(_("%s: root password garbled"), _PATH_SHADOW_PASSWD);
|
|
|
05ad79 |
*pwd.pw_passwd = '\0';
|
|
|
05ad79 |
@@ -524,22 +554,17 @@ err:
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
static void setup(struct console *con)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
- pid_t pid, pgrp, ppgrp, ttypgrp;
|
|
|
05ad79 |
- int fd;
|
|
|
05ad79 |
+ int fd = con->fd;
|
|
|
05ad79 |
+ const pid_t pid = getpid(), pgrp = getpgid(0), ppgrp =
|
|
|
05ad79 |
+ getpgid(getppid()), ttypgrp = tcgetpgrp(fd);
|
|
|
05ad79 |
|
|
|
05ad79 |
if (con->flags & CON_NOTTY)
|
|
|
05ad79 |
return;
|
|
|
05ad79 |
- fd = con->fd;
|
|
|
05ad79 |
|
|
|
05ad79 |
/*
|
|
|
05ad79 |
* Only go through this trouble if the new
|
|
|
05ad79 |
* tty doesn't fall in this process group.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
- pid = getpid();
|
|
|
05ad79 |
- pgrp = getpgid(0);
|
|
|
05ad79 |
- ppgrp = getpgid(getppid());
|
|
|
05ad79 |
- ttypgrp = tcgetpgrp(fd);
|
|
|
05ad79 |
-
|
|
|
05ad79 |
if (pgrp != ttypgrp && ppgrp != ttypgrp) {
|
|
|
05ad79 |
if (pid != getsid(0)) {
|
|
|
05ad79 |
if (pid == getpgid(0))
|
|
|
05ad79 |
@@ -575,21 +600,20 @@ static void setup(struct console *con)
|
|
|
05ad79 |
* Ask for the password. Note that there is no default timeout as we normally
|
|
|
05ad79 |
* skip this during boot.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
-static char *getpasswd(struct console *con)
|
|
|
05ad79 |
+static const char *getpasswd(struct console *con)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
struct sigaction sa;
|
|
|
05ad79 |
struct termios tty;
|
|
|
05ad79 |
static char pass[128], *ptr;
|
|
|
05ad79 |
struct chardata *cp;
|
|
|
05ad79 |
- char *ret = pass;
|
|
|
05ad79 |
+ const char *ret = pass;
|
|
|
05ad79 |
unsigned char tc;
|
|
|
05ad79 |
char c, ascval;
|
|
|
05ad79 |
int eightbit;
|
|
|
05ad79 |
- int fd;
|
|
|
05ad79 |
+ const int fd = con->fd;
|
|
|
05ad79 |
|
|
|
05ad79 |
if (con->flags & CON_NOTTY)
|
|
|
05ad79 |
goto out;
|
|
|
05ad79 |
- fd = con->fd;
|
|
|
05ad79 |
cp = &con->cp;
|
|
|
05ad79 |
tty = con->tio;
|
|
|
05ad79 |
|
|
|
05ad79 |
@@ -597,6 +621,7 @@ static char *getpasswd(struct console *con)
|
|
|
05ad79 |
tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP|ISIG);
|
|
|
05ad79 |
tc = (tcsetattr(fd, TCSAFLUSH, &tty) == 0);
|
|
|
05ad79 |
|
|
|
05ad79 |
+ sigemptyset(&sa.sa_mask);
|
|
|
05ad79 |
sa.sa_handler = alrm_handler;
|
|
|
05ad79 |
sa.sa_flags = 0;
|
|
|
05ad79 |
sigaction(SIGALRM, &sa, NULL);
|
|
|
05ad79 |
@@ -615,7 +640,7 @@ static char *getpasswd(struct console *con)
|
|
|
05ad79 |
ret = NULL;
|
|
|
05ad79 |
goto quit;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
- usleep(1000);
|
|
|
05ad79 |
+ usleep(250000);
|
|
|
05ad79 |
continue;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
ret = (char*)0;
|
|
|
05ad79 |
@@ -627,7 +652,7 @@ static char *getpasswd(struct console *con)
|
|
|
05ad79 |
case ENOENT:
|
|
|
05ad79 |
break;
|
|
|
05ad79 |
default:
|
|
|
05ad79 |
- warn(_("%s: read failed"), con->tty);
|
|
|
05ad79 |
+ warn(_("cannot read %s"), con->tty);
|
|
|
05ad79 |
break;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
goto quit;
|
|
|
05ad79 |
@@ -694,8 +719,8 @@ static void sushell(struct passwd *pwd)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
char shell[PATH_MAX];
|
|
|
05ad79 |
char home[PATH_MAX];
|
|
|
05ad79 |
- char *p;
|
|
|
05ad79 |
- char *su_shell;
|
|
|
05ad79 |
+ char const *p;
|
|
|
05ad79 |
+ char const *su_shell;
|
|
|
05ad79 |
|
|
|
05ad79 |
/*
|
|
|
05ad79 |
* Set directory and shell.
|
|
|
05ad79 |
@@ -731,16 +756,16 @@ static void sushell(struct passwd *pwd)
|
|
|
05ad79 |
if (getcwd(home, sizeof(home)) == NULL)
|
|
|
05ad79 |
strcpy(home, "/");
|
|
|
05ad79 |
|
|
|
05ad79 |
- setenv("HOME", home, 1);
|
|
|
05ad79 |
- setenv("LOGNAME", "root", 1);
|
|
|
05ad79 |
- setenv("USER", "root", 1);
|
|
|
05ad79 |
+ xsetenv("HOME", home, 1);
|
|
|
05ad79 |
+ xsetenv("LOGNAME", "root", 1);
|
|
|
05ad79 |
+ xsetenv("USER", "root", 1);
|
|
|
05ad79 |
if (!profile)
|
|
|
05ad79 |
- setenv("SHLVL","0",1);
|
|
|
05ad79 |
+ xsetenv("SHLVL","0",1);
|
|
|
05ad79 |
|
|
|
05ad79 |
/*
|
|
|
05ad79 |
* Try to execute a shell.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
- setenv("SHELL", su_shell, 1);
|
|
|
05ad79 |
+ xsetenv("SHELL", su_shell, 1);
|
|
|
05ad79 |
unmask_signal(SIGINT, &saved_sigint);
|
|
|
05ad79 |
unmask_signal(SIGTSTP, &saved_sigtstp);
|
|
|
05ad79 |
unmask_signal(SIGQUIT, &saved_sigquit);
|
|
|
05ad79 |
@@ -765,17 +790,21 @@ static void sushell(struct passwd *pwd)
|
|
|
05ad79 |
execl(su_shell, shell, NULL);
|
|
|
05ad79 |
warn(_("failed to execute %s"), su_shell);
|
|
|
05ad79 |
|
|
|
05ad79 |
- setenv("SHELL", "/bin/sh", 1);
|
|
|
05ad79 |
+ xsetenv("SHELL", "/bin/sh", 1);
|
|
|
05ad79 |
execl("/bin/sh", profile ? "-sh" : "sh", NULL);
|
|
|
05ad79 |
warn(_("failed to execute %s"), "/bin/sh");
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
-static void usage(FILE *out)
|
|
|
05ad79 |
+static void usage(void)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
+ FILE *out = stdout;
|
|
|
05ad79 |
fputs(USAGE_HEADER, out);
|
|
|
05ad79 |
fprintf(out, _(
|
|
|
05ad79 |
" %s [options] [tty device]\n"), program_invocation_short_name);
|
|
|
05ad79 |
|
|
|
05ad79 |
+ fputs(USAGE_SEPARATOR, out);
|
|
|
05ad79 |
+ fputs(_("Single-user login.\n"), out);
|
|
|
05ad79 |
+
|
|
|
05ad79 |
fputs(USAGE_OPTIONS, out);
|
|
|
05ad79 |
fputs(_(" -p, --login-shell start a login shell\n"
|
|
|
05ad79 |
" -t, --timeout <seconds> max time to wait for a password (default: no limit)\n"
|
|
|
05ad79 |
@@ -783,32 +812,35 @@ static void usage(FILE *out)
|
|
|
05ad79 |
out);
|
|
|
05ad79 |
|
|
|
05ad79 |
fputs(USAGE_SEPARATOR, out);
|
|
|
05ad79 |
- fputs(USAGE_HELP, out);
|
|
|
05ad79 |
- fputs(USAGE_VERSION, out);
|
|
|
05ad79 |
- fprintf(out, USAGE_MAN_TAIL("sulogin(8)"));
|
|
|
05ad79 |
+ printf(USAGE_HELP_OPTIONS(26));
|
|
|
05ad79 |
+ printf(USAGE_MAN_TAIL("sulogin(8)"));
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
int main(int argc, char **argv)
|
|
|
05ad79 |
{
|
|
|
05ad79 |
- LIST_HEAD(consoles);
|
|
|
05ad79 |
- struct list_head *ptr;
|
|
|
05ad79 |
+ struct list_head *ptr, consoles;
|
|
|
05ad79 |
struct console *con;
|
|
|
05ad79 |
char *tty = NULL;
|
|
|
05ad79 |
struct passwd *pwd;
|
|
|
05ad79 |
- int c, status = 0;
|
|
|
05ad79 |
- int reconnect = 0;
|
|
|
05ad79 |
+ const struct timespec sigwait = { .tv_sec = 0, .tv_nsec = 50000000 };
|
|
|
05ad79 |
+ siginfo_t status = { 0 };
|
|
|
05ad79 |
+ sigset_t set;
|
|
|
05ad79 |
+ int c, reconnect = 0;
|
|
|
05ad79 |
int opt_e = 0;
|
|
|
05ad79 |
+ int wait = 0;
|
|
|
05ad79 |
pid_t pid;
|
|
|
05ad79 |
|
|
|
05ad79 |
static const struct option longopts[] = {
|
|
|
05ad79 |
- { "login-shell", 0, 0, 'p' },
|
|
|
05ad79 |
- { "timeout", 1, 0, 't' },
|
|
|
05ad79 |
- { "force", 0, 0, 'e' },
|
|
|
05ad79 |
- { "help", 0, 0, 'h' },
|
|
|
05ad79 |
- { "version", 0, 0, 'V' },
|
|
|
05ad79 |
- { NULL, 0, 0, 0 }
|
|
|
05ad79 |
+ { "login-shell", no_argument, NULL, 'p' },
|
|
|
05ad79 |
+ { "timeout", required_argument, NULL, 't' },
|
|
|
05ad79 |
+ { "force", no_argument, NULL, 'e' },
|
|
|
05ad79 |
+ { "help", no_argument, NULL, 'h' },
|
|
|
05ad79 |
+ { "version", no_argument, NULL, 'V' },
|
|
|
05ad79 |
+ { NULL, 0, NULL, 0 }
|
|
|
05ad79 |
};
|
|
|
05ad79 |
|
|
|
05ad79 |
+ INIT_LIST_HEAD(&consoles);
|
|
|
05ad79 |
+
|
|
|
05ad79 |
/*
|
|
|
05ad79 |
* If we are init we need to set up a own session.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
@@ -840,17 +872,16 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
printf(UTIL_LINUX_VERSION);
|
|
|
05ad79 |
return EXIT_SUCCESS;
|
|
|
05ad79 |
case 'h':
|
|
|
05ad79 |
- usage(stdout);
|
|
|
05ad79 |
+ usage();
|
|
|
05ad79 |
return EXIT_SUCCESS;
|
|
|
05ad79 |
default:
|
|
|
05ad79 |
- usage(stderr);
|
|
|
05ad79 |
- /* Do not exit! */
|
|
|
05ad79 |
+ /* Do not exit! getopt prints a warning. */
|
|
|
05ad79 |
break;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
if (geteuid() != 0)
|
|
|
05ad79 |
- errx(EXIT_FAILURE, _("only root can run this program."));
|
|
|
05ad79 |
+ errx(EXIT_FAILURE, _("only superuser can run this program"));
|
|
|
05ad79 |
|
|
|
05ad79 |
mask_signal(SIGQUIT, SIG_IGN, &saved_sigquit);
|
|
|
05ad79 |
mask_signal(SIGTSTP, SIG_IGN, &saved_sigtstp);
|
|
|
05ad79 |
@@ -877,7 +908,7 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
reconnect = detect_consoles(tty, STDIN_FILENO, &consoles);
|
|
|
05ad79 |
|
|
|
05ad79 |
/*
|
|
|
05ad79 |
- * If previous stdin was not the speified tty and therefore reconnected
|
|
|
05ad79 |
+ * If previous stdin was not the specified tty and therefore reconnected
|
|
|
05ad79 |
* to the specified tty also reconnect stdout and stderr.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
if (reconnect) {
|
|
|
05ad79 |
@@ -900,7 +931,7 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
* Get the root password.
|
|
|
05ad79 |
*/
|
|
|
05ad79 |
if ((pwd = getrootpwent(opt_e)) == NULL) {
|
|
|
05ad79 |
- warnx(_("cannot open password database."));
|
|
|
05ad79 |
+ warnx(_("cannot open password database"));
|
|
|
05ad79 |
sleep(2);
|
|
|
05ad79 |
return EXIT_FAILURE;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
@@ -923,9 +954,6 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
tcinit(con);
|
|
|
05ad79 |
}
|
|
|
05ad79 |
ptr = (&consoles)->next;
|
|
|
05ad79 |
- usemask = (uint32_t*) mmap(NULL, sizeof(uint32_t),
|
|
|
05ad79 |
- PROT_READ|PROT_WRITE,
|
|
|
05ad79 |
- MAP_ANONYMOUS|MAP_SHARED, -1, 0);
|
|
|
05ad79 |
|
|
|
05ad79 |
if (ptr->next == &consoles) {
|
|
|
05ad79 |
con = list_entry(ptr, struct console, entry);
|
|
|
05ad79 |
@@ -942,7 +970,6 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
switch ((con->pid = fork())) {
|
|
|
05ad79 |
case 0:
|
|
|
05ad79 |
mask_signal(SIGCHLD, SIG_DFL, NULL);
|
|
|
05ad79 |
- /* fall through */
|
|
|
05ad79 |
nofork:
|
|
|
05ad79 |
setup(con);
|
|
|
05ad79 |
while (1) {
|
|
|
05ad79 |
@@ -971,9 +998,7 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
if (doshell) {
|
|
|
05ad79 |
- *usemask |= (1<<con->id);
|
|
|
05ad79 |
sushell(pwd);
|
|
|
05ad79 |
- *usemask &= ~(1<<con->id);
|
|
|
05ad79 |
failed++;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
|
|
|
05ad79 |
@@ -982,7 +1007,7 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
mask_signal(SIGINT, SIG_IGN, &saved_sigint);
|
|
|
05ad79 |
|
|
|
05ad79 |
if (failed) {
|
|
|
05ad79 |
- fprintf(stderr, _("Can not execute su shell\n\n"));
|
|
|
05ad79 |
+ fprintf(stderr, _("cannot execute su shell\n\n"));
|
|
|
05ad79 |
break;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
fprintf(stderr, _("Login incorrect\n\n"));
|
|
|
05ad79 |
@@ -997,7 +1022,7 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
exit(0);
|
|
|
05ad79 |
case -1:
|
|
|
05ad79 |
warn(_("fork failed"));
|
|
|
05ad79 |
- /* fall through */
|
|
|
05ad79 |
+ /* fallthrough */
|
|
|
05ad79 |
default:
|
|
|
05ad79 |
break;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
@@ -1006,28 +1031,80 @@ int main(int argc, char **argv)
|
|
|
05ad79 |
|
|
|
05ad79 |
} while (ptr != &consoles);
|
|
|
05ad79 |
|
|
|
05ad79 |
- while ((pid = wait(&status))) {
|
|
|
05ad79 |
- if (errno == ECHILD)
|
|
|
05ad79 |
+ do {
|
|
|
05ad79 |
+ int ret;
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ status.si_pid = 0;
|
|
|
05ad79 |
+ ret = waitid(P_ALL, 0, &status, WEXITED);
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ if (ret == 0)
|
|
|
05ad79 |
break;
|
|
|
05ad79 |
- if (pid < 0)
|
|
|
05ad79 |
- continue;
|
|
|
05ad79 |
- list_for_each(ptr, &consoles) {
|
|
|
05ad79 |
- con = list_entry(ptr, struct console, entry);
|
|
|
05ad79 |
- if (con->pid == pid) {
|
|
|
05ad79 |
- *usemask &= ~(1<<con->id);
|
|
|
05ad79 |
+ if (ret < 0) {
|
|
|
05ad79 |
+ if (errno == ECHILD)
|
|
|
05ad79 |
+ break;
|
|
|
05ad79 |
+ if (errno == EINTR)
|
|
|
05ad79 |
continue;
|
|
|
05ad79 |
- }
|
|
|
05ad79 |
- if (kill(con->pid, 0) < 0) {
|
|
|
05ad79 |
- *usemask &= ~(1<<con->id);
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ errx(EXIT_FAILURE, _("cannot wait on su shell\n\n"));
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ } while (1);
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ list_for_each(ptr, &consoles) {
|
|
|
05ad79 |
+ con = list_entry(ptr, struct console, entry);
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ if (con->fd < 0)
|
|
|
05ad79 |
+ continue;
|
|
|
05ad79 |
+ if (con->pid < 0)
|
|
|
05ad79 |
+ continue;
|
|
|
05ad79 |
+ if (con->pid == status.si_pid)
|
|
|
05ad79 |
+ con->pid = -1;
|
|
|
05ad79 |
+ else {
|
|
|
05ad79 |
+ kill(con->pid, SIGTERM);
|
|
|
05ad79 |
+ wait++;
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ sigemptyset(&set);
|
|
|
05ad79 |
+ sigaddset(&set, SIGCHLD);
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ do {
|
|
|
05ad79 |
+ int signum, ret;
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ if (!wait)
|
|
|
05ad79 |
+ break;
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ status.si_pid = 0;
|
|
|
05ad79 |
+ ret = waitid(P_ALL, 0, &status, WEXITED|WNOHANG);
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ if (ret < 0) {
|
|
|
05ad79 |
+ if (errno == ECHILD)
|
|
|
05ad79 |
+ break;
|
|
|
05ad79 |
+ if (errno == EINTR)
|
|
|
05ad79 |
continue;
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ if (!ret && status.si_pid > 0) {
|
|
|
05ad79 |
+ list_for_each(ptr, &consoles) {
|
|
|
05ad79 |
+ con = list_entry(ptr, struct console, entry);
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ if (con->fd < 0)
|
|
|
05ad79 |
+ continue;
|
|
|
05ad79 |
+ if (con->pid < 0)
|
|
|
05ad79 |
+ continue;
|
|
|
05ad79 |
+ if (con->pid == status.si_pid) {
|
|
|
05ad79 |
+ con->pid = -1;
|
|
|
05ad79 |
+ wait--;
|
|
|
05ad79 |
+ }
|
|
|
05ad79 |
}
|
|
|
05ad79 |
- if (*usemask & (1<<con->id))
|
|
|
05ad79 |
- continue;
|
|
|
05ad79 |
- kill(con->pid, SIGHUP);
|
|
|
05ad79 |
- usleep(5000);
|
|
|
05ad79 |
- kill(con->pid, SIGKILL);
|
|
|
05ad79 |
+ continue;
|
|
|
05ad79 |
}
|
|
|
05ad79 |
- }
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ signum = sigtimedwait(&set, NULL, &sigwait);
|
|
|
05ad79 |
+ if (signum != SIGCHLD && signum < 0 && errno == EAGAIN)
|
|
|
05ad79 |
+ break;
|
|
|
05ad79 |
+
|
|
|
05ad79 |
+ } while (1);
|
|
|
05ad79 |
|
|
|
05ad79 |
mask_signal(SIGCHLD, SIG_DFL, NULL);
|
|
|
05ad79 |
return EXIT_SUCCESS;
|
|
|
05ad79 |
--
|
|
|
05ad79 |
2.14.4
|
|
|
05ad79 |
|