how the programmers made it possible to run different applications based on command line arguments.
Those are called subcommands in OpenSSL. They include s_cient
, s_server
, digest
, enc
, dec
, x509
, speed
, etc.
Any ideas?
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 knows when its including all the subcommands with the openssl
command, and it defines MONOLITH
to switch "off" the mains
in the subcommands.
And from 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
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.
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)