OpenSDE Packages Database (without history before r20070)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

527 lines
12 KiB

  1. /*
  2. * --- SDE-COPYRIGHT-NOTE-BEGIN ---
  3. * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
  4. *
  5. * Filename: package/.../musl/getent.c
  6. * Copyright (C) 2020 The OpenSDE Project
  7. *
  8. * More information can be found in the files COPYING and README.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; version 2 of the License. A copy of the
  13. * GNU General Public License can be found in the file COPYING.
  14. * --- SDE-COPYRIGHT-NOTE-END ---
  15. */
  16. /*-
  17. * Copyright (c) 2004-2006 The NetBSD Foundation, Inc.
  18. * All rights reserved.
  19. *
  20. * This code is derived from software contributed to The NetBSD Foundation
  21. * by Luke Mewburn.
  22. * Timo Teräs cleaned up the code for use in Alpine Linux with musl libc.
  23. *
  24. * Redistribution and use in source and binary forms, with or without
  25. * modification, are permitted provided that the following conditions
  26. * are met:
  27. * 1. Redistributions of source code must retain the above copyright
  28. * notice, this list of conditions and the following disclaimer.
  29. * 2. Redistributions in binary form must reproduce the above copyright
  30. * notice, this list of conditions and the following disclaimer in the
  31. * documentation and/or other materials provided with the distribution.
  32. *
  33. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  34. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  35. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  36. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  37. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  38. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  39. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  40. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  41. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  43. * POSSIBILITY OF SUCH DAMAGE.
  44. */
  45. #include <sys/socket.h>
  46. #include <sys/param.h>
  47. #include <ctype.h>
  48. #include <errno.h>
  49. #include <limits.h>
  50. #include <netdb.h>
  51. #include <pwd.h>
  52. #include <grp.h>
  53. #include <stdio.h>
  54. #include <stdarg.h>
  55. #include <stdbool.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include <unistd.h>
  59. #include <paths.h>
  60. #include <err.h>
  61. #include <arpa/inet.h>
  62. #include <arpa/nameser.h>
  63. #include <net/if.h>
  64. #include <net/ethernet.h>
  65. #include <netinet/ether.h>
  66. #include <netinet/in.h>
  67. enum {
  68. RV_OK = 0,
  69. RV_USAGE = 1,
  70. RV_NOTFOUND = 2,
  71. RV_NOENUM = 3
  72. };
  73. static int usage(const char *);
  74. static int parsenum(const char *word, unsigned long *result)
  75. {
  76. unsigned long num;
  77. char *ep;
  78. if (!isdigit((unsigned char)word[0]))
  79. return 0;
  80. errno = 0;
  81. num = strtoul(word, &ep, 10);
  82. if (num == ULONG_MAX && errno == ERANGE)
  83. return 0;
  84. if (*ep != '\0')
  85. return 0;
  86. *result = num;
  87. return 1;
  88. }
  89. /*
  90. * printfmtstrings --
  91. * vprintf(format, ...),
  92. * then the aliases (beginning with prefix, separated by sep),
  93. * then a newline
  94. */
  95. __attribute__ ((format (printf, 4, 5)))
  96. static void printfmtstrings(char *strings[], const char *prefix, const char *sep,
  97. const char *fmt, ...)
  98. {
  99. va_list ap;
  100. const char *curpref;
  101. size_t i;
  102. va_start(ap, fmt);
  103. (void)vprintf(fmt, ap);
  104. va_end(ap);
  105. curpref = prefix;
  106. for (i = 0; strings[i] != NULL; i++) {
  107. (void)printf("%s%s", curpref, strings[i]);
  108. curpref = sep;
  109. }
  110. (void)printf("\n");
  111. }
  112. static int ethers(int argc, char *argv[])
  113. {
  114. char hostname[MAXHOSTNAMELEN + 1], *hp;
  115. struct ether_addr ea, *eap;
  116. int i, rv;
  117. if (argc == 2) {
  118. warnx("Enumeration not supported on ethers");
  119. return RV_NOENUM;
  120. }
  121. rv = RV_OK;
  122. for (i = 2; i < argc; i++) {
  123. if ((eap = ether_aton(argv[i])) == NULL) {
  124. eap = &ea;
  125. hp = argv[i];
  126. if (ether_hostton(hp, eap) != 0) {
  127. rv = RV_NOTFOUND;
  128. break;
  129. }
  130. } else {
  131. hp = hostname;
  132. if (ether_ntohost(hp, eap) != 0) {
  133. rv = RV_NOTFOUND;
  134. break;
  135. }
  136. }
  137. (void)printf("%-17s %s\n", ether_ntoa(eap), hp);
  138. }
  139. return rv;
  140. }
  141. static void groupprint(const struct group *gr)
  142. {
  143. printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u",
  144. gr->gr_name, gr->gr_passwd, gr->gr_gid);
  145. }
  146. static int group(int argc, char *argv[])
  147. {
  148. struct group *gr;
  149. unsigned long id;
  150. int i, rv;
  151. rv = RV_OK;
  152. if (argc == 2) {
  153. while ((gr = getgrent()) != NULL)
  154. groupprint(gr);
  155. } else {
  156. for (i = 2; i < argc; i++) {
  157. if (parsenum(argv[i], &id))
  158. gr = getgrgid((gid_t)id);
  159. else
  160. gr = getgrnam(argv[i]);
  161. if (gr == NULL) {
  162. rv = RV_NOTFOUND;
  163. break;
  164. }
  165. groupprint(gr);
  166. }
  167. }
  168. endgrent();
  169. return rv;
  170. }
  171. static void hostsprint(const struct hostent *he)
  172. {
  173. char buf[INET6_ADDRSTRLEN];
  174. if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
  175. (void)strlcpy(buf, "# unknown", sizeof(buf));
  176. printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name);
  177. }
  178. static int hosts(int argc, char *argv[])
  179. {
  180. struct hostent *he;
  181. char addr[IN6ADDRSZ];
  182. int i, rv;
  183. sethostent(1);
  184. rv = RV_OK;
  185. if (argc == 2) {
  186. while ((he = gethostent()) != NULL)
  187. hostsprint(he);
  188. } else {
  189. for (i = 2; i < argc; i++) {
  190. if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
  191. he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
  192. else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
  193. he = gethostbyaddr(addr, INADDRSZ, AF_INET);
  194. else if ((he = gethostbyname2(argv[i], AF_INET6)) == NULL)
  195. he = gethostbyname2(argv[i], AF_INET);
  196. if (he == NULL) {
  197. rv = RV_NOTFOUND;
  198. break;
  199. }
  200. hostsprint(he);
  201. }
  202. }
  203. endhostent();
  204. return rv;
  205. }
  206. static int ahosts_ex(int family, int flags, int argc, char *argv[])
  207. {
  208. static const char *socktypes[] = {
  209. [SOCK_STREAM] = "STREAM",
  210. [SOCK_DGRAM] = "DGRAM",
  211. [SOCK_RAW] = "RAW",
  212. [SOCK_RDM] = "RDM",
  213. [SOCK_SEQPACKET] = "SEQPACKET",
  214. [SOCK_DCCP] = "DCCP",
  215. [SOCK_PACKET] = "PACKET",
  216. };
  217. const char *sockstr;
  218. char sockbuf[16], buf[INET6_ADDRSTRLEN];
  219. struct addrinfo *res, *r, hint;
  220. void *addr;
  221. int i;
  222. if (argc == 2)
  223. return hosts(argc, argv);
  224. hint = (struct addrinfo) {
  225. .ai_family = family,
  226. .ai_flags = AI_ADDRCONFIG | AI_CANONNAME | flags,
  227. };
  228. for (i = 2; i < argc; i++) {
  229. if (getaddrinfo(argv[i], 0, &hint, &res) != 0)
  230. return RV_NOTFOUND;
  231. for (r = res; r; r = r->ai_next) {
  232. sockstr = NULL;
  233. if (r->ai_socktype >= 0 && r->ai_socktype < sizeof(socktypes)/sizeof(socktypes[0]))
  234. sockstr = socktypes[r->ai_socktype];
  235. if (!sockstr) {
  236. sprintf(buf, "%d", r->ai_socktype);
  237. sockstr = sockbuf;
  238. }
  239. switch (r->ai_family) {
  240. case AF_INET:
  241. addr = &((struct sockaddr_in*) r->ai_addr)->sin_addr;
  242. break;
  243. case AF_INET6:
  244. addr = &((struct sockaddr_in6*) r->ai_addr)->sin6_addr;
  245. break;
  246. default:
  247. continue;
  248. }
  249. if (inet_ntop(r->ai_family, addr, buf, sizeof(buf)) == NULL)
  250. (void)strlcpy(buf, "# unknown", sizeof(buf));
  251. printf("%-15s %-6s %s\n", buf, sockstr, r->ai_canonname ?: "");
  252. }
  253. }
  254. return RV_OK;
  255. }
  256. static int ahosts(int argc, char *argv[])
  257. {
  258. return ahosts_ex(AF_UNSPEC, 0, argc, argv);
  259. }
  260. static int ahostsv4(int argc, char *argv[])
  261. {
  262. return ahosts_ex(AF_INET, 0, argc, argv);
  263. }
  264. static int ahostsv6(int argc, char *argv[])
  265. {
  266. return ahosts_ex(AF_INET6, AI_V4MAPPED, argc, argv);
  267. }
  268. static void networksprint(const struct netent *ne)
  269. {
  270. char buf[INET6_ADDRSTRLEN];
  271. struct in_addr ianet;
  272. ianet = inet_makeaddr(ne->n_net, 0);
  273. if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
  274. (void)strlcpy(buf, "# unknown", sizeof(buf));
  275. printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf);
  276. }
  277. static int networks(int argc, char *argv[])
  278. {
  279. struct netent *ne;
  280. in_addr_t net;
  281. int i, rv;
  282. setnetent(1);
  283. rv = RV_OK;
  284. if (argc == 2) {
  285. while ((ne = getnetent()) != NULL)
  286. networksprint(ne);
  287. } else {
  288. for (i = 2; i < argc; i++) {
  289. net = inet_network(argv[i]);
  290. if (net != INADDR_NONE)
  291. ne = getnetbyaddr(net, AF_INET);
  292. else
  293. ne = getnetbyname(argv[i]);
  294. if (ne != NULL) {
  295. rv = RV_NOTFOUND;
  296. break;
  297. }
  298. networksprint(ne);
  299. }
  300. }
  301. endnetent();
  302. return rv;
  303. }
  304. static void passwdprint(struct passwd *pw)
  305. {
  306. (void)printf("%s:%s:%u:%u:%s:%s:%s\n",
  307. pw->pw_name, pw->pw_passwd, pw->pw_uid,
  308. pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell);
  309. }
  310. static int passwd(int argc, char *argv[])
  311. {
  312. struct passwd *pw;
  313. unsigned long id;
  314. int i, rv;
  315. rv = RV_OK;
  316. if (argc == 2) {
  317. while ((pw = getpwent()) != NULL)
  318. passwdprint(pw);
  319. } else {
  320. for (i = 2; i < argc; i++) {
  321. if (parsenum(argv[i], &id))
  322. pw = getpwuid((uid_t)id);
  323. else
  324. pw = getpwnam(argv[i]);
  325. if (pw == NULL) {
  326. rv = RV_NOTFOUND;
  327. break;
  328. }
  329. passwdprint(pw);
  330. }
  331. }
  332. endpwent();
  333. return rv;
  334. }
  335. static void protocolsprint(struct protoent *pe)
  336. {
  337. printfmtstrings(pe->p_aliases, " ", " ",
  338. "%-16s %5d", pe->p_name, pe->p_proto);
  339. }
  340. static int protocols(int argc, char *argv[])
  341. {
  342. struct protoent *pe;
  343. unsigned long id;
  344. int i, rv;
  345. setprotoent(1);
  346. rv = RV_OK;
  347. if (argc == 2) {
  348. while ((pe = getprotoent()) != NULL)
  349. protocolsprint(pe);
  350. } else {
  351. for (i = 2; i < argc; i++) {
  352. if (parsenum(argv[i], &id))
  353. pe = getprotobynumber((int)id);
  354. else
  355. pe = getprotobyname(argv[i]);
  356. if (pe == NULL) {
  357. rv = RV_NOTFOUND;
  358. break;
  359. }
  360. protocolsprint(pe);
  361. }
  362. }
  363. endprotoent();
  364. return rv;
  365. }
  366. static void servicesprint(struct servent *se)
  367. {
  368. printfmtstrings(se->s_aliases, " ", " ",
  369. "%-16s %5d/%s",
  370. se->s_name, ntohs(se->s_port), se->s_proto);
  371. }
  372. static int services(int argc, char *argv[])
  373. {
  374. struct servent *se;
  375. unsigned long id;
  376. char *proto;
  377. int i, rv;
  378. setservent(1);
  379. rv = RV_OK;
  380. if (argc == 2) {
  381. while ((se = getservent()) != NULL)
  382. servicesprint(se);
  383. } else {
  384. for (i = 2; i < argc; i++) {
  385. proto = strchr(argv[i], '/');
  386. if (proto != NULL)
  387. *proto++ = '\0';
  388. if (parsenum(argv[i], &id))
  389. se = getservbyport(htons(id), proto);
  390. else
  391. se = getservbyname(argv[i], proto);
  392. if (se == NULL) {
  393. rv = RV_NOTFOUND;
  394. break;
  395. }
  396. servicesprint(se);
  397. }
  398. }
  399. endservent();
  400. return rv;
  401. }
  402. static int shells(int argc, char *argv[])
  403. {
  404. const char *sh;
  405. int i, rv;
  406. setusershell();
  407. rv = RV_OK;
  408. if (argc == 2) {
  409. while ((sh = getusershell()) != NULL)
  410. (void)printf("%s\n", sh);
  411. } else {
  412. for (i = 2; i < argc; i++) {
  413. setusershell();
  414. while ((sh = getusershell()) != NULL) {
  415. if (strcmp(sh, argv[i]) == 0) {
  416. (void)printf("%s\n", sh);
  417. break;
  418. }
  419. }
  420. if (sh == NULL) {
  421. rv = RV_NOTFOUND;
  422. break;
  423. }
  424. }
  425. }
  426. endusershell();
  427. return rv;
  428. }
  429. static struct getentdb {
  430. const char *name;
  431. int (*callback)(int, char *[]);
  432. } databases[] = {
  433. { "ethers", ethers, },
  434. { "group", group, },
  435. { "hosts", hosts, },
  436. { "ahosts", ahosts, },
  437. { "ahostsv4", ahostsv4, },
  438. { "ahostsv6", ahostsv6, },
  439. { "networks", networks, },
  440. { "passwd", passwd, },
  441. { "protocols", protocols, },
  442. { "services", services, },
  443. { "shells", shells, },
  444. { NULL, NULL, },
  445. };
  446. static int usage(const char *arg0)
  447. {
  448. struct getentdb *curdb;
  449. size_t i;
  450. (void)fprintf(stderr, "Usage: %s database [key ...]\n", arg0);
  451. (void)fprintf(stderr, "\tdatabase may be one of:");
  452. for (i = 0, curdb = databases; curdb->name != NULL; curdb++, i++) {
  453. if (i % 7 == 0)
  454. (void)fputs("\n\t\t", stderr);
  455. (void)fprintf(stderr, "%s%s", i % 7 == 0 ? "" : " ",
  456. curdb->name);
  457. }
  458. (void)fprintf(stderr, "\n");
  459. exit(RV_USAGE);
  460. /* NOTREACHED */
  461. }
  462. int
  463. main(int argc, char *argv[])
  464. {
  465. struct getentdb *curdb;
  466. if (argc < 2)
  467. usage(argv[0]);
  468. for (curdb = databases; curdb->name != NULL; curdb++)
  469. if (strcmp(curdb->name, argv[1]) == 0)
  470. return (*curdb->callback)(argc, argv);
  471. warn("Unknown database `%s'", argv[1]);
  472. usage(argv[0]);
  473. /* NOTREACHED */
  474. }