0

I am creating a shell command from the custom shell to do the ssh from one terminal to another terminal. In order to do the ssh, I am using the inbuilt ssh command of the linux. Here is my code that does the ssh login. However, I am seeing that the I/O buffers are not in sync.

This is what I am seeing on the terminal. After SSH to the other terminal. I did the following in the terminal.

PRT# ssh 192.168.10.42
PRT# Could not create directory '/root/.ssh'.
root@192.168.10.42's password: 
# screen -r
-sh: cen-: not found
# hello
-sh: el: not found
# 

I don't what's the reason here. Here is the code.

int sshLogin(chr *destIp)
{
    char cmd[CMD_LEN];
    char readbuff[CMD_LEN];
    pid_t pid;
    int ret = 0;
    int fd[2];
    int result;
    memset(cmd,'\0',sizeof(cmd));
    int status = 0;

    /** --tt required to force pseudowire allocation because we are behind screen app **/
    sprintf(cmd,"/usr/bin/ssh -tt %s",destIp);

    /** create a pipe this will be shared on fork() **/
    pipe(fd);

    if((pid = fork()) == -1)
    {
        perror("fork:");
        return -1;
    }
    if( pid == 0 )
    {
        /** Child Process of Main APP --Make this parent process for the command**/

        if((pid = fork()) == -1)
        {
            perror("fork:");
            return -1;
        }

        if( pid == 0)
        {
            /** basically Main APP grand child - this is where we running the command **/
            ret = execlp("ssh", "ssh", "-tt", destIp, NULL);
            printf("done execlp\r\n");
        }
        else
        {
           /** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/
            while( (read(fd[0], readbuff, sizeof(readbuff))))
            {
                printf("%s",readbuff);
            }

            waitpid(0,&status,0);
            LOG_STRING("SSH CONNC CLOSED");
            exit(0);
        }
    }
    else
    {
        /** Parent process APP MAIN--  **/
        /** no need to wait let APP MAIN run -- **/
    }

    return 0;
}

Based on Patrick Ideas.

POST 2# - It seems that it works when we close the stdin in the parent process. However, it becomes very slugguish, I feel like I am typing the keyboard too slow. The system becomes too sluggish. Also, I have a web-server from this terminal. I see that I can no longer access the web. So, the solution is somewhere around stdin but I am not sure.

int sshLogin(chr *destIp)
    {
        char cmd[CMD_LEN];
        char readbuff[CMD_LEN];
        pid_t pid;
        int ret = 0;
        int fd[2];
        int result;
        memset(cmd,'\0',sizeof(cmd));
        int status = 0;

        /** --tt required to force pseudowire allocation because we are behind screen app **/
        sprintf(cmd,"/usr/bin/ssh -tt %s",destIp);

        /** create a pipe this will be shared on fork() **/
        pipe(fd);

        if((pid = fork()) == -1)
        {
            perror("fork:");
            return -1;
        }
        if( pid == 0 )
        {
            /** Child Process of Main APP --Make this parent process for the command**/

            if((pid = fork()) == -1)
            {
                perror("fork:");
                return -1;
            }

            if( pid == 0)
            {
                /** basically Main APP grand child - this is where we running the command **/
                ret = execlp("ssh", "ssh", "-tt", destIp, NULL);
                printf("done execlp\r\n");
            }
            else
            {
               /** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/
                while( (read(fd[0], readbuff, sizeof(readbuff))))
                {
                    printf("%s",readbuff);
                }

                waitpid(0,&status,0);
                LOG_STRING("SSH CONNC CLOSED");
                exit(0);
            }
        }
        else
        {
            /** Parent process APP MAIN--  **/
            /** no need to wait let APP MAIN run -- **/
            close(stdin);
        }

        return 0;
    }

Basically, I have added - close(stdin);

dexterous
  • 5,684
  • 9
  • 42
  • 84

2 Answers2

1

You have 2 different processes trying to read from STDIN. This causes process 1 to get char 1, process 2 to get char 2, process 1 to get char 3, process 2 to get char 4, etc, alternating back and forth.

Your 2 processes are:

  1. execlp("ssh", "ssh", "-tt", destIp, NULL);.
  2. while( (read(fd[0], readbuff, sizeof(readbuff))))

Basically you need to ditch the read(fd[0],...).

phemmer
  • 4,436
  • 1
  • 27
  • 27
  • I see that the read is never called, In fact, I have commented out that part now. – dexterous Apr 27 '16 at 03:17
  • Oh, you're also returning from the program without waiting for your forked process to exit, so you've got your parent shell trying to read from STDIN and your forked `ssh`. – phemmer Apr 27 '16 at 03:26
  • have reworded the problem now. It seems that it has do with STDIN only. – dexterous Apr 27 '16 at 04:29
  • You should ask a new question, as the new behavior is now completely different from the original issue. – phemmer Apr 28 '16 at 12:24
0

My initial thought is that perhaps it is buffering the output: stdout is buffered, so unless you print a newline, nothing will be printed until a certain number of characters build up. This is because I/O operations are expensive. You can find more detail on this here. The result is that there is a delay because your program is waiting to print.

My suggestion: in your main function, before calling your sshLogin function, try disabling buffering with this line of code:

setbuf(stdout, NULL);

You can also call fflush(stdout); periodically to do the same thing, but the above method is more efficient. Try it and see if that solves your problem.

SevenBits
  • 2,756
  • 1
  • 17
  • 31