Поймать CTRL-\ сигнал

У меня есть пользовательский проект оболочки, где я пытаюсь реализовать cat команда, но позволяет пользователю нажать CTRL-/ для отображения следующих х-строк. Я новичок в сигналах, так что я думаю, что у меня где-то неправильный синтаксис...

в основном...

    while (fgets(buf, sizeof(buf), file) != NULL){ //CITE
        //print out first four lines
        if (j == 0){
          for (i = 0; i < 4; i++){
            printf("%s", buf);
            fgets(buf, sizeof(buf), file);
          }
          j++;
        }
        signal(SIGQUIT, sig_int);
        //now check for user input for the next x lines
        if (keepRunning){
          for (i = 0; i < 4; i++){
            printf("%s", buf);
            if (i < 3){
              if (fgets(buf, sizeof(buf), file) == NULL){
                fclose(file);
                return 0;
              }
            }
          }
          keepRunning = 0;
        }

Тогда я определил следующую функцию sig_int...

static volatile int keepRunning = 0;
void sig_int(int sig){
  keepRunning = 1;
}

1 ответ

Решение

Основная проблема в том, что вы не замедляетесь и не останавливаетесь, когда сигнал не принимается. Вы могли бы использовать pause(), например; возвращается только при получении сигнала. Вы бы тогда использовали это вместо if (keepRunning) блок (включая условие).

В качестве альтернативы вы можете изменить режимы терминала, чтобы символы отправлялись по мере их ввода (режим "raw"), и пытаться прочитать символ перед продолжением. Однако, если вы это сделаете, на вас лежит обязанность гарантировать, что режим терминала будет сброшен до того, как программа закроется при максимально возможном количестве обстоятельств. Хорошая новость заключается в том, что в исходном режиме с клавиатуры не будет генерироваться никаких сигналов, но вам нужно беспокоиться о сигналах из других источников.

Возможно, вы захотите позволить другим сигналам разбудить программу и выйти из цикла, но если вы не установите для них обработчик сигналов, это произойдет автоматически. То есть после pause() возвращается (он всегда будет возвращаться со статусом ошибки и errno установить EINTR), вы можете проверить, keepRunning сейчас 1 и выйдите из цикла, если нет.

Другие вопросы по тегам