晒晒我的常用软件清单(和某安全中心推荐清单无交集)

Windows软件清单

工作中我90%的时间用perforce+cygwin+Visual Studio+vi+firefox.下班后基本不碰windows.

名称 说明 频率 性质
perforce 版本控制 收费
cygwin Linux下常用工具集合 开源
7-Zip 压缩解压缩 开源
AviSynth 2.5 视频编辑 开源
BitSpirit BT下载 免费
utorrent BT下载 免费
Brother Brother打印机附赠软件,其ControlCenter3的ocr功能对我有点用.如扫描账单备份到网上 免费
CDBurnerXP 刻录 免费
CDex170b2 cd转mp3,可从网上获得cd信息后自动生成mp3文件名 开源
ditto 剪贴板管理 免费
CMake 2.6 跨平台build工具,相见恨晚 开源
CodeBlocks 跨平台的c++ IDE 开源
ColorPic 4.1 取色 免费
comicsviewe 看漫画 免费
DAEMON Tools 虚拟光驱 免费
Debugging Tools for Windows 如题 免费
Wink 录屏 免费
Dependency Walker 检查dll依赖 免费
eMule p2p下载 开源
FBReader 电子图书阅读 开源
foobar2000 音乐播放 开源
Foxit Reader PDF阅读器 免费
GhostScript pdf解析引擎 开源
GIMP 图像编辑 开源
gnuplot 数据分析,主要用于数据显示 开源
gtalk 即时通信,语音服务佳 免费
Picasa (google) 照片管理 免费
google拼音 输入法,主要特色在于可以在线同步词库,资源消耗高 免费
AVG Free 杀毒 免费
hoekey 热键 免费
ImageMagick-6.3.5 命令行图像处理 开源
InfraRecorder 刻录 开源
Inno Setup 5 打包,开发用 开源
Internet Explorer 系统自带 免费
IPMsg 局域网通信 开源
IrfanView 看图,可与total commander集成 免费
Mercurial 分布式版本控制 开源
Msn Messenger 微软的即时通信软件 免费
Microsoft Platform SDK for Windows Server 2003 R2 和Visual C++ 2005 Express结合开发win32平台软件 免费
Microsoft Visual Studio Express 2005 C++ IDE 免费
Miranda IM 集成了yahoo,icq,qq,msn,gtalk,irc,msn的即时通信 开源
Firefox 网页浏览 开源
Mozilla Thunderbird 读email,在web mail出问题时有用 开源
mtPaint mspaint的替代品,简单画图,界面费解 开源
MWSnap 截图 免费
Notepad++ 文本编辑,我用vi,给别人用 开源
LibreOffice 办公字处理,导出word到pdf.最,画组织结构图,中文教程少 开源
OpenVPN VPN 开源
Opera 网页浏览 免费
Chrome 网页浏览 免费
Pandora Recovery 恢复误删除的文件 免费
Passcape Mozilla套件密码恢复 免费
password-recovery 密码恢复 免费
PPLive 在线电视 免费
reshacker 从可执行文件中提取资源(图标) 免费
ScanSoft 买打印机附送的扫描软件,可以扫描为pdf文件 免费
sitman 复读机 共享
Skype 即时通信,语音通话 免费
SopCast 在线电视,在国外看央视效果不错:) 开源
StarDict 辞典 开源
Subversion 版本控制 开源
SumatraPDF pdf阅读器 开源
VirtualBox 虚拟机,用于模拟开发环境,或是网上银行专用的操作系统 开源
QQ 如题 免费
MiniThunder(迅雷) 下载 免费
PDF-XChange Viewer PDF阅读器(由于工作关系,我装了很多PDF阅读器) 免费
UltraVNC 远程桌面控制 开源
Subtitle Workshop 字幕调整 免费
USBOOT 1.7 使usb能够启动电脑,制作usb自启动盘时用 免费
F…gate 翻墙 开源
Vim/GVim 文本编辑 开源
Total Commander 说是世界第一的文件管理器不算过分,未注册版 共享
bblean windows shell 开源
Bridge Base Online 游戏 免费
ntemacs 文本编辑 开源
openssl 如题 开源
python2.7 一种脚本语言 开源
wtl 微软的c++ gui程序开发库 开源
wxWidgets 跨平台c++ GUI库 开源
mplayer 命令行视频播放软件 开源
autoruns 检查启动时默认启动那些软件,用于手动杀木马 免费
process explorer 检查电脑中有什么程序在运行,用于手动杀木马 免费
Everything 找文件 免费
treewalk 缓存DNS 免费

firefox插件

名称 说明 频率
adblock plus 过滤广告,支持正则表达式
del.icio.us 1.2 网络书签的插件,较老版本
downloadhelper 视频下载
Autoproxy 代理上网
Firefox sync 同步个人数据
Greasemonkey 安装了Greased Lightbox (看图)和Lookitup(资料查找)脚本
pronounce 输入单词发标准美音
firebug 最好的web开发工具
KeySnail 安装了HoK(快捷键设置)脚本代替vimperator
Autopager 自动翻页
ChatZilla IRC
ColorZilla 取色
Vacuum Palaces Improved firefox使用的sqlite数据库加速

total commander插件

名称 说明 频率
CatalogMaker.wcx 创建文件列表
CHMDir.wcx 生成chm文件
7zip.wcx 压缩解压缩7zip格式的压缩文件
UnInstTC.wfx 管理”添加/删除软件”面板
Registry 管理注册表
ex2fs.wfx 访问linux分区(只读)
sftpplug.wfx 支持sftp
imagine.wlx 看图

vim插件

名称 说明 频率
cscopemaps.vim 为vim中使用cscope(看c/c++代码工具)添加快捷键支持
LargeFile.vim 看大文件时自动优化vim
matchit.vim 跳转至匹配的符号,比如在匹配的括号见跳来跳去
NERDcommenter.vim 码(支持很多语言)添加/取消注释
taglist.vim 显示函数列表

emacs插件

我正全面转向emacs中,所使用的插件清单尚未稳定,这里列的只是固定下来的项目.

名称 说明 频率
gnus gmail,新闻组
org-mode 个人项目管理,笔记
w3m 网页浏览
eim 中文输入
elim 即时通信
elpa emacs的app store
erc irc
smart-tab auto complete everything by TAB
org2blog 写博客
rinari ruby IDE
better-registers 使用register更方便

Linux软件清单

操作系统为Arch Linux 使用频率最高的软件为git+emacs+vi+firefox+musca+bash

名称 说明 频率
emacs 任何事
vi 文本编辑
firefox 网页浏览
opera 网页浏览,当跑不动firefox时
pidgin 即时通信
rxvt-unicode Terminal
bash shell
musca 窗口管理(使用musca-mm-git)
qtcreator C++ IDE
wine win32模拟器
gappproxy 翻墙
f…gate 翻墙,需要wine
mplayer 视频播放
audacious 音频播放
amule p2p下载
rtorrent BT下载
virtualbox 虚拟机
gimp 图片编辑
git 版本控制
zathura pdf阅读

用org2blog+emacs发表博客

我有兴趣开始写博,完全是因为我开始爱上emacs,以至有人说emacs的插件org2blog使的写博客非常高效,我就想试试.

我(计划)把所有的文章都放在一个org文件里(BTW,我爱死org-mode了,它本来是做计划管理和日志的,但事实上是无所不能),然后post sub-tree:

M-x org2blog/wp-post-subtree

要正常使用org2blog,必需安装最新的org-mode(我的版本为7.5,`M-x org-version’检查当前版本,警告,7.5不可靠,应升级到最新版本,我用从git服务器取得”d6aba4db”版本).

emacs(版本23.3.1)自带的org-mode太老,和最新的org2blog(<2011-04-12 二>的版本)不兼容.

org2blog安装步骤在上文的链接里都有,也可以参看Blogging with org2blog.

org-mode安装步骤见官方文档.

切.格瓦拉 阿根廷(Che: Part One),一部无聊的政治宣传片

剧情基本上就是记流水帐,从1955年卡斯特罗(Castro)等人在墨西哥城组织七·二六运动(26th of July Movement)开始,然后就是行军,袭击兵营,伏击战,救治伤员,做群众工作(给村民看病,演讲),处决违法军纪的士兵,最后是革命的高潮,切.格瓦拉(Che Guevara)和Camilo Cienfuegos夺取Las Villas省的首府Santa Clara,这是古巴革命最后一场战役,12小时后古巴独裁者巴蒂斯塔(Batista)离开了古巴. 当中穿插了卡斯特罗访问美国,在联合国做演讲,接受采访的片段.

电影的主要缺点是缺少人物性格刻画.格瓦拉的政治主张是什么(例如建立什么样的政府?)?他为何接受社会主义?他喜欢什么?不喜欢什么?他的性格有什么特点(不愿意在阿根廷做医生而去古巴参加革命的人很可能性格有不同于常人的地方)?这些电影中都没有提及.我看到的只有好人打坏人再加上一些战斗场面.

古巴政府和军队坏,因为电影中古巴革命者说Batista腐败.说古巴政府出卖国家利益给美国,例如古巴对美国的贸易逆差为10亿美元.还因为一些比较感性的镜头,比如古巴军队枪杀帮助游击队的平民.古巴军队的飞机轰炸攻入城市的革命者,杀伤了很多平民.古巴军队虐待俘虏.

说实话我认为这种对坏蛋的描写挺幼稚的.我感兴趣的是古巴革命爆发和革命队伍壮大的原因,对此电影没有做出合理的解释.

例如所谓古巴和美国的贸易逆差,我也可以从经济学解释为古巴需要从美国进口的货物多,可以出口给美国的美国人需要的货物少,这好像恰恰是”美国是世界最强大的发达国家的”的结果.当然”贸易逆差”可以是激发”民族主义”的借口,民族主义几乎是近现代革命的必备导火索.但是”贸易逆差”的这段戏导演仅处理为几个领袖间的闲谈,给我的印象就是领袖们私下的谈话缺乏逻辑思维,如果是通过给群众或士兵的演讲来表现的话,我就会认为卡斯特罗等人确实挺会激发(或操纵)大众的情绪.

电影中描写古巴军队残忍的场景很平庸,例如有一幕是一个平民跑来见格瓦拉,要求其部下离开他家,因为政府军要是发现叛军,会认为他通敌,把他全家杀死.我的理解是,从逻辑上来讲,这段镜头说明了政府军的反游击队战术很成功.如果导演想说明政府军是非正义的话,至少这和古巴革命没什么关系,因为在革命和战争中清洗通敌嫌疑分子是很常见的,是内战导致了清洗而不是反之.

其他类似场景我就不罗嗦了,本质上都一样,内战中常见的残酷行为如果一边倒地都列在政府军的头上,感觉太假了,没有说服力.而且这些行为古巴革命没有重要的因果联系(同样的事件也发生在美国,英国,法国,俄国内战上).

对好人的描写我怀疑是参考了我国早期的革命电影.电影的一开始,古巴军队在追捕逃亡的格瓦拉,导演拉了个惊慌失措的普通战士给格瓦拉作伴来衬托主角的镇定自若.接下,格瓦拉免费给村民看病,格瓦拉教文盲战士识字,格瓦拉英明神武,某个战士连发两发火箭炮都没有打中敌人的据点,格瓦拉说声”让我来”,夺过火箭炮一炮就打爆敌人据点.等等等等…

电影唯一的亮点是战争场面不错,挺火爆残酷的,我作为男性观众挺享受的.
Technorati Tags: , , , ,

perl code to change ip

I write this script for a real project. It changes ip of every node in a local network. All the information related to our customer is deleted.

if you see the test() function and you will notice “assert” lines. Yes, I believe in TDD (Test Drivern Development).

  1 #!/usr/bin/perl
  2 
  3 # File name: chgip
  4 # Description : change ip of every node in the local network
  5 require "assert.pl";
  6 use File::Basename;
  7 
  8 #
  9 # Globals
 10 #
 11 use vars qw/ %opt /;
 12 
 13 # valid input:
 14 # 192.168.30.151 node1 -> change /etc/hosts ;$k= node1;
 15 # 192.168.30.151 node1 eth0 none-> NOT change /etc/hosts;$k=node1 eth0
 16 # 192.168.30.151 node1 eth1 none-> NOT change /etc/hosts;$k=node1 eth1
 17 # 192.168.30.151 192.168.30.111 -> NOT change /etc/hosts;$k= 192.168.30.111
 18 # 192.168.30.151 node1 eth1 default -> change /etc/hosts;$k=node1 eth1 default 
 19 # 192.168.30.151 node1 eth1 -> "eth1" will be skipped andit equals 
 20 #                          192.168.30.151 node1
 21 #                         cat /etc/hosts/ and you will see
 22 #                         "150.245.178.31 node1 node1.dcinema.com", 
 23 #                         we will avoid confilict with such lines in /etc/hosts
 24 
 25 $USE_SSH=1;
 26 $USE_TELNET=2;
 27 ############################
 28 # main
 29 ############################
 30 $NDEBUG=0; # NDEBUG  NOT debug version
 31 
 32 &init();
 33 if($opt{h}){
 34   usage();exit 1;
 35 }
 36 
 37 $NDEBUG=$opt{d}?0:1;
 38 
 39 if($NDEBUG){
 40 my @pipein;
 41 
 42 if(&is_interactive()){
 43   if($#ARGV==-1){
 44     usage();exit 1;
 45   }
 46   @pipein=split(/[\r\n]+/,$ARGV[$#ARGV]);
 47 }
 48 else{
 49   @pipein=;
 50 }
 51 
 52 #print "pipein[0]=$pipein[0]\n"; #debug
 53 
 54 if(!$opt{a} && !$opt{p}){
 55   $opt{a}=$USE_SSH;
 56 }
 57 
 58 my $arp;
 59 if($opt{a}){
 60   $arp=&get_hosts_from_arp();
 61 }
 62 my $h=&who_will_change(\@pipein);
 63 
 64 my $pingable;
 65 if($opt{p}){
 66   $pingable=&who_are_pingable($h);
 67 }
 68 
 69 my %whose_ip_changed=();
 70 
 71 my $local_restart_later=0;
 72 #for my $it (keys %$h){ print "key=$it:val=$h->{$it}\n"; } #debug 
 73 my $pingcmd=&get_pingcmd();
 74 for my $k (sort keys %$h){
 75   my @a=split(/[\s\t]+/,$k);
 76   my $s=`hostname`;chomp($s);
 77   if($a[0] eq $s){
 78     $local_restart_later=1;
 79   }
 80 
 81   if($opt{a}){
 82     if(!exists($arp->{$a[0]})){ if($s ne $a[0]){ next; } }
 83   }
 84 
 85   if($opt{p}){
 86     if(!exists($pingable->{$a[0]})){ next; }
 87   }
 88   my $netcard="eth0";
 89   if($#a==2){
 90     if($a[2] eq "default" || $a[2] eq "none"){
 91       $netcard=$a[1];
 92     }
 93   }
 94   #print "netcard=$netcard\n"; #debug
 95   print "changing ip of $netcard on $a[0] ... ";
 96   my $try_telnet=0;
 97   $ret=&change_ip($a[0],$h->{$k},"/etc/sysconfig/network-scripts",
 98                   $netcard,\$try_telnet);
 99   if($ret){
100     print "failed!\n";
101   }
102   else{
103     $whose_ip_changed{$a[0]}=1;
104     print "succeeded\n";
105   }
106   if($try_telnet){
107     if($opt{a}){
108       $arp->{$a[0]}=$USE_TELNET;
109     }
110 
111     if($opt{p}){
112       $pingable->{$a[0]}=$USE_TELNET;
113     }
114   }
115 }
116 
117 #change /etc/host, every node need it
118   my %nodes_restarted=();
119   system("cp -f /etc/hosts /tmp/hosts.new >/dev/null 2>&1");
120   &change_etc_hosts("/tmp/hosts.new",$h);
121 
122 #distribute /etc/hosts
123   for my $k (keys %$h){
124     my @a=split(/[\s\t]+/,$k);
125     my $s=`hostname`;chomp($s);
126     if( $s eq $a[0]){
127       #print "s=$s;k=$k****\n"; #debug
128       #you need reinstall ssh key, if you change anyone's ip and you want 
129       #ssh it again 
130       next;
131     }
132 
133     #if we cannot connect to the node, how can we send it /etc/hosts
134     if($opt{a}){
135       if(!exists($arp->{$a[0]}) || $arp->{$a[0]}==$USE_TELNET )
136       {
137         next;
138       }
139     }
140 
141     if($opt{p}){
142       if(!exists($pingable->{$a[0]}) || $pingable->{$a[0]}==$USE_TELNET )
143       {
144         next;
145       }
146     }
147 
148     my @a=split(/[\s\t]+/,$k);
149     #it's ridiculous to restart same pc again and again!
150     if(!exists($nodes_restarted{$a[0]})){
151       my $ret=0;
152       print "distributing new /etc/hosts to $a[0] ... ";
153       $ret=system("scp /tmp/hosts.new root\@$a[0]:/etc/hosts >/dev/null 2>&1");
154       if($ret){
155         print "failed!\n";
156       }
157       else{
158         print "succeeded\n";
159       }
160 
161 
162       #http://groups.google.com/group/linux.gentoo.user/browse_frm/thread/
163       #       677f23ea20dd85a/506384edeba2c270?lnk=st&q=ssh+network+restart&rnum=5&hl
164       #       =zh-CN#506384edeba2c270
165       #print `cat /etc/hosts|grep node1`; #debug
166       #nohup return too quickly, before ssh starts, we've already changed /etc/hosts
167       my $restart_cmd="/etc/init.d/network restart;/etc/init.d/rmiregistry restart;";
168       if($a[0]=~/node[0-9]+/){
169         $restart_cmd.="restart_some_scripts;";
170       }
171       elsif($a[0]=~/ekfp[0-9]+/){
172         $restart_cmd.="fp_restart;";
173       }
174       #print "restart_cmd=$restart_cmd\n"; #debug
175       $ret=system("nohup ssh root\@".&get_ip($a[0])." '$restart_cmd' >/dev/null 2>&1 &");
176       $nodes_restarted{$a[0]}=1;
177     }
178     else{
179       $nodes_restarted{$a[0]}+=1;
180     }
181   } #end of for
182 
183 #print("local_restart_later=$local_restart_later\n");#debug
184 system("cp -f /tmp/hosts.new /etc/hosts >/dev/null 2>&1");
185 #print `cat /etc/hosts|grep node1`; #debug
186 if($local_restart_later ){
187   my $restart_cmd="/etc/init.d/network restart >/dev/null 2>&1;";
188   my $s=`hostname`;chomp($s);
189   print "restarting $s ... ";
190   if($s=~/manager.*/ ){
191     $restart_cmd.="restart_some_scripts >/dev/null 2>&1;";
192   }
193   else{
194     $restart_cmd.="restart_some_scripts >/dev/null 2>&1;";
195   }
196   #assume this is a cms or tms
197   my $ret=system($restart_cmd);
198   if($ret){
199     print "failed!\n";
200   }
201   else{
202     print "succeeded\n";
203   }
204 
205 }
206 
207 print "finished to change ip!\n";
208 system("rm nohup.out >/dev/null 2>&1");
209 system("rm ~/.ssh/known_hosts>/dev/null 2>&1");
210 
211 if($opt{a}){
212 print "updating arp cache ... ";
213 for my $k (keys %whose_ip_changed){
214   my $pingcmd=&get_pingcmd();
215   system("$pingcmd $k >/dev/null 2>&1");
216 }
217 print "finished\n";
218 }
219 }#if(0)
220 
221 ############################
222 # test
223 ############################
224 if(!$NDEBUG){
225   &test();
226 }#if(0)
227 
228 sub test
229 {
230 
231 if(1){
232   my $hostname=`hostname`;chomp($hostname);
233   my $pipein;
234   if(&is_interactive()){
235     @pipein=split(/[\r\n]/,"127.0.0.9 $hostname");
236     my $h=&who_will_change(\@pipein);
237     my $pingable=&who_are_pingable($h);
238     assert(exists($pingable->{$hostname}));
239   }
240   else{
241     @pipein=;
242     my $h=&who_will_change(\@pipein);
243     my $pingable=&who_are_pingable($h);
244     print "*********who are pingable**********begin\n";
245     for my $k (keys %$pingable){
246       print "key=$k\n";
247       print "val=$pingable->{$k}\n";
248     }
249     print "*********who are pingable**********end\n";
250   }
251 }
252 
253 if(1){
254   my $id=&unique_id();
255   print "id=$id\n";
256   assert( $id ne "");
257 }#if(0)
258 
259 if(1){
260   my $id="test_set_one_card";
261   print "file written by set_onecard=$id\n";
262   `echo "IPADDR=192.168.30.100" > $id`;
263   `echo "NETWORK=192.168.30.0" >> $id`;
264   `echo "BROADCAST=192.168.30.255" >> $id`;
265   `echo "GATEWAY=192.168.30.1" >> $id`;
266   &set_one_card("11.168.30.100",$id);
267   open(F,$id);
268   my @lines=;
269   close(F);
270   chomp($lines[0]);assert($lines[0] eq "IPADDR=11.168.30.100");
271   chomp($lines[1]);assert($lines[1] eq "NETWORK=11.168.30.0");
272   chomp($lines[2]);assert($lines[2] eq "BROADCAST=11.168.30.255");
273   chomp($lines[3]);assert($lines[3] eq "GATEWAY=11.168.30.1");
274   `rm $id`;
275 }
276 if(1){
277   my $hostname=`hostname`;chomp($hostname);
278   my $ip=get_ip($hostname);
279   print "ip=$ip\n";
280   assert(&is_valid_ip($ip));
281   my $rubbish=get_ip("rubbish");
282   assert( $rubbish eq "rubbish");
283 }
284 
285 
286 if(1){
287   my $p="127.0.0.9 node1\n0.0.0.0 node2";
288   my @pipein=split(/[\r\n]+/,$p);
289   my $h=&who_will_change(\@pipein);
290   assert($h->{'node1'} eq '127.0.0.9');
291   assert($h->{'node2'} eq '0.0.0.0');
292   `echo "1.1.1.1 node1" > hosts`;
293   `echo "1.1.1.1 node2 node2.dcinema.com" >> hosts`;
294   `echo "1.1.1.1 node3" >> hosts`;
295   &change_etc_hosts("hosts",$h);
296   open(F,"<hosts");
297   my @lines=;
298   close(F);
299   chomp($lines[0]);assert($lines[0] eq "127.0.0.9 node1");
300   chomp($lines[1]);assert($lines[1] eq "0.0.0.0 node2 node2.dcinema.com");
301   chomp($lines[2]);assert($lines[2] eq "1.1.1.1 node3");
302 }#if(0)
303 
304 if(1){
305   my $hostname=`hostname`;chomp($hostname);
306   print("hostname=$hostname\n");
307   my $p="11.168.30.10 $hostname";
308   my @pipein=split(/[\r\n]+/,$p);
309   my $h=&who_will_change(\@pipein);
310   assert($h->{$hostname} eq '11.168.30.10');
311   `echo "DEVICE=eth0" > ifcfg-eth0`;
312   `echo "IPADDR=192.168.30.10" >> ifcfg-eth0`;
313   `echo "NETWORK=192.168.30.0" >> ifcfg-eth0`;
314   `echo "NETMASK=255.255.255.0" >> ifcfg-eth0`;
315   `echo "ONBOOT=yes" >> ifcfg-eth0`;
316   `echo "TYPE=Ethernet" >> ifcfg-eth0`;
317   `echo "GATEWAY=192.168.30.1" >> ifcfg-eth0`;
318   `echo "BROADCAST=192.168.30.255" >> ifcfg-eth0`;
319   use Cwd;
320   my $d=getcwd;
321   print "cwd=$d\n";
322   my $pingcmd=&get_pingcmd();
323   for my $k (keys %$h){
324     my $ret=0;
325     if(system("$pingcmd $k")!=0){
326       #meanless to ping self
327       if($s ne $a[0]) { next; }
328     }
329 
330     # $k: node1
331     #     node1 eth1
332     #     eckp1 ech1 default
333     my $netcard="eth0";
334     my @a=split(/[\s\t]+/,$k);
335     if($#a==2){
336       $netcard=$a[1];
337     }
338     my $try_telnet;
339     $ret=&change_ip($a[0],$h->{$k},$d,$netcard,\$try_telnet);
340   }
341   open(F,"<ifcfg-eth0");
342   my @lines=;
343   close(F);
344   chomp($lines[0]);assert($lines[0] eq "DEVICE=eth0");
345   chomp($lines[1]);assert($lines[1] eq "IPADDR=11.168.30.10");
346   chomp($lines[2]);assert($lines[2] eq "NETWORK=11.168.30.0");
347   chomp($lines[3]);assert($lines[3] eq "NETMASK=255.255.255.0");
348   chomp($lines[4]);assert($lines[4] eq "ONBOOT=yes");
349   chomp($lines[5]);assert($lines[5] eq "TYPE=Ethernet");
350   chomp($lines[6]);assert($lines[6] eq "GATEWAY=11.168.30.1");
351   chomp($lines[7]);assert($lines[7] eq "BROADCAST=11.168.30.255");
352 }
353 
354 if(0){
355   my ($name,$dir,$suffix)=fileparse($0);
356   print "name=$name;dir=$dir;suffix=$suffix;\n";
357   assert(-e $dir."chg_jnior_ip.exp");
358   my $pingcmd=&get_pingcmd();
359   my $e1ip=&get_ip("node1-auto");
360   if(!system("$pingcmd node1-auto")){
361     print "ip of node1-auto=$e1ip\n";
362     assert($e1ip ne "192.168.30.52");
363     assert(system("$pingcmd 192.168.30.52"));
364     if(system($dir."chg_jnior_ip.exp node1-auto 192.168.30.52")){
365       assert(0);
366     }
367     sleep(8); #wait jnior
368     assert(!system("$pingcmd 192.168.30.52"));
369     assert(system("$pingcmd node1-auto"));
370     if(system($dir."chg_jnior_ip.exp 192.168.30.52 $e1ip")){
371       assert(0);
372     }
373     sleep(8); #wait jnior
374     assert(system("$pingcmd 192.168.30.52"));
375     assert(!system("$pingcmd node1-auto"));
376   }
377   else{
378     print "cannnot connect to node1-auto!\n";
379   }
380 }
381 
382 if(1){
383   my ($network,$broadcast)=&get_netprop("192.168.1.1");
384   assert($network eq "192.168.1.0");
385   assert($broadcast eq "192.168.1.255");
386 }
387 
388 
389 if(1){
390   my $h=&get_hosts_from_arp();
391   foreach my $k (keys %$h){
392     print "key=$k;val=$h->{$k}\n"; #debug
393   }
394 }
395 
396 }
397 
398 sub a()
399 {
400   if(!$NDEBUG){
401     assert($_[$[]);
402   }
403 }
404 
405 ############################
406 # subroutines
407 ############################
408 sub get_ip{
409   my $hostname=shift;
410   my $pingcmd=&get_pingcmd();
411   my $ip=`$pingcmd $hostname`;
412   #PING node1 (192.168.30.111) 56(84) bytes of data.
413   #64 bytes from node1 (192.168.30.111): icmp_seq=0 ttl=64 time=0.129 ms
414   my @a=split(/[\r\n]+/,`$pingcmd $hostname`);
415   chomp($a[0]);
416 # on cygwin, the first line is empty
417   if($a[0] eq ""){ $a[0]=$a[1]; }
418   my @v=split(/[\s\t]+/,$a[0]);
419   $v[2]=~s/[\(\)\[\] ]*//g;
420   if(!&is_valid_ip($v[2])){
421     return $hostname;
422   }
423   return $v[2];
424 }
425 
426 sub is_interactive {
427   return -t STDIN && -t STDOUT;
428 }
429 
430 
431 sub who_will_change
432 {
433   my $ls=shift;
434   my %h=();
435   my @rlt=grep(/^[0-9\.]+.*/,@$ls);
436   # change ip address to 127.0.0.1 is crazy idea!
437   my @rlt=grep(!/^127\.0\.0\.1.*/,@rlt);
438   foreach (@rlt){
439     chomp($_);
440     if($_ eq ""){next;}
441     my @a=split(/[\s\t]+/);
442     if($#a == 0){next;}
443     my $k=$a[1];
444     for(my $i=2;$i<=$#a;$i++){
445       $k.=" ".$a[$i];
446     }
447     $h{$k}=$a[0];
448   }
449   return \%h;
450 }
451 
452 
453 sub change_etc_hosts
454 {
455   my $f=shift;
456   my $h=shift;
457   open(F,$f);
458   @lines=;
459   close(F);
460   for my $k (keys %$h){
461     #print "k=$k\n"; #debug
462     my $need_replace=0;
463     my $replaced=0;
464     my @a=();
465     for(my $i=0;$i<=$#lines;$i++){
466       @a=split(/[\s\t]+/,$k);
467       if( $#a == 2 && ($a[2] eq "none") ){
468         next;
469       }
470 
471       if(&is_valid_ip($a[0])){
472         next;
473       }
474 
475       $need_replace=1;
476       $_=$a[0];
477       if($lines[$i]!~/^[\d\.]+[\s\t]+$_[\s\t\r\n]+/){
478         next;
479       }
480 
481       $lines[$i]=~s/^[\d\.]+/$h->{$k}/g;
482       $replaced=1;
483 
484       #print "line=".$lines[$i]; #debug
485     }
486 
487     if( $need_replace && !$replaced ){
488       push(@lines,"$h->{$k} $a[0]\n");
489     }
490   }
491   #foreach (@lines){print "line=$_";}; #debug
492   open (F,">$f");
493   print F (@lines);
494   close(F);
495 }
496 
497 sub get_pingcmd
498 {
499   my $s=`uname`;chomp($s);
500   if($s eq "Linux"){
501     return "ping -c3";
502   }
503   return "ping";
504 }
505 
506 sub set_one_card
507 {
508   my $addr=shift;
509   my $ifcfg=shift;
510   my @p=split(/\./,$addr);
511   open(F,"<$ifcfg");
512   my @lines=;
513   for(my $i=0;$i<=$#lines;$i++){
514     if($lines[$i]=~/IPADDR=.*$/){
515       $lines[$i]="IPADDR=$addr\n";
516     }
517     elsif($lines[$i]=~/NETWORK=.*$/){
518       my @orig=split(/=/,$lines[$i]);
519       chomp($orig[1]);
520       my @o=split(/\./,$orig[1]);
521       $s="$p[0].$p[1].$p[2].$o[3]";
522       $lines[$i]="NETWORK=$s\n";
523 
524     }
525     elsif($lines[$i]=~/BROADCAST=.*$/){
526       my @orig=split(/=/,$lines[$i]);
527       chomp($orig[1]);
528       my @o=split(/\./,$orig[1]);
529       $s="$p[0].$p[1].$p[2].$o[3]";
530       $lines[$i]="BROADCAST=$s\n";
531     }
532     elsif($lines[$i]=~/GATEWAY=.*$/){
533       my @orig=split(/=/,$lines[$i]);
534       chomp($orig[1]);
535       my @o=split(/\./,$orig[1]);
536       $s="$p[0].$p[1].$p[2].$o[3]";
537       $lines[$i]="GATEWAY=$s\n";
538     }
539   }
540   close(F);
541   open (F,">$ifcfg");
542   print F (@lines);
543   close(F);
544   return 0;
545 }
546 
547 sub get_netprop
548 {
549   my $addr=shift;
550   my @p=split(/\./,$addr);
551   my $network="$p[0].$p[1].$p[2].0";
552   my $broadcast="$p[0].$p[1].$p[2].255";
553   return ($network,$broadcast,);
554 }
555 
556 # Return: 
557 sub change_ip
558 {
559   my $k=shift;
560   my $addr=shift;
561   my $dir=shift;
562   my $netcard=shift;
563   my $tr=shift;
564 
565   my $ret=0;
566   my $s=`hostname`;chomp($s);
567   my ($network,$broadcast)=&get_netprop($addr);
568   if( $s eq $k){ #local
569     #print "s=$s;k=$k\n"; #debug
570     $ret=&set_one_card($addr,"$dir/ifcfg-$netcard");
571     if($ret){ &a(0); return $ret;}
572     return $ret;
573   }
574   #remote
575   my $u=&unique_id();
576   #print "k=$k\n"; #debug
577   $ret=system("scp root\@$k:$dir/ifcfg-$netcard /tmp/$u.ifcfg-$netcard 
578               >/dev/null 2>&1");
579   if($ret){ # maybe jnior
580     $$tr=1;
581     my ($name,$dir,$suffix)=fileparse($0);
582     &a(-e $dir."chg_jnior_ip.exp");
583     $ret=system($dir."chg_jnior_ip.exp $k $addr >/dev/null 2>&1");
584     return $ret;
585   }
586   else{
587     $$tr=0;
588   }
589   $ret=&set_one_card($addr,"/tmp/$u.ifcfg-$netcard");
590 
591   if($ret){ &a(0); return $ret;}
592   $ret=system("scp /tmp/$u.ifcfg-$netcard root\@$k:$dir/ifcfg-$netcard 
593               >/dev/null 2>&1");
594   system("rm -f /tmp/$u.ifcfg-$netcard >/dev/null 2>&1");
595   if($ret){ &a(0); return $ret;}
596   return $ret;
597 }
598 
599 sub unique_id()
600 {
601   my $sessionId  ="";
602   for($i=0 ; $i< 32 ;)
603   {
604     $j = chr(int(rand(127)));
605     if($j =~ /[a-zA-Z0-9]/)
606     {
607       $sessionId .=$j;
608       $i++;
609     }
610   }
611   return $sessionId;
612 }
613 
614 sub is_valid_ip
615 {
616   my $ip=shift;
617   if( $ip !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ ){
618     return 0;
619   }
620   my @a=split('\.',$ip);
621   #print "$a[0] $a[1] $a[2] $a[3]\n";#debug
622   if($a[0]>255){ return 0;}
623   if($a[1]>255){ return 0;}
624   if($a[2]>255){ return 0;}
625   if($a[3]>255){ return 0;}
626   return 1;
627 }
628 
629 sub who_are_pingable
630 {
631   my $h=shift;
632   my %p=();
633   for my $k (sort keys %$h){
634     my @a=split(/[\s\t]+/,$k);
635     my $s=`hostname`;chomp($s);
636     if($a[0] eq $s){
637       print "test $a[0] ... connectable\n";
638       $p{$a[0]}=$USE_SSH;
639       next;
640     }
641     my $pingcmd=&get_pingcmd();
642     print "test $a[0] ... ";
643     if(system("$pingcmd $a[0] >/dev/null 2>&1")!=0){
644       print "NOT connectable\n";
645       next;
646     }
647     else{
648       print "connectable\n";
649     }
650 
651     $p{$a[0]}=1;
652   }
653   return \%p;
654 }
655 
656 sub get_hosts_from_arp
657 {
658   my @a=grep(!/incomplete/,split(/[\r\n]/,`arp -a`));
659   my %h=();
660   foreach my $l (@a){
661     my @s=split(/[\s\t\(\)]+/,$l);
662     $h{$s[0]}=$s[1];
663   }
664   return \%h;
665 }
666 
667 sub usage
668 {
669   my ($name,$dir,$suffix)=fileparse($0);
670   print STDERR << "EOF";
671 USAGE
672         $name [OPTION] "ip hostname [netcard default/none]"
673 
674 DESCRIPTION
675         Change IP of remote hosts.
676         -h    : this (help) message
677         -d    : self test and print debugging messages to stderr
678         -a    : use `arp -a` to verify remote hosts reachable
679                 `$name "ip host"` (without either -a or -p)  
680                 equals `$name -a "ip host"`
681         -p    : use `ping` to verify remote hosts reachable
682 
683         netcard      : the name of the netcard
684         default/none : default - the changed ip will be recorded in /etc/hosts
685                        none    - contrary to "default"
686 
687 EXAMPLE
688         echo 192.168.30.151 manager|$name
689         echo 192.168.30.151 manager eth1 none|$name 
690         echo 192.168.30.151 manager eth1 none|$name  -p
691         cat /etc/hosts|$name -a
692         $name "192.168.30.151 manager"
693         $name "192.168.30.151 manager eth0 default"
694 
695 AUTHOR
696         Chen Bin 
697 
698 EOF
699 }
700 sub init()
701 {
702   use Getopt::Std;
703   my $opt_string = 'hdap';
704   getopts( "$opt_string", \%opt ) or usage();
705 }
706