作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/
可以根據終端大小自動調整輸出,並且修正了上一個版本的一些小bug,更加貼近現在Linux用的More。
/** =====================================================================================** Filename: more02.c** Description: A User Version of Command more** Version: 2.0* Created: 12/03/2008 06:36:56 PM* Revision: none* Compiler: gcc** Author: Futuredaemon (BUPT), futuredaemon@gmail.com* Company: BUPT_UNITED** =====================================================================================*/#include #include #include #include #include #define LINELEN 512 /*The length of Line to be printed */void do_more(FILE *);int see_more(FILE *);void noneprint(int); /* To control the terminal echo */static void sig_winch(int);static void pr_winsize(int);struct winsize size;int main ( int argc, char *argv[] ){FILE *fp; /* File Descriptor */if(signal(SIGWINCH,sig_winch)==SIG_ERR)perror("Signal Error");pr_winsize(1);if ( argc ==1 ) /* If no files exist,use the keyboard */do_more(stdin); /* Through this method,a program may support pipe '|' */elsewhile(--argc)if((fp=fopen(*++argv,"r"))!=NULL){do_more(fp);fclose(fp);}elseexit(1);return EXIT_SUCCESS;} /* ---------- end of function main ---------- */void do_more(FILE *fp){char line[LINELEN];int num_of_lines=0;int reply;FILE *fp_tty;fp_tty = fopen( "/dev/tty" , "r");if (fp_tty==NULL)exit(1);while(fgets( line,LINELEN,fp)){if( num_of_lines == (size.ws_row-2)){reply = see_more(fp_tty);noneprint(0);if( reply == 0)break;num_of_lines-=reply;}if( fputs (line,stdout)==EOF)exit(1);num_of_lines++;}}int see_more(FILE *cmd){int c;system ("stty -F /dev/tty cbreak");/*開啟/dev/tty作為輸入終端,並且控制屬性為不需要斷行符號*/printf("/033[7m more? /033[m");noneprint(1);while((c=getc(cmd))!=EOF){if(c == 'q'){printf("/n");return 0;} if(c == ' '){//printf("/033[2J"); printf("/n");return size.ws_row;}if(c == '/n'){printf("/33[7D/33[K"); return 1;}}system ("stty -F /dev/tty -cbreak");/*恢複終端屬性為需要斷行符號*/return 0;}void noneprint(int flag){struct termios init_setting;struct termios pend_setting;if (tcgetattr(1, &init_setting) < 0){perror("Getting the attribute Error!");exit (1);}pend_setting = init_setting;if(flag==1)pend_setting.c_lflag &= ~ECHO;elsepend_setting.c_lflag |= ECHO;tcsetattr (1, TCSANOW, &pend_setting);}static void pr_winsize(int fd){if(ioctl(fd,TIOCGWINSZ, (char *)&size)<0)perror("TIOCGWINSZ Error!");}static void sig_winch(int signo){pr_winsize(1);}