This repository has been archived by the owner on Jan 25, 2022. It is now read-only.
/
main.go
126 lines (105 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
package main
import (
"flag"
"fmt"
"io"
"os"
"os/signal"
"syscall"
"github.com/cloudfoundry-incubator/garden"
"github.com/cloudfoundry-incubator/garden-linux/container_daemon"
"github.com/cloudfoundry-incubator/garden-linux/container_daemon/unix_socket"
"github.com/cloudfoundry-incubator/garden-linux/pkg/vars"
"golang.org/x/crypto/ssh/terminal"
)
func main() {
socketPath := flag.String("socket", "./run/wshd.sock", "Path to socket")
user := flag.String("user", "root", "User to change to")
dir := flag.String("dir", "", "Working directory for the running process")
readSignals := flag.Bool("readSignals", false, "Read signals from extra file descriptor")
var envVars vars.StringList
flag.Var(&envVars, "env", "Environment variables to set for the command.")
flag.Bool("rsh", false, "RSH compatibility mode")
flag.Parse()
extraArgs := flag.Args()
if len(extraArgs) == 0 {
// Default is to run a shell.
extraArgs = []string{"/bin/sh"}
}
var tty *garden.TTYSpec
resize := make(chan os.Signal, 1)
if terminal.IsTerminal(syscall.Stdin) {
tty = &garden.TTYSpec{}
signal.Notify(resize, syscall.SIGWINCH)
}
var signalReader io.Reader
if *readSignals {
signalReader = os.NewFile(uintptr(3), "extrafd")
}
process := &container_daemon.Process{
Connector: &unix_socket.Connector{
SocketPath: *socketPath,
},
Term: container_daemon.TermPkg{},
SigwinchCh: resize,
ReadSignals: *readSignals,
SignalReader: signalReader,
Spec: &garden.ProcessSpec{
Path: extraArgs[0],
Args: extraArgs[1:],
Env: envVars.List,
Dir: *dir,
User: *user,
TTY: tty, // used as a boolean -- non-nil = attach pty
Limits: getRlimits(),
},
IO: &garden.ProcessIO{
Stdin: os.Stdin,
Stderr: os.Stderr,
Stdout: os.Stdout,
},
}
exitCode := container_daemon.UnknownExitStatus
defer func() {
process.Cleanup()
os.Exit(exitCode)
}()
err := process.Start()
if err != nil {
fmt.Fprintf(os.Stderr, "start process: %s", err)
return
}
exitCode, err = process.Wait()
if err != nil {
fmt.Fprintf(os.Stderr, "wait for process: %s", err)
return
}
}
func getRLimitFromEnv(envVar string) *uint64 {
strVal := os.Getenv(envVar)
if strVal == "" {
return nil
}
var val uint64
fmt.Sscanf(strVal, "%d", &val)
return &val
}
func getRlimits() garden.ResourceLimits {
return garden.ResourceLimits{
As: getRLimitFromEnv("RLIMIT_AS"),
Core: getRLimitFromEnv("RLIMIT_CORE"),
Cpu: getRLimitFromEnv("RLIMIT_CPU"),
Data: getRLimitFromEnv("RLIMIT_DATA"),
Fsize: getRLimitFromEnv("RLIMIT_FSIZE"),
Locks: getRLimitFromEnv("RLIMIT_LOCKS"),
Memlock: getRLimitFromEnv("RLIMIT_MEMLOCK"),
Msgqueue: getRLimitFromEnv("RLIMIT_MSGQUEUE"),
Nice: getRLimitFromEnv("RLIMIT_NICE"),
Nofile: getRLimitFromEnv("RLIMIT_NOFILE"),
Nproc: getRLimitFromEnv("RLIMIT_NPROC"),
Rss: getRLimitFromEnv("RLIMIT_RSS"),
Rtprio: getRLimitFromEnv("RLIMIT_RTPRIO"),
Sigpending: getRLimitFromEnv("RLIMIT_SIGPENDING"),
Stack: getRLimitFromEnv("RLIMIT_STACK"),
}
}