OLD | NEW |
| (Empty) |
1 /* Licensed to the Apache Software Foundation (ASF) under one or more | |
2 * contributor license agreements. See the NOTICE file distributed with | |
3 * this work for additional information regarding copyright ownership. | |
4 * The ASF licenses this file to You under the Apache License, Version 2.0 | |
5 * (the "License"); you may not use this file except in compliance with | |
6 * the License. You may obtain a copy of the License at | |
7 * | |
8 * http://www.apache.org/licenses/LICENSE-2.0 | |
9 * | |
10 * Unless required by applicable law or agreed to in writing, software | |
11 * distributed under the License is distributed on an "AS IS" BASIS, | |
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 * See the License for the specific language governing permissions and | |
14 * limitations under the License. | |
15 */ | |
16 | |
17 /* | |
18 * | |
19 * @author Mladen Turk | |
20 * @version $Id: proc.c 1442587 2013-02-05 13:49:48Z rjung $ | |
21 */ | |
22 | |
23 #include "tcn.h" | |
24 #include "apr_thread_proc.h" | |
25 #include "apr_version.h" | |
26 | |
27 #define ERRFN_USERDATA_KEY "TCNATIVECHILDERRFN" | |
28 | |
29 static void generic_child_errfn(apr_pool_t *pool, apr_status_t err, | |
30 const char *description) | |
31 { | |
32 void *data; | |
33 tcn_callback_t *cb; | |
34 | |
35 apr_pool_userdata_get(&data, ERRFN_USERDATA_KEY, pool); | |
36 cb = (tcn_callback_t *)data; | |
37 if (cb) { | |
38 JNIEnv *env; | |
39 tcn_get_java_env(&env); | |
40 if (!TCN_IS_NULL(env, cb->obj)) { | |
41 (*(env))->CallVoidMethod(env, cb->obj, cb->mid[0], | |
42 P2J(pool), (jint)err, | |
43 (*(env))->NewStringUTF(env, description), | |
44 NULL); | |
45 } | |
46 } | |
47 } | |
48 | |
49 static apr_status_t child_errfn_pool_cleanup(void *data) | |
50 { | |
51 tcn_callback_t *cb = (tcn_callback_t *)data; | |
52 | |
53 if (data) { | |
54 JNIEnv *env; | |
55 tcn_get_java_env(&env); | |
56 if (!TCN_IS_NULL(env, cb->obj)) { | |
57 TCN_UNLOAD_CLASS(env, cb->obj); | |
58 } | |
59 free(cb); | |
60 } | |
61 return APR_SUCCESS; | |
62 } | |
63 | |
64 TCN_IMPLEMENT_CALL(jlong, Procattr, create)(TCN_STDARGS, | |
65 jlong pool) | |
66 { | |
67 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
68 apr_procattr_t *attr; | |
69 | |
70 | |
71 UNREFERENCED(o); | |
72 TCN_THROW_IF_ERR(apr_procattr_create(&attr, p), attr); | |
73 | |
74 cleanup: | |
75 return P2J(attr); | |
76 } | |
77 | |
78 TCN_IMPLEMENT_CALL(jint, Procattr, ioSet)(TCN_STDARGS, | |
79 jlong attr, jint in, | |
80 jint out, jint err) | |
81 { | |
82 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
83 | |
84 UNREFERENCED_STDARGS; | |
85 return (jint)apr_procattr_io_set(a, (apr_int32_t)in, | |
86 (apr_int32_t)out, (apr_int32_t)err); | |
87 } | |
88 | |
89 TCN_IMPLEMENT_CALL(jint, Procattr, childInSet)(TCN_STDARGS, | |
90 jlong attr, jlong in, | |
91 jlong parent) | |
92 { | |
93 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
94 apr_file_t *f = J2P(in, apr_file_t *); | |
95 apr_file_t *p = J2P(parent, apr_file_t *); | |
96 | |
97 UNREFERENCED_STDARGS; | |
98 return (jint)apr_procattr_child_in_set(a, f, p); | |
99 } | |
100 | |
101 TCN_IMPLEMENT_CALL(jint, Procattr, childOutSet)(TCN_STDARGS, | |
102 jlong attr, jlong out, | |
103 jlong parent) | |
104 { | |
105 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
106 apr_file_t *f = J2P(out, apr_file_t *); | |
107 apr_file_t *p = J2P(parent, apr_file_t *); | |
108 | |
109 UNREFERENCED_STDARGS; | |
110 return (jint)apr_procattr_child_out_set(a, f, p); | |
111 } | |
112 | |
113 TCN_IMPLEMENT_CALL(jint, Procattr, childErrSet)(TCN_STDARGS, | |
114 jlong attr, jlong err, | |
115 jlong parent) | |
116 { | |
117 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
118 apr_file_t *f = J2P(err, apr_file_t *); | |
119 apr_file_t *p = J2P(parent, apr_file_t *); | |
120 | |
121 UNREFERENCED_STDARGS; | |
122 return (jint)apr_procattr_child_in_set(a, f, p); | |
123 } | |
124 | |
125 TCN_IMPLEMENT_CALL(jint, Procattr, dirSet)(TCN_STDARGS, | |
126 jlong attr, | |
127 jstring dir) | |
128 { | |
129 apr_status_t rv; | |
130 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
131 TCN_ALLOC_CSTRING(dir); | |
132 | |
133 UNREFERENCED(o); | |
134 | |
135 rv = apr_procattr_dir_set(a, J2S(dir)); | |
136 TCN_FREE_CSTRING(dir); | |
137 return (jint) rv; | |
138 } | |
139 | |
140 TCN_IMPLEMENT_CALL(jint, Procattr, cmdtypeSet)(TCN_STDARGS, | |
141 jlong attr, jint cmd) | |
142 { | |
143 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
144 | |
145 UNREFERENCED_STDARGS; | |
146 return (jint)apr_procattr_cmdtype_set(a, (apr_int32_t)cmd); | |
147 } | |
148 | |
149 TCN_IMPLEMENT_CALL(jint, Procattr, detachSet)(TCN_STDARGS, | |
150 jlong attr, jint detach) | |
151 { | |
152 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
153 | |
154 UNREFERENCED_STDARGS; | |
155 return (jint)apr_procattr_detach_set(a, (apr_int32_t)detach); | |
156 } | |
157 | |
158 TCN_IMPLEMENT_CALL(jint, Procattr, errorCheckSet)(TCN_STDARGS, | |
159 jlong attr, jint chk) | |
160 { | |
161 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
162 | |
163 UNREFERENCED_STDARGS; | |
164 return (jint)apr_procattr_error_check_set(a, (apr_int32_t)chk); | |
165 } | |
166 | |
167 TCN_IMPLEMENT_CALL(jint, Procattr, addrspaceSet)(TCN_STDARGS, | |
168 jlong attr, jint addr) | |
169 { | |
170 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
171 | |
172 UNREFERENCED_STDARGS; | |
173 return (jint)apr_procattr_addrspace_set(a, (apr_int32_t)addr); | |
174 } | |
175 | |
176 TCN_IMPLEMENT_CALL(jlong, Proc, alloc)(TCN_STDARGS, | |
177 jlong pool) | |
178 { | |
179 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
180 apr_proc_t *proc; | |
181 | |
182 UNREFERENCED_STDARGS; | |
183 proc = (apr_proc_t *)apr_pcalloc(p, sizeof(apr_proc_t)); | |
184 | |
185 return P2J(proc); | |
186 } | |
187 | |
188 #define MAX_ARGS_SIZE 1024 | |
189 #define MAX_ENV_SIZE 1024 | |
190 | |
191 TCN_IMPLEMENT_CALL(jint, Proc, create)(TCN_STDARGS, jlong proc, | |
192 jstring progname, | |
193 jobjectArray args, | |
194 jobjectArray env, | |
195 jlong attr, jlong pool) | |
196 { | |
197 apr_status_t rv; | |
198 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
199 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
200 apr_proc_t *np = J2P(proc, apr_proc_t *); | |
201 TCN_ALLOC_CSTRING(progname); | |
202 char *s_args[MAX_ARGS_SIZE]; | |
203 char *s_env[MAX_ENV_SIZE]; | |
204 const char * const *pargs = NULL; | |
205 const char * const *penv = NULL; | |
206 jsize as = 0; | |
207 jsize es = 0; | |
208 jsize i; | |
209 | |
210 UNREFERENCED(o); | |
211 if (args) | |
212 as = (*e)->GetArrayLength(e, args); | |
213 if (env) | |
214 es = (*e)->GetArrayLength(e, env); | |
215 if (as > (MAX_ARGS_SIZE - 1) || es > (MAX_ENV_SIZE - 2)) { | |
216 TCN_FREE_CSTRING(progname); | |
217 return APR_EINVAL; | |
218 } | |
219 if (as) { | |
220 for (i = 0; i < as; i++) { | |
221 jstring str = (*e)->GetObjectArrayElement(e, args, i); | |
222 s_args[i] = tcn_get_string(e, str); | |
223 (*e)->DeleteLocalRef(e, str); | |
224 } | |
225 s_args[i] = NULL; | |
226 pargs = (const char * const *)&s_args[0]; | |
227 } | |
228 if (es) { | |
229 for (i = 0; i < es; i++) { | |
230 jstring str = (*e)->GetObjectArrayElement(e, env, i); | |
231 s_env[i] = tcn_get_string(e, str); | |
232 (*e)->DeleteLocalRef(e, str); | |
233 } | |
234 #ifdef WIN32 | |
235 s_env[i++] = apr_psprintf(p, TCN_PARENT_IDE "=%d", getpid()); | |
236 #endif | |
237 s_env[i] = NULL; | |
238 penv = (const char * const *)&s_env[0]; | |
239 } | |
240 #ifdef WIN32 | |
241 else { | |
242 char pps[32]; | |
243 itoa(getpid(), pps, 10); | |
244 SetEnvironmentVariable(TCN_PARENT_IDE, pps); | |
245 } | |
246 #endif | |
247 rv = apr_proc_create(np, J2S(progname), pargs, | |
248 penv, a, p); | |
249 #ifdef WIN32 | |
250 if (!es) | |
251 SetEnvironmentVariable(TCN_PARENT_IDE, NULL); | |
252 #endif | |
253 | |
254 /* Free local resources */ | |
255 TCN_FREE_CSTRING(progname); | |
256 for (i = 0; i < as; i++) { | |
257 if (s_args[i]) | |
258 free(s_args[i]); | |
259 } | |
260 for (i = 0; i < es; i++) { | |
261 if (s_env[i]) | |
262 free(s_env[i]); | |
263 } | |
264 return rv; | |
265 } | |
266 | |
267 TCN_IMPLEMENT_CALL(jint, Proc, wait)(TCN_STDARGS, jlong proc, | |
268 jintArray rvals, jint waithow) | |
269 { | |
270 apr_status_t rv; | |
271 apr_proc_t *p = J2P(proc, apr_proc_t *); | |
272 int exitcode; | |
273 apr_exit_why_e exitwhy; | |
274 | |
275 UNREFERENCED(o); | |
276 | |
277 rv = apr_proc_wait(p, &exitcode, &exitwhy, (apr_wait_how_e)waithow); | |
278 if (rv == APR_SUCCESS && rvals) { | |
279 jsize n = (*e)->GetArrayLength(e, rvals); | |
280 if (n > 1) { | |
281 jint *ints = (*e)->GetIntArrayElements(e, rvals, NULL); | |
282 ints[0] = exitcode; | |
283 ints[1] = exitwhy; | |
284 (*e)->ReleaseIntArrayElements(e, rvals, ints, 0); | |
285 } | |
286 } | |
287 return rv; | |
288 } | |
289 | |
290 TCN_IMPLEMENT_CALL(jint, Proc, waitAllProcs)(TCN_STDARGS, | |
291 jlong proc, jintArray rvals, | |
292 jint waithow, jlong pool) | |
293 { | |
294 apr_status_t rv; | |
295 apr_proc_t *p = J2P(proc, apr_proc_t *); | |
296 apr_pool_t *c = J2P(pool, apr_pool_t *); | |
297 int exitcode; | |
298 apr_exit_why_e exitwhy; | |
299 | |
300 UNREFERENCED(o); | |
301 | |
302 rv = apr_proc_wait_all_procs(p, &exitcode, &exitwhy, | |
303 (apr_wait_how_e)waithow, c); | |
304 if (rv == APR_SUCCESS && rvals) { | |
305 jsize n = (*e)->GetArrayLength(e, rvals); | |
306 if (n > 1) { | |
307 jint *ints = (*e)->GetIntArrayElements(e, rvals, NULL); | |
308 ints[0] = exitcode; | |
309 ints[1] = exitwhy; | |
310 (*e)->ReleaseIntArrayElements(e, rvals, ints, 0); | |
311 } | |
312 } | |
313 return rv; | |
314 } | |
315 | |
316 TCN_IMPLEMENT_CALL(jint, Proc, detach)(TCN_STDARGS, jint daemonize) | |
317 { | |
318 | |
319 UNREFERENCED_STDARGS; | |
320 #if defined(WIN32) || defined (NETWARE) | |
321 UNREFERENCED(daemonize); | |
322 return APR_ENOTIMPL; | |
323 #else | |
324 return (jint)apr_proc_detach(daemonize); | |
325 #endif | |
326 } | |
327 | |
328 TCN_IMPLEMENT_CALL(jint, Proc, kill)(TCN_STDARGS, jlong proc, jint sig) | |
329 { | |
330 apr_proc_t *p = J2P(proc, apr_proc_t *); | |
331 | |
332 UNREFERENCED_STDARGS; | |
333 return (jint)apr_proc_kill(p, (int)sig); | |
334 } | |
335 | |
336 TCN_IMPLEMENT_CALL(void, Pool, noteSubprocess)(TCN_STDARGS, jlong pool, | |
337 jlong proc, jint how) | |
338 { | |
339 apr_proc_t *p = J2P(proc, apr_proc_t *); | |
340 apr_pool_t *a = J2P(pool, apr_pool_t *); | |
341 | |
342 UNREFERENCED_STDARGS; | |
343 apr_pool_note_subprocess(a, p, (apr_kill_conditions_e)how); | |
344 } | |
345 | |
346 TCN_IMPLEMENT_CALL(jint, Proc, fork)(TCN_STDARGS, | |
347 jlongArray proc, | |
348 jlong pool) | |
349 { | |
350 apr_status_t rv = APR_EINVAL; | |
351 | |
352 #if APR_HAS_FORK | |
353 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
354 apr_proc_t *f = apr_pcalloc(p, sizeof(apr_proc_t)); | |
355 | |
356 UNREFERENCED(o); | |
357 | |
358 rv = apr_proc_fork(f, p); | |
359 if (rv == APR_SUCCESS && proc) { | |
360 jsize n = (*e)->GetArrayLength(e, proc); | |
361 if (n > 0) { | |
362 jlong *rp = (*e)->GetLongArrayElements(e, proc, NULL); | |
363 rp[0] = P2J(f); | |
364 (*e)->ReleaseLongArrayElements(e, proc, rp, 0); | |
365 } | |
366 } | |
367 #else | |
368 UNREFERENCED_STDARGS; | |
369 UNREFERENCED(proc); | |
370 UNREFERENCED(pool); | |
371 | |
372 #endif | |
373 return rv; | |
374 } | |
375 | |
376 TCN_IMPLEMENT_CALL(void, Procattr, errfnSet)(TCN_STDARGS, jlong attr, | |
377 jlong pool, jobject obj) | |
378 { | |
379 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
380 apr_pool_t *p = J2P(pool, apr_pool_t *); | |
381 tcn_callback_t *cb = (tcn_callback_t *)malloc(sizeof(tcn_callback_t)); | |
382 jclass cls; | |
383 | |
384 UNREFERENCED(o); | |
385 | |
386 if (cb == NULL) { | |
387 return; | |
388 } | |
389 cls = (*e)->GetObjectClass(e, obj); | |
390 cb->obj = (*e)->NewGlobalRef(e, obj); | |
391 cb->mid[0] = (*e)->GetMethodID(e, cls, "callback", "(JILjava/lang/String;)V"
); | |
392 | |
393 apr_pool_userdata_setn(cb, ERRFN_USERDATA_KEY, child_errfn_pool_cleanup, p); | |
394 apr_procattr_child_errfn_set(a, generic_child_errfn); | |
395 | |
396 } | |
397 | |
398 TCN_IMPLEMENT_CALL(jint, Procattr, userSet)(TCN_STDARGS, | |
399 jlong attr, | |
400 jstring username, | |
401 jstring password) | |
402 { | |
403 | |
404 #if ((APR_MAJOR_VERSION >= 1) && (APR_MINOR_VERSION >= 1)) | |
405 apr_status_t rv; | |
406 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
407 TCN_ALLOC_CSTRING(username); | |
408 #if APR_PROCATTR_USER_SET_REQUIRES_PASSWORD | |
409 TCN_ALLOC_CSTRING(password); | |
410 #else | |
411 const char *cpassword = NULL; | |
412 #endif | |
413 UNREFERENCED(o); | |
414 | |
415 rv = apr_procattr_user_set(a, J2S(username), J2S(password)); | |
416 TCN_FREE_CSTRING(username); | |
417 #if APR_PROCATTR_USER_SET_REQUIRES_PASSWORD | |
418 TCN_FREE_CSTRING(password); | |
419 #endif | |
420 return (jint) rv; | |
421 #else | |
422 UNREFERENCED_STDARGS; | |
423 UNREFERENCED(attr); | |
424 UNREFERENCED(username); | |
425 UNREFERENCED(password); | |
426 | |
427 return APR_ENOTIMPL; | |
428 #endif | |
429 } | |
430 | |
431 TCN_IMPLEMENT_CALL(jint, Procattr, groupSet)(TCN_STDARGS, | |
432 jlong attr, | |
433 jstring group) | |
434 { | |
435 | |
436 #if ((APR_MAJOR_VERSION >= 1) && (APR_MINOR_VERSION >= 1)) | |
437 apr_status_t rv; | |
438 apr_procattr_t *a = J2P(attr, apr_procattr_t *); | |
439 TCN_ALLOC_CSTRING(group); | |
440 | |
441 UNREFERENCED(o); | |
442 | |
443 rv = apr_procattr_group_set(a, J2S(group)); | |
444 TCN_FREE_CSTRING(group); | |
445 return (jint) rv; | |
446 #else | |
447 UNREFERENCED_STDARGS; | |
448 UNREFERENCED(attr); | |
449 UNREFERENCED(group); | |
450 | |
451 return APR_ENOTIMPL; | |
452 #endif | |
453 } | |
OLD | NEW |