ghosTzone
main(_){return _} && echo $? /* Keep It Simple Stupid | 本博客所有文章皆为原创 转载请注明 - ghosTM55 */

发现一个很有趣的工具——shred 5

2008年11月22日 04:01 in bash tags:

  shred是GNU fileutils中的一员,它的功能简单的说就是涂鸦,把一个文件用随机的编码篡改的一塌糊涂。其宗旨就是更安全地帮助删除一个机密文件:

txi@ghosTunix.org:test> cat txt
helloworld
txi@ghosTunix.org:test> shred txt
txi@ghosTunix.org:test> cat txt
ËgÆ,##WPEõȮ~    !å9û@2`vÑùGìãl$¼Àã¼"÷Ďñ\cïFçà8mGdt#'öxðô
                                                        ö·ÀBS&º7`Ì1¼éOµö}ёÍDèRjXµà     ·u@    ¸÷=IJXpj<l÷çñóɅ`Êå/ËÏg]êhòP¶:¡gw-v
â* ¯m¥ÝLôâ;nãâÅߤÁh>_zïìñ´©C«U            K¶z԰
ɡÈ_`u+«Q>,]Φ    IÖ
}#%)<Àn°ÒV%<½i³ .ÑójAý¯=¯,I
¦®    "
rå±ÝNrNý1ÌÁ¸"îbïս¦`UiávNý(¼DlÕÅ(!shôîV_-ad­Kjy·k    ÃeûGùð£Àª=Û55 Dù­*÷!£?úÉ]ÊÀH­´ò(±÷>õÃñ¬V8gÎç'
                   CÛkg=$fU9+ãȴQcBx©ôÑʒ¥JÎO½]ÄkK2ܾ
                                                   »/¸mÕÝÎÿX)àûÇSîí-slçò9dfP·_áÍC±,êK6yf?!Ëا\ *èqû³½ТøBՂ¾»ñÀIäôGÔ=埰YÒ°V1Dú¡²ý^iÙÓNÒ    ȹleÞ
                                                    ú&ò@·0Þr4yóüA{0ÃX%À
àjU2Ëљ)hô3Ky¯¢R˸Vºeòg¬
                      ¤ïöQâ¡Ô̖ºT\��7£²Ң,ÍZÆbÜ}ôùб
                                               LIpù;6pYäÛ9dl)hQSw·öAÑÁ¡SGG_H^\`߆1LMþ"
ÕÑÀƄP#Ö&¿ÖҼm24Çç<9"H¢Wwffð/`L! Â쫎}øî_ÌŲ²°µgn-±Ěül±ÿày@Ú
                                                   ô°âO$+Uê³Ð水"
0à㦫G;Íè4
......省略无数乱码

  可见,shred可以将一个文件的内容改的面目全非。

txi@ghosTunix.org:~> date
Fri Aug 15 08:38:17 CST 2008


学会使用last 0

2008年11月22日 03:56 in bash tags:

  last命令通过查看(或者说搜索)/var/log/wtmp文件或者使用命令选项-f指定的自定义文件来列出自从该记录文件建立起系统上所有用户登录登出的信息,该工具能够很好的帮助管理员来监视系统的登录情况。

  在last给出的信息中,包含了用户名、登录终端、登录登出时间等多项重要信息,下面就举出常见的使用方法,具体的参考man:

:~$ last -x
这里x是一个数字,该命令将列出最近指定数目条登录登出信息
txi@ghosTunix.org:~> last -3
txi      vc/7         :0               Sat Aug 30 18:50   still logged in
reboot   system boot 2.6.26-ARCH      Sat Aug 30 18:49          (00:14)   
txi      vc/7         :0               Sat Aug 30 17:55 - 17:58 (00:02)

wtmp begins Tue Aug 19 07:54:56 2008
在最后一行可以看到wtmp文件创建的时间

:~$ last -a

将hostname一栏放在最后显示
txi@ghosTunix.org:~> last -3 -a
txi      vc/7         Sat Aug 30 18:50   still logged in    :0
reboot   system boot Sat Aug 30 18:49          (00:22)     2.6.26-ARCH
txi      vc/7         Sat Aug 30 17:55 - 17:58 (00:02)     :0

wtmp begins Tue Aug 19 07:54:56 2008
试比较该例与上一个例子的显示结果的不同

  lastb工具与last相同,但是它需要root权限才能执行,来显示所有可能是恶意的登录事件

txi@ghosTunix.org:~> date
Sat Aug 30 19:16:32 CST 2008


随机数的生成与使用技巧 0

2008年11月22日 02:00 in C/C++ tags:

  在C语言中,rand()函数能够帮助用户生成一个从0到RAND_MAX之间的任意数,它们的定义包含在stdlib.h的头文件中。

  这段代码展示了一些使用随机数的一些技巧:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
        int chose=0;
        for(;chose-1!=0;)
        { 
                srand(time(NULL));
                chose=1+rand()%20; /* 限制随机数的范围: 1~20 */
                printf("%d\n",chose);
        } 
        return 0;
}

  rand()函数在使用之前需要一个seed,而通过srand()与time()函数能够帮助用户产生随机的 rand()函数seed。time()所返回的值是从1970年1月1日至今所经过的秒数,所以,这个程序在执行的时候,可以看到每经过一秒,就会产生一个新的随机数,直到随机数为1时退出循环。

txi@ghosTunix:~$ date
2008年 05月 17日 星期六 07:37:11 CST


循环条件的使用问题 0

2008年11月22日 01:59 in C/C++ tags:

#include<stdio.h>
int main(void)
{
        float t=2.0,i=0.0;
        for(;i!=t;i+=0.2);
        printf("terminated\n");
        return 0;
}

txi@ghosTunix:~$ date
2008年 05月 17日 星期六 07:47:27 CST


让C程序暂停一秒 2

2008年11月22日 01:57 in C/C++ tags:

  在C语言中,time.h头文件中包含了clock()函数,它负责返回程序开始运行后的时间,以时钟周期为单位。同时,在time.h中定义了CLOCKS_PER_SEC的常量,即1秒的时钟周期数。利用这两个特性,可以实现C语言中的程序暂停1秒的功能。

#include<stdio.h>
#include<time.h>
int main(void)
{
        int now=clock();
        printf("%d\n",now);     /* 显示0 */
        for(;clock()-now<CLOCKS_PER_SEC;);
        printf("1\n");          /* 一秒后显示1 */
        now=clock();
        for(;clock()-now<CLOCKS_PER_SEC;);
        printf("2\n");          /* 再过一秒后显示2 */
        return 0;
}



清除输入缓存 0

2008年11月22日 01:53 in C/C++ tags:

  我们熟知的scanf()函数事实上并不是从键盘直接接受输入,而是检查键盘缓存。所以,初学者常常会对一些奇怪的输入问题感到困惑。先来看下面这段代码:

#include<stdio.h>
int main(void)
{
        int c='y';
        while(c=='y')
        {
                printf("y/n:");
                scanf("%c",&c);
        }
        return 0;
}

  无论程序执行者是循规蹈矩地输入一个y然后按下回车,或者是输入yes后按下回车,程序都不会按照表面看起来那样让执行者进行下一次循环:

txi@ghosTunix:~/programming/c/test$ ./a.out
y/n:y
y/n:txi@ghosTunix:~/programming/c/test$

  可以看到,在按下y+回车后,下一个循环直接跳过,并为执行。这是因为在第二个循环中,程序将回车,也就是"\n"赋值给了变量c,由于"\n"!='y',所以跳出了循环。通过清楚输入缓存,能够很好的解决这个问题:

#include<stdio.h>
int main(void)
{
        int c='y',flush;
        while(c=='y')
        {
                printf("y/n:");
                scanf("%c",&c);
                while((flush=getchar()) != '\n' && flush != EOF); /* 清除缓存 */
        }
        return 0;
}

  清楚输入缓存并没有官方的方法,通过执行一个空while语句,可以将输入缓存“消耗”掉。

  参考资料:http://www.c-faq.com,Question 12.26[ab]

txi@ghosTunix:~$ date
2008年 05月 18日 星期日 08:50:31 CST


正确使用strlen计算字符数组长度 0

2008年11月22日 01:51 in C/C++ tags:

#include<stdio.h>
#include<string.h>
/*#include<stddef.h>*/
int main(void)
{
        char str[]="helloworld!!!";
        size_t length=strlen(str);
        printf("%d\n",length);
        return 0;
}
 

  由于strlen()函数返回的值其实是size_t类型的,所以,采用size_t来声明一个记录数组长度的变量能够达到更好的移植性。数据类型 size_t是在stddef.h头文件中定义的,由于在stdio.h头文件中预处理了stddef.h,所以能够直接使用。

txi@ghosTunix:~$ date
2008年 05月 18日 星期日 21:14:45 CST


判断是否正确分配内存 1

2008年11月22日 01:49 in C/C++ tags:

  在使用malloc进行内存分配时,由于一些原因(比如内存不够)而导致内存分配失败后,malloc函数将返回一个值为NULL的指针。所以,在每次分配完内存后,对其成功性进行验证非常有必要:

#include<stdio.h>
#include<stdlib.h>
int main(void)
{
    long *pArray=(long *)malloc(1000000*sizeof(long));
    if(pArray==NULL)
    {
        printf("Memory allocation failure :(\n");
        exit(1);
    }
    else
    {
        printf("Memory allocation success :),%u\n",pArray);
        free(pArray);
        exit(0);
    }
}

  运行结果:
Memory allocation success :),3082084360

  如果再多分配一些内存,就会失败:
Memory allocation failure :(

  可是,当我这样分配内存时,它却成功了:
long *pArray=(long *)malloc(1000000000000000000000000000*sizeof(long));

  至于为什么以及如何改进,就留给大家自己思考了。

txi@ghosTunix.org:~> date
2008年 07月 08日 星期二 16:35:38 CST


C语言误区之void main() 0

2008年11月22日 01:45 in C/C++ tags:

  大学开学一个月了,看到了很多胡扯的老师和学生,具体的没必要浪费时间进行愤怒的驳斥了。先说说C语言的一个非常大的误区,在很多教材上都没有提到,甚至引用了这种错误的代码写法,就是著名的void main()问题。

  先来看一下这段看似正确的代码:

#include<stdio.h>
void main()
{
    printf("helloworld\n");
}

  然后使用gcc编译器进行编译,会提示警告:

txi@ghosTunix.org:test> gcc helloworld.c
helloworld.c: In function ‘main’:
helloworld.c:3: warning: return type of ‘main’ is not ‘int’

  不过没关系,程序照样能执行:

txi@ghosTunix.org:test> ./a.out
helloworld

  运行完全正确,但我们查看该程序的返回值会发现系统接受到了一个错误的返回值11:

txi@ghosTunix.org:test> echo $?
11

  可见,void main()其实根本就是一个错误的写法,系统在执行完这样一段程序后,得到的程序返回值是一个错误的返回值。

  在C语言的标准中,从来没有定义过void main()这样的写法,标准的main函数调用形式如下

#include<stdio.h>
int main(void)
{
    printf("helloworld\n");
    return 0;
}

  有了确切的返回值,程序能够在像用户需要的情况那样运行时,还能让系统很好的了解到程序已经成功或者错误地执行了。

txi@ghosTunix.org:~> date
Wed Oct 15 20:47:08 CST 2008


多Linux系统引导问题 0

2008年11月22日 01:41 in Linux tags:

  在一台计算机上,可以通过GRUB这个强大的引导程序来引导大部分操作系统,一般来说,都是一个Linux和一个Windows的双系统,而安装了两个或者是多个Linux系统的时候,会存在一个隐蔽的问题。

  前一阵安装了Archlinux,非常优秀的一个Linux发行版本,在配置GRUB的时候,我想到了一个问题,就是,我之前安装了ubuntu,当我ubuntu进行了内核的升级后,那么这里的静态的GRUB条目还是会引导老的内核,甚至无法引导。于是我找到一个能够动态的解决这个问题的方法。

# (0) Arch Linux
title Arch Linux
root   (hd0,3)
kernel /boot/vmlinuz26 root=/dev/sda4 ro
initrd /boot/kernel26.img

# (1) Arch Linux
title Arch Linux Fallback
root   (hd0,3)
kernel /boot/vmlinuz26 root=/dev/sda4 ro
initrd /boot/kernel26-fallback.img

#ubuntu
title ubuntu
configfile (hd0,0)/boot/grub/menu.lst

  这是我GRUB配置文件的片断代码,在ubuntu这里,使用了configfile功能来指向ubuntu自身的GRUB配置文件,这样,就可以通过ubuntu自身的GRUB再去引导GRUB。这样一来,就是动态的了。

  问题解决。

ghostm55@ghosTunix.org:~$ date
Sat Mar 29 09:11:19 CST 2008