blob: fa2a36bcaccbf5302e09beb7ea59e72a0739600f [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package internal defines common types and functions used by both tunnel
// clients and servers.
package internal
import (
// Winsize defines the window size used by ioctl TIOCGWINSZ and TIOCSWINSZ.
type Winsize struct {
Row uint16
Col uint16
Xpixel uint16
// SetWindowSize sets the terminal's window size.
func SetWindowSize(fd uintptr, ws Winsize) error {
ret, _, _ := syscall.Syscall(
if int(ret) == -1 {
return errors.New("ioctl(TIOCSWINSZ) failed")
return nil
// GetWindowSize gets the terminal's window size.
func GetWindowSize() (*Winsize, error) {
ws := &Winsize{}
ret, _, _ := syscall.Syscall(
if int(ret) == -1 {
return nil, errors.New("ioctl(TIOCGWINSZ) failed")
return ws, nil
// EnterRawTerminalMode uses stty to enter the terminal into raw mode; stdin is
// unbuffered, local echo of input characters is disabled, and special signal
// characters are disabled. Returns a string which may be passed to
// RestoreTerminalSettings to restore to the original terminal settings.
func EnterRawTerminalMode(ctx *context.T) string {
var savedBytes []byte
var err error
if savedBytes, err = exec.Command("stty", "-F", "/dev/tty", "-g").Output(); err != nil {
ctx.Infof("Failed to save terminal settings: %q (%v)", savedBytes, err)
saved := strings.TrimSpace(string(savedBytes))
args := []string{
"-F", "/dev/tty",
// Don't buffer stdin. Read characters as they are typed.
"-icanon", "min", "1", "time", "0",
// Turn off local echo of input characters.
"-echo", "-echoe", "-echok", "-echonl",
// Disable interrupt, quit, and suspend special characters.
// Ignore characters with parity errors.
// Disable translate newline to carriage return.
// Disable ignore carriage return.
// Disable translate carriage return to newline.
// Disable flow control.
"-ixon", "-ixany", "-ixoff",
// Disable non-POSIX special characters.
if out, err := exec.Command("stty", args...).CombinedOutput(); err != nil {
ctx.Infof("stty failed (%v) (%q)", err, out)
return string(saved)
// RestoreTerminalSettings uses stty to restore the terminal to the original
// settings, taking the saved settings returned by EnterRawTerminalMode.
func RestoreTerminalSettings(ctx *context.T, saved string) {
args := []string{
"-F", "/dev/tty",
if out, err := exec.Command("stty", args...).CombinedOutput(); err != nil {
ctx.Infof("stty failed (%v) (%q)", err, out)