/* 重定向方面存在缺憾(重定向后没有调试完成) 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 }