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