xref: /illumos-gate/usr/src/cmd/ypcmd/ypmatch.c (revision a506a34c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /*	  All Rights Reserved   */
28 
29 /*
30  * Portions of this source code were derived from Berkeley
31  * under license from the Regents of the University of
32  * California.
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 /*
38  * This is a user command which looks up the value of a key in a map
39  *
40  * Usage is:
41  *	ypmatch [-d domain] [-t] [-k] key [key ...] mname
42  *  ypmatch -x
43  *
44  * where:  the -d switch can be used to specify a domain other than the
45  * default domain.  mname may be either a mapname, or a nickname which
46  * will be translated into a mapname according this translation.  The
47  * -k switch prints keys as well as values. The -x switch may be used
48  * to dump the translation table.
49  */
50 
51 #include <stdio.h>
52 #include <rpc/rpc.h>
53 #include <rpcsvc/yp_prot.h>
54 #include <rpcsvc/ypclnt.h>
55 #include <string.h>
56 #include <unistd.h>
57 #include <stdlib.h>
58 
59 static void get_command_line_args();
60 static void getdomain();
61 static bool match_list();
62 static bool match_one();
63 static void print_one();
64 extern void maketable();
65 extern int getmapname();
66 extern int yp_match_rsvdport();
67 
68 static int translate = TRUE;
69 static int dodump = FALSE;
70 static int printkeys = FALSE;
71 static char *domain = NULL;
72 static char default_domain_name[YPMAXDOMAIN];
73 static char *map = NULL;
74 static char nm[YPMAXMAP+1];
75 static char **keys = NULL;
76 static int nkeys;
77 static char err_usage[] =
78 "Usage:\n\
79 	ypmatch [-d domain] [-t] [-k] key [key ...] mname\n\
80 	ypmatch -x\n\
81 where\n\
82 	mname may be either a mapname or a nickname for a map\n\
83 	-t inhibits map nickname translation\n\
84 	-k prints keys as well as values.\n\
85 	-x dumps the map nickname translation table.\n";
86 static char err_bad_args[] =
87 	"ypmatch:  %s argument is bad.\n";
88 static char err_cant_get_kname[] =
89 	"ypmatch:  can't get %s back from system call.\n";
90 static char err_null_kname[] =
91 	"ypmatch:  the %s hasn't been set on this machine.\n";
92 static char err_bad_mapname[] = "mapname";
93 static char err_bad_domainname[] = "domainname";
94 
95 /*
96  * This is the main line for the ypmatch process.
97  */
98 int
99 main(argc, argv)
100 	char **argv;
101 {
102 	get_command_line_args(argc, argv);
103 
104 	if (dodump) {
105 		maketable(dodump);
106 		exit(0);
107 	}
108 
109 	if (!domain) {
110 		getdomain();
111 	}
112 
113 	if (translate && (strchr(map, '.') == NULL) &&
114 		(getmapname(map, nm))) {
115 		map = nm;
116 	}
117 
118 	if (!match_list())
119 		return (1);
120 	return (0);
121 }
122 
123 /*
124  * This does the command line argument processing.
125  */
126 static void
127 get_command_line_args(argc, argv)
128 	int argc;
129 	char **argv;
130 
131 {
132 
133 	if (argc < 2) {
134 		(void) fprintf(stderr, err_usage);
135 		exit(1);
136 	}
137 	argv++;
138 
139 	while (--argc > 0 && (*argv)[0] == '-') {
140 
141 		switch ((*argv)[1]) {
142 
143 		case 't':
144 			translate = FALSE;
145 			break;
146 
147 		case 'k':
148 			printkeys = TRUE;
149 			break;
150 
151 		case 'x':
152 			dodump = TRUE;
153 			break;
154 
155 		case 'd':
156 
157 			if (argc > 1) {
158 				argv++;
159 				argc--;
160 				domain = *argv;
161 
162 				if ((int)strlen(domain) > YPMAXDOMAIN) {
163 					(void) fprintf(stderr, err_bad_args,
164 					    err_bad_domainname);
165 					exit(1);
166 				}
167 
168 			} else {
169 				(void) fprintf(stderr, err_usage);
170 				exit(1);
171 			}
172 
173 			break;
174 
175 		default:
176 			(void) fprintf(stderr, err_usage);
177 			exit(1);
178 		}
179 
180 		argv++;
181 	}
182 
183 	if (!dodump) {
184 		if (argc < 2) {
185 			(void) fprintf(stderr, err_usage);
186 			exit(1);
187 		}
188 
189 		keys = argv;
190 		nkeys = argc -1;
191 		map = argv[argc -1];
192 
193 		if ((int)strlen(map) > YPMAXMAP) {
194 			(void) fprintf(stderr, err_bad_args, err_bad_mapname);
195 			exit(1);
196 		}
197 	}
198 }
199 
200 /*
201  * This gets the local default domainname, and makes sure that it's set
202  * to something reasonable.  domain is set here.
203  */
204 static void
205 getdomain()
206 {
207 	if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
208 		domain = default_domain_name;
209 	} else {
210 		(void) fprintf(stderr, err_cant_get_kname, err_bad_domainname);
211 		exit(1);
212 	}
213 
214 	if ((int)strlen(domain) == 0) {
215 		(void) fprintf(stderr, err_null_kname, err_bad_domainname);
216 		exit(1);
217 	}
218 }
219 
220 /*
221  * This traverses the list of argument keys.
222  */
223 static bool
224 match_list()
225 {
226 	bool error;
227 	bool errors = FALSE;
228 	char *val;
229 	int len;
230 	int n = 0;
231 
232 	while (n < nkeys) {
233 		error = match_one(keys[n], &val, &len);
234 
235 		if (!error) {
236 			print_one(keys[n], val, len);
237 			free(val);
238 		} else {
239 			errors = TRUE;
240 		}
241 
242 		n++;
243 	}
244 
245 	return (!errors);
246 }
247 
248 /*
249  * This fires off a "match" request to any old yp server, using the vanilla
250  * yp client interface.  To cover the case in which trailing NULLs are included
251  * in the keys, this retrys the match request including the NULL if the key
252  * isn't in the map.
253  */
254 static bool
255 match_one(key, val, len)
256 	char *key;
257 	char **val;
258 	int *len;
259 {
260 	int err;
261 	bool error = FALSE;
262 
263 	*val = NULL;
264 	*len = 0;
265 	err = yp_match_rsvdport(domain, map, key, (int)strlen(key), val, len);
266 
267 
268 	if (err == YPERR_KEY) {
269 		err = yp_match_rsvdport(domain, map, key,
270 					((int)strlen(key) + 1),
271 		    val, len);
272 	}
273 
274 	if (err) {
275 		(void) fprintf(stderr,
276 		    "Can't match key %s in map %s.  Reason: %s.\n", key, map,
277 		    yperr_string(err));
278 		error = TRUE;
279 	}
280 
281 	return (error);
282 }
283 
284 /*
285  * This prints the value, (and optionally, the key) after first checking that
286  * the last char in the value isn't a NULL.  If the last char is a NULL, the
287  * \n\0 sequence which the yp client layer has given to us is shuffled back
288  * one byte.
289  */
290 static void
291 print_one(key, val, len)
292 	char *key;
293 	char *val;
294 	int len;
295 {
296 	if (printkeys) {
297 		(void) printf("%s: ", key);
298 	}
299 
300 	(void) printf("%.*s\n", len, val);
301 }
302