0

I'm trying to write an example program in C which reads user input character by character, without the user having to press enter. I have used the code seen here, and it works just fine, with a slight issue. I want to process all of the user's input when they press enter, and when I use system(/bin/stty raw);, the program can no longer detect it. As in:

int n, i;
char buffer[50];
system ("/bin/stty raw");
for(i=0; i<30 ; i++) {

    buffer[i] = getchar();
    printf("%d\n", buffer[i] == '\n');   //this prints 0 when I press enter
    if(buffer[i] == '\n'){
        break;
    }
}
printf("%s\n",buffer);

system ("/bin/stty cooked");

Is there a way to detect the user pressing enter when doing this?

What I'm actually trying to do is read the user's input before they press enter, but do something when they do. Another way I thought of doing this is, if I were to not read it character by character, but rather using, for example fgets(buffer, 255, stdin);, is there a way to read stdin 's buffer before the user pressing enter? I want to use the Enter key for this, so terminating the user input on another character, like with while((c=getchar())!= '.'){}, used here is not an option.

Community
  • 1
  • 1
Luke Sykpe
  • 311
  • 1
  • 11
  • With `raw`, do you have `icrnl` and/or `inlcr` turned on? These relate to CR to NL (`\r` to `\n`) mapping on input. Try: `system("/bin/stty -a");` in your code — maybe even twice, once before turning `raw` on and once after doing so. Or, in other words, there's a decent chance that you need to trap `\r` instead of, or as well as, `\n` when working in raw mode. – Jonathan Leffler Feb 09 '17 at 00:32
  • This is all the code. Really, all I left out is `int main()` and `return 0;` – Luke Sykpe Feb 09 '17 at 00:37
  • If you're addressing me, Luke, then I'm not saying you should have created more of an MCVE. I'm telling you that the `stty raw` command is changing lots of settings in your terminal, and that some of those are related to the conversion of CR (`\r`) to NL (`\n`) and vice versa. I'm also suggesting that you can experiment to find the settings before and after you do `stty raw` — which will help you determine what's changed. Also, as is pointed out in the answer, you should look into using the POSIX `` header and related functions to manage the terminal settings more directly. – Jonathan Leffler Feb 09 '17 at 00:41
  • You may find it useful to capture the output of `stty -g` before your program tampers with the terminal controls (use `popen()`) and you can then use that string to reset the terminal to the exact state it was in when `stty -g` was run. – Jonathan Leffler Feb 09 '17 at 00:42
  • Also note that there's a reason `getchar` returns `int` rather than `char`, and the implicit narrowing conversion from `int` to `char` you're causing here discards information... Work out what that information is, as it might be useful to you to solve a bug you've not yet noticed. – autistic Feb 09 '17 at 01:00

1 Answers1

3

The terminal settings you disable with stty raw are also responsible for harmonizing \r and \n.

You can use stty -icanon min 1 to only disable buffering, or alternatively accept both \r and \n as enter.

PS: It's considered good practice to use the TCGETS/TCSETS ioctls to get, modify and reapply the previous settings rather than invoking stty and forcing cooked mode afterwards.

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • Sorry, but I didn't quite understand. You mean I should check for \r instead of \n? If so, that's fine. Edit: Never mind, I tried it, and it works with `buffer[i] == '\r'` – Luke Sykpe Feb 09 '17 at 00:39