sysinit.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package sysinit
  2. import (
  3. "flag"
  4. "fmt"
  5. "github.com/dotcloud/docker/netlink"
  6. "github.com/dotcloud/docker/utils"
  7. "log"
  8. "net"
  9. "os"
  10. "os/exec"
  11. "strconv"
  12. "strings"
  13. "syscall"
  14. )
  15. // Setup networking
  16. func setupNetworking(gw string) {
  17. if gw == "" {
  18. return
  19. }
  20. ip := net.ParseIP(gw)
  21. if ip == nil {
  22. log.Fatalf("Unable to set up networking, %s is not a valid IP", gw)
  23. return
  24. }
  25. if err := netlink.AddDefaultGw(ip); err != nil {
  26. log.Fatalf("Unable to set up networking: %v", err)
  27. }
  28. }
  29. // Setup working directory
  30. func setupWorkingDirectory(workdir string) {
  31. if workdir == "" {
  32. return
  33. }
  34. if err := syscall.Chdir(workdir); err != nil {
  35. log.Fatalf("Unable to change dir to %v: %v", workdir, err)
  36. }
  37. }
  38. // Takes care of dropping privileges to the desired user
  39. func changeUser(u string) {
  40. if u == "" {
  41. return
  42. }
  43. userent, err := utils.UserLookup(u)
  44. if err != nil {
  45. log.Fatalf("Unable to find user %v: %v", u, err)
  46. }
  47. uid, err := strconv.Atoi(userent.Uid)
  48. if err != nil {
  49. log.Fatalf("Invalid uid: %v", userent.Uid)
  50. }
  51. gid, err := strconv.Atoi(userent.Gid)
  52. if err != nil {
  53. log.Fatalf("Invalid gid: %v", userent.Gid)
  54. }
  55. if err := syscall.Setgid(gid); err != nil {
  56. log.Fatalf("setgid failed: %v", err)
  57. }
  58. if err := syscall.Setuid(uid); err != nil {
  59. log.Fatalf("setuid failed: %v", err)
  60. }
  61. }
  62. // Clear environment pollution introduced by lxc-start
  63. func cleanupEnv(env utils.ListOpts) {
  64. os.Clearenv()
  65. for _, kv := range env {
  66. parts := strings.SplitN(kv, "=", 2)
  67. if len(parts) == 1 {
  68. parts = append(parts, "")
  69. }
  70. os.Setenv(parts[0], parts[1])
  71. }
  72. }
  73. func executeProgram(name string, args []string) {
  74. path, err := exec.LookPath(name)
  75. if err != nil {
  76. log.Printf("Unable to locate %v", name)
  77. os.Exit(127)
  78. }
  79. if err := syscall.Exec(path, args, os.Environ()); err != nil {
  80. panic(err)
  81. }
  82. }
  83. // Sys Init code
  84. // This code is run INSIDE the container and is responsible for setting
  85. // up the environment before running the actual process
  86. func SysInit() {
  87. if len(os.Args) <= 1 {
  88. fmt.Println("You should not invoke dockerinit manually")
  89. os.Exit(1)
  90. }
  91. var u = flag.String("u", "", "username or uid")
  92. var gw = flag.String("g", "", "gateway address")
  93. var workdir = flag.String("w", "", "workdir")
  94. var flEnv utils.ListOpts
  95. flag.Var(&flEnv, "e", "Set environment variables")
  96. flag.Parse()
  97. cleanupEnv(flEnv)
  98. setupNetworking(*gw)
  99. setupWorkingDirectory(*workdir)
  100. changeUser(*u)
  101. executeProgram(flag.Arg(0), flag.Args())
  102. }