github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/containers/compilers/rump/go/stub/gomaincaller.go (about) 1 package main 2 3 import "C" 4 import ( 5 "bufio" 6 "bytes" 7 "errors" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "log" 12 "net/http" 13 "os" 14 "unsafe" 15 ) 16 17 //export gomaincaller 18 func gomaincaller(kludge_dns_addrs_len C.int, kludge_dns_addrs unsafe.Pointer, argc C.int, argv unsafe.Pointer) { 19 os.Args = nil 20 argcint := int(argc) 21 argvarr := ((*[1 << 30]*C.char)(argv)) 22 for i := 0; i < argcint; i += 1 { 23 os.Args = append(os.Args, C.GoString(argvarr[i])) 24 } 25 26 //cDnsAddrArray := ((*[1 << 30]*C.uint)(kludge_dns_addrs)) 27 dnsAddrs := C.GoBytes(kludge_dns_addrs, kludge_dns_addrs_len) 28 29 if err := stub(dnsAddrs); err != nil { 30 log.Printf("fatal: stub failed: %v", err) 31 return 32 } 33 main() 34 } 35 36 const BROADCAST_LISTENING_PORT = 9967 37 38 func stub(dnsAddrs []byte) error { 39 if len(dnsAddrs)%4 != 0 { 40 errMsg := fmt.Sprintf("expected len(dnsAddrs) to be a multiple of 4, but instead got %v", dnsAddrs) 41 return errors.New(errMsg) 42 } 43 var resolvConf string 44 numAddrs := len(dnsAddrs) / 4 45 for i := 0; i < numAddrs; i++ { 46 b1 := dnsAddrs[i+0] 47 b2 := dnsAddrs[i+1] 48 b3 := dnsAddrs[i+2] 49 b4 := dnsAddrs[i+3] 50 resolvConf += fmt.Sprintf("nameserver %d.%d.%d.%d\n", b1, b2, b3, b4) 51 } 52 53 log.Printf("writing dns addr: %s from %v", resolvConf, dnsAddrs) 54 55 if err := ioutil.WriteFile("/etc/resolv.conf", []byte(resolvConf), 0644); err != nil { 56 return errors.New("filling in dns address " + err.Error()) 57 } 58 59 //make logs available via http request 60 logs := &bytes.Buffer{} 61 if err := teeStdout(logs); err != nil { 62 return errors.New("teeing stdout: " + err.Error()) 63 } 64 if err := teeStderr(logs); err != nil { 65 return errors.New("teeing stderr: " + err.Error()) 66 } 67 log.SetOutput(os.Stderr) 68 69 log.Printf("unik v0.0 boostrapping beginning...") 70 71 if err := os.Chdir("/bootpart"); err != nil { 72 return errors.New("changing wd to /bootpart: " + err.Error()) 73 } 74 75 mux := http.NewServeMux() 76 //serve logs 77 mux.HandleFunc("/logs", func(res http.ResponseWriter, req *http.Request) { 78 fmt.Fprintf(res, "logs: %s", string(logs.Bytes())) 79 }) 80 log.Printf("starting log server\n") 81 go func() { 82 log.Printf("serving logs failed: %v", http.ListenAndServe(fmt.Sprintf(":%v", BROADCAST_LISTENING_PORT), mux)) 83 }() 84 85 if err := bootstrap(); err != nil { 86 return errors.New("bootstrap failed: " + err.Error()) 87 } 88 return nil 89 } 90 91 func setEnv(env map[string]string) error { 92 for key, val := range env { 93 os.Setenv(key, val) 94 } 95 return nil 96 } 97 98 func teeStdout(writer io.Writer) error { 99 r, w, err := os.Pipe() 100 if err != nil { 101 return errors.New("creating pipe: " + err.Error()) 102 } 103 stdout := os.Stdout 104 os.Stdout = w 105 multi := io.MultiWriter(stdout, writer) 106 reader := bufio.NewReader(r) 107 go func() { 108 for { 109 _, err := io.Copy(multi, reader) 110 if err != nil { 111 panic("copying pipe reader to multi writer: " + err.Error()) 112 } 113 } 114 }() 115 return nil 116 } 117 118 func teeStderr(writer io.Writer) error { 119 r, w, err := os.Pipe() 120 if err != nil { 121 return errors.New("creating pipe: " + err.Error()) 122 } 123 stderr := os.Stderr 124 os.Stderr = w 125 multi := io.MultiWriter(stderr, writer) 126 reader := bufio.NewReader(r) 127 go func() { 128 for { 129 _, err := io.Copy(multi, reader) 130 if err != nil { 131 panic("copying pipe reader to multi writer: " + err.Error()) 132 } 133 } 134 }() 135 return nil 136 }