|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 [email protected] ! 4: // ! 5: ! 6: #include "console.h" ! 7: #include "mystring.h" ! 8: #include <poll.h> ! 9: ! 10: // ! 11: // コンソール基本クラス ! 12: // ! 13: ! 14: // コンストラクタ ! 15: Console::Console() ! 16: { ! 17: inp.fd = -1; ! 18: inp.file = NULL; ! 19: out.fd = -1; ! 20: out.file = NULL; ! 21: } ! 22: ! 23: #if defined(HAVE_HISTEDIT_H) ! 24: // プロンプト文字列を返す (editline からコールバックで呼ばれる) ! 25: static char * ! 26: prompt_callback(EditLine *e) ! 27: { ! 28: void *p; ! 29: ! 30: // CLIENTDATA に (char *)prompt が入っている ! 31: el_get(e, EL_CLIENTDATA, &p); ! 32: return (char *)p; ! 33: } ! 34: #endif ! 35: ! 36: // EditLine を初期化する。p はプロンプト文字列。 ! 37: void ! 38: Console::InitEditLine(const char *prompt_arg) ! 39: { ! 40: // editline(3) を使わない場合は、プロンプトを自前で出すために覚えておく。 ! 41: // 使う場合には代入が無駄になるけど気にしない。 ! 42: prompt = prompt_arg; ! 43: ! 44: #if defined(HAVE_HISTEDIT_H) ! 45: if (use_editline) { ! 46: // ヒストリの初期化 ! 47: hist = history_init(); ! 48: history(hist, &hev, H_SETSIZE, 100); ! 49: ! 50: // editline の初期化、設定 ! 51: el = el_init(getprogname(), inp.file, out.file, stderr); ! 52: if (el == NULL) { ! 53: // どうすべ ! 54: warnx("el_init failed"); ! 55: return; ! 56: } ! 57: // CLIENTDATA にプロンプトを入れておく ! 58: el_set(el, EL_CLIENTDATA, prompt_arg); ! 59: el_set(el, EL_PROMPT, prompt_callback); ! 60: el_set(el, EL_EDITOR, "emacs"); ! 61: el_set(el, EL_HIST, history, hist); ! 62: } ! 63: #endif ! 64: } ! 65: ! 66: // クローズ ! 67: void ! 68: Console::Close() ! 69: { ! 70: #if defined(HAVE_HISTEDIT_H) ! 71: if (use_editline) { ! 72: el_end(el); ! 73: } ! 74: #endif ! 75: ! 76: // fclose は fd も閉じる。 ! 77: if (inp.file != NULL) { ! 78: fclose(inp.file); ! 79: inp.file = NULL; ! 80: inp.fd = -1; ! 81: } ! 82: if (out.file != NULL) { ! 83: fclose(out.file); ! 84: out.file = NULL; ! 85: out.fd = -1; ! 86: } ! 87: } ! 88: ! 89: // プロンプトを出力する ! 90: void ! 91: Console::Prompt() ! 92: { ! 93: #if defined(HAVE_HISTEDIT_H) ! 94: if (use_editline) { ! 95: // editline(3) を使う場合は Gets() がプロンプトを出すので ! 96: // ここでは何もしない。 ! 97: } else ! 98: #endif ! 99: { ! 100: // そうでない場合は、ここで自前でプロンプトを出す。 ! 101: Print("%s", prompt); ! 102: Flush(); ! 103: } ! 104: } ! 105: ! 106: // 出力 ! 107: void ! 108: Console::Print(const char *fmt, ...) ! 109: { ! 110: va_list ap; ! 111: ! 112: va_start(ap, fmt); ! 113: vfprintf(out.file, fmt, ap); ! 114: va_end(ap); ! 115: } ! 116: ! 117: // 出力フラッシュ ! 118: void ! 119: Console::Flush() ! 120: { ! 121: fflush(out.file); ! 122: } ! 123: ! 124: // 1行出力 ! 125: bool ! 126: Console::Gets(std::string& buf) ! 127: { ! 128: #if defined(HAVE_HISTEDIT_H) ! 129: if (use_editline) ! 130: return Gets_editline(buf); ! 131: else ! 132: #endif ! 133: return Gets_normal(buf); ! 134: } ! 135: ! 136: #if defined(HAVE_HISTEDIT_H) ! 137: // 1行出力 (Editline 版) ! 138: bool ! 139: Console::Gets_editline(std::string& buf) ! 140: { ! 141: const char *p; ! 142: int num; ! 143: ! 144: p = el_gets(el, &num); ! 145: if (p == NULL || num < 1) { ! 146: // EOF ! 147: return false; ! 148: } ! 149: // 呼び出し元へは EditLine から入力されたものをそのまま返す ! 150: buf = std::string(p); ! 151: ! 152: // ヒストリに記録 ! 153: // の前に前後の空白は取り除いておく ! 154: std::string hbuf = string_ltrim(buf); ! 155: string_rtrim(hbuf); ! 156: ! 157: // 空文字列でなければ、ヒストリに記録 ! 158: if (!hbuf.empty()) { ! 159: history(hist, &hev, H_ENTER, hbuf.c_str()); ! 160: } ! 161: ! 162: return true; ! 163: } ! 164: #endif ! 165: ! 166: // 1行出力 (通常版) ! 167: bool ! 168: Console::Gets_normal(std::string& buf) ! 169: { ! 170: char cbuf[1024]; ! 171: ! 172: if (fgets(cbuf, sizeof(cbuf), inp.file) == NULL) { ! 173: return false; ! 174: } ! 175: buf = std::string(cbuf); ! 176: return true; ! 177: } ! 178: ! 179: // 入力チェック ! 180: int ! 181: Console::Poll() ! 182: { ! 183: struct pollfd pfd; ! 184: ! 185: if (inp.fd == -1) { ! 186: errno = EBADF; ! 187: return -1; ! 188: } ! 189: ! 190: pfd.fd = inp.fd; ! 191: pfd.events = POLLIN; ! 192: pfd.revents = 0; ! 193: int r = poll(&pfd, 1, 0); ! 194: return r; ! 195: } ! 196: ! 197: // ファイルディスクリプタから FILE* を開く ! 198: void ! 199: Console::FDOpen() ! 200: { ! 201: inp.file = fdopen(inp.fd, "r"); ! 202: out.file = fdopen(out.fd, "w"); ! 203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.