github.com/dolfly/pty@v1.2.1/run_unix.go (about) 1 //go:build !windows 2 //+build !windows 3 4 package pty 5 6 import ( 7 "os/exec" 8 "syscall" 9 ) 10 11 // StartWithSize assigns a pseudo-terminal Tty to c.Stdin, c.Stdout, 12 // and c.Stderr, calls c.Start, and returns the File of the tty's 13 // corresponding Pty. 14 // 15 // This will resize the Pty to the specified size before starting the command. 16 // Starts the process in a new session and sets the controlling terminal. 17 func StartWithSize(c *exec.Cmd, sz *Winsize) (Pty, error) { 18 if c.SysProcAttr == nil { 19 c.SysProcAttr = &syscall.SysProcAttr{} 20 } 21 c.SysProcAttr.Setsid = true 22 c.SysProcAttr.Setctty = true 23 return StartWithAttrs(c, sz, c.SysProcAttr) 24 } 25 26 // StartWithAttrs assigns a pseudo-terminal Tty to c.Stdin, c.Stdout, 27 // and c.Stderr, calls c.Start, and returns the File of the tty's 28 // corresponding Pty. 29 // 30 // This will resize the Pty to the specified size before starting the command if a size is provided. 31 // The `attrs` parameter overrides the one set in c.SysProcAttr. 32 // 33 // This should generally not be needed. Used in some edge cases where it is needed to create a pty 34 // without a controlling terminal. 35 func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (Pty, error) { 36 pty, tty, err := open() 37 if err != nil { 38 return nil, err 39 } 40 defer func() { 41 // always close tty fds since it's being used in another process 42 // but pty is kept to resize tty 43 _ = tty.Close() 44 }() 45 46 if sz != nil { 47 if err := Setsize(pty, sz); err != nil { 48 _ = pty.Close() 49 return nil, err 50 } 51 } 52 if c.Stdout == nil { 53 c.Stdout = tty 54 } 55 if c.Stderr == nil { 56 c.Stderr = tty 57 } 58 if c.Stdin == nil { 59 c.Stdin = tty 60 } 61 62 c.SysProcAttr = attrs 63 64 if err := c.Start(); err != nil { 65 _ = pty.Close() 66 return nil, err 67 } 68 return pty, err 69 }