func (c *cliClient) Start() { oldState, err := terminal.MakeRaw(0) if err != nil { panic(err.Error()) } defer terminal.Restore(0, oldState) signal.Notify(make(chan os.Signal), os.Interrupt) wrapper, interruptChan := NewTerminalWrapper(os.Stdin) wrapper.SetErrorOnInterrupt(true) c.interrupt = interruptChan c.termWrapper = wrapper c.term = terminal.NewTerminal(wrapper, "> ") if width, height, err := terminal.GetSize(0); err == nil { c.term.SetSize(width, height) } c.loadUI() if c.writerChan != nil { c.save() } if c.writerChan != nil { close(c.writerChan) <-c.writerDone } if c.fetchNowChan != nil { close(c.fetchNowChan) } if c.stateLock != nil { c.stateLock.Close() } }
func newTerm() Term { u := new(uterm) var err error u.s, err = terminal.MakeRaw(0) if err != nil { panic(err) } u.t = terminal.NewTerminal(os.Stdin, "lixian >> ") return u }
// Start raw acts as Start but put the terminal into raw mode. Returns an // additional function that should be used to restore the terminal state. func StartRaw(c *exec.Cmd) (pty *os.File, restore func(), err error) { pty, err = Start(c) oldState, err := terminal.MakeRaw(int(pty.Fd())) if err != nil { return nil, nil, err } return pty, func() { _ = terminal.Restore(int(pty.Fd()), oldState) }, nil }
func getch() byte { if oldState, err := terminal.MakeRaw(0); err != nil { panic(err) } else { defer terminal.Restore(0, oldState) } var buf [1]byte if n, err := syscall.Read(0, buf[:]); n == 0 || err != nil { panic(err) } return buf[0] }
// makeSession initializes a gossh.Session connected to the invoking process's stdout/stderr/stdout. // If the invoking session is a terminal, a TTY will be requested for the SSH session. // It returns a gossh.Session, a finalizing function used to clean up after the session terminates, // and any error encountered in setting up the session. func makeSession(client *SSHForwardingClient) (session *gossh.Session, finalize func(), err error) { session, err = client.NewSession() if err != nil { return } if err = client.ForwardAgentAuthentication(session); err != nil { return } session.Stdout = os.Stdout session.Stderr = os.Stderr session.Stdin = os.Stdin modes := gossh.TerminalModes{ gossh.ECHO: 1, // enable echoing gossh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud gossh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud } fd := int(os.Stdin.Fd()) if terminal.IsTerminal(fd) { var termWidth, termHeight int var oldState *terminal.State oldState, err = terminal.MakeRaw(fd) if err != nil { return } finalize = func() { session.Close() terminal.Restore(fd, oldState) } termWidth, termHeight, err = terminal.GetSize(fd) if err != nil { return } err = session.RequestPty("xterm-256color", termHeight, termWidth, modes) } else { finalize = func() { session.Close() } } return }
// NewStartedQShell returns an initialized QShell, ready to Interact() with. // Prints mongo startup message. func NewStartedQShell(driver *strata.Driver, mountPath string, showSize bool, mongodPath, mongoPath string) (*QShell, error) { finished := false sh := QShell{driver: driver, mountPath: mountPath, showSize: showSize, mongodPath: mongodPath, mongoPath: mongoPath} // Put terminal in raw mode var err error sh.stdinFd = int(os.Stdin.Fd()) sh.oldState, err = terminal.MakeRaw(sh.stdinFd) if err != nil { return &sh, err } // Convention seems to be that caller invokes Close() only if there is no error. // But we need to clean up if there is an error. defer func() { if !finished { sh.Close() } }() sh.term = terminal.NewTerminal(&readerWriter{r: os.Stdin, w: os.Stdout}, "\r> ") sh.mongoStateHolder, err = newMongoStateHolder(sh.mongoPath) if err != nil { return &sh, err } if err := sh.print("Wrapper around MongoDB shell with additional commands for querying backups.\n"); err != nil { return &sh, err } if err := sh.printMongoOutput(true); err != nil { return &sh, err } finished = true return &sh, nil }
func main() { w := eval.NewWorld() w.DefineVar("connect", eval.NewFuncType([]eval.Type{}, false, []eval.Type{}), &funcV{&testFunc{}}) fmt.Println(":: welcome to go-eval...\n(hit ^D to exit)") fd := int(os.Stdin.Fd()) oldState, err := terminal.MakeRaw(fd) if err != nil { panic(err) } defer terminal.Restore(fd, oldState) term := terminal.NewTerminal(&shell{r: os.Stdin, w: os.Stdout}, "> ") if term == nil { panic(errors.New("could not create terminal")) } for { line, err := term.ReadLine() if err != nil { break } code, err := w.Compile(fset, line) if err != nil { term.Write([]byte(err.Error() + "\n")) continue } v, err := code.Run() if err != nil { term.Write([]byte(err.Error() + "\n")) continue } if v != nil { term.Write([]byte(v.String() + "\n")) } } }
func (c *attachCmd) run(args []string) error { name := "foo" if len(args) > 1 { return errArgs } if len(args) == 1 { name = args[0] } config, err := flex.LoadConfig() if err != nil { return err } // NewClient will ping the server to test the connection before returning. d, err := flex.NewClient(config) if err != nil { return err } // TODO - random value in place of 5 :) secret := "5" l, err := d.Attach(name, "/bin/bash", secret) if err != nil { return err } cfd := syscall.Stdout if terminal.IsTerminal(cfd) { oldttystate, err := terminal.MakeRaw(cfd) if err != nil { return err } defer terminal.Restore(cfd, oldttystate) } // open a connection to l and connect stdin/stdout to it // connect conn, err := net.Dial("tcp", l) if err != nil { return err } _, err = conn.Write([]byte(secret)) if err != nil { return err } go func() { _, err := io.Copy(conn, os.Stdin) if err != nil { fmt.Println("Stdin read error: %s", err.Error()) return } }() _, err = io.Copy(os.Stdout, conn) if err != nil { fmt.Println("Connection read error: %s", err.Error()) return err } return nil }
func main() { flag.Parse() if flag.NArg() > 0 { cons = flag.Arg(0) } else { log.Fatal("Must give a console name as the last argument.") } state, err := terminal.MakeRaw(int(os.Stdin.Fd())) if err != nil { log.Fatal("MakeRaw: ", err) } // put it back the way we found it when we exit defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), state) // clean up cursor position fmt.Print("\r") }() c, err := net.Dial("tcp", "localhost:1234") if err != nil { log.Print("Could not connect: ", err) return } enc := gob.NewEncoder(c) req := new(connReq) req.Cmd = Listen req.Name = cons err = enc.Encode(req) if err != nil { log.Print("Could not write request: ", err) return } take(enc, Take) go readinput(c, enc) dec := gob.NewDecoder(c) reply := new(connReply) L: for { err := dec.Decode(reply) if err != nil { if err != io.EOF { log.Print("recv error: ", err) } break } debug("Reply code: ", reply.Code) switch reply.Code { default: log.Print("Bad reply from server: ", reply.Code, "\r") break case Ok: // nothing case ReadOnly: fmt.Fprintf(os.Stdout, " [read-only] ") readwrite = false case ReadWrite: fmt.Fprintf(os.Stdout, " [read-write] ") readwrite = true case Err: log.Print("Error from server: ", reply.Err, "\r") break L case Data: os.Stdout.Write(reply.Data[:]) } } log.Print("Disconnecting.\r") c.Close() }
func main() { flag.Parse() oldState, err := terminal.MakeRaw(0) if err != nil { panic(err.Error()) } defer terminal.Restore(0, oldState) term := terminal.NewTerminal(os.Stdin, "> ") updateTerminalSize(term) resizeChan := make(chan os.Signal) go func() { for _ = range resizeChan { updateTerminalSize(term) } }() signal.Notify(resizeChan, syscall.SIGWINCH) if len(*configFile) == 0 { homeDir := os.Getenv("HOME") if len(homeDir) == 0 { alert(term, "$HOME not set. Please either export $HOME or use the -config-file option.\n") return } persistentDir := filepath.Join(homeDir, "Persistent") if stat, err := os.Lstat(persistentDir); err == nil && stat.IsDir() { // Looks like Tails. homeDir = persistentDir } *configFile = filepath.Join(homeDir, ".xmpp-client") } config, err := ParseConfig(*configFile) if err != nil { alert(term, "Failed to parse config file: "+err.Error()) config = new(Config) if !enroll(config, term) { return } config.filename = *configFile config.Save() } password := config.Password if len(password) == 0 { if password, err = term.ReadPassword(fmt.Sprintf("Password for %s (will not be saved to disk): ", config.Account)); err != nil { alert(term, "Failed to read password: "******"@", 2) if len(parts) != 2 { alert(term, "invalid username (want user@domain): "+config.Account) return } user := parts[0] domain := parts[1] var addr string addrTrusted := false if len(config.Server) > 0 && config.Port > 0 { addr = fmt.Sprintf("%s:%d", config.Server, config.Port) addrTrusted = true } else { if len(config.Proxies) > 0 { alert(term, "Cannot connect via a proxy without Server and Port being set in the config file as an SRV lookup would leak information.") return } host, port, err := xmpp.Resolve(domain) if err != nil { alert(term, "Failed to resolve XMPP server: "+err.Error()) return } addr = fmt.Sprintf("%s:%d", host, port) } var dialer proxy.Dialer for i := len(config.Proxies) - 1; i >= 0; i-- { u, err := url.Parse(config.Proxies[i]) if err != nil { alert(term, "Failed to parse "+config.Proxies[i]+" as a URL: "+err.Error()) return } if dialer == nil { dialer = proxy.Direct } if dialer, err = proxy.FromURL(u, dialer); err != nil { alert(term, "Failed to parse "+config.Proxies[i]+" as a proxy: "+err.Error()) return } } var certSHA256 []byte if len(config.ServerCertificateSHA256) > 0 { certSHA256, err = hex.DecodeString(config.ServerCertificateSHA256) if err != nil { alert(term, "Failed to parse ServerCertificateSHA256 (should be hex string): "+err.Error()) return } if len(certSHA256) != 32 { alert(term, "ServerCertificateSHA256 is not 32 bytes long") return } } xmppConfig := &xmpp.Config{ Log: &lineLogger{term, nil}, Create: *createAccount, TrustedAddress: addrTrusted, Archive: false, ServerCertificateSHA256: certSHA256, } if len(config.RawLogFile) > 0 { rawLog, err := os.OpenFile(config.RawLogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) if err != nil { alert(term, "Failed to open raw log file: "+err.Error()) return } lock := new(sync.Mutex) in := rawLogger{ out: rawLog, prefix: []byte("<- "), lock: lock, } out := rawLogger{ out: rawLog, prefix: []byte("-> "), lock: lock, } in.other, out.other = &out, &in xmppConfig.InLog = &in xmppConfig.OutLog = &out defer in.flush() defer out.flush() } if dialer != nil { info(term, "Making connection to "+addr+" via proxy") if xmppConfig.Conn, err = dialer.Dial("tcp", addr); err != nil { alert(term, "Failed to connect via proxy: "+err.Error()) return } } conn, err := xmpp.Dial(addr, user, domain, password, xmppConfig) if err != nil { alert(term, "Failed to connect to XMPP server: "+err.Error()) return } s := Session{ account: config.Account, conn: conn, term: term, conversations: make(map[string]*otr.Conversation), knownStates: make(map[string]string), privateKey: new(otr.PrivateKey), config: config, pendingRosterChan: make(chan *rosterEdit), pendingSubscribes: make(map[string]string), lastActionTime: time.Now(), } info(term, "Fetching roster") //var rosterReply chan xmpp.Stanza rosterReply, _, err := s.conn.RequestRoster() if err != nil { alert(term, "Failed to request roster: "+err.Error()) return } conn.SignalPresence("") s.input = Input{ term: term, uidComplete: new(priorityList), } commandChan := make(chan interface{}) go s.input.ProcessCommands(commandChan) stanzaChan := make(chan xmpp.Stanza) go s.readMessages(stanzaChan) s.privateKey.Parse(config.PrivateKey) s.timeouts = make(map[xmpp.Cookie]time.Time) info(term, fmt.Sprintf("Your fingerprint is %x", s.privateKey.Fingerprint())) ticker := time.NewTicker(1 * time.Second) MainLoop: for { select { case now := <-ticker.C: haveExpired := false for _, expiry := range s.timeouts { if now.After(expiry) { haveExpired = true break } } if !haveExpired { continue } newTimeouts := make(map[xmpp.Cookie]time.Time) for cookie, expiry := range s.timeouts { if now.After(expiry) { s.conn.Cancel(cookie) } else { newTimeouts[cookie] = expiry } } s.timeouts = newTimeouts case edit := <-s.pendingRosterChan: if !edit.isComplete { info(s.term, "Please edit "+edit.fileName+" and run /rostereditdone when complete") s.pendingRosterEdit = edit continue } if s.processEditedRoster(edit) { s.pendingRosterEdit = nil } else { alert(s.term, "Please reedit file and run /rostereditdone again") } case rosterStanza, ok := <-rosterReply: if !ok { alert(s.term, "Failed to read roster: "+err.Error()) return } if s.roster, err = xmpp.ParseRoster(rosterStanza); err != nil { alert(s.term, "Failed to parse roster: "+err.Error()) return } for _, entry := range s.roster { s.input.AddUser(entry.Jid) } info(s.term, "Roster received") case cmd, ok := <-commandChan: if !ok { warn(term, "Exiting because command channel closed") break MainLoop } s.lastActionTime = time.Now() switch cmd := cmd.(type) { case quitCommand: for to, conversation := range s.conversations { msgs := conversation.End() for _, msg := range msgs { s.conn.Send(to, string(msg)) } } break MainLoop case versionCommand: replyChan, cookie, err := s.conn.SendIQ(cmd.User, "get", xmpp.VersionQuery{}) if err != nil { alert(s.term, "Error sending version request: "+err.Error()) continue } s.timeouts[cookie] = time.Now().Add(5 * time.Second) go s.awaitVersionReply(replyChan, cmd.User) case rosterCommand: info(s.term, "Current roster:") maxLen := 0 for _, item := range s.roster { if maxLen < len(item.Jid) { maxLen = len(item.Jid) } } for _, item := range s.roster { state, ok := s.knownStates[item.Jid] line := "" if ok { line += "[*] " } else if cmd.OnlineOnly { continue } else { line += "[ ] " } line += item.Jid numSpaces := 1 + (maxLen - len(item.Jid)) for i := 0; i < numSpaces; i++ { line += " " } line += item.Subscription + "\t" + item.Name if ok { line += "\t" + state } info(s.term, line) } case rosterEditCommand: if s.pendingRosterEdit != nil { warn(s.term, "Aborting previous roster edit") s.pendingRosterEdit = nil } rosterCopy := make([]xmpp.RosterEntry, len(s.roster)) copy(rosterCopy, s.roster) go s.editRoster(rosterCopy) case rosterEditDoneCommand: if s.pendingRosterEdit == nil { warn(s.term, "No roster edit in progress. Use /rosteredit to start one") continue } go s.loadEditedRoster(*s.pendingRosterEdit) case toggleStatusUpdatesCommand: s.config.HideStatusUpdates = !s.config.HideStatusUpdates s.config.Save() // Tell the user the current state of the statuses if s.config.HideStatusUpdates { info(s.term, "Status updated disabled") } else { info(s.term, "Status updates enabled") } case confirmCommand: s.handleConfirmOrDeny(cmd.User, true /* confirm */) case denyCommand: s.handleConfirmOrDeny(cmd.User, false /* deny */) case addCommand: s.conn.SendPresence(cmd.User, "subscribe", "" /* generate id */) case msgCommand: conversation, ok := s.conversations[cmd.to] if (!ok || !conversation.IsEncrypted()) && config.ShouldEncryptTo(cmd.to) { warn(s.term, fmt.Sprintf("Did not send: no encryption established with %s", cmd.to)) continue } var msgs [][]byte message := []byte(cmd.msg) // Automatically tag all outgoing plaintext // messages with a whitespace tag that // indicates that we support OTR. if config.OTRAutoAppendTag && !bytes.Contains(message, []byte("?OTR")) && (!ok || !conversation.IsEncrypted()) { message = append(message, OTRWhitespaceTag...) } if ok { var err error msgs, err = conversation.Send(message) if err != nil { alert(s.term, err.Error()) break } } else { msgs = [][]byte{[]byte(message)} } for _, message := range msgs { s.conn.Send(cmd.to, string(message)) } case otrCommand: s.conn.Send(string(cmd.User), otr.QueryMessage) case otrInfoCommand: info(term, fmt.Sprintf("Your OTR fingerprint is %x", s.privateKey.Fingerprint())) for to, conversation := range s.conversations { if conversation.IsEncrypted() { info(s.term, fmt.Sprintf("Secure session with %s underway:", to)) printConversationInfo(s, to, conversation) } } case endOTRCommand: to := string(cmd.User) conversation, ok := s.conversations[to] if !ok { alert(s.term, "No secure session established") break } msgs := conversation.End() for _, msg := range msgs { s.conn.Send(to, string(msg)) } case authQACommand: to := string(cmd.User) conversation, ok := s.conversations[to] if !ok { alert(s.term, "Can't authenticate without a secure conversation established") break } msgs, err := conversation.Authenticate(cmd.Question, []byte(cmd.Secret)) if err != nil { alert(s.term, "Error while starting authentication with "+to+": "+err.Error()) } for _, msg := range msgs { s.conn.Send(to, string(msg)) } case authOobCommand: fpr, err := hex.DecodeString(cmd.Fingerprint) if err != nil { alert(s.term, fmt.Sprintf("Invalid fingerprint %s - not authenticated", cmd.Fingerprint)) break } existing := s.config.UserIdForFingerprint(fpr) if len(existing) != 0 { alert(s.term, fmt.Sprintf("Fingerprint %s already belongs to %s", cmd.Fingerprint, existing)) break } s.config.KnownFingerprints = append(s.config.KnownFingerprints, KnownFingerprint{fingerprint: fpr, UserId: cmd.User}) s.config.Save() info(s.term, fmt.Sprintf("Saved manually verified fingerprint %s for %s", cmd.Fingerprint, cmd.User)) case awayCommand: s.conn.SignalPresence("away") case chatCommand: s.conn.SignalPresence("chat") case dndCommand: s.conn.SignalPresence("dnd") case xaCommand: s.conn.SignalPresence("xa") case onlineCommand: s.conn.SignalPresence("") } case rawStanza, ok := <-stanzaChan: if !ok { warn(term, "Exiting because channel to server closed") break MainLoop } switch stanza := rawStanza.Value.(type) { case *xmpp.ClientMessage: s.processClientMessage(stanza) case *xmpp.ClientPresence: s.processPresence(stanza) case *xmpp.ClientIQ: if stanza.Type != "get" && stanza.Type != "set" { continue } reply := s.processIQ(stanza) if reply == nil { reply = xmpp.ErrorReply{ Type: "cancel", Error: xmpp.ErrorBadRequest{}, } } if err := s.conn.SendIQReply(stanza.From, "result", stanza.Id, reply); err != nil { alert(term, "Failed to send IQ message: "+err.Error()) } default: info(term, fmt.Sprintf("%s %s", rawStanza.Name, rawStanza.Value)) } } } os.Stdout.Write([]byte("\n")) }
func doRewritePackage(pkg *build.Package, st *rewriteState, opts *rewriteOptions) error { libraryMode := opts.LibraryMode(pkg) abs, err := filepath.Abs(pkg.Dir) if err != nil { return err } fset := token.NewFileSet() var names []string names = append(names, pkg.GoFiles...) names = append(names, pkg.CgoFiles...) files, err := parseFiles(fset, abs, names, parser.ParseComments) if err != nil { return err } // First check if we should keep any original imports in the package due to // the use it makes of the imported pkg (type assertions, etc...). disabled := make(map[string]bool) for _, v := range files { imports := astutil.Imports(fset, v) for _, group := range imports { for _, imp := range group { if unquoted, err := strconv.Unquote(imp.Path.Value); err == nil { m := repositoryRe.FindStringSubmatch(unquoted) if len(m) > 0 && shouldKeepOriginalImport(fset, unquoted, imp, v, opts) { disabled[unquoted] = true } } } } } using := make(map[string]bool) for _, v := range files { imports := astutil.Imports(fset, v) for _, group := range imports { for _, imp := range group { if unquoted, err := strconv.Unquote(imp.Path.Value); err == nil { m := repositoryRe.FindStringSubmatch(unquoted) if len(m) > 0 && !disabled[unquoted] { using[m[0]] = true } } } } } // Now check imports we should rewrite if len(using) == 0 { return nil } var repoNames []string for k := range using { repoNames = append(repoNames, k) } if opts.Verbose { fmt.Printf("package %s uses %d 3rd party repositories: %v\n", pkgName(pkg), len(repoNames), repoNames) } repos, err := st.RequestRepos(repoNames) if err != nil { return err } rewrites := make(map[string]string) addRewrites: for _, v := range repos { var importPath string if libraryMode { if v.Version == 0 { if v.AllowsUnpinned { importPath = v.GoPkgsPath } else { if opts.Verbose { fmt.Printf("ignoring package %s, no versions available\n", v.Path) } continue } } else { importPath = v.VersionImportPath() } } else { if opts.PreferRevisions { importPath = v.RevisionImportPath() } else { importPath = v.VersionImportPath() } } if opts.Interactive { prompt: for { fmt.Printf("rewrite import %s to %s in package %s? (y/N)", v.Path, importPath, pkgName(pkg)) oldState, err := terminal.MakeRaw(0) if err != nil { panic(err) } var buf [1]byte os.Stdin.Read(buf[:]) terminal.Restore(0, oldState) fmt.Print("\n") switch buf[0] { case 'y', 'Y': break prompt case 'n', 'N', '\r': // /r is enter continue addRewrites case '\x03', '\x01': // ctrl+c, ctrl+z os.Exit(0) } } } rewrites[v.Path] = importPath } if len(rewrites) == 0 { return nil } // TODO go get new imports return rewriteImports(fset, pkg, files, rewrites, st, opts) }
func (sshToContainerCmd) Run(context *cmd.Context, _ *cmd.Client) error { serverURL, err := cmd.GetURL("/docker/ssh/" + context.Args[0]) if err != nil { return err } request, err := http.NewRequest("GET", serverURL, nil) if err != nil { return err } request.Close = true token, err := cmd.ReadToken() if err == nil { request.Header.Set("Authorization", "bearer "+token) } parsedURL, _ := url.Parse(serverURL) conn, err := net.Dial("tcp", parsedURL.Host) if err != nil { return err } defer conn.Close() request.Write(conn) if stdin, ok := context.Stdin.(*os.File); ok { fd := int(stdin.Fd()) if terminal.IsTerminal(fd) { oldState, err := terminal.MakeRaw(fd) if err != nil { return err } defer terminal.Restore(fd, oldState) sigChan := make(chan os.Signal, 2) go func(c <-chan os.Signal) { if _, ok := <-c; ok { terminal.Restore(fd, oldState) os.Exit(1) } }(sigChan) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT) } } bytesLimit := 50 var readStr string byteBuffer := make([]byte, 1) for i := 0; i < bytesLimit && byteBuffer[0] != '\n'; i++ { _, err := conn.Read(byteBuffer) if err != nil { break } readStr += string(byteBuffer) } matches := httpHeaderRegexp.FindAllStringSubmatch(readStr, -1) if len(matches) > 0 && len(matches[0]) > 1 { code, _ := strconv.Atoi(matches[0][1]) return &errors.HTTP{ Code: code, Message: strings.TrimSpace(readStr), } } else { context.Stdout.Write([]byte(readStr)) } errs := make(chan error, 2) quit := make(chan bool) go io.Copy(conn, context.Stdin) go func() { defer close(quit) _, err := io.Copy(context.Stdout, conn) if err != nil && err != io.EOF { errs <- err } }() <-quit close(errs) return <-errs }
func run() error { fset := twik.NewFileSet() scope := twik.NewDefaultScope(fset) scope.Create("printf", printfFn) scope.Create("list", listFn) if len(os.Args) > 1 { if strings.HasPrefix(os.Args[1], "-") { return fmt.Errorf("usage: twik [<source file>]") } f, err := os.Open(os.Args[1]) if err != nil { return err } defer f.Close() data, err := ioutil.ReadAll(f) if err != nil { return err } node, err := twik.Parse(fset, os.Args[1], data) if err != nil { return err } _, err = scope.Eval(node) return err } state, err := terminal.MakeRaw(1) if err != nil { return err } defer terminal.Restore(1, state) t := terminal.NewTerminal(os.Stdout, "> ") unclosed := "" for { line, err := t.ReadLine() if err == io.EOF { break } if err != nil { return err } if unclosed != "" { line = unclosed + "\n" + line } unclosed = "" t.SetPrompt("> ") node, err := twik.ParseString(fset, "", line) if err != nil { if strings.HasSuffix(err.Error(), "missing )") { unclosed = line t.SetPrompt(". ") continue } fmt.Println(err) continue } value, err := scope.Eval(node) if err != nil { fmt.Println(err) continue } if value != nil { if reflect.TypeOf(value).Kind() == reflect.Func { fmt.Println("#func") } else if v, ok := value.([]interface{}); ok { if len(v) == 0 { fmt.Println("()") } else { fmt.Print("(list") for _, e := range v { fmt.Printf(" %#v", e) } fmt.Println(")") } } else { fmt.Printf("%#v\n", value) } } } fmt.Println() return nil }
// Shell opens a shell connection on the servives ssh address. func Shell(app *schemas.Application, service *schemas.Service) error { // Make sure we're in raw mode. termState, err := terminal.MakeRaw(int(os.Stdin.Fd())) if err != nil { if prompt.IsNotTerminal(err) { return errors.ErrIORedirection } return errors.NewStackError(err) } defer terminal.Restore(int(os.Stdin.Fd()), termState) // Get terminal size. cols, rows, err := terminal.GetSize(int(os.Stdout.Fd())) if err != nil { if prompt.IsNotTerminal(err) { return errors.ErrIORedirection } return errors.NewStackError(err) } // Open an SSH connection to the address. config := &ssh.ClientConfig{User: "******", Auth: []ssh.AuthMethod{ ssh.Password("password"), }} client, err := ssh.Dial("tcp", service.SSHAddr, config) if err != nil { return errors.NewStackError(err) } defer client.Close() // Start a session on the client. session, err := client.NewSession() if err != nil { return errors.NewStackError(err) } defer session.Close() session.Stdout = prompt.NewAnsiWriter(os.Stdout) session.Stderr = prompt.NewAnsiWriter(os.Stderr) // Create a stdin pipe copying os.Stdin to it. stdin, err := session.StdinPipe() if err != nil { return errors.NewStackError(err) } defer stdin.Close() go func() { io.Copy(stdin, prompt.NewAnsiReader(os.Stdin)) }() log.Println("magenta", "Welcome to Bowery Services.") log.Println("magenta", "---------------------------------------------") log.Println("magenta", "Name:", service.Name) log.Println("magenta", "Application:", app.ID) log.Println("magenta", "Time:", time.Now()) log.Println("magenta", "---------------------------------------------") // Start a shell session. termModes := ssh.TerminalModes{ ssh.ECHO: 1, ssh.TTY_OP_ISPEED: 14400, ssh.TTY_OP_OSPEED: 14400, } err = session.RequestPty("xterm", rows, cols, termModes) if err == nil { err = session.Shell() } if err != nil { return errors.NewStackError(err) } // Wait for the session. err = session.Wait() if err != nil && err != io.EOF { // Ignore the error if it's an ExitError with an empty message, // this occurs when you do CTRL+c and then run exit cmd which isn't an // actual error. waitMsg, ok := err.(*ssh.ExitError) if ok && waitMsg.Msg() == "" { return nil } return errors.NewStackError(err) } return nil }
func main() { flag.Parse() w := eval.NewWorld() if *filename != "" { data, err := ioutil.ReadFile(*filename) if err != nil { fmt.Println(err.Error()) os.Exit(1) } file, err := parser.ParseFile(fset, *filename, data, 0) if err != nil { fmt.Println(err.Error()) os.Exit(1) } files := []*ast.File{file} code, err := w.CompilePackage(fset, files, "main") if err != nil { if list, ok := err.(scanner.ErrorList); ok { for _, e := range list { fmt.Println(e.Error()) } } else { fmt.Println(err.Error()) } os.Exit(1) } code, err = w.Compile(fset, "main()") if err != nil { fmt.Println(err.Error()) os.Exit(1) } _, err = code.Run() if err != nil { fmt.Println(err.Error()) os.Exit(1) } os.Exit(0) } fmt.Println(":: welcome to go-eval...\n(hit ^D to exit)") fd := int(os.Stdin.Fd()) oldState, err := terminal.MakeRaw(fd) if err != nil { panic(err) } defer terminal.Restore(fd, oldState) term := terminal.NewTerminal(&shell{r: os.Stdin, w: os.Stdout}, "> ") if term == nil { panic(errors.New("could not create terminal")) } for { line, err := term.ReadLine() if err != nil { break } code, err := w.Compile(fset, line) if err != nil { term.Write([]byte(err.Error() + "\n")) continue } v, err := code.Run() if err != nil { term.Write([]byte(err.Error() + "\n")) continue } if v != nil { term.Write([]byte(v.String() + "\n")) } } }