xref: /illumos-gate/usr/src/cmd/ypcmd/ypmatch.c (revision a4568e19224dbd8e405999c57ff8d4e4fd0d877f)
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 /*
36  * This is a user command which looks up the value of a key in a map
37  *
38  * Usage is:
39  *	ypmatch [-d domain] [-t] [-k] key [key ...] mname
40  *  ypmatch -x
41  *
42  * where:  the -d switch can be used to specify a domain other than the
43  * default domain.  mname may be either a mapname, or a nickname which
44  * will be translated into a mapname according this translation.  The
45  * -k switch prints keys as well as values. The -x switch may be used
46  * to dump the translation table.
47  */
48 
49 #include <stdio.h>
50 #include <rpc/rpc.h>
51 #include <rpcsvc/yp_prot.h>
52 #include <rpcsvc/ypclnt.h>
53 #include <string.h>
54 #include <unistd.h>
55 #include <stdlib.h>
56 
57 static void get_command_line_args();
58 static void getdomain();
59 static bool match_list();
60 static bool match_one();
61 static void print_one();
62 extern void maketable();
63 extern int getmapname();
64 extern int yp_match_rsvdport();
65 
66 static int translate = TRUE;
67 static int dodump = FALSE;
68 static int printkeys = FALSE;
69 static char *domain = NULL;
70 static char default_domain_name[YPMAXDOMAIN];
71 static char *map = NULL;
72 static char nm[YPMAXMAP+1];
73 static char **keys = NULL;
74 static int nkeys;
75 static char err_usage[] =
76 "Usage:\n\
77 	ypmatch [-d domain] [-t] [-k] key [key ...] mname\n\
78 	ypmatch -x\n\
79 where\n\
80 	mname may be either a mapname or a nickname for a map\n\
81 	-t inhibits map nickname translation\n\
82 	-k prints keys as well as values.\n\
83 	-x dumps the map nickname translation table.\n";
84 static char err_bad_args[] =
85 	"ypmatch:  %s argument is bad.\n";
86 static char err_cant_get_kname[] =
87 	"ypmatch:  can't get %s back from system call.\n";
88 static char err_null_kname[] =
89 	"ypmatch:  the %s hasn't been set on this machine.\n";
90 static char err_bad_mapname[] = "mapname";
91 static char err_bad_domainname[] = "domainname";
92 
93 /*
94  * This is the main line for the ypmatch process.
95  */
96 int
97 main(argc, argv)
98 	char **argv;
99 {
100 	get_command_line_args(argc, argv);
101 
102 	if (dodump) {
103 		maketable(dodump);
104 		exit(0);
105 	}
106 
107 	if (!domain) {
108 		getdomain();
109 	}
110 
111 	if (translate && (strchr(map, '.') == NULL) &&
112 		(getmapname(map, nm))) {
113 		map = nm;
114 	}
115 
116 	if (!match_list())
117 		return (1);
118 	return (0);
119 }
120 
121 /*
122  * This does the command line argument processing.
123  */
124 static void
125 get_command_line_args(argc, argv)
126 	int argc;
127 	char **argv;
128 
129 {
130 
131 	if (argc < 2) {
132 		(void) fprintf(stderr, err_usage);
133 		exit(1);
134 	}
135 	argv++;
136 
137 	while (--argc > 0 && (*argv)[0] == '-') {
138 
139 		switch ((*argv)[1]) {
140 
141 		case 't':
142 			translate = FALSE;
143 			break;
144 
145 		case 'k':
146 			printkeys = TRUE;
147 			break;
148 
149 		case 'x':
150 			dodump = TRUE;
151 			break;
152 
153 		case 'd':
154 
155 			if (argc > 1) {
156 				argv++;
157 				argc--;
158 				domain = *argv;
159 
160 				if ((int)strlen(domain) > YPMAXDOMAIN) {
161 					(void) fprintf(stderr, err_bad_args,
162 					    err_bad_domainname);
163 					exit(1);
164 				}
165 
166 			} else {
167 				(void) fprintf(stderr, err_usage);
168 				exit(1);
169 			}
170 
171 			break;
172 
173 		default:
174 			(void) fprintf(stderr, err_usage);
175 			exit(1);
176 		}
177 
178 		argv++;
179 	}
180 
181 	if (!dodump) {
182 		if (argc < 2) {
183 			(void) fprintf(stderr, err_usage);
184 			exit(1);
185 		}
186 
187 		keys = argv;
188 		nkeys = argc -1;
189 		map = argv[argc -1];
190 
191 		if ((int)strlen(map) > YPMAXMAP) {
192 			(void) fprintf(stderr, err_bad_args, err_bad_mapname);
193 			exit(1);
194 		}
195 	}
196 }
197 
198 /*
199  * This gets the local default domainname, and makes sure that it's set
200  * to something reasonable.  domain is set here.
201  */
202 static void
203 getdomain()
204 {
205 	if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
206 		domain = default_domain_name;
207 	} else {
208 		(void) fprintf(stderr, err_cant_get_kname, err_bad_domainname);
209 		exit(1);
210 	}
211 
212 	if ((int)strlen(domain) == 0) {
213 		(void) fprintf(stderr, err_null_kname, err_bad_domainname);
214 		exit(1);
215 	}
216 }
217 
218 /*
219  * This traverses the list of argument keys.
220  */
221 static bool
222 match_list()
223 {
224 	bool error;
225 	bool errors = FALSE;
226 	char *val;
227 	int len;
228 	int n = 0;
229 
230 	while (n < nkeys) {
231 		error = match_one(keys[n], &val, &len);
232 
233 		if (!error) {
234 			print_one(keys[n], val, len);
235 			free(val);
236 		} else {
237 			errors = TRUE;
238 		}
239 
240 		n++;
241 	}
242 
243 	return (!errors);
244 }
245 
246 /*
247  * This fires off a "match" request to any old yp server, using the vanilla
248  * yp client interface.  To cover the case in which trailing NULLs are included
249  * in the keys, this retrys the match request including the NULL if the key
250  * isn't in the map.
251  */
252 static bool
253 match_one(key, val, len)
254 	char *key;
255 	char **val;
256 	int *len;
257 {
258 	int err;
259 	bool error = FALSE;
260 
261 	*val = NULL;
262 	*len = 0;
263 	err = yp_match_rsvdport(domain, map, key, (int)strlen(key), val, len);
264 
265 
266 	if (err == YPERR_KEY) {
267 		err = yp_match_rsvdport(domain, map, key,
268 					((int)strlen(key) + 1),
269 		    val, len);
270 	}
271 
272 	if (err) {
273 		(void) fprintf(stderr,
274 		    "Can't match key %s in map %s.  Reason: %s.\n", key, map,
275 		    yperr_string(err));
276 		error = TRUE;
277 	}
278 
279 	return (error);
280 }
281 
282 /*
283  * This prints the value, (and optionally, the key) after first checking that
284  * the last char in the value isn't a NULL.  If the last char is a NULL, the
285  * \n\0 sequence which the yp client layer has given to us is shuffled back
286  * one byte.
287  */
288 static void
289 print_one(key, val, len)
290 	char *key;
291 	char *val;
292 	int len;
293 {
294 	if (printkeys) {
295 		(void) printf("%s: ", key);
296 	}
297 
298 	(void) printf("%.*s\n", len, val);
299 }
300