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 那套简单多了 :-)
使用方法很简单: