cttyhack: new applet.
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 18 May 2007 09:45:36 +0000 (09:45 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 18 May 2007 09:45:36 +0000 (09:45 -0000)
coreutils/sleep.c
include/applets.h
shell/Config.in
shell/Kbuild
shell/cttyhack.c [new file with mode: 0644]

index b758de33b0054bfd4ba3b958f849d8123cdcdbc4..592005babf7f377f885b5a412db6ce036cf5adae 100644 (file)
@@ -61,8 +61,6 @@ int sleep_main(int argc, char **argv)
 #endif /* FEATURE_FANCY_SLEEP */
 
        if (sleep(duration)) {
-//for hush debugging:
-sleep(1);
                bb_perror_nomsg_and_die();
        }
 
index 99e6aceb5211823d9f2a804db6e13ff1c50a83b2..e4dff119a63963a39bdf581d30d0a846dcd244b1 100644 (file)
@@ -102,6 +102,7 @@ USE_CPIO(APPLET(cpio, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_CROND(APPLET(crond, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
 USE_CRONTAB(APPLET(crontab, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
 USE_CRYPTPW(APPLET(cryptpw, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_CTTYHACK(APPLET_NOUSAGE(cttyhack, cttyhack, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_CUT(APPLET_NOEXEC(cut, cut, _BB_DIR_USR_BIN, _BB_SUID_NEVER, cut))
 USE_DATE(APPLET(date, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_DC(APPLET(dc, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
index 027993483792380312cc50c9a27f98edc471619b..253752bc3281505fb6a433ddc3bbd8005cec5630 100644 (file)
@@ -270,4 +270,24 @@ config FEATURE_SH_STANDALONE
 #        that exact location with that exact name, this option will not work at
 #        all.
 
+config CTTYHACK
+       bool "cttyhack"
+       default n
+       help
+         One common problem reported on the mailing list is "can't access tty;
+         job control turned off" error message which typically appears when
+         one tries to use shell with stdin/stdout opened to /dev/console.
+         This device is special - it cannot be a controlling tty.
+
+         Proper solution is to use correct device instead of /dev/console.
+
+         cttyhack provides "quick and dirty" solution to this problem.
+         It analyzes stdin with various ioctls, trying to determine whether
+         it is a /dev/ttyN or /dev/ttySN (virtual terminal or serial line).
+         If it detects one, it closes stdin/out/err and reopens that device.
+         Then it executes given program. Usage example for /etc/inittab
+         (for busybox init):
+
+         ::respawn:/bin/cttyhack /bin/sh
+
 endmenu
index 6b58040fcb94d38459d932d7a02e2939405b6be8..944eaff51ea859f322a2375b1fe5b62e2f8e9963 100644 (file)
@@ -9,3 +9,5 @@ lib-$(CONFIG_ASH)  += ash.o
 lib-$(CONFIG_HUSH) += hush.o
 lib-$(CONFIG_LASH) += lash.o
 lib-$(CONFIG_MSH)  += msh.o
+
+lib-$(CONFIG_CTTYHACK) += cttyhack.o
diff --git a/shell/cttyhack.c b/shell/cttyhack.c
new file mode 100644 (file)
index 0000000..cdd0ed1
--- /dev/null
@@ -0,0 +1,73 @@
+/* This code is adapted from busybox project
+ *
+ * Licensed under GPLv2
+ */
+#include "libbb.h"
+
+/* From <linux/vt.h> */
+struct vt_stat {
+       unsigned short v_active;        /* active vt */
+       unsigned short v_signal;        /* signal to send */
+       unsigned short v_state; /* vt bitmask */
+};
+enum { VT_GETSTATE = 0x5603 }; /* get global vt state info */
+
+/* From <linux/serial.h> */
+struct serial_struct {
+       int     type;
+       int     line;
+       unsigned int    port;
+       int     irq;
+       int     flags;
+       int     xmit_fifo_size;
+       int     custom_divisor;
+       int     baud_base;
+       unsigned short  close_delay;
+       char    io_type;
+       char    reserved_char[1];
+       int     hub6;
+       unsigned short  closing_wait; /* time to wait before closing */
+       unsigned short  closing_wait2; /* no longer used... */
+       unsigned char   *iomem_base;
+       unsigned short  iomem_reg_shift;
+       unsigned int    port_high;
+       unsigned long   iomap_base;     /* cookie passed into ioremap */
+       int     reserved[1];
+};
+
+int cttyhack_main(int argc, char **argv) ATTRIBUTE_NORETURN;
+int cttyhack_main(int argc, char **argv)
+{
+       int fd;
+       char console[sizeof(int)*3 + 16];
+       union {
+               struct vt_stat vt;
+               struct serial_struct sr;
+               char paranoia[sizeof(struct serial_struct) * 3];
+       } u;
+
+       if (!*++argv) {
+               bb_show_usage();
+       }
+
+       strcpy(console, "/dev/tty");
+       if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) {
+               /* this is a serial console */
+               sprintf(console + 8, "S%d", u.sr.line);
+       } else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) {
+               /* this is linux virtual tty */
+               sprintf(console + 8, "S%d" + 1, u.vt.v_active);
+       }
+
+       if (console[8]) {
+               fd = xopen(console, O_RDWR);
+               //bb_error_msg("switching to '%s'", console);
+               dup2(fd, 0);
+               dup2(fd, 1);
+               dup2(fd, 2);
+               while (fd > 2) close(fd--);
+       }
+
+       execvp(argv[0], argv);
+       bb_perror_msg_and_die("cannot exec '%s'", argv[0]);
+}