in zookeeper-client/zookeeper-client-c/src/cli.c [752:1123]
int main(int argc, char **argv) {
static struct option long_options[] = {
{"host", required_argument, NULL, 'h'}, //hostPort
{"ssl", required_argument, NULL, 's'}, //certificate files
{"myid", required_argument, NULL, 'm'}, //myId file
{"cmd", required_argument, NULL, 'c'}, //cmd
{"readonly", no_argument, NULL, 'r'}, //read-only
{"debug", no_argument, NULL, 'd'}, //set log level to DEBUG from the beginning
#ifdef HAVE_CYRUS_SASL_H
// Parameters for SASL authentication.
{"service", required_argument, NULL, 'z'},
{"server-fqdn", required_argument, NULL, 'o'}, //Host used for SASL auth
{"mechlist", required_argument, NULL, 'n'}, //SASL mechanism list
{"user", required_argument, NULL, 'u'}, //SASL user
{"realm", required_argument, NULL, 'l'}, //SASL realm
{"password-file", required_argument, NULL, 'p'},
#endif /* HAVE_CYRUS_SASL_H */
{NULL, 0, NULL, 0},
};
#ifndef THREADED
fd_set rfds, wfds, efds;
int processed=0;
#endif
char buffer[4096];
char p[2048];
#ifdef YCA
char *cert=0;
char appId[64];
#endif
int bufoff = 0;
int flags;
FILE *fh;
#ifdef HAVE_CYRUS_SASL_H
char *service = "zookeeper";
char *serverFQDN = NULL;
char *mechlist = NULL;
char *user = NULL;
char *realm = NULL;
char *passwordFile = NULL;
#endif /* HAVE_CYRUS_SASL_H */
int opt;
int option_index = 0;
verbose = 0;
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
flags = 0;
while ((opt = getopt_long(argc, argv, "h:s:m:c:rdz:o:n:u:l:p:", long_options, &option_index)) != -1) {
switch (opt) {
case 'h':
hostPort = optarg;
break;
case 'm':
clientIdFile = optarg;
break;
case 'r':
flags = ZOO_READONLY;
break;
case 'c':
cmd = optarg;
batchMode = 1;
fprintf(stderr,"Batch mode: %s\n",cmd);
break;
case 's':
cert = optarg;
break;
case 'd':
verbose = 1;
zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
fprintf(stderr, "logging level set to DEBUG\n");
break;
#ifdef HAVE_CYRUS_SASL_H
case 'z':
service = optarg;
break;
case 'o':
serverFQDN = optarg;
break;
case 'n':
mechlist = optarg;
break;
case 'u':
user = optarg;
break;
case 'l':
realm = optarg;
break;
case 'p':
passwordFile = optarg;
break;
#endif /* HAVE_CYRUS_SASL_H */
case '?':
if (optopt == 'h') {
fprintf (stderr, "Option -%c requires host list.\n", optopt);
} else if (isprint (optopt)) {
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
} else {
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
}
}
}
if (!hostPort && optind < argc) {
/*
* getopt_long did not find a '-h <connect-string>' option.
*
* The invoker may be using using the "old-style" command
* syntax, with positional parameters and "magical" prefixes
* such as 'cmd:'; let's see if we can make sense of it.
*/
hostPort = argv[optind++];
if (optind < argc && !cmd && !clientIdFile) {
int batchModeRes = handleBatchMode(argv[optind], &cmd);
if (batchModeRes == 1) {
batchMode=1;
fprintf(stderr, "Batch mode: '%s'\n", cmd);
} else {
clientIdFile = argv[optind];
}
optind++;
}
}
if (!hostPort || optind < argc) {
fprintf(stderr,
"\nUSAGE: %s -h zk_host_1:port_1,zk_host_2:port_2,... [OPTIONAL ARGS]\n\n"
"MANDATORY ARGS:\n"
"-h, --host <host:port pairs> Comma separated list of ZooKeeper host:port pairs\n\n"
"OPTIONAL ARGS:\n"
"-m, --myid <clientid file> Path to the file contains the client ID\n"
"-c, --cmd <command> Command to execute, e.g. ls|ls2|create|create2|od|...\n"
#ifdef HAVE_OPENSSL_H
"-s, --ssl <ssl params> Comma separated parameters to initiate SSL connection\n"
" e.g.: server_cert.crt,client_cert.crt,client_priv_key.pem,passwd\n"
#endif
#ifdef HAVE_CYRUS_SASL_H
"-u, --user <user> SASL user name\n"
"-n, --mechlist <mechlist> Comma separated list of SASL mechanisms (GSSAPI and/or DIGEST-MD5)\n"
"-o, --server-fqdn <fqdn> SASL server name ('zk-sasl-md5' for DIGEST-MD5; default: reverse DNS lookup)\n"
"-p, --password-file <file> File containing the password (recommended for SASL/DIGEST-MD5)\n"
"-l, --realm <realm> Realm (for SASL/GSSAPI)\n"
"-z, --service <service> SASL service parameter (default: 'zookeeper')\n"
#endif /* HAVE_CYRUS_SASL_H */
"-r, --readonly Connect in read-only mode\n"
"-d, --debug Activate debug logs right from the beginning (you can also use the \n"
" command 'verbose' later to activate debug logs in the cli shell)\n\n",
argv[0]);
#ifdef HAVE_CYRUS_SASL_H
fprintf(stderr,
"SASL EXAMPLES:\n"
"$ %s --mechlist DIGEST-MD5 --user bob --password-file bob.secret --server-fqdn zk-sasl-md5 -h ...\n"
"$ %s --mechlist GSSAPI --user bob --realm BOBINC.COM -h ...\n"
"Notes:\n"
" * SASL and SSL support are currently incompatible (ZOOKEEPER-3482);\n"
" * SASL parameters map to Cyrus SASL's _new/_start APIs and callbacks;\n"
" * DIGEST-MD5 requires '--server-fqdn zk-sasl-md5' for historical reasons.\n"
" * Passwords are obtained via the obsolete 'getpass()' if not provided via '--password-file'.\n"
"\n",
argv[0], argv[0]);
#endif /* HAVE_CYRUS_SASL_H */
fprintf(stderr,
"Version: ZooKeeper cli (c client) version %s\n",
ZOO_VERSION);
return 2;
}
if (clientIdFile) {
fh = fopen(clientIdFile, "r");
if (fh) {
if (fread(&myid, sizeof(myid), 1, fh) != 1) {
memset(&myid, 0, sizeof(myid));
}
fclose(fh);
}
}
#ifdef YCA
strcpy(appId,"yahoo.example.yca_test");
cert = yca_get_cert_once(appId);
if(cert!=0) {
fprintf(stderr,"Certificate for appid [%s] is [%s]\n",appId,cert);
strncpy(p,cert,sizeof(p)-1);
free(cert);
} else {
fprintf(stderr,"Certificate for appid [%s] not found\n",appId);
strcpy(p,"dummy");
}
#else
strcpy(p, "dummy");
#endif
zoo_deterministic_conn_order(1); // enable deterministic order
#ifdef HAVE_CYRUS_SASL_H
/*
* We need to disable the deprecation warnings as Apple has
* decided to deprecate all of CyrusSASL's functions with OS 10.11
* (see MESOS-3030, ZOOKEEPER-4201). We are using GCC pragmas also
* for covering clang.
*/
#ifdef __APPLE__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
if (mechlist) {
zoo_sasl_params_t sasl_params = { 0 };
int sr;
if (cert) {
fprintf(stderr, "SASL and SSL support are currently incompatible (ZOOKEEPER-3482); exiting.\n");
return 1;
}
sr = sasl_client_init(NULL);
if (sr != SASL_OK) {
fprintf(stderr, "Unable to initialize SASL library: %s\n",
sasl_errstring(sr, NULL, NULL));
return 1;
}
sasl_params.service = service;
sasl_params.host = serverFQDN;
sasl_params.mechlist = mechlist;
sasl_params.callbacks = zoo_sasl_make_basic_callbacks(user, realm,
passwordFile);
zh = zookeeper_init_sasl(hostPort, watcher, 30000, &myid, NULL, flags,
NULL, &sasl_params);
if (!zh) {
return errno;
}
}
#ifdef __APPLE__
#pragma GCC diagnostic pop
#endif
#endif /* HAVE_CYRUS_SASL_H */
if (!zh) {
#ifdef HAVE_OPENSSL_H
if (!cert) {
zh = zookeeper_init(hostPort, watcher, 30000, &myid, NULL, flags);
} else {
zh = zookeeper_init_ssl(hostPort, cert, watcher, 30000, &myid, NULL, flags);
}
#else
zh = zookeeper_init(hostPort, watcher, 30000, &myid, NULL, flags);
#endif
if (!zh) {
return errno;
}
}
#ifdef YCA
if(zoo_add_auth(zh,"yca",p,strlen(p),0,0)!=ZOK)
return 2;
#endif
#ifdef THREADED
if (batchMode) {
processline(cmd);
}
while(!shutdownThisThing) {
int rc, len;
if (batchMode) {
// We are just waiting for the asynchronous command to complete.
millisleep(10);
continue;
}
len = sizeof(buffer) - bufoff -1;
if (len <= 0) {
fprintf(stderr, "Can't handle lines that long!\n");
exit(2);
}
rc = read(0, buffer+bufoff, len);
if (rc <= 0) {
fprintf(stderr, "bye\n");
shutdownThisThing=1;
break;
}
bufoff += rc;
buffer[bufoff] = '\0';
while (strchr(buffer, '\n')) {
char *ptr = strchr(buffer, '\n');
*ptr = '\0';
processline(buffer);
ptr++;
memmove(buffer, ptr, strlen(ptr)+1);
bufoff = 0;
}
}
#else
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
while (!shutdownThisThing) {
int fd;
int interest;
int events;
struct timeval tv;
int rc;
zookeeper_interest(zh, &fd, &interest, &tv);
if (fd != -1) {
if (interest&ZOOKEEPER_READ) {
FD_SET(fd, &rfds);
} else {
FD_CLR(fd, &rfds);
}
if (interest&ZOOKEEPER_WRITE) {
FD_SET(fd, &wfds);
} else {
FD_CLR(fd, &wfds);
}
} else {
fd = 0;
}
FD_SET(0, &rfds);
rc = select(fd+1, &rfds, &wfds, &efds, &tv);
events = 0;
if (rc > 0) {
if (FD_ISSET(fd, &rfds)) {
events |= ZOOKEEPER_READ;
}
if (FD_ISSET(fd, &wfds)) {
events |= ZOOKEEPER_WRITE;
}
}
if(batchMode && processed==0){
//batch mode
processline(cmd);
processed=1;
}
if (!processed && FD_ISSET(0, &rfds)) {
int rc;
int len = sizeof(buffer) - bufoff -1;
if (len <= 0) {
fprintf(stderr, "Can't handle lines that long!\n");
exit(2);
}
rc = read(0, buffer+bufoff, len);
if (rc <= 0) {
fprintf(stderr, "bye\n");
break;
}
bufoff += rc;
buffer[bufoff] = '\0';
while (strchr(buffer, '\n')) {
char *ptr = strchr(buffer, '\n');
*ptr = '\0';
processline(buffer);
ptr++;
memmove(buffer, ptr, strlen(ptr)+1);
bufoff = 0;
}
}
zookeeper_process(zh, events);
}
#endif
if (to_send!=0)
fprintf(stderr,"Recvd %d responses for %d requests sent\n",recvd,sent);
zookeeper_close(zh);
return 0;
}