Allocates a PTY and starts the specified command attached to it. See: https://docs.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session#creating-the-hosted-process
(cmd *Cmd, opt ...StartOption)
| 18 | // Allocates a PTY and starts the specified command attached to it. |
| 19 | // See: https://docs.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session#creating-the-hosted-process |
| 20 | func startPty(cmd *Cmd, opt ...StartOption) (_ PTYCmd, _ Process, retErr error) { |
| 21 | var opts startOptions |
| 22 | for _, o := range opt { |
| 23 | o(&opts) |
| 24 | } |
| 25 | |
| 26 | fullPath, err := exec.LookPath(cmd.Path) |
| 27 | if err != nil { |
| 28 | return nil, nil, err |
| 29 | } |
| 30 | pathPtr, err := windows.UTF16PtrFromString(fullPath) |
| 31 | if err != nil { |
| 32 | return nil, nil, err |
| 33 | } |
| 34 | argsPtr, err := windows.UTF16PtrFromString(windows.ComposeCommandLine(cmd.Args)) |
| 35 | if err != nil { |
| 36 | return nil, nil, err |
| 37 | } |
| 38 | if cmd.Dir == "" { |
| 39 | cmd.Dir, err = os.Getwd() |
| 40 | if err != nil { |
| 41 | return nil, nil, err |
| 42 | } |
| 43 | } |
| 44 | dirPtr, err := windows.UTF16PtrFromString(cmd.Dir) |
| 45 | if err != nil { |
| 46 | return nil, nil, err |
| 47 | } |
| 48 | |
| 49 | winPty, err := newConPty(opts.ptyOpts...) |
| 50 | if err != nil { |
| 51 | return nil, nil, err |
| 52 | } |
| 53 | defer func() { |
| 54 | if retErr != nil { |
| 55 | // we hit some error finishing setup; close pty, so |
| 56 | // we don't leak the kernel resources associated with it |
| 57 | _ = winPty.Close() |
| 58 | } |
| 59 | }() |
| 60 | if winPty.opts.sshReq != nil { |
| 61 | cmd.Env = append(cmd.Env, fmt.Sprintf("SSH_TTY=%s", winPty.Name())) |
| 62 | } |
| 63 | |
| 64 | attrs, err := windows.NewProcThreadAttributeList(1) |
| 65 | if err != nil { |
| 66 | return nil, nil, err |
| 67 | } |
| 68 | // Taken from: https://github.com/microsoft/hcsshim/blob/2314362e977aa03b3ed245a4beb12d00422af0e2/internal/winapi/process.go#L6 |
| 69 | err = attrs.Update(0x20016, unsafe.Pointer(winPty.console), unsafe.Sizeof(winPty.console)) |
| 70 | if err != nil { |
| 71 | return nil, nil, err |
| 72 | } |
| 73 | |
| 74 | startupInfo := &windows.StartupInfoEx{} |
| 75 | startupInfo.ProcThreadAttributeList = attrs.List() |
| 76 | startupInfo.StartupInfo.Flags = windows.STARTF_USESTDHANDLES |
| 77 | startupInfo.StartupInfo.Cb = uint32(unsafe.Sizeof(*startupInfo)) |
nothing calls this directly
no test coverage detected