Home | History | Annotate | Download | only in pty
      1 // Copyright 2017 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build darwin dragonfly freebsd linux,!android netbsd openbsd
      6 // +build cgo
      7 
      8 // Package pty is a simple pseudo-terminal package for Unix systems,
      9 // implemented by calling C functions via cgo.
     10 // This is only used for testing the os/signal package.
     11 package pty
     12 
     13 /*
     14 #define _XOPEN_SOURCE 600
     15 #include <fcntl.h>
     16 #include <stdlib.h>
     17 #include <unistd.h>
     18 */
     19 import "C"
     20 
     21 import (
     22 	"fmt"
     23 	"os"
     24 	"syscall"
     25 )
     26 
     27 type PtyError struct {
     28 	FuncName    string
     29 	ErrorString string
     30 	Errno       syscall.Errno
     31 }
     32 
     33 func ptyError(name string, err error) *PtyError {
     34 	return &PtyError{name, err.Error(), err.(syscall.Errno)}
     35 }
     36 
     37 func (e *PtyError) Error() string {
     38 	return fmt.Sprintf("%s: %s", e.FuncName, e.ErrorString)
     39 }
     40 
     41 // Open returns a master pty and the name of the linked slave tty.
     42 func Open() (master *os.File, slave string, err error) {
     43 	m, err := C.posix_openpt(C.O_RDWR)
     44 	if err != nil {
     45 		return nil, "", ptyError("posix_openpt", err)
     46 	}
     47 	if _, err := C.grantpt(m); err != nil {
     48 		C.close(m)
     49 		return nil, "", ptyError("grantpt", err)
     50 	}
     51 	if _, err := C.unlockpt(m); err != nil {
     52 		C.close(m)
     53 		return nil, "", ptyError("unlockpt", err)
     54 	}
     55 	slave = C.GoString(C.ptsname(m))
     56 	return os.NewFile(uintptr(m), "pty-master"), slave, nil
     57 }
     58