xref: /illumos-gate/usr/src/cmd/ypcmd/ypmatch.c (revision f83283b9)
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
main(int argc,char ** argv)97 main(int argc, char **argv)
98 {
99 	get_command_line_args(argc, argv);
100 
101 	if (dodump) {
102 		maketable(dodump);
103 		exit(0);
104 	}
105 
106 	if (!domain) {
107 		getdomain();
108 	}
109 
110 	if (translate && (strchr(map, '.') == NULL) &&
111 		(getmapname(map, nm))) {
112 		map = nm;
113 	}
114 
115 	if (!match_list())
116 		return (1);
117 	return (0);
118 }
119 
120 /*
121  * This does the command line argument processing.
122  */
123 static void
get_command_line_args(argc,argv)124 get_command_line_args(argc, argv)
125 	int argc;
126 	char **argv;
127 
128 {
129 
130 	if (argc < 2) {
131 		(void) fprintf(stderr, err_usage);
132 		exit(1);
133 	}
134 	argv++;
135 
136 	while (--argc > 0 && (*argv)[0] == '-') {
137 
138 		switch ((*argv)[1]) {
139 
140 		case 't':
141 			translate = FALSE;
142 			break;
143 
144 		case 'k':
145 			printkeys = TRUE;
146 			break;
147 
148 		case 'x':
149 			dodump = TRUE;
150 			break;
151 
152 		case 'd':
153 
154 			if (argc > 1) {
155 				argv++;
156 				argc--;
157 				domain = *argv;
158 
159 				if ((int)strlen(domain) > YPMAXDOMAIN) {
160 					(void) fprintf(stderr, err_bad_args,
161 					    err_bad_domainname);
162 					exit(1);
163 				}
164 
165 			} else {
166 				(void) fprintf(stderr, err_usage);
167 				exit(1);
168 			}
169 
170 			break;
171 
172 		default:
173 			(void) fprintf(stderr, err_usage);
174 			exit(1);
175 		}
176 
177 		argv++;
178 	}
179 
180 	if (!dodump) {
181 		if (argc < 2) {
182 			(void) fprintf(stderr, err_usage);
183 			exit(1);
184 		}
185 
186 		keys = argv;
187 		nkeys = argc -1;
188 		map = argv[argc -1];
189 
190 		if ((int)strlen(map) > YPMAXMAP) {
191 			(void) fprintf(stderr, err_bad_args, err_bad_mapname);
192 			exit(1);
193 		}
194 	}
195 }
196 
197 /*
198  * This gets the local default domainname, and makes sure that it's set
199  * to something reasonable.  domain is set here.
200  */
201 static void
getdomain()202 getdomain()
203 {
204 	if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
205 		domain = default_domain_name;
206 	} else {
207 		(void) fprintf(stderr, err_cant_get_kname, err_bad_domainname);
208 		exit(1);
209 	}
210 
211 	if ((int)strlen(domain) == 0) {
212 		(void) fprintf(stderr, err_null_kname, err_bad_domainname);
213 		exit(1);
214 	}
215 }
216 
217 /*
218  * This traverses the list of argument keys.
219  */
220 static bool
match_list()221 match_list()
222 {
223 	bool error;
224 	bool errors = FALSE;
225 	char *val;
226 	int len;
227 	int n = 0;
228 
229 	while (n < nkeys) {
230 		error = match_one(keys[n], &val, &len);
231 
232 		if (!error) {
233 			print_one(keys[n], val, len);
234 			free(val);
235 		} else {
236 			errors = TRUE;
237 		}
238 
239 		n++;
240 	}
241 
242 	return (!errors);
243 }
244 
245 /*
246  * This fires off a "match" request to any old yp server, using the vanilla
247  * yp client interface.  To cover the case in which trailing NULLs are included
248  * in the keys, this retrys the match request including the NULL if the key
249  * isn't in the map.
250  */
251 static bool
match_one(key,val,len)252 match_one(key, val, len)
253 	char *key;
254 	char **val;
255 	int *len;
256 {
257 	int err;
258 	bool error = FALSE;
259 
260 	*val = NULL;
261 	*len = 0;
262 	err = yp_match_rsvdport(domain, map, key, (int)strlen(key), val, len);
263 
264 
265 	if (err == YPERR_KEY) {
266 		err = yp_match_rsvdport(domain, map, key,
267 					((int)strlen(key) + 1),
268 		    val, len);
269 	}
270 
271 	if (err) {
272 		(void) fprintf(stderr,
273 		    "Can't match key %s in map %s.  Reason: %s.\n", key, map,
274 		    yperr_string(err));
275 		error = TRUE;
276 	}
277 
278 	return (error);
279 }
280 
281 /*
282  * This prints the value, (and optionally, the key) after first checking that
283  * the last char in the value isn't a NULL.  If the last char is a NULL, the
284  * \n\0 sequence which the yp client layer has given to us is shuffled back
285  * one byte.
286  */
287 static void
print_one(key,val,len)288 print_one(key, val, len)
289 	char *key;
290 	char *val;
291 	int len;
292 {
293 	if (printkeys) {
294 		(void) printf("%s: ", key);
295 	}
296 
297 	(void) printf("%.*s\n", len, val);
298 }
299