charmbracelet / wish

Make SSH apps, just like that! 💫
MIT License
3.57k stars 71 forks source link

wish.Command() : bash script is displayed in the server console, not the client console. #303

Open Buanderie opened 2 months ago

Buanderie commented 2 months ago

Describe the bug Bash script using "dialog" is displayed on server side (on the console that launched my wish app)

Setup Please complete the following information along with version numbers, if applicable.

To Reproduce Use my app like so: ./myapp -i script.sh

This bash script works:

#!/bin/bash

echo "Hello !"
while(true)
do
    echo -n "."
    sleep 1
done

While this one does not (displayed on the server side, instead...)

#!/bin/bash

SCRIPT_DIR="$( dirname "${BASH_SOURCE[0]}" )"

# Function to display the main menu
show_menu() {
    whiptail --clear --backtitle "" --title "Main Menu" \
    --menu "Choose a task:" 15 50 4 \
    1 "Go to command line"
}

show_menu

Source Code

package main

import (
    "flag"
    "strconv"
    "log"
    // "os/exec"
    "github.com/charmbracelet/ssh"
    "github.com/charmbracelet/wish"
    "github.com/charmbracelet/wish/logging"
    "github.com/charmbracelet/wish/activeterm"
)

func main() {

    // Define command-line flags
    serverPort := flag.Int("p", 2222, "SSH Server port")
    scriptPath := flag.String("i", "", "Input script to be executed")
    flag.Parse()

    // Create the SSH server with a custom server configuration
    portStr := strconv.Itoa(*serverPort)
    s, err := wish.NewServer(
        wish.WithAddress("0.0.0.0:"+portStr),
        ssh.AllocatePty(),
        wish.WithMiddleware(
            logging.Middleware(),
            activeterm.Middleware(),
        ),
        wish.WithPasswordAuth(func(ctx ssh.Context, password string) bool {
            // Implement your password authentication logic here
            // Example: only allow a specific username and password
            return ctx.User() == "root" && password == "root"
        }),

        wish.WithMiddleware(
            func(next ssh.Handler) ssh.Handler {
                return func(sess ssh.Session) {
                    pty, _, _ := sess.Pty()

                    wish.Printf(sess, "Term: %s\r\n", pty.Term)
                    wish.Printf(sess, "PTY: %s\r\n", pty.Slave.Name())
                    wish.Printf(sess, "FD: %d\r\n", pty.Slave.Fd())

                    // wish.Println(sess, "Hello, world!")

                    cmd := wish.Command( sess, "/bin/bash", *scriptPath)

                    // cmd := exec.Command("/bin/bash", *scriptPath)
                    // cmd.Stdout = sess
                    // cmd.Stderr = sess
                    // cmd.Stdin = pty.Slave

                    cmd.Run()

                    next(sess)
                }
            },

            // The last item in the chain is the first to be called.
            logging.Middleware(),
        ),
    )
    if err != nil {
        log.Fatalln(err)
    }

    // Start the SSH server
    // log.Println("Starting SSH server on port 2222...")
    log.Printf( "Serving script %s on SSH server [port=%d]\n", *scriptPath, *serverPort)
    log.Fatal(s.ListenAndServe())

}

Expected behavior The script is displayed on the console of the client

caarlos0 commented 2 months ago

not sure what's going there, but I cannot repro...

even added an example https://github.com/charmbracelet/wish/tree/main/examples/exec

caarlos0 commented 2 months ago

maybe whiptail is doing something funky...