cat显示一个文件的内容。需要注意的是,cat并不能处理目录。
1 extern int cat_main(int argc, char **argv)
2 {
3 int status = EXIT_SUCCESS;
4
5 if (argc == 1) {
6 print_file(stdin);
7 return status;
8 }
9
10 while (--argc > 0) {
11 if(!(strcmp(*++argv, "-"))) {
12 print_file(stdin);
13 } else if (print_file_by_name(*argv) == FALSE) {
14 status = EXIT_FAILURE;
15 }
16 }
17 return status;
18 }
当输入cat或者是cat -时,都会调用print_file函数。
1 extern void print_file(FILE *file)
2 {
3 fflush(stdout);
4 copyfd(fileno(file), fileno(stdout));//将file文件的内容拷贝到stdout
5 fclose(file);
6 }
显然,print_file(stdin)就是将stdin的内容拷贝到stdout。即输入什么,就输出什么。
V658tekiMacBook-Pro:busybox-0.60.3 neilhappy$ cat -
input--stdin
input--stdin
当cat filename时,进入print_file_by_name函数。
1 extern int print_file_by_name(char *filename)
2 {
3 struct stat statBuf;
4 int status = TRUE;
5
6 if(is_directory(filename, TRUE, &statBuf)==TRUE) {
7 error_msg("%s: Is directory", filename);
8 status = FALSE;
9 } else {
10 FILE *f = wfopen(filename, "r");
11 if(f!=NULL)
12 print_file(f);
13 else
14 status = FALSE;
15 }
16
17 return status;
18 }
is_directory判断是否是目录。如果不是目录,就用pring_file函数打印。要注意,这里的TRUE参数决定了只使用stat(不考虑符号链接)。
1 int is_directory(const char *fileName, const int followLinks, struct stat *statBuf)
2 {
3 int status;
4 int didMalloc = 0;
5
6 if (statBuf == NULL) {
7 statBuf = (struct stat *)xmalloc(sizeof(struct stat));
8 ++didMalloc;
9 }
10
11 if (followLinks == TRUE)
12 status = stat(fileName, statBuf);
13 else
14 status = lstat(fileName, statBuf);
15
16 if (status < 0 || !(S_ISDIR(statBuf->st_mode))) {
17 status = FALSE;
18 }
19 else status = TRUE;
20
21 if (didMalloc) {
22 free(statBuf);
23 statBuf = NULL;
24 }
25 return status;
26 }
整个流程的结构非常清晰。