//TerminalHandler TerminalHandler::TerminalHandler(Compositor& comp) { const char* number = getenv("XDG_VTNR"); if(!number) { throw std::runtime_error("tty::tty: XDG_VTNR not set"); return; } number_ = std::stoi(number); //open tty std::string ttyString = "/dev/tty" + std::to_string(number_); tty_ = open(ttyString.c_str(), O_RDWR | O_NOCTTY | O_CLOEXEC); if(tty_ < 0) { throw std::runtime_error("TerminalHandler::TerminalHandler: couldnt open " + ttyString); return; } int fd = tty_; //save current vt_stat state; if(ioctl(fd, VT_GETSTATE, &state) == -1) { throw std::runtime_error("could not get current tty"); return; } //set it up if(ioctl(tty_, VT_ACTIVATE, number_) == -1 || ioctl(tty_, VT_WAITACTIVE, number_) == -1) { throw std::runtime_error("Could not activate tty"); return; } focus_ = 1; /* if (ioctl(fd, KDSKBMUTE, 1) == -1 && ioctl(fd, KDSKBMODE, K_OFF) == -1) { throw std::runtime_error("failed to set tty keyboard mode"); return; } if(ioctl(fd, KDSETMODE, KD_GRAPHICS) == -1) { throw std::runtime_error("Could not set tty to graphics mode"); return; } */ vt_mode mode; mode.mode = VT_PROCESS; mode.acqsig = SIGUSR1; mode.relsig = SIGUSR2; if(ioctl(fd, VT_SETMODE, &mode) == -1) { throw std::runtime_error("Could not set vt_mode"); return; } wl_event_loop_add_signal(&comp.wlEventLoop(), SIGUSR1, ttySignalhandler, this); wl_event_loop_add_signal(&comp.wlEventLoop(), SIGUSR2, ttySignalhandler, this); }
WL_EXPORT int module_init(struct weston_compositor *compositor, int *argc, char *argv[]) { struct wl_display *display = compositor->wl_display; struct weston_xserver *wxs; char lockfile[256], display_name[8]; wxs = zalloc(sizeof *wxs); if (wxs == NULL) return -1; wxs->process.cleanup = weston_xserver_cleanup; wxs->wl_display = display; wxs->compositor = compositor; wxs->display = 0; retry: if (create_lockfile(wxs->display, lockfile, sizeof lockfile) < 0) { if (errno == EAGAIN) { goto retry; } else if (errno == EEXIST) { wxs->display++; goto retry; } else { free(wxs); return -1; } } wxs->abstract_fd = bind_to_abstract_socket(wxs->display); if (wxs->abstract_fd < 0 && errno == EADDRINUSE) { wxs->display++; unlink(lockfile); goto retry; } wxs->unix_fd = bind_to_unix_socket(wxs->display); if (wxs->unix_fd < 0) { unlink(lockfile); close(wxs->abstract_fd); free(wxs); return -1; } snprintf(display_name, sizeof display_name, ":%d", wxs->display); weston_log("xserver listening on display %s\n", display_name); setenv("DISPLAY", display_name, 1); wxs->loop = wl_display_get_event_loop(display); wxs->abstract_source = wl_event_loop_add_fd(wxs->loop, wxs->abstract_fd, WL_EVENT_READABLE, weston_xserver_handle_event, wxs); wxs->unix_source = wl_event_loop_add_fd(wxs->loop, wxs->unix_fd, WL_EVENT_READABLE, weston_xserver_handle_event, wxs); wxs->sigusr1_source = wl_event_loop_add_signal(wxs->loop, SIGUSR1, handle_sigusr1, wxs); wxs->destroy_listener.notify = weston_xserver_destroy; wl_signal_add(&compositor->destroy_signal, &wxs->destroy_listener); return 0; }
struct tty * tty_create(struct weston_compositor *compositor, tty_vt_func_t vt_func, int tty_nr) { struct termios raw_attributes; struct vt_mode mode = { 0 }; int ret; struct tty *tty; struct wl_event_loop *loop; struct stat buf; char filename[16]; struct vt_stat vts; tty = malloc(sizeof *tty); if (tty == NULL) return NULL; memset(tty, 0, sizeof *tty); tty->compositor = compositor; tty->vt_func = vt_func; tty->fd = weston_environment_get_fd("WESTON_TTY_FD"); if (tty->fd < 0) tty->fd = STDIN_FILENO; if (tty_nr > 0) { snprintf(filename, sizeof filename, "/dev/tty%d", tty_nr); fprintf(stderr, "compositor: using %s\n", filename); tty->fd = open(filename, O_RDWR | O_NOCTTY | O_CLOEXEC); tty->vt = tty_nr; } else if (fstat(tty->fd, &buf) == 0 && major(buf.st_rdev) == TTY_MAJOR && minor(buf.st_rdev) > 0) { if (tty->fd == STDIN_FILENO) tty->fd = fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC, 0); tty->vt = minor(buf.st_rdev); } else { /* Fall back to try opening a new VT. This typically * requires root. */ tty->fd = try_open_vt(tty); } if (tty->fd <= 0) { fprintf(stderr, "failed to open tty: %m\n"); free(tty); return NULL; } if (ioctl(tty->fd, VT_GETSTATE, &vts) == 0) tty->starting_vt = vts.v_active; else tty->starting_vt = tty->vt; if (tty->starting_vt != tty->vt) { if (ioctl(tty->fd, VT_ACTIVATE, tty->vt) < 0 || ioctl(tty->fd, VT_WAITACTIVE, tty->vt) < 0) { fprintf(stderr, "failed to swtich to new vt\n"); return NULL; } } if (tcgetattr(tty->fd, &tty->terminal_attributes) < 0) { fprintf(stderr, "could not get terminal attributes: %m\n"); goto err; } /* Ignore control characters and disable echo */ raw_attributes = tty->terminal_attributes; cfmakeraw(&raw_attributes); /* Fix up line endings to be normal (cfmakeraw hoses them) */ raw_attributes.c_oflag |= OPOST | OCRNL; if (tcsetattr(tty->fd, TCSANOW, &raw_attributes) < 0) fprintf(stderr, "could not put terminal into raw mode: %m\n"); ioctl(tty->fd, KDGKBMODE, &tty->kb_mode); ret = ioctl(tty->fd, KDSKBMODE, K_OFF); if (ret) { fprintf(stderr, "failed to set K_OFF keyboard mode on tty: %m\n"); goto err_attr; } ret = ioctl(tty->fd, KDSETMODE, KD_GRAPHICS); if (ret) { fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n"); goto err_kdkbmode; } tty->has_vt = 1; mode.mode = VT_PROCESS; mode.relsig = SIGUSR1; mode.acqsig = SIGUSR1; if (ioctl(tty->fd, VT_SETMODE, &mode) < 0) { fprintf(stderr, "failed to take control of vt handling\n"); goto err_kdmode; } loop = wl_display_get_event_loop(compositor->wl_display); tty->vt_source = wl_event_loop_add_signal(loop, SIGUSR1, vt_handler, tty); if (!tty->vt_source) goto err_vtmode; return tty; err_vtmode: ioctl(tty->fd, VT_SETMODE, &mode); err_kdmode: ioctl(tty->fd, KDSETMODE, KD_TEXT); err_kdkbmode: ioctl(tty->fd, KDSKBMODE, tty->kb_mode); err_attr: tcsetattr(tty->fd, TCSANOW, &tty->terminal_attributes); err: close(tty->fd); free(tty); return NULL; }
static int setup_tty(struct launcher_direct *launcher, int tty) { struct wl_event_loop *loop; struct vt_mode mode = { 0 }; struct stat buf; char tty_device[32] ="<stdin>"; int ret, kd_mode; if (tty == 0) { launcher->tty = dup(tty); if (launcher->tty == -1) { weston_log("couldn't dup stdin: %m\n"); return -1; } } else { snprintf(tty_device, sizeof tty_device, "/dev/tty%d", tty); launcher->tty = open(tty_device, O_RDWR | O_CLOEXEC); if (launcher->tty == -1) { weston_log("couldn't open tty %s: %m\n", tty_device); return -1; } } if (fstat(launcher->tty, &buf) == -1 || major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0) { weston_log("%s not a vt\n", tty_device); weston_log("if running weston from ssh, " "use --tty to specify a tty\n"); goto err_close; } ret = ioctl(launcher->tty, KDGETMODE, &kd_mode); if (ret) { weston_log("failed to get VT mode: %m\n"); return -1; } if (kd_mode != KD_TEXT) { weston_log("%s is already in graphics mode, " "is another display server running?\n", tty_device); goto err_close; } ioctl(launcher->tty, VT_ACTIVATE, minor(buf.st_rdev)); ioctl(launcher->tty, VT_WAITACTIVE, minor(buf.st_rdev)); if (ioctl(launcher->tty, KDGKBMODE, &launcher->kb_mode)) { weston_log("failed to read keyboard mode: %m\n"); goto err_close; } if (ioctl(launcher->tty, KDSKBMUTE, 1) && ioctl(launcher->tty, KDSKBMODE, K_OFF)) { weston_log("failed to set K_OFF keyboard mode: %m\n"); goto err_close; } ret = ioctl(launcher->tty, KDSETMODE, KD_GRAPHICS); if (ret) { weston_log("failed to set KD_GRAPHICS mode on tty: %m\n"); goto err_close; } /* * SIGRTMIN is used as global VT-acquire+release signal. Note that * SIGRT* must be tested on runtime, as their exact values are not * known at compile-time. POSIX requires 32 of them to be available. */ if (SIGRTMIN > SIGRTMAX) { weston_log("not enough RT signals available: %u-%u\n", SIGRTMIN, SIGRTMAX); ret = -EINVAL; goto err_close; } mode.mode = VT_PROCESS; mode.relsig = SIGRTMIN; mode.acqsig = SIGRTMIN; if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0) { weston_log("failed to take control of vt handling\n"); goto err_close; } loop = wl_display_get_event_loop(launcher->compositor->wl_display); launcher->vt_source = wl_event_loop_add_signal(loop, SIGRTMIN, vt_handler, launcher); if (!launcher->vt_source) goto err_close; return 0; err_close: close(launcher->tty); return -1; }