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  }