编写Linux实用程序的艺术( 四 )

< /home),前者会给出详细的错误消息 。另一方面,当它在获得无效数据的早期就选择放弃可能是理想的 。
安全漏洞经常植根于在意料之外的数据面前表现得不够健壮的程序中 。务必记住,优秀的实用程序能够设法在 shell 脚本中作为根(root)用户身份运行 。诸如 find 这样的程序中的缓冲区溢出可能会给大量的系统带来风险 。
程序对意料之外的数据处理得越好,它就更可能适应变化的环境 。通常,设法使程序更健壮会导致您更好地理解该程序的作用,从而更好地使之通用化 。
新颖
要编写的最糟糕的实用程序种类之一就是您已经有了的实用程序 。我编写过一个名为 count 的美妙的实用程序 。它允许我执行几乎任何计数任务 。它是一个出色的实用程序,但是已经有一个名为 jot 的标准 BSD 实用程序做同样的事情 。同样地,我的一个用于将数据转换为列的灵活的程序重复了一个现有实用程序 rs 的功能,这个实用程序同样可以在 BSD 系统上找到,只不过 rs 更灵活,设计得更好 。请参阅下面的 参考资料 以了解关于 jot 和 rs 的更多信息 。
如果您即将开始编写一个实用程序,请花一点时间浏览一下各种系统,以确定那样的实用程序是否已经存在 。不要害怕在 BSD 上借用 Linux 实用程序,或在 Linux 上借用 BSD 实用程序;实用程序代码的乐趣之一在于,几乎所有实用程序都具有很好的可移植性 。
不要忘了考察一下组合现有应用程序来形成一个实用程序的可能性 。从理论上讲,组合现有程序来形成的实用程序运行得不足够快是可能的,但是编写一个新的实用程序很少会比等待一个稍慢的管道更快 。
一个例子实用程序
从某种意义上,这个程序是一个可执行文件,因为对于作为过滤器来说,它决不会有任何用处 。然而,它作为一个命令行实用程序却工作得非常好 。
这个程序仅做一件事情 。它以近乎完美的输出格式输出 /usr/include/sys/errno.h 中的 errno 行 。例如:
$ errno 22
EINVAL [22]: Invalid argument
清单 2. errno 查找器

#!/bin/sh
usage() {
echo >&2 "usage: errno [numbers or error names]n"
exit 1
}
for i
do
case "$i" in
[0-9]*)
awk "/^#define/ && $3 == ""$i"" {
for (i = 5; i < NF;i) {
foo = foo " " $i;
}
printf("%-22s%sn", $2 " [" $3 "]:", foo);
foo = ""
}" < /usr/include/sys/errno.h
;;
E*)
awk "/^#define/ && $2 == """$i""" {
for (i = 5; i < NF;i) {
foo = foo " " $i;
}
printf("%-22s%sn", $2 " [" $3 "]:", foo);
foo = ""
}" < /usr/include/sys/errno.h
;;
*)
echo >&2 "errno: can"t figure out whether "$i" is a name or a number."
usage
;;
esac
done
这个程序通用化了吗?是的,非常理想 。它同时支持数字和符号名称 。另一方面,它不知道关于可能具有相同格式的其他文件的信息,比如 /usr/include/sys/signal.h 。可以容易地扩展它来做到这点,但是对于这样一个便利的实用能够程序,简单地创建一个名为“signal”的拷贝来读取 signal.h,同时使用“SIG*”作为模式来匹配名称,这样会更容易 。
虽然这仅比对系统头文件使用 grep 方便一小点,但是它更不容易出错 。它不会因为考虑不周的参数而产生无用的结果 。另一方面,如果没有从头文件中找到给定的名称或数字,它不会产生诊断信息 。它也不会费心去纠正某些输入错误 。而且,由于命令行实用程序从来没有打算在自动化的环境中使用,因此它的上述特性无可非议 。
另一个例子可能是取消对输入排序的程序(请参阅 参考资料 以获得指向此实用程序的链接) 。这相当简单;也就是读入输入文件,以某种方式存储它们,然后生成一个随机顺序来输出那些行 。这是一个几乎具有无限应用前景的实用程序 。编写这个实用程序也比编写排序程序容易得多;例如,您不需要指定您没有对哪些键排序,或者是您希望按字母顺序、词法顺序还是按数字顺序随机排序 。棘手的部分在于读入可能非常长的行 。事实上,上面提供的版本在搞欺骗;它假设所读入的行中没有空字节 。纠正这个问题要困难多了,我在编写它时懒得去理会它 。

推荐阅读