Skip to content

Instantly share code, notes, and snippets.

@vinitkumar
Created June 6, 2025 06:34
Show Gist options
  • Save vinitkumar/960ff3b9d5da80b9724930ab280e30ea to your computer and use it in GitHub Desktop.
Save vinitkumar/960ff3b9d5da80b9724930ab280e30ea to your computer and use it in GitHub Desktop.

Revisions

  1. vinitkumar created this gist Jun 6, 2025.
    156 changes: 156 additions & 0 deletions temp.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,156 @@
    package main

    import (
    "bufio"
    "fmt"
    "io"
    "log"
    "os"
    "os/exec"
    "runtime"
    "syscall"
    )

    // Dummy values for the example
    var (
    binaryPath = "echo" // Simple command that works on all platforms
    shell = "bash"
    authorizedKeysFile = "/tmp/dummy_authorized_keys"
    privateKeyPath = "/tmp/dummy_private_key"
    server = "dummy.server.com"
    sessionID = "dummy-session-123"
    )

    // PTY interface to match the original code
    type PTY interface {
    Read([]byte) (int, error)
    Write([]byte) (int, error)
    Close() error
    }

    // Simple PTY implementation that wraps exec.Cmd stdout
    type simplePTY struct {
    cmd *exec.Cmd
    stdout io.ReadCloser
    stdin io.WriteCloser
    }

    func (p *simplePTY) Read(b []byte) (int, error) {
    return p.stdout.Read(b)
    }

    func (p *simplePTY) Write(b []byte) (int, error) {
    return p.stdin.Write(b)
    }

    func (p *simplePTY) Close() error {
    if p.stdout != nil {
    p.stdout.Close()
    }
    if p.stdin != nil {
    p.stdin.Close()
    }
    return nil
    }

    // Simplified startPTY function - just uses regular pipes instead of real PTY
    func startPTY(cmd *exec.Cmd) (PTY, error) {
    stdout, err := cmd.StdoutPipe()
    if err != nil {
    return nil, err
    }

    stdin, err := cmd.StdinPipe()
    if err != nil {
    return nil, err
    }

    if err := cmd.Start(); err != nil {
    return nil, err
    }

    return &simplePTY{
    cmd: cmd,
    stdout: stdout,
    stdin: stdin,
    }, nil
    }

    // ptyError handles PTY-specific errors across different platforms
    func ptyError(err error) error {
    if err == nil {
    return nil
    }

    if runtime.GOOS == "windows" {
    return err
    }

    // Unix systems - ignore EIO errors
    if pathErr, ok := err.(*os.PathError); !ok || pathErr.Err != syscall.EIO {
    return err
    }

    return nil
    }

    // processOutput function from the original code
    func processOutput(reader io.Reader) {
    var sessionID string
    var receivedSessionID bool

    scanner := bufio.NewScanner(reader)
    for scanner.Scan() {
    line := scanner.Text()
    fmt.Println("line", line)
    // Check if this is the session ID line
    if !receivedSessionID {
    sessionID = line
    log.Printf("Received session ID: %s", sessionID)
    receivedSessionID = true
    continue
    }

    // Log all subsequent lines
    log.Printf("[%s] Received output: %s", sessionID, line)
    }

    if err := scanner.Err(); err != nil {
    log.Fatalf("Error reading command output: %v", err)
    }
    }

    func main() {
    log.Println("Starting minimal reproducible example")

    // Simulate the original command structure with dummy values
    // Instead of the complex upterm command, we'll use echo to simulate output
    cmd := exec.Command("echo", "session-id-123\nHello from upterm session\nAnother line of output")

    log.Printf("Command Executed: %s", cmd.String())

    // Start the command with our simplified PTY
    ptmx, err := startPTY(cmd)
    if err != nil {
    log.Fatalf("Failed to start command: %v", err)
    }
    defer ptmx.Close()

    // Create a pipe to capture the command's output
    reader, writer := io.Pipe()

    // Start a goroutine to copy the command's output to the pipe
    go func() {
    defer writer.Close()
    _, err := io.Copy(writer, ptmx)
    actualError := ptyError(err)
    if actualError != nil {
    log.Fatalf("Error copying command output to pipe: %v", err)
    }
    }()

    // Pass the output of the command to another function
    processOutput(reader)

    log.Println("Example completed")
    }