func getCmdWeb(s liblush.Session, idstr string) (liblush.Cmd, error) { id, _ := liblush.ParseCmdId(idstr) c := s.GetCommand(id) if c == nil { return nil, web.WebError{404, "no such command: " + idstr} } return c, nil }
func getCmd(s *server, idstr string) (liblush.Cmd, error) { var err error id, _ := liblush.ParseCmdId(idstr) c := s.session.GetCommand(id) if c == nil { err = errors.New("no such command: " + idstr) } return c, err }
// free resources associated with a command. eg: // // release;3 // // will generate a cmd_released;<id> event. eg: // // cmd_released;3 // // cannot be executed while command is running. func wseventRelease(s *server, idstr string) error { id, _ := liblush.ParseCmdId(idstr) err := s.session.ReleaseCommand(id) if err != nil { return err } _, err = fmt.Fprintf(&s.ctrlclients, "cmd_released;%s", idstr) return err }
func handleGetCmdJson(ctx *web.Context, idstr string) error { id, _ := liblush.ParseCmdId(idstr) s := ctx.User.(*server) c := s.session.GetCommand(id) if c == nil { return web.WebError{404, "no such command: " + idstr} } md, err := metacmd{c}.Metadata() if err != nil { return err } ctx.ContentType("json") // Don't hammer me, but don't cache for too long. This resource is not // intended for polling, anyway. This may seem race sensitive, but that's // because it is. Only matters in big, multi user setups with lots of // concurrent changes, which is totally not lush's current intended use // case. So a few race conditions here and there are no biggy (for now). ctx.Response.Header().Set("cache-control", "max-age=3") return json.NewEncoder(ctx).Encode(md) }
func handlePostClose(ctx *web.Context, idstr string) error { if err := errorIfNotMaster(ctx); err != nil { return err } id, _ := liblush.ParseCmdId(idstr) s := ctx.User.(*server) c := s.session.GetCommand(id) if c == nil { return web.WebError{404, "no such command: " + idstr} } if ctx.Params["stream"] != "stdin" { return web.WebError{400, "must send to stdin"} } err := c.Stdin().Close() if err != nil { return err } redirect(ctx, cmdloc(c)) return nil }
func handleWsStream(ctx *web.Context, idstr, streamname string) error { id, _ := liblush.ParseCmdId(idstr) s := ctx.User.(*server) c := s.session.GetCommand(id) if c == nil { return web.WebError{404, "no such command: " + idstr} } var stream liblush.OutStream switch streamname { case "stdout": stream = c.Stdout() case "stderr": stream = c.Stderr() default: return web.WebError{400, "No such stream: " + streamname} } stream.Peeker().AddWriter(ctx.WebsockConn) buf := make([]byte, 1) ctx.WebsockConn.Read(buf) return nil }
func handleGetCmdInfo(ctx *web.Context, idstr string) error { id, _ := liblush.ParseCmdId(idstr) s := ctx.User.(*server) c := s.session.GetCommand(id) if c == nil { return web.WebError{404, "no such command: " + idstr} } ctx.Header().Set("content-type", "application/json") enc := json.NewEncoder(ctx) var info = struct { Started, Exited *time.Time Error string `json:",omitempty"` }{ Started: c.Status().Started(), Exited: c.Status().Exited(), } if cerr := c.Status().Err(); cerr != nil { info.Error = cerr.Error() } return enc.Encode(info) }
func handleGetCmd(ctx *web.Context, idstr string) error { type cmdctx struct { Cmd liblush.Cmd Stdout string Stderr string Connectables chan liblush.Cmd } id, _ := liblush.ParseCmdId(idstr) s := ctx.User.(*server) c := s.session.GetCommand(id) if c == nil { return web.WebError{404, "no such command: " + idstr} } stdout := make([]byte, 1000) stderr := make([]byte, 1000) n := c.Stdout().Scrollback().Last(stdout) stdout = stdout[:n] n = c.Stderr().Scrollback().Last(stderr) stderr = stderr[:n] ch := make(chan liblush.Cmd) go func() { for _, id := range s.session.GetCommandIds() { other := s.session.GetCommand(id) if c.Id() != other.Id() && other.Status().Started() == nil { ch <- other } } close(ch) }() tmplCtx := cmdctx{ Cmd: c, Stdout: string(stdout), Stderr: string(stderr), Connectables: ch, } err := s.tmplts.ExecuteTemplate(ctx, "cmd", tmplCtx) return err }