this repo has no description smallweb.run
smallweb
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix support for interactive inputs

pomdtr 45921ab1 2cc4a04c

+53 -24
+53 -24
cmd/up.go
··· 17 17 "slices" 18 18 "strings" 19 19 "sync" 20 + "syscall" 21 + "unsafe" 20 22 21 23 _ "embed" 22 24 ··· 25 27 "github.com/charmbracelet/keygen" 26 28 "github.com/charmbracelet/ssh" 27 29 "github.com/charmbracelet/wish" 30 + "github.com/creack/pty" 28 31 "github.com/libdns/acmedns" 29 32 "github.com/picosh/pobj" 30 33 "github.com/pomdtr/smallweb/storage" ··· 273 276 sftp.SSHOption(handler), 274 277 wish.WithMiddleware(func(next ssh.Handler) ssh.Handler { 275 278 return func(sess ssh.Session) { 279 + var cmd *exec.Cmd 276 280 if sess.User() == "_" { 277 - rootCmd := NewCmdRoot() 278 - args := make([]string, 0) 279 - args = append(args, sess.Command()...) 280 - rootCmd.SetArgs(args) 281 - rootCmd.SetIn(sess) 282 - rootCmd.SetOut(sess) 283 - rootCmd.SetErr(sess.Stderr()) 284 - rootCmd.CompletionOptions.DisableDefaultCmd = true 285 - if err := rootCmd.Execute(); err != nil { 286 - _ = sess.Exit(1) 281 + execPath, err := os.Executable() 282 + if err != nil { 283 + 284 + } 285 + 286 + cmd = exec.Command(execPath, sess.Command()...) 287 + cmd.Env = os.Environ() 288 + cmd.Env = append(cmd.Env, fmt.Sprintf("SMALLWEB_DIR=%s", k.String("dir"))) 289 + cmd.Env = append(cmd.Env, fmt.Sprintf("SMALLWEB_DOMAIN=%s", k.String("domain"))) 290 + } else { 291 + a, err := app.LoadApp(sess.User(), k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), sess.User())) 292 + if err != nil { 293 + fmt.Fprintf(sess, "failed to load app: %v\n", err) 287 294 return 288 295 } 289 296 290 - return 291 - } 297 + wk := worker.NewWorker(a) 298 + command, err := wk.Command(sess.Context(), sess.Command()...) 299 + if err != nil { 300 + fmt.Fprintf(sess, "failed to get command: %v\n", err) 301 + return 302 + } 292 303 293 - a, err := app.LoadApp(sess.User(), k.String("dir"), k.String("domain"), slices.Contains(k.Strings("adminApps"), sess.User())) 294 - if err != nil { 295 - fmt.Fprintf(sess, "failed to load app: %v\n", err) 296 - return 304 + cmd = command 297 305 } 298 306 299 - wk := worker.NewWorker(a) 300 - command, err := wk.Command(sess.Context(), sess.Command()...) 301 - if err != nil { 302 - fmt.Fprintf(sess, "failed to get command: %v\n", err) 307 + ptyReq, winCh, isPty := sess.Pty() 308 + if isPty { 309 + cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term)) 310 + f, err := pty.Start(cmd) 311 + if err != nil { 312 + panic(err) 313 + } 314 + go func() { 315 + for win := range winCh { 316 + syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), 317 + uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(win.Height), uint16(win.Width), 0, 0}))) 318 + } 319 + }() 320 + go func() { 321 + io.Copy(f, sess) 322 + }() 323 + io.Copy(sess, f) 324 + 325 + if err := cmd.Wait(); err != nil { 326 + var exitErr *exec.ExitError 327 + if errors.As(err, &exitErr) { 328 + sess.Exit(exitErr.ExitCode()) 329 + } 330 + sess.Exit(1) 331 + } 303 332 return 304 333 } 305 334 306 - command.Stdout = sess 307 - command.Stderr = sess.Stderr() 308 - stdin, err := command.StdinPipe() 335 + cmd.Stdout = sess 336 + cmd.Stderr = sess.Stderr() 337 + stdin, err := cmd.StdinPipe() 309 338 if err != nil { 310 339 fmt.Fprintf(sess, "failed to get stdin: %v\n", err) 311 340 return ··· 316 345 io.Copy(stdin, sess) 317 346 }() 318 347 319 - if err := command.Run(); err != nil { 348 + if err := cmd.Run(); err != nil { 320 349 var exitErr *exec.ExitError 321 350 if errors.As(err, &exitErr) { 322 351 sess.Exit(exitErr.ExitCode())