github.com/jlowellwofford/u-root@v1.0.0/xcmds/run/run.go (about)

     1  // Copyright 2012-2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Run executes its arguments as a Go program.
     6  //
     7  // Synopsis:
     8  //     run [-v] GO_CODE..
     9  //
    10  // Examples:
    11  //     run {fmt.Println("hello")}
    12  //
    13  // Options:
    14  //     -v: verbose display of processing
    15  package main
    16  
    17  import (
    18  	"flag"
    19  	"log"
    20  	"os"
    21  	"os/exec"
    22  
    23  	"golang.org/x/tools/imports"
    24  )
    25  
    26  var verbose = flag.Bool("v", false, "Verbose display of processing")
    27  
    28  func main() {
    29  	opts := imports.Options{
    30  		Fragment:  true,
    31  		AllErrors: true,
    32  		Comments:  true,
    33  		TabIndent: true,
    34  		TabWidth:  8,
    35  	}
    36  	flag.Parse()
    37  	// Interesting problem:
    38  	// We want a combination of args and arbitrary Go code.
    39  	// Possibly, we should take the entire Go code as the one arg,
    40  	// i.e. in a 'string', and then take the args following.
    41  	a := "func main()"
    42  	for _, v := range flag.Args() {
    43  		a = a + v
    44  	}
    45  	if *verbose {
    46  		log.Printf("Pre-import version: '%v'", a)
    47  	}
    48  	goCode, err := imports.Process("commandline", []byte(a), &opts)
    49  	if err != nil {
    50  		log.Fatalf("bad parse: '%v': %v", a, err)
    51  	}
    52  	if *verbose {
    53  		log.Printf("Post-import version: '%v'", string(goCode))
    54  	}
    55  
    56  	// of course we have to deal with the Unix issue that /tmp is not private.
    57  	f, err := TempFile("", "run%s.go")
    58  	if err != nil {
    59  		log.Fatalf("Script: opening TempFile: %v", err)
    60  	}
    61  
    62  	if _, err := f.Write([]byte(goCode)); err != nil {
    63  		log.Fatalf("Script: Writing %v: %v", f, err)
    64  	}
    65  	if err := f.Close(); err != nil {
    66  		log.Fatalf("Script: Closing %v: %v", f, err)
    67  	}
    68  
    69  	os.Setenv("GOBIN", "/tmp")
    70  	cmd := exec.Command("go", "install", "-x", f.Name())
    71  	cmd.Dir = "/"
    72  
    73  	cmd.Stdin = os.Stdin
    74  	cmd.Stderr = os.Stderr
    75  	cmd.Stdout = os.Stdout
    76  	log.Printf("Install %v", f.Name())
    77  	if err = cmd.Run(); err != nil {
    78  		log.Printf("%v\n", err)
    79  	}
    80  
    81  	// stupid, but hey ...
    82  	execName := f.Name()
    83  	// strip .go from the name.
    84  	execName = execName[:len(execName)-3]
    85  	cmd = exec.Command(execName)
    86  	cmd.Dir = "/tmp"
    87  
    88  	cmd.Stdin = os.Stdin
    89  	cmd.Stderr = os.Stderr
    90  	cmd.Stdout = os.Stdout
    91  	log.Printf("Run %v", f.Name())
    92  	if err := cmd.Run(); err != nil {
    93  		log.Printf("%v\n", err)
    94  	}
    95  
    96  }