1/*
2 * Copyright (c) 2011 Apple 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 <stdio.h>
25#include <string.h>
26#include <errno.h>
27#include <sys/types.h>
28#include <unistd.h>
29
30#include <SMBClient/smbclient.h>
31#include <SMBClient/smbclient_internal.h>
32
33/*
34 * This is a bit ugly.
35 *
36 * We're doing this in a subprocess so that we run in the audit
37 * session that the kernel asked automountd to use.
38 *
39 * However, we need to be passed a Rodent Of Unusual Size, err, umm, a
40 * blob of variable size to pass to the SMBRemountServer call.  That's
41 * a bit ugly to pass on the command line, so we do it over a pipe.
42 *
43 * The first thing we read from the pipe is a big-endian 4-byte byte
44 * count.  Then we allocate a buffer and read the rest of the data
45 * into that.
46 */
47int
48main()
49{
50	ssize_t bytes_read;
51	uint32_t byte_count;
52	void *blob;
53	int child_pid;
54	int status;
55
56	/*
57	 * Read the byte count.
58	 */
59	bytes_read = read(0, &byte_count, sizeof byte_count);
60	if (bytes_read == -1) {
61		fprintf(stderr, "smbremountserver: Error reading byte count: %s\n",
62		    strerror(errno));
63		return 2;
64	}
65	if (bytes_read < 0 || (size_t)bytes_read != sizeof byte_count) {
66		fprintf(stderr, "smbremountserver: Read only %zd bytes of byte count\n",
67		    bytes_read);
68		return 2;
69	}
70
71	if (byte_count == 0) {
72		fprintf(stderr, "smbremountserver: byte count is 0\n");
73		return 2;
74	}
75
76	blob = malloc(byte_count);
77	if (blob == NULL) {
78		fprintf(stderr, "smbremountserver: Can't allocate %u bytes\n",
79		    byte_count);
80		return 2;
81	}
82
83	bytes_read = read(0, blob, byte_count);
84	if (bytes_read == -1) {
85		fprintf(stderr, "smbremountserver: Error reading blob: %s\n",
86		    strerror(errno));
87		return 2;
88	}
89	if (bytes_read < 0 || bytes_read != (ssize_t)byte_count) {
90		fprintf(stderr, "smbremountserver: Read only %zd bytes of %u-byte blob\n",
91		    bytes_read, byte_count);
92		return 2;
93	}
94
95	/*
96	 * OK, do this in a subsubprocess, so our parent can wait for us
97	 * to exit and thus reap us, without blocking waiting for
98	 * SMBRemountServer() to finish.
99	 */
100	switch ((child_pid = fork())) {
101
102	case -1:
103		/*
104		 * Fork failure.  Report an error and quit.
105		 */
106		fprintf(stderr, "smbremountserver: Cannot fork: %s\n",
107		    strerror(errno));
108		status = 2;
109		break;
110
111	case 0:
112		/*
113		 * Child.  Make the call, and quit.
114		 */
115		SMBRemountServer(blob, byte_count);
116		status = 0;
117		break;
118
119	default:
120		/*
121		 * Parent.  Just quit.
122		 */
123		status = 0;
124		break;
125	}
126
127	return status;
128}
129