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 (
"errors"
"os/exec"
"strings"
"syscall"
"unsafe"
"v.io/v23/context"
)
// 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(
syscall.SYS_IOCTL,
fd,
uintptr(syscall.TIOCSWINSZ),
uintptr(unsafe.Pointer(&ws)))
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(
syscall.SYS_IOCTL,
uintptr(syscall.Stdin),
uintptr(syscall.TIOCGWINSZ),
uintptr(unsafe.Pointer(ws)))
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.
"-isig",
// Ignore characters with parity errors.
"ignpar",
// Disable translate newline to carriage return.
"-inlcr",
// Disable ignore carriage return.
"-igncr",
// Disable translate carriage return to newline.
"-icrnl",
// Disable flow control.
"-ixon", "-ixany", "-ixoff",
// Disable non-POSIX special characters.
"-iexten",
}
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",
saved,
}
if out, err := exec.Command("stty", args...).CombinedOutput(); err != nil {
ctx.Infof("stty failed (%v) (%q)", err, out)
}
}