This repository has been archived by the owner on Mar 4, 2023. It is now read-only.
forked from mattn/sudo
-
Notifications
You must be signed in to change notification settings - Fork 2
/
client.go
96 lines (83 loc) · 1.76 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// +build windows
package main
import (
"encoding/gob"
"fmt"
"net"
"os"
"os/exec"
"runtime"
"syscall"
)
func client(addr string, args []string) int {
// connect to server
conn, err := net.Dial("tcp", addr)
if err != nil {
panic(err.Error())
}
defer conn.Close()
enc, dec := gob.NewEncoder(conn), gob.NewDecoder(conn)
cmd := exec.Command(args[0], args[1:]...)
// stdin
inw, err := cmd.StdinPipe()
if err != nil {
enc.Encode(&msg{Name: "error", Error: fmt.Sprintf("cannot execute command: %v", makeCmdLine(args))})
return 1
}
defer inw.Close()
// stdout
outw := msgWrite(enc, "stdout")
defer outw.Close()
cmd.Stdout = outw
// stderr
errw := msgWrite(enc, "stderr")
defer errw.Close()
cmd.Stderr = errw
go func() {
defer inw.Close()
in_loop:
for {
var m msg
err = dec.Decode(&m)
if err != nil {
return
}
switch m.Name {
case "close":
inw.Close()
case "ctrlc":
if runtime.GOOS == "windows" {
// windows doesn't support os.Interrupt
exec.Command("taskkill", "/F", "/T", "/PID", fmt.Sprint(cmd.Process.Pid)).Run()
} else {
cmd.Process.Signal(os.Interrupt)
}
break in_loop
case "stdin":
inw.Write(m.Data)
}
}
}()
var environ []string
err = dec.Decode(&environ)
if err != nil {
enc.Encode(&msg{Name: "error", Error: fmt.Sprintf("cannot execute command: %v", makeCmdLine(args))})
return 1
}
cmd.Env = environ
err = cmd.Run()
code := 1
if err != nil {
if status, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok {
code = status.ExitStatus()
}
} else {
code = 0
}
err = enc.Encode(&msg{Name: "exit", Exit: code})
if err != nil {
enc.Encode(&msg{Name: "error", Error: fmt.Sprintf("cannot detect exit code: %v", makeCmdLine(args))})
return 1
}
return 0
}