1

I have a file called get_int.c on a remote Unix system, containing the following:

#include <stdio.h>

int main() {
    int input;

    printf("Give an integer: ");
    fflush(stdout);
    scanf("%d", &input);

    printf("Try again: ");
    scanf("%d", &input);

    printf("You said... %d\n", input);

    return 0;
}

I have a command to compile and run this file from my local WSL:

sshpass -f pass.txt ssh username@remote.host.address "cd path/to/file/ && gcc get_int.c && a.out"

When I execute this command, I successfully get the prompt Give an integer: and provide one and press enter. Then, however, I do not get the prompt Try again:. I can still type an integer (123) and press enter. When I do, it then prints Try again: You said... 123

As you can see, no printing occurs until I either fflush(stdout) or the program ends. Can I possibly modify my ssh command so that output goes to the local terminal without having to fflush before every scanf?

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
jhud
  • 49
  • 2
  • 9
  • 2
    It wouldn't hurt to add a [second] `fflush` after the "Try again:" `printf` as you did for the first `printf` You could wrap this `printf`/`fflush` sequence in a macro, or you could set unbuffered using `setbuf`. Or, you could write a wrapper function for `printf` using `...` and `va_start` and `va_end` and `vprintf` – Craig Estey Feb 13 '20 at 06:46
  • The title is a bit misleading -- `scanf` actually does not prevent anything... – Peter - Reinstate Monica Feb 13 '20 at 07:51
  • @Peter-ReinstateMonica My bad, I agree; just not sure how to phrase the title. – jhud Feb 13 '20 at 17:42
  • @CraigEstey It wouldn't hurt I suppose, although it is annoying to have to do flush every time I scan. I'm wondering/asking if there is some way to change my SSH command so output appears correctly without having to flush all the time. – jhud Feb 13 '20 at 17:43
  • @jhud No prob, I took the liberty of changing it, I hope to the better. If you don't like it simply revert, no harm done. – Peter - Reinstate Monica Feb 13 '20 at 17:53
  • Looks good, thanks! – jhud Feb 13 '20 at 18:01

1 Answers1

2

Output to stdout does not seem to be flushed when reading from stdin on your system in the specific circumstances described. You must flush stdout explicitly with fflush() before every call to scanf():

#include <stdio.h>

int main() {
    int input;

    printf("Give an integer: ");
    fflush(stdout);
    scanf("%d", &input);

    printf("Try again: ");
    fflush(stdout);
    scanf("%d", &input);

    printf("You said... %d\n", input);

    return 0;
}

Alternately, you can set the output stream as unbuffered and won't need to flush it at all:

#include <stdio.h>

int main() {
    int input;

    setvbuf(stdout, NULL, _IONBF, 0);

    printf("Give an integer: ");
    scanf("%d", &input);

    printf("Try again: ");
    scanf("%d", &input);

    printf("You said... %d\n", input);

    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Easiest would be to simply set it to unbuffered, I suppose. In this interactive application performance is irrelevant. (Of course, if this is just a proof of concept for non-interactive communication buffering may be essential again.) – Peter - Reinstate Monica Feb 13 '20 at 07:53
  • Right, I recognize that for my current setup I have to `fflush` before every `scanf`. This is very tedious, however. My question is: Is there some way to change my SSH command so that I don't ever have to flush stdout? – jhud Feb 13 '20 at 17:40
  • @jhud: is manual flushing is tedious due to numerous instances of output, just set the stream as unbuffered as shown in the amended answer. The flushing issue is probably independent from the `ssh` configuration. – chqrlie Feb 13 '20 at 18:50
  • 1
    @chqrlie Love the second solution! If SSH is indeed not the problem, this seems like the best option since it's just one line at the top of main. – jhud Feb 13 '20 at 19:10