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