[インデックス 13021] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおいて、macOS (Darwin) 環境でのtermios
(ターミナルI/O設定)サポートを追加するものです。これにより、GoプログラムからmacOSのターミナルデバイスの挙動をより詳細に制御できるようになります。
コミット
commit 61060acdc12ef0e0b9ff2250efdf8da10d53c5a2
Author: Francisco Souza <franciscossouza@gmail.com>
Date: Thu May 3 17:33:19 2012 -0400
syscall: add Termios support on darwin
Update #3316.
R=dave, kevlar, devon.odell, rsc, minux.ma
CC=golang-dev
https://golang.org/cl/6063053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/61060acdc12ef0e0b9ff2250efdf8da10d53c5a2
元コミット内容
syscall: add Termios support on darwin
Update #3316.
変更の背景
この変更は、Go言語のsyscall
パッケージがmacOS上でtermios
構造体と関連する定数をサポートしていなかったという問題(Issue 3316)に対応するために行われました。termios
はUnix系システムにおいて、シリアルポートやターミナルデバイスの入出力設定を制御するための標準的なインターフェースです。GoプログラムがmacOS上でターミナルと対話する際、例えばパスワード入力時のエコーバックの無効化、生の入力モードへの切り替え、特殊文字の処理の変更など、より低レベルな制御が必要となる場合があります。このコミット以前は、Goのsyscall
パッケージにはこれらの機能が不足しており、macOS上でターミナル関連の高度な操作を行うGoアプリケーションの開発が困難でした。
前提知識の解説
termios
とは
termios
は、POSIX (Portable Operating System Interface) 標準で定義されている、ターミナルI/Oを制御するためのデータ構造と関数群です。Unix系オペレーティングシステム(Linux, macOS, BSDなど)において、プログラムがシリアルポートや擬似ターミナル(pty)などの文字デバイスと対話する際に使用されます。
termios
構造体には、以下のようなターミナル設定が含まれます。
- 入力モード (c_iflag): 入力処理に関するフラグ(例:
ICANON
(カノニカルモード),ECHO
(エコー),IGNCR
(CR無視))。 - 出力モード (c_oflag): 出力処理に関するフラグ(例:
OPOST
(後処理),ONLCR
(LFをCR-LFに変換))。 - 制御モード (c_cflag): ハードウェア制御に関するフラグ(例:
CSIZE
(文字サイズ),CLOCAL
(ローカル接続),CRTSCTS
(RTS/CTSフロー制御))。 - ローカルモード (c_lflag): ローカル処理に関するフラグ(例:
ISIG
(シグナル生成),NOFLSH
(フラッシュ無効))。 - 特殊文字 (c_cc): EOF, EOL, INTRなどの特殊文字の定義。
- ボーレート (c_ispeed, c_ospeed): 入出力のボーレート。
これらの設定を操作することで、ターミナルの挙動(例: 入力文字のエコー、行バッファリング、Ctrl+Cによるシグナル送信など)を細かく制御できます。
Go言語のsyscall
パッケージ
Go言語の標準ライブラリであるsyscall
パッケージは、オペレーティングシステムが提供する低レベルなシステムコールへのインターフェースを提供します。これにより、Goプログラムはファイルシステム、プロセス管理、ネットワークI/O、シグナル処理など、OSのコア機能に直接アクセスできます。
syscall
パッケージは、OS固有の定数、構造体、関数を定義しており、クロスプラットフォームなGoプログラムが各OSのネイティブな機能を利用できるように抽象化されています。このコミットのように、特定のOS(ここではmacOS)で利用可能な新しいシステムコールや構造体を追加する場合、syscall
パッケージ内のOS固有のファイルが更新されます。
mkerrors.sh
, zerrors_darwin_*.go
, ztypes_darwin_*.go
Goのsyscall
パッケージでは、OS固有の定数や構造体の定義を自動生成する仕組みが採用されています。
mkerrors.sh
: このシェルスクリプトは、C言語のヘッダーファイルからシステムコールに関連するエラーコード、定数、構造体などの情報を抽出し、Goのソースコードを生成するために使用されます。このコミットでは、termios
に関連する多数の定数を認識し、Goコードとして出力するための新しい正規表現パターンが追加されています。zerrors_darwin_*.go
:mkerrors.sh
によって生成されるファイルの一つで、Darwin(macOS)環境におけるシステムコール関連の定数(エラーコード、フラグなど)がGoのconst
として定義されます。このコミットでは、termios
の入力モード、出力モード、制御モード、ローカルモード、ボーレートなどに関する膨大な数の定数(例:B0
,ICANON
,OPOST
,CS8
など)が追加されています。ファイル名に386
やamd64
が含まれるのは、32ビットおよび64ビットアーキテクチャ固有の定義を区別するためです。ztypes_darwin_*.go
:mkerrors.sh
によって生成されるもう一つのファイルで、Darwin環境におけるシステムコール関連のC言語の構造体がGoのstruct
として定義されます。このコミットでは、termios
構造体(Iflag
,Oflag
,Cflag
,Lflag
,Cc
,Ispeed
,Ospeed
フィールドを持つ)がGoの型として追加されています。
これらの自動生成されたファイルは、GoプログラムがC言語のシステムコールインターフェースとシームレスに連携するために不可欠です。
技術的詳細
このコミットの主要な目的は、macOSにおけるtermios
のサポートをGoのsyscall
パッケージに統合することです。これは、主に以下の3つの側面から実現されています。
termios.h
のインクルード:src/pkg/syscall/types_darwin.go
ファイルにC言語のヘッダーファイル<termios.h>
がインクルードされるようになりました。これにより、Goのsyscall
パッケージがC言語のtermios
構造体の定義にアクセスできるようになります。Termios
Go構造体の定義:src/pkg/syscall/types_darwin.go
にtype Termios C.struct_termios
というエイリアスが追加されました。これは、C言語のstruct termios
をGoのTermios
型として直接利用できるようにするためのものです。termios
関連定数の追加:src/pkg/syscall/mkerrors.sh
スクリプトが更新され、termios
に関連する多数の定数(例: ボーレート、制御フラグ、特殊文字など)を認識し、Goのコードとして自動生成できるようになりました。これにより、src/pkg/syscall/zerrors_darwin_386.go
およびsrc/pkg/syscall/zerrors_darwin_amd64.go
に、これらの定数が追加されました。これらの定数は、termios
構造体の各フラグ(c_iflag
,c_oflag
,c_cflag
,c_lflag
)や特殊文字配列(c_cc
)を設定する際に使用されます。Termios
Go構造体の自動生成:src/pkg/syscall/ztypes_darwin_386.go
およびsrc/pkg/syscall/ztypes_darwin_amd64.go
に、Termios
構造体の具体的なGoの定義が自動生成されました。これらは、C言語のstruct termios
のフィールド(c_iflag
,c_oflag
,c_cflag
,c_lflag
,c_cc
,c_ispeed
,c_ospeed
)に対応するGoの型とフィールド名を持ちます。
これらの変更により、Goプログラムはsyscall.Termios
型を使用してターミナル設定を読み書きし、syscall
パッケージで定義された関連定数を用いてその設定を操作できるようになります。例えば、syscall.Tcgetattr
やsyscall.Tcsetattr
のような関数(このコミットでは直接追加されていませんが、termios
サポートの前提となる)を通じて、ターミナルのカノニカルモードの有効/無効、エコーの制御、ボーレートの設定などが可能になります。
コアとなるコードの変更箇所
src/pkg/syscall/mkerrors.sh
このスクリプトは、CヘッダーファイルからGoの定数を生成するための正規表現パターンを拡張しています。特に、termios
に関連する定数(B*
, V*
, CS*
, I*
, IGN*
, IX*
, IN*
, FLUSH*
, C*
, HUPCL
, PENDIN
, TOSTOP
, PAR*
, O*
など)を捕捉するための新しいパターンが追加されています。
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -174,7 +174,22 @@ ccflags="$@"
$2 !~ /^EQUIV_/ &&
$2 !~ /^EXPR_/ &&
$2 ~ /^E[A-Z0-9_]+$/ ||
+ $2 ~ /^B[0-9_]+$/ ||
+ $2 ~ /^V[A-Z0-9]+$/ ||
+ $2 ~ /^CS[A-Z0-9]/ ||
+ $2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
+ $2 ~ /^IGN/ ||
+ $2 ~ /^IX(ON|ANY|OFF)$/ ||
+ $2 ~ /^IN(LCR|PCK)$/ ||
+ $2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
+ $2 ~ /^C(LOCAL|READ)$/ ||
+ $2 == "BRKINT" ||
+ $2 == "HUPCL" ||
+ $2 == "PENDIN" ||
+ $2 == "TOSTOP" ||
+ $2 ~ /^PAR/ ||
$2 ~ /^SIG[^_]/ ||
+ $2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ ||
$2 ~ /^IN_/ ||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
src/pkg/syscall/types_darwin.go
このファイルは、Cヘッダーのインクルードと、GoのTermios
型定義を追加しています。
--- a/src/pkg/syscall/types_darwin.go
+++ b/src/pkg/syscall/types_darwin.go
@@ -20,6 +20,7 @@ package syscall
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>
+#include <termios.h>
#include <unistd.h>
#include <mach/mach.h>
#include <mach/message.h>
@@ -226,3 +227,5 @@ type BpfProgram C.struct_bpf_program
type BpfInsn C.struct_bpf_insn
type BpfHdr C.struct_bpf_hdr
+
+type Termios C.struct_termios
src/pkg/syscall/zerrors_darwin_386.go
および src/pkg/syscall/zerrors_darwin_amd64.go
これらのファイルは、mkerrors.sh
によって生成され、termios
に関連する多数の定数が追加されています。例として、zerrors_darwin_386.go
の一部を示します。amd64
版も同様の変更です。
--- a/src/pkg/syscall/zerrors_darwin_386.go
+++ b/src/pkg/syscall/zerrors_darwin_386.go
@@ -43,6 +43,29 @@ const (
AF_SYSTEM = 0x20
AF_UNIX = 0x1
AF_UNSPEC = 0x0
+ B0 = 0x0
+ B110 = 0x6e
+ B115200 = 0x1c200
+ B1200 = 0x4b0
+ B134 = 0x86
+ B14400 = 0x3840
+ B150 = 0x96
+ B1800 = 0x708
+ B19200 = 0x4b00
+ B200 = 0xc8
+ B230400 = 0x38400
+ B2400 = 0x960
+ B28800 = 0x7080
+ B300 = 0x12c
+ B38400 = 0x9600
+ B4800 = 0x12c0
+ B50 = 0x32
+ B57600 = 0xe100
+ B600 = 0x258
+ B7200 = 0x1c20
+ B75 = 0x4b
+ B76800 = 0x12c00
+ B9600 = 0x2580
BIOCFLUSH = 0x20004268
BIOCGBLEN = 0x40044266
BIOCGDLT = 0x4004426a
@@ -108,6 +131,20 @@ const (
BPF_TXA = 0x80
BPF_W = 0x0
BPF_X = 0x8
+ BRKINT = 0x2
+ CFLUSH = 0xf
+ CLOCAL = 0x8000
+ CREAD = 0x800
+ CS5 = 0x0
+ CS6 = 0x100
+ CS7 = 0x200
+ CS8 = 0x300
+ CSIZE = 0x300
+ CSTART = 0x11
+ CSTATUS = 0x14
+ CSTOP = 0x13
+ CSTOPB = 0x400
+ CSUSP = 0x1a
CTL_MAXNAME = 0xc
CTL_NET = 0x4
DLT_APPLE_IP_OVER_IEEE1394 = 0x8a
... (以下、多数のtermios関連定数が追加)
src/pkg/syscall/ztypes_darwin_386.go
および src/pkg/syscall/ztypes_darwin_amd64.go
これらのファイルは、mkerrors.sh
によって生成され、Termios
構造体のGoの定義が追加されています。
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -416,3 +416,13 @@ type BpfHdr struct {
Hdrlen uint16
Pad_cgo_0 [2]byte
}\n
+type Termios struct {
+ Iflag uint32
+ Oflag uint32
+ Cflag uint32
+ Lflag uint32
+ Cc [20]uint8
+ Ispeed uint32
+ Ospeed uint32
+}\n
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -425,3 +425,14 @@ type BpfHdr struct {
Hdrlen uint16
Pad_cgo_0 [2]byte
}\n
+type Termios struct {
+ Iflag uint64
+ Oflag uint64
+ Cflag uint64
+ Lflag uint64
+ Cc [20]uint8
+ Pad_cgo_0 [4]byte
+ Ispeed uint64
+ Ospeed uint64
+}\n
コアとなるコードの解説
このコミットの核となる変更は、Goのsyscall
パッケージがmacOSのtermios
機能を認識し、Goプログラムから利用できるようにするための基盤を構築した点にあります。
-
types_darwin.go
におけるtermios.h
のインクルードとTermios
型の定義:#include <termios.h>
は、Goのcgo
メカニズムを通じて、C言語のtermios.h
ヘッダーファイルの内容をGoのコンパイルプロセスに含めることを指示します。これにより、Goコード内でC言語のstruct termios
を参照できるようになります。type Termios C.struct_termios
という行は、C言語のstruct termios
をGoのTermios
という新しい型として定義しています。これは、GoプログラムがCの構造体を直接扱うためのGoの表現です。この型を通じて、Goプログラムはターミナル設定の各フィールドにアクセスできるようになります。
-
mkerrors.sh
の更新による定数自動生成の強化:mkerrors.sh
に追加された新しい正規表現パターンは、C言語のヘッダーファイル内に存在するtermios
関連の定数(例:B115200
(ボーレート),ICANON
(カノニカルモードフラグ),CS8
(文字サイズ)など)を自動的に抽出し、Goのconst
としてzerrors_darwin_*.go
ファイルに書き出す役割を担います。- この自動生成プロセスは、手動で膨大な数の定数をGoに移植する手間を省き、Cヘッダーファイルとの同期を保つ上で非常に重要です。これにより、GoプログラムはOSが提供する正確な
termios
定数を使用して、ターミナル設定を細かく制御できるようになります。
-
zerrors_darwin_*.go
およびztypes_darwin_*.go
への自動生成されたコードの追加:zerrors_darwin_*.go
ファイルに大量に追加されたconst
定義は、termios
構造体の各フラグ(c_iflag
,c_oflag
,c_cflag
,c_lflag
)や特殊文字配列(c_cc
)に設定できる具体的な値をGoプログラムに提供します。例えば、B115200
はボーレートを115200bpsに設定するための値であり、ICANON
は入力を行単位で処理するカノニカルモードを有効にするためのフラグです。ztypes_darwin_*.go
ファイルに自動生成されたTermios
構造体は、Goプログラムがtermios
設定を読み書きするための具体的なメモリレイアウトを定義します。Iflag
,Oflag
,Cflag
,Lflag
はそれぞれ入力、出力、制御、ローカルモードのフラグを保持し、Cc
は特殊文字の配列、Ispeed
とOspeed
は入出力のボーレートを保持します。これらのフィールドは、C言語のstruct termios
の対応するフィールドと一致するように設計されています。
これらの変更が組み合わさることで、GoプログラムはmacOS上でtermios
APIを介してターミナルデバイスの低レベルな制御を行うための、堅牢でOSに準拠したインターフェースを獲得しました。これにより、Goでより高度なCLIツールやターミナルアプリケーションを開発する道が開かれました。
関連リンク
- Go Issue 3316:
syscall: add Termios support on darwin
- このコミットが解決した元のIssue。 - Go CL 6063053:
syscall: add Termios support on darwin
- このコミットに対応するGoのコードレビュー(Change List)。
参考にした情報源リンク
- termios(3) - Linux man page:
termios
構造体と関連関数の詳細な説明。 - Go言語のsyscallパッケージのドキュメント:
- cgoのドキュメント: GoとC言語の相互運用に関する情報。
- POSIX
termios
に関する情報: - Goのソースコードリポジトリ:
- GoのIssueトラッカー:
- GoのChange List (CL) システム: