serial console and log-in
Natanael Copa
natanael.copa at gmail.com
Tue Mar 6 13:00:51 UTC 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