Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
PTY on Rust
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Hibariya Hi
July 12, 2015
Programming
1.6k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PTY on Rust
Hibariya Hi
July 12, 2015
More Decks by Hibariya Hi
See All by Hibariya Hi
Creating an Active Job Adapter for Cloud Run
hibariya
0
720
Idobata on GKE - Moving an Ordinary Rails App
hibariya
0
190
Using Docker for your Rails Development Environment
hibariya
1
3.8k
GraphQL Subscription with Relay and Action Cable
hibariya
1
2.5k
Various Services
hibariya
1
370
Building a Web API with GraphQL
hibariya
2
4.3k
My recent troubles in using Ember Data
hibariya
0
1.2k
Idobata をもっと便利に 使うための tips
hibariya
0
1.6k
Control a Shell With pty-shell
hibariya
0
1.9k
Other Decks in Programming
See All in Programming
高橋メソッドでCVE解説シリーズ 〜CVE-2026-112816〜
hakkadaikon
0
230
Crash Auto Pipelines
veronikapj
1
380
私なりのハーネスエンジニアリング ~独自の言語処理系の開発を通して~
seosoft
0
180
作れるエンジニアから、価値を届けるエンジニアへ
ryunakayama
1
240
AI時代のIaC入門 〜なぜインフラをコードで管理したいのか?〜 / Introduction to IaC in the AI Era
akihisaikeda
6
1.4k
社内AIエージェント「Askワンバン」における コストチューニングの取り組み
t0yohei
0
160
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
140
Kawaiicon: Kubernetes, it's no longer cool, but let's secure it anyway!
barnbarn
0
110
flutter_test のその先へ — Flutter アプリの LLM 機能に「評価」という品質保証を
kosukesaigusa
0
200
プロジェクトコードをキレイキレイしよう!暗黙的な参照を読み解く静的解析
ostk0069
0
210
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
220
React Native에 현대적인 빌드 도구 더하기: Rollipop 구현기
leegeunhyeok
0
180
Featured
See All Featured
Faster Mobile Websites
deanohume
310
32k
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
Context Engineering - Making Every Token Count
addyosmani
9
1.3k
Six Lessons from altMBA
skipperchong
29
4.6k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
630
Become a Pro
speakerdeck
PRO
31
6.4k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.2k
Side Projects
sachag
456
43k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
470
Large-scale JavaScript Application Architecture
addyosmani
516
110k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
480
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
Transcript
PTY on Rust 2015-07-12 Rust of Us - Chapter 2
@hibariya
やりたいこと • Rust で • PTY を使って • シェルの入出力を好きなようにする
こういうこと
こういうこと
入出力を好きなようにできると嬉しい • 何か入出力があるたびに音を鳴らせる • 出力を記録してあとで再現したりできる • ターミナルの表示を遠方の人と共有できる
方法 • パイプを使う • 親の端末につなぐ • システムコールを監視する • 新たな端末を割り付ける
方法 • パイプを使う • 親の端末につなぐ • システムコールを監視する • 新たな端末を割り付ける
パイプを使う 端末 <> 親 <> パイプ <> 子
パイプを使う • うまくいかない • デフォルトの端末はカノニカルモード (入力は行 ごとに親プロセスへ送られる) なので、改行が来 るまで入力を子プロセスへ送ることができない •
vi や nano が使えない • 端末に接続されていないのも都合が悪い
方法 • パイプを使う • 親の端末につなぐ • システムコールを監視する • 新たな端末を割り付ける
親の端末につなぐ 端末 <> 親 <> 子
親の端末につなぐ • うまくいかない • 入力はすぐに子プロセスへ届くが... • 親が子の入出力を捕捉できない • (方法を知らないだけ?)
方法 • パイプを使う • 親の端末につなぐ • システムコールを監視する • 新たな端末を割り付ける
システムコールを監視 自分 -> プロセス (write(2) を監視!)
システムコールを監視 github.com/hibariya/process_tail • ちょっと微妙 • 既に走っているプロセスにも使える • Linux と Mac
OS X で実装が別 • 環境によって微妙に動きが違うのができた • ちょっと重い気がする
方法 • パイプを使う • 親の端末につなぐ • システムコールを監視する • 新たな端末を割り付ける
新たな端末を割り付ける 端末 <> 親 <> 端末 <> 子 (親の端末は raw
モードに)
新たな端末を割り付ける note.hibariya.org/articles/20150628/pty.html • うまくいく • 既に走っているプロセスには使えない • 端末を想定しているコマンドも動作する • Linux
と Mac OS X でほぼ同じ実装 • 比較的シンプル
色々試した結果 • パイプを使う • 親の端末につなぐ • システムコールを監視する • 新たな端末を割り付ける
PTY (Pseudo terminal) • 疑似端末 • 端末をソフトウェアでエミュレートしたもの • ターミナルエミュレータなどが使っている •
/dev/pts/4 みたいな名前がついている
新たな端末を割り付ける 端末 <> 親 <> 端末 <> 子 (親の端末は raw
モードに)
Ruby で書くと1行 output, input, pid = PTY.spawn('bash')
Rust ではどうすれば • わからない • PTY.spawn は無かった • libc の
API を使えばやれそう • PTY の使い方を調べるところから
情報源 • script(1) のソース • Ruby の ext/pty/pty.c • APUE
第3版 18, 19章
PTY のしくみ • マスタとスレーブがある • 双方向パイプのように振る舞う • 親から子へ入力、子から親へ出力できる
PTY のしくみ マスタ <> スレーブ <> ラインディシプリン
PTY.spawn(‘bash’) のようなこと 1. 親でマスタ側を開いて fork 2. 子を新しいセッションに入れる 3. 子でスレーブ側を開く 4.
子でスレーブを標準入出力にする 5. 子で (bash を) exec 6. 親でマスタ越しに入出力を操作
PTY.spawn(‘bash’) のようなこと 1. 親でマスタ側を開いて fork 2. 子を新しいセッションに入れる 3. 子でスレーブ側を開く 4.
子でスレーブを標準入出力にする 5. 子で (bash を) exec 6. 親でマスタ越しに入出力を操作
親でマスタ側を開いて fork • posix_openpt (3) • スレーブを開くために grantpt (3), unlockpt
(3) も呼んでおく
PTY.spawn(‘bash’) のようなこと 1. 親でマスタ側を開いて fork 2. 子を新しいセッションに入れる 3. 子でスレーブ側を開く 4.
子でスレーブを標準入出力にする 5. 子で (bash を) exec 6. 親でマスタ越しに入出力を操作
子を新しいセッションに入れる • setsid (2) • セッションひとつにつき端末ひとつまで
PTY.spawn(‘bash’) のようなこと 1. 親でマスタ側を開いて fork 2. 子を新しいセッションに入れる 3. 子でスレーブ側を開く 4.
子でスレーブを標準入出力にする 5. 子で (bash を) exec 6. 親でマスタ越しに入出力を操作
子でスレーブ側を開く • ptsname (3) でスレーブの名前を得る • こっちは open(2) で開く
PTY.spawn(‘bash’) のようなこと 1. 親でマスタ側を開いて fork 2. 子を新しいセッションに入れる 3. 子でスレーブ側を開く 4.
子でスレーブを標準入出力にする 5. 子で (bash を) exec 6. 親でマスタ越しに入出力を操作
子でスレーブを標準入出力にする • dup (2) • この時点で入出力が端末につながる
PTY.spawn(‘bash’) のようなこと 1. 親でマスタ側を開いて fork 2. 子を新しいセッションに入れる 3. 子でスレーブ側を開く 4.
子でスレーブを標準入出力にする 5. 子で (bash を) exec 6. 親でマスタ越しに入出力を操作
PTY.spawn(‘bash’) のようなこと 1. 親でマスタ側を開いて fork 2. 子を新しいセッションに入れる 3. 子でスレーブ側を開く 4.
子でスレーブを標準入出力にする 5. 子で (bash を) exec 6. 親でマスタ越しに入出力を操作
できた • note.hibariya.org/articles/20150628/pty.html • Rust から同じものを FFI で呼べばよさそう
PTY on Rust FFI でライブラリの API を呼ぶ extern crate libc;
#[link(name = "c")] extern { pub fn posix_openpt(flags: libc::c_int) -> libc::c_int; pub fn grantpt(fd: libc::c_int) -> libc::c_int; pub fn unlockpt(fd: libc::c_int) -> libc::c_int; pub fn ptsname(fd: libc::c_int) -> *mut libc::c_schar; }
PTY on Rust • 目的の動作をするものはできた • unsafe 祭りになった • もっと簡単に書けるようにしたい
Crate にした • github.com/hibariya/pty-rs • let (child_process, pty_master) = pty::fork();
• おかしなところにパッチがほしい • もっといい API があれば改善したい
extern crate pty;