github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/container_daemon/wsh/main.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "io" 7 "os" 8 "os/signal" 9 "syscall" 10 11 "github.com/cloudfoundry-incubator/garden" 12 "github.com/cloudfoundry-incubator/garden-linux/container_daemon" 13 "github.com/cloudfoundry-incubator/garden-linux/container_daemon/unix_socket" 14 "github.com/cloudfoundry-incubator/garden-linux/pkg/vars" 15 "golang.org/x/crypto/ssh/terminal" 16 ) 17 18 func main() { 19 socketPath := flag.String("socket", "./run/wshd.sock", "Path to socket") 20 user := flag.String("user", "root", "User to change to") 21 dir := flag.String("dir", "", "Working directory for the running process") 22 readSignals := flag.Bool("readSignals", false, "Read signals from extra file descriptor") 23 24 var envVars vars.StringList 25 flag.Var(&envVars, "env", "Environment variables to set for the command.") 26 27 flag.Bool("rsh", false, "RSH compatibility mode") 28 29 flag.Parse() 30 31 extraArgs := flag.Args() 32 if len(extraArgs) == 0 { 33 // Default is to run a shell. 34 extraArgs = []string{"/bin/sh"} 35 } 36 37 var tty *garden.TTYSpec 38 resize := make(chan os.Signal, 1) 39 if terminal.IsTerminal(syscall.Stdin) { 40 tty = &garden.TTYSpec{} 41 signal.Notify(resize, syscall.SIGWINCH) 42 } 43 44 var signalReader io.Reader 45 if *readSignals { 46 signalReader = os.NewFile(uintptr(3), "extrafd") 47 } 48 49 process := &container_daemon.Process{ 50 Connector: &unix_socket.Connector{ 51 SocketPath: *socketPath, 52 }, 53 54 Term: container_daemon.TermPkg{}, 55 56 SigwinchCh: resize, 57 58 ReadSignals: *readSignals, 59 SignalReader: signalReader, 60 61 Spec: &garden.ProcessSpec{ 62 Path: extraArgs[0], 63 Args: extraArgs[1:], 64 Env: envVars.List, 65 Dir: *dir, 66 User: *user, 67 TTY: tty, // used as a boolean -- non-nil = attach pty 68 Limits: getRlimits(), 69 }, 70 71 IO: &garden.ProcessIO{ 72 Stdin: os.Stdin, 73 Stderr: os.Stderr, 74 Stdout: os.Stdout, 75 }, 76 } 77 78 exitCode := container_daemon.UnknownExitStatus 79 defer func() { 80 process.Cleanup() 81 os.Exit(exitCode) 82 }() 83 84 err := process.Start() 85 if err != nil { 86 fmt.Fprintf(os.Stderr, "start process: %s", err) 87 return 88 } 89 90 exitCode, err = process.Wait() 91 if err != nil { 92 fmt.Fprintf(os.Stderr, "wait for process: %s", err) 93 return 94 } 95 } 96 97 func getRLimitFromEnv(envVar string) *uint64 { 98 strVal := os.Getenv(envVar) 99 if strVal == "" { 100 return nil 101 } 102 103 var val uint64 104 fmt.Sscanf(strVal, "%d", &val) 105 return &val 106 } 107 108 func getRlimits() garden.ResourceLimits { 109 return garden.ResourceLimits{ 110 As: getRLimitFromEnv("RLIMIT_AS"), 111 Core: getRLimitFromEnv("RLIMIT_CORE"), 112 Cpu: getRLimitFromEnv("RLIMIT_CPU"), 113 Data: getRLimitFromEnv("RLIMIT_DATA"), 114 Fsize: getRLimitFromEnv("RLIMIT_FSIZE"), 115 Locks: getRLimitFromEnv("RLIMIT_LOCKS"), 116 Memlock: getRLimitFromEnv("RLIMIT_MEMLOCK"), 117 Msgqueue: getRLimitFromEnv("RLIMIT_MSGQUEUE"), 118 Nice: getRLimitFromEnv("RLIMIT_NICE"), 119 Nofile: getRLimitFromEnv("RLIMIT_NOFILE"), 120 Nproc: getRLimitFromEnv("RLIMIT_NPROC"), 121 Rss: getRLimitFromEnv("RLIMIT_RSS"), 122 Rtprio: getRLimitFromEnv("RLIMIT_RTPRIO"), 123 Sigpending: getRLimitFromEnv("RLIMIT_SIGPENDING"), 124 Stack: getRLimitFromEnv("RLIMIT_STACK"), 125 } 126 }