2 * Copyright (c) 2004-2006 The NetBSD Foundation, Inc.
5 * This code is derived from software contributed to The NetBSD Foundation
7 * Timo Teräs cleaned up the code for use in Alpine Linux with musl libc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/socket.h>
32 #include <sys/param.h>
48 #include <arpa/inet.h>
49 #include <arpa/nameser.h>
52 #include <net/ethernet.h>
53 #include <netinet/ether.h>
54 #include <netinet/in.h>
63 static int usage(const char *);
65 static int parsenum(const char *word
, unsigned long *result
)
70 if (!isdigit((unsigned char)word
[0]))
73 num
= strtoul(word
, &ep
, 10);
74 if (num
== ULONG_MAX
&& errno
== ERANGE
)
84 * vprintf(format, ...),
85 * then the aliases (beginning with prefix, separated by sep),
88 __attribute__ ((format (printf
, 4, 5)))
89 static void printfmtstrings(char *strings
[], const char *prefix
, const char *sep
,
97 (void)vprintf(fmt
, ap
);
101 for (i
= 0; strings
[i
] != NULL
; i
++) {
102 (void)printf("%s%s", curpref
, strings
[i
]);
108 static int ethers(int argc
, char *argv
[])
110 char hostname
[MAXHOSTNAMELEN
+ 1], *hp
;
111 struct ether_addr ea
, *eap
;
115 warnx("Enumeration not supported on ethers");
120 for (i
= 2; i
< argc
; i
++) {
121 if ((eap
= ether_aton(argv
[i
])) == NULL
) {
124 if (ether_hostton(hp
, eap
) != 0) {
130 if (ether_ntohost(hp
, eap
) != 0) {
135 (void)printf("%-17s %s\n", ether_ntoa(eap
), hp
);
140 static void groupprint(const struct group
*gr
)
142 printfmtstrings(gr
->gr_mem
, ":", ",", "%s:%s:%u",
143 gr
->gr_name
, gr
->gr_passwd
, gr
->gr_gid
);
146 static int group(int argc
, char *argv
[])
154 while ((gr
= getgrent()) != NULL
)
157 for (i
= 2; i
< argc
; i
++) {
158 if (parsenum(argv
[i
], &id
))
159 gr
= getgrgid((gid_t
)id
);
161 gr
= getgrnam(argv
[i
]);
173 static void hostsprint(const struct hostent
*he
)
175 char buf
[INET6_ADDRSTRLEN
];
177 if (inet_ntop(he
->h_addrtype
, he
->h_addr
, buf
, sizeof(buf
)) == NULL
)
178 (void)strlcpy(buf
, "# unknown", sizeof(buf
));
179 printfmtstrings(he
->h_aliases
, " ", " ", "%-16s %s", buf
, he
->h_name
);
182 static int hosts(int argc
, char *argv
[])
185 char addr
[IN6ADDRSZ
];
191 while ((he
= gethostent()) != NULL
)
194 for (i
= 2; i
< argc
; i
++) {
195 if (inet_pton(AF_INET6
, argv
[i
], (void *)addr
) > 0)
196 he
= gethostbyaddr(addr
, IN6ADDRSZ
, AF_INET6
);
197 else if (inet_pton(AF_INET
, argv
[i
], (void *)addr
) > 0)
198 he
= gethostbyaddr(addr
, INADDRSZ
, AF_INET
);
199 else if ((he
= gethostbyname2(argv
[i
], AF_INET6
)) == NULL
)
200 he
= gethostbyname2(argv
[i
], AF_INET
);
212 static int ahosts_ex(int family
, int flags
, int argc
, char *argv
[])
214 static const char *socktypes
[] = {
215 [SOCK_STREAM
] = "STREAM",
216 [SOCK_DGRAM
] = "DGRAM",
219 [SOCK_SEQPACKET
] = "SEQPACKET",
220 [SOCK_DCCP
] = "DCCP",
221 [SOCK_PACKET
] = "PACKET",
224 char sockbuf
[16], buf
[INET6_ADDRSTRLEN
];
225 struct addrinfo
*res
, *r
, hint
;
230 return hosts(argc
, argv
);
232 hint
= (struct addrinfo
) {
234 .ai_flags
= AI_ADDRCONFIG
| AI_CANONNAME
| flags
,
237 for (i
= 2; i
< argc
; i
++) {
238 if (getaddrinfo(argv
[i
], 0, &hint
, &res
) != 0)
241 for (r
= res
; r
; r
= r
->ai_next
) {
243 if (r
->ai_socktype
>= 0 && r
->ai_socktype
< sizeof(socktypes
)/sizeof(socktypes
[0]))
244 sockstr
= socktypes
[r
->ai_socktype
];
246 sprintf(buf
, "%d", r
->ai_socktype
);
249 switch (r
->ai_family
) {
251 addr
= &((struct sockaddr_in
*) r
->ai_addr
)->sin_addr
;
254 addr
= &((struct sockaddr_in6
*) r
->ai_addr
)->sin6_addr
;
259 if (inet_ntop(r
->ai_family
, addr
, buf
, sizeof(buf
)) == NULL
)
260 (void)strlcpy(buf
, "# unknown", sizeof(buf
));
261 printf("%-15s %-6s %s\n", buf
, sockstr
, r
->ai_canonname
?: "");
268 static int ahosts(int argc
, char *argv
[])
270 return ahosts_ex(AF_UNSPEC
, 0, argc
, argv
);
273 static int ahostsv4(int argc
, char *argv
[])
275 return ahosts_ex(AF_INET
, 0, argc
, argv
);
278 static int ahostsv6(int argc
, char *argv
[])
280 return ahosts_ex(AF_INET6
, AI_V4MAPPED
, argc
, argv
);
283 static void networksprint(const struct netent
*ne
)
285 char buf
[INET6_ADDRSTRLEN
];
286 struct in_addr ianet
;
288 ianet
= inet_makeaddr(ne
->n_net
, 0);
289 if (inet_ntop(ne
->n_addrtype
, &ianet
, buf
, sizeof(buf
)) == NULL
)
290 (void)strlcpy(buf
, "# unknown", sizeof(buf
));
291 printfmtstrings(ne
->n_aliases
, " ", " ", "%-16s %s", ne
->n_name
, buf
);
294 static int networks(int argc
, char *argv
[])
303 while ((ne
= getnetent()) != NULL
)
306 for (i
= 2; i
< argc
; i
++) {
307 net
= inet_network(argv
[i
]);
308 if (net
!= INADDR_NONE
)
309 ne
= getnetbyaddr(net
, AF_INET
);
311 ne
= getnetbyname(argv
[i
]);
323 static void passwdprint(struct passwd
*pw
)
325 (void)printf("%s:%s:%u:%u:%s:%s:%s\n",
326 pw
->pw_name
, pw
->pw_passwd
, pw
->pw_uid
,
327 pw
->pw_gid
, pw
->pw_gecos
, pw
->pw_dir
, pw
->pw_shell
);
330 static int passwd(int argc
, char *argv
[])
338 while ((pw
= getpwent()) != NULL
)
341 for (i
= 2; i
< argc
; i
++) {
342 if (parsenum(argv
[i
], &id
))
343 pw
= getpwuid((uid_t
)id
);
345 pw
= getpwnam(argv
[i
]);
357 static void protocolsprint(struct protoent
*pe
)
359 printfmtstrings(pe
->p_aliases
, " ", " ",
360 "%-16s %5d", pe
->p_name
, pe
->p_proto
);
363 static int protocols(int argc
, char *argv
[])
372 while ((pe
= getprotoent()) != NULL
)
375 for (i
= 2; i
< argc
; i
++) {
376 if (parsenum(argv
[i
], &id
))
377 pe
= getprotobynumber((int)id
);
379 pe
= getprotobyname(argv
[i
]);
391 static void servicesprint(struct servent
*se
)
393 printfmtstrings(se
->s_aliases
, " ", " ",
395 se
->s_name
, ntohs(se
->s_port
), se
->s_proto
);
399 static int services(int argc
, char *argv
[])
409 while ((se
= getservent()) != NULL
)
412 for (i
= 2; i
< argc
; i
++) {
413 proto
= strchr(argv
[i
], '/');
416 if (parsenum(argv
[i
], &id
))
417 se
= getservbyport(htons(id
), proto
);
419 se
= getservbyname(argv
[i
], proto
);
431 static int shells(int argc
, char *argv
[])
439 while ((sh
= getusershell()) != NULL
)
440 (void)printf("%s\n", sh
);
442 for (i
= 2; i
< argc
; i
++) {
444 while ((sh
= getusershell()) != NULL
) {
445 if (strcmp(sh
, argv
[i
]) == 0) {
446 (void)printf("%s\n", sh
);
460 static struct getentdb
{
462 int (*callback
)(int, char *[]);
464 { "ethers", ethers
, },
467 { "ahosts", ahosts
, },
468 { "ahostsv4", ahostsv4
, },
469 { "ahostsv6", ahostsv6
, },
470 { "networks", networks
, },
471 { "passwd", passwd
, },
472 { "protocols", protocols
, },
473 { "services", services
, },
474 { "shells", shells
, },
479 static int usage(const char *arg0
)
481 struct getentdb
*curdb
;
484 (void)fprintf(stderr
, "Usage: %s database [key ...]\n", arg0
);
485 (void)fprintf(stderr
, "\tdatabase may be one of:");
486 for (i
= 0, curdb
= databases
; curdb
->name
!= NULL
; curdb
++, i
++) {
488 (void)fputs("\n\t\t", stderr
);
489 (void)fprintf(stderr
, "%s%s", i
% 7 == 0 ? "" : " ",
492 (void)fprintf(stderr
, "\n");
498 main(int argc
, char *argv
[])
500 struct getentdb
*curdb
;
504 for (curdb
= databases
; curdb
->name
!= NULL
; curdb
++)
505 if (strcmp(curdb
->name
, argv
[1]) == 0)
506 return (*curdb
->callback
)(argc
, argv
);
508 warn("Unknown database `%s'", argv
[1]);