xref: /illumos-gate/usr/src/lib/libsmbfs/smb/subr.c (revision 4bff34e37def8a90f9194d81bc345c52ba20086a)
1*4bff34e3Sthurlow /*
2*4bff34e3Sthurlow  * Copyright (c) 2000, Boris Popov
3*4bff34e3Sthurlow  * All rights reserved.
4*4bff34e3Sthurlow  *
5*4bff34e3Sthurlow  * Redistribution and use in source and binary forms, with or without
6*4bff34e3Sthurlow  * modification, are permitted provided that the following conditions
7*4bff34e3Sthurlow  * are met:
8*4bff34e3Sthurlow  * 1. Redistributions of source code must retain the above copyright
9*4bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer.
10*4bff34e3Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
11*4bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer in the
12*4bff34e3Sthurlow  *    documentation and/or other materials provided with the distribution.
13*4bff34e3Sthurlow  * 3. All advertising materials mentioning features or use of this software
14*4bff34e3Sthurlow  *    must display the following acknowledgement:
15*4bff34e3Sthurlow  *    This product includes software developed by Boris Popov.
16*4bff34e3Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
17*4bff34e3Sthurlow  *    may be used to endorse or promote products derived from this software
18*4bff34e3Sthurlow  *    without specific prior written permission.
19*4bff34e3Sthurlow  *
20*4bff34e3Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21*4bff34e3Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*4bff34e3Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*4bff34e3Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24*4bff34e3Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25*4bff34e3Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26*4bff34e3Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*4bff34e3Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28*4bff34e3Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29*4bff34e3Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30*4bff34e3Sthurlow  * SUCH DAMAGE.
31*4bff34e3Sthurlow  *
32*4bff34e3Sthurlow  * $Id: subr.c,v 1.19 2005/02/09 00:23:45 lindak Exp $
33*4bff34e3Sthurlow  */
34*4bff34e3Sthurlow 
35*4bff34e3Sthurlow #pragma ident	"%Z%%M%	%I%	%E% SMI"
36*4bff34e3Sthurlow 
37*4bff34e3Sthurlow #include <sys/param.h>
38*4bff34e3Sthurlow #include <sys/types.h>
39*4bff34e3Sthurlow #include <sys/errno.h>
40*4bff34e3Sthurlow #include <sys/syscall.h>
41*4bff34e3Sthurlow #include <sys/wait.h>
42*4bff34e3Sthurlow #include <sys/debug.h>
43*4bff34e3Sthurlow 
44*4bff34e3Sthurlow #include <unistd.h>
45*4bff34e3Sthurlow #include <ctype.h>
46*4bff34e3Sthurlow #include <string.h>
47*4bff34e3Sthurlow #include <stdio.h>
48*4bff34e3Sthurlow #include <stdlib.h>
49*4bff34e3Sthurlow #include <stdarg.h>
50*4bff34e3Sthurlow #include <errno.h>
51*4bff34e3Sthurlow #include <sysexits.h>
52*4bff34e3Sthurlow #include <libintl.h>
53*4bff34e3Sthurlow 
54*4bff34e3Sthurlow #include <netsmb/netbios.h>
55*4bff34e3Sthurlow #include <netsmb/smb_lib.h>
56*4bff34e3Sthurlow #include <netsmb/nb_lib.h>
57*4bff34e3Sthurlow #include <cflib.h>
58*4bff34e3Sthurlow #include <err.h>
59*4bff34e3Sthurlow 
60*4bff34e3Sthurlow uid_t real_uid, eff_uid;
61*4bff34e3Sthurlow 
62*4bff34e3Sthurlow static int smblib_initialized;
63*4bff34e3Sthurlow 
64*4bff34e3Sthurlow struct rcfile *smb_rc;
65*4bff34e3Sthurlow 
66*4bff34e3Sthurlow int
67*4bff34e3Sthurlow smb_lib_init(void)
68*4bff34e3Sthurlow {
69*4bff34e3Sthurlow 	int error;
70*4bff34e3Sthurlow 
71*4bff34e3Sthurlow 	if (smblib_initialized)
72*4bff34e3Sthurlow 		return (0);
73*4bff34e3Sthurlow 	if ((error = nls_setlocale("")) != 0) {
74*4bff34e3Sthurlow 		fprintf(stdout, dgettext(TEXT_DOMAIN,
75*4bff34e3Sthurlow 		    "%s: can't initialise locale\n"), __progname);
76*4bff34e3Sthurlow 		return (error);
77*4bff34e3Sthurlow 	}
78*4bff34e3Sthurlow 	smblib_initialized++;
79*4bff34e3Sthurlow 	return (0);
80*4bff34e3Sthurlow }
81*4bff34e3Sthurlow 
82*4bff34e3Sthurlow /*
83*4bff34e3Sthurlow  * Private version of strerror(3C) that
84*4bff34e3Sthurlow  * knows our special error codes.
85*4bff34e3Sthurlow  */
86*4bff34e3Sthurlow char *
87*4bff34e3Sthurlow smb_strerror(int err)
88*4bff34e3Sthurlow {
89*4bff34e3Sthurlow 	char *msg;
90*4bff34e3Sthurlow 
91*4bff34e3Sthurlow 	switch (err) {
92*4bff34e3Sthurlow 	case EBADRPC:
93*4bff34e3Sthurlow 		msg = dgettext(TEXT_DOMAIN,
94*4bff34e3Sthurlow 		    "remote call failed");
95*4bff34e3Sthurlow 		break;
96*4bff34e3Sthurlow 	case EAUTH:
97*4bff34e3Sthurlow 		msg = dgettext(TEXT_DOMAIN,
98*4bff34e3Sthurlow 		    "authentication failed");
99*4bff34e3Sthurlow 		break;
100*4bff34e3Sthurlow 	default:
101*4bff34e3Sthurlow 		msg = strerror(err);
102*4bff34e3Sthurlow 		break;
103*4bff34e3Sthurlow 	}
104*4bff34e3Sthurlow 
105*4bff34e3Sthurlow 	return (msg);
106*4bff34e3Sthurlow }
107*4bff34e3Sthurlow 
108*4bff34e3Sthurlow /*
109*4bff34e3Sthurlow  * Print a (descriptive) error message
110*4bff34e3Sthurlow  * error values:
111*4bff34e3Sthurlow  *         0 - no specific error code available;
112*4bff34e3Sthurlow  *  1..32767 - system error
113*4bff34e3Sthurlow  */
114*4bff34e3Sthurlow void
115*4bff34e3Sthurlow smb_error(const char *fmt, int error, ...) {
116*4bff34e3Sthurlow 	va_list ap;
117*4bff34e3Sthurlow 	const char *cp;
118*4bff34e3Sthurlow 	int errtype;
119*4bff34e3Sthurlow 
120*4bff34e3Sthurlow 	fprintf(stderr, "%s: ", __progname);
121*4bff34e3Sthurlow 	va_start(ap, error);
122*4bff34e3Sthurlow 	vfprintf(stderr, fmt, ap);
123*4bff34e3Sthurlow 	va_end(ap);
124*4bff34e3Sthurlow 	if (error == -1) {
125*4bff34e3Sthurlow 		error = errno;
126*4bff34e3Sthurlow 		errtype = SMB_SYS_ERROR;
127*4bff34e3Sthurlow 	} else {
128*4bff34e3Sthurlow 		errtype = error & SMB_ERRTYPE_MASK;
129*4bff34e3Sthurlow 		error &= ~SMB_ERRTYPE_MASK;
130*4bff34e3Sthurlow 	}
131*4bff34e3Sthurlow 	switch (errtype) {
132*4bff34e3Sthurlow 	    case SMB_SYS_ERROR:
133*4bff34e3Sthurlow 		if (error)
134*4bff34e3Sthurlow 			fprintf(stderr, ": syserr = %s\n", smb_strerror(error));
135*4bff34e3Sthurlow 		else
136*4bff34e3Sthurlow 			fprintf(stderr, "\n");
137*4bff34e3Sthurlow 		break;
138*4bff34e3Sthurlow 	    case SMB_RAP_ERROR:
139*4bff34e3Sthurlow 		fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
140*4bff34e3Sthurlow 		break;
141*4bff34e3Sthurlow 	    case SMB_NB_ERROR:
142*4bff34e3Sthurlow 		cp = nb_strerror(error);
143*4bff34e3Sthurlow 		if (cp == NULL)
144*4bff34e3Sthurlow 			fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
145*4bff34e3Sthurlow 		else
146*4bff34e3Sthurlow 			fprintf(stderr, ": nberr = %s\n", cp);
147*4bff34e3Sthurlow 		break;
148*4bff34e3Sthurlow 	    default:
149*4bff34e3Sthurlow 		fprintf(stderr, "\n");
150*4bff34e3Sthurlow 	}
151*4bff34e3Sthurlow }
152*4bff34e3Sthurlow 
153*4bff34e3Sthurlow char *
154*4bff34e3Sthurlow smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
155*4bff34e3Sthurlow 	int first = 1;
156*4bff34e3Sthurlow 
157*4bff34e3Sthurlow 	strcpy(dest, "<");
158*4bff34e3Sthurlow 	for (; bnp->bn_bit; bnp++) {
159*4bff34e3Sthurlow 		if (flags & bnp->bn_bit) {
160*4bff34e3Sthurlow 			strcat(dest, bnp->bn_name);
161*4bff34e3Sthurlow 			first = 0;
162*4bff34e3Sthurlow 		}
163*4bff34e3Sthurlow 		if (!first && (flags & bnp[1].bn_bit))
164*4bff34e3Sthurlow 			strcat(dest, "|");
165*4bff34e3Sthurlow 	}
166*4bff34e3Sthurlow 	strcat(dest, ">");
167*4bff34e3Sthurlow 	return (dest);
168*4bff34e3Sthurlow }
169*4bff34e3Sthurlow 
170*4bff34e3Sthurlow extern int home_nsmbrc;
171*4bff34e3Sthurlow 
172*4bff34e3Sthurlow #ifdef DEBUG
173*4bff34e3Sthurlow #include "queue.h"
174*4bff34e3Sthurlow #include "rcfile_priv.h"
175*4bff34e3Sthurlow 
176*4bff34e3Sthurlow struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname);
177*4bff34e3Sthurlow struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *keyname);
178*4bff34e3Sthurlow 
179*4bff34e3Sthurlow void
180*4bff34e3Sthurlow dump_props(char *where)
181*4bff34e3Sthurlow {
182*4bff34e3Sthurlow 	struct rcsection *rsp = NULL;
183*4bff34e3Sthurlow 	struct rckey *rkp = NULL;
184*4bff34e3Sthurlow 
185*4bff34e3Sthurlow 	printf("Settings %s\n", where);
186*4bff34e3Sthurlow 	SLIST_FOREACH(rsp, &smb_rc->rf_sect, rs_next) {
187*4bff34e3Sthurlow 		printf("section=%s\n", rsp->rs_name);
188*4bff34e3Sthurlow 		fflush(stdout);
189*4bff34e3Sthurlow 
190*4bff34e3Sthurlow 		SLIST_FOREACH(rkp, &rsp->rs_keys, rk_next) {
191*4bff34e3Sthurlow 			printf("  key=%s, value=%s\n",
192*4bff34e3Sthurlow 			    rkp->rk_name, rkp->rk_value);
193*4bff34e3Sthurlow 			fflush(stdout);
194*4bff34e3Sthurlow 		}
195*4bff34e3Sthurlow 	}
196*4bff34e3Sthurlow }
197*4bff34e3Sthurlow #endif
198*4bff34e3Sthurlow 
199*4bff34e3Sthurlow /*
200*4bff34e3Sthurlow  * first read ~/.smbrc, next try to merge SMB_CFG_FILE - if that fails
201*4bff34e3Sthurlow  * because SMB_CFG_FILE doesn't exist, try to merge OLD_SMB_CFG_FILE
202*4bff34e3Sthurlow  */
203*4bff34e3Sthurlow int
204*4bff34e3Sthurlow smb_open_rcfile(struct smb_ctx *ctx)
205*4bff34e3Sthurlow {
206*4bff34e3Sthurlow 	char *home, *fn;
207*4bff34e3Sthurlow 	int error, len;
208*4bff34e3Sthurlow 
209*4bff34e3Sthurlow 	smb_rc = NULL;
210*4bff34e3Sthurlow #ifdef DEPRECATED
211*4bff34e3Sthurlow 	fn = SMB_CFG_FILE;
212*4bff34e3Sthurlow 	error = rc_merge(fn, &smb_rc);
213*4bff34e3Sthurlow 	if (error == ENOENT) {
214*4bff34e3Sthurlow 		/*
215*4bff34e3Sthurlow 		 * OK, try to read a config file in the old location.
216*4bff34e3Sthurlow 		 */
217*4bff34e3Sthurlow 		fn = OLD_SMB_CFG_FILE;
218*4bff34e3Sthurlow 		error = rc_merge(fn, &smb_rc);
219*4bff34e3Sthurlow 	}
220*4bff34e3Sthurlow #endif
221*4bff34e3Sthurlow 	fn = "/usr/sbin/sharectl get smbfs";
222*4bff34e3Sthurlow 	error = rc_merge_pipe(fn, &smb_rc);
223*4bff34e3Sthurlow 	if (error != 0 && error != ENOENT)
224*4bff34e3Sthurlow 		fprintf(stderr, dgettext(TEXT_DOMAIN,
225*4bff34e3Sthurlow 		    "Can't open %s: %s\n"), fn, smb_strerror(errno));
226*4bff34e3Sthurlow #ifdef DEBUG
227*4bff34e3Sthurlow 	dump_props("after reading global repository");
228*4bff34e3Sthurlow #endif
229*4bff34e3Sthurlow 
230*4bff34e3Sthurlow 	home = getenv("HOME");
231*4bff34e3Sthurlow 	if (home == NULL && ctx && ctx->ct_home)
232*4bff34e3Sthurlow 		home = ctx->ct_home;
233*4bff34e3Sthurlow 	if (home) {
234*4bff34e3Sthurlow 		len = strlen(home) + 20;
235*4bff34e3Sthurlow 		fn = malloc(len);
236*4bff34e3Sthurlow 		snprintf(fn, len, "%s/.nsmbrc", home);
237*4bff34e3Sthurlow 		home_nsmbrc = 1;
238*4bff34e3Sthurlow 		error = rc_merge(fn, &smb_rc);
239*4bff34e3Sthurlow 		if (error != 0 && error != ENOENT) {
240*4bff34e3Sthurlow 			fprintf(stderr, dgettext(TEXT_DOMAIN,
241*4bff34e3Sthurlow 			    "Can't open %s: %s\n"), fn, smb_strerror(errno));
242*4bff34e3Sthurlow 		}
243*4bff34e3Sthurlow 		free(fn);
244*4bff34e3Sthurlow 	}
245*4bff34e3Sthurlow 	home_nsmbrc = 0;
246*4bff34e3Sthurlow #ifdef DEBUG
247*4bff34e3Sthurlow 	dump_props("after reading user settings");
248*4bff34e3Sthurlow #endif
249*4bff34e3Sthurlow 	if (smb_rc == NULL) {
250*4bff34e3Sthurlow 		return (ENOENT);
251*4bff34e3Sthurlow 	}
252*4bff34e3Sthurlow 	return (0);
253*4bff34e3Sthurlow }
254*4bff34e3Sthurlow 
255*4bff34e3Sthurlow void
256*4bff34e3Sthurlow smb_simplecrypt(char *dst, const char *src)
257*4bff34e3Sthurlow {
258*4bff34e3Sthurlow 	int ch, pos;
259*4bff34e3Sthurlow 
260*4bff34e3Sthurlow 	*dst++ = '$';
261*4bff34e3Sthurlow 	*dst++ = '$';
262*4bff34e3Sthurlow 	*dst++ = '1';
263*4bff34e3Sthurlow 	pos = 27;
264*4bff34e3Sthurlow 	while (*src) {
265*4bff34e3Sthurlow 		ch = *src++;
266*4bff34e3Sthurlow 		if (isascii(ch))
267*4bff34e3Sthurlow 			ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
268*4bff34e3Sthurlow 			    islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
269*4bff34e3Sthurlow 		ch ^= pos;
270*4bff34e3Sthurlow 		pos += 13;
271*4bff34e3Sthurlow 		sprintf(dst, "%02x", ch);
272*4bff34e3Sthurlow 		dst += 2;
273*4bff34e3Sthurlow 	}
274*4bff34e3Sthurlow 	*dst = 0;
275*4bff34e3Sthurlow }
276*4bff34e3Sthurlow 
277*4bff34e3Sthurlow int
278*4bff34e3Sthurlow smb_simpledecrypt(char *dst, const char *src)
279*4bff34e3Sthurlow {
280*4bff34e3Sthurlow 	char *ep, hexval[3];
281*4bff34e3Sthurlow 	int len, ch, pos;
282*4bff34e3Sthurlow 
283*4bff34e3Sthurlow 	if (strncmp(src, "$$1", 3) != 0)
284*4bff34e3Sthurlow 		return (EINVAL);
285*4bff34e3Sthurlow 	src += 3;
286*4bff34e3Sthurlow 	len = strlen(src);
287*4bff34e3Sthurlow 	if (len & 1)
288*4bff34e3Sthurlow 		return (EINVAL);
289*4bff34e3Sthurlow 	len /= 2;
290*4bff34e3Sthurlow 	hexval[2] = 0;
291*4bff34e3Sthurlow 	pos = 27;
292*4bff34e3Sthurlow 	while (len--) {
293*4bff34e3Sthurlow 		hexval[0] = *src++;
294*4bff34e3Sthurlow 		hexval[1] = *src++;
295*4bff34e3Sthurlow 		ch = strtoul(hexval, &ep, 16);
296*4bff34e3Sthurlow 		if (*ep != 0)
297*4bff34e3Sthurlow 			return (EINVAL);
298*4bff34e3Sthurlow 		ch ^= pos;
299*4bff34e3Sthurlow 		pos += 13;
300*4bff34e3Sthurlow 		if (isascii(ch))
301*4bff34e3Sthurlow 			ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
302*4bff34e3Sthurlow 			    islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
303*4bff34e3Sthurlow 		*dst++ = ch;
304*4bff34e3Sthurlow 	}
305*4bff34e3Sthurlow 	*dst = 0;
306*4bff34e3Sthurlow 	return (0);
307*4bff34e3Sthurlow }
308*4bff34e3Sthurlow 
309*4bff34e3Sthurlow 
310*4bff34e3Sthurlow static int
311*4bff34e3Sthurlow safe_execv(char *args[])
312*4bff34e3Sthurlow {
313*4bff34e3Sthurlow 	int	pid;
314*4bff34e3Sthurlow 	int status;
315*4bff34e3Sthurlow 
316*4bff34e3Sthurlow 	pid = fork();
317*4bff34e3Sthurlow 	if (pid == 0) {
318*4bff34e3Sthurlow 		(void) execv(args[0], args);
319*4bff34e3Sthurlow 		/* Changed from errx() to fprintf(stderr) -Pavan */
320*4bff34e3Sthurlow 		fprintf(stderr, dgettext(TEXT_DOMAIN,
321*4bff34e3Sthurlow 		    "%s: execv %s failed, %s\n"), __progname,
322*4bff34e3Sthurlow 		    args[0], smb_strerror(errno));
323*4bff34e3Sthurlow 	}
324*4bff34e3Sthurlow 	if (pid == -1) {
325*4bff34e3Sthurlow 		fprintf(stderr, dgettext(TEXT_DOMAIN, "%s: fork failed, %s\n"),
326*4bff34e3Sthurlow 		    __progname, smb_strerror(errno));
327*4bff34e3Sthurlow 		return (1);
328*4bff34e3Sthurlow 	}
329*4bff34e3Sthurlow 	if (wait4(pid, &status, 0, NULL) != pid) {
330*4bff34e3Sthurlow 		fprintf(stderr, dgettext(TEXT_DOMAIN,
331*4bff34e3Sthurlow 		    "%s: BUG executing %s command\n"), __progname, args[0]);
332*4bff34e3Sthurlow 		return (1);
333*4bff34e3Sthurlow 	} else if (!WIFEXITED(status)) {
334*4bff34e3Sthurlow 		fprintf(stderr, dgettext(TEXT_DOMAIN,
335*4bff34e3Sthurlow 		    "%s: %s command aborted by signal %d\n"),
336*4bff34e3Sthurlow 		    __progname, args[0], WTERMSIG(status));
337*4bff34e3Sthurlow 		return (1);
338*4bff34e3Sthurlow 	} else if (WEXITSTATUS(status)) {
339*4bff34e3Sthurlow 		fprintf(stderr, dgettext(TEXT_DOMAIN,
340*4bff34e3Sthurlow 		    "%s: %s command failed, exit status %d: %s\n"),
341*4bff34e3Sthurlow 		    __progname, args[0], WEXITSTATUS(status),
342*4bff34e3Sthurlow 		    smb_strerror(WEXITSTATUS(status)));
343*4bff34e3Sthurlow 		return (1);
344*4bff34e3Sthurlow 	}
345*4bff34e3Sthurlow 	return (0);
346*4bff34e3Sthurlow }
347*4bff34e3Sthurlow 
348*4bff34e3Sthurlow 
349*4bff34e3Sthurlow void
350*4bff34e3Sthurlow dropsuid()
351*4bff34e3Sthurlow {
352*4bff34e3Sthurlow 	/* drop setuid root privs asap */
353*4bff34e3Sthurlow 	eff_uid = geteuid();
354*4bff34e3Sthurlow 	real_uid = getuid();
355*4bff34e3Sthurlow 	seteuid(real_uid);
356*4bff34e3Sthurlow }
357*4bff34e3Sthurlow 
358*4bff34e3Sthurlow 
359*4bff34e3Sthurlow #define	KEXTLOAD_COMMAND	"/sbin/kextload"
360*4bff34e3Sthurlow #define	FS_KEXT_DIR		"/System/Library/Extensions/smbfs.kext"
361*4bff34e3Sthurlow #define	FULL_KEXTNAME		"com.apple.filesystems.smbfs"
362*4bff34e3Sthurlow 
363*4bff34e3Sthurlow 
364*4bff34e3Sthurlow int
365*4bff34e3Sthurlow loadsmbvfs()
366*4bff34e3Sthurlow {
367*4bff34e3Sthurlow 	char *kextargs[] = {KEXTLOAD_COMMAND, FS_KEXT_DIR, NULL};
368*4bff34e3Sthurlow 	int error = 0;
369*4bff34e3Sthurlow 
370*4bff34e3Sthurlow 	/*
371*4bff34e3Sthurlow 	 * temporarily revert to root (required for kextload)
372*4bff34e3Sthurlow 	 */
373*4bff34e3Sthurlow 	seteuid(eff_uid);
374*4bff34e3Sthurlow 	error = safe_execv(kextargs);
375*4bff34e3Sthurlow 	seteuid(real_uid); /* and back to real user */
376*4bff34e3Sthurlow 	return (error);
377*4bff34e3Sthurlow }
378*4bff34e3Sthurlow 
379*4bff34e3Sthurlow #undef __progname
380*4bff34e3Sthurlow 
381*4bff34e3Sthurlow char *__progname = NULL;
382*4bff34e3Sthurlow 
383*4bff34e3Sthurlow char *
384*4bff34e3Sthurlow smb_getprogname()
385*4bff34e3Sthurlow {
386*4bff34e3Sthurlow 	char *p;
387*4bff34e3Sthurlow 
388*4bff34e3Sthurlow 	if (__progname == NULL) {
389*4bff34e3Sthurlow 		__progname = (char *)getexecname();
390*4bff34e3Sthurlow 		if ((p = strrchr(__progname, '/')) != 0)
391*4bff34e3Sthurlow 			__progname = p + 1;
392*4bff34e3Sthurlow 	}
393*4bff34e3Sthurlow 	return (__progname);
394*4bff34e3Sthurlow }
395