Skip to content
This repository
Newer
Older
100644 265 lines (237 sloc) 8.989 kb
24678062 »
2011-03-26 LICENSE: Simplified BSD
1 /*
2 * Copyright (c) 2011, Chris Johnsen <chris_johnsen@pobox.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials
16 * provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
6d017a03 »
2011-03-24 test: runtime configurable actions
32 #include <unistd.h>
33 #include <stdlib.h>
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
34 #include <sys/errno.h>
35 #include <string.h>
36 #include <fcntl.h>
6d017a03 »
2011-03-24 test: runtime configurable actions
37 #include <dlfcn.h>
97ba1605 »
2011-03-18 SessionCreate from Security framework
38
6d017a03 »
2011-03-24 test: runtime configurable actions
39 #include "msg.h"
bd9e3a54 » lembacon
2014-06-05 test: Add diagnostic for `move-to-user=10.10`
40 #include "move_to_user_namespace.h"
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
41
d847e846 »
2011-03-29 Crank up and fix warnings
42 #define UNUSED __attribute__ ((unused))
43
564759bb »
2011-03-29 test: internal functions should be static
44 static int our_daemon(int nochdir, int noclose) {
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
45 /*
6d017a03 »
2011-03-24 test: runtime configurable actions
46 * Implementation based on description in daemon(3).
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
47 * Hmm, got pretty close.
48 * http://www.opensource.apple.com/source/Libc/Libc-594.9.4/gen/daemon-fbsd.c
49 * Theirs touches on signal handling, too. And, it does the
50 * unwanted bit about moving to the root bootstrap namespace.
51 */
52 pid_t p;
53 int fd, i;
54 if ((p = fork()) < 0) return -1;
55 if (p>0) exit(0);
56 if ((p = setsid()) < 0) return -1;
57 if (!nochdir) chdir("/");
58 if (!noclose &&
59 !((fd = open("/dev/null", O_RDWR)) < 0)) {
60 for (i = 0; i < 3; i++) { dup2(fd,i); }
61 if (fd > 2) close(fd);
62 }
63 return 0;
64 }
65
6d017a03 »
2011-03-24 test: runtime configurable actions
66 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
67 static int sys_daemon(int nocd, int nocl) { return daemon(nocd, nocl); }
68 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
69
70 static void do_daemon(const char *opt) {
71 if (!(opt && *opt))
72 die(2, "daemon requires an option (i.e. daemon=sys)");
73
74 int (*daemon_)(int,int);
75 if (!strcmp(opt,"sys"))
76 daemon_ = sys_daemon;
77 else if (!strcmp(opt, "ours"))
78 daemon_ = our_daemon;
79 else
80 die(2, "daemon: unknown option: %s", opt);
81
82 int r = daemon_(1,0);
83 if (r) die_errno(2, "%s daemon() failed = %d", opt, r);
84 }
85
86 static void show_pid(const char *opt) {
87 msg("pid: %d (%s)", getpid(), opt ? opt : "");
88 }
89
90 static void move_to_user(const char *opt) {
91 if (!(opt && *opt))
92 die(3, "move-to-user: requires an option (i.e. move-to-user=10.6)");
93
bd9e3a54 » lembacon
2014-06-05 test: Add diagnostic for `move-to-user=10.10`
94 int r;
6d017a03 »
2011-03-24 test: runtime configurable actions
95 if (!strcmp(opt, "10.5"))
bd9e3a54 » lembacon
2014-06-05 test: Add diagnostic for `move-to-user=10.10`
96 r = move_to_user_namespace(100500);
6d017a03 »
2011-03-24 test: runtime configurable actions
97 else if (!strcmp(opt, "10.6"))
bd9e3a54 » lembacon
2014-06-05 test: Add diagnostic for `move-to-user=10.10`
98 r = move_to_user_namespace(100600);
99 else if (!strcmp(opt, "10.10"))
100 r = move_to_user_namespace(101000);
6d017a03 »
2011-03-24 test: runtime configurable actions
101 else
102 die(3, "move-to-user: unkown option: %s", opt);
bd9e3a54 » lembacon
2014-06-05 test: Add diagnostic for `move-to-user=10.10`
103 if (r) die(3, "move_to_user_namespace failed");
6d017a03 »
2011-03-24 test: runtime configurable actions
104 }
105
106 typedef void *(*detach_from_console_f)(unsigned int flags);
564759bb »
2011-03-29 test: internal functions should be static
107 static void detach_from_console(const char *opt UNUSED) {
dc3687f3 »
2011-03-30 standardize static strings
108 static const char detach_fn[] = "_vprocmgr_detach_from_console";
6d017a03 »
2011-03-24 test: runtime configurable actions
109 void *f = dlsym(RTLD_NEXT, detach_fn);
110 if (!f) die(4, "unable to find %s: %s", detach_fn, dlerror());
111 if (((detach_from_console_f)f)(0) != NULL)
112 die(4, "%s failed", detach_fn);
113 }
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
114
6d017a03 »
2011-03-24 test: runtime configurable actions
115 static int out_fd;
564759bb »
2011-03-29 test: internal functions should be static
116 static void do_system(const char *opt) {
6d017a03 »
2011-03-24 test: runtime configurable actions
117 if (dup2(out_fd,1) < 0)
118 die_errno(5, "dup2(out_fd,1) failed");
119 if (dup2(out_fd,2) < 0)
120 die_errno(5, "dup2(out_fd,2) failed");
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
121
6d017a03 »
2011-03-24 test: runtime configurable actions
122 int r = system(opt);
123 if (r < 0)
124 die(5, "system() failed");
125
126 if (WIFEXITED(r))
127 msg("system(%s) process exited %d", opt, WEXITSTATUS(r));
128 else if (WIFSIGNALED(r))
129 msg("system(%s) process terminated by signal %d", opt, WTERMSIG(r));
130 else if (WIFSTOPPED(r))
131 msg("system(%s) process stopped with signal %d", opt, WSTOPSIG(r));
132 }
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
133
6d017a03 »
2011-03-24 test: runtime configurable actions
134 static int parse_int(const char *str, char **rest_,
135 char expected_stop) {
136 char *rest;
137 errno = 0;
138 int v = strtoul(str, &rest, 0);
139 if (errno)
140 die_errno(1, "error parsing \"%s\" as int", str);
141 if (rest && *rest != expected_stop)
142 die(1, "unexpected char '%c' (%d) while parsing int from \"%s\"",
143 *rest, *rest, str);
144 if (rest_) *rest_ = rest;
145 return v;
146 }
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
147
6d017a03 »
2011-03-24 test: runtime configurable actions
148 typedef int (*session_create_f)(int, int);
149 static void session_create(const char *opt) {
dc3687f3 »
2011-03-30 standardize static strings
150 static const char fw[] =
6d017a03 »
2011-03-24 test: runtime configurable actions
151 "/System/Library/Frameworks/Security.framework/Versions/Current/Security";
dc3687f3 »
2011-03-30 standardize static strings
152 static const char fn[] = "SessionCreate";
6d017a03 »
2011-03-24 test: runtime configurable actions
153 if (!(opt && *opt && strchr(opt, ',')))
154 die(6, "session-createn needs two args (e.g. 0,0)");
155 char *rest;
156 int a = parse_int(opt, &rest, ',');
157 int b = parse_int(rest+1, NULL, '\0');
158 void *lib = dlopen(fw, RTLD_LAZY|RTLD_LOCAL);
159 if (!lib)
160 die(6, "unable to load Security framework (%s): %s", fw, dlerror());
161 void *f = dlsym(lib, fn);
162 msg("calling %s(0x%x,0x%x)", fn, a, b);
163 int r = ((session_create_f)f)(a, b);
164 if (r) die(6, "%s failed: %d", fn, r);
165 if (dlclose(lib))
166 die(6, "unable to close Security framework: %s", dlerror());
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
167 /*
97ba1605 »
2011-03-18 SessionCreate from Security framework
168 OSStatus result = SessionCreate(0, 0x30);
6d017a03 »
2011-03-24 test: runtime configurable actions
169 * 0x1,0x11,0x21,0x1001,0x1011,0x1021,0x1031 -> -60501
97ba1605 »
2011-03-18 SessionCreate from Security framework
170 * (invalid attribute bits)
171 */
6d017a03 »
2011-03-24 test: runtime configurable actions
172 }
173
564759bb »
2011-03-29 test: internal functions should be static
174 static void do_sleep(const char *opt) {
6d017a03 »
2011-03-24 test: runtime configurable actions
175 int s = parse_int(opt, NULL, '\0');
176 sleep(s);
177 }
97ba1605 »
2011-03-18 SessionCreate from Security framework
178
564759bb »
2011-03-29 test: internal functions should be static
179 static void show_msg(const char *opt) {
6d017a03 »
2011-03-24 test: runtime configurable actions
180 msg("%s", opt);
181 }
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
182
07b849f1 »
2011-03-29 test: const-ize (struct cmd).func
183 typedef void cmd_func(const char *opt);
6d017a03 »
2011-03-24 test: runtime configurable actions
184 struct cmd {
07b849f1 »
2011-03-29 test: const-ize (struct cmd).func
185 cmd_func * const func;
80c176c9 »
2011-03-29 test: clean up struct cmd strings
186 const char * const str;
187 const char * const desc;
6d017a03 »
2011-03-24 test: runtime configurable actions
188 };
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
189
07b849f1 »
2011-03-29 test: const-ize (struct cmd).func
190 static cmd_func
191 show_msg, show_pid, do_sleep, do_daemon, detach_from_console,
192 do_system, move_to_user, session_create, help;
193
6d017a03 »
2011-03-24 test: runtime configurable actions
194 static struct cmd all_cmds[] = {
8f7b0afe »
2011-03-26 add usage/help
195 { show_msg, "msg", "=<text> print text to stderr" },
196 { show_pid, "pid", "=<text> print pid and text to stderr" },
197 { do_sleep, "sleep", "=<secs> sleep(secs)" },
198 { do_daemon, "daemon", "=sys system daemon(3)\n"
199 "=ours non-Apple version" },
200 { detach_from_console,
201 "detach", " _vprocmgr_detach_from_console(0)", },
202 { do_system, "system", "=<cmd> system(cmd)"},
203 { move_to_user, "move-to-user",
204 "=10.5 _vprocmgr_move_subset_to_user(uid,\"Background\")\n"
bd9e3a54 » lembacon
2014-06-05 test: Add diagnostic for `move-to-user=10.10`
205 "=10.6 call with extra arg == 0\n"
206 "=10.10 custom implementation simulating _vprocmgr_move_subset_to_user" },
8f7b0afe »
2011-03-26 add usage/help
207 { session_create, "session-create",
208 "=<a>,<b> SessionCreate(a,b) (numeric a and b)" },
209 { help, "help", " show this help text" },
210 { NULL, "", "" }
6d017a03 »
2011-03-24 test: runtime configurable actions
211 };
212
d847e846 »
2011-03-29 Crank up and fix warnings
213 static void help(const char *opt UNUSED) {
6d017a03 »
2011-03-24 test: runtime configurable actions
214 struct cmd *c = all_cmds;
8f7b0afe »
2011-03-26 add usage/help
215 int w, cmd_width = 0;
216 for (c = all_cmds; c->func; c++) {
217 w = strlen(c->str);
218 cmd_width = w > cmd_width ? w : cmd_width;
219 }
220 for (c = all_cmds; c->func; c++) {
80c176c9 »
2011-03-29 test: clean up struct cmd strings
221 const char *nl, *s = c->desc;
8f7b0afe »
2011-03-26 add usage/help
222 while ((nl = strchr(s, '\n'))) {
223 msg(" %*s%.*s", cmd_width, c->str, nl-s, s);
224 s = nl+1;
225 }
226 msg(" %*s%s", cmd_width, c->str, s);
227 }
228 }
229
230 static void run_cmd(const char *cmd) {
6d017a03 »
2011-03-24 test: runtime configurable actions
231 const char *opt = strchr(cmd, '=');
d847e846 »
2011-03-29 Crank up and fix warnings
232 size_t cmd_len = opt ? (size_t)(opt-cmd) : strlen(cmd);
6d017a03 »
2011-03-24 test: runtime configurable actions
233 if (!cmd_len)
234 die(1, "no command in argument: %s", cmd);
235 if (opt)
236 opt++;
8f7b0afe »
2011-03-26 add usage/help
237 struct cmd *c;
238 for (c = all_cmds; c->func; c++)
6d017a03 »
2011-03-24 test: runtime configurable actions
239 if (!strncmp(cmd, c->str, cmd_len) &&
99f1fe9d »
2013-03-12 Clean up warnings
240 c->str[cmd_len] == '\0') {
241 c->func(opt);
242 return;
243 }
8f7b0afe »
2011-03-26 add usage/help
244 die(1, "unknown command: %s (try help)", cmd);
6d017a03 »
2011-03-24 test: runtime configurable actions
245 }
246
247 int main(int argc, const char * const argv[]) {
248 if ((out_fd = dup(2)) < 0)
249 die_errno(1, "dup msgout");
250 FILE *out = fdopen(out_fd, "w");
251 if (!out) die_errno(1, "fdopen for msgout");
252 msgout = out;
253
8f7b0afe »
2011-03-26 add usage/help
254 if (argc < 2)
255 die(1, "usage: %s <command>...\n\n"
256 " Execute the given commands.\n"
257 " Run \"%s help\" for command list.\n",
258 argv[0], argv[0]);
6d017a03 »
2011-03-24 test: runtime configurable actions
259
8f7b0afe »
2011-03-26 add usage/help
260 const char * const * cmds = argv+1;
6d017a03 »
2011-03-24 test: runtime configurable actions
261 while(*cmds)
262 run_cmd(*cmds++);
31864a17 »
2011-03-17 Notes and code to test daemon(3) and pbpaste
263
264 return 0;
265 }
Something went wrong with that request. Please try again.