how to handle specific character of ssh.StdoutPipe()

Viewed 170

I am working on app, needs to manage ssh. so I used ssh module and as i needed, using StdoutPipe expect of session.Stdout.

by the way, in some situation, I got output with specific character

My problem is: there are some specific character (here backspace), that are handled correctly when using fmt.Println(). but it will be printed in sample files out.log!. so it exists in text too. How can I handle them? in another word; how can I convert them to printable format and store then in the string variable

    stdOutputResult := []byte{114, 111, 111, 116, 64, 100, 101, 98, 105, 97, 110, 58, 126, 35, 32, 104, 101, 108, 108, 111, 8, 8, 8, 8, 8, 116, 101, 115, 116, 50, 8, 8, 8, 120, 116, 49}
    text := string(stdOutputResult)
    fmt.Println("len(stdOutputResult):", len(stdOutputResult))
    fmt.Println("len(text):", len(text))
    fmt.Println(text)
    ioutil.WriteFile("out.log", []byte(text), 0644)

cli output:

   len(stdOutputResult): 36
   len(text): 36
   root@debian:~# text1

file output 'out.log':

root@debian:~# helloBSBSBSBSBStest2BSBSBSxt1

here is part of my code:

import (
    "bufio"
    "fmt"
    "golang.org/x/crypto/ssh"
    "golang.org/x/crypto/ssh/terminal"
    "log"
    "net"
    "os"
    "os/exec"
    "strings"
)

type Connection struct {
    *ssh.Client
    password string
}

func connectServer(addr, user, password string) (sInfo *SessionInfo, err error){
    conn, err := dialSSH(addr, user, password)
    if err != nil {
        return nil, err
    }
    closeGoRoutines := false
    quit2 := make(chan bool)
    quit4 := make(chan bool)

    session, err := conn.NewSession()
    if err != nil {
        panic("Failed to create session: " + err.Error())
    }
    defer session.Close()

    //// Set IO
    //session.Stdout = os.Stdout
    sessionStdout, _ := session.StdoutPipe()
    session.Stderr = os.Stderr
    in, _ := session.StdinPipe()

    modes := ssh.TerminalModes{
        ssh.ECHO:          1,     // enable echoing
        ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
        ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
    }
    fileDescriptor := int(os.Stdin.Fd())

    if terminal.IsTerminal(fileDescriptor) {
        originalState, err := terminal.MakeRaw(fileDescriptor)
        if err != nil {

        }
        defer terminal.Restore(fileDescriptor, originalState)

        termWidth, termHeight, err := terminal.GetSize(fileDescriptor)
        if err != nil {

        }

        //err = session.RequestPty("xterm-256color", termHeight, termWidth, modes)
        err = session.RequestPty("xterm", termHeight, termWidth, modes)
        //err = session.RequestPty("dumb", termHeight, termWidth, modes)
        if err != nil {

        }
    }

    // Start remote shell
    if err := session.Shell(); err != nil {
        log.Fatalf("failed to start shell: %s", err)
    }

    // handle stdout
    //chanStdout := make(chan string)
    chanStdout := make(chan byte)
    go func(ch chan byte) {
        r := bufio.NewReader(sessionStdout)
        for {
            var b []byte = make([]byte, 1)
            _, err := r.Read(b)
            //if err != nil && err == io.EOF {
            if err != nil{
                prepareToExit()
                closeGoRoutines = true
                quit2 <- true
                quit4 <- true
                return
            }
            //w.Write(b)
            chanStdout <- b[0]
            //chanStdout <- string(b)
        }
    }(chanStdout)
    lastoutLine :=  ""

    sInfo = NewSessionInfo()

    go func() {
        for {
            select {
            case <-quit2:
                return
            case stdout, _ := <-chanStdout:
                sInfo.AddToCLI(stdout)

            
            }
        }
    }()

    stdinLine := ""


    go func() {
        //disable input buffering
        exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
        //do not display entered characters on the screen
        exec.Command("stty", "-F", "/dev/tty", "-echo").Run()
        //fmt.Fprint(in, "bind 'set bell-style none'\n")
        fmt.Fprint(in, "sudo -i\n")
        var b []byte = make([]byte, 1)
        for {
            _ , err := os.Stdin.Read(b)
            if err != nil{
                return
            }
            if closeGoRoutines{
                return
            }
            stdin := b[0]
            if stdin == 13 || stdin == 10 {
                //fmt.Println("------------"+stdinLine+"-")
                if stdinLine == "ssmgo" {
                    fmt.Println("\r\nyou'r morteza iravani")
                }
                if ! isCommandAllowed(stdinLine, lastoutLine){
                    stdinLine = ""
                    fmt.Println("command not allowed")
                    continue
                }
                sInfo.appendHistory(stdinLine)
                //sInfo.appendHistoryFromSTDIN(stdinLine)
                //print("<" + lastoutLine + ">")
                //lastoutLine = ""

                //historyBashOld = append(historyBashOld, sInfo.command)
                stdinLine = ""
                //con
            } else {
                stdinLine = stdinLine + string(stdin)
                //fmt.Println(stdinLine)
            }


            in.Write(b)
            //ch <- b[0]
        }
    }()


    <- quit4
    return

}

func dialSSH(addr, user, password string) (*Connection, error) {
    sshConfig := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
        },
        HostKeyCallback: ssh.HostKeyCallback(func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }),
    }
    conn, err := ssh.Dial("tcp", addr, sshConfig)
    if err != nil {
        return nil, err
    }

    return &Connection{conn, password}, nil

}

func isCommandAllowed(line, lastoutLine string) bool {
    if len(line) > 0 {
        cmd := strings.Split(line, " ")[0]
        //fmt.Println(" is ("+cmd+")  ["+lastoutLine+"] banded:" + string(bandedCommands[cmd]))
        _, exist := bandedCommands[cmd]
        return !exist
    }
    return true
}

func prepareToExit(){
    exec.Command("stty", "-F", "/dev/tty", "sane").Run()
}
0 Answers
Related