Как направить вывод NCurses на последовательный терминал при загрузке из Linux? - PullRequest
0 голосов
/ 04 октября 2018

Обзор

Я пишу код для отображения меню и экранов, используя библиотеку 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 в текущем терминале.

1 Ответ

0 голосов
/ 04 октября 2018

initscr не предполагает ничего об устройствах: он использует текущий вход / выход стандартный ввод и стандартный вывод при инициализации (и через newterm, setupterm, он копирует дескрипторы файлов).

Если ваше приложение (или среда / сценарии) устанавливает эти потоки для устройства, к которому вы хотите подключиться, этого должно быть достаточно для C ++интерфейс.ncurses не использует C + cout и т. д.

...