2005 年 4 月 @ blogchina

2005 年 4 月

装了个realvncvncviewer切换全屏模式要替换了,学了一点 sed郁闷的依赖规则makedepend

装了个realvnc

日有所得 2005-04-05 13:55:18

安装:

tar xzvf vnc-4_1_1-x86_linux.tar.gz
cd vnc-4_1_1-x86_linux
./vncinstall ~/bin ~/man

配置:

把 ~/bin 加到 PATH 中
~/bin/vncpasswd 设置密码
vi ~/bin/vncserver 改分辨率
~/bin/vncserver 启动

登陆:

free 版本是不加密的,于是配合 SSH 端口转发来用,windows 上用 vncviewer 连接 localhost:5901 登陆嗯, 不错,这下某某人的 Q 就可以 7x24 小时挂着了。老庞新换的 ADSL 还比较快。只是缺省带的 twm 窗口管理器实在太难用了,于是再装一个 fluxbox,安装及其简单:

./configure --prefix=$HOME && make && make install
这种就相当于 windows 下装软件的一路点鼠标了。装好之后改 vncserver 把 twm 换成 fluxbox(得先删除 ~/.vnc/xstartup)。

vncviewer切换全屏模式

日有所得 2005-04-08 10:01:53

换到全屏模式换不回来了,还好 ctrl_alt_del 能弹出任务栏。
google 了一通,才知道热键是 F8


远程调试 iptables 又犯错了

日有所得 2005-04-08 16:16:02

唉,太鲁莽了,第一次出错搞得自己连不上了,还好那边控制台有人,清空规则之后长了个心眼,先写个清空规则的脚本:

#!/bin/sh
# cleanfw
/sbin/iptables -P INPUT ACCEPT
/sbin/iptables -P OUTPUT ACCEPT
/sbin/iptables -F

改完规则运行之前先把清空的脚本准备着,两分钟之后运行:

sleep 120 && sh cleanfw &

试了一下效果不错。可惜实际用的时候写成了

sleep 120 & sh cleanfw &
少写了一个 &符号,当时提示进程退出的信息也没留意,以为是上次试验时候的后台进程退出。不凑巧,这次规则还有问题,结果自己再次断线......,我真是猪脑袋:-(

想来 sleep 120 && sh cleanfw & 这样也不安全,万一 sleep
120 失败(例如收到某种信号?)cleanfw 就不会执行了,最安全的还是:

(sleep 120; sh cleanfw) &
吃了亏下次就要记牢了。


要替换了,学了一点 sed

日有所得 2005-04-11 15:39:00

要对 openssl 代码施行大规模的字符串替换了,其中有个任务,要把

#include <openssl/xxx.h>
这样替换成
#include "xxx.h"
grep 了一下,情况还比较复杂,有各种各样的 include:
#include <stdio.h>
#include "cryptlib.h"
#include<openssl/conf.h>
#include <openssl/x509v3.h>
#include <openssl/x509.h>
#include <openssl/x509.h> /* comment */
#include "openssl/x509.h"
#include "openssl/x509.h"
#include "openssl/x509.h"
文件太多,非 sed 不可了,学了一会总算能完成任务了。

sed 简单教程(From IBM DeveloperWorks):

part 1part 2part 3
完成上面替换的 sed 语句是:
sed -e 's|[<"]openssl/\(.*\)[>"]|"\1"|g' foo.c
s      是替换命令
| 为自定义分隔符
[<"] 匹配 < 和 " 两个字符
[>"] 匹配 > 和 " 两个字符
\(.*\) 定义了一个区域,随后的 \1 引用这个区域
这个命令将 <openssl/xxx.h> 替换为 "xxx.h"
同时也能将 "openssl/xxx.h" 替换为 "xxx.h"

多个替换任务:用

$ cat > my.sed
{
s/unsigned char/uint8/g
s/unsigned int/uint32/g
s/unsigned short/uint16/g
}
^D
$ sed -f my.sed foo > bar

郁闷的依赖规则

日有所得 2005-04-14 15:40:58

lib: $(LIB_OBJS) 
$(AR) $(LIB) $(LIB_OBJS)
$(RANLIB) $(LIB) || echo Never mind.
发现每次 make lib 都会 ar 一遍,依赖规则没有用了。折腾了好久才想过来原
因是始终不会有一个叫 lib 的文件产生(它是伪目标),改成让 lib 目标依赖
于具体的文件 $(LIB) ,依赖规则就能生效了:
lib: $(LIB)

$(LIB): $(LIB_OBJS)
$(AR) $(LIB) $(LIB_OBJS)
$(RANLIB) $(LIB) || echo Never mind.
容易忽略的细节。

makedepend

日有所得 2005-04-18 21:39:59

depend:
makedepend -Y -- $(CFLAGS) -- $(SOURCES)

用 -Y 避免搜索 /usr/include,这样不会产生类似 foo.c: /usr/include/stdio.h这样浪费编译时间的规则,但同时也会报成堆的找不到头文件的错误。如果重定向
stderr,又担心漏掉有用的信息,唉,难办啊,大概只有改它的源码了。其实在 openssl 里面也有这问题,它是自己编写的工具,不处理 /usr/include,但那个 domd 不太完善,试了一下有些情况会把 Makefile 弄成 0 字节文件 :(

May 1, 2005 at 7:59am | 0 Comments

2005 年 3 月 @ blogchina

2005 年 3 月

循序渐进替换 libcrypto.aprintf 中的 %* 格式strip 静态库openssl 静态库连接顺序关 于静态库的连接顺序不易觉察的类 型提升The Blower's Daughtergcc -MMopenssl 里的 stack API 的问题openssl ca -extfile 参数

循序渐进替换libcrypto.a

日有所得 2005-03-01 09:24:45

将编译过的 openssl-0.9.7e/apps/*.o 打包成 libappobjs.a,将 libcrypto.a 和 libappobjs.a 放入自己的目录,libssl 就用最新安装到 /usr/lib/ 中的库就行了,新改和新增的源文件编译成 .o 之后添加或者替换到 libcrypto.a 中去,链结就很简单了:

CRYPTO_OBJS = ../crypto/x509v3/ipextn.o ../crypto/x509v3/v3_lib.o               ../crypto/x509v3/v3_prn.o

lib/libcrypto.a : $(CRYPTO_OBJS)
ar r lib/libcrypto.a $^

openssl : lib/libcrypto.a lib/libappobjs.a
$(CC) -o $@ lib/libappobjs.a lib/libcrypto.a -lssl -ldl

printf 中的 %* 格式

日有所得 2005-03-01 17:17:37

今天折腾 OpenSSL 源码遇到的,manual 半天也看不懂,问 hcz 他也不知道,还是写了几行代码试了一下才搞明白:

%*                   要对应两个参数,第一个是域宽,第二个是实际要输出的数据,例如:
%*s, width, aString 表示输出字符串 aString,占 width 列
%*d, width, num 表示输出整数 num,占 width 列

举个例子:

int count = 1, indent = 4;
printf("%*sHello world, %d\n", indent, "", count);

将缩进 4 格然后输出 Hello world, 1。因为这里 "" 占四格。这个在调整对齐格式时很有用,在 openssl 的 BIO_printf 之类调用里面大量用到。

想到在华诺打工时他们的 debug_log 函数输出很漂亮,估计是用一个 indent 值来记录竖线的缩进位置,每进入一次函数就 indent++,出来前就 indent--,用的 printf 类函数可能也是要用 %*。

| function foo start
| | function bar start
| | ...
| | function bar end
| function foo end

strip 静态库

日有所得 2005-03-01 21:02:07

静态库太大了,因为弄过来的 .o 文件都是带有调试信息的,这些现在已经用不着了,也不想重新编译了,strip 一下即可由十几 M 变成几百 K,回到学校时update 也快得多。注意单纯 strip 会把所有符号都去掉了,导致不能连结,strip -d(相当于 strip --strip-debug)就可以了,还有个--strip-unneeded 应该还能更小,不懂连接过程,没有去试。可以直接对静态库进行 strip,可笑我傻乎乎把静态库解开,再 strip,再重新打包 :D

另:注意 cvs update 不会将其他地方加的目录同步,需要 cvs update -d,可加到 ~/.cvsrc 中。


openssl 静态库连接顺序

日有所得 2005-03-10 21:57:43

在 apps/ 目录下连接 openssl :

gcc -o openssl  {object files in apps/}  ../libssl.a ../libcrypto.a -ldl

libssl 一定要在 libcrypto 前面,自己连接改过的代码时,无意中把 libssl 放到 libcrypto 后面去了,结果竟然报一堆错误,折腾好久才发现这个连接顺序有玄机。而且三部分的顺序还都不能改变,玄机是什么呢?为什么顺序变了就不行?明天找人问问。


关于静态库的连接顺序

日有所得 2005-03-11 16:39:57

解决了昨天的疑问,顺序的确是至关重要的。

假设 main.c 中有 main(),依次调用 test.c 中的 test() 和 quit.c 中的 quit()。将他们都编译成 .o,再把 test.o 用 ar 打包成 libtest.a,把quit.o 打包成 libquit.a,这里为了简单,只用一个目标文件做静态库,但已经足够能说明问题了。

/* main.c */
void test();
void quit();
int main() { test(); quit(); return 0; }

/* test.c */
void test() { }

/* quit.c */
void quit() { }

先编译:

$ gcc -c main.c test.c quit.c

可以看到用目标文件的时候顺序是没有关系的,还有三种组合有兴趣自己试:

$ gcc -o main test.o quit.o main.o
$ gcc -o main quit.o test.o main.o
$ gcc -o main main.o quit.o test.o

打包:

$ ar rc libtest.a test.o
$ ar rc libquit.a quit.o

main.o 在最前面则没有问题:

$ gcc -o main main.o libtest.a libquit.a

其他情况就不行了:

$ gcc -o main libtest.a main.o libquit.a
main.o(.text+0x11): In function `main':
: undefined reference to `test'
collect2: ld returned 1 exit status

$ gcc -o main libquit.a main.o libtest.a
main.o(.text+0x16): In function `main':
: undefined reference to `quit'
collect2: ld returned 1 exit status

$ gcc -o main libquit.a libtest.a main.o
main.o(.text+0x11): In function `main':
: undefined reference to `test'
main.o(.text+0x16): In function `main':
: undefined reference to `quit'
collect2: ld returned 1 exit status

原因是 gcc 连接静态库比较奇怪(不知道为什么),已扫描过的符号表中没有谁引用过当前库中的函数的话,就直接把该函数对应的信息丢掉了,就是说,当前处理的静态库扫 描完了之后,后续的目标代码再来调用刚才库中的函数就找不到了。比如刚才第一种组合,libtest.a 扫描过之后,因为前面没有引用 test() 的,就把 test() 符号信息丢弃,之后连接到 main.o 就找不到 test()了;第二种组合类似;第三种组合 main.o 在最后,于是前面库中的 test() 和 quit() 就都找不到了。

因此昨天连接 openssl 的问题便是 libssl 引用了 libcrypto 中的函数,反之则不是。所以 libssl 一定要位于 libcrypto 前面。


不易觉察的类型提升

日有所得 2005-03-16 20:52:19

(v4range->max[i] | ~mask) != v4range->max[i]

max[i] 和 mask 都是 unsigned char,mask 为 0xff 取反时发生了类型提升,变成了一个负的 int 型整数,bitor 之后两边作为 int 来比较,条件判断意外的为真了。将 ~mask 前面再加上个 (unsigned char) 强制转换才行。要记牢。

mask &= ~(1 << j);

这里中间其实也发生了类型提升,只不过最后又截断为 unsigned char 了。


终于整出来一个切换 hlsearch 的热键了

日有所得 2005-03-17 14:52:48

终于整出来一个切换 hlsearch 的热键了

好好看了一下 vim 的帮助文件 eval.txt,学到了 if-else-endif 的表达式,弄出了一个 F8 热键来切换 hlsearch:

map <F8> :if &hls<CR>set nohls<CR>else<CR>set hls<CR>endif<CR><CR>

最后那个 <CR> 是因为命令执行完还需要敲个键。&option 这个可以访问设置的选项。又如:

if &bg == "light"
hi Comment ctermfg=6 guifg=darkcyan
else
hi Comment ctermfg=3 guifg=darkcyan
endif

另外脚本里面行末写注释时可以用 `|' 指定命令结束了,注释开始了

map <F1> I/* <ESC>A */<ESC>| " Use /* .. */ to comment current line
map <F2> ^xxx$xxx| " Clear /* .. */ comment of current line

The Blower's Daughter

胡思乱想 2005-03-20 20:17:29

(实验室又要搬家了,不知道到我们毕业时它还存不存在。老庞,保重。)

今天看了个电影《Closer(偷心)》,关于爱情,伦理,道德,不会写评论,但确实很触动,配的那首歌非常好,很搭配,很感伤,现在知道名叫 The Blower's Daughter,演唱者 Damien Rice 的嗓音很悲,但并不是个老男人,而是个爱尔兰英俊小生。这首歌这里有个链接:The Blower's Daughter

The Blower's Daughter
Artist: Damien Rice

And so it is
Just like you said it would be
Life goes easy on me
Most of the time
And so it is
The shorter story
No love, no glory
No hero in her sky

I can't take my eyes off of you
I can't take my eyes off you
I can't take my eyes off of you
I can't take my eyes off you
I can't take my eyes off you
I can't take my eyes...

And so it is
Just like you said it should be
We'll both forget the breeze
Most of the time
And so it is
The colder water
The blower's daughter
The pupil in denial

I can't take my eyes off of you
I can't take my eyes off you
I can't take my eyes off of you
I can't take my eyes off you
I can't take my eyes off you
I can't take my eyes...

Did I say that I loathe you?
Did I say that I want to
Leave it all behind?

I can't take my mind off of you
I can't take my mind off you
I can't take my mind off of you
I can't take my mind off you
I can't take my mind off you
I can't take my mind...
My mind...my mind...
'Til I find somebody new

gcc -MM

日有所得 2005-03-28 11:16:41

为了安全、省事,把 c 文件定义为依赖于所有的头文件,现在发现文件多了之后编译不相干的文件浪费了很多时间,现在知道了:

gcc -MM foo.c

这个命令能生成依赖规则,避免改一个头文件重新编译了不相干的 c 文件:

foo.o: foo.c foo.h bar.h

openssl 里的 stack API 的问题

日有所得 2005-03-28 12:34:59

sk_dup() 复制完发现释放了原来的 stack 之后新的 stack 中 data[] 指向的数据变成了垃圾。查了好久发现它的 sk_dup() 根本不复制 data[] 里面的指针指向的内存(因为根本不知道该分配多少),只是 memcpy 一下了事:

openssl-0.9.7e/crypto/stack/stack.c
103 memcpy(ret->data,sk->data,sizeof(char *)*sk->num);

自己修改了一下,写了一个 sk_dup_fn() 函数,要带两个函数指针作参数,一个用于复制 data[i] 中指针指向的内存,另一个用于失败时释放,把上面这条memcpy 改成:

    for (i = 0; i < sk->num; i++) {
ret->data[i] = (*dup_fn)(sk->data[i]);
/* avoid null pointer */
if (NULL == ret->data[i]) goto err;
}

...

err:
if (ret != NULL) sk_pop_free(ret, free_fn);

(嗯,接触 openssl 之后也用上了 goto,哪个说 goto 影响可读性的,我看 openssl 里面用的都挺好,不用的话又难写又难读 :-)

函数原型:

STACK *sk_dup_fn(const STACK *sk, char* (*dup_fn)(const char *),
void (*free_fn)(void *));

注意,sk_free() 也不是随便用的,它不会释放 data[] 里面指针指向的内存,要用 sk_pop_free() 带一个附加的函数指针做参数。


openssl ca -extfile 参数

日有所得 2005-03-30 17:02:55

可以指定读取扩展的文件名和段名:

-extfile filename
-extfile filename -extensions section

如果不带 -extensions section 就取 [ default ] 段。

下面是包含典型的 CA 证书扩展和普通证书扩展对应的 ext 文件格式:

[ ca ]

# Extensions for a typical CA

# PKIX recommendation.

subjectKeyIdentifier=hash

authorityKeyIdentifier=keyid:always,issuer:always

basicConstraints = CA:true

# total blocks: 2
# block 0:
# addressFamily: IPv4, unicast
# ipAddreessChoice: NULL (inherit from issuer)
# block 1:
# addressFamily: IPv6
# ipAddreessChoice: NULL (inherit from issuer)
sbqp-ipAddrBlock = critical,DER:30:11:30:07:04:03:00:01:01:05:...

[ user ]

basicConstraints = CA:FALSE

nsComment = "OpenSSL Generated Certificate"

subjectKeyIdentifier = hash

authorityKeyIdentifier = keyid,issuer:always
# 拿新写的 ipextn-gen 生成
sbqp-ipAddrBlock = critical,DER:30:49:30:1A:04:03:00:01:01:30:...

一个完整的用法例子:

$ openssl ca -config democa.conf -days 7300 -notext \
-keyfile private/subca.key -cert subca.pem \
-extfile ipextn.ext -extensions user \
-out ipextn.pem -infiles ipextn.req

Apr 1, 2005 at 7:59am | 0 Comments

2005 年 2 月 @ blogchina

2005 年 2 月

 终于把IP地址扩展的编解码弄出来了 关于Hungarian notation 婚宴归来

终于把IP地址扩展的编解码弄出来了

日有所得 2005-02-24 10:12:54

经过一番折腾,总算把IP地址扩展的编解码弄出来了。OpenSSL的ASN.1库确实强大,任意新类型,要实现编解码的步骤是:

  1. 写一个头文件按照其 ASN.1 定义写出数据结构的定义
  2. 头文件中用一下它的 DECLARE_ASN1_FUNCTIONS 宏声明原型
  3. 写一个实现文件,用 ASN1_SEQUENCE、ASN1_CHOICE 等定义好结构的模板,都是与其 ASN.1 定义一一对应的。这里面还没有搞得太清 楚,得读一下头文件并参照一些例子
  4. 实现文件中用宏 IMPLEMENT_ASN1_FUNCTIONS 实现 new、free、d2i 和 i2d 的功能

然后便可以使用对应的i2d和d2i函数进行编解码了。

注意DECLARE_ASN1_FUNCTIONS和IMPLEMENT_ASN1_FUNCTIONS是对应的,还有一个 DECLARE_ASN1_FUNCTIONS_const和IMPLEMENT_ASN1_FUNCTIONS_const是对应的,区别是后者声明的 d2i和i2d里面有适宜的const修饰,这当然更合理。然而这里有个不大不小的问题:DECLARE_ASN1_FUNCTIONS_const漏掉 了d2i和i2d的声明,-Wall编译时就看看出来警告没有函数原型。或许可以mail给openssl开发人员。

DECLARE_ASN1_FUNCTIONS
new, free
d2i, i2d

IMPLEMENT_ASN1_FUNCTIONS
encode: d2i, i2d
alloc: new, free

DECLARE_ASN1_FUNCTIONS_const
new, free
/* 就是这里,少了一句 DECLARE_ASN1_ENCODE_FUNCTIONS_const */

IMPLEMENT_ASN1_FUNCTIONS_const
const encode: d2i, i2d
alloc: new, free

评论人:sagely Fri Feb 25 19:52:12 CST 2005 

我假设做最简单的实验

.h中只有如下:

typedef struct ASN1_TEST ASN1_TEST;
struct ASN1_TEST
{
ASN1_BIT_STRING *test;
};

DECLARE_ASN1_FUNCTIONS(ASN1_TEST)

而.c中只有如下:

ASN1_SEQUENCE(ASN1_TEST) =
{
ASN1_SIMPLE(ASN1_TEST, test, ASN1_BIT_STRING),
} ASN1_SEQUENCE_END(ASN1_TEST)

IMPLEMENT_ASN1_FUNCTIONS(ASN1_TEST)

请问:我如何测试一个BIT STRING的“011011100101110111”的编码是多少?
或者说我得到DER编码为“03 04 06 6e 5d c0"的BIT STRING是多少?

评论人:admin Fri Feb 25 21:51:05 CST 2005 

要测试DER编码为 03 04 06 6e 5d c0 的 BIT STRING的解码,需要再包一层,因为你定义的test是在结构中,要作为SEQUENCE,即,准备一个SEQUENCE 的 DER
编码用来测试。测试代码示例如下:

   unsigned char *der = "\x30\x06\x03\x04\x06\x6e\x5d\xc0";
ASN1_TEST *p;

p = d2i_ASN1_TEST(NULL, &der, 8);

懒得写printf语句,你 gcc -g 编译后,在gdb里看即可。当然VC里面更方便。d2i_ASN1_TEST 执行完后即可观察 p 的内容:

(gdb) p p->test
$3 = (struct asn1_string_st *) 0x8067018
(gdb) p *p->test
$4 = {length = 3, type = 3, data = 0x8067030 "n]à", flags = 14}
(gdb) x/3xb p->test->data
0x8067030: 0x6e 0x5d 0xc0
(gdb)

对了,那个const的问题还是因为你发的短消息我才发现的。

评论人:sagely Sat Feb 26 09:00:11 CST 2005 

昨天我也申请了一个blog,我看你这里讨论linux和C语言比较多,很值得我经常来来呀.我的地址是sagely.blogchina.com

评论人:匿名网友 Sat Feb 26 18:56:36 CST 2005 

char *der = "\x30\x06\x03\x04\x06\x6e\x5d\xc0";
ASN1_TEST *p;
p = d2i_ASN1_TEST(NULL,(unsigned char **)&der, 8);
printf("%2x\n",p->test->data);

得到的结果好象是882bd8.
然后我把char *der中的数值随便改变了一下,可是输出的还是882bd8,不知道为什么。

评论人:admin Sun Feb 27 20:23:59 CST 2005 

你打印出来的是地址的值。正确的做法是:

for (i = 0; i < test->length; i++)
printf("%02x ", p->test->data[i]);

评论人:sagely Tue Mar 01 18:12:14 CST 2005 http://sagely.blogchina.com

哦,呵呵,对呀,p->test->data只是一个地址而已.

以后要要向你多请教C语言的基础呀.

评论人:sagely Tue Mar 01 18:13:25 CST 2005 

哎,我写油箱写习惯了,居然把我的blog地址都写错了.真是糊涂拉.

评论人:admin Tue Mar 01 20:07:02 CST 2005 

不要谦虚,互相学习吧,我看你写的倒是很高深啊


关于Hungarian notation

日有所得 2005-02-25 22:24:56

adjHungarian nounNotation verbIs advReally advFriggin adjAnnoying

来自一个关于 Hungarian notation 的争论,很有意思:

http://www.sitepoint.com/forums/showthread.php?t=143993

个人认为对于 C 程序员来说这东西实在是不好用,虽然偶尔也能有点帮助。我看除了指针用 p 开头,二级指针用 pp 开头这两条之外,就没什么必要用了:)


婚宴归来

日有所得 2005-02-28 09:46:27

昨日参加同学liang'r'a的婚宴,去了很多多年未见的本科同学,大家喝得比较高兴,酒酣耳热之际,让新郎新娘做的节目,有几个还挺有意思,暗暗留了 心,未雨绸缪啊!

1. 用一个空酒瓶灌入合适的水,使得一根木筷子浸入、浮起之后只露出瓶口两到三毫米,要求新郎新娘合力把筷子弄出来,只需用嘴、舌头。物理博士出的题,呵呵。 新郎新娘失败了 n 次,总算弄出来了。(对策:婚宴前可勤加练习。技巧:一人往里吹气,筷子便可浮起更高,另一人抓住时机以嘴噙之)

2. 吊个苹果要新人来咬。这个就比较传统了,没什么好说的。

3. 新人轮流拍对方脸,说一句"你真好玩"、"你真好笑"之类的话,双方都不准笑,违例则罚酒。10 轮不笑方为过关。(对策:这种日子不笑很难,游戏不要做了,直接认罚得了)

4. 新郎站在椅上,新娘将一鸡蛋由新郎的一条裤管进去,用手在裤子外面将鸡蛋往上移动或滚动,从另一裤管下来为过关。新娘两次失手掉了鸡蛋(生的),还好掉在 地上才破的,第三次换成了一个小西红柿果然好弄些了,不过似乎不太容易"过桥",新娘急了,伸手进去抓了然后放到了另一个裤管,未满十八请闭眼 ^_^,旁边有人叫了:小心别抓错了哦!大家一个个乐得脸涨红了,可算是婚宴的一个高潮,因此一致鼓掌同意过关。(对策?这个很难啊,婚宴前练练吧,据说 还有用香蕉替代鸡蛋的,怕怕)

5. 蒙住新娘/新郎的眼睛,要求从一堆手中摸出对方的手。这个也比较传统,新娘做的时候一次成功,因为新郎的手实在太肥厚了,找不出可以乱真的;轮新郎做的时 候,可真不争气,居然连错三次,呵呵。(对策:给对方暗示,小心宾客也会故意给暗示,因此自己给的暗示要能区别,先商量好,忍心的话就狠狠掐一下吧,宾客 是不敢狠掐的)

6. 一张厚纸巾从面对面的新人头上方做自由落体运动,经过新人的脸之间,要求新人用嘴夹住,"接纸"谐"接子"。这个有点意思,因为一开始掌握不了纸巾的运动 规律,新郎新娘当场接吻了好几次 ^_^。(对策?又不能找陪练)

Mar 1, 2005 at 7:59am | 0 Comments

2005 年 1 月 @ blogchina

2005 年 1 月

远程调试工具?ddd凑合能用MPlayer win32 几个有用的设置Gmail, MSN……图标产生器开题答辩轻松过关: -)gdb print 时报上下文没有该符号One of GNU humorsC 中一个经典错误·数组与指针的区别gdb 中察看 macro又一个郁闷的问题 · 匿名结构

远程调试工具?

日有所得 2005-01-04 17:02:40

自己用的xp,想远程调试linux上的c程序,有啥好的工具?现在老本介绍了两个BVRDEmagic c++,前者试了一下不好 上手,文档不详细,后者还没试过,另外自己试了insight这 个gdb的gui外壳,但我用x-win32老断,干不成事。考虑装cygwin用xfree86或者干脆自己也用linux得了。


ddd凑合能用

日有所得 2005-01-05 22:16:30

insight不知怎么回事调试openssl老死菜,ddd 凑合能用,可以在命令行直接指定参数:

ddd --args ~/bin/openssl x509 -text -in ipaddr.crt

今 天的收获是对比basicConstraint和ipAddrBlock,发现缺的是对ipAddrBlock这个ASN.1对象相应的处理函 数。看了一下,basicConstraint的处理函数都在crypto/x509v3/v3_bcons.c,应该是要添加一个类似的 v3_ipaddrblk.c了。zhjun上次讲的那个自定义ASN.1对象对应的结构的文档要派上用场了。


MPlayer win32 几个有用的设置

日有所得 2005-01-09 20:49:45

这些是看片时不爽,然后google加上看手册找出的设置。



加到配置文件mplayer\mplayer\config中:

指定字幕字体和字符集

subcp=GBK

font=c:\winnt\fonts\simsun.ttc

字幕文字大小,subfont-autoscale=2 指定度量尺度是相对于影片画面的宽度,第二个指定字幕文字大小占3%,这个大小差不 多是合适的

subfont-autoscale=2

subfont-text-scale=3

即使把系统音量调到最大,影片声音还是不够大,No problem,mplayer可以对付,softvol指定使用软件调节音量,后面的max值指定最大调整范围是实际音量的百分之多少

softvol=yes

softvol-max=400


Gmail,MSN……图标产生器

信笔涂鸦 2005-01-10 14:01:08

E-Mail Icon Generator

For GMail, Hotmail, MSN, Yahoo!, AOL and many more!

http://www.nhacks.com/email/index.php


开题答辩轻松过关:-)

信笔涂鸦 2005-01-11 16:24:08

三个老师对我这背景都不熟悉,问不出什么,居然还问了个IETF是什么,问的工作量相关的我早有准备,轻松过关,哈哈。对比别人做的ppt,我的还是字有 点多,中期的时候再注意一下好了。不过我的profile模板肯定是最好看的,嘿嘿


gdb print 时报上下文没有该符号

日有所得 2005-01-14 10:01:34

(gdb) print foo
No symbol "foo" in current context.

但实际上函数中的确有这个变量。原因是使用了优化,int或指针之类的变量被放到寄存器里了,或是没有用的变量优化后不在目标代码中。去掉优 化就好了。

gdb手册里也提到了另一种办法:编译时指定用不同的格式存调试信息:

To solve such problems, either recompile without optimizations, or use
a different debug info format, if the compiler supports several such
formats. For example, GCC, the GNU C/C++ compiler usually supports the
`-gstabs' option. `-gstabs' produces debug info in a format that is
superior to formats such as COFF. You may be able to use DWARF2
(`-gdwarf-2'), which is also an effective form for debug info. See
section `Options for Debugging Your Program or GNU CC' in Using GNU
CC, for more information.

但是我试了一下 -gstabs,发现gdb进去后报找不到源码,不爽,懒得每次指定源码查找路径了,去掉-O3了事。


One of GNU humors :-)

信笔涂鸦 2005-01-14 13:14:13

There are 10 kinds of people in the world - those who understand

binary and those who don't.

From http://www.gnu.org/fun/jokes/10-kinds-of-people.html

Here is another one: http://www.gnu.org/fun/jokes/helloworld.html


C 中一个经典错误·数组与指针的区别

日有所得 2005-01-19 16:06:19

/* extn.c */
char s[] = "Hello world.";
/* main.c */
extern char *s; /* XXX */

int main()
{
s[0] = 'A';
return 0;
}
$ gcc -c main.c extn.c
$ gcc -o main main.o extn.o
$ ./main
Segmentation fault (core dumped)

这是 C 中容易犯的一个经典错误。正确的应该是在 main.c 中声明 s 为 extern char s[];

把修改前后的 main.c 分别 gcc -S 编译成汇编,一比较就清楚了:

$ diff main.s.old main.s
12,13c12
< movb $65, s

可 见:错误版本中 s 声明为指针后,执行时先要取到 s 这个符号本身的地址,从该地址处取出 s 代表的地址放到 eax 中,然后往这个地址存 'A',但是,s 在 extn.o 中作为数组存放在 .text 段中,这个符号的地址就是 extn.o 中那个数组的地址,该处存放的东西是 "Hello world.",取一个指针出来就是四个字节'H', 'e', 'l', 'l'代表的 long,在 little-endian 平台上它是 0x6c6c6548,再往这个地址存字符 'A',就 core dump 了。而在正确版本中,已经知道它是数组了,就只会往 s 这个符号本身的地址处存放了。这便是数组与指针的区别。

总结:访问指针时,先要找到指针变量本身的地址,从该地址处再取到存放的指针值,然后再对指针指向的对象进行访问,是间接访问。访问数组则是先找数组变量 符号代表的地址,对这个地址指向的对象进行访问,是直接访问。


gdb 中察看 macro

日有所得 2005-01-21 10:53:08

gcc 编译时要加参数"-gdwarf-2 -g3"。用法见 gdb 手册中的描述

常用的也就两个:

info macro macroinfo ma macro 显示宏定义和相关源文件

macro expand expressionmacro exp expression 显示宏展开的结果

macro expand-once expressionmacro exp1 expression 显示宏只展开一层的结果,这个还没实现:-(

注意:

  1. 只有 list 到了宏定义的地方才能显示宏的信息。很弱智?应该是因为宏跟上下文相关吧
  2. 还不能支持处理 # 和 ## 这两个 token。这一点倒真是很faint的,导致调试 openssl 时 macro 的功能无用武之地--太多这种东西了

又一个郁闷的问题 · 匿名结构

日有所得 2005-01-24 11:34:54

用 gdb 调试 OpenSSL 代码发现一个 ASN1_VALUE 类型的变量无法察看它的定义

(gdb) pt ptmpval
type = struct ASN1_VALUE_st {
<incomplete>
} *

察看源码只能找到下面这样一句:

typedef struct ASN1_VALUE_st ASN1_VALUE;

却找不到 ASN1_VALUE_st 的定义,ctags 没用,上一次遇到这样的问题是宏名用 ## 拼起来的,这一次,我也考虑了这种情况,用多种组合 grep,但仍是一无所获。

走投无路之下,想到,会不会本来就不存在这样的结构?察看了源码,用到这个类型的地方都是用这种指针,对它内容的引用都是在别的类型之间转换的。

这样也可以?试验了一下:

[wayman@SEND ~/tmp]$ cat tmp.c
typedef struct unknown_st UNKNOWN;

int main()
{
UNKNOWN * u;
int arr[10];

u = (UNKNOWN *)arr;

return 0;
}
[wayman@SEND ~/tmp]$ gcc -Wall tmp.c
[wayman@SEND ~/tmp]$

编译没错,出乎意料,看来我对 C 的理解还是不够深。但也证明了我找不到ASN1_VALUE_st 的定义是正常的,因为根本就不需要有一个实际的定义,程序中没有需要知道它的具体形式的地方,都是把这种指针转来转去的操作。也就是说这个 ASN1_VALUE_st 是一种没有实际定义的结构,ASN1_VALUE_st * 就相当于void *,OpenSSL中这么写只是为了让指针有意义一点,到时候是要转换为已知的某种结构的指针的。但是,可读性真的变好了吗?!不禁越发崇拜 OpenSSL 的作者了。

Feb 1, 2005 at 7:59am | 0 Comments

2004 年 12 月 @ blogchina

2004 年 12 月

  mm的口腔溃疡  带mm去看医生了  ADSL动态IP的 NAT解决方案  XP定时关机  关闭XP资源管理器zip文件夹显示  Re 松涛:关于三黄口疡平胶囊

mm的口腔溃疡

胡思乱想 2004-12-11 22:24:23

老是复发,看她痛我也心疼,唉,情绪还容易变差,惹得两个人都不开心。一直想买光华医院的叫三黄口疡平胶囊的药,可是谁知道能不能见效啊,mm说一 瓶就700太贵了。贵就贵吧,能治好就行,先买一瓶试试看吧,可我现在当务之急是要说服她去医院,得医生瞧一瞧才能买药吧!

http://www.kckfw.com 查了一下,越来越想带她去了。

东三环,坐725到小庄站下车。


带mm去看医生了

胡思乱想 2004-12-12 19:43:41

坐了一个小时的车才找到,矮矮的三层的不起眼的楼,mm一看就说,可不敢在这买药啊。其实医生看来还不错,很和蔼,讲得听来很有道理,只是那药,三 黄口疡平胶囊一个疗程是10瓶药,700块,mm不停掐我,到底还是没有买药。唉,让前面先看的那个河北来的大姐先吃了看效果吧,留了她的电话,过阵子打 电话问问情况。

mm口腔溃疡的原因:脉象细,体质弱,胃火大,肝火也不小(常发脾气嘛),脾胃不和,睡眠不好,挑食、偏食。至于缺微量元素,一般只有儿童才会有这 种原因(不过我mm看起来也象儿童啊:-)。

解决之道,除了吃他们的药之外,更重要的是自己调理,注意饮食结构,多吃蔬菜水果,少吃辛辣、油腻、过咸的食物,加强锻炼,提高免疫力。

评论人:net8866 Wed Jan 05 15:40:46 CST 2005 shihui at sunyard dot com
我也看到了光华医院的宣传广告,刚才还有一个医生给我回复le,你买了药吗?疗效怎么样啊?给我回个邮件好吗

评论人:崔文秀 Mon Feb 21 16:56:43 CST 2005 wx_828 at 126 dot com
我也想了解一下,她们也给我回复了,同样是推荐我使用此药。但会不会是在打广告呀。MM的溃疡多久了,我的要有3-4年了。如果MM用的不错,我也买,只 要能治好。


ADSL动态IP的NAT解决方案

日有所得 2004-12-20 13:27:33

keywords: adsl dynamic ip nat iptables

动机是为了自己的机器eMule能获得highID。自己的XP通过网关(Linux)上网,由于在内网,需要NAT才能获得highID,即和 Internet用户能直接相连。

由于IP是动态的,重拨之后一般IP就变了,而iptables做NAT时一定要知道IP才行。我的办法是每次拨号成功之后就自动取得ppp0的 IP地址,传递给防火墙脚本并执行一次。

1. 在iptables防火墙脚本中加个do_nat()函数(里面大写的变量在函数之前初始化)。iptables做NAT的具体命令不是这里 的重点,就不罗嗦了。

2. 再加这段代码获取IP,当IP不空(拨号成功)时调用do_nat做NAT,做成函数 自然是为了调用方便。下面的例子是针对eMule的:

3. pppoe每次连线成功时会执行/etc/ppp/ip-up(这是缺省位置),这个脚本会执行/etc/ppp/ip-up.local,按照Unix 的风格,自己加的东西还是放在 local 里吧:把防火墙脚本的启动命令添到/etc/ppp/ip-up.local。当然,这里要求防火墙脚本文件每次先清空规则再重建,避免多次执行可能带来 的问题。

在eMule中文版中,用测试端口的工具测试通过。也可以找一台外网的机器直接telnet到NAT的端口测试。


XP定时关机

日有所得 2004-12-21 14:12:00

用shutdown命令。

shutdown -f -s -t seconds

D:\>shutdown /?

用法: shutdown [-i | -l | -s | -r | -a] [-f] [-m \\computername] [-t xx] [-c "comment"] [-d up:xx:yy]
...


关闭XP资源管理器zip文件夹显示

日有所得 2004-12-23 22:40:22

regsvr32 /u zipfldr.dll

Powered by google



Re松涛:关于三黄口疡平胶囊

信笔涂鸦 2004-12-29 14:04:59

那药号称症状轻的(一年左右)可以痊愈终身不复发,是他们医院的独门解药,疗效谁知道呢?我这周一去买了,因为mm舌头又起泡了,没有办法,买了试 试看吧。花了700块买了十瓶药,只够吃一个月的,是一个疗程。每顿要吃五颗!是胶囊。刚吃两天,也看不出效果。

他们的网站你可以看一下,http://www.kckfw.com, 可以留言咨询的。如果是在北京,可以先去医院看看,三块五挂个号好好咨询一下,那个医生讲得听来还是很有道理的。

评论人:MM Sun Jan 09 21:15:11 CST 2005 
大哥,怎么没有了下文,我想知道疗效如何

评论人:admin Sun Jan 09 23:22:30 CST 2005 
目前看有点效果,前天舌尖又起泡,时间正好是复发的周期,不过这次只有很小很小一个泡,mm自己说觉得有效果

评论人:难兄难弟 Mon Jan 31 20:13:38 CST 2005 wfengyang at tom.com
老兄,能否告知有无新的进展。同病相怜之人,期待你的回复和帮助。

评论人:admin Thu Feb 17 21:37:59 CST 2005 
私下交流,以免影响他人对此药的判断,给你发信了。
评论人:小C Mon Feb 28 00:30:05 CST 2005 
最后效果怎么样啊?用了多长时间啊?700一个月啊?有点贵。先谢了。

评论人:admin Mon Feb 28 09:07:42 CST 2005 
留个mail我告诉你。
评论人:心客 Sat Mar 05 21:35:01 CST 2005 qing2010 at 21cn.com
請把情况發給我好嗎?我也一樣受此疾病折磨,請發到我郵箱,謝謝了!qing2010 at 21cn.com

Jan 1, 2005 at 7:59am | 1 Comment

2004 年 11 月 @ blogchina

2004 年 11 月

Macros in openssl source codemini openssl command line howtoCVS over SSH on different portTwo reference of pki4ipsec

Macros in openssl source code

日有所得 2004-11-23 09:30:52

你看到代码中某个地方用了一个Marco,想找它的原型,你发现ctags帮不上忙,grep -r 也一无所获,想得通怎么回事吗?

crypto/pem/pem.h

#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE"

#define IMPLEMENT_PEM_rw(name, type, str, asn1) \
IMPLEMENT_PEM_read(name, type, str, asn1) \
IMPLEMENT_PEM_write(name, type, str, asn1)

#define IMPLEMENT_PEM_read(name, type, str, asn1) \
IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
IMPLEMENT_PEM_read_fp(name, type, str, asn1)

#define IMPLEMENT_PEM_write(name, type, str, asn1)
IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
IMPLEMENT_PEM_write_fp(name, type, str, asn1)

#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u) \
{ return((type *)PEM_ASN1_read_bio((char *(*)())d2i_##asn1, str,bp, \
(char **)x,cb,u)); }
/home/wayman/src/openssl-0.9.7e/crypto/pem/pem_xaux.c:68:
IMPLEMENT_PEM_rw(X509_AUX, X509, PEM_STRING_X509_TRUSTED, X509_AUX)
Now this marco is expanded to 4 functions:
X509 * PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u)
{
return (X509 *)PEM_ASN1_read_bio((char *(*)())d2i_X509_AUX,
"TRUSTED CERTIFICATE", bp, (char **)x, cb, u);
}

...
and ``grep -r PEM_read_bio_X509_AUX '' will get nothing :-(

mini openssl command line howto

日有所得 2004-11-23 09:34:09

$Id: openssl.txt,v 1.1 2004/11/19 08:14:16 wayman Exp $

0. install openssl

tar xzvf openssl-0.9.7e.tar.gz
cd openssl-0.9.7e
./config --prefix=$HOME
make
make test
make install
export PATH=$HOME/bin:$PATH

1. prepare CA path structure

cd ~/ssl
mkdir FakeCA
cd FakeCA
mkdir certs
mkdir newcerts
mkdir crl
mkdir private
touch index.txt
echo 01 > serial
vi ../openssl.cnf # change demoCA, policy, filename of key and root cert
# note: you can use ./demoCA of course ...

2. create key and root cert

openssl genrsa -out private/ca.key -des3 2048
openssl req -new -x509 -days 3650 -out ca.crt -key private/ca.key -notext

3. sign sub ca cert

cd ~/tmp
openssl req -new -keyout ca2.key -out ca2.req -days 3650
openssl ca -days 3650 -notext -extensions v3_ca -out ca2.crt -infiles ca2.req
rm ca2.req

4. use sub ca key to sign web server cert

openssl req -new -keyout waking.key -out waking.req -days 3650
openssl ca -days 3650 -notext -keyfile ca2.key -cert ca2.crt -out waking.crt
-infiles waking.req
rm waking.req
#now waking.key and waking.crt can be use in apache

other tips ============

o test cert use s_server

openssl s_server -accept 8443 -key my.key -cert my.crt -www
use browser to access https://server:8443

o test https web site use s_client (retrive remote cert)

openssl s_client -connect host:port

o revoke

openssl ca -revoke newcerts/01.pem
openssl ca -gencrl -out crl/fakeca.crl

o password

openssl passwd MySecret #generate crypt-style password, eg. used in cvs
N8eFL9uEhdHQU
openssl passwd MySecret -salt N8 #salt is the first 2 letter
N8eFL9uEhdHQU

CVS over SSH on different port

日有所得 2004-11-24 22:51:22

CVS server side

1. Create `guest' account, don't give him a normal shell!

# useradd -s /sbin/nologin guest

2. Generate public-private keys for guest account

# mkdir ~guest/.ssh
# cd ~guest/.ssh
# ssh-keygen -t dsa -f guest-on-cvsserver.key
# cat guest-on-cvsserver.key.pub >> authorized_keys
# chown -R guest:guest .
# chmod 700 .
# chmod 600 authorized_keys

CVS client side

1. Put guest-on-cvsserver.key in ~/.ssh/, and

$ chmod 700 ~/.ssh
$ chmod 400 ~/.ssh/guest-on-cvsserver.key

2. Append following lines to ~/.ssh/config

Host cvsserver
Hostname cvsserver.hostname.or.ip
Port 22222
User guest
PreferredAuthentications publickey
IdentityFile ~/.ssh/guest-on-cvsuser.key

3. Use cvs over SSH (I mean OpenSSH!)
CVS_RSH=ssh cvs -d :ext:cvsuser@cvsserver:/cvs co module_name


Two reference of pki4ipsec

日有所得 2004-11-27 20:23:30

Profiling Use of PKI in IPSEC (pki4ipsec)http://www.ietf.org/html.charters/pki4ipsec-charter.html

Requirements for an IPsec Certificate Management Profilehttp://www.ietf.org/internet-drafts/draft-bonatti-pki4ipsec-profile-reqts-01.txt

Dec 1, 2004 at 7:59am | 0 Comments

2004 年 10 月 @ blogchina

2004 年 10 月(9月的没有)

 #define变参 Some optimizing tips gcc 生成静态库和动态库的方法

#define变参

日有所得 2004-10-19 19:47:29
#define dbg(fmt, args...) fprintf(stderr, fmt, ##args)

Not ANSI C


Some optimizing tips

日有所得 2004-10-28 08:39:33

1. unrolling loops

2. reducing if-statements

e.g. if (var < v) cnt++;

can be replaced by:

cnt = cnt + (var < v);

3. use & and | instead of && and ||

e.g. if (a == 7 && b == 4)

cause a branch because condion can only be tested when the
first one is true (ANSI C)

if ((a == 7) & (b == 4))

Now both conditions can be evaluted in parallel.

4. use marcos bring less overhead than function inline


gcc 生成静态库和动态库的方法

日有所得 2004-10-29 09:00:42

总是想不起来,这次自己整理一下。

/* hello.c */#include <stdio.h>extern void hello()
{
printf("hello world.\n");
}
/* tool.c */#include <stdio.h>extern void tool()
{
printf("i am tool().\n");
}

还需要一个头文件声明导出的函数:

/* test.h */extern void hello();extern void tool();

o 生成静态库的方法

$ gcc -c hello.c
$ gcc -c tool.c
$ ar rc libtest.a hello.o tool.o
(ranlib libtest.a 可生成索引)

用 nm libtest.a 来看里面的目标文件和导出函数(带 T 标记)。

o 生成动态库的方法

$ gcc -c hello.c
$ gcc -c tool.c
$ gcc -o libtest.so -shared -fPIC hello.o tool.o

-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程需要,而不能达到真正代码段共享的目的。可用 nm libtest.so 来看里面导出的函数(带 T 标记)。

用动态库的好处是:更新了动态库之后链结它的程序不用重新编译。

o 用法

假设有个 main() 在 main.c 中:

/* main.c */#include "test.h"int main()
{
hello();
tool();return 0;
}

> 静态库:

$ gcc -c main.o
$ gcc -o main main.o libtest.a
$ ./main

> 动态库:

$ gcc -o main main.o -L. -ltest
$ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
$ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ldd main

可以看到 main 程序所链结的动态库。把 libtest.so 放到 /etc/ld.so.conf
中列出的目录下就可以不用先指定环境变量,注意先 ldconfig 刷新系统动态库的缓存

TODO: 还有一种 ld -rpath dir
这样的方法可避免设定环境变量

Nov 1, 2004 at 7:59am | 0 Comments

← Previous  1 … 23 24 25