From: Boria F. <bo...@qu...> - 2001-02-27 12:39:27
|
Hi i still can't get my head round what's going on in stdio_console, chan and tty code. So several questions about it: o The only place where the code might be referring to a tty is the code from stdio_console.c which deals with vts[0], which on the chan level looks like two chan structs for input and output. Is that correct ? o So to save the state of that tty, one would need to put something like if(isatty(chan->fd)) save_tty_state_attrs(); into open_fd, which would perhaps introduce a slight perfomance problem, as only a very small fraction of the fd's will refer to a tty. o I couldn't find the code that closes fd's which chan opens, i'm assuming this is done automagically. In that case, the only way to restore terminal settings which i could find was to introduce something like a chan_close() and chan_pair_close() functions, which would be called by con_close() to restore the state of a tty. Am i going in the right direction? TIA boria |
From: Jeff D. <jd...@ka...> - 2001-02-27 15:10:48
|
bo...@qu... said: > o The only place where the code might be referring to a tty is the > code from stdio_console.c which deals with vts[0], which on the chan > level looks like two chan structs for input and output. Is that > correct ? Any console or serial line may be passed 'fd:0,fd:1' or 'tty:/dev/tty0', which would make them refer to a tty. > o So to save the state of that tty, one would need to put something > like if(isatty(chan->fd)) save_tty_state_attrs(); into open_fd, which > would perhaps introduce a slight perfomance problem, as only a very > small fraction of the fd's will refer to a tty. You'll need to kmalloc a struct termios to save the state in. Make it void * as chan.data.fd. > o I couldn't find the code that closes fd's which chan opens, i'm > assuming this is done automagically. In that case, the only way to > restore terminal settings which i could find was to introduce > something like a chan_close() and chan_pair_close() functions, which > would be called by con_close() to restore the state of a tty. Yup. Except I don't think the main console ever really gets closed for the last time. That will probably require some halt callbacks similar to the __init ones. To get around that, you might experiment with putting another console on a host virtual console and make sure that its modes get restored correctly. > Am i going in the right direction? So far, so good. Jeff |
From: Boria F. <bo...@qu...> - 2001-02-27 23:13:53
|
On Tue, Feb 27, 2001 at 11:23:10AM -0500, Jeff Dike wrote: > You'll need to kmalloc a struct termios to save the state in. Make it void * > as chan.data.fd. > Hi in struct chan, data is a union, so if i were to put a member fd into that union to hold attrs it would overwrite the char *tty member. As these two almost always will go together, i have just created a struct tty inside union data with char *name and void* fd_data as it's members. > Except I don't think the main console ever really gets closed for the last > time. That will probably require some halt callbacks similar to the __init > ones. To get around that, you might experiment with putting another console > on a host virtual console and make sure that its modes get restored correctly. > This seems to be correct. I have ran the code with my changes(see diffs below) several times, but during the shutdown sequence it looks like the code never closes the main console which leads to never kfree()'ing the memory which i kmalloc()'ed for tty attributes. I've tried removing the tty stuff from main.c, but the console is left in a mess which only 'stty sane' can cure, for the same reason. With these diffs, i've attached the uml virtual console #1 to host /dev/tty8 and did a 'stty --file=/dev/tty8' before, during and after running uml, the before and after versions are the same. Nevertheless, these diffs are BROKEN, they just show what i'm up to. Check them out, see if you like it. TIA, boria --- chan.h.orig Tue Feb 27 17:25:12 2001 +++ chan.h Tue Feb 27 20:53:18 2001 @@ -22,7 +22,10 @@ void (*announce)(char *dev_name, int dev); int dev; } pty, pts; - char *tty; + struct { + void *fd_data; + char *name; + } tty; struct { int port; int connected; @@ -50,7 +53,7 @@ { XTERM, -1, 0, 0, pri, { xterm: { -1, n, title } } } #define TTY_CHAN_INIT(dev, pri) \ - { TTY, -1, 0, 0, pri, { tty: dev } } + { TTY, -1, 0, 0, pri, { tty: { NULL, dev } } } #define SOCK_CHAN_INIT(port, pri) \ { SOCKET, -1, 0, 0, pri, { sock: { port, 0, -1 } } } @@ -96,12 +99,15 @@ extern void tty_receive_char(void *tty_ptr, char ch); extern int open_chan_pair(struct io_chan *chan, int (*irq_setup)(int fd, void *data), void *data); +extern int close_chan_pair(struct io_chan *chan); extern int open_fd(struct chan *chan); extern int open_xterm(struct chan *chan); extern int open_pty(struct chan *chan); extern int open_tty(struct chan *chan); extern int open_pts(struct chan *chan); extern int open_socket(struct chan *chan); +extern int close_fd(struct chan *chan); +extern int close_tty(struct chan *chan); extern int write_chan(struct io_chan *chan, const char *buf, int len); extern int parse_chan_pair(char *str, int device, struct io_chan *chan, int pri, struct chan_opts *opts); --- chan_kern.c.orig Tue Feb 27 17:25:12 2001 +++ chan_kern.c Tue Feb 27 21:31:15 2001 @@ -114,6 +114,40 @@ return(err); } +static int close_chan(struct chan *chan) +{ + int err; + + if(!chan->opened) return(0); + switch(chan->type){ + case FD: + err = close_fd(chan); + break; + case TTY: + err = close_tty(chan); + break; + + default: + return(0); + break; + } + chan->opened = 0; + + return(err); +} + +int close_chan_pair(struct io_chan *chan) +{ + int err; + + err = close_chan(&chan->in); + if(err) return(err); + if(chan->out.type != COPY) + err = close_chan(&chan->out); + return(err); +} + + int write_chan(struct io_chan *chan, const char *buf, int len) { struct chan *c; --- chan_user.c.orig Tue Feb 27 17:25:12 2001 +++ chan_user.c Tue Feb 27 22:31:23 2001 @@ -9,6 +9,7 @@ #include <unistd.h> #include <errno.h> #include <fcntl.h> +#include <termios.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> @@ -43,10 +44,28 @@ int open_fd(struct chan *chan) { + if(isatty(chan->fd)){ + chan->data.tty.fd_data = kmalloc(sizeof(struct termios), 7); + if(!chan->data.tty.fd_data) printk("Malloc termios failed, ignoring\n"); + else if(tcgetattr(chan->fd, chan->data.tty.fd_data) < 0) + printf("tcgetattr() failed, chan->fd = %d \n", chan->fd); + } raw(chan->fd, 0); return(0); } +int close_fd(struct chan *chan) +{ + if(isatty(chan->fd) && chan->data.tty.fd_data){ + if(tcsetattr(chan->fd, TCSANOW, chan->data.tty.fd_data) < 0) + panic("tcsetattr() failed, chan->fd = %d\n", chan->fd); + kfree(chan->data.tty.fd_data); + chan->data.tty.fd_data = NULL; + } + + return(0); +} + struct xterm_info { char tty[2]; int fd; @@ -113,13 +132,30 @@ { int fd; - fd = open(chan->data.tty, O_RDWR); + fd = open(chan->data.tty.name, O_RDWR); if(fd < 0) return(-errno); chan->fd = fd; + + chan->data.tty.fd_data = kmalloc(sizeof(struct termios), 7); + if(!chan->data.tty.fd_data) printk("Mallocing termios failed, ignoring\n"); + else if(tcgetattr(chan->fd, chan->data.tty.fd_data) < 0) + panic("tcgetattr() for tty failed, fd: %d, name: %s, errno: %s\n", chan->fd, chan->data.tty.name, strerror(errno)); + raw(fd, 1); return(0); } +int close_tty(struct chan *chan) +{ + if(chan->data.tty.fd_data){ + if(tcsetattr(chan->fd, TCSANOW, chan->data.tty.fd_data) < 0) + printf("tcsetattr() for tty failed, fd: %d, name: %s, errno: %s\n", chan->fd, chan->data.tty.name, strerror(errno)); + kfree(chan->data.tty.fd_data); + chan->data.tty.fd_data = NULL; + } + return(0); +} + int open_pts(struct chan *chan) { int fd; --- ssl.c.orig Tue Feb 27 17:25:12 2001 +++ ssl.c Tue Feb 27 19:35:13 2001 @@ -87,7 +87,10 @@ line = MINOR(tty->device) - tty->driver.minor_start; private[line].count--; - if(private[line].count == 0) private[line].tty = NULL; + if(private[line].count == 0){ + private[line].tty = NULL; + close_chan_pair(&private[line].chan); + } } static int ssl_write(struct tty_struct * tty, int from_user, --- stdio_console.c.orig Tue Feb 27 17:25:12 2001 +++ stdio_console.c Tue Feb 27 22:43:26 2001 @@ -88,7 +88,7 @@ int line; line = MINOR(tty->device) - tty->driver.minor_start; - vts[line].count--; + if(--vts[line].count == 0) close_chan_pair(&vts[line].chan); } static int con_write(struct tty_struct * tty, int from_user, |