📄 00000004.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人: wshu (树上的老虎), 信区: Unix <BR>标 题: UNIX FAQ 中文版(四) <BR>发信站: BBS 水木清华站 (Mon May 19 10:12:11 1997) <BR> <BR>本篇文章回答以下问题: <BR> <BR> 4.1) 要如何在使用者不必按 RETURN 的情况下从 terminal 读进东西? <BR> 4.2) 我要如何在未曾真的读进东西的情况下检查是否有字元等待读取? <BR> 4.3) 要怎样才能得知一个已open 档案之档名? <BR> 4.4) 一个执行中的程式如何知道自己的 pathname? <BR> 4.5) 如何用 popen() 对一个 process 做读写的动作? <BR> 4.6) 在 C 程式中要怎么用 sleep() 才能够 sleep 小于一秒? <BR> 4.7) 如何让 setuid 的 shell script 可以使用? <BR> 4.8) 我要如何得知有哪些 process 开了某一档案,或某一 process 正在使用哪 <BR> 一个 fileystem(以至于我无法 unmount 这个 filesystem)? <BR> 4.9) 我要怎么知道是谁在 finger 我啊? <BR> 4.10) 能不能在一个 process 和 terminal 的连接已经断掉之后再接回来,例如 <BR> 在 background 跑一个程式然后就 logout 而断掉的程式? <BR> 4.11) 有没有办法可以偷听一个 terminal,就是说将其输出复制一份至其他的 <BR> terminal。 <BR> <BR> 4.1) 要如何在使用者不必按 RETURN 的情况下从 terminal 读进东西? <BR> <BR> 在 BSD 中用 cbreak 模式,在 SysV 中则用 ~ICANON 模式。 <BR> <BR> 如果你懒得用 "ioctl(2)" 来设定 terminal 的参数,也可以用 stty 来做, <BR> 不过有点慢又没有效率就是了。底下的程式自己看著办吧: <BR> <BR> #include <stdio.h> <BR> main() <BR> { <BR> int c; <BR> <BR> printf("Hit any character to continue\n"); <BR> /* <BR> * ioctl() would be better here; only lazy <BR> * programmers do it this way: <BR> */ <BR> system("/bin/stty cbreak"); /* or "stty raw" */ <BR> c = getchar(); <BR> system("/bin/stty -cbreak"); <BR> printf("Thank you for typing %c.\n", c); <BR> <BR> exit(0); <BR> } <BR> <BR> 有好几个人送给我更正确的解法。不过很抱歉我不想把它们加进去,因为这已经 <BR> 超出这份文件的范围了。 <BR> <BR> 通常对这个问题有兴趣的人,都是想要做一些控制萤幕显示之类的事情。如果你 <BR> 也是的话,那请参考 "curses" 的相关文件。 "curses" 是一个 portable 的萤 <BR> 幕控制函数库。 <BR> <BR> <BR> 4.2) 我要如何在未曾真的读进东西的情况下检查是否有字元等待读取? <BR> <BR> 一些版本的 UNIX 提供了检查某个 file descriptor 目前是否有东西待读取的 <BR> 方法。在 BSD 中,可以用 "select(2),也可以用 FIONREAD ioctl,检查有几 <BR> 个字元等待读取,不过这只对 terminal, pipe, 与 socket 有用。在 System <BR> V Release 3 中可以用 poll(2),不过只对 stream 有用。在 Xenix 与 Sys V <BR> r3.2 及其以后的版本里,有一个名叫 rdchk() 的 system call 可以用来检查 <BR> 对一个 file descriptor 做 read() 会不会卡住。 <BR> <BR> 没有方法可以用来判断是否有字元在 FILE pointer 中待读取。(你可以直接查 <BR> 看 stdio 的资料结构,看看是否 input buffer 是空的,但是这方法有时会失 <BR> 效,因为你没有办法知道当你下一次要填满这个 buffer 时会发生什么事。) <BR> <BR> 有时人们问这个问题是因为想写 <BR> if (characters available from fd) <BR> read(fd, buf, sizeof buf); <BR> 以达成 nonblocking read。这不是一种好的做法,因为可能测的时候有东西, <BR> 要读的时候,已经没有东西可读了。正确的做法应该是用 fcntl(2) 里的 <BR> F_SETFL 设定 O_NDELAY。比较旧的系统(Version 7, 4.1 BSD) 没有 <BR> O_NDELAY,那就得用 alarm(2) 来设定 read 的 timeout,以达成近似 <BR> nonblocking read 的功能。 <BR> <BR> <BR> 4.3) 要怎样才能得知一个已 open 档案之档名? <BR> <BR> 这个是非常困难的。若是这个 file descriptor 是对应到 pipe 或 pty 就没 <BR> 有名字了。这个 file descriptor 对应的档案也有可能已被删除。若是有 <BR> symbolic link 或 hard link,则可能有许多个名字。 <BR> <BR> 如果你经过一再考虑后别无选择一定要这么做的话,可以用 find 的 -inum 与 <BR> -xdev 选项,或用 ncheck,或用自己写类似的程式来做。在这么做时要耐心的 <BR> 等,因为在一个几百 megabyte 甚至几 gigabyte 的 file system中找一个档 <BR> 案,一定得花不少时间。 <BR> <BR> <BR> 4.4) 一个执行中的程式如何知道自己的 pathname? <BR> <BR> 若果 argv[0] 是以 "/" 开始的字,它可能就是你的程式所在地的绝对路径。 <BR> 如果不是那就得照顺序检查 PATH 里的每一个目录看看里面是否有与 argv[0] <BR> 一样的程式。如果找得到的话将那个目录与程式名称兜起来可能就是你要的 <BR> pathname 了。 <BR> <BR> 不过上述方法找到的并不一定是正确的,因为在程式中用到 exec() 时, <BR> argv[0] 是可以随便给的。将 argv[0] 设为与要执行的程式名称相同只是一 <BR> 种惯用法罢了! <BR> <BR> 以下的例子可能会使你更清楚些: <BR> <BR> #include <stdio.h> <BR> main() <BR> { <BR> execl("/usr/games/rogue", "vi Thesis", (char *)NULL); <BR> } <BR> <BR> 这个被执行的程式就会认为它的名字(argv[0] 之值)是 "vi Thesis")。 <BR> <BR> <BR> 4.5) 如何用 popen() 对一个 process 做读写的动作? <BR> <BR> 用 pipe 将一个 process 的输出、输入转给任意的 process 所可能会发生的 <BR> 问题就是 deadlock,譬如这两个 processes 刚好同时都在等待「尚未产生」 <BR> 的输入时。唯一能避免 deadlock 的方法就是在 pipe 的两端都要遵循严格的 <BR> deadlock-free 协定,但是需要这些 processes 之间的互相合作才能达成, <BR> 而对于像 popen() 这类的函数来说并不太适合。 <BR> <BR> 在 'expect' 这个软体中附有一个能够让 C 程式直接引用的函式库。其中有 <BR> 一个函式不管是在读或写都能达到和 popen 相同的功能。但是这个函式使 <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -