sysvinit/showconsole-1.08.dif

600 lines
14 KiB
Plaintext

--- blogd.c
+++ blogd.c 2006-08-10 18:41:55.000000000 +0200
@@ -155,25 +155,60 @@ static void reset_signal(int sig, struct
* To be able to reconnect to real tty on EIO
*/
static char * tty;
+static char * second;
static void reconnect(int fd)
{
int newfd = -1;
- if ((newfd = open(tty, O_WRONLY|O_NONBLOCK|O_NOCTTY)) < 0)
- error("can not open %s: %s\n", tty, strerror(errno));
-
- if (newfd != 1)
- dup2(newfd, 1);
- if (newfd != 2)
- dup2(newfd, 2);
-
- if (fd == 1 || fd == 2)
- goto out;
- if (newfd != fd)
- dup2(newfd, fd);
-out:
- if (newfd > 2)
- close(newfd);
+ switch (fd) {
+ case 0: /* Standard in */
+
+ if (tty == (char*)0)
+ break;
+
+ if ((newfd = open(tty, O_RDWR|O_NONBLOCK|O_NOCTTY)) < 0)
+ error("can not open %s: %s\n", tty, strerror(errno));
+
+ if (newfd != 0) {
+ dup2(newfd, 0);
+ close(newfd);
+ }
+
+ break;
+
+ case 1: /* Standard out */
+ case 2: /* Standard error */
+
+ if (tty == (char*)0)
+ break;
+
+ if ((newfd = open(tty, O_WRONLY|O_NONBLOCK|O_NOCTTY)) < 0)
+ error("can not open %s: %s\n", tty, strerror(errno));
+
+ if (newfd != 1)
+ dup2(newfd, 1);
+ if (newfd != 2)
+ dup2(newfd, 2);
+ if (newfd > 2)
+ close(newfd);
+
+ break;
+
+ default: /* IO of second console */
+
+ if (second == (char*)0)
+ break;
+
+ if ((newfd = open(second, O_WRONLY|O_NONBLOCK|O_NOCTTY)) < 0)
+ error("can not open %s: %s\n", second, strerror(errno));
+
+ if (newfd != fd) {
+ dup2(newfd, fd);
+ close(newfd);
+ }
+
+ break;
+ }
}
/*
@@ -181,7 +216,7 @@ out:
*/
int main(int argc, char *argv[])
{
- int fd, flags;
+ int fd, fd2, flags;
int ptm, pts, cntrtty = 1;
pid_t pid, ppid = getppid();
char ptsname[NAME_MAX+1];
@@ -198,7 +233,7 @@ int main(int argc, char *argv[])
if (argc == 2)
tty = argv[1];
else
- tty = fetchtty(getpid(), ppid);
+ tty = fetchtty(getpid(), ppid, NULL);
if (!tty || !*tty)
error("can not discover real system console tty, boot logging disabled.\n");
@@ -241,6 +276,38 @@ int main(int argc, char *argv[])
if (!w.ws_col)
w.ws_row = 80;
+ fd2 = -1;
+ do {
+
+ if ((second = secondtty(tty)) == (char*)0)
+ break;
+
+ if ((fd2 = open(second, O_WRONLY|O_NONBLOCK|O_NOCTTY)) < 0) {
+ warn("can not open %s: %s\n", second, strerror(errno));
+ goto out;
+ }
+
+ if ((flags = fcntl(fd2, F_GETFL)) < 0) {
+ warn("can not get terminal flags of %s: %s\n", second, strerror(errno));
+ close(fd2);
+ fd2 = -1;
+ goto out;
+ }
+
+ flags &= ~(O_NONBLOCK);
+ flags |= O_NOCTTY;
+ if (fcntl(fd2, F_SETFL, flags) < 0) {
+ warn("can not set terminal flags of %s: %s\n", second, strerror(errno));
+ close(fd2);
+ fd2 = -1;
+ goto out;
+ }
+
+ out:
+ free(second);
+
+ } while (0);
+
if (openpty(&ptm, &pts, ptsname, &t, &w) < 0)
error("can not open pty/tty pair: %s\n", strerror(errno));
@@ -268,12 +335,15 @@ int main(int argc, char *argv[])
dup2(fd, 1);
dup2(fd, 2);
close(ptm);
- close(fd);
+ if (fd > 2)
+ close(fd);
break;
case -1:
close(pts);
close(ptm);
close(fd);
+ if (fd2 > 0)
+ close(fd2);
error("can not fork to become daemon: %s\n", strerror(errno));
break;
default:
@@ -282,12 +352,13 @@ int main(int argc, char *argv[])
close(pts);
close(ptm);
close(fd);
+ if (fd2 > 0)
+ close(fd2);
fprintf(stdout, "\rBoot logging started on %s(%s) at %.24s\n", tty, name, stt);
fflush(stdout);
exit(0);
}
- free(name);
- prepareIO(reconnect, pidfile, 0, 1);
+ prepareIO(reconnect, pidfile, 0, 1, fd2);
while (!signaled)
safeIO();
@@ -297,6 +368,10 @@ int main(int argc, char *argv[])
if (!cntrtty)
kill(ppid, SIGCONT);
+ if (fd2 > 0) {
+ (void)tcflush(fd2, TCOFLUSH);
+ close(fd2);
+ }
(void)tcflush(1, TCOFLUSH);
close(1);
(void)tcflush(2, TCOFLUSH);
--- libconsole.c
+++ libconsole.c 2006-08-10 18:41:23.000000000 +0200
@@ -158,41 +158,52 @@ static void (*vc_reconnect)(int fd) = NU
static inline void safeout (int fd, const char *ptr, size_t s)
{
int saveerr = errno;
- static int repeated;
+ int repeated = 0;
+ static int eiocount;
- repeated = 0;
while (s > 0) {
ssize_t p = write (fd, ptr, s);
if (p < 0) {
- if (repeated++ > 1000)
- error("Repeated error on writing to fd %d: %s\n", fd, STRERR);
- if (errno == EPIPE)
+ if (errno == EPIPE) {
+ warn("error on writing to fd %d: %s\n", fd, STRERR);
exit (0);
+ }
if (errno == EINTR) {
errno = 0;
continue;
}
if (errno == EAGAIN) { /* Kernel 2.6 seems todo this very often */
+ int ret;
fd_set check;
- struct timeval two = {2, 0};
- errno = 0;
+ if (repeated++ > 1000)
+ error("repeated error on writing to fd %d: %s\n", fd, STRERR);
+
FD_ZERO (&check);
FD_SET (fd, &check);
/* Avoid high load: wait upto two seconds if system is not ready */
- select(fd + 1, (fd_set*)0, &check, (fd_set*)0, &two);
errno = 0;
+ do {
+ struct timeval two = {2, 0};
+ ret = select(fd + 1, (fd_set*)0, &check, (fd_set*)0, &two);
+
+ } while ((ret < 0) && (errno == EINTR));
+
+ if (ret < 0)
+ error("can not write to fd %d: %s\n", fd, STRERR);
+ errno = 0;
continue;
}
- if (errno == EIO && vc_reconnect) {
+ if (errno == EIO) {
+ if ((eiocount++ > 10) || !vc_reconnect)
+ error("can not write to fd %d: %s\n", fd, STRERR);
(*vc_reconnect)(fd);
- vc_reconnect = NULL;
errno = 0;
continue;
}
- error("Can not write to fd %d: %s\n", fd, STRERR);
+ error("can not write to fd %d: %s\n", fd, STRERR);
}
repeated = 0;
ptr += p;
@@ -267,6 +278,7 @@ out:
*/
static FILE * flog = NULL;
static int fdwrite = -1;
+static int fdsec = -1;
static int fdread = -1;
static int fdfifo = -1;
@@ -714,12 +726,13 @@ static void *action(void *dummy)
static void (*rw_connect)(void) = NULL;
static const char *fifo_name = _PATH_BLOG_FIFO;
-void prepareIO(void (*rfunc)(int), void (*cfunc)(void), const int in, const int out)
+void prepareIO(void (*rfunc)(int), void (*cfunc)(void), const int in, const int out, const int second)
{
vc_reconnect = rfunc;
rw_connect = cfunc;
fdread = in;
fdwrite = out;
+ fdsec = second;
if (fifo_name && fdfifo < 0) {
struct stat st;
@@ -729,7 +742,7 @@ void prepareIO(void (*rfunc)(int), void
(void)mkfifo(fifo_name, 0600);
errno = 0;
if (!stat(fifo_name, &st) && S_ISFIFO(st.st_mode)) {
- if ((fdfifo = open(fifo_name, O_RDWR)) < 0)
+ if ((fdfifo = open(fifo_name, O_RDWR|O_NOCTTY)) < 0)
warn("can not open named fifo %s: %s\n", fifo_name, STRERR);
}
}
@@ -769,12 +782,17 @@ static void more_input (struct timeval *
const ssize_t cnt = safein(fdread, (char*)trans, sizeof(trans));
if (cnt > 0) {
- parselog(trans, cnt); /* Parse and make copy of the input */
+ parselog(trans, cnt); /* Parse and make copy of the input */
+
+ safeout(fdwrite, (char*)trans, cnt); /* Write copy of input to real tty */
+ (void)tcdrain(fdwrite);
- safeout(fdwrite, (char*)trans, cnt); /* Write copy of input to real tty */
- tcdrain(fdwrite);
+ if (fdsec > 0) {
+ safeout(fdsec, (char*)trans, cnt); /* Write copy of input to second tty */
+ (void)tcdrain(fdsec);
+ }
- flushlog();
+ flushlog();
}
}
@@ -883,6 +901,8 @@ void closeIO(void)
} else
warn("no message logging because /var file system is not accessible\n");
(void)tcdrain(fdwrite); /* Hold in sync with console */
+ if (fdsec > 0)
+ (void)tcdrain(fdsec); /* Hold in sync with second console */
do {
/*
@@ -926,6 +946,8 @@ void closeIO(void)
flog = NULL;
xout:
(void)tcdrain(fdwrite);
+ if (fdsec > 0)
+ (void)tcdrain(fdsec);
return;
}
@@ -941,7 +963,7 @@ static void ctty(pid_t pid, unsigned int
int fd;
sprintf(fetched, "/proc/%d/stat", (int)pid);
- if ((fd = open(fetched, O_RDONLY)) < 0)
+ if ((fd = open(fetched, O_RDONLY|O_NOCTTY)) < 0)
error("can not open(%s): %s\n", fetched, STRERR);
cnt = safein(fd, fetched, sizeof(fetched));
close(fd);
@@ -1034,12 +1056,11 @@ static int checkdev(char ** retname, uns
int found = 0;
struct dirent * d;
struct stat st;
- char * name = NULL;
static int deep;
memset(&st, 0, sizeof(struct stat));
while ((d = readdir(dev))) {
- name = d->d_name;
+ char * name = d->d_name;
if (*name == '.')
continue;
@@ -1143,6 +1164,14 @@ static int checkdev(char ** retname, uns
}
found++;
+
+ /*
+ * Allocate memory to be able to return several
+ * different buffers for different files names.
+ */
+ name = strdup(name);
+ if (!name)
+ error("checkdev(): %s\n", STRERR);
*retname = name;
break;
}
@@ -1151,7 +1180,7 @@ static int checkdev(char ** retname, uns
}
/* main routine to fetch tty */
-char * fetchtty(const pid_t pid, const pid_t ppid)
+char * fetchtty(const pid_t pid, const pid_t ppid, unsigned int *mjmi)
{
unsigned int tty = 0, found = 0;
char * name = NULL;
@@ -1167,14 +1196,15 @@ char * fetchtty(const pid_t pid, const p
if (!(name = ttyname(0)) || !strcmp(name, "/dev/console"))
tty = fallback(pid, ppid);
else {
- strcpy(lnk, name);
- free(name);
- name = lnk;
+ name = strdup(name);
+ if (!name)
+ error("fetchtty(): %s\n", STRERR);
goto out;
}
#ifdef TIOCGDEV
}
#endif
+ if (mjmi) *mjmi = tty;
if (!(dev = opendir("/dev")))
error("can not opendir(/dev): %s\n", STRERR);
@@ -1186,8 +1216,131 @@ char * fetchtty(const pid_t pid, const p
if (!name)
goto out;
- if (!found)
- *name = '\0';
+ if (!found) {
+ free(name);
+ name = (char*)0;
+ }
out:
return name;
}
+
+/* Do we have some more system console around? */
+char * secondtty(char * compare)
+{
+ char buf[1024], *ptr, *shcmp, *res = (char*)0;
+ unsigned int tty = 0, found = 0;
+ int fd = -1, len;
+ char * name = (char*)0;
+ DIR * dev;
+
+ if ((fd = open("/proc/cmdline", O_RDONLY|O_NOCTTY)) < 0) {
+ warn("can not open /proc/cmdline\n");
+ goto out;
+ }
+
+ if ((len = read(fd, buf, sizeof(buf) - 1)) < 0) {
+ warn("can not read /proc/cmdline\n");
+ close(fd);
+ goto out;
+ }
+ close(fd);
+
+ if (len == 0)
+ goto out;
+
+ shcmp = compare;
+ if (!strncmp(shcmp, "/dev/", 5))
+ shcmp += 5;
+
+ /*
+ * Check for e.g. /dev/tty[1-9] which is equal to /dev/tty0
+ */
+ if (!strncmp(shcmp, "tty", 3)) {
+ size_t len = strspn(shcmp + 3, "123456789");
+
+ if (strlen(shcmp) == len + 3) {
+ compare = "/dev/tty0";
+ shcmp = "tty0";
+ }
+ }
+
+ ptr = &buf[len];
+ while (ptr >= &buf[0]) {
+ if (*ptr == ',' || *ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') {
+ *ptr-- = 0;
+ continue;
+ }
+ if (*ptr == 'c' && !strncmp(ptr, "console=", 8)) {
+ char * console = ptr + 8;
+
+ if (!strncmp(console, "/dev/", 5))
+ console += 5;
+
+ /*
+ * Compare known console tty with that of the kernel command
+ * line. If already known skip this console tty and search
+ * for the next one.
+ */
+ if (strcmp(shcmp, console)) {
+ res = console; /* New device not identical to tty */
+ break;
+ }
+ }
+ ptr--;
+ }
+
+ if (!res)
+ goto out;
+
+ if (!(dev = opendir("/dev")))
+ error("can not opendir(/dev): %s\n", STRERR);
+ pushd("/dev");
+
+ /* Open second console e.g. /dev/tty0 */
+ if ((fd = open(res, O_RDWR|O_NONBLOCK|O_NOCTTY)) < 0)
+ goto out;
+
+ /*
+ * We do this because if we would write out the buffered
+ * messages to e.g. /dev/tty0 after this we would (re)read
+ * those and buffer them again which leads to an endless loop.
+ */
+#ifdef TIOCGDEV
+ if (ioctl (fd, TIOCGDEV, &tty) < 0) {
+ if (errno == EINVAL && !getenv("NOTIOCGDEV"))
+ warn("Warning: the ioctl TIOCGDEV is not known by the kernel\n");
+ close(fd);
+ popd();
+ closedir(dev);
+ goto out;
+ }
+#else
+# error The ioctl TIOCGDEV is not defined (SuSE TIOCGDEV patch is missed)
+#endif
+ close(fd);
+
+ /* Try to open the real device e.g. /dev/tty1 */
+ found = checkdev(&name, tty, dev);
+
+ popd();
+ closedir(dev);
+
+ if (!name)
+ goto out;
+
+ if (!found) {
+ free(name);
+ name = (char*)0;
+ goto out;
+ }
+
+ if (!strcmp(compare, name)) {
+ free(name);
+ name = (char*)0;
+ goto out; /* Already in use */
+ }
+
+ return name;
+out:
+ return (char*)0;
+}
--- libconsole.h
+++ libconsole.h 2006-08-10 18:41:28.000000000 +0200
@@ -1,6 +1,7 @@
extern void pushd(const char * path);
extern void popd(void);
-extern char * fetchtty(const pid_t pid, const pid_t ppid);
-extern void prepareIO(void (*rfunc)(int), void (*cfunc)(void), const int in, const int out);
+extern char * fetchtty(const pid_t pid, const pid_t ppid, unsigned int *mjmi);
+extern char * secondtty(char * compare);
+extern void prepareIO(void (*rfunc)(int), void (*cfunc)(void), const int in, const int out, const int second);
extern void safeIO (void);
extern void closeIO(void);
--- showconsole.8
+++ showconsole.8 2006-08-10 18:55:37.000000000 +0200
@@ -16,6 +16,7 @@ Setconsole \- sets the underlying tty of
.SH SYNOPSIS
.\"
.B showconsole
+.RI [ -n ]
.PP
.B setconsole /dev/tty<xy> < /dev/console
.SH DESCRIPTION
@@ -38,6 +39,15 @@ with
and exactly one argument, a valid character device
is given.
\."
+.SH OPTIONS
+.TP
+.B \-n
+Return the major and minor device numbers instead of
+the device file name. This can be used to asked the
+kernel for the major and minor device numbers of a not
+existing device file in
+.IR /dev .
+\."
.SH BUGS
.B showconsole
needs a mounted
--- showconsole.c
+++ showconsole.c 2006-08-10 18:51:15.000000000 +0200
@@ -51,7 +51,7 @@ void warn (const char *fmt, ...)
*/
int main(int argc, char *argv[])
{
- char * tty = NULL;
+ char * tty = NULL, numeric = 0;
myname = basename(*argv);
if (!strcmp(myname, "setconsole")) {
@@ -73,8 +73,30 @@ int main(int argc, char *argv[])
close(fdc);
goto out;
}
- tty = fetchtty(getpid(), getppid());
- if (tty)
+
+ if (argc == 2) {
+ const char* opt = argv[1];
+ if (opt && *opt++ == '-' && *opt++ == 'n' && *opt == '\0')
+ numeric++;
+ else
+ error("Usage: %s [-n]\n", myname);
+ } else if (argc > 2)
+ error("Usage: %s [-n]\n", myname);
+
+ if (numeric) {
+ unsigned int dev = 0;
+ (void)fetchtty(getpid(), getppid(), &dev);
+
+ if (dev)
+ printf("%u %u\n", major(dev), minor(dev));
+ else {
+ error("real tty unknown\n");
+ fprintf(stderr, "real tty unknown\n");
+ }
+ goto out;
+ }
+
+ if ((tty = fetchtty(getpid(), getppid(), NULL)))
printf("%s\n", tty);
else {
error("real tty unknown\n");