forked from vladimirvivien/gosh
/
syscmd.go
168 lines (145 loc) · 4.48 KB
/
syscmd.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package main
import (
"context"
"errors"
"fmt"
"io"
"os"
"runtime"
"strconv"
"github.com/donrudo/gosh/api"
)
// helpCmd represents the `help` command
// which prints out help information about other commands
type helpCmd string
func (h helpCmd) Name() string { return string(h) }
func (h helpCmd) Usage() string { return fmt.Sprintf("%s or %s <command-name>", h.Name(), h.Name()) }
func (h helpCmd) LongDesc() string { return "" }
func (h helpCmd) ShortDesc() string {
return `prints help information for other commands.`
}
func (h helpCmd) Exec(ctx context.Context, args []string) (context.Context, error) {
if ctx == nil {
return ctx, errors.New("nil context")
}
out := api.GetStdout(ctx)
cmdsVal := ctx.Value("gosh.commands")
if cmdsVal == nil {
return ctx, errors.New("nil context")
}
commands, ok := cmdsVal.(map[string]api.Command)
if !ok {
return ctx, errors.New("command map type mismatch")
}
var cmdNameParam string
if len(args) > 1 {
cmdNameParam = args[1]
}
// print help for a specified command
if cmdNameParam != "" {
cmd, found := commands[cmdNameParam]
if !found {
str := fmt.Sprintf("command %s not found", cmdNameParam)
return ctx, errors.New(str)
}
fmt.Fprintf(out, "\n%s\n", cmdNameParam)
if cmd.Usage() != "" {
fmt.Fprintf(out, " Usage: %s\n", cmd.Usage())
}
if cmd.ShortDesc() != "" {
fmt.Fprintf(out, " %s\n\n", cmd.ShortDesc())
}
if cmd.LongDesc() != "" {
fmt.Fprintf(out, "%s\n\n", cmd.LongDesc())
}
return ctx, nil
}
fmt.Fprintf(out, "\n%s: %s\n", h.Name(), h.ShortDesc())
fmt.Fprintln(out, "\nAvailable commands")
fmt.Fprintln(out, "------------------")
for cmdName, cmd := range commands {
fmt.Fprintf(out, "%12s:\t%s\n", cmdName, cmd.ShortDesc())
}
fmt.Fprintln(out, "\nUse \"help <command-name>\" for detail about the specified command\n")
return ctx, nil
}
// exitCmd implements a command to exit the shell
type exitCmd string
func (c exitCmd) Name() string { return string(c) }
func (c exitCmd) Usage() string { return "exit" }
func (c exitCmd) LongDesc() string { return "" }
func (c exitCmd) ShortDesc() string {
return `exits the interactive shell immediately`
}
func (c exitCmd) Exec(ctx context.Context, args []string) (context.Context, error) {
out := api.GetStdout(ctx)
fmt.Fprintln(out, "exiting...")
os.Exit(0)
return ctx, nil
}
// promptCmd a command that can change the prompt value
type promptCmd string
func (c promptCmd) Name() string { return string(c) }
func (c promptCmd) Usage() string { return "prompt <new-prompt>" }
func (c promptCmd) LongDesc() string { return "" }
func (c promptCmd) ShortDesc() string {
return `sets a new shell prompt`
}
func (c promptCmd) Exec(ctx context.Context, args []string) (context.Context, error) {
if len(args) < 2 {
return ctx, errors.New("unable to set prompt, see usage")
}
return context.WithValue(ctx, "gosh.prompt", args[1]), nil
}
// sysinfoCmd implements a command that returns system information
type sysinfoCmd string
func (c sysinfoCmd) Name() string { return string(c) }
func (c sysinfoCmd) Usage() string { return c.Name() }
func (c sysinfoCmd) LongDesc() string { return "" }
func (c sysinfoCmd) ShortDesc() string {
return `sets a new shell prompt`
}
func (c sysinfoCmd) Exec(ctx context.Context, args []string) (context.Context, error) {
out := api.GetStdout(ctx)
hostname, _ := os.Hostname()
exe, _ := os.Executable()
memStats := new(runtime.MemStats)
runtime.ReadMemStats(memStats)
info := []struct{ name, value string }{
{"arc", runtime.GOARCH},
{"os", runtime.GOOS},
{"cpus", strconv.Itoa(runtime.NumCPU())},
{"mem", strconv.FormatUint(memStats.Sys, 10)},
{"hostname", hostname},
{"pagesize", strconv.Itoa(os.Getpagesize())},
{"groupid", strconv.Itoa(os.Getgid())},
{"userid", strconv.Itoa(os.Geteuid())},
{"pid", strconv.Itoa(os.Getpid())},
{"exec", exe},
}
fmt.Fprint(out, "\nSystem Info")
fmt.Fprint(out, "\n-----------")
for _, k := range info {
fmt.Fprintf(out, "\n%12s:\t%s", k.name, k.value)
}
fmt.Fprintln(out, "\n")
return ctx, nil
}
// sysCommands represents a collection of commands supported by this
// command module.
type sysCommands struct {
stdout io.Writer
}
func (c *sysCommands) Init(ctx context.Context) error {
return nil
}
func (t *sysCommands) Registry() map[string]api.Command {
return map[string]api.Command{
"help": helpCmd("help"),
"exit": exitCmd("exit"),
"prompt": promptCmd("prompt"),
"sys": sysinfoCmd("sys"),
}
}
// plugin entry point
var Commands sysCommands