[apue] 一個查看當前終端標誌位設置的小工具

来源:https://www.cnblogs.com/goodcitizen/archive/2020/01/21/12222417.html
-Advertisement-
Play Games

話不多說,先看運行效果: >./term input flag 0x00000500 BRKINT not in ICRNL IGNBRK not in IGNCR not in IGNPAR not in IMAXBEL not in INLCR not in INPCK not in ISTRI ...


話不多說,先看運行效果:

>./term
input flag 0x00000500
    BRKINT not in
    ICRNL
    IGNBRK not in
    IGNCR not in
    IGNPAR not in
    IMAXBEL not in
    INLCR not in
    INPCK not in
    ISTRIP not in
    IUCLC not in
    IXANY not in
    IXOFF not in
    IXON
    PARMRK not in
output flag 0x00000005
    BSDLY not in
    CMSPAR not defined
    CRDLY not in
    FFDLY not in
    NLDLY not in
    OCRNL not in
    OFDEL not in
    OFILL not in
    OLCUC not in
    ONLCR
    ONLRET not in
    ONOCR not in
    ONOEOT not defined
    OPOST
    OXTABS not defined
    TABDLY not in
    VTDLY not in
control flag 0x000000bf
    CBAUDEXT not defined
    CCAR_OFLOW not defined
    CCTS_OFLOW not defined
    CDSR_OFLOW not defined
    CDTR_IFLOW not defined
    CIBAUDEXT not defined
    CIGNORE not defined
    CLOCAL not in
    CREAD
    CRTSCTS not defined
    CRTS_IFLOW not defined
    CRTSXOFF not defined
    CSIZE
    CSTOPB not in
    HUPCL not in
    MDMBUF not defined
    PARENB not in
    PAREXT not defined
    PARODD not in
local flag 0x00008a3b
    ALTWERASE not defined
    ECHO
    ECHOCTL not defined
    ECHOE
    ECHOK
    ECHOKE not defined
    ECHONL not in
    ECHOPRT not defined
    EXTPROC not defined
    FLUSHO not defined
    ICANON
    IEXTEN
    ISIG
    NOFLSH not in
    NOKERNINFO not defined
    PENDIN not defined
    TOSTOP not in
    XCASE not in
input control char array size 32
    cc[VDISCARD=13] = 15 ()
    VDSUSP not defined
    cc[VEOF=4] = 4 ()
    cc[VEOL=11] = 0 ()
    cc[VEOL2=16] = 0 ()
    cc[VERASE=2] = 127 ()
    VERASE2 not defined
    cc[VINTR=0] = 3 ()
    cc[VKILL=3] = 21 ()
    cc[VLNEXT=15] = 22 ()
    cc[VQUIT=1] = 28 ()
    cc[VREPRINT=12] = 18 ()
    cc[VSTART=8] = 17 ()
    VSTATUS not defined
    cc[VSTOP=9] = 19 ()
    cc[VSUSP=10] = 26 ()
    cc[VWERASE=14] = 23 ()

 

眾所周知,通過 tcgetattr 介面與 termios 結構體,我們可以獲取一個終端設備的設置信息:

struct termios
{
    tcflag_t c_iflag;       /* input mode flags */
    tcflag_t c_oflag;       /* output mode flags */
    tcflag_t c_cflag;       /* control mode flags */
    tcflag_t c_lflag;       /* local mode flags */
    cc_t c_cc[NCCS];        /* control characters */
};

 

主要是各種類型的標誌位,雖然你可以將它們列印出來,但是一眼望去,這些數字是什麼意思,還要查對應平臺的 man 手冊。

這個工具可以將二進位的標誌位,翻譯為人類可以讀懂的常量巨集,例如上面的輸出中,可以看到輸入標誌位打開了 ICRNL 與 IXON 兩個標誌位,

對應的含義分別是“將輸入的CR轉換為NL”、“使啟動/停止輸出控制流起作用”。

 

看這段輸出也許你已經想到了代碼的實現,就是挨個常量巨集嘗試唄,這有啥難的。

不錯,但是考慮到不同平臺上定義的巨集不一致,有時增加一兩個巨集可能還需要修改源代碼,這是多麼痛苦的事啊!

這個小工具就解決了這個痛點,你可以在配置文件中指定要測試的巨集名稱,然後 make 一下就可以啦~~~

 

iflag.sym

BRKINT
ICRNL
IGNBRK
IGNCR
IGNPAR
IMAXBEL
INLCR
INPCK
ISTRIP
IUCLC
IXANY
IXOFF
IXON
PARMRK

 

oflag.sym

BSDLY
CMSPAR
CRDLY
FFDLY
NLDLY
OCRNL
OFDEL
OFILL
OLCUC
ONLCR
ONLRET
ONOCR
ONOEOT
OPOST
OXTABS
TABDLY
VTDLY

 

cflag.sym

CBAUDEXT
CCAR_OFLOW
CCTS_OFLOW
CDSR_OFLOW
CDTR_IFLOW
CIBAUDEXT
CIGNORE
CLOCAL
CREAD
CRTSCTS
CRTS_IFLOW
CRTSXOFF
CSIZE
CSTOPB
HUPCL
MDMBUF
PARENB
PAREXT
PARODD

 

lflag.sym

ALTWERASE
ECHO
ECHOCTL
ECHOE
ECHOK
ECHOKE
ECHONL
ECHOPRT
EXTPROC
FLUSHO
ICANON
IEXTEN
ISIG
NOFLSH
NOKERNINFO
PENDIN
TOSTOP
XCASE

 

其實這裡是用 awk 讀取配置文件自動生成 c 語言的代碼來實現的:

print_flag.awk

 1 #! /bin/awk -f
 2 # usage: print_flag.awk -v FUNC_NAME=xxx -v MACRO_FILE=xxx
 3 # i.e.: print_flag.awk -v FUNC_NAME=output -v MACRO_FILE=oflag.sym
 4 BEGIN {
 5 printf("#include \"../apue.h\"\n")
 6 printf("#include <termios.h>\n")
 7 printf("\n")
 8 printf("void print_%s_flag (tcflag_t flag)\n", FUNC_NAME)
 9 printf("{\n")
10 printf("    printf (\"%s flag 0x%%08x\\n\", flag); \n", FUNC_NAME)
11 FS=":"
12 while (getline < MACRO_FILE > 0) {
13 printf("#ifdef %s\n", $1)
14 printf("    if (flag & %s)\n", $1)
15 printf("        printf (\"    %s\\n\"); \n", $1)
16 printf("    else\n")
17 printf("        printf (\"    %s not in\\n\"); \n", $1)
18 printf("#else\n")
19 printf("    printf (\"    %s not defined\\n\"); \n", $1)
20 printf("#endif\n")
21 }
22 close (MACRO_FILE)
23 exit
24 }
25 END {
26 printf("}")
27 }

 

生成的 c 文件類似這樣:

 1 #include "../apue.h"
 2 #include <termios.h>
 3 
 4 void print_input_flag (tcflag_t flag)
 5 {
 6     printf ("input flag 0x%08x\n", flag); 
 7 #ifdef BRKINT
 8     if (flag & BRKINT)
 9         printf ("    BRKINT\n"); 
10     else
11         printf ("    BRKINT not in\n"); 
12 #else
13     printf ("    BRKINT not defined\n"); 
14 #endif
15 #ifdef ICRNL
16     if (flag & ICRNL)
17         printf ("    ICRNL\n"); 
18     else
19         printf ("    ICRNL not in\n"); 
20 #else
21     printf ("    ICRNL not defined\n"); 
22 #endif
23 }

 

再看下 Makefile 的生成規則就更清楚啦:

Makefile

 1 all: term 
 2 
 3 term: term.o print_iflag.o print_oflag.o print_cflag.o print_lflag.o print_cchar.o apue.o 
 4     gcc -Wall -g $^ -o $@
 5 
 6 term.o: term.c ../apue.h
 7     gcc -Wall -g -c $< -o $@
 8 
 9 print_iflag.o: print_iflag.c ../apue.h
10     gcc -Wall -g -c $< -o $@
11 
12 print_iflag.c: print_flag.awk iflag.sym
13     ./print_flag.awk -v FUNC_NAME=input -v MACRO_FILE=iflag.sym > print_iflag.c
14 
15 print_oflag.o: print_oflag.c ../apue.h
16     gcc -Wall -g -c $< -o $@
17 
18 print_oflag.c: print_flag.awk oflag.sym
19     ./print_flag.awk -v FUNC_NAME=output -v MACRO_FILE=oflag.sym > print_oflag.c
20 
21 print_cflag.o: print_cflag.c ../apue.h
22     gcc -Wall -g -c $< -o $@
23 
24 print_cflag.c: print_flag.awk cflag.sym
25     ./print_flag.awk -v FUNC_NAME=control -v MACRO_FILE=cflag.sym > print_cflag.c
26 
27 print_lflag.o: print_lflag.c ../apue.h
28     gcc -Wall -g -c $< -o $@
29 
30 print_lflag.c: print_flag.awk lflag.sym
31     ./print_flag.awk -v FUNC_NAME=local -v MACRO_FILE=lflag.sym > print_lflag.c
32 
33 print_cchar.o: print_cchar.c ../apue.h
34     gcc -Wall -g -c $< -o $@
35 
36 print_cchar.c: print_char.awk cchar.sym
37     ./print_char.awk -v FUNC_NAME=control -v MACRO_FILE=cchar.sym > print_cchar.c
38 
39 log.o: ../log.c ../log.h
40     gcc -Wall -g -c $< -o $@
41 
42 apue.o: ../apue.c ../apue.h 
43     gcc -Wall -g -c $< -o $@ -D__USE_BSD
44 
45 clean: 
46     @echo "start clean..."
47     -rm -f *.o core.* *.log *~ *.swp term 
48     @echo "end clean"
49 
50 .PHONY: clean

 

具體分析下生成過程:

1.通過 print_flag.awk 分別生成 print_iflag.c / print_oflag.c / print_cflag.c / print_lflag.c

2.分別將生成的 .c 編譯為 .o 文件

3.在生成 term 工具時鏈接上述 .o 文件生成最終的可執行文件

 

當然了,除了各種標誌位外,這裡還處理了 cc_t cc 欄位,它列印每個特殊輸入字元,原理和上面相仿,就不再贅述了。

檢查列印的特殊字元,發現少了下標為 5 / 6 / 7 的字元,查看頭文件定義,原來是 linux 上面增加了三個新的定義:

cchar.sym

VTIME
VMIN
VSWTC

 

將它們添加到 sym 文件中,重新編譯、運行,果然新的輸出里有了:

    cc[VTIME=5] = 0 ()
    cc[VMIN=6] = 1 ()
    cc[VSWTC=7] = 0 ()

 

這對於在不同平臺上進行測試有很大的幫助。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7723225.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講結構型設計模式的第三個模式--裝飾模式。當第一次看到這個名稱時想到的是另外一個詞語“裝修”,個人觀點談談對“裝修”的理解吧,請大家 ...
  • 在上一篇文章:《閃電光速拳? .NetCore 中的Span》中我們提到了在.net core 2.x 所新增的一個類型:Span。但是您會發現它無法用在我們項目的某些地方,它獨特的 ref結構 使它沒有辦法跨線程使用、更沒有辦法使用Lambda表達式。所以,這個時候如果我們又想跨線程操作數據又想獲... ...
  • 前言:想在.net framework環境使用自定義定時器的話,參考我的另一篇文章:https://www.cnblogs.com/lxhbky/p/10242839.html 想在.net core中使用定時器功能,需要藉助一個服務介面:IHostedService, 繼承並實現對應方法,最後再s ...
  • 要點 導出特性 如何導出Excel表頭 如何導出數據、如何進行數據的切割、如何使用篩選器 導出特性 ExporterAttribute + Name : 名稱(當前Sheet 名稱) + HeaderFontSize :頭部字體大小 + FontSize :正文字體大小 + MaxRowNumber ...
  • 你是否在初學 .net core時,被依賴註入所折磨? 你是否在開發過程中,為了註入依賴而不停的在Startup中增加註入代碼,而感到麻煩? 你是否考慮過或尋找過能輕鬆實現自動註入的組件? 如果有,那請歡迎繼續往下看。 或許你是被我這標題給吸引過來的,請不要懷疑自己的眼睛,如果你真的遇到過以上的問題 ...
  • 序言: 在 UWP 中,常見的存儲數據方式基本上就兩種。第一種方案是 UWP 框架提供的 ApplicationData Settings 這一系列的方法,適用於存放比較輕量的數據,例如存個 Boolean 類型的設置項這種是最適合不過的了。另一種方案是用 Sqlite 這種資料庫,適合存放數據量大 ...
  • 一、前言 在進行 Web 項目開發的過程中,可能會存在一些需要經常訪問的靜態數據,針對這種在程式運行過程中可能幾乎不會發生變化的數據,我們可以嘗試在程式運行前寫入到緩存中,這樣在系統後續使用時就可以直接從緩存中進行獲取,從而減緩因為頻繁讀取這些靜態數據造成的應用資料庫伺服器的巨大承載壓力。 既然需要 ...
  • 這是該系列的第一篇文章:在ASP.NET Core 3.0中使用Serilog.AspNetCore。 1. 第1部分 使用 來簡化ASP.NET Core的日誌輸出(本篇文章) 2. 第2部分 使用Serilog記錄所選的端點名稱[敬請期待] 3. 第3部分 使用Serilog.AspNetCor ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...