/*
重定向方面存在缺憾(重定向后没有调试完成)
stdin时非重定向可用read和write屏蔽部分部分
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>//lstat
#include <sys/stat.h> //lstat
#include<termios.h>
#define PAGELEN 24
#define LINELEN 1024
//#define BUFFSIZE 8192
void settermattr(); //设置终端属性
void do_more(FILE *);
int see_more(FILE *);
int filesize; //文件的大小
int readsize; //已经显示的内容长度
struct termios ts,ots; //终端属性
int main(int argc,char *argv[])
{
FILE *fp;
struct stat buf;
settermattr();
if(argc==1) //eg: mymore < mymore.c ->argc=1 未计算filesize,filesize为0
{ do_more(stdin); }
else{
while(--argc)
{
if(lstat(*++argv,&buf)<0)
{
fprintf(stderr,"ERROR: lstat error\n");
}
else{
filesize+=buf.st_size; //输入重定向后,标准输入< 后的参数不可获得
if((fp = fopen(*argv,"r"))!=NULL)
{
fprintf(stdout,"............................\n");
fprintf(stdout,"....%20s....\n",*argv);
fprintf(stdout,"............................\n");
do_more(fp);
fclose(fp);
}
else{
fprintf(stderr,"ERROR: cannot open file: %s\n",*argv);
exit(1);
}
}
}
}
tcsetattr(STDIN_FILENO,TCSANOW,&ots);//将修改后的终端属性复原,TCSANOW表示修改立即生效
return 0;
}
void do_more(FILE * fp)
{
char line[LINELEN];
int num_of_lines = 0;
int see_more(FILE *);
int replay;
// int n;
// char buf[BUFFSIZE];
FILE *fp_tty;
fp_tty = fopen( "/dev/tty", "r" ); /* NEW: cmd stream */
if ( fp_tty == NULL ) /* if open fails */
{
fprintf(stderr,"ERROR: open /dev/tty fails\n");
exit(1);
}
/*
* 当用重定向符定向标准输入时,不能分页显示,一下全部显示出来。故屏掉
*
if( fp ==stdin) //将标准输入写到标准输出,read write 包含在unistd.h头文件中
{
while ( (n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) //read返回读得的字节数,用作要写的字节数,当达到末尾时,read返回0,发生错误返回-1
if (write(STDOUT_FILENO, buf, n) != n)
{ fprintf(stderr,"ERROR: write error!\n");
exit(1);
}
if(n<0){
fprintf(stderr,"ERROR: read error!\n");
exit(1);
}
}else
{
*
*
*
*/
while(fgets(line,LINELEN,fp))
{
readsize+=strlen(line);
if(num_of_lines == PAGELEN)
{
replay = see_more(fp_tty); /* NEW: pass FILE * */
if(replay==0)
{ tcsetattr(STDIN_FILENO,TCSANOW,&ots); //TCSANOW表示修改立即生效
break;
}
num_of_lines-=replay;
}
if(fputs(line,stdout)==EOF)
{
tcsetattr(STDIN_FILENO,TCSANOW,&ots); //TCSANOW表示修改立即生效
break;
}
num_of_lines++;
}
//}
}
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--(%2.0f%%)\033[m",(double)readsize/filesize*100);
//printf("\033[7m--more--(%d/%d)\033[m",readsize,filesize);
while( (c=getc(cmd)) != EOF ) /* NEW: reads from tty */
{
if ( c == 'q' ) /* q -> N */
{
printf("\033[2K\n");
return 0;
}
if ( c == ' ' ) /* ' ' => next page */
{
printf("\033[2K"); /*清除上行提示信息*/
return PAGELEN; /* how many to show */
}
if ( c == '\n' ) /* Enter key => 1 line */
{
printf("\033[2K");
return 1;
}
}
return 0;
}
void settermattr(){
tcgetattr(STDIN_FILENO,&ts); //获取终端属性
ots=ts; //备份终端属性
ts.c_lflag &= (~ECHO); //阻止回显
ts.c_lflag &= (~ICANON); //设置终端为非标准模式
ts.c_cc[VMIN]=1; //这两行当需要从终端获取字符时立即返回,不需要按回车键
ts.c_cc[VTIME]=0;
tcsetattr(STDIN_FILENO,TCSAFLUSH,&ts); //设置终端的新属性。TCSAFLUSH表示输出队列空了以后才生效,生效之前的输出队列被flush
}
自己编写的more命令
最新推荐文章于 2020-02-12 16:01:06 发布