github.com/oweisse/u-root@v0.0.0-20181109060735-d005ad25fef1/cmds/elvish/program/shell/shell.go (about)

     1  // Package shell is the entry point for the terminal interface of Elvish.
     2  package shell
     3  
     4  import (
     5  	"fmt"
     6  	"os"
     7  	"os/signal"
     8  	"syscall"
     9  
    10  	"github.com/u-root/u-root/cmds/elvish/runtime"
    11  	"github.com/u-root/u-root/cmds/elvish/sys"
    12  	"github.com/u-root/u-root/cmds/elvish/util"
    13  )
    14  
    15  var logger = util.GetLogger("[shell] ")
    16  
    17  // Shell keeps flags to the shell.
    18  type Shell struct {
    19  	BinPath     string
    20  	SockPath    string
    21  	DbPath      string
    22  	Cmd         bool
    23  	CompileOnly bool
    24  }
    25  
    26  func New(binpath, sockpath, dbpath string, cmd, compileonly bool) *Shell {
    27  	return &Shell{binpath, sockpath, dbpath, cmd, compileonly}
    28  }
    29  
    30  // Main runs Elvish using the default terminal interface. It blocks until Elvish
    31  // quites, and returns the exit code.
    32  func (sh *Shell) Main(args []string) int {
    33  	defer rescue()
    34  
    35  	ev, dataDir := runtime.InitRuntime(sh.BinPath, sh.SockPath, sh.DbPath)
    36  	defer runtime.CleanupRuntime(ev)
    37  
    38  	handleSignals()
    39  
    40  	if len(args) > 0 {
    41  		err := script(ev, args, sh.Cmd, sh.CompileOnly)
    42  		if err != nil {
    43  			util.PprintError(err)
    44  			return 2
    45  		}
    46  	} else {
    47  		interact(ev, dataDir)
    48  	}
    49  
    50  	return 0
    51  }
    52  
    53  // Global panic handler.
    54  func rescue() {
    55  	r := recover()
    56  	if r != nil {
    57  		println()
    58  		fmt.Println(r)
    59  		print(sys.DumpStack())
    60  		println("\nexecing recovery shell /bin/sh")
    61  		syscall.Exec("/bin/sh", []string{"/bin/sh"}, os.Environ())
    62  	}
    63  }
    64  
    65  func handleSignals() {
    66  	sigs := make(chan os.Signal)
    67  	signal.Notify(sigs)
    68  	go func() {
    69  		for sig := range sigs {
    70  			logger.Println("signal", sig)
    71  			handleSignal(sig)
    72  		}
    73  	}()
    74  }