--- nono/host/comdriver_stdio.cpp 2026/04/29 17:05:11 1.1.1.1 +++ nono/host/comdriver_stdio.cpp 2026/04/29 17:05:47 1.1.1.3 @@ -10,29 +10,40 @@ #include "comdriver_stdio.h" #include "hostcom.h" -#include // コンストラクタ COMDriverStdio::COMDriverStdio(HostDevice *hostdev_) - : inherited(hostdev_, "Stdio") + : inherited(hostdev_, "stdio") { - // 現在の端末属性を取得 - tcgetattr(STDIN_FILENO, &oldtc); } // デストラクタ COMDriverStdio::~COMDriverStdio() { + hostdev->DelOuter(STDIN_FILENO); + // 端末属性を元に戻す - tcsetattr(STDIN_FILENO, TCSANOW, &oldtc); + if (tc_changed) { + tcsetattr(STDIN_FILENO, TCSANOW, &oldtc); + } + + stdio_occupied = false; } // ドライバ初期化 bool -COMDriverStdio::InitDriver() +COMDriverStdio::InitDriver(bool startup) { struct termios tc; - int fds[2]; + + if (stdio_occupied) { + errmsg = "'stdio' is already in use by another hostcom-driver"; + putmsg(1, "%s", errmsg.c_str()); + return false; + } + + // 現在の端末属性を取得 + tcgetattr(STDIN_FILENO, &oldtc); // 端末の設定を変更 tc = oldtc; @@ -43,74 +54,27 @@ COMDriverStdio::InitDriver() tc.c_lflag &= ~ECHO; // エコーオフ tc.c_lflag &= ~ICANON; // 非カノニカルモード tc.c_lflag &= ~IEXTEN; // DISCARD(^O)と LNEXT をオフ? + tc.c_lflag &= ~ISIG; // シグナルを生成しない tc.c_cc[VTIME] = 0; tc.c_cc[VMIN] = 1; if (tcsetattr(STDIN_FILENO, TCSANOW, &tc) < 0) { - putmsg(0, "tcsetattr: %s", strerror(errno)); + errmsg = string_format("tcsetattr: %s", strerror(errno)); + putmsg(1, "%s", errmsg.c_str()); return false; } - - // シグナルを受け取る - if (pipe(fds) < 0) { - putmsg(0, "pipe: %s", strerror(errno)); - return false; - } - if (hostdev->AddSignal(fds[0], fds[1]) < 0) { - putmsg(0, "AddSignal: %s", strerror(errno)); - close(fds[0]); - close(fds[1]); - return false; - } - sigfd = fds[0]; + tc_changed = true; if (hostdev->AddOuter(STDIN_FILENO) < 0) { - putmsg(0, "AddOuter: %s", strerror(errno)); - sigfd.Close(); - close(fds[1]); + errmsg = string_format("AddOuter: %s", strerror(errno)); + putmsg(1, "%s", errmsg.c_str()); return false; } - char_from_signal = 0; - + stdio_occupied = true; return true; } -// Driver の Dispatch() は udata を返す。 -int -COMDriverStdio::Dispatch(int udata) -{ - if (udata == HostDevice::DATA_FROM_SIGNAL) { - char buf[1]; - if (read(sigfd, buf, sizeof(buf)) < 0) { - putmsg(0, "read(sigfd=%d): %s", (int)sigfd, strerror(errno)); - return HostDevice::DONE; - } - int signo = buf[0]; - switch (signo) { - case SIGINT: - // ^C が入力されたのでシリアルに '\x03' を送り込む - char_from_signal = 0x03; - break; - case SIGTSTP: - // ^Z が入力されたのでシリアルに '\x1a' を送り込む - char_from_signal = 0x1a; - break; - case SIGQUIT: - // ^\ が入力されたのでシリアルに '\x1e' を送り込む - char_from_signal = 0x1e; - break; - default: - return HostDevice::DONE; - } - - // シグナルで来た文字を Read で読める文字が外から来たことにする - return HostDevice::DATA_FROM_OUTER; - } - - return udata; -} - // 外部への1バイト書き出し void COMDriverStdio::Write(uint32 data) @@ -137,13 +101,6 @@ COMDriverStdio::Read() uint8 buf[1]; int r; - // シグナルで来た文字があればそちらを返す - if (char_from_signal) { - r = char_from_signal; - char_from_signal = 0; - return r; - } - r = read(STDIN_FILENO, buf, sizeof(buf)); if (r < 0) { putmsg(0, "read: %s", strerror(errno)); @@ -154,3 +111,6 @@ COMDriverStdio::Read() } return buf[0]; } + +// stdio を使えるのは同時に1人だけに限定する。 +/*static*/ bool COMDriverStdio::stdio_occupied = false;