emacs + cygwin fail

真郁闷啊,装了cygwin还没怎么好好玩过。最近因为拆机-重装系统,暂时没装linux,就想着也摸索摸索cygwin,结果上来就给我难题。。
xemacs不太会用,关键是貌似函数名什么的都变掉了,配置文件还要重新写?麻烦啊。
于是emacs有什么问题呢?
居然ctrl-c 是默认绑定到ctrl-g上面去了。。所以怎么退出emacs啊C x C c啊。
查了查资料,原来这个问题04年就有人在问了。真的没有解吗。。

cygwin’s emacs

这里转载一下内容:

>On Tue, Mar 09, 2004 at 10:46:47PM -0500, George Hester wrote:
>>I go into emacs easy enough.  I start cygwin and type emacs and there I
>>am in emacs.  The directions say to exit type C-x C-c where C is the
>>control key.  I am assuming that is the left control key.  So I hold
>>down the left control key and type x.  I get a C-x in the lower bottom
>>of the window.  I then try C-c which is holding down the left control
>>key and hitting the c key.  Nothing.  Justy a ding.  In fact I casnnot
>>exit from emacs at all.  Does anyone have a way of exiting from emacs
>>which works?  Thanks.
>
>Either set the environment variable CYGWIN=tty prior to running any
>cygwin program or run emacs under rxvt.  CTRL-C is not remappable in
>the normal cygwin console due to windows constraints.

2 more options:
1. Run emacs under the X-Windows server.
2. Use "M-x kill-emacs", which is either:
	a. Hit the key ALT-x, then type "kill-emacs", then hit the key ENTER.
	b. Hit the key ESCAPE, then hit the key x, then type "kill-emacs", then hit the key ENTER.

-Richard Campbell.

好吧,所以结果还是可以接受的。反正emacs一般也就是一直开着他了。就让他tty设定过去也无所谓吧。

<编辑>
后来又发现这个网站,给了一个更好的解决方案~~
Cygwin

Cygwin下的Emacs不能退出的问题
Xemacs就没有这个问题
 
需要在cygwin.bat里面加进:
@echo off
set CYGWIN=binmode tty ntsec   #加进这句话Emacs就能正常退出了
g:
chdir g:\cygwin\bin           #$PATH/Cygwin/bin/
bash --login -

问题解决~~
</编辑>

圆周率节转圆周

上帝啊。。。我终于复活了!(是我家CQ…|||)
本来3.14节想出了一个挺好玩的想法,想实现一下,结果准备重启进入linux的时候机器就挂了orz|||
反复重启。光驱引导不能。
是BIOS病毒吗?

已经是晚上了,等不及送修,居然真的自己动手拆起机器来了!

真可惜啊,心情太焦急了居然没有心情拍照。人生第一次推倒啊(compaq娘|||

拆掉屏幕,拉下键盘,掀开后盖。取下风扇,拿掉散热片。CPU和显卡明晃晃地立着。为什么就是找不到CMOS线啊。。。
找到了个形似开关的东西按了几按。这样好像跟重置BIOS毫不相关吧。。
拆得这么零碎,真的还能组回去吗?组回去真的还能用吗?

还好。网上的攻略很给力……除了多出几个螺丝不知往哪里按,基本上都装回去了。尽管。。尽管原本的开机重启的问题完全没有解决。。
本来绝望的心冷静下来反而清醒了。重启或许只是硬盘本身的故障呢?光盘引导不能或许只是因为光盘没有读出来,所以又默认从硬盘引导,然后又重启了而已呢?
拔掉硬盘后再试光盘引导,果然不是反复重启的症状了。所以。。所以到头来无非是。。光盘太脏这个缘故吗。。多吐两口涂抹擦擦干净。。居然真的就进了live CD了。。。

转了一大圈,又回到原地。果然只不过是硬盘分区表损坏而已,什么BIOS病毒的。。都是自己胡诌啊胡诌。
或许。。或许我只是想找个借口拆拆本子吧。从来还没拆过本本的人。。

可惜这不明情况的分区表故障,貌似导致了grub无法识别硬盘,所以最后还是不得不重装系统了。。
所以本来圆周率节那个挺好的想法,只好留到其他节日再做咯。。。|||

啊哈哈凑足30小时无睡眠时间,好啦洗澡爬床~~

linux内核学习 – C风格的面向对象

linux内核大量使用面向对象的编码风格。然而linux内核是完全使用C写就。学习他们如何使用C模拟面向对象机制很有意思。这种做法很可能被人贬为扯淡,但是的确使用C模拟面向对象机制,使得程序员对类型构造/析构,拷贝/赋值等操作有了绝对的控制权,可以提高对效率的嗅觉,减少错误,同时也避免了对C++编译器各种不同类/对象实现机制的依赖。

类的多态特征是linux内核经常用到的。例如在驱动代码中常常使用函数指针来定义一组设备操作函数,从而模拟了多态的特点。


struct file_operations scull_fops = {
    .owner = THIS_MODULE,
    .llseek = scull_llseek,
    .read = scull_read,
    .write = scull_write,
    .ioctl = scull_ioctl,
    .open = scull_open,
    .release = scull_release,
};

上面的例子是Linux Device Driver中抄来的示例代码。很好地展示了file operation结构体如何使用这种机制来定义一组文件操作的方式。用这种方式,Linux很好地贯彻了所有的设备都是文件这种概念。不同的设备可以有不同的处理函数,但使用相同的接口,这样就把底层设备的差异在文件系统这一层隔离开来了。

Linux内核中也经常用到类的继承关系。这种关系使用C也很容易模拟,就是使用结构体嵌套。例如


struct scull_dev {
     struct scull_qset *data;   
     int quantum;               
     int qset;                  
     unsigned long size;    
     unsigned int access_key;  
     struct semaphore sem;     
     struct cdev cdev;      //内嵌linux内核定义的cdev结构体
};

这个例子同样来自LDD。注意在自定义的cdev字符设备结构体中包含了struct cdev cdev成员。这个成员同样是一个结构体,由内核定义,是字符设备描述符。使用这种方式,可以一定程度模拟C++的继承机制,当然有他的局限,例如他不能如同在C++中一样直接引用cdev的成员,而必须通过scull_dev.cdev来引用。

另一方面,这种方式也无法通过“基类”,即cdev的指针,访问“子类”,即scull_dev的成员。精彩的部分来了,linux通过一组宏,巧妙的实现了这一点。在文件处理的函数中,入参会给入inode指针,从这个指针可获得其cdev成员。如何从这个cdev成员获取包含它的“子类”对象,scull_dev的指针呢?

container_of(ptr, type, member)

使用这个宏,container_of(inode->i_cdev, struct scull_dev, cdev)就可获得包含cdev的scull_dev的地址。这个巧妙的宏是如何实现的呢?

#define container_of(ptr, type, member) ({ \
                const typeof( ((type *)0)->member ) *__mptr = (ptr); 
                (type *)( (char *)__mptr - offsetof(type,member) );})

这个宏首先定义一个指向结构体成员的指针__mptr = (ptr),他的类型是const typeof(...)。这里用到了C语言一个较新的关键字typeof,可以在编译期获得变量的类型。而这个类型是((type*)0)->member,这里type和member分别是宏传入的参数。这一行代码就比较清晰了。得到这个__mptr之后,将他向回移动一个offset,(char*)__mprt - offsetof(...),而这个offset恰好为member相对于type的偏移量,offsetof(type,member),则移动完毕__mptr就指向type类型的起始地址了,只需将其转换为type*类型就可以了,(type*)(...)

好了,这个宏已经看懂,神奇的地方就出在这个offsetof宏了,他是如何计算成员相对于结构体的偏移量呢?这里linux内核hacker们用了一个小小trick。

#define offsetof(s, m)   (size_t)&(((s *)0)->m)

是的,代码非常简单。其思想是,假如结构体处于0地址,获取其成员的地址。这个地址就是成员相对于结构体初始地址的偏移量了。没错0地址是不能运行时访问的,但这句代码只在编译期使用了0地址,因此是合法的。当然其实使用成员指针和结构体指针相减也可做到,但用这种方式可以减少一次运算,确保了这个宏可以在编译期求出结果。可谓是精益求精。

我说错了。即使使用减法也可以做到编译期求值,因为结构体和成员指针地址都是可以编译期得到的,常量数值计算应该可以做到编译期优化,计算完成。这种做法应该是
&((type*)0)->member - ((type*)0)
这样的代码的一个直觉性的优化,减0的话,何必还要减呢。事实上两句代码的运行时间是一样的,但这样做可以减轻编译时间。
在container_of宏中,也有一句减法计算。这个计算引用了运行时求值的__mptr,所以无法做到编译期求值。

类似这种用法,在linux内核中经常出现。深深佩服大牛们的创造力,并且深深的意识到了即使是C语言也是学无止境的。

远程解析DNS躲避DNS污染

我发现我前两天发的博nslookup-解决ssh隧道无法访问twitter很受大家的欢迎,sjw同学也说到,其实使用OpenDNS就可解决这个问题。

因为我之前尝试过OpenDNS仍然发现问题,才出此下策的,因此专门去研究了一下,发现其实@williamlong有一篇老文,早就可以解决这个问题。OpenDNS不能解决DNS解析错误,而这文的解决方案,比我提出的要简单许多,就是使用远程解析DNS。

关于如何使用远程DNS解析,月光博客提到了firefox的启动参数。至于我所喜爱的chrome,网上的讨论也很多。具体的方法就是使用sock代理和switchy扩展的自动模式(auto switch mode)。当然,正如sjw同学提到的,使用vpn的同学直接使用墙外dns就可以了,有些客户端似乎是默认使用本地dns,可能是需要配置一下的。因为我不用vpn所以不是很了解。
我找到的比较好的参考是这篇chrome 扩展: Proxy Switchy!之图解使用方法和这篇在 Chrome + Switchy 下使用 AutoProxy gfwList PAC这篇正是来自autoproxy的博,下面回复讨论很多,很值得看。而这一篇关于 SOCKS 代理的远端 DNS 解析的讨论则可让我们把一些原理搞得更清楚。

chrome app store in new tab

Recently Google began to put app store things into chrome new tab page.

I found this on ubuntu with chromium 9.0.597.94 (73967).

It’s pretty cool and I tried a lot of things, like my favorite  flash game Canabalt, google Talk and so on.

The apps web page is also become more attractive, comparing with chrome extension web pages.

I tried google talk app the first time I saw it, and it turned to be Chrome OS only… Google is definitely working on making Chrome OS special, and unfortunately, exclusive. I really don’t like the way as Apple goes, but on the other hand, the open minded Android market is not such a success as well.

php nslookup 安全性检查

昨天做了这个http://pp.hawkwithwind.net/nslookup.php之后,忽然想到,其实完全可以做一个网页版的命令行,远程控制服务器,其实相当于网页版的ssh了。转念一想,不行,因为那样的话安全性没有保障,等于是把自家后院交给人家随意践踏了。

想到这里,忽然意识到,自己写的那个nslookup.php,其实只是简单的把用户提交的字符串前面加一个"nslookup "然后给系统调用,这样其实是非常危险的。例如我尝试在输入框里面输入twitter.com & whoami,结果除了返回twitter的ip信息,也返回了我在服务器上的用户名。这种可怕的缺陷给黑客太多可趁之机了。立刻修改。

我目前的想法是,字符串里包含后台符号 &,分号 ; , 管道符号 | , 重定向符号 > 或者选项符号 – 的时候,就拒绝服务。另外也禁止了字符串内部的空格或者换行符。这样的话,似乎就没有其他的问题了吧?我在这方面不是很熟,估计还会有问题,欢迎黑客及爱好者们赐教~

后来又发现了好多其他可能的符号会导致插入语句。。现在我禁止的符号更多了。。包括大括号{}还有问号冒号等等都被我禁掉了。。

另外,虽然只有几行代码,我把他放到了github上,希望能给大家提供一点帮助~
https://github.com/hawkwithwind/phpNetTools

nslookup – 解决ssh隧道无法访问twitter

我最近发现,即使使用ssh隧道,有时也会无法访问twitter, facebook等知名网站,但查询自己的ip地址已经在美国,并且另外一些被墙的网站如blogger等,却又能访问。想到应该是最近GFW的新动作造成的。网上查了查,在google的实时搜索中发现了很多关于最近GFW升级的传闻,很多人抱怨自己ssh或者VPN开始不好用了。

只要能够连上ssh或者vpn,GFW就无法真正对我们造成威胁。仍然无法访问这些网站,极有可能是dns污染造成的。只要能获取到正确的ip地址,就可以访问到对应的网站。然而,网上搜索到的ip地址,往往比较旧,可能已经失效。想要得到最新最正确的dns对应ip地址,最好的方法是通过墙外的主机ping得的ip地址。将其写入自己的hosts文件就好了。

为此,我自己写了一个小小的服务,用美国主机nslookup你想问的域名,给出对应的ip。
pp.hawkwithwind.net/nslookup.php
我还提供了他的api版本,只要使用如下格式的命令,就可得到 json 格式的返回包:
pp.hawkwithwind.net/nslookup.php?server=google.com
返回形式如下
['74.125.224.176', '74.125.224.177', '74.125.224.178', '74.125.224.179', '74.125.224.180']
相信还是蛮有用的。至于原理,非常简单,用php的exec函数执行nslookup命令就可以了。