最近在写toolbox,增加了more命令,发现网上很多人写的more都有bug,我来吧我的发上来,可以通过管道,< ,以及标准文件进行读取,回头还会加入getopt的支持。
#include
#include
#include
#include
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include
#include </p>
static struct winsize winsz;
static struct termios old, new;
static int use_tty, use_pipe;
static int page_col, page_row;
static char filename[1024];
/* Initialize new terminal i/o settings */
static void initTermios(int echo)
{
tcgetattr(0, &old); /* grab old terminal i/o settings */
new = old; /* make new settings same as old settings */
new.c_iflag &= ~ICRNL; /* Translate carriage return to newline on input (unless IGNCR is set) */
new.c_lflag &= ~ICANON; /* disable buffered i/o */
new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */
}
/* Restore old terminal i/o settings */
static void resetTermios(void)
{
tcsetattr(0, TCSANOW, &old);
}
/* Read 1 character - echo defines echo mode */
static char getch_(int echo)
{
char ch;
initTermios(echo);
ch = getchar();
resetTermios();
return ch;
}
/* Read 1 character without echo */
static char getch(void)
{
return getch_(0);
}
/* Read 1 character with echo */
static char getche(void)
{
return getch_(1);
}
static int usage(char *name) {
fprintf(stdout, "Usage:\n"
"%s [options] ...\n", name);
return 1;
}</p>
static int read_more() {
switch(getch()) {
case 13:
page_row++;
/* Clean the current line */
printf("\x1b[1K");
/* Set the cursor to the start of the line */
printf("\x1b[%d;0H",winsz.ws_row);
break;
case 32:
page_row = winsz.ws_row;
/* Clean the current line */
printf("\x1b[1K");
/* Set the cursor to the start of the line */
printf("\x1b[%d;0H",winsz.ws_row);
break;
default:
/* Clean the current line */
printf("\x1b[1K");
/* Set the cursor to the start of the line */
printf("\x1b[%d;0H",winsz.ws_row);
break;
}
return 0;
}
static int read_file(FILE *fp, int use_pipe) {
char line[page_col];
int seek;
if(!use_pipe) {
struct stat filestat;
lstat(filename, &filestat);
while(fgets(line, page_col, fp) != NULL) {
if(page_row != 1) {
fprintf(stdout,"%s",line);
//fflush(stdout);
page_row--;
} else {
seek=ftell(fp);
int percent = ((float)seek/(float)filestat.st_size) * 100;
fprintf(stdout, "--More-- (%%%d)",percent);
read_more();
}
}
} else {
char **buff;
int i = 1;
char line[page_col];
/* First alloc */
buff = (char **)malloc(sizeof(char *));
while(fgets(line, page_col, fp) != NULL) {
/* Alloc buff[i-1] */
buff[i-1] = (char *)malloc(sizeof(char)*page_col+1);
strcpy(buff[i-1], line);
i++;
/* realloc */
buff = (char **)realloc(buff, sizeof(char *)*i);
//printf("%s",buff[i-1]);
}
if(close(STDIN_FILENO)) {
perror("STDIN_FILENO close faild");
return errno;
}
if((fp = fopen("/dev/tty","r")) == NULL) {
perror("Error open TTY");
return errno;
}
int line_num = i -1;
int l = 0;
for(i-- ;i > 0; i--) {
if(page_row != 1) {
fprintf(stdout,"%s",buff[l]);
//fflush(stdout);
page_row--;
} else {
int percent = ((float)l/(float)line_num) * 100;
fprintf(stdout, "--More-- (%%%d)",percent);
read_more();
}
l++;
}
/* Free memory */
for(i=0;i<=line_num;i++) {
free(buff[i]);
}
free(buff);
}
if(fclose(fp) != 0) {
perror("Error to close");
return errno;
}
return 0;
}
int more_main(int argc, char *argv[]) {
use_tty = isatty(STDOUT_FILENO);
int use_pipe = !isatty(STDIN_FILENO);
if(use_tty) {
/*
* Get windows size
*
* struct winsize {
* unsigned short ws_row;
* unsigned short ws_col;
* unsigned short ws_xpixel;
* unsigned short ws_ypixel;
*};
*/
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsz) == -1) {
return errno;
}
page_row = winsz.ws_row;
page_col = winsz.ws_col;
} else {
usage(argv[0]);
return 1;
}
/*
* Now only support open a file or pipe
* So I dont use get opt now.
*/
FILE *fp;
if(argc != 1) {
strcpy(filename, argv[1]);
if((fp = fopen(filename,"r")) == NULL) {
perror("Error open file");
return errno;
}
}else if(argc == 1 && !use_pipe) {
usage(argv[0]);
return 1;
} else if(use_pipe) {
if((fp = fdopen(STDIN_FILENO,"r")) == NULL) {
perror("Error open STDIN_FILENO");
return errno;
}
}
read_file(fp, use_pipe);
return 0;
}
</pre>
在 Ubuntu/Debian 下有一个问题经常会困扰大家,就是运行 apt-get update 是出现 Hash校验和不符(Hash Sum mismatch)的提示
This is a known issue, and is exacerbated for clients behind proxy caches. Some large organisations and ISPs (especially in remote parts of the world) have transparent caches of which you may not be aware.</p>
The fundamental issue is that the apt repository format is subject to race conditions when a mirror is updated. This problem particularly affects repositories that change rapidly, such as the development release.
You can track progress on the fix for this in this bug (please mark yourself as "affects me too" in the bug) and this blueprint. But be aware that it is a complex issue and may take more than one release to resolve.
shareimprove this answer
answered Jul 5 '12 at 22:21</pre>
大意是:你所使用的网络供应商,有些会设置一些透明缓存,以增加网络内部速度,减少出口的流量,你获取的某些文件不是源服务器上的真正文件,是从缓存中获取的,当缓存中获取的一些校验信息跟源中不一致的时候,自然提示校验失败,无法继续更新。
此问题实际上跟apt软件仓库的格式设计有关。新发布的版本的软件仓库更新比较频繁,按道理缓存中的文件应该同步更新,可惜因为多个镜像站点的有快慢,因此造成了缓存无法保证一致性。
当网络提供商足够有实力,不设至透明缓存时,这个问题是不存在的。这就是为什么有些人反馈使用无线上网卡(移动、联通的3g网络)就一切OK,一单换回长城宽带、或者宽带通就不行了。
以上就是问题出现的真正原因
解决方法呢,就是为APT 配置http sever或者使用apt-fast</h3>
这里推荐大家使用apt-fast</p>
Apt-fast
Apt-fast 是一款替代 apt-get 提升下载速度的软件,安装软件时,通过增加线程使下载软件速度加快。 Apt-fast 已经更新到1.6.4版本,引入配置“对话框”,在其安装过程中,一步步对话框选择设置,每个用户的配置选项,从而改善和清晰化Apt-fast的初始配置过程。</p>
命令
如何安装 apt-fast ? 添加官方 PPA 源(支持ubuntu Lucid, Natty, Oneiric, Precise, Quantal),打开终端,输入以下命令:
Ubuntu 11.04~13.10 (out of date)
sudo apt-get install axel aria2
sudo apt-add-repository ppa:apt-fast/stable
sudo apt-get update
sudo apt-get install apt-fast
Ubuntu 14.04 and later versions
sudo add-apt-repository ppa:saiarcot895/myppa
sudo apt-get update
sudo apt-get -y install apt-fast
使用
安装之后使用方法和apt-get使用一样. 更新源列表
sudo apt-fast update
安装Chromium浏览器
sudo apt-fast install chromium-browser
更新系统
sudo apt-fast upgrade</pre>
获取最新的apt-fast安装方法:http://wiki.ubuntu.org.cn/Apt-fast</a></p>
You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve --watch, which launches a web server and auto-regenerates your site when a file is updated.