8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / cmd / svc / servinfo / servinfo.c
blobd65b0f7d20e2d4e840512670c7c64730ac3f7094
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * This file delivers /usr/lib/servinfo which provides description for
29 * IANA and running RPC services. Given a IANA name or RPC program name
30 * or number, the program uses getservbyname(3SOCKET) and rpcbind(3NSL)
31 * to obtain port and proto information for the specified service.
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <strings.h>
37 #include <netconfig.h>
38 #include <netdb.h>
39 #include <rpc/rpc.h>
40 #include <rpc/rpcent.h>
41 #include <sys/types.h>
42 #include <netinet/in.h>
43 #include <netdir.h>
44 #include <inttypes.h>
45 #include <limits.h>
46 #include <libintl.h>
47 #include <locale.h>
49 #ifndef TEXT_DOMAIN
50 #define TEXT_DOMAIN "SUNW_OST_OSCMD"
51 #endif /* TEXT_DOMAIN */
53 #define TCP "tcp"
54 #define TCP6 "tcp6"
55 #define UDP "udp"
56 #define UDP6 "udp6"
58 #define DEFAULT 0x1
59 #define PORT 0x2
60 #define PROTO 0x4
62 #define NETID_LEN 12 /* length for a netid or 2^16 port value */
64 static void
65 usage(char *arg0)
67 (void) fprintf(stderr, gettext("Usage: %s [-R] [-Pp] [-tu[6]] "
68 "-s service_name\n"), arg0);
71 static rpcport_t
72 uaddr2port(char *addr)
74 rpcport_t port = 0;
75 char *dot, *p;
77 if ((dot = strrchr(addr, '.')) == 0) {
78 return (0);
79 } else {
80 if (dot == addr)
81 return (0);
83 p = dot - 1;
84 while (*p != '.') {
86 * If the first dot hasn't been seen, it's a
87 * malformed universal address.
89 if (p == addr)
90 return (0);
91 p--;
94 port = strtol(p + 1, &dot, 10) << 8;
95 port = port | strtol(dot + 1, (char **)NULL, 10);
98 return (port);
101 static int
102 svc_getrpcinfo(char *sname, char *sproto, int options)
104 struct netconfig *nconf;
105 struct rpcblist *blist;
106 int prognum = -1;
107 rpcport_t rpc_port;
108 struct rpcent rentry;
109 struct rpcent *rpc;
110 char line[LINE_MAX] = "";
111 int line_len = LINE_MAX - 1;
112 char buf[NETID_LEN];
114 prognum = atoi(sname);
115 if (prognum > 0)
116 rpc = (struct rpcent *)getrpcbynumber(prognum);
117 else
118 rpc = (struct rpcent *)getrpcbyname(sname);
121 * If an entry doesn't exist, it could be a running program
122 * without a registered RPC entry.
124 if (rpc == NULL) {
125 if (prognum <= 0) {
126 (void) fprintf(stderr,
127 gettext("Can't get rpc entry\n"));
128 return (1);
131 rpc = &rentry;
132 rpc->r_number = prognum;
133 rpc->r_name = sname;
136 if (setnetconfig() == NULL) {
137 (void) fprintf(stderr, gettext("setnetconfig failed\n"));
138 return (1);
141 if ((nconf = getnetconfigent(TCP)) == NULL) {
142 (void) fprintf(stderr, gettext("getnetconfig failed\n"));
143 return (1);
146 if ((blist = (struct rpcblist *)rpcb_getmaps(nconf, "localhost"))
147 == NULL) {
148 (void) fprintf(stderr,
149 gettext("Failed: rpcb_getmaps failed\n"));
150 return (1);
153 for (; blist != NULL; blist = blist->rpcb_next) {
154 if (blist->rpcb_map.r_prog != rpc->r_number)
155 continue;
157 if (sproto) {
158 if (strcmp(blist->rpcb_map.r_netid, sproto) != 0)
159 continue;
160 } else {
161 if (strcmp(blist->rpcb_map.r_netid, UDP) &&
162 strcmp(blist->rpcb_map.r_netid, UDP6) &&
163 strcmp(blist->rpcb_map.r_netid, TCP) &&
164 strcmp(blist->rpcb_map.r_netid, TCP6))
165 continue;
167 rpc_port = uaddr2port(blist->rpcb_map.r_addr);
169 if (options & DEFAULT) {
170 (void) printf("Program %ld\n", blist->rpcb_map.r_prog);
171 (void) printf("Protocol %s\n", blist->rpcb_map.r_netid);
172 (void) printf("Port %ld\n", rpc_port);
173 (void) printf("Version %ld\n", blist->rpcb_map.r_vers);
174 (void) printf("Name %s\n", rpc->r_name);
176 } else if (options & PROTO) {
177 if (strstr(line, blist->rpcb_map.r_netid))
178 continue;
180 (void) snprintf(buf, sizeof (buf), "%5s ",
181 blist->rpcb_map.r_netid);
183 if (strlen(buf) > line_len)
184 continue;
186 line_len = line_len - strlen(buf);
187 (void) strlcat(line, buf, sizeof (line));
188 } else {
189 (void) snprintf(buf, sizeof (buf), "%-7ld ", rpc_port);
191 if (strstr(line, buf) || strlen(buf) > line_len)
192 continue;
194 line_len = line_len - strlen(buf);
195 (void) strlcat(line, buf, sizeof (line));
200 * Print the concatenated output if options is PROTO or PORT.
202 if (options & (PROTO | PORT))
203 (void) puts(line);
205 return (0);
209 main(int argc, char *argv[])
211 struct servent *service;
212 char *sname = NULL;
213 char *sproto = NULL;
214 int options = DEFAULT;
215 int c, isrpc = 0, v6_flag = 0;
217 (void) setlocale(LC_ALL, "");
218 (void) textdomain(TEXT_DOMAIN);
220 optind = 1;
221 opterr = 1;
222 while ((c = getopt(argc, argv, "s:PplRtu6?")) != -1) {
223 switch (c) {
224 case 's':
225 sname = optarg;
226 break;
227 case 't':
228 sproto = TCP;
229 break;
230 case 'u':
231 sproto = UDP;
232 break;
233 case '6':
234 v6_flag = 1;
235 break;
236 case 'P':
237 options = PROTO;
238 break;
239 case 'p':
240 options = PORT;
241 break;
242 case 'R':
243 isrpc = 1;
244 break;
245 default:
246 usage(argv[0]);
247 return (1);
250 if (sname == NULL) {
251 usage(argv[0]);
252 return (1);
256 * Specified service is an RPC service.
258 if (isrpc) {
259 if (sproto && v6_flag) {
260 if (strcmp(sproto, TCP) == 0)
261 sproto = TCP6;
262 if (strcmp(sproto, UDP) == 0)
263 sproto = UDP6;
266 return (svc_getrpcinfo(sname, sproto, options));
269 if ((service = getservbyname(sname, sproto)) == NULL) {
270 (void) fprintf(stderr, gettext(
271 "Failed to get information for %s\n"), sname);
272 return (1);
275 if (options & DEFAULT) {
276 (void) printf("Name %s\n", service->s_name);
277 (void) printf("Protocol %s\n", service->s_proto);
278 (void) printf("Port %d\n", htons(service->s_port));
279 } else if (options & PROTO)
280 (void) printf("%s\n", service->s_proto);
281 else
282 (void) printf("%d\n", htons(service->s_port));
284 return (0);