好久没有C语言编程了,最近看了下linux编程实践这本书,就将书上的程序练习下,下面是简单实现命令more的代码,如回车查看下一行,空格查看下一页,q退出,不完善的地方请指出。编译后,在linux命令行输入 ./progrom(编译后的程序) filename(要查看的文件),即可查看文件内容。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<termios.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define PAGELEN 24
#define LINELEN 512
void do_more(FILE *);
int see_more(FILE *, double);
off_t get_file_size(int);
int get_term_size();
int line_size;
int main(int argc, char **argv)
{
line_size = get_term_size();
FILE *fp;
if(argc == 1)
do_more(stdin);
while(--argc)
{
if((fp = fopen(*++argv, "r")) != NULL)
{
do_more(fp);
fclose(fp);
}
else
exit(1);
}
return 0;
}
int get_term_size()
{
struct winsize sz;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &sz);
line_size = sz.ws_row;
return line_size;
}
off_t get_file_size(int fd)
{
struct stat file_info;
off_t file_size;
if(fstat(fd, &file_info) == -1)
exit(1);
file_size = file_info.st_size;
return file_size;
}
void do_more(FILE *fp)
{
char line[LINELEN];
memset(line, 0, LINELEN);
int num_of_lines = 0, reply, fd, file_no;
double percent;
off_t file_size, total_size = 0;
FILE *fp_tty;
if((fp_tty = fopen("/dev/tty", "r")) == NULL)
exit(1);
//get file descriptor form file stream
fd = fileno(fp);
file_no = fileno(fp_tty);
//get file size according the fd
file_size = get_file_size(fd);
//set the termios to disable the character echo function
struct termios new_setting, init_setting;
if(tcgetattr(file_no, &init_setting) == -1)
exit(1);
new_setting = init_setting;
new_setting.c_lflag &= ~(ECHO | ICANON);
tcsetattr(file_no, TCSANOW, &new_setting);
while(fgets(line, LINELEN, fp))
{
total_size += strlen(line);
percent = (double)total_size / file_size * 100;
if(num_of_lines == PAGELEN)
{
reply = see_more(fp_tty, percent);
printf("\33[13D");
printf("\33[K");
if(reply == 0)
break;
num_of_lines -= reply;
}
if(fputs(line, stdout) == EOF)
exit(1);
num_of_lines++;
}
//set the default buffer and terminal setting
tcsetattr(file_no, TCSANOW, &init_setting);
}
int see_more(FILE *fp, double percent)
{
int c;
printf("\033[7m--More--(%%%03.0f%%)\033[0m", percent);
while((c = getc(fp)) != EOF)
{
if(c == ' ')
return PAGELEN;
if(c == '\n')
return 1;
if(c == 'q')
return 0;
}
return 0;
}