Blame bin/getent.c

Kylie McClain b61f59
/*-
Kylie McClain b61f59
 * Copyright (c) 2004-2006 The NetBSD Foundation, Inc.
Kylie McClain b61f59
 * All rights reserved.
Kylie McClain b61f59
 *
Kylie McClain b61f59
 * This code is derived from software contributed to The NetBSD Foundation
Kylie McClain b61f59
 * by Luke Mewburn.
Kylie McClain b61f59
 * Timo Teräs cleaned up the code for use in Alpine Linux with musl libc.
Kylie McClain b61f59
 *
Kylie McClain b61f59
 * Redistribution and use in source and binary forms, with or without
Kylie McClain b61f59
 * modification, are permitted provided that the following conditions
Kylie McClain b61f59
 * are met:
Kylie McClain b61f59
 * 1. Redistributions of source code must retain the above copyright
Kylie McClain b61f59
 *    notice, this list of conditions and the following disclaimer.
Kylie McClain b61f59
 * 2. Redistributions in binary form must reproduce the above copyright
Kylie McClain b61f59
 *    notice, this list of conditions and the following disclaimer in the
Kylie McClain b61f59
 *    documentation and/or other materials provided with the distribution.
Kylie McClain b61f59
 *
Kylie McClain b61f59
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
Kylie McClain b61f59
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Kylie McClain b61f59
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Kylie McClain b61f59
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
Kylie McClain b61f59
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Kylie McClain b61f59
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Kylie McClain b61f59
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Kylie McClain b61f59
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Kylie McClain b61f59
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Kylie McClain b61f59
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Kylie McClain b61f59
 * POSSIBILITY OF SUCH DAMAGE.
Kylie McClain b61f59
 */
Kylie McClain b61f59
Kylie McClain b61f59
#include <sys/socket.h>
Kylie McClain b61f59
#include <sys/param.h>
Kylie McClain b61f59
#include <ctype.h>
Kylie McClain b61f59
#include <errno.h>
Kylie McClain b61f59
#include <limits.h>
Kylie McClain b61f59
#include <netdb.h>
Kylie McClain b61f59
#include <pwd.h>
Kylie McClain b61f59
#include <grp.h>
Kylie McClain b61f59
#include <stdio.h>
Kylie McClain b61f59
#include <stdarg.h>
Kylie McClain b61f59
#include <stdbool.h>
Kylie McClain b61f59
#include <stdlib.h>
Kylie McClain b61f59
#include <string.h>
Kylie McClain b61f59
#include <unistd.h>
Kylie McClain b61f59
#include <paths.h>
Kylie McClain b61f59
#include <err.h>
Kylie McClain b61f59
Kylie McClain b61f59
#include <arpa/inet.h>
Kylie McClain b61f59
#include <arpa/nameser.h>
Kylie McClain b61f59
Kylie McClain b61f59
#include <net/if.h>
Kylie McClain b61f59
#include <net/ethernet.h>
Kylie McClain b61f59
#include <netinet/ether.h>
Kylie McClain b61f59
#include <netinet/in.h>
Kylie McClain b61f59
Kylie McClain b61f59
enum {
Kylie McClain b61f59
	RV_OK		= 0,
Kylie McClain b61f59
	RV_USAGE	= 1,
Kylie McClain b61f59
	RV_NOTFOUND	= 2,
Kylie McClain b61f59
	RV_NOENUM	= 3
Kylie McClain b61f59
};
Kylie McClain b61f59
Kylie McClain b61f59
static int usage(const char *);
Kylie McClain b61f59
Kylie McClain b61f59
static int parsenum(const char *word, unsigned long *result)
Kylie McClain b61f59
{
Kylie McClain b61f59
	unsigned long	num;
Kylie McClain b61f59
	char		*ep;
Kylie McClain b61f59
Kylie McClain b61f59
	if (!isdigit((unsigned char)word[0]))
Kylie McClain b61f59
		return 0;
Kylie McClain b61f59
	errno = 0;
Kylie McClain b61f59
	num = strtoul(word, &ep, 10);
Kylie McClain b61f59
	if (num == ULONG_MAX && errno == ERANGE)
Kylie McClain b61f59
		return 0;
Kylie McClain b61f59
	if (*ep != '\0')
Kylie McClain b61f59
		return 0;
Kylie McClain b61f59
	*result = num;
Kylie McClain b61f59
	return 1;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
/*
Kylie McClain b61f59
 * printfmtstrings --
Kylie McClain b61f59
 *	vprintf(format, ...),
Kylie McClain b61f59
 *	then the aliases (beginning with prefix, separated by sep),
Kylie McClain b61f59
 *	then a newline
Kylie McClain b61f59
 */
Kylie McClain b61f59
__attribute__ ((format (printf, 4, 5)))
Kylie McClain b61f59
static void printfmtstrings(char *strings[], const char *prefix, const char *sep,
Kylie McClain b61f59
	const char *fmt, ...)
Kylie McClain b61f59
{
Kylie McClain b61f59
	va_list		ap;
Kylie McClain b61f59
	const char	*curpref;
Kylie McClain b61f59
	size_t		i;
Kylie McClain b61f59
Kylie McClain b61f59
	va_start(ap, fmt);
Kylie McClain b61f59
	(void)vprintf(fmt, ap);
Kylie McClain b61f59
	va_end(ap);
Kylie McClain b61f59
Kylie McClain b61f59
	curpref = prefix;
Kylie McClain b61f59
	for (i = 0; strings[i] != NULL; i++) {
Kylie McClain b61f59
		(void)printf("%s%s", curpref, strings[i]);
Kylie McClain b61f59
		curpref = sep;
Kylie McClain b61f59
	}
Kylie McClain b61f59
	(void)printf("\n");
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static int ethers(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	char		hostname[MAXHOSTNAMELEN + 1], *hp;
Kylie McClain b61f59
	struct ether_addr ea, *eap;
Kylie McClain b61f59
	int		i, rv;
Kylie McClain b61f59
Kylie McClain b61f59
	if (argc == 2) {
Kylie McClain b61f59
		warnx("Enumeration not supported on ethers");
Kylie McClain b61f59
		return RV_NOENUM;
Kylie McClain b61f59
	}
Kylie McClain b61f59
Kylie McClain b61f59
	rv = RV_OK;
Kylie McClain b61f59
	for (i = 2; i < argc; i++) {
Kylie McClain b61f59
		if ((eap = ether_aton(argv[i])) == NULL) {
Kylie McClain b61f59
			eap = &ea;
Kylie McClain b61f59
			hp = argv[i];
Kylie McClain b61f59
			if (ether_hostton(hp, eap) != 0) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
		} else {
Kylie McClain b61f59
			hp = hostname;
Kylie McClain b61f59
			if (ether_ntohost(hp, eap) != 0) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
		}
Kylie McClain b61f59
		(void)printf("%-17s  %s\n", ether_ntoa(eap), hp);
Kylie McClain b61f59
	}
Kylie McClain b61f59
	return rv;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static void groupprint(const struct group *gr)
Kylie McClain b61f59
{
Kylie McClain b61f59
	printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u",
Kylie McClain b61f59
			gr->gr_name, gr->gr_passwd, gr->gr_gid);
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static int group(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	struct group	*gr;
Kylie McClain b61f59
	unsigned long	id;
Kylie McClain b61f59
	int		i, rv;
Kylie McClain b61f59
Kylie McClain b61f59
	rv = RV_OK;
Kylie McClain b61f59
	if (argc == 2) {
Kylie McClain b61f59
		while ((gr = getgrent()) != NULL)
Kylie McClain b61f59
			groupprint(gr);
Kylie McClain b61f59
	} else {
Kylie McClain b61f59
		for (i = 2; i < argc; i++) {
Kylie McClain b61f59
			if (parsenum(argv[i], &id))
Kylie McClain b61f59
				gr = getgrgid((gid_t)id);
Kylie McClain b61f59
			else
Kylie McClain b61f59
				gr = getgrnam(argv[i]);
Kylie McClain b61f59
			if (gr == NULL) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
			groupprint(gr);
Kylie McClain b61f59
		}
Kylie McClain b61f59
	}
Kylie McClain b61f59
	endgrent();
Kylie McClain b61f59
	return rv;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static void hostsprint(const struct hostent *he)
Kylie McClain b61f59
{
Kylie McClain b61f59
	char	buf[INET6_ADDRSTRLEN];
Kylie McClain b61f59
Kylie McClain b61f59
	if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
Kylie McClain b61f59
		(void)strlcpy(buf, "# unknown", sizeof(buf));
Kylie McClain b61f59
	printfmtstrings(he->h_aliases, "  ", " ", "%-16s  %s", buf, he->h_name);
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static int hosts(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	struct hostent	*he;
Kylie McClain b61f59
	char		addr[IN6ADDRSZ];
Kylie McClain b61f59
	int		i, rv;
Kylie McClain b61f59
Kylie McClain b61f59
	sethostent(1);
Kylie McClain b61f59
	rv = RV_OK;
Kylie McClain b61f59
	if (argc == 2) {
Kylie McClain b61f59
		while ((he = gethostent()) != NULL)
Kylie McClain b61f59
			hostsprint(he);
Kylie McClain b61f59
	} else {
Kylie McClain b61f59
		for (i = 2; i < argc; i++) {
Kylie McClain b61f59
			if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
Kylie McClain b61f59
				he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
Kylie McClain b61f59
			else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
Kylie McClain b61f59
				he = gethostbyaddr(addr, INADDRSZ, AF_INET);
Kylie McClain b61f59
			else
Kylie McClain b61f59
				he = gethostbyname(argv[i]);
Kylie McClain b61f59
			if (he == NULL) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
			hostsprint(he);
Kylie McClain b61f59
		}
Kylie McClain b61f59
	}
Kylie McClain b61f59
	endhostent();
Kylie McClain b61f59
	return rv;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static void networksprint(const struct netent *ne)
Kylie McClain b61f59
{
Kylie McClain b61f59
	char		buf[INET6_ADDRSTRLEN];
Kylie McClain b61f59
	struct	in_addr	ianet;
Kylie McClain b61f59
Kylie McClain b61f59
	ianet = inet_makeaddr(ne->n_net, 0);
Kylie McClain b61f59
	if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
Kylie McClain b61f59
		(void)strlcpy(buf, "# unknown", sizeof(buf));
Kylie McClain b61f59
	printfmtstrings(ne->n_aliases, "  ", " ", "%-16s  %s", ne->n_name, buf);
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static int networks(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	struct netent	*ne;
Kylie McClain b61f59
	in_addr_t	net;
Kylie McClain b61f59
	int		i, rv;
Kylie McClain b61f59
Kylie McClain b61f59
	setnetent(1);
Kylie McClain b61f59
	rv = RV_OK;
Kylie McClain b61f59
	if (argc == 2) {
Kylie McClain b61f59
		while ((ne = getnetent()) != NULL)
Kylie McClain b61f59
			networksprint(ne);
Kylie McClain b61f59
	} else {
Kylie McClain b61f59
		for (i = 2; i < argc; i++) {
Kylie McClain b61f59
			net = inet_network(argv[i]);
Kylie McClain b61f59
			if (net != INADDR_NONE)
Kylie McClain b61f59
				ne = getnetbyaddr(net, AF_INET);
Kylie McClain b61f59
			else
Kylie McClain b61f59
				ne = getnetbyname(argv[i]);
Kylie McClain b61f59
			if (ne != NULL) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
			networksprint(ne);
Kylie McClain b61f59
		}
Kylie McClain b61f59
	}
Kylie McClain b61f59
	endnetent();
Kylie McClain b61f59
	return rv;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static void passwdprint(struct passwd *pw)
Kylie McClain b61f59
{
Kylie McClain b61f59
	(void)printf("%s:%s:%u:%u:%s:%s:%s\n",
Kylie McClain b61f59
		pw->pw_name, pw->pw_passwd, pw->pw_uid,
Kylie McClain b61f59
		pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell);
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static int passwd(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	struct passwd	*pw;
Kylie McClain b61f59
	unsigned long	id;
Kylie McClain b61f59
	int		i, rv;
Kylie McClain b61f59
Kylie McClain b61f59
	rv = RV_OK;
Kylie McClain b61f59
	if (argc == 2) {
Kylie McClain b61f59
		while ((pw = getpwent()) != NULL)
Kylie McClain b61f59
			passwdprint(pw);
Kylie McClain b61f59
	} else {
Kylie McClain b61f59
		for (i = 2; i < argc; i++) {
Kylie McClain b61f59
			if (parsenum(argv[i], &id))
Kylie McClain b61f59
				pw = getpwuid((uid_t)id);
Kylie McClain b61f59
			else
Kylie McClain b61f59
				pw = getpwnam(argv[i]);
Kylie McClain b61f59
			if (pw == NULL) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
			passwdprint(pw);
Kylie McClain b61f59
		}
Kylie McClain b61f59
	}
Kylie McClain b61f59
	endpwent();
Kylie McClain b61f59
	return rv;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static void protocolsprint(struct protoent *pe)
Kylie McClain b61f59
{
Kylie McClain b61f59
	printfmtstrings(pe->p_aliases, "  ", " ",
Kylie McClain b61f59
			"%-16s  %5d", pe->p_name, pe->p_proto);
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static int protocols(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	struct protoent	*pe;
Kylie McClain b61f59
	unsigned long	id;
Kylie McClain b61f59
	int		i, rv;
Kylie McClain b61f59
Kylie McClain b61f59
	setprotoent(1);
Kylie McClain b61f59
	rv = RV_OK;
Kylie McClain b61f59
	if (argc == 2) {
Kylie McClain b61f59
		while ((pe = getprotoent()) != NULL)
Kylie McClain b61f59
			protocolsprint(pe);
Kylie McClain b61f59
	} else {
Kylie McClain b61f59
		for (i = 2; i < argc; i++) {
Kylie McClain b61f59
			if (parsenum(argv[i], &id))
Kylie McClain b61f59
				pe = getprotobynumber((int)id);
Kylie McClain b61f59
			else
Kylie McClain b61f59
				pe = getprotobyname(argv[i]);
Kylie McClain b61f59
			if (pe == NULL) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
			protocolsprint(pe);
Kylie McClain b61f59
		}
Kylie McClain b61f59
	}
Kylie McClain b61f59
	endprotoent();
Kylie McClain b61f59
	return rv;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static void servicesprint(struct servent *se)
Kylie McClain b61f59
{
Kylie McClain b61f59
	printfmtstrings(se->s_aliases, "  ", " ",
Kylie McClain b61f59
			"%-16s  %5d/%s",
Kylie McClain b61f59
			se->s_name, ntohs(se->s_port), se->s_proto);
Kylie McClain b61f59
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static int services(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	struct servent	*se;
Kylie McClain b61f59
	unsigned long	id;
Kylie McClain b61f59
	char		*proto;
Kylie McClain b61f59
	int		i, rv;
Kylie McClain b61f59
Kylie McClain b61f59
	setservent(1);
Kylie McClain b61f59
	rv = RV_OK;
Kylie McClain b61f59
	if (argc == 2) {
Kylie McClain b61f59
		while ((se = getservent()) != NULL)
Kylie McClain b61f59
			servicesprint(se);
Kylie McClain b61f59
	} else {
Kylie McClain b61f59
		for (i = 2; i < argc; i++) {
Kylie McClain b61f59
			proto = strchr(argv[i], '/');
Kylie McClain b61f59
			if (proto != NULL)
Kylie McClain b61f59
				*proto++ = '\0';
Kylie McClain b61f59
			if (parsenum(argv[i], &id))
Kylie McClain b61f59
				se = getservbyport(htons(id), proto);
Kylie McClain b61f59
			else
Kylie McClain b61f59
				se = getservbyname(argv[i], proto);
Kylie McClain b61f59
			if (se == NULL) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
			servicesprint(se);
Kylie McClain b61f59
		}
Kylie McClain b61f59
	}
Kylie McClain b61f59
	endservent();
Kylie McClain b61f59
	return rv;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static int shells(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	const char	*sh;
Kylie McClain b61f59
	int		i, rv;
Kylie McClain b61f59
Kylie McClain b61f59
	setusershell();
Kylie McClain b61f59
	rv = RV_OK;
Kylie McClain b61f59
	if (argc == 2) {
Kylie McClain b61f59
		while ((sh = getusershell()) != NULL)
Kylie McClain b61f59
			(void)printf("%s\n", sh);
Kylie McClain b61f59
	} else {
Kylie McClain b61f59
		for (i = 2; i < argc; i++) {
Kylie McClain b61f59
			setusershell();
Kylie McClain b61f59
			while ((sh = getusershell()) != NULL) {
Kylie McClain b61f59
				if (strcmp(sh, argv[i]) == 0) {
Kylie McClain b61f59
					(void)printf("%s\n", sh);
Kylie McClain b61f59
					break;
Kylie McClain b61f59
				}
Kylie McClain b61f59
			}
Kylie McClain b61f59
			if (sh == NULL) {
Kylie McClain b61f59
				rv = RV_NOTFOUND;
Kylie McClain b61f59
				break;
Kylie McClain b61f59
			}
Kylie McClain b61f59
		}
Kylie McClain b61f59
	}
Kylie McClain b61f59
	endusershell();
Kylie McClain b61f59
	return rv;
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
static struct getentdb {
Kylie McClain b61f59
	const char	*name;
Kylie McClain b61f59
	int		(*callback)(int, char *[]);
Kylie McClain b61f59
} databases[] = {
Kylie McClain b61f59
	{	"ethers",	ethers,		},
Kylie McClain b61f59
	{	"group",	group,		},
Kylie McClain b61f59
	{	"hosts",	hosts,		},
Kylie McClain b61f59
	{	"networks",	networks,	},
Kylie McClain b61f59
	{	"passwd",	passwd,		},
Kylie McClain b61f59
	{	"protocols",	protocols,	},
Kylie McClain b61f59
	{	"services",	services,	},
Kylie McClain b61f59
	{	"shells",	shells,		},
Kylie McClain b61f59
Kylie McClain b61f59
	{	NULL,		NULL,		},
Kylie McClain b61f59
};
Kylie McClain b61f59
Kylie McClain b61f59
static int usage(const char *arg0)
Kylie McClain b61f59
{
Kylie McClain b61f59
	struct getentdb	*curdb;
Kylie McClain b61f59
	size_t i;
Kylie McClain b61f59
Kylie McClain b61f59
	(void)fprintf(stderr, "Usage: %s database [key ...]\n", arg0);
Kylie McClain b61f59
	(void)fprintf(stderr, "\tdatabase may be one of:");
Kylie McClain b61f59
	for (i = 0, curdb = databases; curdb->name != NULL; curdb++, i++) {
Kylie McClain b61f59
		if (i % 7 == 0)
Kylie McClain b61f59
			(void)fputs("\n\t\t", stderr);
Kylie McClain b61f59
		(void)fprintf(stderr, "%s%s", i % 7 == 0 ? "" : " ",
Kylie McClain b61f59
		    curdb->name);
Kylie McClain b61f59
	}
Kylie McClain b61f59
	(void)fprintf(stderr, "\n");
Kylie McClain b61f59
	exit(RV_USAGE);
Kylie McClain b61f59
	/* NOTREACHED */
Kylie McClain b61f59
}
Kylie McClain b61f59
Kylie McClain b61f59
int
Kylie McClain b61f59
main(int argc, char *argv[])
Kylie McClain b61f59
{
Kylie McClain b61f59
	struct getentdb	*curdb;
Kylie McClain b61f59
Kylie McClain b61f59
	if (argc < 2)
Kylie McClain b61f59
		usage(argv[0]);
Kylie McClain b61f59
	for (curdb = databases; curdb->name != NULL; curdb++)
Kylie McClain b61f59
		if (strcmp(curdb->name, argv[1]) == 0)
Kylie McClain b61f59
			return (*curdb->callback)(argc, argv);
Kylie McClain b61f59
Kylie McClain b61f59
	warn("Unknown database `%s'", argv[1]);
Kylie McClain b61f59
	usage(argv[0]);
Kylie McClain b61f59
	/* NOTREACHED */
Kylie McClain b61f59
}