1 /* $OpenBSD: getent.c,v 1.5 2008/06/26 05:42:21 ray Exp $ */ 2 /* $NetBSD: getent.c,v 1.7 2005/08/24 14:31:02 ginsbach Exp $ */ 3 4 /*- 5 * Copyright (c) 2004 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Luke Mewburn. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 36 #include <ctype.h> 37 #include <errno.h> 38 #include <grp.h> 39 #include <limits.h> 40 #include <netdb.h> 41 #include <pwd.h> 42 #include <stdio.h> 43 #include <stdarg.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include <net/if.h> 49 #include <netinet/in.h> /* for INET6_ADDRSTRLEN */ 50 #include <netinet/if_ether.h> 51 52 #include <arpa/inet.h> 53 #include <arpa/nameser.h> 54 55 #include <rpc/rpc.h> 56 57 static int usage(void); 58 static int ethers(int, char *[]); 59 static int group(int, char *[]); 60 static int hosts(int, char *[]); 61 static int networks(int, char *[]); 62 static int passwd(int, char *[]); 63 static int protocols(int, char *[]); 64 static int rpc(int, char *[]); 65 static int services(int, char *[]); 66 static int shells(int, char *[]); 67 extern char *__progname; 68 69 enum { 70 RV_OK = 0, 71 RV_USAGE = 1, 72 RV_NOTFOUND = 2, 73 RV_NOENUM = 3 74 }; 75 76 static struct getentdb { 77 const char *name; 78 int (*fn)(int, char *[]); 79 } databases[] = { 80 { "ethers", ethers, }, 81 { "group", group, }, 82 { "hosts", hosts, }, 83 { "networks", networks, }, 84 { "passwd", passwd, }, 85 { "protocols", protocols, }, 86 { "rpc", rpc, }, 87 { "services", services, }, 88 { "shells", shells, }, 89 90 { NULL, NULL, }, 91 }; 92 93 int 94 main(int argc, char *argv[]) 95 { 96 struct getentdb *curdb; 97 98 if (argc < 2) 99 usage(); 100 for (curdb = databases; curdb->name != NULL; curdb++) { 101 if (strcmp(curdb->name, argv[1]) == 0) { 102 exit(curdb->fn(argc, argv)); 103 break; 104 } 105 } 106 fprintf(stderr, "%s: unknown database: %s\n", __progname, argv[1]); 107 return RV_USAGE; 108 } 109 110 static int 111 usage(void) 112 { 113 fprintf(stderr, "usage: %s database [key ...]\n", __progname); 114 exit(RV_USAGE); 115 /* NOTREACHED */ 116 } 117 118 /* 119 * printfmtstrings -- 120 * vprintf(format, ...), 121 * then the aliases (beginning with prefix, separated by sep), 122 * then a newline 123 */ 124 static void 125 printfmtstrings(char *strings[], const char *prefix, const char *sep, 126 const char *fmt, ...) 127 { 128 va_list ap; 129 const char *curpref; 130 int i; 131 132 va_start(ap, fmt); 133 vprintf(fmt, ap); 134 va_end(ap); 135 136 curpref = prefix; 137 for (i = 0; strings[i] != NULL; i++) { 138 printf("%s%s", curpref, strings[i]); 139 curpref = sep; 140 } 141 printf("\n"); 142 } 143 144 #define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp) 145 146 static int 147 ethers(int argc, char *argv[]) 148 { 149 char hostname[MAXHOSTNAMELEN], *hp; 150 int i, rv = RV_OK; 151 struct ether_addr ea, *eap; 152 153 if (argc == 2) { 154 fprintf(stderr, "%s: Enumeration not supported on ethers\n", 155 __progname); 156 rv = RV_NOENUM; 157 } else { 158 for (i = 2; i < argc; i++) { 159 if ((eap = ether_aton(argv[i])) == NULL) { 160 eap = &ea; 161 hp = argv[i]; 162 if (ether_hostton(hp, eap) != 0) { 163 rv = RV_NOTFOUND; 164 break; 165 } 166 } else { 167 hp = hostname; 168 if (ether_ntohost(hp, eap) != 0) { 169 rv = RV_NOTFOUND; 170 break; 171 } 172 } 173 ETHERSPRINT; 174 } 175 } 176 return rv; 177 } 178 179 #define GROUPPRINT \ 180 printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \ 181 gr->gr_name, gr->gr_passwd, gr->gr_gid) 182 183 static int 184 group(int argc, char *argv[]) 185 { 186 int i, rv = RV_OK; 187 struct group *gr; 188 189 setgroupent(1); 190 if (argc == 2) { 191 while ((gr = getgrent()) != NULL) 192 GROUPPRINT; 193 } else { 194 for (i = 2; i < argc; i++) { 195 const char *err; 196 long long id = strtonum(argv[i], 0, UINT_MAX, &err); 197 198 if (!err) 199 gr = getgrgid((gid_t)id); 200 else 201 gr = getgrnam(argv[i]); 202 if (gr != NULL) 203 GROUPPRINT; 204 else { 205 rv = RV_NOTFOUND; 206 break; 207 } 208 } 209 } 210 endgrent(); 211 return rv; 212 } 213 214 static void 215 hostsprint(const struct hostent *he) 216 { 217 char buf[INET6_ADDRSTRLEN]; 218 219 if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL) 220 strlcpy(buf, "# unknown", sizeof(buf)); 221 printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name); 222 } 223 224 static int 225 hosts(int argc, char *argv[]) 226 { 227 char addr[IN6ADDRSZ]; 228 int i, rv = RV_OK; 229 struct hostent *he; 230 231 sethostent(1); 232 if (argc == 2) { 233 while ((he = gethostent()) != NULL) 234 hostsprint(he); 235 } else { 236 for (i = 2; i < argc; i++) { 237 if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0) 238 he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6); 239 else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0) 240 he = gethostbyaddr(addr, INADDRSZ, AF_INET); 241 else 242 he = gethostbyname(argv[i]); 243 if (he != NULL) 244 hostsprint(he); 245 else { 246 rv = RV_NOTFOUND; 247 break; 248 } 249 } 250 } 251 endhostent(); 252 return rv; 253 } 254 255 static void 256 networksprint(const struct netent *ne) 257 { 258 char buf[INET6_ADDRSTRLEN]; 259 struct in_addr ianet; 260 261 ianet = inet_makeaddr(ne->n_net, 0); 262 if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL) 263 strlcpy(buf, "# unknown", sizeof(buf)); 264 printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf); 265 } 266 267 static int 268 networks(int argc, char *argv[]) 269 { 270 int i, rv = RV_OK; 271 struct netent *ne; 272 in_addr_t net; 273 274 setnetent(1); 275 if (argc == 2) { 276 while ((ne = getnetent()) != NULL) 277 networksprint(ne); 278 } else { 279 for (i = 2; i < argc; i++) { 280 net = inet_network(argv[i]); 281 if (net != INADDR_NONE) 282 ne = getnetbyaddr(net, AF_INET); 283 else 284 ne = getnetbyname(argv[i]); 285 if (ne != NULL) 286 networksprint(ne); 287 else { 288 rv = RV_NOTFOUND; 289 break; 290 } 291 } 292 } 293 endnetent(); 294 return rv; 295 } 296 297 #define PASSWDPRINT \ 298 printf("%s:%s:%u:%u:%s:%s:%s\n", \ 299 pw->pw_name, pw->pw_passwd, pw->pw_uid, \ 300 pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell) 301 302 static int 303 passwd(int argc, char *argv[]) 304 { 305 int i, rv = RV_OK; 306 struct passwd *pw; 307 308 setpassent(1); 309 if (argc == 2) { 310 while ((pw = getpwent()) != NULL) 311 PASSWDPRINT; 312 } else { 313 for (i = 2; i < argc; i++) { 314 const char *err; 315 long long id = strtonum(argv[i], 0, UINT_MAX, &err); 316 317 if (!err) 318 pw = getpwuid((uid_t)id); 319 else 320 pw = getpwnam(argv[i]); 321 if (pw != NULL) 322 PASSWDPRINT; 323 else { 324 rv = RV_NOTFOUND; 325 break; 326 } 327 } 328 } 329 endpwent(); 330 return rv; 331 } 332 333 #define PROTOCOLSPRINT \ 334 printfmtstrings(pe->p_aliases, " ", " ", \ 335 "%-16s %5d", pe->p_name, pe->p_proto) 336 337 static int 338 protocols(int argc, char *argv[]) 339 { 340 struct protoent *pe; 341 int i, rv = RV_OK; 342 343 setprotoent(1); 344 if (argc == 2) { 345 while ((pe = getprotoent()) != NULL) 346 PROTOCOLSPRINT; 347 } else { 348 for (i = 2; i < argc; i++) { 349 const char *err; 350 long long id = strtonum(argv[i], 0, UINT_MAX, &err); 351 352 if (!err) 353 pe = getprotobynumber((int)id); 354 else 355 pe = getprotobyname(argv[i]); 356 if (pe != NULL) 357 PROTOCOLSPRINT; 358 else { 359 rv = RV_NOTFOUND; 360 break; 361 } 362 } 363 } 364 endprotoent(); 365 return rv; 366 } 367 368 #define RPCPRINT \ 369 printfmtstrings(re->r_aliases, " ", " ", \ 370 "%-16s %6d", re->r_name, re->r_number) 371 372 static int 373 rpc(int argc, char *argv[]) 374 { 375 struct rpcent *re; 376 int i, rv = RV_OK; 377 378 setrpcent(1); 379 if (argc == 2) { 380 while ((re = getrpcent()) != NULL) 381 RPCPRINT; 382 } else { 383 for (i = 2; i < argc; i++) { 384 const char *err; 385 long long id = strtonum(argv[i], 0, UINT_MAX, &err); 386 387 if (!err) 388 re = getrpcbynumber((int)id); 389 else 390 re = getrpcbyname(argv[i]); 391 if (re != NULL) 392 RPCPRINT; 393 else { 394 rv = RV_NOTFOUND; 395 break; 396 } 397 } 398 } 399 endrpcent(); 400 return rv; 401 } 402 403 #define SERVICESPRINT \ 404 printfmtstrings(se->s_aliases, " ", " ", \ 405 "%-16s %5d/%s", se->s_name, ntohs(se->s_port), se->s_proto) 406 407 static int 408 services(int argc, char *argv[]) 409 { 410 struct servent *se; 411 int i, rv = RV_OK; 412 413 setservent(1); 414 if (argc == 2) { 415 while ((se = getservent()) != NULL) 416 SERVICESPRINT; 417 } else { 418 for (i = 2; i < argc; i++) { 419 const char *err; 420 long long id; 421 char *proto = strchr(argv[i], '/'); 422 423 if (proto != NULL) 424 *proto++ = '\0'; 425 id = strtonum(argv[i], 0, UINT_MAX, &err); 426 if (!err) 427 se = getservbyport(htons((u_short)id), proto); 428 else 429 se = getservbyname(argv[i], proto); 430 if (se != NULL) 431 SERVICESPRINT; 432 else { 433 rv = RV_NOTFOUND; 434 break; 435 } 436 } 437 } 438 endservent(); 439 return rv; 440 } 441 442 #define SHELLSPRINT printf("%s\n", sh) 443 444 static int 445 shells(int argc, char *argv[]) 446 { 447 const char *sh; 448 int i, rv = RV_OK; 449 450 setusershell(); 451 if (argc == 2) { 452 while ((sh = getusershell()) != NULL) 453 SHELLSPRINT; 454 } else { 455 for (i = 2; i < argc; i++) { 456 setusershell(); 457 while ((sh = getusershell()) != NULL) { 458 if (strcmp(sh, argv[i]) == 0) { 459 SHELLSPRINT; 460 break; 461 } 462 } 463 if (sh == NULL) { 464 rv = RV_NOTFOUND; 465 break; 466 } 467 } 468 } 469 endusershell(); 470 return rv; 471 } 472