Can I make ungetc unlock a blocking call to fgetc?

I would like to write the character 'A' in stdin using ungetc when getting SIGUSR1. Imagine that I have a good reason for this.

When foo () is called, the read lock in stdin is not interrupted by the ungetc call when a signal is received. Although I did not expect this to work as it is, I wonder if there is a way to achieve this - does anyone have any suggestions?

void handler (int sig)
{
  ungetc ('A', stdin);
}

void foo ()
{
  signal (SIGUSR1, handler);

  while ((key = fgetc (stdin))! = EOF)
  {
    ...
  }
}
+3
source share
4 answers

, ungetc(), fgetc() , , fgetc() stdin select().


. , ( Enter).

, , () , tcsetattr() termios. fgetc(), , ungetc().


void handler(int sig) {
   /* I know I shouldn't do this in a signal handler,
    * but this is modeled after the OP code.
    */
   ungetc('A', stdin);
}

void wait_for_stdin() {
   fd_set fdset;
   FD_ZERO(&fdset);
   FD_SET(fileno(stdin),&fdset);
   select(1, &fdset, NULL, NULL, NULL);
}

void foo () {
   int key;
   struct termios terminal_settings;

   signal(SIGUSR1, handler);

   /* set the terminal to raw mode */
   tcgetattr(fileno(stdin), &terminal_settings);
   terminal_settings.c_lflag &= ~(ECHO|ICANON);
   terminal_settings.c_cc[VTIME] = 0;
   terminal_settings.c_cc[VMIN] = 0;
   tcsetattr(fileno(stdin), TCSANOW, &terminal_settings);

   for (;;) {
      wait_for_stdin();
      key = fgetc(stdin);
      /* terminate loop on Ctrl-D */
      if (key == 0x04) {
         break;
      }      
      if (key != EOF) {
         printf("%c\n", key);
      }
   }
}

. .

ECHO ICANON - . VTIME VMIN c_cc (fgetc()) , ; stdin. , key EOF, . stdin , stdin, select().


, SIGUSR1 t e s t 1:

A
t
e
s
t

1), Linux

+5

, , , ?

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

int handle = 0;

void handler (int sig) {
  handle = 1;
}

void foo () {
  int key;

  signal (SIGUSR1, handler);

  while ((key = fgetc (stdin)) != EOF) {
    printf("%c\n",key);
    if (handle) {
      handle = 0;
      ungetc('A',stdin);
    }
  }
}

int main(void) {
  printf("PID: %d\n",getpid());
  foo();
}

:

PID: 8902
test (typed on stdin)
t
A
e
s
t
+1

FILE * s .

FILE * , - FILE *. , , :

http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html. ( Windows, FILE * .

+1

, @Jamie, , A t, , .

int insert_an_A = 0;
void handler(int sig) { insert_an_A = 1; }

void process_char(char c) { ... }

int main(int argc, char **argv) {
    int c;
    /* skip signal setup */
    while ((c = fgetc(stdin)) != EOF) {
        if (insert_an_A) {
            process_char('A');
            insert_an_A = 0;
        }
        process_char(c);
    }
}

, fgetc, EOF, insert_an_A while.

Also note that in general, the best practice for signal handlers is to set a global variable and return from the handler. Elsewhere in your program, find a variable that changes and reacts accordingly.

+1
source

Source: https://habr.com/ru/post/1740731/


All Articles