summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makemodule.am6
-rw-r--r--lib/consoles.c781
2 files changed, 0 insertions, 787 deletions
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index d3cf8928d..81e20b106 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -28,7 +28,6 @@ libcommon_la_SOURCES = \
if LINUX
libcommon_la_SOURCES += \
- lib/consoles.c \
lib/linux_version.c \
lib/loopdev.c
endif
@@ -62,7 +61,6 @@ endif
check_PROGRAMS += \
test_sysfs \
test_loopdev \
- test_consoles \
test_pager
endif
@@ -110,10 +108,6 @@ test_pager_CFLAGS = -DTEST_PROGRAM
test_loopdev_SOURCES = lib/loopdev.c
test_loopdev_CFLAGS = -DTEST_PROGRAM_LOOPDEV
test_loopdev_LDADD = libcommon.la
-
-test_consoles_SOURCES = lib/consoles.c
-test_consoles_CFLAGS = -DTEST_PROGRAM
-test_consoles_LDADD = libcommon.la
endif
test_fileutils_SOURCES = lib/fileutils.c
diff --git a/lib/consoles.c b/lib/consoles.c
deleted file mode 100644
index 7175a0882..000000000
--- a/lib/consoles.c
+++ /dev/null
@@ -1,781 +0,0 @@
-/*
- * consoles.c Routines to detect the system consoles
- *
- * Copyright (c) 2011 SuSE LINUX Products GmbH, All rights reserved.
- * Copyright (C) 2012 Karel Zak <kzak@redhat.com>
- * Copyright (C) 2012 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 <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#ifdef __linux__
-# include <sys/vt.h>
-# include <sys/kd.h>
-# include <linux/serial.h>
-#endif
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-
-#ifdef USE_SULOGIN_EMERGENCY_MOUNT
-# include <sys/mount.h>
-# include <linux/fs.h>
-# include <linux/magic.h>
-# include <linux/major.h>
-# ifndef MNT_DETACH
-# define MNT_DETACH 2
-# endif
-#endif
-
-#include "c.h"
-#include "canonicalize.h"
-#include "consoles.h"
-
-#ifdef __linux__
-# include <linux/major.h>
-#endif
-
-#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
-# ifndef typeof
-# define typeof __typeof__
-# endif
-# ifndef restrict
-# define restrict __restrict__
-# endif
-#endif
-
-#define alignof(type) ((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1))
-#define strsize(string) (strlen((string))+1)
-
-static int consoles_debug;
-#define DBG(x) do { \
- if (consoles_debug) { \
- fputs("consoles debug: ", stderr); \
- x; \
- } \
- } while (0)
-
-static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
-dbgprint(const char *mesg, ...)
-{
- va_list ap;
- va_start(ap, mesg);
- vfprintf(stderr, mesg, ap);
- va_end(ap);
- fputc('\n', stderr);
-}
-
-#ifdef USE_SULOGIN_EMERGENCY_MOUNT
-/*
- * Make C library standard calls such like ttyname(3) work
- * even if the system does not show any of the standard
- * directories.
- */
-
-static uint32_t emergency_flags;
-# define MNT_PROCFS 0x0001
-# define MNT_DEVTMPFS 0x0002
-
-static __attribute__((__destructor__))
-void emergency_do_umounts(void)
-{
- if (emergency_flags & MNT_DEVTMPFS)
- umount2("/dev", MNT_DETACH);
- if (emergency_flags & MNT_PROCFS)
- umount2("/proc", MNT_DETACH);
-}
-
-static __attribute__((__constructor__))
-void emergency_do_mounts(void)
-{
- struct stat rt, xt;
-
- if (emergency_flags) {
- emergency_flags = 0;
- return;
- }
-
- if (stat("/", &rt) != 0) {
- warn("can not get file status of root file system\n");
- return;
- }
-
- if (stat("/proc", &xt) == 0
- && rt.st_dev == xt.st_dev
- && mount("proc", "/proc", "proc", MS_RELATIME, NULL) == 0)
- emergency_flags |= MNT_PROCFS;
-
- if (stat("/dev", &xt) == 0
- && rt.st_dev == xt.st_dev
- && mount("devtmpfs", "/dev", "devtmpfs",
- MS_RELATIME, "mode=0755,nr_inodes=0") == 0) {
-
- emergency_flags |= MNT_DEVTMPFS;
- mknod("/dev/console", S_IFCHR|S_IRUSR|S_IWUSR,
- makedev(TTYAUX_MAJOR, 1));
-
- if (symlink("/proc/self/fd", "/dev/fd") == 0) {
- ignore_result( symlink("fd/0", "/dev/stdin") );
- ignore_result( symlink("fd/1", "/dev/stdout") );
- ignore_result( symlink("fd/2", "/dev/stderr") );
- }
- }
-}
-#endif /* USE_SULOGIN_EMERGENCY_MOUNT */
-
-/*
- * Read and allocate one line from file,
- * the caller has to free the result
- */
-static __attribute__((__nonnull__))
-char *oneline(const char *file)
-{
- FILE *fp;
- char *ret = NULL;
- size_t len = 0;
-
- DBG(dbgprint("reading %s", file));
-
- if (!(fp = fopen(file, "re")))
- return NULL;
- if (getline(&ret, &len, fp) >= 0) {
- char *nl;
-
- if (len)
- ret[len-1] = '\0';
- if ((nl = strchr(ret, '\n')))
- *nl = '\0';
- }
-
- fclose(fp);
- return ret;
-}
-
-#ifdef __linux__
-/*
- * Read and determine active attribute for tty below
- * /sys/class/tty, the caller has to free the result.
- */
-static __attribute__((__malloc__))
-char *actattr(const char *tty)
-{
- char *ret, *path;
-
- if (!tty || !*tty)
- return NULL;
- if (asprintf(&path, "/sys/class/tty/%s/active", tty) < 0)
- return NULL;
-
- ret = oneline(path);
- free(path);
- return ret;
-}
-
-/*
- * Read and determine device attribute for tty below
- * /sys/class/tty.
- */
-static
-dev_t devattr(const char *tty)
-{
- dev_t dev = 0;
- char *path, *value;
-
- if (!tty || !*tty)
- return 0;
- if (asprintf(&path, "/sys/class/tty/%s/dev", tty) < 0)
- return 0;
-
- value = oneline(path);
- if (value) {
- unsigned int maj, min;
-
- if (sscanf(value, "%u:%u", &maj, &min) == 2)
- dev = makedev(maj, min);
- free(value);
- }
-
- free(path);
- return dev;
-}
-#endif /* __linux__ */
-
-/*
- * Search below /dev for the characer device in `dev_t comparedev' variable.
- */
-static
-#ifdef __GNUC__
-__attribute__((__nonnull__,__malloc__,__hot__))
-#endif
-char* scandev(DIR *dir, dev_t comparedev)
-{
- char *name = NULL;
- struct dirent *dent;
- int fd;
-
- DBG(dbgprint("scanning /dev for %u:%u", major(comparedev), minor(comparedev)));
-
- fd = dirfd(dir);
- rewinddir(dir);
- while ((dent = readdir(dir))) {
- char path[PATH_MAX];
- struct stat st;
- if (fstatat(fd, dent->d_name, &st, 0) < 0)
- continue;
- if (!S_ISCHR(st.st_mode))
- continue;
- if (comparedev != st.st_rdev)
- continue;
- if ((size_t)snprintf(path, sizeof(path), "/dev/%s", dent->d_name) >= sizeof(path))
- continue;
-#ifdef USE_SULOGIN_EMERGENCY_MOUNT
- if (emergency_flags & MNT_DEVTMPFS)
- mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev);
-#endif
-
- name = canonicalize_path(path);
- break;
- }
-
- return name;
-}
-
-/*
- * Default control characters for an unknown terminal line.
- */
-
-/*
- * Allocate an aligned `struct console' memory area,
- * initialize its default values, and append it to
- * the global linked list.
- */
-static
-#ifdef __GNUC__
-__attribute__((__nonnull__,__hot__))
-#endif
-int append_console(struct list_head *consoles, const char *name)
-{
- static const struct chardata initcp = {
- .erase = CERASE,
- .kill = CKILL,
- .eol = CTRL('r'),
- .parity = 0
- };
- struct console *restrict tail;
- struct console *last = NULL;
-
- DBG(dbgprint("appenging %s", name));
-
- if (!list_empty(consoles))
- last = list_last_entry(consoles, struct console, entry);
-
- if (posix_memalign((void *) &tail, sizeof(void *),
- alignof(struct console) + strsize(name)) != 0)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&tail->entry);
-
- list_add_tail(&tail->entry, consoles);
- tail->tty = ((char *) tail) + alignof(struct console);
- strcpy(tail->tty, name);
-
- tail->file = (FILE*)0;
- tail->flags = 0;
- tail->fd = -1;
- tail->id = last ? last->id + 1 : 0;
- tail->pid = 0;
- memset(&tail->tio, 0, sizeof(tail->tio));
- memcpy(&tail->cp, &initcp, sizeof(struct chardata));
-
- return 0;
-}
-
-#ifdef __linux__
-/*
- * return codes:
- * < 0 - fatal error (no mem or so... )
- * 0 - success
- * 1 - recoverable error
- * 2 - detection not available
- */
-static int detect_consoles_from_proc(struct list_head *consoles)
-{
- char fbuf[16 + 1];
- DIR *dir = NULL;
- FILE *fc = NULL;
- int maj, min, rc = 1;
-
- DBG(dbgprint("trying /proc"));
-
- fc = fopen("/proc/consoles", "re");
- if (!fc) {
- rc = 2;
- goto done;
- }
- dir = opendir("/dev");
- if (!dir)
- goto done;
-
- while (fscanf(fc, "%*s %*s (%16[^)]) %d:%d", fbuf, &maj, &min) == 3) {
- char *name;
- dev_t comparedev;
-
- if (!strchr(fbuf, 'E'))
- continue;
- comparedev = makedev(maj, min);
- name = scandev(dir, comparedev);
- if (!name)
- continue;
- rc = append_console(consoles, name);
- free(name);
- if (rc < 0)
- goto done;
- }
-
- rc = list_empty(consoles) ? 1 : 0;
-done:
- if (dir)
- closedir(dir);
- if (fc)
- fclose(fc);
- DBG(dbgprint("[/proc rc=%d]", rc));
- return rc;
-}
-
-/*
- * return codes:
- * < 0 - fatal error (no mem or so... )
- * 0 - success
- * 1 - recoverable error
- * 2 - detection not available
- */
-static int detect_consoles_from_sysfs(struct list_head *consoles)
-{
- char *attrib = NULL, *words, *token;
- DIR *dir = NULL;
- int rc = 1;
-
- DBG(dbgprint("trying /sys"));
-
- attrib = actattr("console");
- if (!attrib) {
- rc = 2;
- goto done;
- }
-
- words = attrib;
-
- dir = opendir("/dev");
- if (!dir)
- goto done;
-
- while ((token = strsep(&words, " \t\r\n"))) {
- char *name;
- dev_t comparedev;
-
- if (*token == '\0')
- continue;
-
- comparedev = devattr(token);
- if (comparedev == makedev(TTY_MAJOR, 0)) {
- char *tmp = actattr(token);
- if (!tmp)
- continue;
- comparedev = devattr(tmp);
- free(tmp);
- }
-
- name = scandev(dir, comparedev);
- if (!name)
- continue;
- rc = append_console(consoles, name);
- free(name);
- if (rc < 0)
- goto done;
- }
-
- rc = list_empty(consoles) ? 1 : 0;
-done:
- free(attrib);
- if (dir)
- closedir(dir);
- DBG(dbgprint("[/sys rc=%d]", rc));
- return rc;
-}
-
-
-static int detect_consoles_from_cmdline(struct list_head *consoles)
-{
- char *cmdline, *words, *token;
- dev_t comparedev;
- DIR *dir = NULL;
- int rc = 1, fd;
-
- DBG(dbgprint("trying kernel cmdline"));
-
- cmdline = oneline("/proc/cmdline");
- if (!cmdline) {
- rc = 2;
- goto done;
- }
-
- words= cmdline;
- dir = opendir("/dev");
- if (!dir)
- goto done;
-
- while ((token = strsep(&words, " \t\r\n"))) {
-#ifdef TIOCGDEV
- unsigned int devnum;
-#else
- struct vt_stat vt;
- struct stat st;
-#endif
- char *colon, *name;
-
- if (*token != 'c')
- continue;
- if (strncmp(token, "console=", 8) != 0)
- continue;
- token += 8;
-
- if (strcmp(token, "brl") == 0)
- token += 4;
- if ((colon = strchr(token, ',')))
- *colon = '\0';
-
- if (asprintf(&name, "/dev/%s", token) < 0)
- continue;
- if ((fd = open(name, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC)) < 0) {
- free(name);
- continue;
- }
- free(name);
-#ifdef TIOCGDEV
- if (ioctl (fd, TIOCGDEV, &devnum) < 0) {
- close(fd);
- continue;
- }
- comparedev = (dev_t) devnum;
-#else
- if (fstat(fd, &st) < 0) {
- close(fd);
- continue;
- }
- comparedev = st.st_rdev;
- if (comparedev == makedev(TTY_MAJOR, 0)) {
- if (ioctl(fd, VT_GETSTATE, &vt) < 0) {
- close(fd);
- continue;
- }
- comparedev = makedev(TTY_MAJOR, (int)vt.v_active);
- }
-#endif
- close(fd);
-
- name = scandev(dir, comparedev);
- if (!name)
- continue;
- rc = append_console(consoles, name);
- free(name);
- if (rc < 0)
- goto done;
- }
-
- rc = list_empty(consoles) ? 1 : 0;
-done:
- if (dir)
- closedir(dir);
- free(cmdline);
- DBG(dbgprint("[kernel cmdline rc=%d]", rc));
- return rc;
-}
-
-static int detect_consoles_from_tiocgdev(struct list_head *consoles,
- int fallback,
- const char *device)
-{
-#ifdef TIOCGDEV
- unsigned int devnum;
- char *name;
- int rc = 1, fd = -1;
- dev_t comparedev;
- DIR *dir = NULL;
- struct console *console;
-
- DBG(dbgprint("trying tiocgdev"));
-
- if (!device || !*device)
- fd = dup(fallback);
- else
- fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
-
- if (fd < 0)
- goto done;
- if (ioctl (fd, TIOCGDEV, &devnum) < 0)
- goto done;
-
- comparedev = (dev_t) devnum;
- dir = opendir("/dev");
- if (!dir)
- goto done;
-
- name = scandev(dir, comparedev);
- closedir(dir);
-
- if (!name) {
- name = (char *) (device && *device ? device : ttyname(fallback));
- if (!name)
- name = "/dev/tty1";
-
- name = strdup(name);
- if (!name) {
- rc = -ENOMEM;
- goto done;
- }
- }
- rc = append_console(consoles, name);
- free(name);
- if (rc < 0)
- goto done;
- if (list_empty(consoles)) {
- rc = 1;
- goto done;
- }
- console = list_last_entry(consoles, struct console, entry);
- if (console && (!device || !*device))
- console->fd = fallback;
-done:
- if (fd >= 0)
- close(fd);
- DBG(dbgprint("[tiocgdev rc=%d]", rc));
- return rc;
-#endif
- return 2;
-}
-#endif /* __linux__ */
-
-/*
- * Try to detect the real device(s) used for the system console
- * /dev/console if but only if /dev/console is used. On Linux
- * this can be more than one device, e.g. a serial line as well
- * as a virtual console as well as a simple printer.
- *
- * Returns 1 if stdout and stderr should be reconnected and 0
- * otherwise or less than zero on error.
- */
-int detect_consoles(const char *device, int fallback, struct list_head *consoles)
-{
- int fd, reconnect = 0, rc;
- dev_t comparedev = 0;
-
- consoles_debug = getenv("CONSOLES_DEBUG") ? 1 : 0;
-
- if (!device || !*device)
- fd = dup(fallback);
- else {
- fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
- reconnect = 1;
- }
-
- DBG(dbgprint("detection started [device=%s, fallback=%d]",
- device, fallback));
-
- if (fd >= 0) {
- DIR *dir;
- char *name;
- struct stat st;
-#ifdef TIOCGDEV
- unsigned int devnum;
-#endif
- DBG(dbgprint("trying device/fallback file descriptor"));
-
- if (fstat(fd, &st) < 0) {
- close(fd);
- goto fallback;
- }
- comparedev = st.st_rdev;
-
- if (reconnect &&
- (fstat(fallback, &st) < 0 || comparedev != st.st_rdev))
- dup2(fd, fallback);
-#ifdef __linux__
- /*
- * Check if the device detection for Linux system console should be used.
- */
- if (comparedev == makedev(TTYAUX_MAJOR, 0)) { /* /dev/tty */
- close(fd);
- device = "/dev/tty";
- goto fallback;
- }
- if (comparedev == makedev(TTYAUX_MAJOR, 1)) { /* /dev/console */
- close(fd);
- goto console;
- }
- if (comparedev == makedev(TTYAUX_MAJOR, 2)) { /* /dev/ptmx */
- close(fd);
- device = "/dev/tty";
- goto fallback;
- }
- if (comparedev == makedev(TTY_MAJOR, 0)) { /* /dev/tty0 */
- struct vt_stat vt;
- if (ioctl(fd, VT_GETSTATE, &vt) < 0) {
- close(fd);
- goto fallback;
- }
- comparedev = makedev(TTY_MAJOR, (int)vt.v_active);
- }
-#endif
-#ifdef TIOCGDEV
- if (ioctl (fd, TIOCGDEV, &devnum) < 0) {
- close(fd);
- goto fallback;
- }
- comparedev = (dev_t)devnum;
-#endif
- close(fd);
- dir = opendir("/dev");
- if (!dir)
- goto fallback;
- name = scandev(dir, comparedev);
- closedir(dir);
-
- if (name) {
- rc = append_console(consoles, name);
- free(name);
- if (rc < 0)
- return rc;
- }
- if (list_empty(consoles))
- goto fallback;
-
- DBG(dbgprint("detection success [rc=%d]", reconnect));
- return reconnect;
- }
-#ifdef __linux__
-console:
- /*
- * Detection of devices used for Linux system consolei using
- * the /proc/consoles API with kernel 2.6.38 and higher.
- */
- rc = detect_consoles_from_proc(consoles);
- if (rc == 0)
- return reconnect; /* success */
- if (rc < 0)
- return rc; /* fatal error */
-
- /*
- * Detection of devices used for Linux system console using
- * the sysfs /sys/class/tty/ API with kernel 2.6.37 and higher.
- */
- rc = detect_consoles_from_sysfs(consoles);
- if (rc == 0)
- return reconnect; /* success */
- if (rc < 0)
- return rc; /* fatal error */
-
- /*
- * Detection of devices used for Linux system console using
- * kernel parameter on the kernels command line.
- */
- rc = detect_consoles_from_cmdline(consoles);
- if (rc == 0)
- return reconnect; /* success */
- if (rc < 0)
- return rc; /* fatal error */
-
- /*
- * Detection of the device used for Linux system console using
- * the ioctl TIOCGDEV if available (e.g. official 2.6.38).
- */
- rc = detect_consoles_from_tiocgdev(consoles, fallback, device);
- if (rc == 0)
- return reconnect; /* success */
- if (rc < 0)
- return rc; /* fatal error */
-
- if (!list_empty(consoles)) {
- DBG(dbgprint("detection success [rc=%d]", reconnect));
- return reconnect;
- }
-
-#endif /* __linux __ */
-
-fallback:
- if (fallback >= 0) {
- const char *name;
- struct console *console;
-
- if (device && *device != '\0')
- name = device;
- else name = ttyname(fallback);
-
- if (!name)
- name = "/dev/tty";
-
- rc = append_console(consoles, strdup(name));
- if (rc < 0)
- return rc;
- if (list_empty(consoles))
- return 1;
- console = list_last_entry(consoles, struct console, entry);
- if (console)
- console->fd = fallback;
- }
-
- DBG(dbgprint("detection done by fallback [rc=%d]", reconnect));
- return reconnect;
-}
-
-
-#ifdef TEST_PROGRAM
-int main(int argc, char *argv[])
-{
- char *name = NULL;
- int fd, re;
- LIST_HEAD(consoles);
- struct list_head *p;
-
- if (argc == 2) {
- name = argv[1];
- fd = open(name, O_RDWR);
- } else {
- name = ttyname(STDIN_FILENO);
- fd = STDIN_FILENO;
- }
-
- if (!name)
- errx(EXIT_FAILURE, "usage: %s [<tty>]\n", program_invocation_short_name);
-
- re = detect_consoles(name, fd, &consoles);
-
- list_for_each(p, &consoles) {
- struct console *c = list_entry(p, struct console, entry);
- printf("%s: id=%d %s\n", c->tty, c->id, re ? "(reconnect) " : "");
- }
-
- return 0;
-}
-#endif