getent.c revision 202559
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 * 3. All advertising materials mentioning features or use of this software 19158287Smaxim * must display the following acknowledgement: 20158287Smaxim * This product includes software developed by the NetBSD 21158287Smaxim * Foundation, Inc. and its contributors. 22158287Smaxim * 4. Neither the name of The NetBSD Foundation nor the names of its 23158287Smaxim * contributors may be used to endorse or promote products derived 24158287Smaxim * from this software without specific prior written permission. 25158287Smaxim * 26158287Smaxim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27158287Smaxim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28158287Smaxim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29158287Smaxim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30158287Smaxim * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31158287Smaxim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32158287Smaxim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33158287Smaxim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34158287Smaxim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35158287Smaxim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36158287Smaxim * POSSIBILITY OF SUCH DAMAGE. 37158287Smaxim */ 38158287Smaxim 39158287Smaxim#include <sys/cdefs.h> 40158287Smaxim__FBSDID("$FreeBSD: head/usr.bin/getent/getent.c 202559 2010-01-18 10:50:25Z ed $"); 41158287Smaxim 42158287Smaxim#include <sys/socket.h> 43158287Smaxim#include <sys/param.h> 44158287Smaxim#include <arpa/inet.h> 45158287Smaxim#include <arpa/nameser.h> 46158287Smaxim#include <net/if.h> 47158287Smaxim#include <netinet/if_ether.h> 48158287Smaxim#include <netinet/in.h> /* for INET6_ADDRSTRLEN */ 49158287Smaxim#include <rpc/rpcent.h> 50158287Smaxim 51158287Smaxim#include <assert.h> 52158287Smaxim#include <ctype.h> 53158287Smaxim#include <errno.h> 54158287Smaxim#include <grp.h> 55158287Smaxim#include <limits.h> 56158287Smaxim#include <netdb.h> 57158287Smaxim#include <pwd.h> 58158287Smaxim#include <stdio.h> 59158287Smaxim#include <stdarg.h> 60158287Smaxim#include <stdlib.h> 61158287Smaxim#include <string.h> 62158287Smaxim#include <unistd.h> 63202198Sed#include <utmpx.h> 64158287Smaxim 65158287Smaximstatic int usage(void); 66158287Smaximstatic int parsenum(const char *, unsigned long *); 67158287Smaximstatic int ethers(int, char *[]); 68158287Smaximstatic int group(int, char *[]); 69158287Smaximstatic int hosts(int, char *[]); 70158287Smaximstatic int networks(int, char *[]); 71158287Smaximstatic int passwd(int, char *[]); 72158287Smaximstatic int protocols(int, char *[]); 73158287Smaximstatic int rpc(int, char *[]); 74158287Smaximstatic int services(int, char *[]); 75158287Smaximstatic int shells(int, char *[]); 76202198Sedstatic int utmpx(int, char *[]); 77158287Smaxim 78158287Smaximenum { 79158287Smaxim RV_OK = 0, 80158287Smaxim RV_USAGE = 1, 81158287Smaxim RV_NOTFOUND = 2, 82166504Srse RV_NOENUM = 3 83158287Smaxim}; 84158287Smaxim 85158287Smaximstatic struct getentdb { 86158287Smaxim const char *name; 87158287Smaxim int (*callback)(int, char *[]); 88158287Smaxim} databases[] = { 89158287Smaxim { "ethers", ethers, }, 90158287Smaxim { "group", group, }, 91158287Smaxim { "hosts", hosts, }, 92158287Smaxim { "networks", networks, }, 93158287Smaxim { "passwd", passwd, }, 94158287Smaxim { "protocols", protocols, }, 95158287Smaxim { "rpc", rpc, }, 96158287Smaxim { "services", services, }, 97158287Smaxim { "shells", shells, }, 98202198Sed { "utmpx", utmpx, }, 99158287Smaxim 100158287Smaxim { NULL, NULL, }, 101158287Smaxim}; 102158287Smaxim 103158287Smaximint 104158287Smaximmain(int argc, char *argv[]) 105158287Smaxim{ 106158287Smaxim struct getentdb *curdb; 107158287Smaxim 108158287Smaxim setprogname(argv[0]); 109158287Smaxim 110158287Smaxim if (argc < 2) 111158287Smaxim usage(); 112158287Smaxim for (curdb = databases; curdb->name != NULL; curdb++) { 113158287Smaxim if (strcmp(curdb->name, argv[1]) == 0) { 114158287Smaxim exit(curdb->callback(argc, argv)); 115158287Smaxim } 116158287Smaxim } 117158287Smaxim fprintf(stderr, "Unknown database: %s\n", argv[1]); 118158287Smaxim usage(); 119158287Smaxim /* NOTREACHED */ 120158287Smaxim return RV_USAGE; 121158287Smaxim} 122158287Smaxim 123158287Smaximstatic int 124158287Smaximusage(void) 125158287Smaxim{ 126158287Smaxim struct getentdb *curdb; 127158287Smaxim 128158287Smaxim fprintf(stderr, "Usage: %s database [key ...]\n", 129158287Smaxim getprogname()); 130158287Smaxim fprintf(stderr, " database may be one of:\n\t"); 131158287Smaxim for (curdb = databases; curdb->name != NULL; curdb++) { 132158287Smaxim fprintf(stderr, " %s", curdb->name); 133158287Smaxim } 134158287Smaxim fprintf(stderr, "\n"); 135158287Smaxim exit(RV_USAGE); 136158287Smaxim /* NOTREACHED */ 137158287Smaxim} 138158287Smaxim 139158287Smaximstatic int 140158287Smaximparsenum(const char *word, unsigned long *result) 141158287Smaxim{ 142158287Smaxim unsigned long num; 143158287Smaxim char *ep; 144158287Smaxim 145158287Smaxim assert(word != NULL); 146158287Smaxim assert(result != NULL); 147158287Smaxim 148158287Smaxim if (!isdigit((unsigned char)word[0])) 149158287Smaxim return 0; 150158287Smaxim errno = 0; 151158287Smaxim num = strtoul(word, &ep, 10); 152158287Smaxim if (num == ULONG_MAX && errno == ERANGE) 153158287Smaxim return 0; 154158287Smaxim if (*ep != '\0') 155158287Smaxim return 0; 156158287Smaxim *result = num; 157158287Smaxim return 1; 158158287Smaxim} 159158287Smaxim 160158287Smaxim/* 161158287Smaxim * printfmtstrings -- 162158287Smaxim * vprintf(format, ...), 163158287Smaxim * then the aliases (beginning with prefix, separated by sep), 164158287Smaxim * then a newline 165158287Smaxim */ 166158287Smaximstatic void 167158287Smaximprintfmtstrings(char *strings[], const char *prefix, const char *sep, 168158287Smaxim const char *fmt, ...) 169158287Smaxim{ 170158287Smaxim va_list ap; 171158287Smaxim const char *curpref; 172158287Smaxim int i; 173158287Smaxim 174158287Smaxim va_start(ap, fmt); 175158287Smaxim vprintf(fmt, ap); 176158287Smaxim 177158287Smaxim curpref = prefix; 178158287Smaxim for (i = 0; strings[i] != NULL; i++) { 179158287Smaxim printf("%s%s", curpref, strings[i]); 180158287Smaxim curpref = sep; 181158287Smaxim } 182158287Smaxim printf("\n"); 183166504Srse va_end(ap); 184158287Smaxim} 185158287Smaxim 186158287Smaxim/* 187158287Smaxim * ethers 188158287Smaxim */ 189158287Smaximstatic int 190158287Smaximethers(int argc, char *argv[]) 191158287Smaxim{ 192158287Smaxim char hostname[MAXHOSTNAMELEN + 1], *hp; 193158287Smaxim struct ether_addr ea, *eap; 194158287Smaxim int i, rv; 195158287Smaxim 196158287Smaxim assert(argc > 1); 197158287Smaxim assert(argv != NULL); 198158287Smaxim 199158287Smaxim#define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp) 200158287Smaxim 201158287Smaxim rv = RV_OK; 202158287Smaxim if (argc == 2) { 203158287Smaxim fprintf(stderr, "Enumeration not supported on ethers\n"); 204158287Smaxim rv = RV_NOENUM; 205158287Smaxim } else { 206158287Smaxim for (i = 2; i < argc; i++) { 207158287Smaxim if ((eap = ether_aton(argv[i])) == NULL) { 208158287Smaxim eap = &ea; 209158287Smaxim hp = argv[i]; 210158287Smaxim if (ether_hostton(hp, eap) != 0) { 211158287Smaxim rv = RV_NOTFOUND; 212158287Smaxim break; 213158287Smaxim } 214158287Smaxim } else { 215158287Smaxim hp = hostname; 216158287Smaxim if (ether_ntohost(hp, eap) != 0) { 217158287Smaxim rv = RV_NOTFOUND; 218158287Smaxim break; 219158287Smaxim } 220158287Smaxim } 221158287Smaxim ETHERSPRINT; 222158287Smaxim } 223158287Smaxim } 224158287Smaxim return rv; 225158287Smaxim} 226158287Smaxim 227158287Smaxim/* 228158287Smaxim * group 229158287Smaxim */ 230158287Smaxim 231158287Smaximstatic int 232158287Smaximgroup(int argc, char *argv[]) 233158287Smaxim{ 234158287Smaxim struct group *gr; 235158287Smaxim unsigned long id; 236158287Smaxim int i, rv; 237158287Smaxim 238158287Smaxim assert(argc > 1); 239158287Smaxim assert(argv != NULL); 240158287Smaxim 241158287Smaxim#define GROUPPRINT printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \ 242158287Smaxim gr->gr_name, gr->gr_passwd, gr->gr_gid) 243158287Smaxim 244158287Smaxim setgroupent(1); 245158287Smaxim rv = RV_OK; 246158287Smaxim if (argc == 2) { 247158287Smaxim while ((gr = getgrent()) != NULL) 248158287Smaxim GROUPPRINT; 249158287Smaxim } else { 250158287Smaxim for (i = 2; i < argc; i++) { 251158287Smaxim if (parsenum(argv[i], &id)) 252158287Smaxim gr = getgrgid((gid_t)id); 253158287Smaxim else 254158287Smaxim gr = getgrnam(argv[i]); 255158287Smaxim if (gr != NULL) 256158287Smaxim GROUPPRINT; 257158287Smaxim else { 258158287Smaxim rv = RV_NOTFOUND; 259158287Smaxim break; 260158287Smaxim } 261158287Smaxim } 262158287Smaxim } 263158287Smaxim endgrent(); 264158287Smaxim return rv; 265158287Smaxim} 266158287Smaxim 267158287Smaxim 268158287Smaxim/* 269158287Smaxim * hosts 270158287Smaxim */ 271158287Smaxim 272158287Smaximstatic void 273158287Smaximhostsprint(const struct hostent *he) 274158287Smaxim{ 275158287Smaxim char buf[INET6_ADDRSTRLEN]; 276158287Smaxim 277158287Smaxim assert(he != NULL); 278158287Smaxim if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL) 279158287Smaxim strlcpy(buf, "# unknown", sizeof(buf)); 280158287Smaxim printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name); 281158287Smaxim} 282158287Smaxim 283158287Smaximstatic int 284158287Smaximhosts(int argc, char *argv[]) 285158287Smaxim{ 286158287Smaxim struct hostent *he; 287158287Smaxim char addr[IN6ADDRSZ]; 288158287Smaxim int i, rv; 289158287Smaxim 290158287Smaxim assert(argc > 1); 291158287Smaxim assert(argv != NULL); 292158287Smaxim 293158287Smaxim sethostent(1); 294158287Smaxim rv = RV_OK; 295158287Smaxim if (argc == 2) { 296158287Smaxim while ((he = gethostent()) != NULL) 297158287Smaxim hostsprint(he); 298158287Smaxim } else { 299158287Smaxim for (i = 2; i < argc; i++) { 300158287Smaxim if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0) 301158287Smaxim he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6); 302158287Smaxim else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0) 303158287Smaxim he = gethostbyaddr(addr, INADDRSZ, AF_INET); 304158287Smaxim else 305158287Smaxim he = gethostbyname(argv[i]); 306158287Smaxim if (he != NULL) 307158287Smaxim hostsprint(he); 308158287Smaxim else { 309158287Smaxim rv = RV_NOTFOUND; 310158287Smaxim break; 311158287Smaxim } 312158287Smaxim } 313158287Smaxim } 314158287Smaxim endhostent(); 315158287Smaxim return rv; 316158287Smaxim} 317158287Smaxim 318158287Smaxim/* 319158287Smaxim * networks 320158287Smaxim */ 321158287Smaximstatic void 322158287Smaximnetworksprint(const struct netent *ne) 323158287Smaxim{ 324158287Smaxim char buf[INET6_ADDRSTRLEN]; 325158287Smaxim struct in_addr ianet; 326158287Smaxim 327158287Smaxim assert(ne != NULL); 328158287Smaxim ianet = inet_makeaddr(ne->n_net, 0); 329158287Smaxim if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL) 330158287Smaxim strlcpy(buf, "# unknown", sizeof(buf)); 331158287Smaxim printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf); 332158287Smaxim} 333158287Smaxim 334158287Smaximstatic int 335158287Smaximnetworks(int argc, char *argv[]) 336158287Smaxim{ 337158287Smaxim struct netent *ne; 338158287Smaxim in_addr_t net; 339158287Smaxim int i, rv; 340158287Smaxim 341158287Smaxim assert(argc > 1); 342158287Smaxim assert(argv != NULL); 343158287Smaxim 344158287Smaxim setnetent(1); 345158287Smaxim rv = RV_OK; 346158287Smaxim if (argc == 2) { 347158287Smaxim while ((ne = getnetent()) != NULL) 348158287Smaxim networksprint(ne); 349158287Smaxim } else { 350158287Smaxim for (i = 2; i < argc; i++) { 351158287Smaxim net = inet_network(argv[i]); 352158287Smaxim if (net != INADDR_NONE) 353158287Smaxim ne = getnetbyaddr(net, AF_INET); 354158287Smaxim else 355158287Smaxim ne = getnetbyname(argv[i]); 356158287Smaxim if (ne != NULL) 357158287Smaxim networksprint(ne); 358158287Smaxim else { 359158287Smaxim rv = RV_NOTFOUND; 360158287Smaxim break; 361158287Smaxim } 362158287Smaxim } 363158287Smaxim } 364158287Smaxim endnetent(); 365158287Smaxim return rv; 366158287Smaxim} 367158287Smaxim 368158287Smaxim/* 369158287Smaxim * passwd 370158287Smaxim */ 371158287Smaximstatic int 372158287Smaximpasswd(int argc, char *argv[]) 373158287Smaxim{ 374158287Smaxim struct passwd *pw; 375158287Smaxim unsigned long id; 376158287Smaxim int i, rv; 377158287Smaxim 378158287Smaxim assert(argc > 1); 379158287Smaxim assert(argv != NULL); 380158287Smaxim 381158287Smaxim#define PASSWDPRINT printf("%s:%s:%u:%u:%s:%s:%s\n", \ 382158287Smaxim pw->pw_name, pw->pw_passwd, pw->pw_uid, \ 383158287Smaxim pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell) 384158287Smaxim 385158287Smaxim setpassent(1); 386158287Smaxim rv = RV_OK; 387158287Smaxim if (argc == 2) { 388158287Smaxim while ((pw = getpwent()) != NULL) 389158287Smaxim PASSWDPRINT; 390158287Smaxim } else { 391158287Smaxim for (i = 2; i < argc; i++) { 392158287Smaxim if (parsenum(argv[i], &id)) 393158287Smaxim pw = getpwuid((uid_t)id); 394158287Smaxim else 395158287Smaxim pw = getpwnam(argv[i]); 396158287Smaxim if (pw != NULL) 397158287Smaxim PASSWDPRINT; 398158287Smaxim else { 399158287Smaxim rv = RV_NOTFOUND; 400158287Smaxim break; 401158287Smaxim } 402158287Smaxim } 403158287Smaxim } 404158287Smaxim endpwent(); 405158287Smaxim return rv; 406158287Smaxim} 407158287Smaxim 408158287Smaxim/* 409158287Smaxim * protocols 410158287Smaxim */ 411158287Smaximstatic int 412158287Smaximprotocols(int argc, char *argv[]) 413158287Smaxim{ 414158287Smaxim struct protoent *pe; 415158287Smaxim unsigned long id; 416158287Smaxim int i, rv; 417158287Smaxim 418158287Smaxim assert(argc > 1); 419158287Smaxim assert(argv != NULL); 420158287Smaxim 421158287Smaxim#define PROTOCOLSPRINT printfmtstrings(pe->p_aliases, " ", " ", \ 422158287Smaxim "%-16s %5d", pe->p_name, pe->p_proto) 423158287Smaxim 424158287Smaxim setprotoent(1); 425158287Smaxim rv = RV_OK; 426158287Smaxim if (argc == 2) { 427158287Smaxim while ((pe = getprotoent()) != NULL) 428158287Smaxim PROTOCOLSPRINT; 429158287Smaxim } else { 430158287Smaxim for (i = 2; i < argc; i++) { 431158287Smaxim if (parsenum(argv[i], &id)) 432158287Smaxim pe = getprotobynumber((int)id); 433158287Smaxim else 434158287Smaxim pe = getprotobyname(argv[i]); 435158287Smaxim if (pe != NULL) 436158287Smaxim PROTOCOLSPRINT; 437158287Smaxim else { 438158287Smaxim rv = RV_NOTFOUND; 439158287Smaxim break; 440158287Smaxim } 441158287Smaxim } 442158287Smaxim } 443158287Smaxim endprotoent(); 444158287Smaxim return rv; 445158287Smaxim} 446158287Smaxim 447158287Smaxim/* 448158287Smaxim * rpc 449158287Smaxim */ 450158287Smaximstatic int 451158287Smaximrpc(int argc, char *argv[]) 452158287Smaxim{ 453158287Smaxim struct rpcent *re; 454158287Smaxim unsigned long id; 455158287Smaxim int i, rv; 456158287Smaxim 457158287Smaxim assert(argc > 1); 458158287Smaxim assert(argv != NULL); 459158287Smaxim 460158287Smaxim#define RPCPRINT printfmtstrings(re->r_aliases, " ", " ", \ 461158287Smaxim "%-16s %6d", \ 462158287Smaxim re->r_name, re->r_number) 463158287Smaxim 464158287Smaxim setrpcent(1); 465158287Smaxim rv = RV_OK; 466158287Smaxim if (argc == 2) { 467158287Smaxim while ((re = getrpcent()) != NULL) 468158287Smaxim RPCPRINT; 469158287Smaxim } else { 470158287Smaxim for (i = 2; i < argc; i++) { 471158287Smaxim if (parsenum(argv[i], &id)) 472158287Smaxim re = getrpcbynumber((int)id); 473158287Smaxim else 474158287Smaxim re = getrpcbyname(argv[i]); 475158287Smaxim if (re != NULL) 476158287Smaxim RPCPRINT; 477158287Smaxim else { 478158287Smaxim rv = RV_NOTFOUND; 479158287Smaxim break; 480158287Smaxim } 481158287Smaxim } 482158287Smaxim } 483158287Smaxim endrpcent(); 484158287Smaxim return rv; 485158287Smaxim} 486158287Smaxim 487158287Smaxim/* 488158287Smaxim * services 489158287Smaxim */ 490158287Smaximstatic int 491158287Smaximservices(int argc, char *argv[]) 492158287Smaxim{ 493158287Smaxim struct servent *se; 494158287Smaxim unsigned long id; 495158287Smaxim char *proto; 496158287Smaxim int i, rv; 497158287Smaxim 498158287Smaxim assert(argc > 1); 499158287Smaxim assert(argv != NULL); 500158287Smaxim 501158287Smaxim#define SERVICESPRINT printfmtstrings(se->s_aliases, " ", " ", \ 502158287Smaxim "%-16s %5d/%s", \ 503158287Smaxim se->s_name, ntohs(se->s_port), se->s_proto) 504158287Smaxim 505158287Smaxim setservent(1); 506158287Smaxim rv = RV_OK; 507158287Smaxim if (argc == 2) { 508158287Smaxim while ((se = getservent()) != NULL) 509158287Smaxim SERVICESPRINT; 510158287Smaxim } else { 511158287Smaxim for (i = 2; i < argc; i++) { 512158287Smaxim proto = strchr(argv[i], '/'); 513158287Smaxim if (proto != NULL) 514158287Smaxim *proto++ = '\0'; 515158289Sume if (parsenum(argv[i], &id)) 516158289Sume se = getservbyport(htons((u_short)id), proto); 517158289Sume else 518158287Smaxim se = getservbyname(argv[i], proto); 519158287Smaxim if (se != NULL) 520158287Smaxim SERVICESPRINT; 521158287Smaxim else { 522158287Smaxim rv = RV_NOTFOUND; 523158287Smaxim break; 524158287Smaxim } 525158287Smaxim } 526158287Smaxim } 527158287Smaxim endservent(); 528158287Smaxim return rv; 529158287Smaxim} 530158287Smaxim 531158287Smaxim/* 532158287Smaxim * shells 533158287Smaxim */ 534158287Smaximstatic int 535158287Smaximshells(int argc, char *argv[]) 536158287Smaxim{ 537158287Smaxim const char *sh; 538158287Smaxim int i, rv; 539158287Smaxim 540158287Smaxim assert(argc > 1); 541158287Smaxim assert(argv != NULL); 542158287Smaxim 543158287Smaxim#define SHELLSPRINT printf("%s\n", sh) 544158287Smaxim 545158287Smaxim setusershell(); 546158287Smaxim rv = RV_OK; 547158287Smaxim if (argc == 2) { 548158287Smaxim while ((sh = getusershell()) != NULL) 549158287Smaxim SHELLSPRINT; 550158287Smaxim } else { 551158287Smaxim for (i = 2; i < argc; i++) { 552158287Smaxim setusershell(); 553158287Smaxim while ((sh = getusershell()) != NULL) { 554158287Smaxim if (strcmp(sh, argv[i]) == 0) { 555158287Smaxim SHELLSPRINT; 556158287Smaxim break; 557158287Smaxim } 558158287Smaxim } 559158287Smaxim if (sh == NULL) { 560158287Smaxim rv = RV_NOTFOUND; 561158287Smaxim break; 562158287Smaxim } 563158287Smaxim } 564158287Smaxim } 565158287Smaxim endusershell(); 566158287Smaxim return rv; 567158287Smaxim} 568202198Sed 569202198Sed/* 570202198Sed * utmpx 571202198Sed */ 572202198Sed 573202198Sed#define UTMPXPRINTID do { \ 574202198Sed size_t i; \ 575202198Sed for (i = 0; i < sizeof ut->ut_id; i++) \ 576202198Sed printf("%02hhx", ut->ut_id[i]); \ 577202198Sed} while (0) 578202198Sed 579202198Sedstatic void 580202198Sedutmpxprint(const struct utmpx *ut) 581202198Sed{ 582202198Sed 583202198Sed if (ut->ut_type == EMPTY) 584202198Sed return; 585202198Sed 586202198Sed printf("[%.24s] ", ctime(&ut->ut_tv.tv_sec)); 587202198Sed 588202198Sed switch (ut->ut_type) { 589202198Sed case BOOT_TIME: 590202198Sed printf("system boot\n"); 591202198Sed return; 592202198Sed case SHUTDOWN_TIME: 593202198Sed printf("system shutdown\n"); 594202198Sed return; 595202198Sed case OLD_TIME: 596202198Sed printf("old system time\n"); 597202198Sed return; 598202198Sed case NEW_TIME: 599202198Sed printf("new system time\n"); 600202198Sed return; 601202198Sed case USER_PROCESS: 602202198Sed printf("user process: id=\""); 603202198Sed UTMPXPRINTID; 604202559Sed printf("\" pid=\"%d\" user=\"%s\" line=\"%s\" host=\"%s\"\n", 605202559Sed ut->ut_pid, ut->ut_user, ut->ut_line, ut->ut_host); 606202198Sed break; 607202198Sed case DEAD_PROCESS: 608202198Sed printf("dead process: id=\""); 609202198Sed UTMPXPRINTID; 610202559Sed printf("\" pid=\"%d\"\n", ut->ut_pid); 611202198Sed break; 612202198Sed default: 613202198Sed printf("unknown record type\n"); 614202198Sed break; 615202198Sed } 616202198Sed} 617202198Sed 618202198Sedstatic int 619202198Sedutmpx(int argc, char *argv[]) 620202198Sed{ 621202198Sed const struct utmpx *ut; 622202198Sed int rv = RV_OK, db; 623202198Sed 624202198Sed assert(argc > 1); 625202198Sed assert(argv != NULL); 626202198Sed 627202198Sed if (argc == 2) { 628202198Sed db = UTXDB_ACTIVE; 629202198Sed } else if (argc == 3) { 630202198Sed if (strcmp(argv[2], "active") == 0) 631202198Sed db = UTXDB_ACTIVE; 632202198Sed else if (strcmp(argv[2], "lastlogin") == 0) 633202198Sed db = UTXDB_LASTLOGIN; 634202198Sed else if (strcmp(argv[2], "log") == 0) 635202198Sed db = UTXDB_LOG; 636202198Sed else 637202198Sed rv = RV_USAGE; 638202198Sed } else { 639202198Sed rv = RV_USAGE; 640202198Sed } 641202198Sed 642202198Sed if (rv == RV_USAGE) { 643202198Sed fprintf(stderr, "Usage: %s utmpx [active | lastlogin | log]\n", 644202198Sed getprogname()); 645202198Sed } else if (rv == RV_OK) { 646202198Sed if (setutxdb(db, NULL) != 0) 647202198Sed return (RV_NOTFOUND); 648202198Sed while ((ut = getutxent()) != NULL) 649202198Sed utmpxprint(ut); 650202198Sed endutxent(); 651202198Sed } 652202198Sed return (rv); 653202198Sed} 654