xref: /onnv-gate/usr/src/cmd/fs.d/nfs/nfsref/nfsref.c (revision 11291:80bdcd03e626)
1*11291SRobert.Thurlow@Sun.COM /*
2*11291SRobert.Thurlow@Sun.COM  * CDDL HEADER START
3*11291SRobert.Thurlow@Sun.COM  *
4*11291SRobert.Thurlow@Sun.COM  * The contents of this file are subject to the terms of the
5*11291SRobert.Thurlow@Sun.COM  * Common Development and Distribution License (the "License").
6*11291SRobert.Thurlow@Sun.COM  * You may not use this file except in compliance with the License.
7*11291SRobert.Thurlow@Sun.COM  *
8*11291SRobert.Thurlow@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11291SRobert.Thurlow@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*11291SRobert.Thurlow@Sun.COM  * See the License for the specific language governing permissions
11*11291SRobert.Thurlow@Sun.COM  * and limitations under the License.
12*11291SRobert.Thurlow@Sun.COM  *
13*11291SRobert.Thurlow@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*11291SRobert.Thurlow@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11291SRobert.Thurlow@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*11291SRobert.Thurlow@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*11291SRobert.Thurlow@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*11291SRobert.Thurlow@Sun.COM  *
19*11291SRobert.Thurlow@Sun.COM  * CDDL HEADER END
20*11291SRobert.Thurlow@Sun.COM  */
21*11291SRobert.Thurlow@Sun.COM 
22*11291SRobert.Thurlow@Sun.COM /*
23*11291SRobert.Thurlow@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*11291SRobert.Thurlow@Sun.COM  * Use is subject to license terms.
25*11291SRobert.Thurlow@Sun.COM  */
26*11291SRobert.Thurlow@Sun.COM 
27*11291SRobert.Thurlow@Sun.COM #include <stdio.h>
28*11291SRobert.Thurlow@Sun.COM #include <unistd.h>
29*11291SRobert.Thurlow@Sun.COM #include <strings.h>
30*11291SRobert.Thurlow@Sun.COM #include <string.h>
31*11291SRobert.Thurlow@Sun.COM #include <limits.h>
32*11291SRobert.Thurlow@Sun.COM #include <libnvpair.h>
33*11291SRobert.Thurlow@Sun.COM #include <locale.h>
34*11291SRobert.Thurlow@Sun.COM #include <sys/stat.h>
35*11291SRobert.Thurlow@Sun.COM #include <sys/fs_reparse.h>
36*11291SRobert.Thurlow@Sun.COM #include <rp_plugin.h>
37*11291SRobert.Thurlow@Sun.COM #include <uuid/uuid.h>
38*11291SRobert.Thurlow@Sun.COM #include <sys/types.h>
39*11291SRobert.Thurlow@Sun.COM #include <sys/stat.h>
40*11291SRobert.Thurlow@Sun.COM #include <fcntl.h>
41*11291SRobert.Thurlow@Sun.COM #include <priv.h>
42*11291SRobert.Thurlow@Sun.COM #include <nfs/nfs4.h>
43*11291SRobert.Thurlow@Sun.COM #include <rpcsvc/nfs4_prot.h>
44*11291SRobert.Thurlow@Sun.COM #include "ref_subr.h"
45*11291SRobert.Thurlow@Sun.COM 
46*11291SRobert.Thurlow@Sun.COM #ifndef TEXT_DOMAIN
47*11291SRobert.Thurlow@Sun.COM #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
48*11291SRobert.Thurlow@Sun.COM #endif /* TEXT_DOMAIN */
49*11291SRobert.Thurlow@Sun.COM 
50*11291SRobert.Thurlow@Sun.COM extern int errno;
51*11291SRobert.Thurlow@Sun.COM 
52*11291SRobert.Thurlow@Sun.COM void
usage()53*11291SRobert.Thurlow@Sun.COM usage()
54*11291SRobert.Thurlow@Sun.COM {
55*11291SRobert.Thurlow@Sun.COM 	fprintf(stderr, gettext("Usage:\n"));
56*11291SRobert.Thurlow@Sun.COM 	fprintf(stderr,
57*11291SRobert.Thurlow@Sun.COM 	    gettext("\tnfsref [-t type] add path location [location ...]\n"));
58*11291SRobert.Thurlow@Sun.COM 	fprintf(stderr, gettext("\tnfsref [-t type] remove path\n"));
59*11291SRobert.Thurlow@Sun.COM 	fprintf(stderr, gettext("\tnfsref [-t type] lookup path\n"));
60*11291SRobert.Thurlow@Sun.COM }
61*11291SRobert.Thurlow@Sun.COM 
62*11291SRobert.Thurlow@Sun.COM /*
63*11291SRobert.Thurlow@Sun.COM  * Copy a string from source to destination, escaping space
64*11291SRobert.Thurlow@Sun.COM  * with a backslash and escaping the escape character as well.
65*11291SRobert.Thurlow@Sun.COM  */
66*11291SRobert.Thurlow@Sun.COM int
add_escape(char * src,char * dest,int limit)67*11291SRobert.Thurlow@Sun.COM add_escape(char *src, char *dest, int limit)
68*11291SRobert.Thurlow@Sun.COM {
69*11291SRobert.Thurlow@Sun.COM 	char *sp, *dp;
70*11291SRobert.Thurlow@Sun.COM 	int destlen = 0;
71*11291SRobert.Thurlow@Sun.COM 
72*11291SRobert.Thurlow@Sun.COM 	sp = src;
73*11291SRobert.Thurlow@Sun.COM 	dp = dest;
74*11291SRobert.Thurlow@Sun.COM 
75*11291SRobert.Thurlow@Sun.COM 	while (*sp && destlen < limit) {
76*11291SRobert.Thurlow@Sun.COM 		if (*sp == '\\') {
77*11291SRobert.Thurlow@Sun.COM 			*dp++ = '\\';
78*11291SRobert.Thurlow@Sun.COM 			*dp++ = '\\';
79*11291SRobert.Thurlow@Sun.COM 			destlen++;
80*11291SRobert.Thurlow@Sun.COM 		} else if (*sp == ' ') {
81*11291SRobert.Thurlow@Sun.COM 			*dp++ = '\\';
82*11291SRobert.Thurlow@Sun.COM 			*dp++ = ' ';
83*11291SRobert.Thurlow@Sun.COM 			destlen++;
84*11291SRobert.Thurlow@Sun.COM 		} else
85*11291SRobert.Thurlow@Sun.COM 			*dp++ = *sp;
86*11291SRobert.Thurlow@Sun.COM 		destlen++;
87*11291SRobert.Thurlow@Sun.COM 		sp++;
88*11291SRobert.Thurlow@Sun.COM 	}
89*11291SRobert.Thurlow@Sun.COM 	if (limit <= 0)
90*11291SRobert.Thurlow@Sun.COM 		return (-1);
91*11291SRobert.Thurlow@Sun.COM 	return (destlen);
92*11291SRobert.Thurlow@Sun.COM }
93*11291SRobert.Thurlow@Sun.COM 
94*11291SRobert.Thurlow@Sun.COM int
addref(char * sl_path,char * svc_type,int optind,int argc,char * argv[])95*11291SRobert.Thurlow@Sun.COM addref(char *sl_path, char *svc_type, int optind, int argc, char *argv[])
96*11291SRobert.Thurlow@Sun.COM {
97*11291SRobert.Thurlow@Sun.COM 	int err, fd, i, len, oldlen, notfound = 0;
98*11291SRobert.Thurlow@Sun.COM 	char *text, *location;
99*11291SRobert.Thurlow@Sun.COM 	nvlist_t *nvl = NULL;
100*11291SRobert.Thurlow@Sun.COM 	char buf[SYMLINK_MAX];
101*11291SRobert.Thurlow@Sun.COM 	struct stat sbuf;
102*11291SRobert.Thurlow@Sun.COM 
103*11291SRobert.Thurlow@Sun.COM 	/* Get an nvlist */
104*11291SRobert.Thurlow@Sun.COM 	nvl = reparse_init();
105*11291SRobert.Thurlow@Sun.COM 	if (nvl == NULL)
106*11291SRobert.Thurlow@Sun.COM 		return (ENOMEM);
107*11291SRobert.Thurlow@Sun.COM 
108*11291SRobert.Thurlow@Sun.COM 	/* Get the reparse point data, if the RP exists */
109*11291SRobert.Thurlow@Sun.COM 	err = readlink(sl_path, buf, SYMLINK_MAX);
110*11291SRobert.Thurlow@Sun.COM 	if (err == -1) {
111*11291SRobert.Thurlow@Sun.COM 		if (errno == ENOENT) {
112*11291SRobert.Thurlow@Sun.COM 			notfound = 1;
113*11291SRobert.Thurlow@Sun.COM 			err = 0;
114*11291SRobert.Thurlow@Sun.COM 		} else {
115*11291SRobert.Thurlow@Sun.COM 			reparse_free(nvl);
116*11291SRobert.Thurlow@Sun.COM 			return (errno);
117*11291SRobert.Thurlow@Sun.COM 		}
118*11291SRobert.Thurlow@Sun.COM 	} else {
119*11291SRobert.Thurlow@Sun.COM 		buf[err] = '\0';
120*11291SRobert.Thurlow@Sun.COM 	}
121*11291SRobert.Thurlow@Sun.COM 
122*11291SRobert.Thurlow@Sun.COM 	/* Get any data into nvlist */
123*11291SRobert.Thurlow@Sun.COM 	if (notfound == 0)
124*11291SRobert.Thurlow@Sun.COM 		err = reparse_parse(buf, nvl);
125*11291SRobert.Thurlow@Sun.COM 	if (err != 0) {
126*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
127*11291SRobert.Thurlow@Sun.COM 		return (err);
128*11291SRobert.Thurlow@Sun.COM 	}
129*11291SRobert.Thurlow@Sun.COM 
130*11291SRobert.Thurlow@Sun.COM 	/*
131*11291SRobert.Thurlow@Sun.COM 	 * Accumulate multiple locations on the command line into 'buf'
132*11291SRobert.Thurlow@Sun.COM 	 */
133*11291SRobert.Thurlow@Sun.COM 	oldlen = len = 0;
134*11291SRobert.Thurlow@Sun.COM 	location = NULL;
135*11291SRobert.Thurlow@Sun.COM 	for (i = optind; i < argc; i++) {
136*11291SRobert.Thurlow@Sun.COM 		bzero(buf, sizeof (buf));
137*11291SRobert.Thurlow@Sun.COM 		len += add_escape(argv[i], buf, SYMLINK_MAX) + 2;
138*11291SRobert.Thurlow@Sun.COM 		location = realloc(location, len);
139*11291SRobert.Thurlow@Sun.COM 		location[oldlen] = '\0';
140*11291SRobert.Thurlow@Sun.COM 		oldlen = len;
141*11291SRobert.Thurlow@Sun.COM 		strlcat(location, buf, len);
142*11291SRobert.Thurlow@Sun.COM 		strlcat(location, " ", len);
143*11291SRobert.Thurlow@Sun.COM 	}
144*11291SRobert.Thurlow@Sun.COM 	location[len - 2] = '\0';
145*11291SRobert.Thurlow@Sun.COM 
146*11291SRobert.Thurlow@Sun.COM 	/* Add to the list */
147*11291SRobert.Thurlow@Sun.COM 	err = reparse_add(nvl, svc_type, location);
148*11291SRobert.Thurlow@Sun.COM 	if (err) {
149*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
150*11291SRobert.Thurlow@Sun.COM 		return (err);
151*11291SRobert.Thurlow@Sun.COM 	}
152*11291SRobert.Thurlow@Sun.COM 
153*11291SRobert.Thurlow@Sun.COM 	/* Get the new or modified symlink contents */
154*11291SRobert.Thurlow@Sun.COM 	err = reparse_unparse(nvl, &text);
155*11291SRobert.Thurlow@Sun.COM 	reparse_free(nvl);
156*11291SRobert.Thurlow@Sun.COM 	if (err)
157*11291SRobert.Thurlow@Sun.COM 		return (err);
158*11291SRobert.Thurlow@Sun.COM 
159*11291SRobert.Thurlow@Sun.COM 	/* Delete first if found */
160*11291SRobert.Thurlow@Sun.COM 	if (notfound == 0) {
161*11291SRobert.Thurlow@Sun.COM 		err =  reparse_delete(sl_path);
162*11291SRobert.Thurlow@Sun.COM 		if (err) {
163*11291SRobert.Thurlow@Sun.COM 			free(text);
164*11291SRobert.Thurlow@Sun.COM 			return (err);
165*11291SRobert.Thurlow@Sun.COM 		}
166*11291SRobert.Thurlow@Sun.COM 	}
167*11291SRobert.Thurlow@Sun.COM 
168*11291SRobert.Thurlow@Sun.COM 	/* Finally, write out the reparse point */
169*11291SRobert.Thurlow@Sun.COM 	err = reparse_create(sl_path, text);
170*11291SRobert.Thurlow@Sun.COM 	free(text);
171*11291SRobert.Thurlow@Sun.COM 	if (err)
172*11291SRobert.Thurlow@Sun.COM 		return (err);
173*11291SRobert.Thurlow@Sun.COM 
174*11291SRobert.Thurlow@Sun.COM 	err = lstat(sl_path, &sbuf);
175*11291SRobert.Thurlow@Sun.COM 	if (err == 0 && strcasecmp(sbuf.st_fstype, "ZFS") != 0)
176*11291SRobert.Thurlow@Sun.COM 		printf(gettext(
177*11291SRobert.Thurlow@Sun.COM 		    "Warning: referrals do not work on this filesystem\n"));
178*11291SRobert.Thurlow@Sun.COM 
179*11291SRobert.Thurlow@Sun.COM 	if (notfound)
180*11291SRobert.Thurlow@Sun.COM 		printf(gettext("Created reparse point %s\n"), sl_path);
181*11291SRobert.Thurlow@Sun.COM 	else
182*11291SRobert.Thurlow@Sun.COM 		printf(gettext("Added to reparse point %s\n"), sl_path);
183*11291SRobert.Thurlow@Sun.COM 
184*11291SRobert.Thurlow@Sun.COM 	return (0);
185*11291SRobert.Thurlow@Sun.COM }
186*11291SRobert.Thurlow@Sun.COM 
187*11291SRobert.Thurlow@Sun.COM int
delref(char * sl_path,char * svc_type)188*11291SRobert.Thurlow@Sun.COM delref(char *sl_path, char *svc_type)
189*11291SRobert.Thurlow@Sun.COM {
190*11291SRobert.Thurlow@Sun.COM 	char *cp;
191*11291SRobert.Thurlow@Sun.COM 	char *svc_data;
192*11291SRobert.Thurlow@Sun.COM 	int err;
193*11291SRobert.Thurlow@Sun.COM 	nvlist_t *nvl;
194*11291SRobert.Thurlow@Sun.COM 	nvpair_t *curr;
195*11291SRobert.Thurlow@Sun.COM 	char buf[SYMLINK_MAX];
196*11291SRobert.Thurlow@Sun.COM 	int fd, fd2;
197*11291SRobert.Thurlow@Sun.COM 	FILE *fp, *fp2;
198*11291SRobert.Thurlow@Sun.COM 	char uuid[UUID_PRINTABLE_STRING_LENGTH], path[256], loc[2048];
199*11291SRobert.Thurlow@Sun.COM 
200*11291SRobert.Thurlow@Sun.COM 	/* Get an nvlist */
201*11291SRobert.Thurlow@Sun.COM 	if (!(nvl = reparse_init()))
202*11291SRobert.Thurlow@Sun.COM 		return (ENOMEM);
203*11291SRobert.Thurlow@Sun.COM 
204*11291SRobert.Thurlow@Sun.COM 	/* Get the symlink data (should be there) */
205*11291SRobert.Thurlow@Sun.COM 	err = readlink(sl_path, buf, SYMLINK_MAX);
206*11291SRobert.Thurlow@Sun.COM 	if (err == -1) {
207*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
208*11291SRobert.Thurlow@Sun.COM 		return (errno);
209*11291SRobert.Thurlow@Sun.COM 	}
210*11291SRobert.Thurlow@Sun.COM 	buf[err] = '\0';
211*11291SRobert.Thurlow@Sun.COM 
212*11291SRobert.Thurlow@Sun.COM 	/* Get the records into the nvlist */
213*11291SRobert.Thurlow@Sun.COM 	err = reparse_parse(buf, nvl);
214*11291SRobert.Thurlow@Sun.COM 	if (err) {
215*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
216*11291SRobert.Thurlow@Sun.COM 		return (err);
217*11291SRobert.Thurlow@Sun.COM 	}
218*11291SRobert.Thurlow@Sun.COM 
219*11291SRobert.Thurlow@Sun.COM 	/* Remove from nvlist */
220*11291SRobert.Thurlow@Sun.COM 	err = reparse_remove(nvl, svc_type);
221*11291SRobert.Thurlow@Sun.COM 	if (err) {
222*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
223*11291SRobert.Thurlow@Sun.COM 		return (err);
224*11291SRobert.Thurlow@Sun.COM 	}
225*11291SRobert.Thurlow@Sun.COM 
226*11291SRobert.Thurlow@Sun.COM 	/* Any list entries left? If so, turn nvlist back to string. */
227*11291SRobert.Thurlow@Sun.COM 	curr = nvlist_next_nvpair(nvl, NULL);
228*11291SRobert.Thurlow@Sun.COM 	if (curr != NULL) {
229*11291SRobert.Thurlow@Sun.COM 		err = reparse_unparse(nvl, &cp);
230*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
231*11291SRobert.Thurlow@Sun.COM 		if (err)
232*11291SRobert.Thurlow@Sun.COM 			return (err);
233*11291SRobert.Thurlow@Sun.COM 	} else {
234*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
235*11291SRobert.Thurlow@Sun.COM 		cp = NULL;
236*11291SRobert.Thurlow@Sun.COM 	}
237*11291SRobert.Thurlow@Sun.COM 
238*11291SRobert.Thurlow@Sun.COM 	/* Finally, delete and perhaps recreate the reparse point */
239*11291SRobert.Thurlow@Sun.COM 	err = reparse_delete(sl_path);
240*11291SRobert.Thurlow@Sun.COM 	if (err) {
241*11291SRobert.Thurlow@Sun.COM 		free(cp);
242*11291SRobert.Thurlow@Sun.COM 		return (err);
243*11291SRobert.Thurlow@Sun.COM 	}
244*11291SRobert.Thurlow@Sun.COM 
245*11291SRobert.Thurlow@Sun.COM 	if (cp != NULL) {
246*11291SRobert.Thurlow@Sun.COM 		err = reparse_create(sl_path, cp);
247*11291SRobert.Thurlow@Sun.COM 		free(cp);
248*11291SRobert.Thurlow@Sun.COM 		if (err)
249*11291SRobert.Thurlow@Sun.COM 			return (err);
250*11291SRobert.Thurlow@Sun.COM 	}
251*11291SRobert.Thurlow@Sun.COM 	printf(gettext("Removed svc_type '%s' from %s\n"), svc_type, sl_path);
252*11291SRobert.Thurlow@Sun.COM 	return (err);
253*11291SRobert.Thurlow@Sun.COM }
254*11291SRobert.Thurlow@Sun.COM 
255*11291SRobert.Thurlow@Sun.COM int
lookup(char * sl_path,char * svc_type,int type_set)256*11291SRobert.Thurlow@Sun.COM lookup(char *sl_path, char *svc_type, int type_set)
257*11291SRobert.Thurlow@Sun.COM {
258*11291SRobert.Thurlow@Sun.COM 	int err;
259*11291SRobert.Thurlow@Sun.COM 	size_t bufsize;
260*11291SRobert.Thurlow@Sun.COM 	char buf[1024];
261*11291SRobert.Thurlow@Sun.COM 	char *type, *svc_data;
262*11291SRobert.Thurlow@Sun.COM 	nvlist_t *nvl;
263*11291SRobert.Thurlow@Sun.COM 	nvpair_t *curr;
264*11291SRobert.Thurlow@Sun.COM 	fs_locations4 fsl;
265*11291SRobert.Thurlow@Sun.COM 	XDR xdr;
266*11291SRobert.Thurlow@Sun.COM 
267*11291SRobert.Thurlow@Sun.COM 	if (!(nvl = reparse_init()))
268*11291SRobert.Thurlow@Sun.COM 		return (-1);
269*11291SRobert.Thurlow@Sun.COM 
270*11291SRobert.Thurlow@Sun.COM 	/* Get reparse point data */
271*11291SRobert.Thurlow@Sun.COM 	err = readlink(sl_path, buf, SYMLINK_MAX);
272*11291SRobert.Thurlow@Sun.COM 	if (err == -1)
273*11291SRobert.Thurlow@Sun.COM 		return (errno);
274*11291SRobert.Thurlow@Sun.COM 	buf[err] = '\0';
275*11291SRobert.Thurlow@Sun.COM 
276*11291SRobert.Thurlow@Sun.COM 	/* Parse it to an nvlist */
277*11291SRobert.Thurlow@Sun.COM 	err = reparse_parse(buf, nvl);
278*11291SRobert.Thurlow@Sun.COM 	if (err) {
279*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
280*11291SRobert.Thurlow@Sun.COM 		return (err);
281*11291SRobert.Thurlow@Sun.COM 	}
282*11291SRobert.Thurlow@Sun.COM 
283*11291SRobert.Thurlow@Sun.COM 	/* Look for entries of the requested service type */
284*11291SRobert.Thurlow@Sun.COM 	curr = NULL;
285*11291SRobert.Thurlow@Sun.COM 	while ((curr = nvlist_next_nvpair(nvl, curr)) != NULL) {
286*11291SRobert.Thurlow@Sun.COM 		type = nvpair_name(curr);
287*11291SRobert.Thurlow@Sun.COM 		if (type_set && strcasecmp(type, svc_type) == 0)
288*11291SRobert.Thurlow@Sun.COM 			break;
289*11291SRobert.Thurlow@Sun.COM 		if (!type_set && strncasecmp(type, "nfs", 3) == 0)
290*11291SRobert.Thurlow@Sun.COM 			break;
291*11291SRobert.Thurlow@Sun.COM 	}
292*11291SRobert.Thurlow@Sun.COM 	if (curr == NULL) {
293*11291SRobert.Thurlow@Sun.COM 		reparse_free(nvl);
294*11291SRobert.Thurlow@Sun.COM 		return (ENOENT);
295*11291SRobert.Thurlow@Sun.COM 	}
296*11291SRobert.Thurlow@Sun.COM 
297*11291SRobert.Thurlow@Sun.COM 	/* Get the service data and look it up */
298*11291SRobert.Thurlow@Sun.COM 	nvpair_value_string(curr, &svc_data);
299*11291SRobert.Thurlow@Sun.COM 
300*11291SRobert.Thurlow@Sun.COM 	bufsize = sizeof (buf);
301*11291SRobert.Thurlow@Sun.COM 	err = reparse_deref(type, svc_data, buf, &bufsize);
302*11291SRobert.Thurlow@Sun.COM 	reparse_free(nvl);
303*11291SRobert.Thurlow@Sun.COM 	if (err)
304*11291SRobert.Thurlow@Sun.COM 		return (err);
305*11291SRobert.Thurlow@Sun.COM 
306*11291SRobert.Thurlow@Sun.COM 	xdrmem_create(&xdr, buf, bufsize, XDR_DECODE);
307*11291SRobert.Thurlow@Sun.COM 	err = xdr_fs_locations4(&xdr, &fsl);
308*11291SRobert.Thurlow@Sun.COM 	XDR_DESTROY(&xdr);
309*11291SRobert.Thurlow@Sun.COM 	if (err != TRUE)
310*11291SRobert.Thurlow@Sun.COM 		return (ENOENT);
311*11291SRobert.Thurlow@Sun.COM 	printf(gettext("%s points to: "), sl_path);
312*11291SRobert.Thurlow@Sun.COM 	print_referral_summary(&fsl);
313*11291SRobert.Thurlow@Sun.COM 	return (0);
314*11291SRobert.Thurlow@Sun.COM }
315*11291SRobert.Thurlow@Sun.COM 
316*11291SRobert.Thurlow@Sun.COM extern char *optarg;
317*11291SRobert.Thurlow@Sun.COM extern int optind, optopt;
318*11291SRobert.Thurlow@Sun.COM 
319*11291SRobert.Thurlow@Sun.COM int
main(int argc,char * argv[])320*11291SRobert.Thurlow@Sun.COM main(int argc, char *argv[])
321*11291SRobert.Thurlow@Sun.COM {
322*11291SRobert.Thurlow@Sun.COM 	char c, *command, *sl_path, *svc_type;
323*11291SRobert.Thurlow@Sun.COM 	int type_set, err;
324*11291SRobert.Thurlow@Sun.COM 
325*11291SRobert.Thurlow@Sun.COM 	(void) setlocale(LC_ALL, "");
326*11291SRobert.Thurlow@Sun.COM 	(void) textdomain(TEXT_DOMAIN);
327*11291SRobert.Thurlow@Sun.COM 
328*11291SRobert.Thurlow@Sun.COM 	svc_type = "nfs-basic";		/* Default from SMF some day */
329*11291SRobert.Thurlow@Sun.COM 	type_set = 0;			/* Lookup any nfs type */
330*11291SRobert.Thurlow@Sun.COM 
331*11291SRobert.Thurlow@Sun.COM 	/* Look for options (just the service type now) */
332*11291SRobert.Thurlow@Sun.COM 	while ((c = getopt(argc, argv, "t:")) != -1) {
333*11291SRobert.Thurlow@Sun.COM 		switch (c) {
334*11291SRobert.Thurlow@Sun.COM 		case 't':
335*11291SRobert.Thurlow@Sun.COM 			svc_type = optarg;
336*11291SRobert.Thurlow@Sun.COM 			type_set = 1;
337*11291SRobert.Thurlow@Sun.COM 			break;
338*11291SRobert.Thurlow@Sun.COM 
339*11291SRobert.Thurlow@Sun.COM 		default:
340*11291SRobert.Thurlow@Sun.COM 			usage();
341*11291SRobert.Thurlow@Sun.COM 			exit(1);
342*11291SRobert.Thurlow@Sun.COM 		}
343*11291SRobert.Thurlow@Sun.COM 	}
344*11291SRobert.Thurlow@Sun.COM 
345*11291SRobert.Thurlow@Sun.COM 	/* Make sure there's at least a command and one argument */
346*11291SRobert.Thurlow@Sun.COM 	if (optind + 1 >= argc) {
347*11291SRobert.Thurlow@Sun.COM 		usage();
348*11291SRobert.Thurlow@Sun.COM 		exit(1);
349*11291SRobert.Thurlow@Sun.COM 	}
350*11291SRobert.Thurlow@Sun.COM 
351*11291SRobert.Thurlow@Sun.COM 	err = rp_plugin_init();
352*11291SRobert.Thurlow@Sun.COM 	switch (err) {
353*11291SRobert.Thurlow@Sun.COM 	case RP_OK:
354*11291SRobert.Thurlow@Sun.COM 		break;
355*11291SRobert.Thurlow@Sun.COM 	case RP_NO_PLUGIN_DIR:
356*11291SRobert.Thurlow@Sun.COM 		fprintf(stderr,
357*11291SRobert.Thurlow@Sun.COM 		    gettext("Warning: no plugin directory, continuing...\n"));
358*11291SRobert.Thurlow@Sun.COM 		break;
359*11291SRobert.Thurlow@Sun.COM 	case RP_NO_PLUGIN:
360*11291SRobert.Thurlow@Sun.COM 		fprintf(stderr,
361*11291SRobert.Thurlow@Sun.COM 		    gettext("Warning: no plugin found, continuing...\n"));
362*11291SRobert.Thurlow@Sun.COM 		break;
363*11291SRobert.Thurlow@Sun.COM 	case RP_NO_MEMORY:
364*11291SRobert.Thurlow@Sun.COM 		fprintf(stderr,
365*11291SRobert.Thurlow@Sun.COM 		    gettext("rp_plugin_init failed, no memory\n"));
366*11291SRobert.Thurlow@Sun.COM 		exit(0);
367*11291SRobert.Thurlow@Sun.COM 	default:
368*11291SRobert.Thurlow@Sun.COM 		fprintf(stderr,
369*11291SRobert.Thurlow@Sun.COM 		    gettext("rp_plugin_init failed, error %d\n"), err);
370*11291SRobert.Thurlow@Sun.COM 		exit(0);
371*11291SRobert.Thurlow@Sun.COM 	}
372*11291SRobert.Thurlow@Sun.COM 
373*11291SRobert.Thurlow@Sun.COM 	command = argv[optind++];
374*11291SRobert.Thurlow@Sun.COM 	sl_path = argv[optind++];
375*11291SRobert.Thurlow@Sun.COM 
376*11291SRobert.Thurlow@Sun.COM 	if (strcmp(command, "add") == 0) {
377*11291SRobert.Thurlow@Sun.COM 
378*11291SRobert.Thurlow@Sun.COM 		if (optind >= argc) {
379*11291SRobert.Thurlow@Sun.COM 			usage();
380*11291SRobert.Thurlow@Sun.COM 			exit(1);
381*11291SRobert.Thurlow@Sun.COM 		}
382*11291SRobert.Thurlow@Sun.COM 
383*11291SRobert.Thurlow@Sun.COM 		err = addref(sl_path, svc_type, optind, argc, argv);
384*11291SRobert.Thurlow@Sun.COM 
385*11291SRobert.Thurlow@Sun.COM 	} else if (strcmp(command, "remove") == 0) {
386*11291SRobert.Thurlow@Sun.COM 
387*11291SRobert.Thurlow@Sun.COM 		err = delref(sl_path, svc_type);
388*11291SRobert.Thurlow@Sun.COM 
389*11291SRobert.Thurlow@Sun.COM 	} else if (strcmp(command, "lookup") == 0) {
390*11291SRobert.Thurlow@Sun.COM 
391*11291SRobert.Thurlow@Sun.COM 		err = lookup(sl_path, svc_type, type_set);
392*11291SRobert.Thurlow@Sun.COM 
393*11291SRobert.Thurlow@Sun.COM 	} else {
394*11291SRobert.Thurlow@Sun.COM 		usage();
395*11291SRobert.Thurlow@Sun.COM 		exit(1);
396*11291SRobert.Thurlow@Sun.COM 	}
397*11291SRobert.Thurlow@Sun.COM 	if (err != 0)
398*11291SRobert.Thurlow@Sun.COM 		fprintf(stderr, gettext("Command %s failed: %s\n"), command,
399*11291SRobert.Thurlow@Sun.COM 		    strerror(err));
400*11291SRobert.Thurlow@Sun.COM 	return (err);
401*11291SRobert.Thurlow@Sun.COM }
402