Home | History | Annotate | Download | only in ypcmd
      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