Commit 04301c1f authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] uml: clean up terminal state handling

This patch cleans up UML's handling of terminal state with better error
handling, interface cleanup, and some code tidying.
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 02fe18c5
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <termios.h> #include <termios.h>
#include <errno.h>
#include "user.h" #include "user.h"
#include "user_util.h" #include "user_util.h"
#include "chan_user.h" #include "chan_user.h"
...@@ -45,10 +46,16 @@ void *fd_init(char *str, int device, struct chan_opts *opts) ...@@ -45,10 +46,16 @@ void *fd_init(char *str, int device, struct chan_opts *opts)
int fd_open(int input, int output, int primary, void *d, char **dev_out) int fd_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct fd_chan *data = d; struct fd_chan *data = d;
int err;
if(data->raw && isatty(data->fd)){ if(data->raw && isatty(data->fd)){
tcgetattr(data->fd, &data->tt); CATCH_EINTR(err = tcgetattr(data->fd, &data->tt));
raw(data->fd, 0); if(err)
return(err);
err = raw(data->fd);
if(err)
return(err);
} }
sprintf(data->str, "%d", data->fd); sprintf(data->str, "%d", data->fd);
*dev_out = data->str; *dev_out = data->str;
...@@ -58,9 +65,13 @@ int fd_open(int input, int output, int primary, void *d, char **dev_out) ...@@ -58,9 +65,13 @@ int fd_open(int input, int output, int primary, void *d, char **dev_out)
void fd_close(int fd, void *d) void fd_close(int fd, void *d)
{ {
struct fd_chan *data = d; struct fd_chan *data = d;
int err;
if(data->raw && isatty(fd)){ if(data->raw && isatty(fd)){
tcsetattr(fd, TCSAFLUSH, &data->tt); CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt));
if(err)
printk("Failed to restore terminal state - "
"errno = %d\n", -err);
data->raw = 0; data->raw = 0;
} }
} }
......
...@@ -76,12 +76,17 @@ void port_free(void *d) ...@@ -76,12 +76,17 @@ void port_free(void *d)
int port_open(int input, int output, int primary, void *d, char **dev_out) int port_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct port_chan *data = d; struct port_chan *data = d;
int fd; int fd, err;
fd = port_wait(data->kernel_data); fd = port_wait(data->kernel_data);
if((fd >= 0) && data->raw){ if((fd >= 0) && data->raw){
tcgetattr(fd, &data->tt); CATCH_EINTR(err = tcgetattr(fd, &data->tt));
raw(fd, 0); if(err)
return(err);
err = raw(fd);
if(err)
return(err);
} }
*dev_out = data->dev; *dev_out = data->dev;
return(fd); return(fd);
......
...@@ -38,7 +38,7 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out) ...@@ -38,7 +38,7 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct pty_chan *data = d; struct pty_chan *data = d;
char *dev; char *dev;
int fd; int fd, err;
fd = get_pty(); fd = get_pty();
if(fd < 0){ if(fd < 0){
...@@ -46,8 +46,13 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out) ...@@ -46,8 +46,13 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out)
return(-errno); return(-errno);
} }
if(data->raw){ if(data->raw){
tcgetattr(fd, &data->tt); CATCH_EINTR(err = tcgetattr(fd, &data->tt));
raw(fd, 0); if(err)
return(err);
err = raw(fd);
if(err)
return(err);
} }
dev = ptsname(fd); dev = ptsname(fd);
...@@ -89,13 +94,19 @@ int getmaster(char *line) ...@@ -89,13 +94,19 @@ int getmaster(char *line)
int pty_open(int input, int output, int primary, void *d, char **dev_out) int pty_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct pty_chan *data = d; struct pty_chan *data = d;
int fd; int fd, err;
char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx"; char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
fd = getmaster(dev); fd = getmaster(dev);
if(fd < 0) return(-errno); if(fd < 0)
return(-errno);
if(data->raw){
err = raw(fd);
if(err)
return(err);
}
if(data->raw) raw(fd, 0);
if(data->announce) (*data->announce)(dev, data->dev); if(data->announce) (*data->announce)(dev, data->dev);
sprintf(data->dev_name, "%s", dev); sprintf(data->dev_name, "%s", dev);
......
...@@ -41,13 +41,18 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts) ...@@ -41,13 +41,18 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts)
int tty_open(int input, int output, int primary, void *d, char **dev_out) int tty_open(int input, int output, int primary, void *d, char **dev_out)
{ {
struct tty_chan *data = d; struct tty_chan *data = d;
int fd; int fd, err;
fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0); fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0);
if(fd < 0) return(fd); if(fd < 0) return(fd);
if(data->raw){ if(data->raw){
tcgetattr(fd, &data->tt); CATCH_EINTR(err = tcgetattr(fd, &data->tt));
raw(fd, 0); if(err)
return(err);
err = raw(fd);
if(err)
return(err);
} }
*dev_out = data->dev; *dev_out = data->dev;
......
...@@ -142,8 +142,19 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out) ...@@ -142,8 +142,19 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out)
goto out; goto out;
} }
tcgetattr(new, &data->tt); CATCH_EINTR(err = tcgetattr(new, &data->tt));
if(data->raw) raw(new, 0); if(err){
new = err;
goto out;
}
if(data->raw){
err = raw(new);
if(err){
new = err;
goto out;
}
}
data->pid = pid; data->pid = pid;
*dev_out = NULL; *dev_out = NULL;
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "sysdep/ptrace.h" #include "sysdep/ptrace.h"
#define CATCH_EINTR(expr) while (((expr) < 0) && (errno == EINTR))
extern int mode_tt; extern int mode_tt;
extern int grantpt(int __fd); extern int grantpt(int __fd);
...@@ -89,11 +91,8 @@ extern void forward_pending_sigio(int target); ...@@ -89,11 +91,8 @@ extern void forward_pending_sigio(int target);
extern int can_do_skas(void); extern int can_do_skas(void);
extern void arch_init_thread(void); extern void arch_init_thread(void);
extern int setjmp_wrapper(void (*proc)(void *, void *), ...); extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
extern int raw(int fd);
extern int __raw(int fd, int complain, int now);
#define raw(fd, complain) __raw((fd), (complain), 1)
#define CATCH_EINTR(expr) while ( ((expr) < 0) && errno == EINTR)
#endif #endif
/* /*
......
...@@ -68,7 +68,8 @@ void __init check_one_sigio(void (*proc)(int, int)) ...@@ -68,7 +68,8 @@ void __init check_one_sigio(void (*proc)(int, int))
return; return;
} }
err = __raw(master, 1, 0); //Not now, but complain so we now where we failed. /* Not now, but complain so we now where we failed. */
err = raw(master);
if (err < 0) if (err < 0)
panic("check_sigio : __raw failed, errno = %d\n", -err); panic("check_sigio : __raw failed, errno = %d\n", -err);
......
...@@ -118,35 +118,26 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay) ...@@ -118,35 +118,26 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay)
} }
} }
int __raw(int fd, int complain, int now) int raw(int fd)
{ {
struct termios tt; struct termios tt;
int err; int err;
int when;
CATCH_EINTR(err = tcgetattr(fd, &tt)); CATCH_EINTR(err = tcgetattr(fd, &tt));
if (err < 0) { if (err < 0) {
if (complain)
printk("tcgetattr failed, errno = %d\n", errno); printk("tcgetattr failed, errno = %d\n", errno);
return(-errno); return(-errno);
} }
cfmakeraw(&tt); cfmakeraw(&tt);
if (now) CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
when = TCSANOW;
else
when = TCSADRAIN;
CATCH_EINTR(err = tcsetattr(fd, when, &tt));
if (err < 0) { if (err < 0) {
if (complain)
printk("tcsetattr failed, errno = %d\n", errno); printk("tcsetattr failed, errno = %d\n", errno);
return(-errno); return(-errno);
} }
/*XXX: tcsetattr could have applied only some changes
/* XXX tcsetattr could have applied only some changes
* (and cfmakeraw() is a set of changes) */ * (and cfmakeraw() is a set of changes) */
return(0); return(0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment