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.

466 lines
10 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) 2015 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. #if defined(__GNU_LIBRARY__)
  90. static inline size_t strlcpy(char *dest, const char *src, size_t size)
  91. {
  92. size_t ret = strlen(src);
  93. if (size) {
  94. size_t len = (ret >= size) ? size - 1 : ret;
  95. memcpy(dest, src, len);
  96. dest[len] = '\0';
  97. }
  98. return ret;
  99. }
  100. #endif
  101. /*
  102. * printfmtstrings --
  103. * vprintf(format, ...),
  104. * then the aliases (beginning with prefix, separated by sep),
  105. * then a newline
  106. */
  107. __attribute__ ((format (printf, 4, 5)))
  108. static void printfmtstrings(char *strings[], const char *prefix, const char *sep,
  109. const char *fmt, ...)
  110. {
  111. va_list ap;
  112. const char *curpref;
  113. size_t i;
  114. va_start(ap, fmt);
  115. (void)vprintf(fmt, ap);
  116. va_end(ap);
  117. curpref = prefix;
  118. for (i = 0; strings[i] != NULL; i++) {
  119. (void)printf("%s%s", curpref, strings[i]);
  120. curpref = sep;
  121. }
  122. (void)printf("\n");
  123. }
  124. static int ethers(int argc, char *argv[])
  125. {
  126. char hostname[MAXHOSTNAMELEN + 1], *hp;
  127. struct ether_addr ea, *eap;
  128. int i, rv;
  129. if (argc == 2) {
  130. warnx("Enumeration not supported on ethers");
  131. return RV_NOENUM;
  132. }
  133. rv = RV_OK;
  134. for (i = 2; i < argc; i++) {
  135. if ((eap = ether_aton(argv[i])) == NULL) {
  136. eap = &ea;
  137. hp = argv[i];
  138. if (ether_hostton(hp, eap) != 0) {
  139. rv = RV_NOTFOUND;
  140. break;
  141. }
  142. } else {
  143. hp = hostname;
  144. if (ether_ntohost(hp, eap) != 0) {
  145. rv = RV_NOTFOUND;
  146. break;
  147. }
  148. }
  149. (void)printf("%-17s %s\n", ether_ntoa(eap), hp);
  150. }
  151. return rv;
  152. }
  153. static void groupprint(const struct group *gr)
  154. {
  155. printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u",
  156. gr->gr_name, gr->gr_passwd, gr->gr_gid);
  157. }
  158. static int group(int argc, char *argv[])
  159. {
  160. struct group *gr;
  161. unsigned long id;
  162. int i, rv;
  163. rv = RV_OK;
  164. if (argc == 2) {
  165. while ((gr = getgrent()) != NULL)
  166. groupprint(gr);
  167. } else {
  168. for (i = 2; i < argc; i++) {
  169. if (parsenum(argv[i], &id))
  170. gr = getgrgid((gid_t)id);
  171. else
  172. gr = getgrnam(argv[i]);
  173. if (gr == NULL) {
  174. rv = RV_NOTFOUND;
  175. break;
  176. }
  177. groupprint(gr);
  178. }
  179. }
  180. endgrent();
  181. return rv;
  182. }
  183. static void hostsprint(const struct hostent *he)
  184. {
  185. char buf[INET6_ADDRSTRLEN];
  186. if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
  187. (void)strlcpy(buf, "# unknown", sizeof(buf));
  188. printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name);
  189. }
  190. static int hosts(int argc, char *argv[])
  191. {
  192. struct hostent *he;
  193. char addr[IN6ADDRSZ];
  194. int i, rv;
  195. sethostent(1);
  196. rv = RV_OK;
  197. if (argc == 2) {
  198. while ((he = gethostent()) != NULL)
  199. hostsprint(he);
  200. } else {
  201. for (i = 2; i < argc; i++) {
  202. if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0)
  203. he = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
  204. else if (inet_pton(AF_INET, argv[i], (void *)addr) > 0)
  205. he = gethostbyaddr(addr, INADDRSZ, AF_INET);
  206. else
  207. he = gethostbyname(argv[i]);
  208. if (he == NULL) {
  209. rv = RV_NOTFOUND;
  210. break;
  211. }
  212. hostsprint(he);
  213. }
  214. }
  215. endhostent();
  216. return rv;
  217. }
  218. static void networksprint(const struct netent *ne)
  219. {
  220. char buf[INET6_ADDRSTRLEN];
  221. struct in_addr ianet;
  222. ianet = inet_makeaddr(ne->n_net, 0);
  223. if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
  224. (void)strlcpy(buf, "# unknown", sizeof(buf));
  225. printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf);
  226. }
  227. static int networks(int argc, char *argv[])
  228. {
  229. struct netent *ne;
  230. in_addr_t net;
  231. int i, rv;
  232. setnetent(1);
  233. rv = RV_OK;
  234. if (argc == 2) {
  235. while ((ne = getnetent()) != NULL)
  236. networksprint(ne);
  237. } else {
  238. for (i = 2; i < argc; i++) {
  239. net = inet_network(argv[i]);
  240. if (net != INADDR_NONE)
  241. ne = getnetbyaddr(net, AF_INET);
  242. else
  243. ne = getnetbyname(argv[i]);
  244. if (ne != NULL) {
  245. rv = RV_NOTFOUND;
  246. break;
  247. }
  248. networksprint(ne);
  249. }
  250. }
  251. endnetent();
  252. return rv;
  253. }
  254. static void passwdprint(struct passwd *pw)
  255. {
  256. (void)printf("%s:%s:%u:%u:%s:%s:%s\n",
  257. pw->pw_name, pw->pw_passwd, pw->pw_uid,
  258. pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell);
  259. }
  260. static int passwd(int argc, char *argv[])
  261. {
  262. struct passwd *pw;
  263. unsigned long id;
  264. int i, rv;
  265. rv = RV_OK;
  266. if (argc == 2) {
  267. while ((pw = getpwent()) != NULL)
  268. passwdprint(pw);
  269. } else {
  270. for (i = 2; i < argc; i++) {
  271. if (parsenum(argv[i], &id))
  272. pw = getpwuid((uid_t)id);
  273. else
  274. pw = getpwnam(argv[i]);
  275. if (pw == NULL) {
  276. rv = RV_NOTFOUND;
  277. break;
  278. }
  279. passwdprint(pw);
  280. }
  281. }
  282. endpwent();
  283. return rv;
  284. }
  285. static void protocolsprint(struct protoent *pe)
  286. {
  287. printfmtstrings(pe->p_aliases, " ", " ",
  288. "%-16s %5d", pe->p_name, pe->p_proto);
  289. }
  290. static int protocols(int argc, char *argv[])
  291. {
  292. struct protoent *pe;
  293. unsigned long id;
  294. int i, rv;
  295. setprotoent(1);
  296. rv = RV_OK;
  297. if (argc == 2) {
  298. while ((pe = getprotoent()) != NULL)
  299. protocolsprint(pe);
  300. } else {
  301. for (i = 2; i < argc; i++) {
  302. if (parsenum(argv[i], &id))
  303. pe = getprotobynumber((int)id);
  304. else
  305. pe = getprotobyname(argv[i]);
  306. if (pe == NULL) {
  307. rv = RV_NOTFOUND;
  308. break;
  309. }
  310. protocolsprint(pe);
  311. }
  312. }
  313. endprotoent();
  314. return rv;
  315. }
  316. static void servicesprint(struct servent *se)
  317. {
  318. printfmtstrings(se->s_aliases, " ", " ",
  319. "%-16s %5d/%s",
  320. se->s_name, ntohs(se->s_port), se->s_proto);
  321. }
  322. static int services(int argc, char *argv[])
  323. {
  324. struct servent *se;
  325. unsigned long id;
  326. char *proto;
  327. int i, rv;
  328. setservent(1);
  329. rv = RV_OK;
  330. if (argc == 2) {
  331. while ((se = getservent()) != NULL)
  332. servicesprint(se);
  333. } else {
  334. for (i = 2; i < argc; i++) {
  335. proto = strchr(argv[i], '/');
  336. if (proto != NULL)
  337. *proto++ = '\0';
  338. if (parsenum(argv[i], &id))
  339. se = getservbyport(htons(id), proto);
  340. else
  341. se = getservbyname(argv[i], proto);
  342. if (se == NULL) {
  343. rv = RV_NOTFOUND;
  344. break;
  345. }
  346. servicesprint(se);
  347. }
  348. }
  349. endservent();
  350. return rv;
  351. }
  352. static int shells(int argc, char *argv[])
  353. {
  354. const char *sh;
  355. int i, rv;
  356. setusershell();
  357. rv = RV_OK;
  358. if (argc == 2) {
  359. while ((sh = getusershell()) != NULL)
  360. (void)printf("%s\n", sh);
  361. } else {
  362. for (i = 2; i < argc; i++) {
  363. setusershell();
  364. while ((sh = getusershell()) != NULL) {
  365. if (strcmp(sh, argv[i]) == 0) {
  366. (void)printf("%s\n", sh);
  367. break;
  368. }
  369. }
  370. if (sh == NULL) {
  371. rv = RV_NOTFOUND;
  372. break;
  373. }
  374. }
  375. }
  376. endusershell();
  377. return rv;
  378. }
  379. static struct getentdb {
  380. const char *name;
  381. int (*callback)(int, char *[]);
  382. } databases[] = {
  383. { "ethers", ethers, },
  384. { "group", group, },
  385. { "hosts", hosts, },
  386. { "networks", networks, },
  387. { "passwd", passwd, },
  388. { "protocols", protocols, },
  389. { "services", services, },
  390. { "shells", shells, },
  391. { NULL, NULL, },
  392. };
  393. static int usage(const char *arg0)
  394. {
  395. struct getentdb *curdb;
  396. size_t i;
  397. (void)fprintf(stderr, "Usage: %s database [key ...]\n", arg0);
  398. (void)fprintf(stderr, "\tdatabase may be one of:");
  399. for (i = 0, curdb = databases; curdb->name != NULL; curdb++, i++) {
  400. if (i % 7 == 0)
  401. (void)fputs("\n\t\t", stderr);
  402. (void)fprintf(stderr, "%s%s", i % 7 == 0 ? "" : " ",
  403. curdb->name);
  404. }
  405. (void)fprintf(stderr, "\n");
  406. exit(RV_USAGE);
  407. /* NOTREACHED */
  408. }
  409. int
  410. main(int argc, char *argv[])
  411. {
  412. struct getentdb *curdb;
  413. if (argc < 2)
  414. usage(argv[0]);
  415. for (curdb = databases; curdb->name != NULL; curdb++)
  416. if (strcmp(curdb->name, argv[1]) == 0)
  417. return (*curdb->callback)(argc, argv);
  418. warn("Unknown database `%s'", argv[1]);
  419. usage(argv[0]);
  420. /* NOTREACHED */
  421. }