static int
parse_options (int argc, char *argv[], bool has_connection)
{
        uint16_t port = GLUSTER_DEFAULT_PORT;
        int ret = -1;
        int opt = 0;
        int option_index = 0;
        struct xlator_option *option;

        // Reset getopt since other utilities may have called it already.
        optind = 0;
        while (true) {
                opt = getopt_long (argc, argv, "fro:p:", long_options,
                                   &option_index);

                if (opt == -1) {
                        break;
                }

                switch (opt) {
                        case 'd':
                                state->debug = true;
                                break;
                        case 'f':
                                state->force = true;
                                break;
                        case 'o':
                                option = parse_xlator_option (optarg);
                                if (option == NULL) {
                                        error (0, errno, "%s", optarg);
                                        goto err;
                                }

                                if (append_xlator_option (&state->xlator_options, option) == -1) {
                                        error (0, errno, "append_xlator_option: %s", optarg);
                                        goto err;
                                }

                                break;
                        case 'p':
                                port = strtoport (optarg);
                                if (port == 0) {
                                        goto out;
                                }

                                break;
                        case 'r':
                                state->directory = true;
                                break;
                        case 'v':
                                printf ("%s (%s) %s\n%s\n%s\n%s\n",
                                        program_invocation_name,
                                        PACKAGE_NAME,
                                        PACKAGE_VERSION,
                                        COPYRIGHT,
                                        LICENSE,
                                        AUTHORS);
                                ret = -2;
                                goto out;
                        case 'x':
                                usage ();
                                ret = -2;
                                goto out;
                        default:
                                goto err;
                }
        }

        if ((argc - option_index) < 2) {
                error (0, 0, "missing operand");
                goto err;
        } else {
                // state->url is free'd in do_rm()
                state->url = strdup (argv[argc - 1]);
                if (state->url == NULL) {
                        error (0, errno, "strdup");
                        goto out;
                }

                // state->gluster_url is free'd in do_rm()
                if (has_connection) {
                        state->gluster_url = gluster_url_init ();
                        if (state->gluster_url == NULL) {
                                error (0, errno, "gluster_url_init");
                                goto out;
                        }

                        state->gluster_url->path = strdup (argv[argc - 1]);
                        if (state->gluster_url->path == NULL) {
                                error (0, errno, "strdup");
                                goto out;
                        }

                        ret = 0;
                        goto out;
                }

                ret = gluster_parse_url (argv[argc - 1], &(state->gluster_url));
                if (ret == -1) {
                        error (0, EINVAL, "%s", state->url);
                        goto err;
                }

                state->gluster_url->port = port;
        }

        goto out;

err:
        error (0, 0, "Try --help for more information.");
out:
        return ret;
}
int
cli_connect (struct cli_context *ctx)
{
        int argc = ctx->argc;
        char **argv = ctx->argv;
        int ret;
        int opt;
        int option_index;
        struct gluster_url *url = NULL;
        glfs_t *fs = NULL;
        uint16_t port = GLUSTER_DEFAULT_PORT;
        struct xlator_option *xlator_options = NULL;
        struct xlator_option *option;

        while ((opt = getopt_long (argc, argv, "o:p:", connect_options, &option_index)) != -1) {
                switch (opt) {
                        case 'o':
                                option = parse_xlator_option (optarg);
                                if (option == NULL) {
                                        error (0, errno, "%s", optarg);
                                        goto err;
                                }

                                if (append_xlator_option (&xlator_options, option) == -1) {
                                        error (0, errno, "append_xlator_option: %s", optarg);
                                        goto err;
                                }

                                break;
                        case 'p':
                                port = strtoport (optarg);
                                if (port == 0) {
                                        goto err;
                                }

                                break;
                        default:
                                goto err;
                }
        }

        ret = gluster_parse_url (argv[argc - 1], &url);
        if (ret == -1) {
                printf ("Usage: %s [OPTION]... URL\n"
                        "Connect to a Gluster volume for this session.\n\n"
                        "  -o, --xlator-option=OPTION   specify a translator option for the\n"
                        "                               connection. Multiple options are supported\n"
                        "                               and take the form xlator.key=value.\n"
                        "  -p, --port=PORT              specify the port on which to connect\n",
                        argv[0]);
                goto err;
        }

        url->port = port;

        ret = gluster_getfs (&fs, url);
        if (ret == -1) {
                error (0, errno, "failed to connect to %s/%s", url->host, url->volume);
                goto err;
        }

        ret = apply_xlator_options (fs, &xlator_options);
        if (ret == -1) {
                error (0, errno, "failed to apply translator options");
                goto err;
        }

        ret = cli_disconnect (ctx);
        if (ret == -1) {
                error (0, 0, "failed to terminate previous connection");
                goto err;
        }

        ctx->fs = fs;
        ctx->url = url;

        // TODO(craigcabrey): Look into using asprintf here.
        // 5 is the length of the string format: (%s/%s)
        size_t length = strlen (ctx->url->host) + strlen (ctx->url->volume) + 5;

        ctx->conn_str = malloc (length);
        if (ctx->conn_str == NULL) {
                error (0, errno, "malloc");
                handle_quit (ctx);
        }

        snprintf (ctx->conn_str,
                        length,
                        "(%s/%s)",
                        ctx->url->host,
                        ctx->url->volume);

        goto out;

err:
        ret = -1;
        gluster_url_free (url);
out:
        return ret;
}
static int
parse_options (int argc, char *argv[], bool has_connection)
{
        uint16_t port = GLUSTER_DEFAULT_PORT;
        int ret = -1;
        int opt = 0;
        int option_index = 0;
        struct xlator_option *option;

        // Reset getopt since other utilities may have called it already.
        optind = 0;
        while (true) {
                opt = getopt_long (argc, argv, "do:p:rvx", long_options,
                                   &option_index);

                if (opt == -1) {
                        break;
                }

                switch (opt) {
                        case 'd':
                                state->debug = true;
                                break;
                        case 'o':
                                option = parse_xlator_option (optarg);
                                if (option == NULL) {
                                        error (0, errno, "%s", optarg);
                                        goto err;
                                }

                                if (append_xlator_option (&state->xlator_options, option) == -1) {
                                        error (0, errno, "append_xlator_option: %s", optarg);
                                        goto err;
                                }

                                break;
                        case 'p':
                                port = strtoport (optarg);
                                if (port == 0) {
                                        goto err;
                                }

                                break;
                        case 'r':
                                state->parents = true;
                                break;
                        case 'v':
                                printf ("%s (%s) %s\n%s\n%s\n%s\n",
                                        program_invocation_name,
                                        PACKAGE_NAME,
                                        PACKAGE_VERSION,
                                        COPYRIGHT,
                                        LICENSE,
                                        AUTHORS);
                                ret = -2;
                                goto out;
                        case 'x':
                                usage ();
                                ret = -2;
                                goto out;
                        default:
                                goto err;
                }
        }

        if ((argc - option_index) < 2) {
                error (0, 0, "missing operand");
                goto err;
        } else {
                state->url = strdup (argv[argc - 1]);
                if (state->url == NULL) {
                        error (0, errno, "strdup");
                        goto out;
                }

                if (has_connection) {
                        state->gluster_url = gluster_url_init ();
                        if (state->gluster_url == NULL) {
                                error (0, errno, "gluster_url_init");
                                goto out;
                        }

                        state->gluster_url->path = strdup (argv[argc - 1]);
                        if (state->gluster_url->path == NULL) {
                                error (0, errno, "strdup");
                                goto out;
                        }

                        ret = 0;
                        goto out;
                }

                ret = gluster_parse_url (argv[argc - 1], &(state->gluster_url));
                if (ret == -1) {
                        error (0, EINVAL, "%s", state->url);
                        goto err;
                }

                state->gluster_url->port = port;

                // gluster_create_path will not create
                // the last directory in a path if that path does not
                // include a trailing slash ('/'), so add one if it does not
                // exist.
                char *path = state->gluster_url->path;
                if (path[strlen (path) - 1] != '/') {
                        strncat (path, "/", strlen (path) + 2);
                }
        }

        goto out;

err:
        error (0, 0, "Try --help for more information.");
out:
        return ret;
}
void
parse_options (int argc, char *argv[])
{
        uint16_t port = GLUSTER_DEFAULT_PORT;
        int ret = -1;
        int opt = 0;
        int option_index = 0;
        struct xlator_option *option;

        while (true) {
                opt = getopt_long (argc, argv, "adfo:p:r", long_options,
                                   &option_index);

                if (opt == -1) {
                        break;
                }

                switch (opt) {
                        case 'a':
                                state->append = true;
                                break;
                        case 'd':
                                state->debug = true;
                                break;
                        case 'f':
                                state->overwrite = true;
                                break;
                        case 'o':
                                option = parse_xlator_option (optarg);
                                if (option == NULL) {
                                        error (0, errno, "%s", optarg);
                                        goto err;
                                }

                                if (append_xlator_option (&state->xlator_options, option) == -1) {
                                        error (EXIT_FAILURE, errno, "append_xlator_option: %s", optarg);
                                }

                                break;
                        case 'p':
                                port = strtoport (optarg);
                                if (port == 0) {
                                        exit (EXIT_FAILURE);
                                }

                                break;
                        case 'r':
                                state->parents = true;
                                break;
                        case 'v':
                                printf ("%s (%s) %s\n%s\n%s\n%s\n",
                                        program_invocation_name,
                                        PACKAGE_NAME,
                                        PACKAGE_VERSION,
                                        COPYRIGHT,
                                        LICENSE,
                                        AUTHORS);
                                exit (EXIT_SUCCESS);
                        case 'x':
                                usage (EXIT_SUCCESS);
                        default:
                                goto err;
                }
        }

        if ((argc - option_index) < 2) {
                error (0, 0, "missing operand");
                goto err;
        } else {
                state->url = strdup (argv[argc - 1]);
                if (state->url == NULL) {
                        error (0, errno, "strdup");
                        goto out;
                }

                ret = gluster_parse_url (argv[argc - 1], &(state->gluster_url));
                if (ret == -1) {
                        error (0, EINVAL, "%s", state->url);
                        goto err;
                }

                state->gluster_url->port = port;
        }

        goto out;

err:
        error (EXIT_FAILURE, 0, "Try --help for more information.");
out:
        return;
}