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  }