github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/core/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/core/elvish/runtime" 11 "github.com/u-root/u-root/cmds/core/elvish/sys" 12 "github.com/u-root/u-root/cmds/core/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 }