int main()

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;
}