最近都在看一些理论方面的书,缺乏实践真的是云里雾里的,于是今天开始看《Unix/Linux编程实践教程》,理论实践相结合!
自己动手来实现linux的一些功能,确实挺有趣的,而且还能加深对系统的理解~
版本一
/*more01.c
*read and print 24 lines then pause for a few special commands
*/
#include <stdio.h>
#define PAGELEN 24
#define LINELEN 512
/*
*将数据显示在屏幕上,满一屏后,调用see_more函数接受用户的输入,以采取下一步动作。
*/
void do_more(FILE *);
int see_more();
int main(int argc, char * argv[])
{
FILE *fp;
//判断是文件还是标准输入,打开对应的数据源
if ( argc == 1)
do_more(stdin);
else
{
while (argc--)
if ( (fp = fopen(* ++argv, "r")) != NULL) //第一个参数是more01,跳过
{
do_more(fp);
fclose(fp);
}
else
exit(1);
}
return 0;
}
void do_more(FILE *fp)
{
char line[LINELEN];
int num_of_lines = 0;
int see_more(), reply;
while ( fgets(line, LINELEN, fp) ) //逐行读
{
if (num_of_lines == PAGELEN) //满屏
{
reply = see_more();
if (reply == 0)
break;
num_of_lines -= reply; //根据reply重置行数
}
if ( fputs(line, stdout) == EOF )
exit(1);
num_of_lines++;
}
}
int see_more()
{
int c;
printf("\033[7m more? \033[m");
while ( (c = getchar()) != EOF ) //获取用户输入
{
if ( c == 'q' ) //退出
return 0;
if ( c == ' ' ) //下一页
return PAGELEN;
if ( c == '\n' ) //下一行
return 1;
}
return 0;
}
当然这个程序存在挺多问题的,比如输入q和空格后,需要按回车,而且输入是有回显的。
另外,一个比较严重的问题是,如果我们进行重定向:
ls /bin | more01
则more01的标准输入被重定向到ls的标准输出中,这样子用户的输入也从这个输入流中读取,明显有问题。用户的输入应该始终从键盘读取,而不应该被重定向。
所以版本二提供了直接从键盘设备读取的功能。
版本二
设备文件/dev/tty是键盘和显示器的设备描述文件,往该文件写则显示在用户屏幕上,读则从键盘获取用户输入。
/* more02.c - version 0.2 of more
* read and print 24 lines then pause for a few special commands
* feature of version 0.2: reads from /dev/tty for commands
*/
#include <stdio.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE *);
int see_more(FILE *);
int main( int ac , char *av[] )
{
FILE *fp;
if ( ac == 1 )
do_more( stdin );
else
while ( --ac )
if ( (fp = fopen( *++av , "r" )) != NULL )
{
do_more( fp ) ;
fclose( fp );
}
else
exit(1);
return 0;
}
void do_more( FILE *fp )
/*
* read PAGELEN lines, then call see_more() for further instructions
*/
{
char line[LINELEN];
int num_of_lines = 0;
int see_more(FILE *), reply;
FILE *fp_tty;
fp_tty = fopen( "/dev/tty", "r" ); /* NEW: cmd stream */
if ( fp_tty == NULL ) /* if open fails */
exit(1); /* no use in running */
while ( fgets( line, LINELEN, fp ) ){
if ( num_of_lines == PAGELEN ) {
reply = see_more(fp_tty); /* NEW: pass FILE * */
if ( reply == 0 )
break;
num_of_lines -= reply; /* reset count */
}
if ( fputs( line, stdout ) == EOF ) /* show line */
exit(1); /* or die */
num_of_lines++; /* count it */
}
}
int see_more(FILE *cmd) /* NEW: accepts arg */
/*
* print message, wait for response, return # of lines to advance
* q means no, space means yes, CR means one line
*/
{
int c;
printf("\033[7m more? \033[m"); /* reverse on a vt100 */
while( (c=getc(cmd)) != EOF ) /* NEW: reads from tty */
{
if ( c == 'q' )
return 0;
if ( c == ' ' )
return PAGELEN;
if ( c == '\n' )
return 1;
}
return 0;
}
通过一个直观的例子感受了下Linux编程,虽然还有很多不完善的地方,但是完善本程序并不是我们的目的!