getent.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  1. /* Copyright (c) 1998-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>. */
  14. /* getent: get entries from administrative database. */
  15. #include <aliases.h>
  16. #include <argp.h>
  17. #include <ctype.h>
  18. #include <error.h>
  19. #include <grp.h>
  20. #include <gshadow.h>
  21. #include <libintl.h>
  22. #include <locale.h>
  23. #include <mcheck.h>
  24. #include <netdb.h>
  25. #include <pwd.h>
  26. #include <shadow.h>
  27. #include <stdbool.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <arpa/inet.h>
  32. #include <arpa/nameser.h>
  33. #include <netinet/ether.h>
  34. #include <netinet/in.h>
  35. #include <sys/socket.h>
  36. #include <scratch_buffer.h>
  37. #include <inttypes.h>
  38. /* Get libc version number. */
  39. #include <version.h>
  40. #define PACKAGE _libc_intl_domainname
  41. /* Name and version of program. */
  42. static void print_version (FILE *stream, struct argp_state *state);
  43. void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
  44. /* Short description of parameters. */
  45. static const char args_doc[] = N_("database [key ...]");
  46. /* Supported options. */
  47. static const struct argp_option args_options[] =
  48. {
  49. { "service", 's', N_("CONFIG"), 0, N_("Service configuration to be used") },
  50. { "no-idn", 'i', NULL, 0, N_("disable IDN encoding") },
  51. { "no-addrconfig", 'A', NULL, 0,
  52. N_("do not filter out unsupported IPv4/IPv6 addresses (with ahosts*)") },
  53. { NULL, 0, NULL, 0, NULL },
  54. };
  55. /* Short description of program. */
  56. static const char doc[] = N_("Get entries from administrative database.");
  57. /* Prototype for option handler. */
  58. static error_t parse_option (int key, char *arg, struct argp_state *state);
  59. /* Function to print some extra text in the help message. */
  60. static char *more_help (int key, const char *text, void *input);
  61. /* Data structure to communicate with argp functions. */
  62. static struct argp argp =
  63. {
  64. args_options, parse_option, args_doc, doc, NULL, more_help
  65. };
  66. /* Additional getaddrinfo flags for IDN encoding. */
  67. static int idn_flags = AI_IDN | AI_CANONIDN;
  68. /* Set to 0 by --no-addrconfig. */
  69. static int addrconfig_flags = AI_ADDRCONFIG;
  70. /* Print the version information. */
  71. static void
  72. print_version (FILE *stream, struct argp_state *state)
  73. {
  74. fprintf (stream, "getent %s%s\n", PKGVERSION, VERSION);
  75. fprintf (stream, gettext ("\
  76. Copyright (C) %s Free Software Foundation, Inc.\n\
  77. This is free software; see the source for copying conditions. There is NO\n\
  78. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
  79. "), "2024");
  80. fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
  81. }
  82. /* This is for aliases */
  83. static void
  84. print_aliases (struct aliasent *alias)
  85. {
  86. unsigned int i = 0;
  87. printf ("%s: ", alias->alias_name);
  88. for (i = strlen (alias->alias_name); i < 14; ++i)
  89. fputs_unlocked (" ", stdout);
  90. for (i = 0; i < alias->alias_members_len; ++i)
  91. printf ("%s%s",
  92. alias->alias_members [i],
  93. i + 1 == alias->alias_members_len ? "\n" : ", ");
  94. }
  95. static int
  96. aliases_keys (int number, char *key[])
  97. {
  98. int result = 0;
  99. int i;
  100. struct aliasent *alias;
  101. if (number == 0)
  102. {
  103. setaliasent ();
  104. while ((alias = getaliasent ()) != NULL)
  105. print_aliases (alias);
  106. endaliasent ();
  107. return result;
  108. }
  109. for (i = 0; i < number; ++i)
  110. {
  111. alias = getaliasbyname (key[i]);
  112. if (alias == NULL)
  113. result = 2;
  114. else
  115. print_aliases (alias);
  116. }
  117. return result;
  118. }
  119. /* This is for ethers */
  120. static int
  121. ethers_keys (int number, char *key[])
  122. {
  123. int result = 0;
  124. int i;
  125. if (number == 0)
  126. {
  127. fprintf (stderr, _("Enumeration not supported on %s\n"), "ethers");
  128. return 3;
  129. }
  130. for (i = 0; i < number; ++i)
  131. {
  132. struct ether_addr *ethp, eth;
  133. char buffer [1024], *p;
  134. ethp = ether_aton (key[i]);
  135. if (ethp != NULL)
  136. {
  137. if (ether_ntohost (buffer, ethp))
  138. {
  139. result = 2;
  140. continue;
  141. }
  142. p = buffer;
  143. }
  144. else
  145. {
  146. if (ether_hostton (key[i], &eth))
  147. {
  148. result = 2;
  149. continue;
  150. }
  151. p = key[i];
  152. ethp = &eth;
  153. }
  154. printf ("%s %s\n", ether_ntoa (ethp), p);
  155. }
  156. return result;
  157. }
  158. /* This is for group */
  159. static void
  160. print_group (struct group *grp)
  161. {
  162. if (putgrent (grp, stdout) != 0)
  163. fprintf (stderr, "error writing group entry: %m\n");
  164. }
  165. static int
  166. group_keys (int number, char *key[])
  167. {
  168. int result = 0;
  169. int i;
  170. struct group *grp;
  171. if (number == 0)
  172. {
  173. setgrent ();
  174. while ((grp = getgrent ()) != NULL)
  175. print_group (grp);
  176. endgrent ();
  177. return result;
  178. }
  179. for (i = 0; i < number; ++i)
  180. {
  181. errno = 0;
  182. char *ep;
  183. gid_t arg_gid = strtoul(key[i], &ep, 10);
  184. if (errno != EINVAL && *key[i] != '\0' && *ep == '\0')
  185. /* Valid numeric gid. */
  186. grp = getgrgid (arg_gid);
  187. else
  188. grp = getgrnam (key[i]);
  189. if (grp == NULL)
  190. result = 2;
  191. else
  192. print_group (grp);
  193. }
  194. return result;
  195. }
  196. /* This is for gshadow */
  197. static void
  198. print_gshadow (struct sgrp *sg)
  199. {
  200. if (putsgent (sg, stdout) != 0)
  201. fprintf (stderr, "error writing gshadow entry: %m\n");
  202. }
  203. static int
  204. gshadow_keys (int number, char *key[])
  205. {
  206. int result = 0;
  207. int i;
  208. if (number == 0)
  209. {
  210. struct sgrp *sg;
  211. setsgent ();
  212. while ((sg = getsgent ()) != NULL)
  213. print_gshadow (sg);
  214. endsgent ();
  215. return result;
  216. }
  217. for (i = 0; i < number; ++i)
  218. {
  219. struct sgrp *sg;
  220. sg = getsgnam (key[i]);
  221. if (sg == NULL)
  222. result = 2;
  223. else
  224. print_gshadow (sg);
  225. }
  226. return result;
  227. }
  228. /* This is for hosts */
  229. static void
  230. print_hosts (struct hostent *host)
  231. {
  232. unsigned int cnt;
  233. for (cnt = 0; host->h_addr_list[cnt] != NULL; ++cnt)
  234. {
  235. char buf[INET6_ADDRSTRLEN];
  236. const char *ip = inet_ntop (host->h_addrtype, host->h_addr_list[cnt],
  237. buf, sizeof (buf));
  238. printf ("%-15s %s", ip, host->h_name);
  239. unsigned int i;
  240. for (i = 0; host->h_aliases[i] != NULL; ++i)
  241. {
  242. putchar_unlocked (' ');
  243. fputs_unlocked (host->h_aliases[i], stdout);
  244. }
  245. putchar_unlocked ('\n');
  246. }
  247. }
  248. static int
  249. hosts_keys (int number, char *key[])
  250. {
  251. int result = 0;
  252. int i;
  253. struct hostent *host;
  254. if (number == 0)
  255. {
  256. sethostent (0);
  257. while ((host = gethostent ()) != NULL)
  258. print_hosts (host);
  259. endhostent ();
  260. return result;
  261. }
  262. for (i = 0; i < number; ++i)
  263. {
  264. struct hostent *host = NULL;
  265. char addr[IN6ADDRSZ];
  266. if (inet_pton (AF_INET6, key[i], &addr) > 0)
  267. host = gethostbyaddr (addr, IN6ADDRSZ, AF_INET6);
  268. else if (inet_pton (AF_INET, key[i], &addr) > 0)
  269. host = gethostbyaddr (addr, INADDRSZ, AF_INET);
  270. else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
  271. host = gethostbyname2 (key[i], AF_INET);
  272. if (host == NULL)
  273. result = 2;
  274. else
  275. print_hosts (host);
  276. }
  277. return result;
  278. }
  279. /* This is for hosts, but using getaddrinfo */
  280. static int
  281. ahosts_keys_int (int af, int xflags, int number, char *key[])
  282. {
  283. int result = 0;
  284. int i;
  285. struct hostent *host;
  286. if (number == 0)
  287. {
  288. sethostent (0);
  289. while ((host = gethostent ()) != NULL)
  290. print_hosts (host);
  291. endhostent ();
  292. return result;
  293. }
  294. struct addrinfo hint;
  295. memset (&hint, '\0', sizeof (hint));
  296. hint.ai_flags = (AI_V4MAPPED | addrconfig_flags | AI_CANONNAME
  297. | idn_flags | xflags);
  298. hint.ai_family = af;
  299. for (i = 0; i < number; ++i)
  300. {
  301. struct addrinfo *res;
  302. if (getaddrinfo (key[i], NULL, &hint, &res) != 0)
  303. result = 2;
  304. else
  305. {
  306. struct addrinfo *runp = res;
  307. while (runp != NULL)
  308. {
  309. char sockbuf[20];
  310. const char *sockstr;
  311. if (runp->ai_socktype == SOCK_STREAM)
  312. sockstr = "STREAM";
  313. else if (runp->ai_socktype == SOCK_DGRAM)
  314. sockstr = "DGRAM";
  315. else if (runp->ai_socktype == SOCK_RAW)
  316. sockstr = "RAW";
  317. #ifdef SOCK_SEQPACKET
  318. else if (runp->ai_socktype == SOCK_SEQPACKET)
  319. sockstr = "SEQPACKET";
  320. #endif
  321. #ifdef SOCK_RDM
  322. else if (runp->ai_socktype == SOCK_RDM)
  323. sockstr = "RDM";
  324. #endif
  325. #ifdef SOCK_DCCP
  326. else if (runp->ai_socktype == SOCK_DCCP)
  327. sockstr = "DCCP";
  328. #endif
  329. #ifdef SOCK_PACKET
  330. else if (runp->ai_socktype == SOCK_PACKET)
  331. sockstr = "PACKET";
  332. #endif
  333. else
  334. {
  335. snprintf (sockbuf, sizeof (sockbuf), "%d",
  336. runp->ai_socktype);
  337. sockstr = sockbuf;
  338. }
  339. /* Three digits per byte, plus '%' and null terminator. */
  340. char scope[3 * sizeof (uint32_t) + 2];
  341. struct sockaddr_in6 *addr6
  342. = (struct sockaddr_in6 *) runp->ai_addr;
  343. if (runp->ai_family != AF_INET6 || addr6->sin6_scope_id == 0)
  344. /* No scope ID present. */
  345. scope[0] = '\0';
  346. else
  347. snprintf (scope, sizeof (scope), "%%%" PRIu32,
  348. addr6->sin6_scope_id);
  349. char buf[INET6_ADDRSTRLEN];
  350. if (inet_ntop (runp->ai_family,
  351. runp->ai_family == AF_INET
  352. ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr
  353. : &addr6->sin6_addr,
  354. buf, sizeof (buf)) == NULL)
  355. {
  356. strcpy (buf, "<invalid>");
  357. scope[0] = '\0';
  358. }
  359. int pad = 15 - strlen (buf) - strlen (scope);
  360. if (pad < 0)
  361. pad = 0;
  362. printf ("%s%-*s %-6s %s\n",
  363. buf, pad, scope, sockstr, runp->ai_canonname ?: "");
  364. runp = runp->ai_next;
  365. }
  366. freeaddrinfo (res);
  367. }
  368. }
  369. return result;
  370. }
  371. static int
  372. ahosts_keys (int number, char *key[])
  373. {
  374. return ahosts_keys_int (AF_UNSPEC, 0, number, key);
  375. }
  376. static int
  377. ahostsv4_keys (int number, char *key[])
  378. {
  379. return ahosts_keys_int (AF_INET, 0, number, key);
  380. }
  381. static int
  382. ahostsv6_keys (int number, char *key[])
  383. {
  384. return ahosts_keys_int (AF_INET6, AI_V4MAPPED, number, key);
  385. }
  386. /* This is for netgroup */
  387. static int
  388. netgroup_keys (int number, char *key[])
  389. {
  390. int result = 0;
  391. if (number == 0)
  392. {
  393. fprintf (stderr, _("Enumeration not supported on %s\n"), "netgroup");
  394. return 3;
  395. }
  396. if (number == 4)
  397. {
  398. char *host = strcmp (key[1], "*") == 0 ? NULL : key[1];
  399. char *user = strcmp (key[2], "*") == 0 ? NULL : key[2];
  400. char *domain = strcmp (key[3], "*") == 0 ? NULL : key[3];
  401. printf ("%-21s (%s,%s,%s) = %d\n",
  402. key[0], host ?: "", user ?: "", domain ?: "",
  403. innetgr (key[0], host, user, domain));
  404. }
  405. else if (number == 1)
  406. {
  407. if (!setnetgrent (key[0]))
  408. result = 2;
  409. else
  410. {
  411. char *p[3];
  412. printf ("%-21s", key[0]);
  413. while (getnetgrent (p, p + 1, p + 2))
  414. printf (" (%s,%s,%s)", p[0] ?: " ", p[1] ?: "", p[2] ?: "");
  415. putchar_unlocked ('\n');
  416. }
  417. }
  418. endnetgrent ();
  419. return result;
  420. }
  421. #define DYNARRAY_STRUCT gid_list
  422. #define DYNARRAY_ELEMENT gid_t
  423. #define DYNARRAY_PREFIX gid_list_
  424. #define DYNARRAY_INITIAL_SIZE 10
  425. #include <malloc/dynarray-skeleton.c>
  426. /* This is for initgroups */
  427. static int
  428. initgroups_keys (int number, char *key[])
  429. {
  430. if (number == 0)
  431. {
  432. fprintf (stderr, _("Enumeration not supported on %s\n"), "initgroups");
  433. return 3;
  434. }
  435. struct gid_list list;
  436. gid_list_init (&list);
  437. if (!gid_list_resize (&list, 10))
  438. {
  439. fprintf (stderr, _("Could not allocate group list: %m\n"));
  440. return 3;
  441. }
  442. for (int i = 0; i < number; ++i)
  443. {
  444. int no = gid_list_size (&list);
  445. int n;
  446. while ((n = getgrouplist (key[i], -1, gid_list_begin (&list), &no)) == -1
  447. && no > gid_list_size (&list))
  448. {
  449. if (!gid_list_resize (&list, no))
  450. {
  451. fprintf (stderr, _("Could not allocate group list: %m\n"));
  452. return 3;
  453. }
  454. }
  455. if (n == -1)
  456. {
  457. gid_list_free (&list);
  458. return 1;
  459. }
  460. const gid_t *grps = gid_list_begin (&list);
  461. printf ("%-21s", key[i]);
  462. for (int j = 0; j < n; ++j)
  463. if (grps[j] != -1)
  464. printf (" %ld", (long int) grps[j]);
  465. putchar_unlocked ('\n');
  466. }
  467. gid_list_free (&list);
  468. return 0;
  469. }
  470. /* This is for networks */
  471. static void
  472. print_networks (struct netent *net)
  473. {
  474. unsigned int i;
  475. struct in_addr ip;
  476. ip.s_addr = htonl (net->n_net);
  477. printf ("%-21s %s", net->n_name, inet_ntoa (ip));
  478. i = 0;
  479. while (net->n_aliases[i] != NULL)
  480. {
  481. putchar_unlocked (' ');
  482. fputs_unlocked (net->n_aliases[i], stdout);
  483. ++i;
  484. }
  485. putchar_unlocked ('\n');
  486. }
  487. static int
  488. networks_keys (int number, char *key[])
  489. {
  490. int result = 0;
  491. int i;
  492. struct netent *net;
  493. if (number == 0)
  494. {
  495. setnetent (0);
  496. while ((net = getnetent ()) != NULL)
  497. print_networks (net);
  498. endnetent ();
  499. return result;
  500. }
  501. for (i = 0; i < number; ++i)
  502. {
  503. if (isdigit (key[i][0]))
  504. net = getnetbyaddr (ntohl (inet_addr (key[i])), AF_UNSPEC);
  505. else
  506. net = getnetbyname (key[i]);
  507. if (net == NULL)
  508. result = 2;
  509. else
  510. print_networks (net);
  511. }
  512. return result;
  513. }
  514. /* Now is all for passwd */
  515. static void
  516. print_passwd (struct passwd *pwd)
  517. {
  518. if (putpwent (pwd, stdout) != 0)
  519. fprintf (stderr, "error writing passwd entry: %m\n");
  520. }
  521. static int
  522. passwd_keys (int number, char *key[])
  523. {
  524. int result = 0;
  525. int i;
  526. struct passwd *pwd;
  527. if (number == 0)
  528. {
  529. setpwent ();
  530. while ((pwd = getpwent ()) != NULL)
  531. print_passwd (pwd);
  532. endpwent ();
  533. return result;
  534. }
  535. for (i = 0; i < number; ++i)
  536. {
  537. errno = 0;
  538. char *ep;
  539. uid_t arg_uid = strtoul(key[i], &ep, 10);
  540. if (errno != EINVAL && *key[i] != '\0' && *ep == '\0')
  541. /* Valid numeric uid. */
  542. pwd = getpwuid (arg_uid);
  543. else
  544. pwd = getpwnam (key[i]);
  545. if (pwd == NULL)
  546. result = 2;
  547. else
  548. print_passwd (pwd);
  549. }
  550. return result;
  551. }
  552. /* This is for protocols */
  553. static void
  554. print_protocols (struct protoent *proto)
  555. {
  556. unsigned int i;
  557. printf ("%-21s %d", proto->p_name, proto->p_proto);
  558. i = 0;
  559. while (proto->p_aliases[i] != NULL)
  560. {
  561. putchar_unlocked (' ');
  562. fputs_unlocked (proto->p_aliases[i], stdout);
  563. ++i;
  564. }
  565. putchar_unlocked ('\n');
  566. }
  567. static int
  568. protocols_keys (int number, char *key[])
  569. {
  570. int result = 0;
  571. int i;
  572. struct protoent *proto;
  573. if (number == 0)
  574. {
  575. setprotoent (0);
  576. while ((proto = getprotoent ()) != NULL)
  577. print_protocols (proto);
  578. endprotoent ();
  579. return result;
  580. }
  581. for (i = 0; i < number; ++i)
  582. {
  583. if (isdigit (key[i][0]))
  584. proto = getprotobynumber (atol (key[i]));
  585. else
  586. proto = getprotobyname (key[i]);
  587. if (proto == NULL)
  588. result = 2;
  589. else
  590. print_protocols (proto);
  591. }
  592. return result;
  593. }
  594. #if HAVE_SUNRPC
  595. /* Now is all for rpc */
  596. static void
  597. print_rpc (struct rpcent *rpc)
  598. {
  599. int i;
  600. printf ("%-15s %d%s",
  601. rpc->r_name, rpc->r_number, rpc->r_aliases[0] ? " " : "");
  602. for (i = 0; rpc->r_aliases[i]; ++i)
  603. printf (" %s", rpc->r_aliases[i]);
  604. putchar_unlocked ('\n');
  605. }
  606. static int
  607. rpc_keys (int number, char *key[])
  608. {
  609. int result = 0;
  610. int i;
  611. struct rpcent *rpc;
  612. if (number == 0)
  613. {
  614. setrpcent (0);
  615. while ((rpc = getrpcent ()) != NULL)
  616. print_rpc (rpc);
  617. endrpcent ();
  618. return result;
  619. }
  620. for (i = 0; i < number; ++i)
  621. {
  622. if (isdigit (key[i][0]))
  623. rpc = getrpcbynumber (atol (key[i]));
  624. else
  625. rpc = getrpcbyname (key[i]);
  626. if (rpc == NULL)
  627. result = 2;
  628. else
  629. print_rpc (rpc);
  630. }
  631. return result;
  632. }
  633. #endif
  634. /* for services */
  635. static void
  636. print_services (struct servent *serv)
  637. {
  638. unsigned int i;
  639. printf ("%-21s %d/%s", serv->s_name, ntohs (serv->s_port), serv->s_proto);
  640. i = 0;
  641. while (serv->s_aliases[i] != NULL)
  642. {
  643. putchar_unlocked (' ');
  644. fputs_unlocked (serv->s_aliases[i], stdout);
  645. ++i;
  646. }
  647. putchar_unlocked ('\n');
  648. }
  649. static int
  650. services_keys (int number, char *key[])
  651. {
  652. int result = 0;
  653. int i;
  654. struct servent *serv;
  655. if (!number)
  656. {
  657. setservent (0);
  658. while ((serv = getservent ()) != NULL)
  659. print_services (serv);
  660. endservent ();
  661. return result;
  662. }
  663. for (i = 0; i < number; ++i)
  664. {
  665. struct servent *serv;
  666. char *proto = strchr (key[i], '/');
  667. if (proto != NULL)
  668. *proto++ = '\0';
  669. char *endptr;
  670. long port = strtol (key[i], &endptr, 10);
  671. if (isdigit (key[i][0]) && *endptr == '\0'
  672. && 0 <= port && port <= 65535)
  673. serv = getservbyport (htons (port), proto);
  674. else
  675. serv = getservbyname (key[i], proto);
  676. if (serv == NULL)
  677. result = 2;
  678. else
  679. print_services (serv);
  680. }
  681. return result;
  682. }
  683. /* This is for shadow */
  684. static void
  685. print_shadow (struct spwd *sp)
  686. {
  687. if (putspent (sp, stdout) != 0)
  688. fprintf (stderr, "error writing shadow entry: %m\n");
  689. }
  690. static int
  691. shadow_keys (int number, char *key[])
  692. {
  693. int result = 0;
  694. int i;
  695. if (number == 0)
  696. {
  697. struct spwd *sp;
  698. setspent ();
  699. while ((sp = getspent ()) != NULL)
  700. print_shadow (sp);
  701. endspent ();
  702. return result;
  703. }
  704. for (i = 0; i < number; ++i)
  705. {
  706. struct spwd *sp;
  707. sp = getspnam (key[i]);
  708. if (sp == NULL)
  709. result = 2;
  710. else
  711. print_shadow (sp);
  712. }
  713. return result;
  714. }
  715. struct
  716. {
  717. const char *name;
  718. int (*func) (int number, char *key[]);
  719. } databases[] =
  720. {
  721. #define D(name) { #name, name ## _keys },
  722. D(ahosts)
  723. D(ahostsv4)
  724. D(ahostsv6)
  725. D(aliases)
  726. D(ethers)
  727. D(group)
  728. D(gshadow)
  729. D(hosts)
  730. D(initgroups)
  731. D(netgroup)
  732. D(networks)
  733. D(passwd)
  734. D(protocols)
  735. #if HAVE_SUNRPC
  736. D(rpc)
  737. #endif
  738. D(services)
  739. D(shadow)
  740. #undef D
  741. { NULL, NULL }
  742. };
  743. /* Handle arguments found by argp. */
  744. static error_t
  745. parse_option (int key, char *arg, struct argp_state *state)
  746. {
  747. char *endp;
  748. switch (key)
  749. {
  750. case 's':
  751. endp = strchr (arg, ':');
  752. if (endp == NULL)
  753. /* No specific database, change them all. */
  754. for (int i = 0; databases[i].name != NULL; ++i)
  755. __nss_configure_lookup (databases[i].name, arg);
  756. else
  757. {
  758. int i;
  759. for (i = 0; databases[i].name != NULL; ++i)
  760. if (strncmp (databases[i].name, arg, endp - arg) == 0)
  761. {
  762. __nss_configure_lookup (databases[i].name, endp + 1);
  763. break;
  764. }
  765. if (databases[i].name == NULL)
  766. error (EXIT_FAILURE, 0, gettext ("Unknown database name"));
  767. }
  768. break;
  769. case 'i':
  770. idn_flags = 0;
  771. break;
  772. case 'A':
  773. addrconfig_flags = 0;
  774. break;
  775. default:
  776. return ARGP_ERR_UNKNOWN;
  777. }
  778. return 0;
  779. }
  780. static char *
  781. more_help (int key, const char *text, void *input)
  782. {
  783. switch (key)
  784. {
  785. size_t len;
  786. char *doc;
  787. FILE *fp;
  788. case ARGP_KEY_HELP_EXTRA:
  789. /* We print some extra information. */
  790. fp = open_memstream (&doc, &len);
  791. if (fp != NULL)
  792. {
  793. fputs_unlocked (_("Supported databases:\n"), fp);
  794. for (int i = 0, col = 0; databases[i].name != NULL; ++i)
  795. {
  796. len = strlen (databases[i].name);
  797. if (i != 0)
  798. {
  799. if (col + len > 72)
  800. {
  801. col = 0;
  802. fputc_unlocked ('\n', fp);
  803. }
  804. else
  805. fputc_unlocked (' ', fp);
  806. }
  807. fputs_unlocked (databases[i].name, fp);
  808. col += len + 1;
  809. }
  810. fputs ("\n\n", fp);
  811. fprintf (fp, gettext ("\
  812. For bug reporting instructions, please see:\n\
  813. %s.\n"), REPORT_BUGS_TO);
  814. if (fclose (fp) == 0)
  815. return doc;
  816. }
  817. break;
  818. default:
  819. break;
  820. }
  821. return (char *) text;
  822. }
  823. /* the main function */
  824. int
  825. main (int argc, char *argv[])
  826. {
  827. /* Debugging support. */
  828. mtrace ();
  829. /* Set locale via LC_ALL. */
  830. setlocale (LC_ALL, "");
  831. /* Set the text message domain. */
  832. textdomain (PACKAGE);
  833. /* Parse and process arguments. */
  834. int remaining;
  835. argp_parse (&argp, argc, argv, 0, &remaining, NULL);
  836. if ((argc - remaining) < 1)
  837. {
  838. error (0, 0, gettext ("wrong number of arguments"));
  839. argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
  840. return 1;
  841. }
  842. for (int i = 0; databases[i].name; ++i)
  843. if (argv[remaining][0] == databases[i].name[0]
  844. && !strcmp (argv[remaining], databases[i].name))
  845. return databases[i].func (argc - remaining - 1, &argv[remaining + 1]);
  846. fprintf (stderr, _("Unknown database: %s\n"), argv[remaining]);
  847. argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
  848. return 1;
  849. }