forked from keybase/client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
134 lines (113 loc) · 3.04 KB
/
main.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"github.com/keybase/client/go/kbnm/installer"
"github.com/qrtz/nativemessaging"
)
// internalVersion is the logical version of this code (rather than build).
const internalVersion = "1.4.1"
// Version is the build version of kbnm, overwritten during build with metadata.
var Version = "dev"
// Response from the kbnm service
type Response struct {
Client int `json:"client"`
Status string `json:"status"`
Message string `json:"message"`
Result interface{} `json:"result,omitempty"`
}
// Request to the kbnm service
type Request struct {
Client int `json:"client"`
Method string `json:"method"`
To string `json:"to"`
Body string `json:"body"`
}
var plainFlag = flag.Bool("plain", false, "newline-delimited JSON IO, no length prefix")
var versionFlag = flag.Bool("version", false, "print the version and exit")
// process consumes a single message
func process(h *handler, in nativemessaging.JSONDecoder, out nativemessaging.JSONEncoder) error {
var resp Response
var req Request
// If input fails to parse, we can't guarantee future inputs will
// get into a parseable state so we abort after sending an error
// response.
abortErr := in.Decode(&req)
var err error
if abortErr == nil {
resp.Result, err = h.Handle(&req)
}
if err == io.EOF {
// Closed
return err
} else if err != nil {
resp.Status = "error"
resp.Message = err.Error()
} else {
// Success
resp.Status = "ok"
}
resp.Client = req.Client
err = out.Encode(resp)
if err != nil {
// TODO: Log this somewhere?
fmt.Fprintf(os.Stderr, "error: %s", err)
os.Exit(1)
}
return abortErr
}
func exit(code int, msg string, a ...interface{}) {
fmt.Fprintf(os.Stderr, msg+"\n", a...)
os.Exit(code)
}
func main() {
flag.Parse()
if *versionFlag {
fmt.Printf("%s-%s\n", internalVersion, Version)
os.Exit(0)
}
switch flag.Arg(0) {
case "install":
kbnmPath, err := findKeybaseBinary(kbnmBinary)
if err != nil {
exit(2, "error finding kbnm binary: %s", err)
}
log.Print("installing: ", kbnmPath)
if err := installer.InstallKBNM(kbnmPath); err != nil {
exit(2, "error installing kbnm whitelist: %s", err)
}
exit(0, "Installed NativeMessaging whitelists.")
case "uninstall":
if err := installer.UninstallKBNM(); err != nil {
exit(2, "error uninstalling kbnm whitelist: %s", err)
}
exit(0, "Uninstalled NativeMessaging whitelists.")
}
// Native messages include a prefix which describes the length of each message.
var in nativemessaging.JSONDecoder
var out nativemessaging.JSONEncoder
if *plainFlag {
// Used for testing interactively
in = json.NewDecoder(os.Stdin)
out = json.NewEncoder(os.Stdout)
} else {
// Used as part of the NativeMessaging API
in = nativemessaging.NewNativeJSONDecoder(os.Stdin)
out = nativemessaging.NewNativeJSONEncoder(os.Stdout)
}
h := newHandler()
for {
err := process(h, in, out)
if err == io.EOF {
// Clean close
break
}
if err != nil {
exit(1, "stream processig error: %s", err)
}
}
}