繁体   English   中英

如何在从 Linux 启动时将 NCurses 输出定向到串行终端?

[英]How to direct NCurses output to a serial terminal on boot from Linux?

概述

我一直在编写代码来使用 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++ 中工作,我写了一些拦截.c 代码来覆盖在 cursesw.cc 中对 ::initscr() 的调用实际调用的内容

#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 输出定向到所需的串行端口。

由于没有可用的终端定义,因此在启动时执行代码时,上述解决方案现在不起作用。

正在开发它以支持 RHEL 7 和 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把复制当前FILE *定义这里newterm,但一旦标准输入/输出文件*恢复到保存的文件描述符的操作都将丢失。 如果设备仅指向新设备,则它适用于 NCurses,但所有调试/测试信息不可见,因为它被当前终端中的 NCurses 覆盖。

initscr不对设备做任何假设:它在初始化时使用当前的输入/输出标准输入标准输出(并且通过newtermsetupterm ,它复制文件描述符)。

如果您的应用程序(或环境/脚本)将这些流设置为您想要连接的设备,那么对于 C++ 接口来说应该足够了。 ncurses 不使用 C+ cout等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM