1158287Smaxim/* $NetBSD: getent.c,v 1.7 2005/08/24 14:31:02 ginsbach Exp $ */ 2158287Smaxim 3158287Smaxim/*- 4158287Smaxim * Copyright (c) 2004 The NetBSD Foundation, Inc. 5158287Smaxim * All rights reserved. 6158287Smaxim * 7158287Smaxim * This code is derived from software contributed to The NetBSD Foundation 8158287Smaxim * by Luke Mewburn. 9158287Smaxim * 10158287Smaxim * Redistribution and use in source and binary forms, with or without 11158287Smaxim * modification, are permitted provided that the following conditions 12158287Smaxim * are met: 13158287Smaxim * 1. Redistributions of source code must retain the above copyright 14158287Smaxim * notice, this list of conditions and the following disclaimer. 15158287Smaxim * 2. Redistributions in binary form must reproduce the above copyright 16158287Smaxim * notice, this list of conditions and the following disclaimer in the 17158287Smaxim * documentation and/or other materials provided with the distribution. 18158287Smaxim * 19158287Smaxim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20158287Smaxim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21158287Smaxim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22158287Smaxim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23158287Smaxim * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24158287Smaxim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25158287Smaxim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26158287Smaxim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27158287Smaxim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28158287Smaxim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29158287Smaxim * POSSIBILITY OF SUCH DAMAGE. 30158287Smaxim */ 31158287Smaxim 32158287Smaxim#include <sys/cdefs.h> 33158287Smaxim__FBSDID("$FreeBSD$"); 34158287Smaxim 35158287Smaxim#include <sys/socket.h> 36158287Smaxim#include <sys/param.h> 37158287Smaxim#include <arpa/inet.h> 38158287Smaxim#include <arpa/nameser.h> 39158287Smaxim#include <net/if.h> 40158287Smaxim#include <netinet/if_ether.h> 41158287Smaxim#include <netinet/in.h> /* for INET6_ADDRSTRLEN */ 42158287Smaxim#include <rpc/rpcent.h> 43158287Smaxim 44158287Smaxim#include <assert.h> 45158287Smaxim#include <ctype.h> 46158287Smaxim#include <errno.h> 47158287Smaxim#include <grp.h> 48158287Smaxim#include <limits.h> 49158287Smaxim#include <netdb.h> 50158287Smaxim#include <pwd.h> 51202718Sed#include <stdarg.h> 52202718Sed#include <stdint.h> 53158287Smaxim#include <stdio.h> 54158287Smaxim#include <stdlib.h> 55158287Smaxim#include <string.h> 56158287Smaxim#include <unistd.h> 57202198Sed#include <utmpx.h> 58158287Smaxim 59158287Smaximstatic int usage(void); 60158287Smaximstatic int parsenum(const char *, unsigned long *); 61158287Smaximstatic int ethers(int, char *[]); 62158287Smaximstatic int group(int, char *[]); 63158287Smaximstatic int hosts(int, char *[]); 64250942Sghelmerstatic int netgroup(int, char *[]); 65158287Smaximstatic int networks(int, char *[]); 66158287Smaximstatic int passwd(int, char *[]); 67158287Smaximstatic int protocols(int, char *[]); 68158287Smaximstatic int rpc(int, char *[]); 69158287Smaximstatic int services(int, char *[]); 70158287Smaximstatic int shells(int, char *[]); 71202198Sedstatic int utmpx(int, char *[]); 72158287Smaxim 73158287Smaximenum { 74158287Smaxim RV_OK = 0, 75158287Smaxim RV_USAGE = 1, 76158287Smaxim RV_NOTFOUND = 2, 77166504Srse RV_NOENUM = 3 78158287Smaxim}; 79158287Smaxim 80158287Smaximstatic struct getentdb { 81158287Smaxim const char *name; 82158287Smaxim int (*callback)(int, char *[]); 83158287Smaxim} databases[] = { 84158287Smaxim { "ethers", ethers, }, 85158287Smaxim { "group", group, }, 86158287Smaxim { "hosts", hosts, }, 87158287Smaxim { "networks", networks, }, 88158287Smaxim { "passwd", passwd, }, 89158287Smaxim { "protocols", protocols, }, 90158287Smaxim { "rpc", rpc, }, 91158287Smaxim { "services", services, }, 92158287Smaxim { "shells", shells, }, 93250942Sghelmer { "netgroup", netgroup, }, 94202198Sed { "utmpx", utmpx, }, 95158287Smaxim 96158287Smaxim { NULL, NULL, }, 97158287Smaxim}; 98158287Smaxim 99158287Smaximint 100158287Smaximmain(int argc, char *argv[]) 101158287Smaxim{ 102158287Smaxim struct getentdb *curdb; 103158287Smaxim 104158287Smaxim setprogname(argv[0]); 105158287Smaxim 106158287Smaxim if (argc < 2) 107158287Smaxim usage(); 108158287Smaxim for (curdb = databases; curdb->name != NULL; curdb++) { 109158287Smaxim if (strcmp(curdb->name, argv[1]) == 0) { 110158287Smaxim exit(curdb->callback(argc, argv)); 111158287Smaxim } 112158287Smaxim } 113158287Smaxim fprintf(stderr, "Unknown database: %s\n", argv[1]); 114158287Smaxim usage(); 115158287Smaxim /* NOTREACHED */ 116158287Smaxim return RV_USAGE; 117158287Smaxim} 118158287Smaxim 119158287Smaximstatic int 120158287Smaximusage(void) 121158287Smaxim{ 122158287Smaxim struct getentdb *curdb; 123158287Smaxim 124158287Smaxim fprintf(stderr, "Usage: %s database [key ...]\n", 125158287Smaxim getprogname()); 126158287Smaxim fprintf(stderr, " database may be one of:\n\t"); 127158287Smaxim for (curdb = databases; curdb->name != NULL; curdb++) { 128158287Smaxim fprintf(stderr, " %s", curdb->name); 129158287Smaxim } 130158287Smaxim fprintf(stderr, "\n"); 131158287Smaxim exit(RV_USAGE); 132158287Smaxim /* NOTREACHED */ 133158287Smaxim} 134158287Smaxim 135158287Smaximstatic int 136158287Smaximparsenum(const char *word, unsigned long *result) 137158287Smaxim{ 138158287Smaxim unsigned long num; 139158287Smaxim char *ep; 140158287Smaxim 141158287Smaxim assert(word != NULL); 142158287Smaxim assert(result != NULL); 143158287Smaxim 144158287Smaxim if (!isdigit((unsigned char)word[0])) 145158287Smaxim return 0; 146158287Smaxim errno = 0; 147158287Smaxim num = strtoul(word, &ep, 10); 148158287Smaxim if (num == ULONG_MAX && errno == ERANGE) 149158287Smaxim return 0; 150158287Smaxim if (*ep != '\0') 151158287Smaxim return 0; 152158287Smaxim *result = num; 153158287Smaxim return 1; 154158287Smaxim} 155158287Smaxim 156158287Smaxim/* 157158287Smaxim * printfmtstrings -- 158158287Smaxim * vprintf(format, ...), 159158287Smaxim * then the aliases (beginning with prefix, separated by sep), 160158287Smaxim * then a newline 161158287Smaxim */ 162158287Smaximstatic void 163158287Smaximprintfmtstrings(char *strings[], const char *prefix, const char *sep, 164158287Smaxim const char *fmt, ...) 165158287Smaxim{ 166158287Smaxim va_list ap; 167158287Smaxim const char *curpref; 168158287Smaxim int i; 169158287Smaxim 170158287Smaxim va_start(ap, fmt); 171158287Smaxim vprintf(fmt, ap); 172158287Smaxim 173158287Smaxim curpref = prefix; 174158287Smaxim for (i = 0; strings[i] != NULL; i++) { 175158287Smaxim printf("%s%s", curpref, strings[i]); 176158287Smaxim curpref = sep; 177158287Smaxim } 178158287Smaxim printf("\n"); 179166504Srse va_end(ap); 180158287Smaxim} 181158287Smaxim 182158287Smaxim/* 183158287Smaxim * ethers 184158287Smaxim */ 185158287Smaximstatic int 186158287Smaximethers(int argc, char *argv[]) 187158287Smaxim{ 188158287Smaxim char hostname[MAXHOSTNAMELEN + 1], *hp; 189158287Smaxim struct ether_addr ea, *eap; 190158287Smaxim int i, rv; 191158287Smaxim 192158287Smaxim assert(argc > 1); 193158287Smaxim assert(argv != NULL); 194158287Smaxim 195158287Smaxim#define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp) 196158287Smaxim 197158287Smaxim rv = RV_OK; 198158287Smaxim if (argc == 2) { 199158287Smaxim fprintf(stderr, "Enumeration not supported on ethers\n"); 200158287Smaxim rv = RV_NOENUM; 201158287Smaxim } else { 202158287Smaxim for (i = 2; i < argc; i++) { 203158287Smaxim if ((eap = ether_aton(argv[i])) == NULL) { 204158287Smaxim eap = &ea; 205158287Smaxim hp = argv[i]; 206158287Smaxim if (ether_hostton(hp, eap) != 0) { 207158287Smaxim rv = RV_NOTFOUND; 208158287Smaxim break; 209158287Smaxim } 210158287Smaxim } else { 211158287Smaxim hp = hostname; 212158287Smaxim if (ether_ntohost(hp, eap) != 0) { 213158287Smaxim rv = RV_NOTFOUND; 214158287Smaxim break; 215158287Smaxim } 216158287Smaxim } 217158287Smaxim ETHERSPRINT; 218158287Smaxim } 219158287Smaxim } 220158287Smaxim return rv; 221158287Smaxim} 222158287Smaxim 223158287Smaxim/* 224158287Smaxim * group 225158287Smaxim */ 226158287Smaxim 227158287Smaximstatic int 228158287Smaximgroup(int argc, char *argv[]) 229158287Smaxim{ 230158287Smaxim struct group *gr; 231158287Smaxim unsigned long id; 232158287Smaxim int i, rv; 233158287Smaxim 234158287Smaxim assert(argc > 1); 235158287Smaxim assert(argv != NULL); 236158287Smaxim 237158287Smaxim#define GROUPPRINT printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \ 238158287Smaxim gr->gr_name, gr->gr_passwd, gr->gr_gid) 239158287Smaxim 240158287Smaxim setgroupent(1); 241158287Smaxim rv = RV_OK; 242158287Smaxim if (argc == 2) { 243158287Smaxim while ((gr = getgrent()) != NULL) 244158287Smaxim GROUPPRINT; 245158287Smaxim } else { 246158287Smaxim for (i = 2; i < argc; i++) { 247158287Smaxim if (parsenum(argv[i], &id)) 248158287Smaxim gr = getgrgid((gid_t)id); 249158287Smaxim else 250158287Smaxim gr = getgrnam(argv[i]); 251158287Smaxim if (gr != NULL) 252158287Smaxim GROUPPRINT; 253158287Smaxim else { 254158287Smaxim rv = RV_NOTFOUND; 255158287Smaxim break; 256158287Smaxim } 257158287Smaxim } 258158287Smaxim } 259158287Smaxim endgrent(); 260158287Smaxim return rv; 261158287Smaxim} 262158287Smaxim 263158287Smaxim 264158287Smaxim/* 265158287Smaxim * hosts 266158287Smaxim */ 267158287Smaxim 268158287Smaximstatic void 269158287Smaximhostsprint(const struct hostent *he) 270158287Smaxim{ 271158287Smaxim char buf[INET6_ADDRSTRLEN]; 272158287Smaxim 273158287Smaxim assert(he != NULL); 274158287Smaxim if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL) 275158287Smaxim strlcpy(buf, "# unknown", sizeof(buf)); 276158287Smaxim printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name); 277158287Smaxim} 278158287Smaxim 279158287Smaximstatic int 280158287Smaximhosts(int argc, char *argv[]) 281158287Smaxim{ 282240954Skevlo struct hostent *he4, *he6; 283158287Smaxim char addr[IN6ADDRSZ]; 284158287Smaxim int i, rv; 285158287Smaxim 286158287Smaxim assert(argc > 1); 287158287Smaxim assert(argv != NULL); 288158287Smaxim 289158287Smaxim sethostent(1); 290240954Skevlo he4 = he6 = NULL; 291158287Smaxim rv = RV_OK; 292158287Smaxim if (argc == 2) { 293240954Skevlo while ((he4 = gethostent()) != NULL) 294240954Skevlo hostsprint(he4); 295158287Smaxim } else { 296158287Smaxim for (i = 2; i < argc; i++) { 297240954Skevlo if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0) { 298240954Skevlo he6 = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6); 299240954Skevlo if (he6 != NULL) 300240954Skevlo hostsprint(he6); 301240954Skevlo } else if (inet_pton(AF_INET, argv[i], 302240954Skevlo (void *)addr) > 0) { 303240954Skevlo he4 = gethostbyaddr(addr, INADDRSZ, AF_INET); 304240954Skevlo if (he4 != NULL) 305240954Skevlo hostsprint(he4); 306240954Skevlo } else { 307240954Skevlo he6 = gethostbyname2(argv[i], AF_INET6); 308240954Skevlo if (he6 != NULL) 309240954Skevlo hostsprint(he6); 310240954Skevlo he4 = gethostbyname(argv[i]); 311240954Skevlo if (he4 != NULL) 312240954Skevlo hostsprint(he4); 313240954Skevlo } 314240954Skevlo if ( he4 == NULL && he6 == NULL ) { 315158287Smaxim rv = RV_NOTFOUND; 316158287Smaxim break; 317158287Smaxim } 318158287Smaxim } 319158287Smaxim } 320158287Smaxim endhostent(); 321158287Smaxim return rv; 322158287Smaxim} 323158287Smaxim 324158287Smaxim/* 325158287Smaxim * networks 326158287Smaxim */ 327158287Smaximstatic void 328158287Smaximnetworksprint(const struct netent *ne) 329158287Smaxim{ 330158287Smaxim char buf[INET6_ADDRSTRLEN]; 331158287Smaxim struct in_addr ianet; 332158287Smaxim 333158287Smaxim assert(ne != NULL); 334158287Smaxim ianet = inet_makeaddr(ne->n_net, 0); 335158287Smaxim if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL) 336158287Smaxim strlcpy(buf, "# unknown", sizeof(buf)); 337158287Smaxim printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf); 338158287Smaxim} 339158287Smaxim 340158287Smaximstatic int 341158287Smaximnetworks(int argc, char *argv[]) 342158287Smaxim{ 343158287Smaxim struct netent *ne; 344158287Smaxim in_addr_t net; 345158287Smaxim int i, rv; 346158287Smaxim 347158287Smaxim assert(argc > 1); 348158287Smaxim assert(argv != NULL); 349158287Smaxim 350158287Smaxim setnetent(1); 351158287Smaxim rv = RV_OK; 352158287Smaxim if (argc == 2) { 353158287Smaxim while ((ne = getnetent()) != NULL) 354158287Smaxim networksprint(ne); 355158287Smaxim } else { 356158287Smaxim for (i = 2; i < argc; i++) { 357158287Smaxim net = inet_network(argv[i]); 358158287Smaxim if (net != INADDR_NONE) 359158287Smaxim ne = getnetbyaddr(net, AF_INET); 360158287Smaxim else 361158287Smaxim ne = getnetbyname(argv[i]); 362158287Smaxim if (ne != NULL) 363158287Smaxim networksprint(ne); 364158287Smaxim else { 365158287Smaxim rv = RV_NOTFOUND; 366158287Smaxim break; 367158287Smaxim } 368158287Smaxim } 369158287Smaxim } 370158287Smaxim endnetent(); 371158287Smaxim return rv; 372158287Smaxim} 373158287Smaxim 374158287Smaxim/* 375158287Smaxim * passwd 376158287Smaxim */ 377158287Smaximstatic int 378158287Smaximpasswd(int argc, char *argv[]) 379158287Smaxim{ 380158287Smaxim struct passwd *pw; 381158287Smaxim unsigned long id; 382158287Smaxim int i, rv; 383158287Smaxim 384158287Smaxim assert(argc > 1); 385158287Smaxim assert(argv != NULL); 386158287Smaxim 387158287Smaxim#define PASSWDPRINT printf("%s:%s:%u:%u:%s:%s:%s\n", \ 388158287Smaxim pw->pw_name, pw->pw_passwd, pw->pw_uid, \ 389158287Smaxim pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell) 390158287Smaxim 391158287Smaxim setpassent(1); 392158287Smaxim rv = RV_OK; 393158287Smaxim if (argc == 2) { 394158287Smaxim while ((pw = getpwent()) != NULL) 395158287Smaxim PASSWDPRINT; 396158287Smaxim } else { 397158287Smaxim for (i = 2; i < argc; i++) { 398158287Smaxim if (parsenum(argv[i], &id)) 399158287Smaxim pw = getpwuid((uid_t)id); 400158287Smaxim else 401158287Smaxim pw = getpwnam(argv[i]); 402158287Smaxim if (pw != NULL) 403158287Smaxim PASSWDPRINT; 404158287Smaxim else { 405158287Smaxim rv = RV_NOTFOUND; 406158287Smaxim break; 407158287Smaxim } 408158287Smaxim } 409158287Smaxim } 410158287Smaxim endpwent(); 411158287Smaxim return rv; 412158287Smaxim} 413158287Smaxim 414158287Smaxim/* 415158287Smaxim * protocols 416158287Smaxim */ 417158287Smaximstatic int 418158287Smaximprotocols(int argc, char *argv[]) 419158287Smaxim{ 420158287Smaxim struct protoent *pe; 421158287Smaxim unsigned long id; 422158287Smaxim int i, rv; 423158287Smaxim 424158287Smaxim assert(argc > 1); 425158287Smaxim assert(argv != NULL); 426158287Smaxim 427158287Smaxim#define PROTOCOLSPRINT printfmtstrings(pe->p_aliases, " ", " ", \ 428158287Smaxim "%-16s %5d", pe->p_name, pe->p_proto) 429158287Smaxim 430158287Smaxim setprotoent(1); 431158287Smaxim rv = RV_OK; 432158287Smaxim if (argc == 2) { 433158287Smaxim while ((pe = getprotoent()) != NULL) 434158287Smaxim PROTOCOLSPRINT; 435158287Smaxim } else { 436158287Smaxim for (i = 2; i < argc; i++) { 437158287Smaxim if (parsenum(argv[i], &id)) 438158287Smaxim pe = getprotobynumber((int)id); 439158287Smaxim else 440158287Smaxim pe = getprotobyname(argv[i]); 441158287Smaxim if (pe != NULL) 442158287Smaxim PROTOCOLSPRINT; 443158287Smaxim else { 444158287Smaxim rv = RV_NOTFOUND; 445158287Smaxim break; 446158287Smaxim } 447158287Smaxim } 448158287Smaxim } 449158287Smaxim endprotoent(); 450158287Smaxim return rv; 451158287Smaxim} 452158287Smaxim 453158287Smaxim/* 454158287Smaxim * rpc 455158287Smaxim */ 456158287Smaximstatic int 457158287Smaximrpc(int argc, char *argv[]) 458158287Smaxim{ 459158287Smaxim struct rpcent *re; 460158287Smaxim unsigned long id; 461158287Smaxim int i, rv; 462158287Smaxim 463158287Smaxim assert(argc > 1); 464158287Smaxim assert(argv != NULL); 465158287Smaxim 466158287Smaxim#define RPCPRINT printfmtstrings(re->r_aliases, " ", " ", \ 467158287Smaxim "%-16s %6d", \ 468158287Smaxim re->r_name, re->r_number) 469158287Smaxim 470158287Smaxim setrpcent(1); 471158287Smaxim rv = RV_OK; 472158287Smaxim if (argc == 2) { 473158287Smaxim while ((re = getrpcent()) != NULL) 474158287Smaxim RPCPRINT; 475158287Smaxim } else { 476158287Smaxim for (i = 2; i < argc; i++) { 477158287Smaxim if (parsenum(argv[i], &id)) 478158287Smaxim re = getrpcbynumber((int)id); 479158287Smaxim else 480158287Smaxim re = getrpcbyname(argv[i]); 481158287Smaxim if (re != NULL) 482158287Smaxim RPCPRINT; 483158287Smaxim else { 484158287Smaxim rv = RV_NOTFOUND; 485158287Smaxim break; 486158287Smaxim } 487158287Smaxim } 488158287Smaxim } 489158287Smaxim endrpcent(); 490158287Smaxim return rv; 491158287Smaxim} 492158287Smaxim 493158287Smaxim/* 494158287Smaxim * services 495158287Smaxim */ 496158287Smaximstatic int 497158287Smaximservices(int argc, char *argv[]) 498158287Smaxim{ 499158287Smaxim struct servent *se; 500158287Smaxim unsigned long id; 501158287Smaxim char *proto; 502158287Smaxim int i, rv; 503158287Smaxim 504158287Smaxim assert(argc > 1); 505158287Smaxim assert(argv != NULL); 506158287Smaxim 507158287Smaxim#define SERVICESPRINT printfmtstrings(se->s_aliases, " ", " ", \ 508158287Smaxim "%-16s %5d/%s", \ 509158287Smaxim se->s_name, ntohs(se->s_port), se->s_proto) 510158287Smaxim 511158287Smaxim setservent(1); 512158287Smaxim rv = RV_OK; 513158287Smaxim if (argc == 2) { 514158287Smaxim while ((se = getservent()) != NULL) 515158287Smaxim SERVICESPRINT; 516158287Smaxim } else { 517158287Smaxim for (i = 2; i < argc; i++) { 518158287Smaxim proto = strchr(argv[i], '/'); 519158287Smaxim if (proto != NULL) 520158287Smaxim *proto++ = '\0'; 521158289Sume if (parsenum(argv[i], &id)) 522158289Sume se = getservbyport(htons((u_short)id), proto); 523158289Sume else 524158287Smaxim se = getservbyname(argv[i], proto); 525158287Smaxim if (se != NULL) 526158287Smaxim SERVICESPRINT; 527158287Smaxim else { 528158287Smaxim rv = RV_NOTFOUND; 529158287Smaxim break; 530158287Smaxim } 531158287Smaxim } 532158287Smaxim } 533158287Smaxim endservent(); 534158287Smaxim return rv; 535158287Smaxim} 536158287Smaxim 537158287Smaxim/* 538158287Smaxim * shells 539158287Smaxim */ 540158287Smaximstatic int 541158287Smaximshells(int argc, char *argv[]) 542158287Smaxim{ 543158287Smaxim const char *sh; 544158287Smaxim int i, rv; 545158287Smaxim 546158287Smaxim assert(argc > 1); 547158287Smaxim assert(argv != NULL); 548158287Smaxim 549158287Smaxim#define SHELLSPRINT printf("%s\n", sh) 550158287Smaxim 551158287Smaxim setusershell(); 552158287Smaxim rv = RV_OK; 553158287Smaxim if (argc == 2) { 554158287Smaxim while ((sh = getusershell()) != NULL) 555158287Smaxim SHELLSPRINT; 556158287Smaxim } else { 557158287Smaxim for (i = 2; i < argc; i++) { 558158287Smaxim setusershell(); 559158287Smaxim while ((sh = getusershell()) != NULL) { 560158287Smaxim if (strcmp(sh, argv[i]) == 0) { 561158287Smaxim SHELLSPRINT; 562158287Smaxim break; 563158287Smaxim } 564158287Smaxim } 565158287Smaxim if (sh == NULL) { 566158287Smaxim rv = RV_NOTFOUND; 567158287Smaxim break; 568158287Smaxim } 569158287Smaxim } 570158287Smaxim } 571158287Smaxim endusershell(); 572158287Smaxim return rv; 573158287Smaxim} 574202198Sed 575202198Sed/* 576250942Sghelmer * netgroup 577250942Sghelmer */ 578250942Sghelmerstatic int 579250942Sghelmernetgroup(int argc, char *argv[]) 580250942Sghelmer{ 581250942Sghelmer char *host, *user, *domain; 582250942Sghelmer int first; 583250942Sghelmer int rv, i; 584250942Sghelmer 585250942Sghelmer assert(argc > 1); 586250942Sghelmer assert(argv != NULL); 587250942Sghelmer 588250942Sghelmer#define NETGROUPPRINT(s) (((s) != NULL) ? (s) : "") 589250942Sghelmer 590250942Sghelmer rv = RV_OK; 591250942Sghelmer if (argc == 2) { 592250942Sghelmer fprintf(stderr, "Enumeration not supported on netgroup\n"); 593250942Sghelmer rv = RV_NOENUM; 594250942Sghelmer } else { 595250942Sghelmer for (i = 2; i < argc; i++) { 596250942Sghelmer setnetgrent(argv[i]); 597250942Sghelmer first = 1; 598250942Sghelmer while (getnetgrent(&host, &user, &domain) != 0) { 599250942Sghelmer if (first) { 600250942Sghelmer first = 0; 601250942Sghelmer (void)fputs(argv[i], stdout); 602250942Sghelmer } 603250942Sghelmer (void)printf(" (%s,%s,%s)", 604250942Sghelmer NETGROUPPRINT(host), 605250942Sghelmer NETGROUPPRINT(user), 606250942Sghelmer NETGROUPPRINT(domain)); 607250942Sghelmer } 608250942Sghelmer if (!first) 609250942Sghelmer (void)putchar('\n'); 610250942Sghelmer endnetgrent(); 611250942Sghelmer } 612250942Sghelmer } 613250942Sghelmer return rv; 614250942Sghelmer} 615250942Sghelmer 616250942Sghelmer/* 617202198Sed * utmpx 618202198Sed */ 619202198Sed 620202198Sed#define UTMPXPRINTID do { \ 621202198Sed size_t i; \ 622202198Sed for (i = 0; i < sizeof ut->ut_id; i++) \ 623202198Sed printf("%02hhx", ut->ut_id[i]); \ 624202198Sed} while (0) 625202198Sed 626202198Sedstatic void 627202198Sedutmpxprint(const struct utmpx *ut) 628202198Sed{ 629202198Sed 630202198Sed if (ut->ut_type == EMPTY) 631202198Sed return; 632202198Sed 633202718Sed printf("[%jd.%06u -- %.24s] ", 634202718Sed (intmax_t)ut->ut_tv.tv_sec, (unsigned int)ut->ut_tv.tv_usec, 635202718Sed ctime(&ut->ut_tv.tv_sec)); 636202198Sed 637202198Sed switch (ut->ut_type) { 638202198Sed case BOOT_TIME: 639202198Sed printf("system boot\n"); 640202198Sed return; 641202198Sed case SHUTDOWN_TIME: 642202198Sed printf("system shutdown\n"); 643202198Sed return; 644202198Sed case OLD_TIME: 645202198Sed printf("old system time\n"); 646202198Sed return; 647202198Sed case NEW_TIME: 648202198Sed printf("new system time\n"); 649202198Sed return; 650202198Sed case USER_PROCESS: 651202198Sed printf("user process: id=\""); 652202198Sed UTMPXPRINTID; 653202559Sed printf("\" pid=\"%d\" user=\"%s\" line=\"%s\" host=\"%s\"\n", 654202559Sed ut->ut_pid, ut->ut_user, ut->ut_line, ut->ut_host); 655202198Sed break; 656226841Sed case INIT_PROCESS: 657226841Sed printf("init process: id=\""); 658226841Sed UTMPXPRINTID; 659226841Sed printf("\" pid=\"%d\"\n", ut->ut_pid); 660226841Sed break; 661226841Sed case LOGIN_PROCESS: 662226841Sed printf("login process: id=\""); 663226841Sed UTMPXPRINTID; 664226841Sed printf("\" pid=\"%d\" user=\"%s\" line=\"%s\" host=\"%s\"\n", 665226841Sed ut->ut_pid, ut->ut_user, ut->ut_line, ut->ut_host); 666226841Sed break; 667202198Sed case DEAD_PROCESS: 668202198Sed printf("dead process: id=\""); 669202198Sed UTMPXPRINTID; 670202559Sed printf("\" pid=\"%d\"\n", ut->ut_pid); 671202198Sed break; 672202198Sed default: 673226841Sed printf("unknown record type %hu\n", ut->ut_type); 674202198Sed break; 675202198Sed } 676202198Sed} 677202198Sed 678202198Sedstatic int 679202198Sedutmpx(int argc, char *argv[]) 680202198Sed{ 681202198Sed const struct utmpx *ut; 682206087Sed const char *file = NULL; 683206087Sed int rv = RV_OK, db = 0; 684202198Sed 685202198Sed assert(argc > 1); 686202198Sed assert(argv != NULL); 687202198Sed 688206087Sed if (argc == 3 || argc == 4) { 689202198Sed if (strcmp(argv[2], "active") == 0) 690202198Sed db = UTXDB_ACTIVE; 691202198Sed else if (strcmp(argv[2], "lastlogin") == 0) 692202198Sed db = UTXDB_LASTLOGIN; 693202198Sed else if (strcmp(argv[2], "log") == 0) 694202198Sed db = UTXDB_LOG; 695202198Sed else 696202198Sed rv = RV_USAGE; 697206087Sed if (argc == 4) 698206087Sed file = argv[3]; 699202198Sed } else { 700202198Sed rv = RV_USAGE; 701202198Sed } 702202198Sed 703202198Sed if (rv == RV_USAGE) { 704206087Sed fprintf(stderr, 705206087Sed "Usage: %s utmpx active | lastlogin | log [filename]\n", 706202198Sed getprogname()); 707202198Sed } else if (rv == RV_OK) { 708206087Sed if (setutxdb(db, file) != 0) 709202198Sed return (RV_NOTFOUND); 710202198Sed while ((ut = getutxent()) != NULL) 711202198Sed utmpxprint(ut); 712202198Sed endutxent(); 713202198Sed } 714202198Sed return (rv); 715202198Sed} 716