【Linux开发习作】more命令的编写(2)

 作者: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 '|' */
else
while(--argc)
if((fp=fopen(*++argv,"r"))!=NULL)
{
do_more(fp);
fclose(fp);
}
else
exit(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;
else
pend_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);
} 
posted @ 2012-01-13 11:20  gnuhpc  阅读(768)  评论(0编辑  收藏  举报