213
214 static void*
215 xmalloc(JNIEnv *env, size_t size)
216 {
217 void *p = malloc(size);
218 if (p == NULL)
219 JNU_ThrowOutOfMemoryError(env, NULL);
220 return p;
221 }
222
223 #define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
224
225 /**
226 * If PATH is not defined, the OS provides some default value.
227 * Unfortunately, there's no portable way to get this value.
228 * Fortunately, it's only needed if the child has PATH while we do not.
229 */
230 static const char*
231 defaultPath(void)
232 {
233 #ifdef __solaris__
234 /* These really are the Solaris defaults! */
235 return (geteuid() == 0 || getuid() == 0) ?
236 "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
237 "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:";
238 #else
239 return ":/bin:/usr/bin"; /* glibc */
240 #endif
241 }
242
243 static const char*
244 effectivePath(void)
245 {
246 const char *s = getenv("PATH");
247 return (s != NULL) ? s : defaultPath();
248 }
249
250 static int
251 countOccurrences(const char *s, char c)
252 {
253 int count;
254 for (count = 0; *s != '\0'; s++)
255 count += (*s == c);
256 return count;
257 }
258
259 static const char * const *
260 effectivePathv(JNIEnv *env)
435 return offset;
436 }
437 for (p=buf+offset, a=arg; *a != 0; a++) {
438 int len = strlen(*a) +1;
439 memcpy(p, *a, len);
440 p += len;
441 count += len;
442 }
443 return offset+count;
444 }
445
446 /**
447 * We are unusually paranoid; use of vfork is
448 * especially likely to tickle gcc/glibc bugs.
449 */
450 #ifdef __attribute_noinline__ /* See: sys/cdefs.h */
451 __attribute_noinline__
452 #endif
453
454 /* vfork(2) is deprecated on Solaris */
455 #ifndef __solaris__
456 static pid_t
457 vforkChild(ChildStuff *c) {
458 volatile pid_t resultPid;
459
460 /*
461 * We separate the call to vfork into a separate function to make
462 * very sure to keep stack of child from corrupting stack of parent,
463 * as suggested by the scary gcc warning:
464 * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
465 */
466 resultPid = vfork();
467
468 if (resultPid == 0) {
469 childProcess(c);
470 }
471 assert(resultPid != 0); /* childProcess never returns */
472 return resultPid;
473 }
474 #endif
475
476 static pid_t
477 forkChild(ChildStuff *c) {
478 pid_t resultPid;
479
480 /*
481 * From Solaris fork(2): In Solaris 10, a call to fork() is
482 * identical to a call to fork1(); only the calling thread is
483 * replicated in the child process. This is the POSIX-specified
484 * behavior for fork().
485 */
486 resultPid = fork();
487
488 if (resultPid == 0) {
489 childProcess(c);
490 }
491 assert(resultPid != 0); /* childProcess never returns */
492 return resultPid;
493 }
494
566 write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
567 write(c->childenv[1], (char *)c, sizeof(*c));
568 write(c->childenv[1], (char *)&sp, sizeof(sp));
569 write(c->childenv[1], buf, bufsize);
570 free(buf);
571
572 /* In this mode an external main() in invoked which calls back into
573 * childProcess() in this file, rather than directly
574 * via the statement below */
575 return resultPid;
576 }
577
578 /*
579 * Start a child process running function childProcess.
580 * This function only returns in the parent.
581 */
582 static pid_t
583 startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
584 switch (c->mode) {
585 /* vfork(2) is deprecated on Solaris */
586 #ifndef __solaris__
587 case MODE_VFORK:
588 return vforkChild(c);
589 #endif
590 case MODE_FORK:
591 return forkChild(c);
592 case MODE_POSIX_SPAWN:
593 return spawnChild(env, process, c, helperpath);
594 default:
595 return -1;
596 }
597 }
598
599 JNIEXPORT jint JNICALL
600 Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
601 jobject process,
602 jint mode,
603 jbyteArray helperpath,
604 jbyteArray prog,
605 jbyteArray argBlock, jint argc,
606 jbyteArray envBlock, jint envc,
607 jbyteArray dir,
608 jintArray std_fds,
609 jboolean redirectErrorStream)
|
213
214 static void*
215 xmalloc(JNIEnv *env, size_t size)
216 {
217 void *p = malloc(size);
218 if (p == NULL)
219 JNU_ThrowOutOfMemoryError(env, NULL);
220 return p;
221 }
222
223 #define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
224
225 /**
226 * If PATH is not defined, the OS provides some default value.
227 * Unfortunately, there's no portable way to get this value.
228 * Fortunately, it's only needed if the child has PATH while we do not.
229 */
230 static const char*
231 defaultPath(void)
232 {
233 return ":/bin:/usr/bin";
234 }
235
236 static const char*
237 effectivePath(void)
238 {
239 const char *s = getenv("PATH");
240 return (s != NULL) ? s : defaultPath();
241 }
242
243 static int
244 countOccurrences(const char *s, char c)
245 {
246 int count;
247 for (count = 0; *s != '\0'; s++)
248 count += (*s == c);
249 return count;
250 }
251
252 static const char * const *
253 effectivePathv(JNIEnv *env)
428 return offset;
429 }
430 for (p=buf+offset, a=arg; *a != 0; a++) {
431 int len = strlen(*a) +1;
432 memcpy(p, *a, len);
433 p += len;
434 count += len;
435 }
436 return offset+count;
437 }
438
439 /**
440 * We are unusually paranoid; use of vfork is
441 * especially likely to tickle gcc/glibc bugs.
442 */
443 #ifdef __attribute_noinline__ /* See: sys/cdefs.h */
444 __attribute_noinline__
445 #endif
446
447 /* vfork(2) is deprecated on Solaris */
448 static pid_t
449 vforkChild(ChildStuff *c) {
450 volatile pid_t resultPid;
451
452 /*
453 * We separate the call to vfork into a separate function to make
454 * very sure to keep stack of child from corrupting stack of parent,
455 * as suggested by the scary gcc warning:
456 * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
457 */
458 resultPid = vfork();
459
460 if (resultPid == 0) {
461 childProcess(c);
462 }
463 assert(resultPid != 0); /* childProcess never returns */
464 return resultPid;
465 }
466
467 static pid_t
468 forkChild(ChildStuff *c) {
469 pid_t resultPid;
470
471 /*
472 * From Solaris fork(2): In Solaris 10, a call to fork() is
473 * identical to a call to fork1(); only the calling thread is
474 * replicated in the child process. This is the POSIX-specified
475 * behavior for fork().
476 */
477 resultPid = fork();
478
479 if (resultPid == 0) {
480 childProcess(c);
481 }
482 assert(resultPid != 0); /* childProcess never returns */
483 return resultPid;
484 }
485
557 write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
558 write(c->childenv[1], (char *)c, sizeof(*c));
559 write(c->childenv[1], (char *)&sp, sizeof(sp));
560 write(c->childenv[1], buf, bufsize);
561 free(buf);
562
563 /* In this mode an external main() in invoked which calls back into
564 * childProcess() in this file, rather than directly
565 * via the statement below */
566 return resultPid;
567 }
568
569 /*
570 * Start a child process running function childProcess.
571 * This function only returns in the parent.
572 */
573 static pid_t
574 startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
575 switch (c->mode) {
576 /* vfork(2) is deprecated on Solaris */
577 case MODE_VFORK:
578 return vforkChild(c);
579 case MODE_FORK:
580 return forkChild(c);
581 case MODE_POSIX_SPAWN:
582 return spawnChild(env, process, c, helperpath);
583 default:
584 return -1;
585 }
586 }
587
588 JNIEXPORT jint JNICALL
589 Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
590 jobject process,
591 jint mode,
592 jbyteArray helperpath,
593 jbyteArray prog,
594 jbyteArray argBlock, jint argc,
595 jbyteArray envBlock, jint envc,
596 jbyteArray dir,
597 jintArray std_fds,
598 jboolean redirectErrorStream)
|