| #include <stdio.h> |
| #include <unistd.h> |
| #include <signal.h> |
| #include <sched.h> |
| #include <errno.h> |
| #include <termios.h> |
| #include <fcntl.h> |
| #include <sys/select.h> |
| #include <sys/time.h> |
| #include "stdio_console.h" |
| #include "user_util.h" |
| #include "kern_util.h" |
| #include "user.h" |
| |
| void stdio_write(int fd, const char *string, int len) |
| { |
| static int need_cr = 0; |
| int i; |
| |
| for(i=0;i<len;i++){ |
| if(*string == '\n') need_cr = 1; |
| else if(need_cr){ |
| if(*string != '\r') write(fd, "\r", 1); |
| need_cr = 0; |
| } |
| write(fd, string++, 1); |
| } |
| } |
| |
| void stdio_rcv_proc(int fd) |
| { |
| int n; |
| char ch; |
| |
| while((n = read(fd, &ch, sizeof(ch))) == sizeof(ch)){ |
| stdio_receive_char(fd, ch); |
| } |
| if((n < 0) && (errno != EAGAIN)) |
| printk("stdio_rcv_proc read failed, errno = %d\n", errno); |
| enable_fd(fd); |
| } |
| |
| void setup_fd(int fd) |
| { |
| struct termios tt; |
| unsigned long flags; |
| |
| flags = fcntl(fd, F_GETFL); |
| flags |= O_NONBLOCK; |
| flags &= ~O_ASYNC; |
| if(fcntl(fd, F_SETFL, flags) < 0){ |
| perror("fcntl setting flags"); |
| return; |
| } |
| tcgetattr(fd, &tt); |
| cfmakeraw(&tt); |
| if(tcsetattr(fd, TCSADRAIN, &tt) < 0){ |
| printk("tcsetattr failed, errno = %d\n", errno); |
| panic("stdio receive thread couldn't set fd raw"); |
| } |
| } |
| |
| struct xterm_info { |
| char tty[2]; |
| int fd; |
| int console_num; |
| int *pid_out; |
| }; |
| |
| static void xterm_tramp(void *arg) |
| { |
| struct xterm_info *info; |
| int pid; |
| char title[sizeof("Virtual Console nn\0")], flag[sizeof("Sxxnn\0")]; |
| |
| info = arg; |
| sprintf(flag, "-S%c%c%d", info->tty[0], info->tty[1], info->fd); |
| sprintf(title, "Virtual Console %d", info->console_num); |
| if((pid = fork()) != 0) *info->pid_out = pid; |
| else { |
| execlp("xterm", "xterm", flag, "-T", title, NULL); |
| exit(1); |
| } |
| } |
| |
| int open_vt(int n, int *pid_out) |
| { |
| struct xterm_info info; |
| int master, slave; |
| char dev[] = "/dev/ptyXX", c; |
| |
| master = getmaster(dev); |
| dev[strlen("/dev/")] = 't'; |
| slave = open(dev, O_RDWR); |
| if(slave != -1){ |
| info.tty[0] = dev[strlen("/dev/pty")]; |
| info.tty[1] = dev[strlen("/dev/ptyX")]; |
| info.fd = master; |
| info.console_num = n; |
| info.pid_out = pid_out; |
| input_cb(xterm_tramp, &info, sizeof(info)); |
| while((read(slave, &c, sizeof(c)) == sizeof(c)) && (c != '\n')) ; |
| } |
| setup_fd(slave); |
| return(slave); |
| } |