#navi_header|C言語系| お題:ログイン時などに Password: と表示され、入力するけど文字が画面に表示されないのは何で? #more|| ログイン時→loginコマンド? $ locate login /etc/csh.login ... /usr/src/usr.bin/login ... /usr/src/usr.bin/login/login.c → /usr/src/usr.bin/login/login.c : ... pwprompt = "Password:"; p = getpass(pwprompt); getpass(3)はlibcに入ってる関数。"man 3 getpass"参照。 $ locate getpass /usr/share/man/cat3/getpass.0 /usr/share/man/man3/getpass.3 /usr/src/gnu/dist/cvs/lib/getpass.c /usr/src/lib/libc/gen/getpass.3 /usr/src/lib/libc/gen/getpass.c "/usr/src/lib/libc/gen/getpass.c" がそれっぽい。 今回の探索のポイント周り: (void)tcgetattr(fileno(fp), &term); if ((echo = (term.c_lflag & ECHO)) != 0) { term.c_lflag &= ~ECHO; (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term); } /* ... */ /* getc()で入力文字をバッファに保存し、NULLターミネート文字列を返値用に作ってる */ /* ... */ if (echo) { term.c_lflag |= ECHO; (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term); } 端末(ターミナル)の操作の詳細は "man 4 termios", "man 3 tcsetattr" 参照。 ここではtcsetattr()の内部まで潜る。 $ locate tcsetattr /usr/share/man/cat3/tcsetattr.0 /usr/share/man/man3/tcsetattr.3 /usr/src/lib/libc/termios/tcsetattr.3 /usr/src/lib/libc/termios/tcsetattr.c → "/usr/src/lib/libc/termios/tcsetattr.c" を覗いてみる。 #code|c|> tcsetattr(fd, opt, t) int fd, opt; const struct termios *t; { /* ... */ if (opt & TCSASOFT) { /* ... */ } switch (opt & ~TCSASOFT) { /* ... */ case TCSAFLUSH: return (ioctl(fd, TIOCSETAF, t)); /* ... */ } /* ... */ } ||< ということで、最終的にはioctl(2)を使ったデバイス操作に帰着した。 「デーモン君のソース探検」ではgrepでかなり頑張ってる。locateのインデックスを作っておけば、locateの方が見つけやすい時もある。 locateが使えない時は、個人的にはfindによる名前一致検索も使ったりする。 パスワードを見えないようにする・・・つまり、入力をエコーバックさせないようなパターンでは、getpass(3)を直接使っても良いし、シグナルマスクなどを自前で処理したい場合(=getpass(3)の内部のシグナル処理を使いたくない場合)は、tcsetattrでtermios構造体のc_cflagsメンバでECHOビットをOFFにしてエコーバックを無効化すればよいだろう。元に戻すのも忘れずに。 #navi_footer|C言語系|