getent.c revision 206087
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: head/usr.bin/getent/getent.c 206087 2010-04-02 11:05:59Z ed $"); 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 *[]); 64158287Smaximstatic int networks(int, char *[]); 65158287Smaximstatic int passwd(int, char *[]); 66158287Smaximstatic int protocols(int, char *[]); 67158287Smaximstatic int rpc(int, char *[]); 68158287Smaximstatic int services(int, char *[]); 69158287Smaximstatic int shells(int, char *[]); 70202198Sedstatic int utmpx(int, char *[]); 71158287Smaxim 72158287Smaximenum { 73158287Smaxim RV_OK = 0, 74158287Smaxim RV_USAGE = 1, 75158287Smaxim RV_NOTFOUND = 2, 76166504Srse RV_NOENUM = 3 77158287Smaxim}; 78158287Smaxim 79158287Smaximstatic struct getentdb { 80158287Smaxim const char *name; 81158287Smaxim int (*callback)(int, char *[]); 82158287Smaxim} databases[] = { 83158287Smaxim { "ethers", ethers, }, 84158287Smaxim { "group", group, }, 85158287Smaxim { "hosts", hosts, }, 86158287Smaxim { "networks", networks, }, 87158287Smaxim { "passwd", passwd, }, 88158287Smaxim { "protocols", protocols, }, 89158287Smaxim { "rpc", rpc, }, 90158287Smaxim { "services", services, }, 91158287Smaxim { "shells", shells, }, 92202198Sed { "utmpx", utmpx, }, 93158287Smaxim 94158287Smaxim { NULL, NULL, }, 95158287Smaxim}; 96158287Smaxim 97158287Smaximint 98158287Smaximmain(int argc, char *argv[]) 99158287Smaxim{ 100158287Smaxim struct getentdb *curdb; 101158287Smaxim 102158287Smaxim setprogname(argv[0]); 103158287Smaxim 104158287Smaxim if (argc < 2) 105158287Smaxim usage(); 106158287Smaxim for (curdb = databases; curdb->name != NULL; curdb++) { 107158287Smaxim if (strcmp(curdb->name, argv[1]) == 0) { 108158287Smaxim exit(curdb->callback(argc, argv)); 109158287Smaxim } 110158287Smaxim } 111158287Smaxim fprintf(stderr, "Unknown database: %s\n", argv[1]); 112158287Smaxim usage(); 113158287Smaxim /* NOTREACHED */ 114158287Smaxim return RV_USAGE; 115158287Smaxim} 116158287Smaxim 117158287Smaximstatic int 118158287Smaximusage(void) 119158287Smaxim{ 120158287Smaxim struct getentdb *curdb; 121158287Smaxim 122158287Smaxim fprintf(stderr, "Usage: %s database [key ...]\n", 123158287Smaxim getprogname()); 124158287Smaxim fprintf(stderr, " database may be one of:\n\t"); 125158287Smaxim for (curdb = databases; curdb->name != NULL; curdb++) { 126158287Smaxim fprintf(stderr, " %s", curdb->name); 127158287Smaxim } 128158287Smaxim fprintf(stderr, "\n"); 129158287Smaxim exit(RV_USAGE); 130158287Smaxim /* NOTREACHED */ 131158287Smaxim} 132158287Smaxim 133158287Smaximstatic int 134158287Smaximparsenum(const char *word, unsigned long *result) 135158287Smaxim{ 136158287Smaxim unsigned long num; 137158287Smaxim char *ep; 138158287Smaxim 139158287Smaxim assert(word != NULL); 140158287Smaxim assert(result != NULL); 141158287Smaxim 142158287Smaxim if (!isdigit((unsigned char)word[0])) 143158287Smaxim return 0; 144158287Smaxim errno = 0; 145158287Smaxim num = strtoul(word, &ep, 10); 146158287Smaxim if (num == ULONG_MAX && errno == ERANGE) 147158287Smaxim return 0; 148158287Smaxim if (*ep != '\0') 149158287Smaxim return 0; 150158287Smaxim *result = num; 151158287Smaxim return 1; 152158287Smaxim} 153158287Smaxim 154158287Smaxim/* 155158287Smaxim * printfmtstrings -- 156158287Smaxim * vprintf(format, ...), 157158287Smaxim * then the aliases (beginning with prefix, separated by sep), 158158287Smaxim * then a newline 159158287Smaxim */ 160158287Smaximstatic void 161158287Smaximprintfmtstrings(char *strings[], const char *prefix, const char *sep, 162158287Smaxim const char *fmt, ...) 163158287Smaxim{ 164158287Smaxim va_list ap; 165158287Smaxim const char *curpref; 166158287Smaxim int i; 167158287Smaxim 168158287Smaxim va_start(ap, fmt); 169158287Smaxim vprintf(fmt, ap); 170158287Smaxim 171158287Smaxim curpref = prefix; 172158287Smaxim for (i = 0; strings[i] != NULL; i++) { 173158287Smaxim printf("%s%s", curpref, strings[i]); 174158287Smaxim curpref = sep; 175158287Smaxim } 176158287Smaxim printf("\n"); 177166504Srse va_end(ap); 178158287Smaxim} 179158287Smaxim 180158287Smaxim/* 181158287Smaxim * ethers 182158287Smaxim */ 183158287Smaximstatic int 184158287Smaximethers(int argc, char *argv[]) 185158287Smaxim{ 186158287Smaxim char hostname[MAXHOSTNAMELEN + 1], *hp; 187158287Smaxim struct ether_addr ea, *eap; 188158287Smaxim int i, rv; 189158287Smaxim 190158287Smaxim assert(argc > 1); 191158287Smaxim assert(argv != NULL); 192158287Smaxim 193158287Smaxim#define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp) 194158287Smaxim 195158287Smaxim rv = RV_OK; 196158287Smaxim if (argc == 2) { 197158287Smaxim fprintf(stderr, "Enumeration not supported on ethers\n"); 198158287Smaxim rv = RV_NOENUM; 199158287Smaxim } else { 200158287Smaxim for (i = 2; i < argc; i++) { 201158287Smaxim if ((eap = ether_aton(argv[i])) == NULL) { 202158287Smaxim eap = &ea; 203158287Smaxim hp = argv[i]; 204158287Smaxim if (ether_hostton(hp, eap) != 0) { 205158287Smaxim rv = RV_NOTFOUND; 206158287Smaxim break; 207158287Smaxim } 208158287Smaxim } else { 209158287Smaxim hp = hostname; 210158287Smaxim if (ether_ntohost(hp, eap) != 0) { 211158287Smaxim rv = RV_NOTFOUND; 212158287Smaxim break; 213158287Smaxim } 214158287Smaxim } 215158287Smaxim ETHERSPRINT; 216158287Smaxim } 217158287Smaxim } 218158287Smaxim return rv; 219158287Smaxim} 220158287Smaxim 221158287Smaxim/* 222158287Smaxim * group 223158287Smaxim */ 224158287Smaxim 225158287Smaximstatic int 226158287Smaximgroup(int argc, char *argv[]) 227158287Smaxim{ 228158287Smaxim struct group *gr; 229158287Smaxim unsigned long id; 230158287Smaxim int i, rv; 231158287Smaxim 232158287Smaxim assert(argc > 1); 233158287Smaxim assert(argv != NULL); 234158287Smaxim 235158287Smaxim#define GROUPPRINT printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \ 236158287Smaxim gr->gr_name, gr->gr_passwd, gr->gr_gid) 237158287Smaxim 238158287Smaxim setgroupent(1); 239158287Smaxim rv = RV_OK; 240158287Smaxim if (argc == 2) { 241158287Smaxim while ((gr = getgrent()) != NULL) 242158287Smaxim GROUPPRINT; 243158287Smaxim } else { 244158287Smaxim for (i = 2; i < argc; i++) { 245158287Smaxim if (parsenum(argv[i], &id)) 246158287Smaxim gr = getgrgid((gid_t)id); 247158287Smaxim else 248158287Smaxim gr = getgrnam(argv[i]); 249158287Smaxim if (gr != NULL) 250158287Smaxim GROUPPRINT; 251158287Smaxim else { 252158287Smaxim rv = RV_NOTFOUND; 253158287Smaxim break; 254158287Smaxim } 255158287Smaxim } 256158287Smaxim } 257158287Smaxim endgrent(); 258158287Smaxim return rv; 259158287Smaxim} 260158287Smaxim 261158287Smaxim 262158287Smaxim/* 263158287Smaxim * hosts 264158287Smaxim */ 265158287Smaxim 266158287Smaximstatic void 267158287Smaximhostsprint(const struct hostent *he) 268158287Smaxim{ 269158287Smaxim char buf[INET6_ADDRSTRLEN]; 270158287Smaxim 271158287Smaxim assert(he != NULL); 272158287Smaxim if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL) 273158287Smaxim strlcpy(buf, "# unknown", sizeof(buf)); 274158287Smaxim printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name); 275158287Smaxim} 276158287Smaxim 277158287Smaximstatic int 278158287Smaximhosts(int argc, char *argv[]) 279158287Smaxim{ 280158287Smaxim struct hostent *he; 281158287Smaxim char addr[IN6ADDRSZ]; 282158287Smaxim int i, rv; 283158287Smaxim 284158287Smaxim assert(argc > 1); 285158287Smaxim assert(argv != NULL); 286158287Smaxim 287158287Smaxim sethostent(1); 288158287Smaxim rv = RV_OK; 289158287Smaxim if (argc == 2) { 290158287Smaxim while ((he = gethostent()) != NULL) 291158287Smaxim hostsprint(he); 292158287Smaxim } else { 293158287Smaxim for (i = 2; i < argc; i++) { 294158287Smaxim if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0) 295158287Smaxim he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6); 296158287Smaxim else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0) 297158287Smaxim he = gethostbyaddr(addr, INADDRSZ, AF_INET); 298158287Smaxim else 299158287Smaxim he = gethostbyname(argv[i]); 300158287Smaxim if (he != NULL) 301158287Smaxim hostsprint(he); 302158287Smaxim else { 303158287Smaxim rv = RV_NOTFOUND; 304158287Smaxim break; 305158287Smaxim } 306158287Smaxim } 307158287Smaxim } 308158287Smaxim endhostent(); 309158287Smaxim return rv; 310158287Smaxim} 311158287Smaxim 312158287Smaxim/* 313158287Smaxim * networks 314158287Smaxim */ 315158287Smaximstatic void 316158287Smaximnetworksprint(const struct netent *ne) 317158287Smaxim{ 318158287Smaxim char buf[INET6_ADDRSTRLEN]; 319158287Smaxim struct in_addr ianet; 320158287Smaxim 321158287Smaxim assert(ne != NULL); 322158287Smaxim ianet = inet_makeaddr(ne->n_net, 0); 323158287Smaxim if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL) 324158287Smaxim strlcpy(buf, "# unknown", sizeof(buf)); 325158287Smaxim printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf); 326158287Smaxim} 327158287Smaxim 328158287Smaximstatic int 329158287Smaximnetworks(int argc, char *argv[]) 330158287Smaxim{ 331158287Smaxim struct netent *ne; 332158287Smaxim in_addr_t net; 333158287Smaxim int i, rv; 334158287Smaxim 335158287Smaxim assert(argc > 1); 336158287Smaxim assert(argv != NULL); 337158287Smaxim 338158287Smaxim setnetent(1); 339158287Smaxim rv = RV_OK; 340158287Smaxim if (argc == 2) { 341158287Smaxim while ((ne = getnetent()) != NULL) 342158287Smaxim networksprint(ne); 343158287Smaxim } else { 344158287Smaxim for (i = 2; i < argc; i++) { 345158287Smaxim net = inet_network(argv[i]); 346158287Smaxim if (net != INADDR_NONE) 347158287Smaxim ne = getnetbyaddr(net, AF_INET); 348158287Smaxim else 349158287Smaxim ne = getnetbyname(argv[i]); 350158287Smaxim if (ne != NULL) 351158287Smaxim networksprint(ne); 352158287Smaxim else { 353158287Smaxim rv = RV_NOTFOUND; 354158287Smaxim break; 355158287Smaxim } 356158287Smaxim } 357158287Smaxim } 358158287Smaxim endnetent(); 359158287Smaxim return rv; 360158287Smaxim} 361158287Smaxim 362158287Smaxim/* 363158287Smaxim * passwd 364158287Smaxim */ 365158287Smaximstatic int 366158287Smaximpasswd(int argc, char *argv[]) 367158287Smaxim{ 368158287Smaxim struct passwd *pw; 369158287Smaxim unsigned long id; 370158287Smaxim int i, rv; 371158287Smaxim 372158287Smaxim assert(argc > 1); 373158287Smaxim assert(argv != NULL); 374158287Smaxim 375158287Smaxim#define PASSWDPRINT printf("%s:%s:%u:%u:%s:%s:%s\n", \ 376158287Smaxim pw->pw_name, pw->pw_passwd, pw->pw_uid, \ 377158287Smaxim pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell) 378158287Smaxim 379158287Smaxim setpassent(1); 380158287Smaxim rv = RV_OK; 381158287Smaxim if (argc == 2) { 382158287Smaxim while ((pw = getpwent()) != NULL) 383158287Smaxim PASSWDPRINT; 384158287Smaxim } else { 385158287Smaxim for (i = 2; i < argc; i++) { 386158287Smaxim if (parsenum(argv[i], &id)) 387158287Smaxim pw = getpwuid((uid_t)id); 388158287Smaxim else 389158287Smaxim pw = getpwnam(argv[i]); 390158287Smaxim if (pw != NULL) 391158287Smaxim PASSWDPRINT; 392158287Smaxim else { 393158287Smaxim rv = RV_NOTFOUND; 394158287Smaxim break; 395158287Smaxim } 396158287Smaxim } 397158287Smaxim } 398158287Smaxim endpwent(); 399158287Smaxim return rv; 400158287Smaxim} 401158287Smaxim 402158287Smaxim/* 403158287Smaxim * protocols 404158287Smaxim */ 405158287Smaximstatic int 406158287Smaximprotocols(int argc, char *argv[]) 407158287Smaxim{ 408158287Smaxim struct protoent *pe; 409158287Smaxim unsigned long id; 410158287Smaxim int i, rv; 411158287Smaxim 412158287Smaxim assert(argc > 1); 413158287Smaxim assert(argv != NULL); 414158287Smaxim 415158287Smaxim#define PROTOCOLSPRINT printfmtstrings(pe->p_aliases, " ", " ", \ 416158287Smaxim "%-16s %5d", pe->p_name, pe->p_proto) 417158287Smaxim 418158287Smaxim setprotoent(1); 419158287Smaxim rv = RV_OK; 420158287Smaxim if (argc == 2) { 421158287Smaxim while ((pe = getprotoent()) != NULL) 422158287Smaxim PROTOCOLSPRINT; 423158287Smaxim } else { 424158287Smaxim for (i = 2; i < argc; i++) { 425158287Smaxim if (parsenum(argv[i], &id)) 426158287Smaxim pe = getprotobynumber((int)id); 427158287Smaxim else 428158287Smaxim pe = getprotobyname(argv[i]); 429158287Smaxim if (pe != NULL) 430158287Smaxim PROTOCOLSPRINT; 431158287Smaxim else { 432158287Smaxim rv = RV_NOTFOUND; 433158287Smaxim break; 434158287Smaxim } 435158287Smaxim } 436158287Smaxim } 437158287Smaxim endprotoent(); 438158287Smaxim return rv; 439158287Smaxim} 440158287Smaxim 441158287Smaxim/* 442158287Smaxim * rpc 443158287Smaxim */ 444158287Smaximstatic int 445158287Smaximrpc(int argc, char *argv[]) 446158287Smaxim{ 447158287Smaxim struct rpcent *re; 448158287Smaxim unsigned long id; 449158287Smaxim int i, rv; 450158287Smaxim 451158287Smaxim assert(argc > 1); 452158287Smaxim assert(argv != NULL); 453158287Smaxim 454158287Smaxim#define RPCPRINT printfmtstrings(re->r_aliases, " ", " ", \ 455158287Smaxim "%-16s %6d", \ 456158287Smaxim re->r_name, re->r_number) 457158287Smaxim 458158287Smaxim setrpcent(1); 459158287Smaxim rv = RV_OK; 460158287Smaxim if (argc == 2) { 461158287Smaxim while ((re = getrpcent()) != NULL) 462158287Smaxim RPCPRINT; 463158287Smaxim } else { 464158287Smaxim for (i = 2; i < argc; i++) { 465158287Smaxim if (parsenum(argv[i], &id)) 466158287Smaxim re = getrpcbynumber((int)id); 467158287Smaxim else 468158287Smaxim re = getrpcbyname(argv[i]); 469158287Smaxim if (re != NULL) 470158287Smaxim RPCPRINT; 471158287Smaxim else { 472158287Smaxim rv = RV_NOTFOUND; 473158287Smaxim break; 474158287Smaxim } 475158287Smaxim } 476158287Smaxim } 477158287Smaxim endrpcent(); 478158287Smaxim return rv; 479158287Smaxim} 480158287Smaxim 481158287Smaxim/* 482158287Smaxim * services 483158287Smaxim */ 484158287Smaximstatic int 485158287Smaximservices(int argc, char *argv[]) 486158287Smaxim{ 487158287Smaxim struct servent *se; 488158287Smaxim unsigned long id; 489158287Smaxim char *proto; 490158287Smaxim int i, rv; 491158287Smaxim 492158287Smaxim assert(argc > 1); 493158287Smaxim assert(argv != NULL); 494158287Smaxim 495158287Smaxim#define SERVICESPRINT printfmtstrings(se->s_aliases, " ", " ", \ 496158287Smaxim "%-16s %5d/%s", \ 497158287Smaxim se->s_name, ntohs(se->s_port), se->s_proto) 498158287Smaxim 499158287Smaxim setservent(1); 500158287Smaxim rv = RV_OK; 501158287Smaxim if (argc == 2) { 502158287Smaxim while ((se = getservent()) != NULL) 503158287Smaxim SERVICESPRINT; 504158287Smaxim } else { 505158287Smaxim for (i = 2; i < argc; i++) { 506158287Smaxim proto = strchr(argv[i], '/'); 507158287Smaxim if (proto != NULL) 508158287Smaxim *proto++ = '\0'; 509158289Sume if (parsenum(argv[i], &id)) 510158289Sume se = getservbyport(htons((u_short)id), proto); 511158289Sume else 512158287Smaxim se = getservbyname(argv[i], proto); 513158287Smaxim if (se != NULL) 514158287Smaxim SERVICESPRINT; 515158287Smaxim else { 516158287Smaxim rv = RV_NOTFOUND; 517158287Smaxim break; 518158287Smaxim } 519158287Smaxim } 520158287Smaxim } 521158287Smaxim endservent(); 522158287Smaxim return rv; 523158287Smaxim} 524158287Smaxim 525158287Smaxim/* 526158287Smaxim * shells 527158287Smaxim */ 528158287Smaximstatic int 529158287Smaximshells(int argc, char *argv[]) 530158287Smaxim{ 531158287Smaxim const char *sh; 532158287Smaxim int i, rv; 533158287Smaxim 534158287Smaxim assert(argc > 1); 535158287Smaxim assert(argv != NULL); 536158287Smaxim 537158287Smaxim#define SHELLSPRINT printf("%s\n", sh) 538158287Smaxim 539158287Smaxim setusershell(); 540158287Smaxim rv = RV_OK; 541158287Smaxim if (argc == 2) { 542158287Smaxim while ((sh = getusershell()) != NULL) 543158287Smaxim SHELLSPRINT; 544158287Smaxim } else { 545158287Smaxim for (i = 2; i < argc; i++) { 546158287Smaxim setusershell(); 547158287Smaxim while ((sh = getusershell()) != NULL) { 548158287Smaxim if (strcmp(sh, argv[i]) == 0) { 549158287Smaxim SHELLSPRINT; 550158287Smaxim break; 551158287Smaxim } 552158287Smaxim } 553158287Smaxim if (sh == NULL) { 554158287Smaxim rv = RV_NOTFOUND; 555158287Smaxim break; 556158287Smaxim } 557158287Smaxim } 558158287Smaxim } 559158287Smaxim endusershell(); 560158287Smaxim return rv; 561158287Smaxim} 562202198Sed 563202198Sed/* 564202198Sed * utmpx 565202198Sed */ 566202198Sed 567202198Sed#define UTMPXPRINTID do { \ 568202198Sed size_t i; \ 569202198Sed for (i = 0; i < sizeof ut->ut_id; i++) \ 570202198Sed printf("%02hhx", ut->ut_id[i]); \ 571202198Sed} while (0) 572202198Sed 573202198Sedstatic void 574202198Sedutmpxprint(const struct utmpx *ut) 575202198Sed{ 576202198Sed 577202198Sed if (ut->ut_type == EMPTY) 578202198Sed return; 579202198Sed 580202718Sed printf("[%jd.%06u -- %.24s] ", 581202718Sed (intmax_t)ut->ut_tv.tv_sec, (unsigned int)ut->ut_tv.tv_usec, 582202718Sed ctime(&ut->ut_tv.tv_sec)); 583202198Sed 584202198Sed switch (ut->ut_type) { 585202198Sed case BOOT_TIME: 586202198Sed printf("system boot\n"); 587202198Sed return; 588202198Sed case SHUTDOWN_TIME: 589202198Sed printf("system shutdown\n"); 590202198Sed return; 591202198Sed case OLD_TIME: 592202198Sed printf("old system time\n"); 593202198Sed return; 594202198Sed case NEW_TIME: 595202198Sed printf("new system time\n"); 596202198Sed return; 597202198Sed case USER_PROCESS: 598202198Sed printf("user process: id=\""); 599202198Sed UTMPXPRINTID; 600202559Sed printf("\" pid=\"%d\" user=\"%s\" line=\"%s\" host=\"%s\"\n", 601202559Sed ut->ut_pid, ut->ut_user, ut->ut_line, ut->ut_host); 602202198Sed break; 603202198Sed case DEAD_PROCESS: 604202198Sed printf("dead process: id=\""); 605202198Sed UTMPXPRINTID; 606202559Sed printf("\" pid=\"%d\"\n", ut->ut_pid); 607202198Sed break; 608202198Sed default: 609202198Sed printf("unknown record type\n"); 610202198Sed break; 611202198Sed } 612202198Sed} 613202198Sed 614202198Sedstatic int 615202198Sedutmpx(int argc, char *argv[]) 616202198Sed{ 617202198Sed const struct utmpx *ut; 618206087Sed const char *file = NULL; 619206087Sed int rv = RV_OK, db = 0; 620202198Sed 621202198Sed assert(argc > 1); 622202198Sed assert(argv != NULL); 623202198Sed 624206087Sed if (argc == 3 || argc == 4) { 625202198Sed if (strcmp(argv[2], "active") == 0) 626202198Sed db = UTXDB_ACTIVE; 627202198Sed else if (strcmp(argv[2], "lastlogin") == 0) 628202198Sed db = UTXDB_LASTLOGIN; 629202198Sed else if (strcmp(argv[2], "log") == 0) 630202198Sed db = UTXDB_LOG; 631202198Sed else 632202198Sed rv = RV_USAGE; 633206087Sed if (argc == 4) 634206087Sed file = argv[3]; 635202198Sed } else { 636202198Sed rv = RV_USAGE; 637202198Sed } 638202198Sed 639202198Sed if (rv == RV_USAGE) { 640206087Sed fprintf(stderr, 641206087Sed "Usage: %s utmpx active | lastlogin | log [filename]\n", 642202198Sed getprogname()); 643202198Sed } else if (rv == RV_OK) { 644206087Sed if (setutxdb(db, file) != 0) 645202198Sed return (RV_NOTFOUND); 646202198Sed while ((ut = getutxent()) != NULL) 647202198Sed utmpxprint(ut); 648202198Sed endutxent(); 649202198Sed } 650202198Sed return (rv); 651202198Sed} 652