Как вернуть управление обратно на терминал в C с помощью termios

Я создаю оболочку, которая будет имитировать поведение оболочки в Linux, например выполнение таких команд, как ls, mkdir, find и т. д. Теперь я использовал termios для прослушивания нажатие клавиши со стрелкой и нажатие клавиши Enter, если пользователь нажимает клавишу со стрелкой вверх, то показывает пользователю ранее выполненную команду. Но после выполнения моей программы оболочки после ввода первой команды, например: ls, будет отображаться вывод команды, но после этого я не могу выполнить другую команду, набрав в терминале и нажав Enter, просто напечатайте текст обратно в новую строку и не выполняет его.

Мой код:

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <term.h>
#include <curses.h>
#include <unistd.h>

static struct termios initial_settings, new_settings;
static int peek_character = -1;
void init_keyboard();
void close_keyboard();
int kbhit();
int readch();


int main() {

    int ch;
    char str[1000][200];
    init_keyboard();
    int i = 0;
    int j = 0;

    while(ch != 'q') {

    if(kbhit()) {

        ch = readch();

        if (ch == 10) {
            system(str[i]);
            i++;
        } else {
            str[i][j] = ch;

            j++;
        }

    }

}
    close_keyboard();
    exit(0);
}

void init_keyboard() {
    tcgetattr(0, &initial_settings);
    new_settings = initial_settings;
    // new_settings.c_iflag &= ~BRKINT;
    // new_settings.c_iflag &= ICRNL;
    new_settings.c_lflag &= ~ICANON;
    new_settings.c_lflag &= ECHO;
    new_settings.c_lflag &= ~ISIG;
    new_settings.c_cc[VMIN] = 1;
    new_settings.c_cc[VMIN] = 0;
    tcsetattr(0, TCSANOW, &new_settings);

}

void close_keyboard() {

    tcsetattr(0, TCSANOW, &initial_settings);

}

int kbhit() {
    char ch;
    int nread;

    if (peek_character != -1) {
        return 1;
    }

    new_settings.c_cc[VMIN] = 0;
    tcsetattr(0, TCSANOW, &new_settings);
    nread = read(0, &ch,1);
    new_settings.c_cc[VMIN]=1;
    tcsetattr(0, TCSANOW, &new_settings);

    if (nread == 1) {
        peek_character = ch;
        return 1;
    }
    return 0;
}


int readch() {
    char ch;

    if (peek_character != -1) {
        ch = peek_character;
        peek_character = -1;
        return ch;
    }

    read(0, &ch,1);
    return ch;
}


person Osama Xäwãñz    schedule 30.09.2019    source источник
comment
Почему у вас есть read(0, &ch,5); в readch(), когда ch имеет размер только для одного символа?   -  person infixed    schedule 30.09.2019
comment
плохо, должно быть 1, а не 5   -  person Osama Xäwãñz    schedule 30.09.2019
comment
Я не вижу кода для поиска клавиши со стрелкой (которая на самом деле может сильно различаться между различными терминальными протоколами). Как вы думаете, вы сделали это еще?   -  person infixed    schedule 30.09.2019
comment
Вы можете подумать о том, чтобы посмотреть библиотеку ncurses, которая предназначена для помощи в программах со стрелками и прокруткой.   -  person infixed    schedule 30.09.2019
comment
я еще не реализовал функциональность клавиши со стрелкой, но мне просто нужно знать, как я могу вернуть контроль над терминалом. мне не разрешено использовать ncurses   -  person Osama Xäwãñz    schedule 30.09.2019
comment
Что ж, ограниченная форма перерисовки строки состоит в том, чтобы отправить код возврата, чтобы привести вас к началу строки, за которым следует достаточно пробелов, чтобы стереть старое содержимое. Затем еще один возврат и следуйте за ним символами, которые вы хотите отобразить в строке (т.е. старая команда). Достаточно ли этого «контроля»?   -  person infixed    schedule 30.09.2019


Ответы (1)


вам нужно fork() для создания нового процесса, потому что system() выполняет вашу команду и выходит... попробуйте этот код:

int main() {

int ch;
char str[1000][200];
init_keyboard();
int i = 0;
int j = 0;
pid_t father;
father = 0;

while(ch != 'q') {

if(kbhit()) {

    ch = readch();

    father = fork();
    if (father == 0)
    {
        if (ch == 10) {
          system(str[i]);
          i++;
        } else {
        str[i][j] = ch;
        j++;
        }
    }

}

}
person bad-ass_1337    schedule 30.09.2019