1/*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <mach/mach.h>
25#include <mach/mach_error.h>
26#include <servers/bootstrap.h>
27#include <sys/types.h>
28#include <sys/wait.h>
29#include <sys/errno.h>
30#include <sys/mount.h>
31#include <unistd.h>
32#include <stdlib.h>
33#include <asl.h>
34#include <stdio.h>
35#include "load_webdavfs.h"
36
37#include "webdavfs_load_kext.h"
38#include "webdavfs_load_kextServer.h"
39
40/*****************************************************************************/
41
42/* Local Definitions */
43
44#define CFENVFORMATSTRING "__CF_USER_TEXT_ENCODING=0x%X:0:0"
45
46union MaxMsgSize {
47	union __RequestUnion__webdavfs_load_kext_subsystem req;
48	union __ReplyUnion__webdavfs_load_kext_subsystem rep;
49};
50
51/*****************************************************************************/
52
53static int LoadKext(const char *inKextPath)
54{
55	int pid;
56	int result = -1;
57	union wait status;
58
59	pid = fork();
60	if (pid == 0)
61	{
62		char CFUserTextEncodingEnvSetting[sizeof(CFENVFORMATSTRING) + 20];
63		char *env[] = {CFUserTextEncodingEnvSetting, "", (char *) 0 };
64
65		/*
66		 * Create a new environment with a definition of __CF_USER_TEXT_ENCODING to work
67		 * around CF's interest in the user's home directory (which could be networked,
68		 * causing recursive references through automount). Make sure we include the uid
69		 * since CF will check for this when deciding if to look in the home directory.
70		 */
71		snprintf(CFUserTextEncodingEnvSetting, sizeof(CFUserTextEncodingEnvSetting), CFENVFORMATSTRING, getuid());
72
73		result = execle(KEXT_LOAD_PATH, KEXT_LOAD_PATH, inKextPath, NULL, env);
74		/* We can only get here if the exec failed */
75		_exit (errno);
76	}
77
78	if (pid == -1)
79	{
80		result = errno;
81		goto Return;
82	}
83
84	/* Success! */
85	if ((wait4(pid, (int *) &status, 0, NULL) == pid) && (WIFEXITED(status)))
86	{
87		result = status.w_retcode;
88	}
89	else
90	{
91		result = EIO;
92	}
93
94Return:
95
96	return (result);
97}
98
99/*****************************************************************************/
100
101kern_return_t do_load_kext(mach_port_t test_port __attribute__((unused)), string_t kextname)
102{
103	int error = KERN_SUCCESS;
104	struct vfsconf vfc;
105
106    if(geteuid() != 0)
107    {
108		asl_log(NULL, NULL, ASL_LEVEL_ERR, "Need to be root to load kext euid = %d!\n", geteuid());
109        return EACCES;
110    }
111
112	if (strcmp(kextname, WEBDAVFS_VFSNAME) == 0)  {
113		if (getvfsbyname(WEBDAVFS_VFSNAME, &vfc) != 0)
114			error = LoadKext(WEBDAV_KEXT_PATH);
115	} else
116	    error = ENOENT;
117
118	return error;
119
120}
121
122/*****************************************************************************/
123
124static mach_port_t checkin_or_register(const char *bname)
125{
126	kern_return_t kr;
127	mach_port_t mp;
128
129	/* If we're started by launchd or the old mach_init */
130	kr = bootstrap_check_in(bootstrap_port, (const char *)bname, &mp);
131	if (kr == KERN_SUCCESS)
132		return mp;
133	/* If not then get out */
134	exit(EXIT_FAILURE);
135}
136
137/*****************************************************************************/
138
139int main(void)
140{
141	mach_msg_size_t mxmsgsz = (mach_msg_size_t)(sizeof(union MaxMsgSize) + MAX_TRAILER_SIZE);
142	mach_port_t mp = checkin_or_register(WEBDAVFS_LOAD_KEXT_BOOTSTRAP_NAME);
143	kern_return_t kr;
144
145	kr = mach_msg_server_once(webdavfs_load_kext_server, mxmsgsz, mp, 0);
146	if (kr != KERN_SUCCESS) {
147		asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "mach_msg_server(mp): %s\n", mach_error_string(kr));
148		exit(EXIT_FAILURE);
149	}
150
151	exit(EXIT_SUCCESS);
152}
153
154/*****************************************************************************/
155