Profil de PhillipZ.F.BlogListes Outils Aide
03/07/2008

PostfixBasicSetupHowto

Introduction

This document will teach you how to set up a basic Postfix mail server with IMAP and POP3 services. It does not included advanced topics such as integrating virus-checking and spam-filtering, which are dealt with in PostfixVirtualMailBoxClamSmtpHowto and PostfixCompleteVirtualMailSystemHowto.

Setup Overview

In our setup, Postfix sends and receives mail from Internet and stores them in the user mailboxes while clients in the Internet can retrieve their mails via Courier IMAP or POP3. The user authentication is done by Courier Authdaemon. The following diagram shows this process.

1

Anatomy of Postfix

Components

The Following figure shows the main Postfix system components, and the main information flows between them.

2

  • Yellow ellipsoids are mail programs.
  • Yellow boxes are mail queues or files.
  • Blue boxes are lookup tables.
  • Programs in the large box run under control by the Postfix resident master daemon.
  • Data in the large box is property of the Postfix mail system.

    Receiving Mail

    When a message enters the Postfix mail system, the first stop on the inside is the incoming queue. The figure below shows the main components that are involved with new mail.

    3

  • Mail is posted locally. The Postfix sendmail program invokes the privileged postdrop program which deposits the message into the maildrop directory, where the message is picked up by the pickup daemon. This daemon does some sanity checks, in order to protect the rest of the Postfix system.

  • Mail comes in via the network. The Postfix SMTP server receives the message and does some sanity checks, in order to protect the rest of the Postfix system.

  • Mail is generated internally by the Postfix system itself, in order to return undeliverable mail to the sender. The bounce or defer daemon brings the bad news.

  • Mail is forwarded by the local delivery agent, either via an entry in the system-wide alias database, or via an entry in a per-user .forward file. This is indicated with the unlabeled arrow.

  • Mail is generated internally by the Postfix system itself, in order to notify the postmaster of a problem (this path is also indicated with the unlabeled arrow).The Postfix system can be configured to notify the postmaster of SMTP protocol problems, UCE policy violations, and so on.

  • The cleanup daemon implements the final processing stage for new mail. It adds missing From: and other message headers, arranges for address rewriting to the standard user@fully.qualified.domain form, and optionally extracts recipient addresses from message headers. The cleanup daemon inserts the result as a single queue file into the incoming queue, and notifies the queue manager of the arrival of new mail. The cleanup daemon can be configured to transform addresses on the basis of canonical and virtua table lookups.

  • On request by the cleanup daemon, the trivial-rewrite daemon rewrites addresses to the standard user@fully.qualified.domain form.

    Install Postfix

    In this setup I assume that your domain is yourdomain.com and it has a valid MX record call mail.yourdomain.com. Remember to replace yourdomain.com with your actual domain in the example codes in this howto. Also I assume that you know what an MX record is. To find out MX your type in a terminal:

    dig mx yourdomain.com

    To install postfix

    sudo apt-get install postfix

    Intall mailx package for use as command mail utility program. Mail command is installed with this package.

    sudo apt-get install mailx

    Test your default setup

    Add a user before you start this.

    sudo useradd -m -s /bin/bash fmaster
    sudo passwd fmaster

    Test your default installation using the following code segment.

    telnet localhost 25

    Postfix will prompt like following in the terminal so that you can use to type SMTP commands.

    Trying 127.0.0.1...
    Connected to mail.fossedu.org.
    Escape character is '^]'.
    220 localhost.localdomain ESMTP Postfix (Ubuntu)

    Type the following code segment in Postfix's prompt.

    ehlo localhost
    mail from: root@localhost
    rcpt to: fmaster@localhost
    data
    Subject: My first mail on Postfix
    
    Hi,
    Are you there?
    regards,
    Admin
    . (Type the .[dot] in a new Line and press Enter )
    quit

    Check the mailbox of fmaster

    su - fmaster
    mail

    When you type mail command an output like follows display in your terminal.

    Mail version 8.1.2 01/15/2001.  Type ? for help.
    "/var/mail/fmaster": 2 messages 2 new
    >N  1 root@localhost     Mon Mar  6 12:49   13/479   Just a test
     N  2 root@localhost     Mon Mar  6 12:51   15/487   My first mail
    &

    You will observe that mails are indexed by numbers and you can type the number of which the mail that you want to read. For example type no "2" to read the 2nd mail. The type "q" to quit. The mail will be written to a file called mbox in user's home directory. According to our example it will be /home/fmaster/mbox.

    All messages in an mbox type of mailbox are concatenated and stored in a single file. The beginning of each message is indicated by a line whose first five characters are "From " and a blank line is appended to the end of each message

    Setting Postfix Support for Maildir-style Mailboxes

    Maildir is a format for an e-mail spool that does not require file locking to maintain message integrity because the messages are kept in separate files with unique names. A Maildir is a directory (often named Maildir) with three subdirectories named tmp, new, and cur. The subdirectories should all reside on the same filesystem.

    Another reason to use Maildir format is that Courier IMAP/POP3 servers only work with Maildir format of mailboxes.

    Please find out more about Maildir here

    Instruct Postfix to use Maildirs instead of Mboxes:

     sudo postconf -e "home_mailbox = Maildir/"

    Ensure Procmail isn't used: (if the step was taken during dpkg-reconfigure, by mistake)

    sudo postconf -e "mailbox_command = "

    Restart Postfix to make changes effect.

    sudo  /etc/init.d/postfix restart

    Test your setup again

    Installing courier IMAP and POP3

    sudo apt-get install courier-pop
    sudo apt-get install courier-imap

    Adding your local domains to postfix

    Add your domains to mydestination:

    sudo postconf -e "mydestination = mail.fossedu.org, localhost.localdomain, localhost, yourdoamin.com"

    Add your local networks, too:

    Postfix comes with the localhost (127.0.0.1) entry; you may have others, here we assume your LAN is on 192.168.1.0/24. Make changes to suit your situation.

    sudo postconf -e "mynetworks = 127.0.0.0/8, 192.168.1.0/24"

    Make Postfix to receive mail from the Internet

    Instruct Postfix to receive on all interfaces:

    sudo postconf -e "inet_interfaces = all"

    (optional) Make Postfix accept IPv4, IPv6 protocols

    If you're not using IPv6 yet, and you're paranoid, use "ipv4" instead of "all". Again, this is to suit your own network sensibilities.

    sudo postconf -e "inet_protocols = all"

    Finally, restart Postfix;

    sudo  /etc/init.d/postfix restart

    Test your setup again using following code:

    telnet mail.yourdomain.com 25
    ehlo yourdomain.com
    mail from: root@yourdomain.com
    rcpt to: fmaster@yourdomain.com
    data
    Subject: My first mail for my domain
    
    Hi,
    Are you there?
    regards,
    Admin
    . (and Enter In a new Line)
    quit

    Check the mailbox of fmaster

    su - fmaster
    cd Maildir/new
    ls

    Now you will see mail has a separate file.

    Testing Courier POP3

    Type in a terminal:

    telnet mail.yourdomain.com 110

    Use the following example code segment for your test. Be intelligent to tweak the changes appropriately to your environment. An output like follows will display in your terminal.

    Connected to mail.yourdomain.com (208.77.188.166).
    Escape character is '^]'.
    +OK Hello there.

    Type the following code segment in the prompt provided by the Courier POP3 server. I assume that you are intelligent enough not to type the lines which starts from +OK

    user fmaster
    +OK Password required.
    pass password
    +OK logged in.
    quit

    Testing Courier IMAP

    Type in a terminal:

    telnet mail.yourdomain.com 143

    Use the following example code segment for your test. Be intelligent to tweak the changes appropriately to your environment. An output like follows will display in your terminal.

    * OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS XCOURIEROUTBOX=INBOX.Outbox] Courier-IMAP ready. Copyright 1998-2005 Double Precision, Inc.  See COPYING for distribution information.

    Type the following code segment in the prompt provided by the Courier IMAP server.

    a login fmaster password
    a OK LOGIN Ok.
    a logout

    Local Alias database

    When mail is to be delivered locally, the local delivery agent runs each local recipient name through the aliases database. The mapping does not affect addresses in message headers. Local aliases are typically used to implement distribution lists, or to direct mail for standard aliases such as postmaster to real people. The table can also be used to map Firstname.Lastname addresses to login names.

    Alias lookups are enabled by default and you will see following code segment in main.cf file.

    ...
    alias_maps = hash:/etc/aliases
    ...

    Creating an alias for an account

    The following codes illustrate how you can setup an alias. This step is optional since we are going to configure virtual mail domains later in this howto. I have added this step to make understand how you can do this in case of a requirement.

    Create a user

    sudo useradd -m -s /bin/bash sysadmin
    sudo passwd sysadmin

    Edit the alias table

    Open the alias file with:

    sudo vi /etc/aliases

    Add the following code:

    fmaster: sysadmin

    To make your changes effect type:

    sudo newaliases

    To test your changes send a mail to fmaster and check the mail in /home/sysadmin/Maildir/new folder.

    Per User .forward Files

    Users can control their own mail delivery by specifying destinations in a file called .forward in their home directories. The syntax of these files is the same as with system aliases, except that the lookup key and colon are not present.

    I will illustrate an example here:

    Assume that you need to for all the mails which comes sysadmin account to an another account do like this

    su - sysadmin
    touch .forward

    Then open the .forward file

    vi .forward

    Add the following code:

    fossedu@example.com

    Remember to use email address which exists in this exercise.

    Now send a mail to sysadmin and mail should come to fossedu@example.com

    Postfix virtual Aliases for separate domains and Linux system accounts

    With this approach, every hosted domain can have its own info etc. email address. However, it still uses LINUX system accounts for local mailbox deliveries.

    With virtual alias domains, each hosted address is aliased to a local UNIX system account or to a remote address. The example below shows how to use this mechanism for the fossedu.org and linuxelabs.com domains.

    Inside the main.cf file, we tell it how to handle these virtual domains:

    sudo postconf -e "virtual_alias_domains = fossedu.org linuxelabs.com"
    sudo postconf -e "virtual_alias_maps = hash:/etc/postfix/virtual"

    Edit the /etc/postfix/virtual file:

    Add two Linux system accounts

    sudo useradd -m -s /bin/bash sigiri
    sudo useradd -m -s /bin/bash kala

    Set Password for the above users.

    sudo passwd sigiri
    sudo passwd kala

    sudo vi /etc/postfix/virtual

    Add the following code segment:

    info@fossedu.org       sigiri
    info@linuxelabs.com    kala

    To create a Map Database type :

    sudo postmap /etc/postfix/virtual

    The postmap is utility program that will convert /etc/postfix/virtual to /etc/postfix/virtual.db Berkley DB format, so that Postfix can access the data faster.

    Restart Postfix to make changes effect:

    sudo /etc/init.d/postfix restart

    Send mails to both info@fossedu.org and info@linuxelabs.com and those mails should come to mailboxes of sigiri and kala respectively.

  • 29/05/2006

    C#格式化数值结果表

    C#格式化数值结果表

    字符

    说明

    示例

    输出

    C 货币 string.Format("{0:C3}", 2) $2.000
    D 十进制 string.Format("{0:D3}", 2) 002
    E 科学计数法 1.20E+001 1.20E+001
    G 常规 string.Format("{0:G}", 2) 2
    N 用分号隔开的数字 string.Format("{0:N}", 250000) 250,000.00
    X 十六进制 string.Format("{0:X000}", 12) C


    string.Format("{0:000.000}", 12.2) 012.200

    Strings

    There really isn't any formatting within a strong, beyond it's alignment. Alignment works for any argument being printed in a String.Format call.

     

    Sample Generates
    String.Format("->{1,10}<-", "Hello"); -> Hello<-
    String.Format("->{1,-10}<-", "Hello"); ->Hello <-

    Numbers

    Basic number formatting specifiers:

     

    Specifier Type Format

    Output
    (Passed
    Double 1.42)

    Output
    (Passed
    Int -12400)

    c Currency {0:c} $1.42 -$12,400
    d Decimal (Whole number) {0:d} System.
    FormatException
    -12400
    e Scientific {0:e} 1.420000e+000 -1.240000e+004
    f Fixed point {0:f} 1.42 -12400.00
    g General {0:g} 1.42 -12400
    n Number with commas for thousands {0:n} 1.42 -12,400
    r Round trippable {0:r} 1.42 System.
    FormatException
    x Hexadecimal {0:x4} System.
    FormatException
    cf90

    Custom number formatting:

     

    Specifier Type Example Output (Passed Double 1500.42) Note
    0 Zero placeholder {0:00.0000} 1500.4200 Pads with zeroes.
    # Digit placeholder {0:(#).##} (1500).42
    . Decimal point {0:0.0} 1500.4
    , Thousand separator {0:0,0} 1,500 Must be between two zeroes.
    ,. Number scaling {0:0,.} 2 Comma adjacent to Period scales by 1000.
    % Percent {0:0%} 150042% Multiplies by 100, adds % sign.
    e Exponent placeholder {0:00e+0} 15e+2 Many exponent formats available.
    ; Group separator see below  

    The group separator is especially useful for formatting currency values which require that negative values be enclosed in parentheses. This currency formatting example at the bottom of this document makes it obvious:

    Dates

    Note that date formatting is especially dependant on the system's regional settings; the example strings here are from my local locale.

     

    Specifier Type Example (Passed System.DateTime.Now)
    d Short date 10/12/2002
    D Long date December 10, 2002
    t Short time 10:11 PM
    T Long time 10:11:29 PM
    f Full date & time December 10, 2002 10:11 PM
    F Full date & time (long) December 10, 2002 10:11:29 PM
    g Default date & time 10/12/2002 10:11 PM
    G Default date & time (long) 10/12/2002 10:11:29 PM
    M Month day pattern December 10
    r RFC1123 date string Tue, 10 Dec 2002 22:11:29 GMT
    s Sortable date string 2002-12-10T22:11:29
    u Universal sortable, local time 2002-12-10 22:13:50Z
    U Universal sortable, GMT December 11, 2002 3:13:50 AM
    Y Year month pattern December, 2002

    The 'U' specifier seems broken; that string certainly isn't sortable.

    Custom date formatting:

     

    Specifier Type Example Example Output
    dd Day {0:dd} 10
    ddd Day name {0:ddd} Tue
    dddd Full day name {0:dddd} Tuesday
    f, ff, ... Second fractions {0:fff} 932
    gg, ... Era {0:gg} A.D.
    hh 2 digit hour {0:hh} 10
    HH 2 digit hour, 24hr format {0:HH} 22
    mm Minute 00-59 {0:mm} 38
    MM Month 01-12 {0:MM} 12
    MMM Month abbreviation {0:MMM} Dec
    MMMM Full month name {0:MMMM} December
    ss Seconds 00-59 {0:ss} 46
    tt AM or PM {0:tt} PM
    yy Year, 2 digits {0:yy} 02
    yyyy Year {0:yyyy} 2002
    zz Timezone offset, 2 digits {0:zz} -05
    zzz Full timezone offset {0:zzz} -05:00
    : Separator {0:hh:mm:ss} 10:43:20
    / Separator {0:dd/MM/yyyy} 10/12/2002

    Enumerations

     

    Specifier Type
    g Default (Flag names if available, otherwise decimal)
    f Flags always
    d Integer always
    x Eight digit hex.

    Some Useful Examples

    String.Format("{0:$#,##0.00;($#,##0.00);Zero}", value);

    This will output "$1,240.00" if passed 1243.50. It will output the same format but in parentheses if the number is negative, and will output the string "Zero" if the number is zero.

    String.Format("{0:(###) ###-####}", 18005551212);

    This will output "(800) 555-1212".

     

    变量.ToString()


    字符型转换 转为字符串
    12345.ToString("n"); //生成 12,345.00
    12345.ToString("C"); //生成 ¥12,345.00
    12345.ToString("e"); //生成 1.234500e+004
    12345.ToString("f4"); //生成 12345.0000
    12345.ToString("x"); //生成 3039 (16进制)
    12345.ToString("p"); //生成 1,234,500.00%

    13/04/2006

    pragma指令简介 (ZT)

    在编写程序的时候,我们经常要用到#pragma指令来设定编译器的状态或者是指示编译器完成一些特定的动作.
    下面介绍了一下该指令的一些常用参数,希望对大家有所帮助!

    一. message 参数。

    message
    它能够在编译信息输出窗 
    口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为: 

    #pragma message(“消息文本”) 

    当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。 
    当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条
    指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法 
    #ifdef _X86 
    #pragma message(“_X86 macro activated!”) 
    #endif 
    当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_ 
    X86 macro activated!”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了 
     


       
    二. 另一个使用得比较多的#pragma参数是code_seg。格式如: 

    #pragma code_seg( [ [ { push | pop}, ] [ identifier, ] ] [ "segment-name" [, "segment-class" ] )
    该指令用来指定函数在.obj文件中存放的节,观察OBJ文件可以使用VC自带的dumpbin命令行程序,函数在.obj文件中默认的存放节
    为.text节
    如果code_seg没有带参数的话,则函数存放在.text节中
    push (可选参数) 将一个记录放到内部编译器的堆栈中,可选参数可以为一个标识符或者节名
    pop(可选参数) 将一个记录从堆栈顶端弹出,该记录可以为一个标识符或者节名
    identifier (可选参数) 当使用push指令时,为压入堆栈的记录指派的一个标识符,当该标识符被删除的时候和其相关的堆栈中的记录将被弹出堆栈
    "segment-name" (可选参数) 表示函数存放的节名
    例如:
    //默认情况下,函数被存放在.text节中
    void func1() {                  // stored in .text
    }

    //将函数存放在.my_data1节中
    #pragma code_seg(".my_data1")
    void func2() {                  // stored in my_data1
    }

    //r1为标识符,将函数放入.my_data2节中
    #pragma code_seg(push, r1, ".my_data2")
    void func3() {                  // stored in my_data2
    }

    int main() {
    }
     


    三. #pragma once (比较常用) 

    这是一个比较常用的指令,只要在头文件的最开始加入这条指令就能够保证头文件被编译一次


       
    四. #pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。

    BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。  
    有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级,
    如果使用了#pragma package(smart_init) ,BCB就会根据优先级的大小先后编译。  
        


    五. #pragma warning指令

    该指令允许有选择性的修改编译器的警告消息的行为


    指令格式如下:
    #pragma warning( warning-specifier : warning-number-list [; warning-specifier : warning-number-list...]
    #pragma warning( push[ ,n ] )
    #pragma warning( pop )

    主要用到的警告表示有如下几个:

    once:只显示一次(警告/错误等)消息
    default:重置编译器的警告行为到默认状态
    1,2,3,4:四个警告级别
    disable:禁止指定的警告信息
    error:将指定的警告信息作为错误报告

    如果大家对上面的解释不是很理解,可以参考一下下面的例子及说明
     
    #pragma warning( disable : 4507 34; once : 4385; error : 164 ) 
    等价于: 
    #pragma warning(disable:4507 34)  // 不显示4507和34号警告信息 
    #pragma warning(once:4385)        // 4385号警告信息仅报告一次 
    #pragma warning(error:164)        // 把164号警告信息作为一个错误。 
    同时这个pragma warning 也支持如下格式: 
    #pragma warning( push [ ,n ] ) 
    #pragma warning( pop ) 
    这里n代表一个警告等级(1---4)。 
    #pragma warning( push )保存所有警告信息的现有的警告状态。 
    #pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告 
    等级设定为n。  
    #pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的 
    一切改动取消。例如: 
    #pragma warning( push ) 
    #pragma warning( disable : 4705 ) 
    #pragma warning( disable : 4706 ) 
    #pragma warning( disable : 4707 ) 
    #pragma warning( pop )

    在这段代码的最后,重新保存所有的警告信息(包括4705,4706和4707)

    在使用标准C++进行编程的时候经常会得到很多的警告信息,而这些警告信息都是不必要的提示,
    所以我们可以使用#pragma warning(disable:4786)来禁止该类型的警告

    在vc中使用ADO的时候也会得到不必要的警告信息,这个时候我们可以通过
    #pragma warning(disable:4146)来消除该类型的警告信息

     

     
    六. pragma comment(...)
    该指令的格式为
    #pragma comment( "comment-type" [, commentstring] )
     

    该指令将一个注释记录放入一个对象文件或可执行文件中,
    comment-type(注释类型):可以指定为五种预定义的标识符的其中一种
    五种预定义的标识符为:

    compiler:将编译器的版本号和名称放入目标文件中,本条注释记录将被编译器忽略
             如果你为该记录类型提供了commentstring参数,编译器将会产生一个警告
    例如:#pragma comment( compiler )

    exestr:将commentstring参数放入目标文件中,在链接的时候这个字符串将被放入到可执行文件中,
           当操作系统加载可执行文件的时候,该参数字符串不会被加载到内存中.但是,该字符串可以被
           dumpbin之类的程序查找出并打印出来,你可以用这个标识符将版本号码之类的信息嵌入到可
           执行文件中!

    lib:这是一个非常常用的关键字,用来将一个库文件链接到目标文件中


    常用的lib关键字,可以帮我们连入一个库文件。 
    例如:
    #pragma comment(lib, "user32.lib") 
    该指令用来将user32.lib库文件加入到本工程中


    linker:将一个链接选项放入目标文件中,你可以使用这个指令来代替由命令行传入的或者在开发环境中
           设置的链接选项,你可以指定/include选项来强制包含某个对象,例如:
           #pragma comment(linker, "/include:__mySymbol")

    你可以在程序中设置下列链接选项

    /DEFAULTLIB
    /EXPORT
    /INCLUDE
    /MERGE
    /SECTION
    这些选项在这里就不一一说明了,详细信息请看msdn!

    user:将一般的注释信息放入目标文件中commentstring参数包含注释的文本信息,这个注释记录将被链接器忽略
    例如:
    #pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ )

     
    补充一个

     

    #pragma pack(n)

    控制对齐 如

     
    #pragma pack(push)
    #pragma pack(1)
    struct s_1{
    char szname[1];
    int a;
    };
    #pragma pack(pop)
    struct s_2{
    char szname[1];
    int a;
    };

     
    printf("s_1 size : %d\n", sizeof(struct s_1));
    printf("s_2 size : %d\n", sizeof(struct s_2));
    得到5,8。

    上面所说的#pragma指令并没有包含所有的参数说明,本人只是提供了一些相对来说比较常用的参数,有不当的地方还
    请大家指点!
     

    #pragma 预处理指令详解(ZT)

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
    其格式一般为: #Pragma Para
    其中Para 为参数,下面来看一些常用的参数。


    (1)message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗
    口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:
    #Pragma message(“消息文本”)
    当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
    当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法
    #ifdef _X86
    #Pragma message(“_X86 macro activated!”)
    #endif
    当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_
    X86 macro activated!”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了


    (2)另一个使用得比较多的pragma参数是code_seg。格式如:
    #pragma code_seg( ["section-name"[,"section-class"] ] )
    它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。

    (3)#pragma once (比较常用)
    只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。

    (4)#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。
    有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级,如果使用了#pragma package(smart_init) ,BCB就会根据优先级的大小先后编译。

    (5)#pragma resource "*.dfm"表示把*.dfm文件中的资源加入工程。*.dfm中包括窗体
    外观的定义。

    (6)#pragma warning( disable : 4507 34; once : 4385; error : 164 )
    等价于:
    #pragma warning(disable:4507 34) // 不显示4507和34号警告信息
    #pragma warning(once:4385) // 4385号警告信息仅报告一次
    #pragma warning(error:164) // 把164号警告信息作为一个错误。
    同时这个pragma warning 也支持如下格式:
    #pragma warning( push [ ,n ] )
    #pragma warning( pop )
    这里n代表一个警告等级(1---4)。
    #pragma warning( push )保存所有警告信息的现有的警告状态。
    #pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告
    等级设定为n。
    #pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的
    一切改动取消。例如:
    #pragma warning( push )
    #pragma warning( disable : 4705 )
    #pragma warning( disable : 4706 )
    #pragma warning( disable : 4707 )
    //.......
    #pragma warning( pop )
    在这段代码的最后,重新保存所有的警告信息(包括4705,4706和4707)。
    (7)pragma comment(...)
    该指令将一个注释记录放入一个对象文件或可执行文件中。
    常用的lib关键字,可以帮我们连入一个库文件。
    (8)用pragma导出dll中的函数

        传统的到出 DLL 函数的方法是使用模块定义文件 (.def),Visual C++ 提供了更简洁方便的方法,那就是“__declspec()”关键字后面跟“dllexport”,告诉连接去要导出这个函数,例如:

    __declspec(dllexport) int __stdcall MyExportFunction(int iTest);

        把“__declspec(dllexport)”放在函数声明的最前面,连接生成的 DLL 就会导出函数“_MyExportFunction@4”。

        上面的导出函数的名称也许不是我的希望的,我们希望导出的是原版的“MyExportFunction”。还好,VC 提供了一个预处理指示符“#pragma”来指定连接选项 (不仅仅是这一个功能,还有很多指示功能) ,如下:

    #pragma comment(linker,"/EXPORT:MyExportFunction=_MyExportFunction@4")

        这下就天如人愿了:)。如果你想指定导出的顺序,或者只将函数导出为序号,没有 Entryname,这个预处理指示符 (确切地说是连接器) 都能够实现,看看 MSDN 的语法说明:

    /EXPORT:entryname[,@ordinal[,NONAME]][,DATA]

       @ordinal 指定顺序;NONAME 指定只将函数导出为序号;DATA 关键字指定导出项为数据项。



    每个编译程序可以用#pragma指令激活或终止该编译程序支持的一些编译功能。例如,对循环优化功能:
    #pragma loop_opt(on) // 激活
    #pragma loop_opt(off) // 终止
    有时,程序中会有些函数会使编译器发出你熟知而想忽略的警告,如“Parameter xxx is never used in function xxx”,可以这样:
    #pragma warn —100 // Turn off the warning message for warning #100
    int insert_record(REC *r)
    { /* function body */ }
    #pragma warn +100 // Turn the warning message for warning #100 back on
    函数会产生一条有唯一特征码100的警告信息,如此可暂时终止该警告。
    每个编译器对#pragma的实现不同,在一个编译器中有效在别的编译器中几乎无效。可从编译器的文档中查看。
    05/09/2005

    如何通过139端口远程重起NT服务器

    转至:Shotgun

    最近很多朋友问我:NT的机器如果远程管理软件坏了,怎么重起呢?
    其实,如果服务器的139端口开着,重起是很简单的,步骤如下:

    1、net use \\xxx.xxx.xxx.xxx\ipc$ password /user:username
      建立一个IPC会话

    2、net use H: \\xxx.xxx.xxx.xxx\c$
      将对方的C盘映射为自己的H盘

    3、copy con h:\reboot.bat
      iisreset /reboot
      CTRL+Z
      在对方的C盘上生成了一个能重启计算机的文件

    4、net time \\xxx.xxx.xxx.xxx
      得到对方的时间

    5、at \\xxx.xxx.xxx.xxx 重起的时间 c:\reboot.bat
      重起的时间等于对方的时间加几分钟

    6、at \\xxx.xxx.xxx.xxx
      看看任务加上没有

    7、等......

    上面的第三步是only for WIN2K的,如果是NT,你需要用一个特定的重起程序,
    我们可以自己编写一个reboot.exe来取代reboot.bat,原理很简单,代码如下:
    #include "stdio.h"
    #include "windows.h"
    int main()
    {
         //定义重起的时候发送给所有用户的消息
         LPSTR msg="Reboot Tool By Lion Hook\nhttp://www.xici.net";
         //尝试用最简单的API函数重起
         if(ExitWindowsEx(EWX_REBOOT, 0))return TRUE;
         if(ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0))return TRUE;
         //因为上面的重起不成功,所以需要调整本进程的特权
         HANDLE hToken;
         TOKEN_PRIVILEGES tkp;
         if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return FALSE;
         //获取重起的特权SE_SHUTDOWN_NAME
         LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
         tkp.PrivilegeCount = 1;
         tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
         AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
         //判断是NT内核还是9x内核,选择用不同的方式
         if(!(GetVersion() & 0x80000000))
           InitiateSystemShutdown(NULL, msg, 20, TRUE, TRUE);
         else if (!ExitWindowsEx(EWX_REBOOT, 0))
             if(!ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0))
                return FALSE;
         return TRUE;
    }

    netstat命令

    Netstat

      显示协议统计和当前的 TCP/IP 网络连接。该命令只有在安装了 TCP/IP 协议后才可以使用。

      netstat [-a] [-e] [-n] [-s] [-p protocol] [-r] [interval]

      参数

      -a

      显示所有连接和侦听端口。服务器连接通常不显示。

      -e

      显示以太网统计。该参数可以与 -s 选项结合使用。

      -n

      以数字格式显示地址和端口号(而不是尝试查找名称)。

      -s

      显示每个协议的统计。默认情况下,显示 TCP、UDP、ICMP 和 IP 的统计。-p 选项可以用来指定默认的子集。

      -p protocol

      显示由 protocol 指定的协议的连接;protocol 可以是 tcp 或 udp。如果与 -s 选项一同使用显示每个协议的统计,protocol 可以是 tcp、udp、icmp 或 ip。

      -r

      显示路由表的内容。

      interval

      重新显示所选的统计,在每次显示之间暂停 interval 秒。按 CTRL+B 停止重新显示统计。如果省略该参数,netstat 将打印一次当前的配置信息。