如何基于命令行参数运行程序的不同“模式"? [英] How to run different 'modes' of a program based on command line parameters?
问题描述
我正在研究Openssl的源代码,以发现程序员如何使基于命令行参数运行不同的应用程序成为可能.例如:我可以运行具有自己选项的openssl speed
,也可以运行具有其自己选项的openssl s_server
,依此类推.在许多操作系统上,这一切都像魅力一样.此外,Openssl还有一些我称为命令行建议"的东西,当我按制表键时,它会建议可用的选项.
I'm looking into Openssl's source code to find out how the programmers made it possible to run different applications based on command line arguments. For instance: I can run openssl speed
, which has its own options, I can run openssl s_server
which has its own options as well, and so on. It all works like a charm on many operating systems. Besides, Openssl have something which I call 'command line suggestions' where it suggests available options when I press the tabulator key.
我正在研究源代码,但是不知道如何在我的应用程序中实现类似的东西.有什么想法吗?
I'm looking into source code but have any clue how to implement something similar in my application. Any ideas?
推荐答案
程序员如何基于命令行参数运行不同的应用程序成为可能.
how the programmers made it possible to run different applications based on command line arguments.
这些在OpenSSL中称为子命令.它们包括s_cient
,s_server
,digest
,enc
,dec
,x509
,speed
等.
Those are called subcommands in OpenSSL. They include s_cient
, s_server
, digest
, enc
, dec
, x509
, speed
, etc.
有什么想法吗?
Any ideas?
OpenSSL为openssl
命令和所有子命令提供一个main
.子命令中的main
被包装在宏中,因此,如果 not 不能构建openssl
命令,则该子命令可以成为其自己的独立程序.
OpenSSL provides a a main
for the openssl
command and all the subcommands. The main
in the subcommand is wrapped in a macro so that if not building openssl
command, then the subcommand can become its own stand-alone program.
这是该宏的用法.所有子命令都可以执行此操作:
Here's what the use of the macro look like. All of the subcommands do this:
int MAIN(int, char **);
int MAIN(int argc, char **argv)
{
...
}
OpenSSL知道何时将所有子命令与openssl
命令一起使用,并且它定义MONOLITH
以在子命令中关闭" mains
.
OpenSSL knows when its including all the subcommands with the openssl
command, and it defines MONOLITH
to switch "off" the mains
in the subcommands.
并且来自apps.h
:
#ifndef MONOLITH
#define MAIN(a,v) main(a,v)
#ifndef NON_MAIN
CONF *config=NULL;
BIO *bio_err=NULL;
#else
extern CONF *config;
extern BIO *bio_err;
#endif
#else
#define MAIN(a,v) PROG(a,v)
extern CONF *config;
extern char *default_config_file;
extern BIO *bio_err;
#endif
如果是独立构建的子命令,则还需要构建apps.c
并链接到apps.o
,因为它对它们来说是通用的.
If you build the subcommand stand-alone, then you will also need to build apps.c
and link to apps.o
because its common to them.
如果我没记错的话,当使用预处理器魔术来定义MONOLITH
时,PROG
会展开为prog_xxx
之类的内容,其中xxx
是所讨论的子命令.因此,它们看起来像一堆函数:prog_s_cient
,prog_s_server
,prog_digest
等.
If I recall correctly, PROG
unrolls to something like prog_xxx
when MONOLITH
is defined using preprocessor magic, where xxx
is the subcommand in question. So they just look like a bunch of functions: prog_s_cient
, prog_s_server
, prog_digest
, etc.
$ cd apps
$ grep -R MAIN *
app_rand.c:#define NON_MAIN
app_rand.c:#undef NON_MAIN
apps.c:#define NON_MAIN
apps.c:#undef NON_MAIN
apps.h:#define MAIN(a,v) main(a,v)
apps.h:#ifndef NON_MAIN
apps.h:#define MAIN(a,v) PROG(a,v)
asn1pars.c:int MAIN(int, char **);
asn1pars.c:int MAIN(int argc, char **argv)
ca.c:int MAIN(int, char **);
ca.c:int MAIN(int argc, char **argv)
ciphers.c:int MAIN(int, char **);
ciphers.c:int MAIN(int argc, char **argv)
cms.c:int MAIN(int, char **);
cms.c:int MAIN(int argc, char **argv)
crl.c:int MAIN(int, char **);
crl.c:int MAIN(int argc, char **argv)
crl2p7.c:int MAIN(int, char **);
crl2p7.c:int MAIN(int argc, char **argv)
dgst.c:int MAIN(int, char **);
dgst.c:int MAIN(int argc, char **argv)
dh.c:int MAIN(int, char **);
dh.c:int MAIN(int argc, char **argv)
dhparam.c:int MAIN(int, char **);
dhparam.c:int MAIN(int argc, char **argv)
dsa.c:int MAIN(int, char **);
dsa.c:int MAIN(int argc, char **argv)
dsaparam.c:int MAIN(int, char **);
dsaparam.c:int MAIN(int argc, char **argv)
ec.c:int MAIN(int, char **);
ec.c:int MAIN(int argc, char **argv)
ecparam.c:int MAIN(int, char **);
ecparam.c:int MAIN(int argc, char **argv)
enc.c:int MAIN(int, char **);
enc.c:int MAIN(int argc, char **argv)
engine.c:int MAIN(int, char **);
engine.c:int MAIN(int argc, char **argv)
errstr.c:int MAIN(int, char **);
errstr.c:int MAIN(int argc, char **argv)
gendh.c:int MAIN(int, char **);
gendh.c:int MAIN(int argc, char **argv)
gendsa.c:int MAIN(int, char **);
gendsa.c:int MAIN(int argc, char **argv)
genpkey.c:int MAIN(int, char **);
genpkey.c:int MAIN(int argc, char **argv)
genrsa.c:int MAIN(int, char **);
genrsa.c:int MAIN(int argc, char **argv)
nseq.c:int MAIN(int, char **);
nseq.c:int MAIN(int argc, char **argv)
ocsp.c:int MAIN(int, char **);
ocsp.c:int MAIN(int argc, char **argv)
passwd.c:int MAIN(int, char **);
passwd.c:int MAIN(int argc, char **argv)
passwd.c:int MAIN(int argc, char **argv)
pkcs12.c:int MAIN(int, char **);
pkcs12.c:int MAIN(int argc, char **argv)
pkcs7.c:int MAIN(int, char **);
pkcs7.c:int MAIN(int argc, char **argv)
pkcs8.c:int MAIN(int, char **);
pkcs8.c:int MAIN(int argc, char **argv)
pkey.c:int MAIN(int, char **);
pkey.c:int MAIN(int argc, char **argv)
pkeyparam.c:int MAIN(int, char **);
pkeyparam.c:int MAIN(int argc, char **argv)
pkeyutl.c:int MAIN(int argc, char **);
pkeyutl.c:int MAIN(int argc, char **argv)
prime.c:int MAIN(int, char **);
prime.c:int MAIN(int argc, char **argv)
rand.c:int MAIN(int, char **);
rand.c:int MAIN(int argc, char **argv)
req.c:int MAIN(int, char **);
req.c:int MAIN(int argc, char **argv)
rsa.c:int MAIN(int, char **);
rsa.c:int MAIN(int argc, char **argv)
rsautl.c:int MAIN(int argc, char **);
rsautl.c:int MAIN(int argc, char **argv)
s_cb.c:#define NON_MAIN
s_cb.c:#undef NON_MAIN
s_client.c:int MAIN(int, char **);
s_client.c:int MAIN(int argc, char **argv)
s_server.c:int MAIN(int, char **);
s_server.c:int MAIN(int argc, char *argv[])
s_socket.c:#define NON_MAIN
s_socket.c:#undef NON_MAIN
s_time.c: * MAIN - main processing area for client
s_time.c:int MAIN(int, char **);
s_time.c:int MAIN(int argc, char **argv)
sess_id.c:int MAIN(int, char **);
sess_id.c:int MAIN(int argc, char **argv)
smime.c:int MAIN(int, char **);
smime.c:int MAIN(int argc, char **argv)
speed.c:int MAIN(int, char **);
speed.c:int MAIN(int argc, char **argv)
spkac.c:int MAIN(int, char **);
spkac.c:int MAIN(int argc, char **argv)
srp.c:int MAIN(int, char **);
srp.c:int MAIN(int argc, char **argv)
ts.c:int MAIN(int, char **);
ts.c:int MAIN(int argc, char **argv)
verify.c:int MAIN(int, char **);
verify.c:int MAIN(int argc, char **argv)
version.c:int MAIN(int, char **);
version.c:int MAIN(int argc, char **argv)
x509.c:int MAIN(int, char **);
x509.c:int MAIN(int argc, char **argv)
这篇关于如何基于命令行参数运行程序的不同“模式"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!