Annotation of nono/host/comdriver_stdio.cpp, revision 1.1.1.1

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2021 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // シリアルポートの標準入出力ドライバ
                      9: //
                     10: 
                     11: #include "comdriver_stdio.h"
                     12: #include "hostcom.h"
                     13: #include <csignal>
                     14: 
                     15: // コンストラクタ
                     16: COMDriverStdio::COMDriverStdio(HostDevice *hostdev_)
                     17:        : inherited(hostdev_, "Stdio")
                     18: {
                     19:        // 現在の端末属性を取得
                     20:        tcgetattr(STDIN_FILENO, &oldtc);
                     21: }
                     22: 
                     23: // デストラクタ
                     24: COMDriverStdio::~COMDriverStdio()
                     25: {
                     26:        // 端末属性を元に戻す
                     27:        tcsetattr(STDIN_FILENO, TCSANOW, &oldtc);
                     28: }
                     29: 
                     30: // ドライバ初期化
                     31: bool
                     32: COMDriverStdio::InitDriver()
                     33: {
                     34:        struct termios tc;
                     35:        int fds[2];
                     36: 
                     37:        // 端末の設定を変更
                     38:        tc = oldtc;
                     39: 
                     40:        // 入力時の変換は無し
                     41:        tc.c_iflag = 0;
                     42: 
                     43:        tc.c_lflag &= ~ECHO;    // エコーオフ
                     44:        tc.c_lflag &= ~ICANON;  // 非カノニカルモード
                     45:        tc.c_lflag &= ~IEXTEN;  // DISCARD(^O)と LNEXT をオフ?
                     46:        tc.c_cc[VTIME] = 0;
                     47:        tc.c_cc[VMIN] = 1;
                     48: 
                     49:        if (tcsetattr(STDIN_FILENO, TCSANOW, &tc) < 0) {
                     50:                putmsg(0, "tcsetattr: %s", strerror(errno));
                     51:                return false;
                     52:        }
                     53: 
                     54:        // シグナルを受け取る
                     55:        if (pipe(fds) < 0) {
                     56:                putmsg(0, "pipe: %s", strerror(errno));
                     57:                return false;
                     58:        }
                     59:        if (hostdev->AddSignal(fds[0], fds[1]) < 0) {
                     60:                putmsg(0, "AddSignal: %s", strerror(errno));
                     61:                close(fds[0]);
                     62:                close(fds[1]);
                     63:                return false;
                     64:        }
                     65:        sigfd = fds[0];
                     66: 
                     67:        if (hostdev->AddOuter(STDIN_FILENO) < 0) {
                     68:                putmsg(0, "AddOuter: %s", strerror(errno));
                     69:                sigfd.Close();
                     70:                close(fds[1]);
                     71:                return false;
                     72:        }
                     73: 
                     74:        char_from_signal = 0;
                     75: 
                     76:        return true;
                     77: }
                     78: 
                     79: // Driver の Dispatch() は udata を返す。
                     80: int
                     81: COMDriverStdio::Dispatch(int udata)
                     82: {
                     83:        if (udata == HostDevice::DATA_FROM_SIGNAL) {
                     84:                char buf[1];
                     85:                if (read(sigfd, buf, sizeof(buf)) < 0) {
                     86:                        putmsg(0, "read(sigfd=%d): %s", (int)sigfd, strerror(errno));
                     87:                        return HostDevice::DONE;
                     88:                }
                     89:                int signo = buf[0];
                     90:                switch (signo) {
                     91:                 case SIGINT:
                     92:                        // ^C が入力されたのでシリアルに '\x03' を送り込む
                     93:                        char_from_signal = 0x03;
                     94:                        break;
                     95:                 case SIGTSTP:
                     96:                        // ^Z が入力されたのでシリアルに '\x1a' を送り込む
                     97:                        char_from_signal = 0x1a;
                     98:                        break;
                     99:                 case SIGQUIT:
                    100:                        // ^\ が入力されたのでシリアルに '\x1e' を送り込む
                    101:                        char_from_signal = 0x1e;
                    102:                        break;
                    103:                 default:
                    104:                        return HostDevice::DONE;
                    105:                }
                    106: 
                    107:                // シグナルで来た文字を Read で読める文字が外から来たことにする
                    108:                return HostDevice::DATA_FROM_OUTER;
                    109:        }
                    110: 
                    111:        return udata;
                    112: }
                    113: 
                    114: // 外部への1バイト書き出し
                    115: void
                    116: COMDriverStdio::Write(uint32 data)
                    117: {
                    118:        uint8 buf[1];
                    119:        int r;
                    120: 
                    121:        buf[0] = data;
                    122:        r = write(STDOUT_FILENO, buf, sizeof(buf));
                    123:        if (r < 0) {
                    124:                putmsg(0, "write: %s", strerror(errno));
                    125:                return;
                    126:        }
                    127:        if (r < sizeof(buf)) {
                    128:                putmsg(0, "write: short");
                    129:                return;
                    130:        }
                    131: }
                    132: 
                    133: // 外部からの1バイト読み込み
                    134: int
                    135: COMDriverStdio::Read()
                    136: {
                    137:        uint8 buf[1];
                    138:        int r;
                    139: 
                    140:        // シグナルで来た文字があればそちらを返す
                    141:        if (char_from_signal) {
                    142:                r = char_from_signal;
                    143:                char_from_signal = 0;
                    144:                return r;
                    145:        }
                    146: 
                    147:        r = read(STDIN_FILENO, buf, sizeof(buf));
                    148:        if (r < 0) {
                    149:                putmsg(0, "read: %s", strerror(errno));
                    150:                return NODATA;
                    151:        }
                    152:        if (r == 0) {
                    153:                return NODATA;
                    154:        }
                    155:        return buf[0];
                    156: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.