From e980216d0692e6a6d439a4624efb5ded02bf2c53 Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Thu, 10 Nov 2005 19:24:37 +0000 Subject: Introducing getent(1) from NetBSD. ok deraadt@ --- usr.bin/getent/Makefile | 6 + usr.bin/getent/getent.1 | 125 +++++++++++ usr.bin/getent/getent.c | 578 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 709 insertions(+) create mode 100644 usr.bin/getent/Makefile create mode 100644 usr.bin/getent/getent.1 create mode 100644 usr.bin/getent/getent.c diff --git a/usr.bin/getent/Makefile b/usr.bin/getent/Makefile new file mode 100644 index 00000000000..913f6bc237c --- /dev/null +++ b/usr.bin/getent/Makefile @@ -0,0 +1,6 @@ +# $OpenBSD: Makefile,v 1.1 2005/11/10 19:24:36 otto Exp $ +# $NetBSD: Makefile,v 1.2 2004/11/29 05:02:52 lukem Exp $ + +PROG= getent + +.include diff --git a/usr.bin/getent/getent.1 b/usr.bin/getent/getent.1 new file mode 100644 index 00000000000..d14230659f7 --- /dev/null +++ b/usr.bin/getent/getent.1 @@ -0,0 +1,125 @@ +.\" $NetBSD: getent.1,v 1.13 2005/09/11 23:16:15 wiz Exp $ +.\" +.\" Copyright (c) 2004 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Luke Mewburn. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd August 24, 2005 +.Dt GETENT 1 +.Os +.Sh NAME +.Nm getent +.Nd get entries from administrative database +.Sh SYNOPSIS +.Nm +.Ar database +.Op Ar key ... +.Sh DESCRIPTION +The +.Nm +program retrieves and displays entries from the administrative +database specified by +.Ar database , +using the lookup order specified in +.Xr nsswitch.conf 5 . +The display format for a given +.Ar database +is as per the +.Dq traditional +file format for that database. +.Pp +.Ar database +may be one of: +.Bl -column "netgroup" -offset indent -compact +.Sy Database Ta Sy Display format +.It ethers Ta address name +.It group Ta group:passwd:gid:[member[,member]...] +.It hosts Ta address name [alias ...] +.It networks Ta name network [alias ...] +.It passwd Ta user:passwd:uid:gid:gecos:home_dir:shell +.It protocols Ta name protocol [alias ...] +.It rpc Ta name number [alias ...] +.It services Ta name port/protocol [alias ...] +.It shells Ta /path/to/shell +.El +.Pp +If one or more +.Ar key +arguments are provided, they will be looked up in +.Ar database +using the appropriate function. +For example, +.Sy passwd +supports a numeric UID or user name; +.Sy hosts +supports an IPv4 address, IPv6 address, or host name; +and +.Sy services +supports a service name, service name/protocol name, numeric port, or +numeric port/protocol name. +.Pp +If no +.Ar key +is provided and +.Ar database +supports enumeration, all entries for +.Ar database +will be retrieved using the appropriate enumeration function and printed. +.Sh DIAGNOSTICS +.Nm +exits 0 on success, +1 if there was an error in the command syntax, +2 if one of the specified key names was not found in +.Ar database , +or 3 if there is no support for enumeration on +.Ar database . +.Sh SEE ALSO +.Xr ethers 5 , +.Xr group 5 , +.Xr hosts 5 , +.Xr networks 5 , +.Xr nsswitch.conf 5 , +.Xr passwd 5 , +.Xr protocols 5 , +.Xr rpc 5 , +.Xr services 5 , +.Xr shells 5 +.Sh HISTORY +A +.Nm +command appeared in +.Nx 3.0 . +It was based on the command of the same name in +.Tn Solaris +and +.Tn Linux . diff --git a/usr.bin/getent/getent.c b/usr.bin/getent/getent.c new file mode 100644 index 00000000000..a178dc8d5dc --- /dev/null +++ b/usr.bin/getent/getent.c @@ -0,0 +1,578 @@ +/* $openBSD$ */ +/* $NetBSD: getent.c,v 1.7 2005/08/24 14:31:02 ginsbach Exp $ */ + +/*- + * Copyright (c) 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include /* for INET6_ADDRSTRLEN */ +#include + + +#include + +static int usage(void); +static int parsenum(const char *, unsigned long *); +static int ethers(int, char *[]); +static int group(int, char *[]); +static int hosts(int, char *[]); +static int networks(int, char *[]); +static int passwd(int, char *[]); +static int protocols(int, char *[]); +static int rpc(int, char *[]); +static int services(int, char *[]); +static int shells(int, char *[]); + +enum { + RV_OK = 0, + RV_USAGE = 1, + RV_NOTFOUND = 2, + RV_NOENUM = 3, +}; + +static struct getentdb { + const char *name; + int (*callback)(int, char *[]); +} databases[] = { + { "ethers", ethers, }, + { "group", group, }, + { "hosts", hosts, }, + { "networks", networks, }, + { "passwd", passwd, }, + { "protocols", protocols, }, + { "rpc", rpc, }, + { "services", services, }, + { "shells", shells, }, + + { NULL, NULL, }, +}; + + +int +main(int argc, char *argv[]) +{ + struct getentdb *curdb; + + if (argc < 2) + usage(); + for (curdb = databases; curdb->name != NULL; curdb++) { + if (strcmp(curdb->name, argv[1]) == 0) { + exit(curdb->callback(argc, argv)); + break; + } + } + fprintf(stderr, "Unknown database: %s\n", argv[1]); + usage(); + /* NOTREACHED */ + return RV_USAGE; +} + +extern char *__progname; + +static int +usage(void) +{ + struct getentdb *curdb; + + fprintf(stderr, "Usage: %s database [key ...]\n", __progname); + fprintf(stderr, " database may be one of:\n\t"); + for (curdb = databases; curdb->name != NULL; curdb++) { + fprintf(stderr, " %s", curdb->name); + } + fprintf(stderr, "\n"); + exit(RV_USAGE); + /* NOTREACHED */ +} + +static int +parsenum(const char *word, unsigned long *result) +{ + unsigned long num; + char *ep; + + assert(word != NULL); + assert(result != NULL); + + if (!isdigit((unsigned char)word[0])) + return 0; + errno = 0; + num = strtoul(word, &ep, 10); + if (num == ULONG_MAX && errno == ERANGE) + return 0; + if (*ep != '\0') + return 0; + *result = num; + return 1; +} + +/* + * printfmtstrings -- + * vprintf(format, ...), + * then the aliases (beginning with prefix, separated by sep), + * then a newline + */ +static void +printfmtstrings(char *strings[], const char *prefix, const char *sep, + const char *fmt, ...) +{ + va_list ap; + const char *curpref; + int i; + + va_start(ap, fmt); + vprintf(fmt, ap); + + curpref = prefix; + for (i = 0; strings[i] != NULL; i++) { + printf("%s%s", curpref, strings[i]); + curpref = sep; + } + printf("\n"); +} + + + /* + * ethers + */ + +static int +ethers(int argc, char *argv[]) +{ + char hostname[MAXHOSTNAMELEN + 1], *hp; + struct ether_addr ea, *eap; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + +#define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp) + + rv = RV_OK; + if (argc == 2) { + fprintf(stderr, "Enumeration not supported on ethers\n"); + rv = RV_NOENUM; + } else { + for (i = 2; i < argc; i++) { + if ((eap = ether_aton(argv[i])) == NULL) { + eap = &ea; + hp = argv[i]; + if (ether_hostton(hp, eap) != 0) { + rv = RV_NOTFOUND; + break; + } + } else { + hp = hostname; + if (ether_ntohost(hp, eap) != 0) { + rv = RV_NOTFOUND; + break; + } + } + ETHERSPRINT; + } + } + return rv; +} + + /* + * group + */ + +static int +group(int argc, char *argv[]) +{ + struct group *gr; + unsigned long id; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + +#define GROUPPRINT printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \ + gr->gr_name, gr->gr_passwd, gr->gr_gid) + + setgroupent(1); + rv = RV_OK; + if (argc == 2) { + while ((gr = getgrent()) != NULL) + GROUPPRINT; + } else { + for (i = 2; i < argc; i++) { + if (parsenum(argv[i], &id)) + gr = getgrgid((gid_t)id); + else + gr = getgrnam(argv[i]); + if (gr != NULL) + GROUPPRINT; + else { + rv = RV_NOTFOUND; + break; + } + } + } + endgrent(); + return rv; +} + + + /* + * hosts + */ + +static void +hostsprint(const struct hostent *he) +{ + char buf[INET6_ADDRSTRLEN]; + + assert(he != NULL); + if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL) + strlcpy(buf, "# unknown", sizeof(buf)); + printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name); +} + +static int +hosts(int argc, char *argv[]) +{ + struct hostent *he; + char addr[IN6ADDRSZ]; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + + sethostent(1); + rv = RV_OK; + if (argc == 2) { + while ((he = gethostent()) != NULL) + hostsprint(he); + } else { + for (i = 2; i < argc; i++) { + if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0) + he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6); + else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0) + he = gethostbyaddr(addr, INADDRSZ, AF_INET); + else + he = gethostbyname(argv[i]); + if (he != NULL) + hostsprint(he); + else { + rv = RV_NOTFOUND; + break; + } + } + } + endhostent(); + return rv; +} + + + /* + * networks + */ + +static void +networksprint(const struct netent *ne) +{ + char buf[INET6_ADDRSTRLEN]; + struct in_addr ianet; + + assert(ne != NULL); + ianet = inet_makeaddr(ne->n_net, 0); + if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL) + strlcpy(buf, "# unknown", sizeof(buf)); + printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf); +} + +static int +networks(int argc, char *argv[]) +{ + struct netent *ne; + in_addr_t net; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + + setnetent(1); + rv = RV_OK; + if (argc == 2) { + while ((ne = getnetent()) != NULL) + networksprint(ne); + } else { + for (i = 2; i < argc; i++) { + net = inet_network(argv[i]); + if (net != INADDR_NONE) + ne = getnetbyaddr(net, AF_INET); + else + ne = getnetbyname(argv[i]); + if (ne != NULL) + networksprint(ne); + else { + rv = RV_NOTFOUND; + break; + } + } + } + endnetent(); + return rv; +} + + + /* + * passwd + */ + +static int +passwd(int argc, char *argv[]) +{ + struct passwd *pw; + unsigned long id; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + +#define PASSWDPRINT printf("%s:%s:%u:%u:%s:%s:%s\n", \ + pw->pw_name, pw->pw_passwd, pw->pw_uid, \ + pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell) + + setpassent(1); + rv = RV_OK; + if (argc == 2) { + while ((pw = getpwent()) != NULL) + PASSWDPRINT; + } else { + for (i = 2; i < argc; i++) { + if (parsenum(argv[i], &id)) + pw = getpwuid((uid_t)id); + else + pw = getpwnam(argv[i]); + if (pw != NULL) + PASSWDPRINT; + else { + rv = RV_NOTFOUND; + break; + } + } + } + endpwent(); + return rv; +} + + + /* + * protocols + */ + +static int +protocols(int argc, char *argv[]) +{ + struct protoent *pe; + unsigned long id; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + +#define PROTOCOLSPRINT printfmtstrings(pe->p_aliases, " ", " ", \ + "%-16s %5d", pe->p_name, pe->p_proto) + + setprotoent(1); + rv = RV_OK; + if (argc == 2) { + while ((pe = getprotoent()) != NULL) + PROTOCOLSPRINT; + } else { + for (i = 2; i < argc; i++) { + if (parsenum(argv[i], &id)) + pe = getprotobynumber((int)id); + else + pe = getprotobyname(argv[i]); + if (pe != NULL) + PROTOCOLSPRINT; + else { + rv = RV_NOTFOUND; + break; + } + } + } + endprotoent(); + return rv; +} + + /* + * rpc + */ + +static int +rpc(int argc, char *argv[]) +{ + struct rpcent *re; + unsigned long id; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + +#define RPCPRINT printfmtstrings(re->r_aliases, " ", " ", \ + "%-16s %6d", \ + re->r_name, re->r_number) + + setrpcent(1); + rv = RV_OK; + if (argc == 2) { + while ((re = getrpcent()) != NULL) + RPCPRINT; + } else { + for (i = 2; i < argc; i++) { + if (parsenum(argv[i], &id)) + re = getrpcbynumber((int)id); + else + re = getrpcbyname(argv[i]); + if (re != NULL) + RPCPRINT; + else { + rv = RV_NOTFOUND; + break; + } + } + } + endrpcent(); + return rv; +} + + /* + * services + */ + +static int +services(int argc, char *argv[]) +{ + struct servent *se; + unsigned long id; + char *proto; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + +#define SERVICESPRINT printfmtstrings(se->s_aliases, " ", " ", \ + "%-16s %5d/%s", \ + se->s_name, ntohs(se->s_port), se->s_proto) + + setservent(1); + rv = RV_OK; + if (argc == 2) { + while ((se = getservent()) != NULL) + SERVICESPRINT; + } else { + for (i = 2; i < argc; i++) { + proto = strchr(argv[i], '/'); + if (proto != NULL) + *proto++ = '\0'; + if (parsenum(argv[i], &id)) + se = getservbyport((int)id, proto); + else + se = getservbyname(argv[i], proto); + if (se != NULL) + SERVICESPRINT; + else { + rv = RV_NOTFOUND; + break; + } + } + } + endservent(); + return rv; +} + + + /* + * shells + */ + +static int +shells(int argc, char *argv[]) +{ + const char *sh; + int i, rv; + + assert(argc > 1); + assert(argv != NULL); + +#define SHELLSPRINT printf("%s\n", sh) + + setusershell(); + rv = RV_OK; + if (argc == 2) { + while ((sh = getusershell()) != NULL) + SHELLSPRINT; + } else { + for (i = 2; i < argc; i++) { + setusershell(); + while ((sh = getusershell()) != NULL) { + if (strcmp(sh, argv[i]) == 0) { + SHELLSPRINT; + break; + } + } + if (sh == NULL) { + rv = RV_NOTFOUND; + break; + } + } + } + endusershell(); + return rv; +} -- cgit v1.2.3