Обзор
Я пишу код для отображения меню и экранов, используя библиотеку ncurses ++.Желаемый результат - вывод этих меню и экранов через интерфейс последовательного терминала.
Текущие попытки
Я могу успешно сделать это, используя базовую библиотеку C ncurses, используя вызовы.
if( (FDTERM = fopen("/dev/ttyS0", "r+")) != NULL )
{
if(FDTERM == NULL)
{
fprintf(stderr, "Error opening device: %s.\n", ncurses_device);
}
/* Set Screen */
MY_SCREEN = newterm(NULL, FDTERM, FDTERM);
if(MY_SCREEN != NULL)
{
/* Set the terminal */
set_term(MY_SCREEN);
}
}
и для того, чтобы заставить это работать на c ++, я написал некоторый код intercept.c, чтобы переопределить то, что фактически вызывает вызов :: initscr () в cursesw.cc к
#define ncurses_device "/dev/ttyS0"
NCURSES_EXPORT(WINDOW *) initscr(void)
{
WINDOW *result;
pthread_mutex_lock(&CUSTOM_LOCK);
if (!CUSTOM_INITIALIZED)
{
CUSTOM_INITIALIZED = true;
if( (FDTERM = fopen(ncurses_device, "r+")) != NULL )
{
if(FDTERM == NULL)
{
fprintf(stderr, "Error opening device: %s.\n", ncurses_device);
}
/* Set Screen */
MY_SCREEN = newterm(NULL, FDTERM, FDTERM);
if(MY_SCREEN != NULL)
{
/* Set the terminal */
set_term(MY_CDU_SCREEN);
}
/* def_shell_mode - done in newterm/_nc_setupscreen */
def_prog_mode();
}
else
{
CUSTOM_INITIALIZED = true;
NCURSES_CONST char *name;
if ((name = getenv("TERM")) == 0 || *name == '\0')
{
static char unknown_name[] = "unknown";
name = unknown_name;
}
if (newterm(name, stdout, stdin) == 0)
{
fprintf(stderr, "Error opening terminal: %s.\n", name);
result = NULL;
}
}
}
#if NCURSES_SP_FUNCS
#ifdef CURRENT_SCREEN
NCURSES_SP_NAME(def_prog_mode) (CURRENT_SCREEN);
#else
NCURSES_SP_NAME(def_prog_mode) (SP);
#endif
#else
def_prog_mode();
#endif
result = stdscr;
pthread_mutex_unlock(&CUSTOM_LOCK);
return Win(result);
}
intercept.cпозволяет использовать устройство согласно определению, если оно доступно.Это также позволяет initscr () вернуться к поведению по умолчанию при использовании текущего терминала.
Это работает, когда используется для отладки, но я чувствую, что должен быть лучший способ настроить NCurses или среду дляпрямой вывод NCurses через требуемый последовательный порт.
Приведенное выше решение теперь не работает при выполнении кода при загрузке, поскольку отсутствует определение терминала.
Это разрабатывается для поддержки обоих RHEL7 и 6. Некоторые исследования указывают на создание новой службы среды с использованием getty, agetty или путем редактирования start-tty.conf, как отмечалось (https://unix.stackexchange.com/a/318647).
Но другая проблема - указывать NCurses ++ навывод в правильную среду. Из того, что я видел в исходном коде NCurses, видно, что :: initscr () вызывается по умолчанию из cursesw.cc, что затрудняет указание NCurses на новую среду.
Вопросы
Как настроить NCurses ++ для вывода на указанный tty?
Как правильно настроитьКакова среда для использования NCurses при загрузке системы?
Обновление 1:
Обновлен код для выполнения следующих действий:
// Save the current stdin/stdout file descriptors
int saved_stdin = dup(fileno(stdin));
int saved_stdout = dup(fileno(stdout));
// Set the stdin/stdout to the desired device
freopen(ncurses_device, "w+", stdout);
freopen(ncurses_device, "r+", stdin);
// Initialize the NCursesMenu
NCursesMenu *m_pMenu = new NCursesMenu(m_pMenuItems);
// Restore the saved_stdin/stdout to the correct locations
dup2(saved_stdin, STDIN_FILENO);
dup2(saved_stdout, STDOUT_FILENO);
// Close the saved_stdin/stdout file descriptors
close(saved_stdin);
close(saved_stdout);
Это позволяет NCurses копировать текущий файл* как определено здесь в newterm , но как только STDIN / STDOUT FILE * восстанавливается в дескрипторе сохраненного файла, манипуляция теряется.Если устройство указывает только на новое устройство, оно работает для NCurses, но вся информация отладки / теста не видна, поскольку она перезаписывается NCurses в текущем терминале.