forked from bxcodec/simpleshell
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
104 lines (91 loc) · 2.33 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
package main
import (
"fmt"
"time"
"bufio"
"errors"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
)
var allowed = `\b(?:awk|cat|cd|cp|curl|echo|exit|file|find|grep|head|ls|ll|ldd|locate|more|netstat|ping|ps|pwd|sed|sort|tail|tar|uniq|w|wc|help|plus)\b`
var helpStr = `awk cat cd cp curl echo exit file find grep head ls ll ldd locate more netstat ping ps pwd sed sort tail tar uniq w wc help plus`
var prohibt = `\s*(?:/proc|/var|/etc|/boot|/dev|/root|/bin|/sbin|/lib|/usr|/sys)\b`
func main() {
regx := regexp.MustCompile(allowed)
regp := regexp.MustCompile(prohibt)
f, err := os.CreateTemp(".", "rshell-")
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
defer f.Close()
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print("> ")
cmdString, err := reader.ReadString('\n')
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
now := fmt.Sprint(time.Now())
if _, err := f.Write( []byte( ( now + "\t" + cmdString) ) ); err != nil {
fmt.Fprintln(os.Stderr, err)
}
if len(cmdString) < 2 {
continue
}
if regp.MatchString(cmdString) {
fmt.Fprintln(os.Stderr, "path not allowed")
continue
}
if regx.MatchString(cmdString) {
err = runCommand(cmdString)
} else {
fmt.Fprintln(os.Stderr, strings.TrimSpace(cmdString)+" not allowed")
}
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
}
}
func runCommand(commandStr string) error {
commandStr = strings.TrimSuffix(commandStr, "\n")
arrCommandStr := strings.Fields(commandStr)
switch arrCommandStr[0] {
case "exit":
os.Exit(0)
case "help":
fmt.Fprintln(os.Stdout, "allowed cmd: "+helpStr)
return nil
case "ll":
strArr := []string {"ls", "-l"}
arrCommandStr = strArr
case "plus":
if len(arrCommandStr) < 3 {
return errors.New("2 or more arguments required")
}
arrNum := []int64{}
for i, arg := range arrCommandStr {
if i == 0 {
continue
}
n, _ := strconv.ParseInt(arg, 10, 64)
arrNum = append(arrNum, n)
}
fmt.Fprintln(os.Stdout, sum(arrNum...))
return nil
}
cmd := exec.Command(arrCommandStr[0], arrCommandStr[1:]...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
return cmd.Run()
}
func sum(numbers ...int64) int64 {
res := int64(0)
for _, num := range numbers {
res += num
}
return res
}
// https://hackernoon.com/today-i-learned-making-a-simple-interactive-shell-application-in-golang-aa83adcb266a