fcitx-diagnose 是 fcitx 输入法的非常优秀的诊断脚本。当输出到终端时,fcitx-diagnose 会给输出加上易于区分不同类型的消息的彩色高亮。可是,当用户把输出重定向到文件以便让其他人帮助查看时,这些高亮就没了。fcitx-diagnose 的输出很长,但如果通过管道给 less 查看的看,这些彩色也会消失。
要是 fcitx-diagnose 支持--color=always这样的选项就好了。可是 yyc 说他懒得写。getopt我只在 C 里用过,好麻烦的,所以我也懒得写。于是,我还是用我的 ptyless 好了。后来又想到,用于改变 I/O 缓冲方式的 unbuffer 和 stdbuf 应该也可以。测试结果表明,只有 unbuffer 可行,因为它是和 ptyless 一样使用伪终端的。stdbuf 则是使用 LD_PRELOAD 载入一个动态链接库的方式来设置缓冲区。
不过,既然 stdbuf 用 LD_PRELOAD 来设置缓冲区,我何不来用相同的办法改变isatty()函数的返回值呢?同时,我也学学 stdbuf,试了下__attribute__ ((constructor))指令。
#include<stdarg.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<dlfcn.h>
static int (*orig_isatty)(int) = 0;
int isatty(int fd){
if(fd == 1){
return 1;
}
return orig_isatty(fd);
}
void die(char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
fflush(stderr);
exit(-1);
}
__attribute__ ((constructor)) static void setup(void) {
void *libhdl;
char *dlerr;
if (!(libhdl=dlopen("libc.so.6", RTLD_LAZY)))
die("Failed to patch library calls: %s", dlerror());
orig_isatty = dlsym(libhdl, "isatty");
if ((dlerr=dlerror()) != NULL)
die("Failed to patch isatty() library call: %s", dlerr);
}
然后,像 stdbuf、proxychains 那样做了个包装,不用自己手动设置 LD_PRELOAD 环境变量了。这也是我第一次使用 CMake,比 GNU 的 autotools 那套简单多了 :-)
使用方法很简单:
