getent.c revision 158287
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 158287 2006-05-04 08:44:44Z maxim $"); 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> 63158287Smaxim 64158287Smaximstatic int usage(void); 65158287Smaximstatic int parsenum(const char *, unsigned long *); 66158287Smaximstatic int ethers(int, char *[]); 67158287Smaximstatic int group(int, char *[]); 68158287Smaximstatic int hosts(int, char *[]); 69158287Smaximstatic int networks(int, char *[]); 70158287Smaximstatic int passwd(int, char *[]); 71158287Smaximstatic int protocols(int, char *[]); 72158287Smaximstatic int rpc(int, char *[]); 73158287Smaximstatic int services(int, char *[]); 74158287Smaximstatic int shells(int, char *[]); 75158287Smaxim 76158287Smaximenum { 77158287Smaxim RV_OK = 0, 78158287Smaxim RV_USAGE = 1, 79158287Smaxim RV_NOTFOUND = 2, 80158287Smaxim RV_NOENUM = 3, 81158287Smaxim}; 82158287Smaxim 83158287Smaximstatic struct getentdb { 84158287Smaxim const char *name; 85158287Smaxim int (*callback)(int, char *[]); 86158287Smaxim} databases[] = { 87158287Smaxim { "ethers", ethers, }, 88158287Smaxim { "group", group, }, 89158287Smaxim { "hosts", hosts, }, 90158287Smaxim { "networks", networks, }, 91158287Smaxim { "passwd", passwd, }, 92158287Smaxim { "protocols", protocols, }, 93158287Smaxim { "rpc", rpc, }, 94158287Smaxim { "services", services, }, 95158287Smaxim { "shells", shells, }, 96158287Smaxim 97158287Smaxim { NULL, NULL, }, 98158287Smaxim}; 99158287Smaxim 100158287Smaximint 101158287Smaximmain(int argc, char *argv[]) 102158287Smaxim{ 103158287Smaxim struct getentdb *curdb; 104158287Smaxim 105158287Smaxim setprogname(argv[0]); 106158287Smaxim 107158287Smaxim if (argc < 2) 108158287Smaxim usage(); 109158287Smaxim for (curdb = databases; curdb->name != NULL; curdb++) { 110158287Smaxim if (strcmp(curdb->name, argv[1]) == 0) { 111158287Smaxim exit(curdb->callback(argc, argv)); 112158287Smaxim break; 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"); 181158287Smaxim} 182158287Smaxim 183158287Smaxim/* 184158287Smaxim * ethers 185158287Smaxim */ 186158287Smaximstatic int 187158287Smaximethers(int argc, char *argv[]) 188158287Smaxim{ 189158287Smaxim char hostname[MAXHOSTNAMELEN + 1], *hp; 190158287Smaxim struct ether_addr ea, *eap; 191158287Smaxim int i, rv; 192158287Smaxim 193158287Smaxim assert(argc > 1); 194158287Smaxim assert(argv != NULL); 195158287Smaxim 196158287Smaxim#define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp) 197158287Smaxim 198158287Smaxim rv = RV_OK; 199158287Smaxim if (argc == 2) { 200158287Smaxim fprintf(stderr, "Enumeration not supported on ethers\n"); 201158287Smaxim rv = RV_NOENUM; 202158287Smaxim } else { 203158287Smaxim for (i = 2; i < argc; i++) { 204158287Smaxim if ((eap = ether_aton(argv[i])) == NULL) { 205158287Smaxim eap = &ea; 206158287Smaxim hp = argv[i]; 207158287Smaxim if (ether_hostton(hp, eap) != 0) { 208158287Smaxim rv = RV_NOTFOUND; 209158287Smaxim break; 210158287Smaxim } 211158287Smaxim } else { 212158287Smaxim hp = hostname; 213158287Smaxim if (ether_ntohost(hp, eap) != 0) { 214158287Smaxim rv = RV_NOTFOUND; 215158287Smaxim break; 216158287Smaxim } 217158287Smaxim } 218158287Smaxim ETHERSPRINT; 219158287Smaxim } 220158287Smaxim } 221158287Smaxim return rv; 222158287Smaxim} 223158287Smaxim 224158287Smaxim/* 225158287Smaxim * group 226158287Smaxim */ 227158287Smaxim 228158287Smaximstatic int 229158287Smaximgroup(int argc, char *argv[]) 230158287Smaxim{ 231158287Smaxim struct group *gr; 232158287Smaxim unsigned long id; 233158287Smaxim int i, rv; 234158287Smaxim 235158287Smaxim assert(argc > 1); 236158287Smaxim assert(argv != NULL); 237158287Smaxim 238158287Smaxim#define GROUPPRINT printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \ 239158287Smaxim gr->gr_name, gr->gr_passwd, gr->gr_gid) 240158287Smaxim 241158287Smaxim setgroupent(1); 242158287Smaxim rv = RV_OK; 243158287Smaxim if (argc == 2) { 244158287Smaxim while ((gr = getgrent()) != NULL) 245158287Smaxim GROUPPRINT; 246158287Smaxim } else { 247158287Smaxim for (i = 2; i < argc; i++) { 248158287Smaxim if (parsenum(argv[i], &id)) 249158287Smaxim gr = getgrgid((gid_t)id); 250158287Smaxim else 251158287Smaxim gr = getgrnam(argv[i]); 252158287Smaxim if (gr != NULL) 253158287Smaxim GROUPPRINT; 254158287Smaxim else { 255158287Smaxim rv = RV_NOTFOUND; 256158287Smaxim break; 257158287Smaxim } 258158287Smaxim } 259158287Smaxim } 260158287Smaxim endgrent(); 261158287Smaxim return rv; 262158287Smaxim} 263158287Smaxim 264158287Smaxim 265158287Smaxim/* 266158287Smaxim * hosts 267158287Smaxim */ 268158287Smaxim 269158287Smaximstatic void 270158287Smaximhostsprint(const struct hostent *he) 271158287Smaxim{ 272158287Smaxim char buf[INET6_ADDRSTRLEN]; 273158287Smaxim 274158287Smaxim assert(he != NULL); 275158287Smaxim if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL) 276158287Smaxim strlcpy(buf, "# unknown", sizeof(buf)); 277158287Smaxim printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name); 278158287Smaxim} 279158287Smaxim 280158287Smaximstatic int 281158287Smaximhosts(int argc, char *argv[]) 282158287Smaxim{ 283158287Smaxim struct hostent *he; 284158287Smaxim char addr[IN6ADDRSZ]; 285158287Smaxim int i, rv; 286158287Smaxim 287158287Smaxim assert(argc > 1); 288158287Smaxim assert(argv != NULL); 289158287Smaxim 290158287Smaxim sethostent(1); 291158287Smaxim rv = RV_OK; 292158287Smaxim if (argc == 2) { 293158287Smaxim while ((he = gethostent()) != NULL) 294158287Smaxim hostsprint(he); 295158287Smaxim } else { 296158287Smaxim for (i = 2; i < argc; i++) { 297158287Smaxim if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0) 298158287Smaxim he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6); 299158287Smaxim else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0) 300158287Smaxim he = gethostbyaddr(addr, INADDRSZ, AF_INET); 301158287Smaxim else 302158287Smaxim he = gethostbyname(argv[i]); 303158287Smaxim if (he != NULL) 304158287Smaxim hostsprint(he); 305158287Smaxim else { 306158287Smaxim rv = RV_NOTFOUND; 307158287Smaxim break; 308158287Smaxim } 309158287Smaxim } 310158287Smaxim } 311158287Smaxim endhostent(); 312158287Smaxim return rv; 313158287Smaxim} 314158287Smaxim 315158287Smaxim/* 316158287Smaxim * networks 317158287Smaxim */ 318158287Smaximstatic void 319158287Smaximnetworksprint(const struct netent *ne) 320158287Smaxim{ 321158287Smaxim char buf[INET6_ADDRSTRLEN]; 322158287Smaxim struct in_addr ianet; 323158287Smaxim 324158287Smaxim assert(ne != NULL); 325158287Smaxim ianet = inet_makeaddr(ne->n_net, 0); 326158287Smaxim if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL) 327158287Smaxim strlcpy(buf, "# unknown", sizeof(buf)); 328158287Smaxim printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf); 329158287Smaxim} 330158287Smaxim 331158287Smaximstatic int 332158287Smaximnetworks(int argc, char *argv[]) 333158287Smaxim{ 334158287Smaxim struct netent *ne; 335158287Smaxim in_addr_t net; 336158287Smaxim int i, rv; 337158287Smaxim 338158287Smaxim assert(argc > 1); 339158287Smaxim assert(argv != NULL); 340158287Smaxim 341158287Smaxim setnetent(1); 342158287Smaxim rv = RV_OK; 343158287Smaxim if (argc == 2) { 344158287Smaxim while ((ne = getnetent()) != NULL) 345158287Smaxim networksprint(ne); 346158287Smaxim } else { 347158287Smaxim for (i = 2; i < argc; i++) { 348158287Smaxim net = inet_network(argv[i]); 349158287Smaxim if (net != INADDR_NONE) 350158287Smaxim ne = getnetbyaddr(net, AF_INET); 351158287Smaxim else 352158287Smaxim ne = getnetbyname(argv[i]); 353158287Smaxim if (ne != NULL) 354158287Smaxim networksprint(ne); 355158287Smaxim else { 356158287Smaxim rv = RV_NOTFOUND; 357158287Smaxim break; 358158287Smaxim } 359158287Smaxim } 360158287Smaxim } 361158287Smaxim endnetent(); 362158287Smaxim return rv; 363158287Smaxim} 364158287Smaxim 365158287Smaxim/* 366158287Smaxim * passwd 367158287Smaxim */ 368158287Smaximstatic int 369158287Smaximpasswd(int argc, char *argv[]) 370158287Smaxim{ 371158287Smaxim struct passwd *pw; 372158287Smaxim unsigned long id; 373158287Smaxim int i, rv; 374158287Smaxim 375158287Smaxim assert(argc > 1); 376158287Smaxim assert(argv != NULL); 377158287Smaxim 378158287Smaxim#define PASSWDPRINT printf("%s:%s:%u:%u:%s:%s:%s\n", \ 379158287Smaxim pw->pw_name, pw->pw_passwd, pw->pw_uid, \ 380158287Smaxim pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell) 381158287Smaxim 382158287Smaxim setpassent(1); 383158287Smaxim rv = RV_OK; 384158287Smaxim if (argc == 2) { 385158287Smaxim while ((pw = getpwent()) != NULL) 386158287Smaxim PASSWDPRINT; 387158287Smaxim } else { 388158287Smaxim for (i = 2; i < argc; i++) { 389158287Smaxim if (parsenum(argv[i], &id)) 390158287Smaxim pw = getpwuid((uid_t)id); 391158287Smaxim else 392158287Smaxim pw = getpwnam(argv[i]); 393158287Smaxim if (pw != NULL) 394158287Smaxim PASSWDPRINT; 395158287Smaxim else { 396158287Smaxim rv = RV_NOTFOUND; 397158287Smaxim break; 398158287Smaxim } 399158287Smaxim } 400158287Smaxim } 401158287Smaxim endpwent(); 402158287Smaxim return rv; 403158287Smaxim} 404158287Smaxim 405158287Smaxim/* 406158287Smaxim * protocols 407158287Smaxim */ 408158287Smaximstatic int 409158287Smaximprotocols(int argc, char *argv[]) 410158287Smaxim{ 411158287Smaxim struct protoent *pe; 412158287Smaxim unsigned long id; 413158287Smaxim int i, rv; 414158287Smaxim 415158287Smaxim assert(argc > 1); 416158287Smaxim assert(argv != NULL); 417158287Smaxim 418158287Smaxim#define PROTOCOLSPRINT printfmtstrings(pe->p_aliases, " ", " ", \ 419158287Smaxim "%-16s %5d", pe->p_name, pe->p_proto) 420158287Smaxim 421158287Smaxim setprotoent(1); 422158287Smaxim rv = RV_OK; 423158287Smaxim if (argc == 2) { 424158287Smaxim while ((pe = getprotoent()) != NULL) 425158287Smaxim PROTOCOLSPRINT; 426158287Smaxim } else { 427158287Smaxim for (i = 2; i < argc; i++) { 428158287Smaxim if (parsenum(argv[i], &id)) 429158287Smaxim pe = getprotobynumber((int)id); 430158287Smaxim else 431158287Smaxim pe = getprotobyname(argv[i]); 432158287Smaxim if (pe != NULL) 433158287Smaxim PROTOCOLSPRINT; 434158287Smaxim else { 435158287Smaxim rv = RV_NOTFOUND; 436158287Smaxim break; 437158287Smaxim } 438158287Smaxim } 439158287Smaxim } 440158287Smaxim endprotoent(); 441158287Smaxim return rv; 442158287Smaxim} 443158287Smaxim 444158287Smaxim/* 445158287Smaxim * rpc 446158287Smaxim */ 447158287Smaximstatic int 448158287Smaximrpc(int argc, char *argv[]) 449158287Smaxim{ 450158287Smaxim struct rpcent *re; 451158287Smaxim unsigned long id; 452158287Smaxim int i, rv; 453158287Smaxim 454158287Smaxim assert(argc > 1); 455158287Smaxim assert(argv != NULL); 456158287Smaxim 457158287Smaxim#define RPCPRINT printfmtstrings(re->r_aliases, " ", " ", \ 458158287Smaxim "%-16s %6d", \ 459158287Smaxim re->r_name, re->r_number) 460158287Smaxim 461158287Smaxim setrpcent(1); 462158287Smaxim rv = RV_OK; 463158287Smaxim if (argc == 2) { 464158287Smaxim while ((re = getrpcent()) != NULL) 465158287Smaxim RPCPRINT; 466158287Smaxim } else { 467158287Smaxim for (i = 2; i < argc; i++) { 468158287Smaxim if (parsenum(argv[i], &id)) 469158287Smaxim re = getrpcbynumber((int)id); 470158287Smaxim else 471158287Smaxim re = getrpcbyname(argv[i]); 472158287Smaxim if (re != NULL) 473158287Smaxim RPCPRINT; 474158287Smaxim else { 475158287Smaxim rv = RV_NOTFOUND; 476158287Smaxim break; 477158287Smaxim } 478158287Smaxim } 479158287Smaxim } 480158287Smaxim endrpcent(); 481158287Smaxim return rv; 482158287Smaxim} 483158287Smaxim 484158287Smaxim/* 485158287Smaxim * services 486158287Smaxim */ 487158287Smaximstatic int 488158287Smaximservices(int argc, char *argv[]) 489158287Smaxim{ 490158287Smaxim struct servent *se; 491158287Smaxim unsigned long id; 492158287Smaxim char *proto; 493158287Smaxim int i, rv; 494158287Smaxim 495158287Smaxim assert(argc > 1); 496158287Smaxim assert(argv != NULL); 497158287Smaxim 498158287Smaxim#define SERVICESPRINT printfmtstrings(se->s_aliases, " ", " ", \ 499158287Smaxim "%-16s %5d/%s", \ 500158287Smaxim se->s_name, ntohs(se->s_port), se->s_proto) 501158287Smaxim 502158287Smaxim setservent(1); 503158287Smaxim rv = RV_OK; 504158287Smaxim if (argc == 2) { 505158287Smaxim while ((se = getservent()) != NULL) 506158287Smaxim SERVICESPRINT; 507158287Smaxim } else { 508158287Smaxim for (i = 2; i < argc; i++) { 509158287Smaxim proto = strchr(argv[i], '/'); 510158287Smaxim if (proto != NULL) 511158287Smaxim *proto++ = '\0'; 512158287Smaxim if (parsenum(argv[i], &id)) { 513158287Smaxim printf("%lu %s\n", id, proto); 514158287Smaxim se = getservbyport((int)id, proto); 515158287Smaxim } else 516158287Smaxim se = getservbyname(argv[i], proto); 517158287Smaxim if (se != NULL) 518158287Smaxim SERVICESPRINT; 519158287Smaxim else { 520158287Smaxim rv = RV_NOTFOUND; 521158287Smaxim break; 522158287Smaxim } 523158287Smaxim } 524158287Smaxim } 525158287Smaxim endservent(); 526158287Smaxim return rv; 527158287Smaxim} 528158287Smaxim 529158287Smaxim/* 530158287Smaxim * shells 531158287Smaxim */ 532158287Smaximstatic int 533158287Smaximshells(int argc, char *argv[]) 534158287Smaxim{ 535158287Smaxim const char *sh; 536158287Smaxim int i, rv; 537158287Smaxim 538158287Smaxim assert(argc > 1); 539158287Smaxim assert(argv != NULL); 540158287Smaxim 541158287Smaxim#define SHELLSPRINT printf("%s\n", sh) 542158287Smaxim 543158287Smaxim setusershell(); 544158287Smaxim rv = RV_OK; 545158287Smaxim if (argc == 2) { 546158287Smaxim while ((sh = getusershell()) != NULL) 547158287Smaxim SHELLSPRINT; 548158287Smaxim } else { 549158287Smaxim for (i = 2; i < argc; i++) { 550158287Smaxim setusershell(); 551158287Smaxim while ((sh = getusershell()) != NULL) { 552158287Smaxim if (strcmp(sh, argv[i]) == 0) { 553158287Smaxim SHELLSPRINT; 554158287Smaxim break; 555158287Smaxim } 556158287Smaxim } 557158287Smaxim if (sh == NULL) { 558158287Smaxim rv = RV_NOTFOUND; 559158287Smaxim break; 560158287Smaxim } 561158287Smaxim } 562158287Smaxim } 563158287Smaxim endusershell(); 564158287Smaxim return rv; 565158287Smaxim} 566