serial console and log-in

Natanael Copa natanael.copa at gmail.com
Tue Mar 6 05:00:51 PST 2007


On Thu, 2007-03-01 at 00:26 +0100, Denis Vlasenko wrote:
> On Wednesday 28 February 2007 15:50, Natanael Copa wrote:
> > > > I backported the svn init to 1.4.1 (i depend on releases).
> > > > 
> > > > My inittab line looks like this:
> > > > 
> > > > ::respawn:/sbin/getty - 9600 vt100
> > > > 
> > > > I got a login prompt but no controlling tty:
> > > > 
> > > > -ash: cant't access tty; job control turned off
> > > > 
> > > > ~$ echo TEST > /dev/tty
> > > > -ash: cannot create /dev/tty: No such device or address
> > > > 
> > > > That was on a VGA console.
> > > > 
> > > > Then I tried to run it in qemu, with -nographic. It booted, it gave me a
> > > > login, but same as VGA, no controlling tty.
> > > 
> > > I expected that. It stems from the fact that /dev/console
> > > cannot be a ctty.
> > > 
> > > I'm not sure this can be classified as 'bug'.
> > 
> > Probably not. But then I need another feature :-/
> > 
> > Something like running a specified row only when controlling terminal is
> > serial.
> > 
> > ttyS0:serial:respawn:/sbin/getty -L ttyS0 9600 vt100
> > 
> > Drawback is that it needs to use an unused field in inittab.
> 
> How about writing small hack which analyzes stdin (fd #0)
> and closes fd #0,1,2 + reopens/dups /dev/ttyN or /dev/ttySn:
> 
> 
> /* 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 fd;
>         struct vt_stat vt;
>         struct serial_struct sr;
>         char console[64];
> 
>         /* identify the real console backend and try to use it */
>         if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
>                 /* this is a serial console */
>                 snprintf(console, sizeof(console) - 1, "/dev/ttyS%d", sr.line);
>         } else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
>                 /* this is linux virtual tty */
>                 snprintf(console, sizeof(console) - 1, "/dev/tty%d", vt.v_active);
>         } else {
>                /* unable to figure it out */
>                ...
>         }
> 
> 	fd = xopen(console, O_RDWR);
> 	dup2(fd, 0);
> 	dup2(fd, 1);
> 	dup2(fd, 2);
> 	while (fd > 2) close(fd--);
> 
> then exec it's argv?
> 
> Use it like this:
> 
> ::respawn:/somewhere/cttyhack /sbin/getty - 9600 vt100
> 
> Care to try? ;)

I tried this. This works. Does the job. However, its is hackish as you
said:

~ $ who
USER       TTY      IDLE      TIME           HOST
root       -        ?         Mar  6 12:39   
root       tty2     .         Mar  6 12:48   

Note that TTY ends up as -
Are there any drawback with this? Can this make other programs behave
strange?

Another hackish way to solve it would be to have a 'is_serial_tty'
binary in the initramfs:

/* is_serial_tty.c */
int main() {
        return (ioctl(0, TIOCGSERIAL, &sr) != 0);
}

and then copy a second inittab to new root, before running switchroot.

if is_serial_tty ; then
	cp inittab.serial /new_root/etc
fi

This is also hackish and I don't know whats worst.

I'm seriously thinking of writing a new init, based on the upstart
ideas. (unlike runinit, it will reuse sysv init.d scripts)


> --
> vda



More information about the busybox mailing list