自己编写的more命令

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


你可能感兴趣的:(Stream,File,cmd,null,FP,终端)