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
main(argc,argv)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
get_command_line_args(argc,argv)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
getdomain()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
match_list()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
match_one(key,val,len)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
print_one(key,val,len)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