| 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 |