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