Blame tools/tools.c

Packit Service 6d40f9
/*
Packit Service 6d40f9
 * adcli
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * Copyright (C) 2012 Red Hat Inc.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * This program is free software; you can redistribute it and/or modify
Packit Service 6d40f9
 * it under the terms of the GNU Lesser General Public License as
Packit Service 6d40f9
 * published by the Free Software Foundation; either version 2.1 of
Packit Service 6d40f9
 * the License, or (at your option) any later version.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * This program is distributed in the hope that it will be useful, but
Packit Service 6d40f9
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 6d40f9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 6d40f9
 * Lesser General Public License for more details.
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * You should have received a copy of the GNU Lesser General Public
Packit Service 6d40f9
 * License along with this program; if not, write to the Free Software
Packit Service 6d40f9
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
Packit Service 6d40f9
 * MA 02110-1301 USA
Packit Service 6d40f9
 *
Packit Service 6d40f9
 * Author: Stef Walter <stefw@gnome.org>
Packit Service 6d40f9
 */
Packit Service 6d40f9
Packit Service 6d40f9
#include "config.h"
Packit Service 6d40f9
Packit Service 6d40f9
#include "adcli.h"
Packit Service 6d40f9
#include "adprivate.h"
Packit Service 6d40f9
#include "tools.h"
Packit Service 6d40f9
Packit Service 6d40f9
#include <sys/stat.h>
Packit Service 6d40f9
Packit Service 6d40f9
#include <assert.h>
Packit Service 6d40f9
#include <ctype.h>
Packit Service 6d40f9
#include <err.h>
Packit Service 6d40f9
#include <errno.h>
Packit Service 6d40f9
#include <paths.h>
Packit Service 6d40f9
#include <stdio.h>
Packit Service 6d40f9
#include <unistd.h>
Packit Service 6d40f9
Packit Service 6d40f9
Packit Service 6d40f9
static char *adcli_temp_directory = NULL;
Packit Service 6d40f9
static char *adcli_krb5_conf_filename = NULL;
Packit Service 6d40f9
static char *adcli_krb5_d_directory = NULL;
Packit Service 6d40f9
Packit Service 6d40f9
enum {
Packit Service 6d40f9
	CONNECTION_LESS = 1<<0,
Packit Service 6d40f9
};
Packit Service 6d40f9
Packit Service 6d40f9
struct {
Packit Service 6d40f9
	const char *name;
Packit Service 6d40f9
	int (*function) (adcli_conn *, int, char *[]);
Packit Service 6d40f9
	const char *text;
Packit Service 6d40f9
	int flags;
Packit Service 6d40f9
} commands[] = {
Packit Service 6d40f9
	{ "info", adcli_tool_info, "Print information about a domain", CONNECTION_LESS },
Packit Service 6d40f9
	{ "join", adcli_tool_computer_join, "Join this machine to a domain", },
Packit Service 6d40f9
	{ "update", adcli_tool_computer_update, "Update machine membership in a domain", },
Packit Service 6d40f9
	{ "preset-computer", adcli_tool_computer_preset, "Pre setup computers accounts", },
Packit Service 6d40f9
	{ "reset-computer", adcli_tool_computer_reset, "Reset a computer account", },
Packit Service f42a6a
	{ "delete-computer", adcli_tool_computer_delete, "Delete a computer account", },
Packit Service 6d40f9
	{ "create-user", adcli_tool_user_create, "Create a user account", },
Packit Service 6d40f9
	{ "delete-user", adcli_tool_user_delete, "Delete a user account", },
Packit Service 6d40f9
	{ "create-group", adcli_tool_group_create, "Create a group", },
Packit Service 6d40f9
	{ "delete-group", adcli_tool_group_delete, "Delete a group", },
Packit Service 6d40f9
	{ "add-member", adcli_tool_member_add, "Add users to a group", },
Packit Service 6d40f9
	{ "remove-member", adcli_tool_member_remove, "Remove users from a group", },
Packit Service 6d40f9
	{ 0, }
Packit Service 6d40f9
};
Packit Service 6d40f9
Packit Service 6d40f9
static char
Packit Service 6d40f9
short_option (int opt)
Packit Service 6d40f9
{
Packit Service 6d40f9
	if (isalpha (opt) || isdigit (opt))
Packit Service 6d40f9
		return (char)opt;
Packit Service 6d40f9
	return 0;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
static const struct option *
Packit Service 6d40f9
find_option (const struct option *longopts,
Packit Service 6d40f9
             int opt)
Packit Service 6d40f9
{
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	for (i = 0; longopts[i].name != NULL; i++) {
Packit Service 6d40f9
		if (longopts[i].val == opt)
Packit Service 6d40f9
			return longopts + i;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	return NULL;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
void
Packit Service 6d40f9
adcli_tool_usage (const struct option *longopts,
Packit Service 6d40f9
                  const adcli_tool_desc *usages)
Packit Service 6d40f9
{
Packit Service 6d40f9
	const struct option *longopt;
Packit Service 6d40f9
	const int indent = 28;
Packit Service 6d40f9
	const char *description;
Packit Service 6d40f9
	const char *next;
Packit Service 6d40f9
	char short_name;
Packit Service 6d40f9
	int spaces;
Packit Service 6d40f9
	int len;
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	for (i = 0; usages[i].text != NULL; i++) {
Packit Service 6d40f9
Packit Service 6d40f9
		/* If no option, then this is a heading */
Packit Service 6d40f9
		if (!usages[i].option) {
Packit Service 6d40f9
			printf ("%s\n\n", usages[i].text);
Packit Service 6d40f9
			continue;
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		/* Only print out options we can actually parse */
Packit Service 6d40f9
		longopt = find_option (longopts, usages[i].option);
Packit Service 6d40f9
		if (!longopt)
Packit Service 6d40f9
			continue;
Packit Service 6d40f9
Packit Service 6d40f9
		short_name = short_option (usages[i].option);
Packit Service 6d40f9
		if (short_name && longopt->name)
Packit Service 6d40f9
			len = printf ("  -%c, --%s", (int)short_name, longopt->name);
Packit Service 6d40f9
		else if (longopt->name)
Packit Service 6d40f9
			len = printf ("  --%s", longopt->name);
Packit Service 6d40f9
		else
Packit Service 6d40f9
			len = printf ("  -%c", (int)short_name);
Packit Service 6d40f9
		if (longopt->has_arg)
Packit Service 6d40f9
			len += printf ("%s<%s>",
Packit Service 6d40f9
			               longopt->name ? "=" : " ",
Packit Service 6d40f9
			               usages[i].arg ? usages[i].arg : "...");
Packit Service 6d40f9
		if (len < indent) {
Packit Service 6d40f9
			spaces = indent - len;
Packit Service 6d40f9
		} else {
Packit Service 6d40f9
			printf ("\n");
Packit Service 6d40f9
			spaces = indent;
Packit Service 6d40f9
		}
Packit Service 6d40f9
		description = usages[i].text;
Packit Service 6d40f9
		while (description) {
Packit Service 6d40f9
			while (spaces-- > 0)
Packit Service 6d40f9
				fputc (' ', stdout);
Packit Service 6d40f9
			next = strchr (description, '\n');
Packit Service 6d40f9
			if (next) {
Packit Service 6d40f9
				next += 1;
Packit Service 6d40f9
				printf ("%.*s", (int)(next - description), description);
Packit Service 6d40f9
				description = next;
Packit Service 6d40f9
				spaces = indent;
Packit Service 6d40f9
			} else {
Packit Service 6d40f9
				printf ("%s\n", description);
Packit Service 6d40f9
				break;
Packit Service 6d40f9
			}
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
	}
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
int
Packit Service 6d40f9
adcli_tool_getopt (int argc,
Packit Service 6d40f9
                   char *argv[],
Packit Service 6d40f9
                   const struct option *options)
Packit Service 6d40f9
{
Packit Service 6d40f9
	int count = 0;
Packit Service 6d40f9
	char *shorts;
Packit Service 6d40f9
	char *p;
Packit Service 6d40f9
	int ret;
Packit Service 6d40f9
	char opt;
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	/* Number of characters */
Packit Service 6d40f9
	for (i = 0; options[i].name != NULL; i++)
Packit Service 6d40f9
		count++;
Packit Service 6d40f9
Packit Service 6d40f9
	p = shorts = malloc ((count * 2) + 1);
Packit Service 6d40f9
	return_val_if_fail (shorts != NULL, -1);
Packit Service 6d40f9
Packit Service 6d40f9
	for (i = 0; i < count; i++) {
Packit Service 6d40f9
		opt = short_option (options[i].val);
Packit Service 6d40f9
		if (opt != 0) {
Packit Service 6d40f9
			*(p++) = (char)options[i].val;
Packit Service 6d40f9
			if (options[i].has_arg == required_argument)
Packit Service 6d40f9
				*(p++) = ':';
Packit Service 6d40f9
		}
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	*(p++) = '\0';
Packit Service 6d40f9
Packit Service 6d40f9
	ret = getopt_long (argc, argv, shorts, options, NULL);
Packit Service 6d40f9
	free (shorts);
Packit Service 6d40f9
Packit Service 6d40f9
	return ret;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
static void
Packit Service 6d40f9
command_usage (void)
Packit Service 6d40f9
{
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	printf ("usage: adcli command <args>...\n");
Packit Service 6d40f9
	printf ("\nCommon adcli commands are:\n");
Packit Service 6d40f9
	for (i = 0; commands[i].name != NULL; i++)
Packit Service 6d40f9
		printf ("  %-15s  %s\n", commands[i].name, commands[i].text);
Packit Service 6d40f9
	printf ("\nSee 'adcli <command> --help' for more information\n");
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
char *
Packit Service 6d40f9
adcli_prompt_password_func (adcli_login_type login_type,
Packit Service 6d40f9
                            const char *name,
Packit Service 6d40f9
                            int flags,
Packit Service 6d40f9
                            void *unused_data)
Packit Service 6d40f9
{
Packit Service 6d40f9
	char *prompt;
Packit Service 6d40f9
	char *password;
Packit Service 6d40f9
	char *result;
Packit Service 6d40f9
Packit Service 6d40f9
	if (asprintf (&prompt, "Password for %s: ", name) < 0)
Packit Service 6d40f9
		return_val_if_reached (NULL);
Packit Service 6d40f9
Packit Service 6d40f9
	password = getpass (prompt);
Packit Service 6d40f9
	free (prompt);
Packit Service 6d40f9
Packit Service 6d40f9
	if (password == NULL)
Packit Service 6d40f9
		return NULL;
Packit Service 6d40f9
Packit Service 6d40f9
	result = strdup (password);
Packit Service 6d40f9
	adcli_mem_clear (password, strlen (password));
Packit Service 6d40f9
Packit Service 6d40f9
	return result;
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
char *
Packit Service 6d40f9
adcli_read_password_func (adcli_login_type login_type,
Packit Service 6d40f9
                          const char *name,
Packit Service 6d40f9
                          int flags,
Packit Service 6d40f9
                          void *unused_data)
Packit Service 6d40f9
{
Packit Service 6d40f9
	char *buffer = NULL;
Packit Service 6d40f9
	size_t length = 0;
Packit Service 6d40f9
	size_t offset = 0;
Packit Service 6d40f9
	ssize_t res;
Packit Service 6d40f9
Packit Service 6d40f9
	for (;;) {
Packit Service 6d40f9
		if (offset >= length) {
Packit Service 6d40f9
			length += 4096;
Packit Service 6d40f9
			buffer = realloc (buffer, length + 1);
Packit Service 6d40f9
			return_val_if_fail (buffer != NULL, NULL);
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		res = read (0, buffer + offset, length - offset);
Packit Service 6d40f9
		if (res < 0) {
Packit Service 6d40f9
			if (errno == EAGAIN || errno == EINTR)
Packit Service 6d40f9
				continue;
Packit Service bc2650
			err (EFAIL, "couldn't read password from stdin");
Packit Service 6d40f9
Packit Service 6d40f9
		} else if (res == 0) {
Packit Service 6d40f9
			buffer[offset] = '\0';
Packit Service 6d40f9
			/* remove new line character */
Packit Service 6d40f9
			if (offset > 0 && buffer[offset - 1] == '\n') {
Packit Service 6d40f9
				buffer[offset - 1] = '\0';
Packit Service 6d40f9
				if (offset > 1 && buffer[offset - 2] == '\r') {
Packit Service 6d40f9
					buffer[offset - 2] = '\0';
Packit Service 6d40f9
				}
Packit Service 6d40f9
			}
Packit Service 6d40f9
			return buffer;
Packit Service 6d40f9
Packit Service 6d40f9
		} else {
Packit Service bc2650
			if (memchr (buffer + offset, 0, res))
Packit Service bc2650
				errx (EUSAGE, "unsupported null character present in password");
Packit Service 6d40f9
			offset += res;
Packit Service 6d40f9
		}
Packit Service 6d40f9
	}
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
static void
Packit Service 6d40f9
cleanup_krb5_conf_directory (void)
Packit Service 6d40f9
{
Packit Service 6d40f9
	if (adcli_krb5_d_directory) {
Packit Service 6d40f9
		rmdir (adcli_krb5_d_directory);
Packit Service 6d40f9
		free (adcli_krb5_d_directory);
Packit Service 6d40f9
		adcli_krb5_d_directory = NULL;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (adcli_krb5_conf_filename) {
Packit Service 6d40f9
		unlink (adcli_krb5_conf_filename);
Packit Service 6d40f9
		free (adcli_krb5_conf_filename);
Packit Service 6d40f9
		adcli_krb5_conf_filename = NULL;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (adcli_temp_directory) {
Packit Service 6d40f9
		rmdir (adcli_temp_directory);
Packit Service 6d40f9
		free (adcli_temp_directory);
Packit Service 6d40f9
		adcli_temp_directory = NULL;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	unsetenv ("KRB5_CONFIG");
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
static void
Packit Service 6d40f9
setup_krb5_conf_directory (adcli_conn *conn)
Packit Service 6d40f9
{
Packit Service 6d40f9
	const char *parent;
Packit Service 6d40f9
	const char *krb5_conf;
Packit Service 6d40f9
	char *filename = NULL;
Packit Service 6d40f9
	char *snippets = NULL;
Packit Service 6d40f9
	char *contents = NULL;
Packit Service 6d40f9
	char *directory = NULL;
Packit Service 6d40f9
	struct stat sb;
Packit Service 6d40f9
	int failed = 0;
Packit Service 6d40f9
	int errn = 0;
Packit Service 6d40f9
	FILE *fo;
Packit Service 6d40f9
Packit Service 6d40f9
	krb5_conf = getenv ("KRB5_CONFIG");
Packit Service 6d40f9
	if (!krb5_conf || !krb5_conf[0])
Packit Service 6d40f9
		krb5_conf = KRB5_CONFIG;
Packit Service 6d40f9
Packit Service 6d40f9
	parent = getenv ("TMPDIR");
Packit Service 6d40f9
	if (!parent || !*parent)
Packit Service 6d40f9
		parent = _PATH_TMP;
Packit Service 6d40f9
Packit Service 6d40f9
	/* Check that the config file exists, don't include if not */
Packit Service 6d40f9
	if (stat (krb5_conf, &sb) < 0) {
Packit Service 6d40f9
		if (errno != ENOENT)
Packit Service 6d40f9
			warn ("couldn't access file: %s", krb5_conf);
Packit Service 6d40f9
		krb5_conf = NULL;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (asprintf (&directory, "%s%sadcli-krb5-XXXXXX", parent,
Packit Service bc2650
	              (parent[0] && parent[strlen(parent) - 1] == '/') ? "" : "/") < 0)
Packit Service bc2650
		errx (1, "unexpected: out of memory");
Packit Service 579e0b
Packit Service bc2650
	if (mkdtemp (directory) == NULL) {
Packit Service bc2650
		errn = errno;
Packit Service bc2650
		failed = 1;
Packit Service bc2650
		warnx ("couldn't create temporary directory in: %s: %s",
Packit Service bc2650
		       parent, strerror (errn));
Packit Service bc2650
	} else {
Packit Service bc2650
		if (asprintf (&filename, "%s/krb5.conf", directory) < 0 ||
Packit Service bc2650
		    asprintf (&snippets, "%s/krb5.d", directory) < 0 ||
Packit Service bc2650
		    asprintf (&contents, "includedir %s\n%s%s\n", snippets,
Packit Service bc2650
		              krb5_conf ? "include " : "",
Packit Service bc2650
		              krb5_conf ? krb5_conf : "") < 0)
Packit Service bc2650
			errx (1, "unexpected: out of memory");
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (!failed) {
Packit Service 6d40f9
		fo = fopen (filename, "wb");
Packit Service 6d40f9
		if (fo == NULL) {
Packit Service 6d40f9
			errn = errno;
Packit Service 6d40f9
			failed = 1;
Packit Service 6d40f9
		} else {
Packit Service 6d40f9
			fwrite (contents, 1, strlen (contents), fo);
Packit Service 6d40f9
			if (ferror (fo)) {
Packit Service 6d40f9
				errn = errno;
Packit Service 6d40f9
				failed = 1;
Packit Service 6d40f9
				fclose (fo);
Packit Service 6d40f9
			} else {
Packit Service 6d40f9
				if (fclose (fo) != 0) {
Packit Service 6d40f9
					failed = 1;
Packit Service 6d40f9
					errn = errno;
Packit Service 6d40f9
				}
Packit Service 6d40f9
			}
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		if (failed) {
Packit Service 6d40f9
			warnx ("couldn't write new krb5.conf file: %s: %s",
Packit Service 6d40f9
			       filename, strerror (errn));
Packit Service 6d40f9
		}
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
Packit Service 6d40f9
	if (!failed && mkdir (snippets, 0700) < 0) {
Packit Service 6d40f9
		errn = errno;
Packit Service 6d40f9
		failed = 1;
Packit Service 6d40f9
		warnx ("couldn't write new krb5.d directory: %s: %s",
Packit Service 6d40f9
		       snippets, strerror (errn));
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (!failed) {
Packit Service 6d40f9
		adcli_conn_set_krb5_conf_dir (conn, snippets);
Packit Service 6d40f9
		adcli_temp_directory = directory;
Packit Service 6d40f9
		adcli_krb5_conf_filename = filename;
Packit Service 6d40f9
		adcli_krb5_d_directory = snippets;
Packit Service 6d40f9
		setenv ("KRB5_CONFIG", adcli_krb5_conf_filename, 1);
Packit Service 6d40f9
Packit Service 6d40f9
	} else {
Packit Service 6d40f9
		free (filename);
Packit Service 6d40f9
		free (snippets);
Packit Service 6d40f9
		free (directory);
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	free (contents);
Packit Service 6d40f9
	atexit (cleanup_krb5_conf_directory);
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
static void
Packit Service 6d40f9
message_func (adcli_message_type type,
Packit Service 6d40f9
              const char *message)
Packit Service 6d40f9
{
Packit Service 6d40f9
	const char *prefix = "";
Packit Service 6d40f9
Packit Service 6d40f9
	switch (type) {
Packit Service 6d40f9
	case ADCLI_MESSAGE_INFO:
Packit Service 6d40f9
		prefix = " * ";
Packit Service 6d40f9
		break;
Packit Service 6d40f9
	case ADCLI_MESSAGE_WARNING:
Packit Service 6d40f9
	case ADCLI_MESSAGE_ERROR:
Packit Service 6d40f9
		prefix = " ! ";
Packit Service 6d40f9
		break;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	fprintf (stderr, "%s%s\n", prefix, message);
Packit Service 6d40f9
}
Packit Service 6d40f9
Packit Service 6d40f9
int
Packit Service 6d40f9
main (int argc,
Packit Service 6d40f9
      char *argv[])
Packit Service 6d40f9
{
Packit Service 6d40f9
	adcli_conn *conn = NULL;
Packit Service 6d40f9
	char *command = NULL;
Packit Service 6d40f9
	int skip;
Packit Service 6d40f9
	int in, out;
Packit Service 6d40f9
	int ret;
Packit Service 6d40f9
	int i;
Packit Service 6d40f9
Packit Service 6d40f9
	/*
Packit Service 6d40f9
	 * Parse the global options. We rearrange the options as
Packit Service 6d40f9
	 * necessary, in order to pass relevant options through
Packit Service 6d40f9
	 * to the commands, but also have them take effect globally.
Packit Service 6d40f9
	 */
Packit Service 6d40f9
Packit Service 6d40f9
	for (in = 1, out = 1; in < argc; in++, out++) {
Packit Service 6d40f9
		skip = 0;
Packit Service 6d40f9
Packit Service 6d40f9
		/* The non-option is the command, take it out of the arguments */
Packit Service 6d40f9
		if (argv[in][0] != '-') {
Packit Service 6d40f9
			if (!command) {
Packit Service 6d40f9
				skip = 1;
Packit Service 6d40f9
				command = argv[in];
Packit Service 6d40f9
			}
Packit Service 6d40f9
Packit Service 6d40f9
		/* The global long options */
Packit Service 6d40f9
		} else if (argv[in][1] == '-') {
Packit Service 6d40f9
			skip = 0;
Packit Service 6d40f9
Packit Service 6d40f9
			if (strcmp (argv[in], "--") == 0) {
Packit Service 6d40f9
				if (!command)
Packit Service 6d40f9
					errx (2, "no command specified");
Packit Service 6d40f9
Packit Service 6d40f9
			} else if (strcmp (argv[in], "--verbose") == 0) {
Packit Service 6d40f9
				adcli_set_message_func (message_func);
Packit Service 6d40f9
Packit Service 6d40f9
			} else if (strcmp (argv[in], "--help") == 0) {
Packit Service 6d40f9
				if (!command) {
Packit Service 6d40f9
					command_usage ();
Packit Service 6d40f9
					return 0;
Packit Service 6d40f9
				}
Packit Service 6d40f9
Packit Service 6d40f9
			} else {
Packit Service 6d40f9
				if (!command)
Packit Service 6d40f9
					errx (2, "unknown option: %s", argv[in]);
Packit Service 6d40f9
			}
Packit Service 6d40f9
Packit Service 6d40f9
		/* The global short options */
Packit Service 6d40f9
		} else {
Packit Service 6d40f9
			skip = 0;
Packit Service 6d40f9
Packit Service 6d40f9
			for (i = 1; argv[in][i] != '\0'; i++) {
Packit Service 6d40f9
				switch (argv[in][i]) {
Packit Service 6d40f9
				case 'h':
Packit Service 6d40f9
					if (!command) {
Packit Service 6d40f9
						command_usage ();
Packit Service 6d40f9
						return 0;
Packit Service 6d40f9
					}
Packit Service 6d40f9
					break;
Packit Service 6d40f9
Packit Service 6d40f9
				case 'v':
Packit Service 6d40f9
					adcli_set_message_func (message_func);
Packit Service 6d40f9
					break;
Packit Service 6d40f9
Packit Service 6d40f9
				default:
Packit Service 6d40f9
					if (!command)
Packit Service 6d40f9
						errx (2, "unknown option: -%c", (int)argv[in][i]);
Packit Service 6d40f9
					break;
Packit Service 6d40f9
				}
Packit Service 6d40f9
			}
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		/* Skipping this argument? */
Packit Service 6d40f9
		if (skip)
Packit Service 6d40f9
			out--;
Packit Service 6d40f9
		else
Packit Service 6d40f9
			argv[out] = argv[in];
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	if (command == NULL) {
Packit Service 6d40f9
		/* As a special favor if someone just typed 'adcli', help them out */
Packit Service 6d40f9
		if (argc == 1)
Packit Service 6d40f9
			command_usage ();
Packit Service 6d40f9
		else
Packit Service 6d40f9
			warnx ("no command specified");
Packit Service 6d40f9
		return 2;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	argc = out;
Packit Service 6d40f9
	conn = NULL;
Packit Service 6d40f9
Packit Service 6d40f9
	/* Look for the command */
Packit Service 6d40f9
	for (i = 0; commands[i].name != NULL; i++) {
Packit Service 6d40f9
		if (strcmp (commands[i].name, command) != 0)
Packit Service 6d40f9
			continue;
Packit Service 6d40f9
Packit Service 6d40f9
		if (!(commands[i].flags & CONNECTION_LESS)) {
Packit Service 6d40f9
			conn = adcli_conn_new (NULL);
Packit Service 6d40f9
			if (conn == NULL)
Packit Service 6d40f9
				errx (-1, "unexpected memory problems");
Packit Service 6d40f9
			adcli_conn_set_password_func (conn, adcli_prompt_password_func, NULL, NULL);
Packit Service 6d40f9
			setup_krb5_conf_directory (conn);
Packit Service 6d40f9
		}
Packit Service 6d40f9
Packit Service 6d40f9
		argv[0] = command;
Packit Service 6d40f9
		ret = (commands[i].function) (conn, argc, argv);
Packit Service 6d40f9
Packit Service 6d40f9
		if (conn)
Packit Service 6d40f9
			adcli_conn_unref (conn);
Packit Service 6d40f9
		return ret;
Packit Service 6d40f9
	}
Packit Service 6d40f9
Packit Service 6d40f9
	/* At this point we have no command */
Packit Service 6d40f9
	errx (2, "'%s' is not a valid adcli command. See 'adcli --help'", command);
Packit Service 6d40f9
}