300 void |
294 void |
301 CreateExecutionEnvironment(int *pargc, char ***pargv, |
295 CreateExecutionEnvironment(int *pargc, char ***pargv, |
302 char jrepath[], jint so_jrepath, |
296 char jrepath[], jint so_jrepath, |
303 char jvmpath[], jint so_jvmpath, |
297 char jvmpath[], jint so_jvmpath, |
304 char jvmcfg[], jint so_jvmcfg) { |
298 char jvmcfg[], jint so_jvmcfg) { |
305 /* |
299 |
306 * First, determine if we are running the desired data model. If we |
300 char * jvmtype = NULL; |
307 * are running the desired data model, all the error messages |
301 int argc = *pargc; |
308 * associated with calling GetJREPath, ReadKnownVMs, etc. should be |
302 char **argv = *pargv; |
309 * output, otherwise we simply exit with an error, as we no longer |
303 |
310 * support dual data models. |
304 #ifdef SETENV_REQUIRED |
311 */ |
305 jboolean mustsetenv = JNI_FALSE; |
312 jboolean jvmpathExists; |
306 char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */ |
|
307 char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */ |
|
308 char* newpath = NULL; /* path on new LD_LIBRARY_PATH */ |
|
309 char* lastslash = NULL; |
|
310 char** newenvp = NULL; /* current environment */ |
|
311 size_t new_runpath_size; |
|
312 #endif /* SETENV_REQUIRED */ |
313 |
313 |
314 /* Compute/set the name of the executable */ |
314 /* Compute/set the name of the executable */ |
315 SetExecname(*pargv); |
315 SetExecname(*pargv); |
316 |
316 |
317 /* Check data model flags, and exec process, if needed */ |
317 /* Check to see if the jvmpath exists */ |
318 { |
318 /* Find out where the JRE is that we will be using. */ |
319 char * jvmtype = NULL; |
319 if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE)) { |
320 int argc = *pargc; |
320 JLI_ReportErrorMessage(JRE_ERROR1); |
321 char **argv = *pargv; |
321 exit(2); |
322 int running = CURRENT_DATA_MODEL; |
322 } |
323 /* |
323 JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%sjvm.cfg", |
324 * As of jdk9, there is no support for dual mode operations, however |
324 jrepath, FILESEP, FILESEP); |
325 * for legacy error reporting purposes and until -d options are supported |
325 /* Find the specified JVM type */ |
326 * we need this. |
326 if (ReadKnownVMs(jvmcfg, JNI_FALSE) < 1) { |
327 */ |
327 JLI_ReportErrorMessage(CFG_ERROR7); |
328 int wanted = running; |
328 exit(1); |
|
329 } |
|
330 |
|
331 jvmpath[0] = '\0'; |
|
332 jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE); |
|
333 if (JLI_StrCmp(jvmtype, "ERROR") == 0) { |
|
334 JLI_ReportErrorMessage(CFG_ERROR9); |
|
335 exit(4); |
|
336 } |
|
337 |
|
338 if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) { |
|
339 JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath); |
|
340 exit(4); |
|
341 } |
|
342 /* |
|
343 * we seem to have everything we need, so without further ado |
|
344 * we return back, otherwise proceed to set the environment. |
|
345 */ |
329 #ifdef SETENV_REQUIRED |
346 #ifdef SETENV_REQUIRED |
330 jboolean mustsetenv = JNI_FALSE; |
347 mustsetenv = RequiresSetenv(jvmpath); |
331 char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */ |
348 JLI_TraceLauncher("mustsetenv: %s\n", mustsetenv ? "TRUE" : "FALSE"); |
332 char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */ |
349 |
333 char* newpath = NULL; /* path on new LD_LIBRARY_PATH */ |
350 if (mustsetenv == JNI_FALSE) { |
334 char* lastslash = NULL; |
351 return; |
335 char** newenvp = NULL; /* current environment */ |
352 } |
336 size_t new_runpath_size; |
353 #else |
337 #ifdef __solaris__ |
354 return; |
338 char* dmpath = NULL; /* data model specific LD_LIBRARY_PATH, |
355 #endif /* SETENV_REQUIRED */ |
339 Solaris only */ |
356 |
340 #endif /* __solaris__ */ |
357 #ifdef SETENV_REQUIRED |
341 #endif /* SETENV_REQUIRED */ |
358 if (mustsetenv) { |
342 |
|
343 char** newargv = NULL; |
|
344 int newargc = 0; |
|
345 |
|
346 /* |
|
347 * Starting in 1.5, all unix platforms accept the -d32 and -d64 |
|
348 * options. On platforms where only one data-model is supported |
|
349 * (e.g. ia-64 Linux), using the flag for the other data model is |
|
350 * an error and will terminate the program. |
|
351 */ |
|
352 |
|
353 { /* open new scope to declare local variables */ |
|
354 int i; |
|
355 |
|
356 newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(char*)); |
|
357 newargv[newargc++] = argv[0]; |
|
358 |
|
359 /* scan for data model arguments and remove from argument list; |
|
360 last occurrence determines desired data model */ |
|
361 for (i=1; i < argc; i++) { |
|
362 |
|
363 if (JLI_StrCmp(argv[i], "-J-d64") == 0 || JLI_StrCmp(argv[i], "-d64") == 0) { |
|
364 wanted = 64; |
|
365 continue; |
|
366 } |
|
367 if (JLI_StrCmp(argv[i], "-J-d32") == 0 || JLI_StrCmp(argv[i], "-d32") == 0) { |
|
368 wanted = 32; |
|
369 continue; |
|
370 } |
|
371 newargv[newargc++] = argv[i]; |
|
372 |
|
373 if (IsJavaArgs()) { |
|
374 if (argv[i][0] != '-') continue; |
|
375 } else { |
|
376 if (JLI_StrCmp(argv[i], "-classpath") == 0 || JLI_StrCmp(argv[i], "-cp") == 0) { |
|
377 i++; |
|
378 if (i >= argc) break; |
|
379 newargv[newargc++] = argv[i]; |
|
380 continue; |
|
381 } |
|
382 if (argv[i][0] != '-') { i++; break; } |
|
383 } |
|
384 } |
|
385 |
|
386 /* copy rest of args [i .. argc) */ |
|
387 while (i < argc) { |
|
388 newargv[newargc++] = argv[i++]; |
|
389 } |
|
390 newargv[newargc] = NULL; |
|
391 |
|
392 /* |
359 /* |
393 * newargv has all proper arguments here |
360 * We will set the LD_LIBRARY_PATH as follows: |
|
361 * |
|
362 * o $JVMPATH (directory portion only) |
|
363 * o $JRE/lib |
|
364 * o $JRE/../lib |
|
365 * |
|
366 * followed by the user's previous effective LD_LIBRARY_PATH, if |
|
367 * any. |
394 */ |
368 */ |
395 |
369 |
396 argc = newargc; |
370 runpath = getenv(LD_LIBRARY_PATH); |
397 argv = newargv; |
371 |
398 } |
372 /* runpath contains current effective LD_LIBRARY_PATH setting */ |
399 |
373 { /* New scope to declare local variable */ |
400 /* If the data model is not changing, it is an error if the |
374 char *new_jvmpath = JLI_StringDup(jvmpath); |
401 jvmpath does not exist */ |
375 new_runpath_size = ((runpath != NULL) ? JLI_StrLen(runpath) : 0) + |
402 if (wanted == running) { |
376 2 * JLI_StrLen(jrepath) + |
403 /* Find out where the JRE is that we will be using. */ |
377 #ifdef AIX |
404 if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE) ) { |
378 /* On AIX we additionally need 'jli' in the path because ld doesn't support $ORIGIN. */ |
405 JLI_ReportErrorMessage(JRE_ERROR1); |
379 JLI_StrLen(jrepath) + JLI_StrLen("/lib//jli:") + |
406 exit(2); |
380 #endif |
407 } |
381 JLI_StrLen(new_jvmpath) + 52; |
408 JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%sjvm.cfg", |
382 new_runpath = JLI_MemAlloc(new_runpath_size); |
409 jrepath, FILESEP, FILESEP, FILESEP); |
383 newpath = new_runpath + JLI_StrLen(LD_LIBRARY_PATH "="); |
410 /* Find the specified JVM type */ |
384 |
411 if (ReadKnownVMs(jvmcfg, JNI_FALSE) < 1) { |
385 |
412 JLI_ReportErrorMessage(CFG_ERROR7); |
|
413 exit(1); |
|
414 } |
|
415 |
|
416 jvmpath[0] = '\0'; |
|
417 jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE); |
|
418 if (JLI_StrCmp(jvmtype, "ERROR") == 0) { |
|
419 JLI_ReportErrorMessage(CFG_ERROR9); |
|
420 exit(4); |
|
421 } |
|
422 |
|
423 if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, 0 )) { |
|
424 JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath); |
|
425 exit(4); |
|
426 } |
|
427 /* |
|
428 * we seem to have everything we need, so without further ado |
|
429 * we return back, otherwise proceed to set the environment. |
|
430 */ |
|
431 #ifdef SETENV_REQUIRED |
|
432 mustsetenv = RequiresSetenv(jvmpath); |
|
433 JLI_TraceLauncher("mustsetenv: %s\n", mustsetenv ? "TRUE" : "FALSE"); |
|
434 |
|
435 if (mustsetenv == JNI_FALSE) { |
|
436 JLI_MemFree(newargv); |
|
437 return; |
|
438 } |
|
439 #else |
|
440 JLI_MemFree(newargv); |
|
441 return; |
|
442 #endif /* SETENV_REQUIRED */ |
|
443 } else { /* do the same speculatively or exit */ |
|
444 JLI_ReportErrorMessage(JRE_ERROR2, wanted); |
|
445 exit(1); |
|
446 } |
|
447 #ifdef SETENV_REQUIRED |
|
448 if (mustsetenv) { |
|
449 /* |
386 /* |
450 * We will set the LD_LIBRARY_PATH as follows: |
387 * Create desired LD_LIBRARY_PATH value for target data model. |
451 * |
|
452 * o $JVMPATH (directory portion only) |
|
453 * o $JRE/lib |
|
454 * o $JRE/../lib |
|
455 * |
|
456 * followed by the user's previous effective LD_LIBRARY_PATH, if |
|
457 * any. |
|
458 */ |
388 */ |
459 |
389 { |
460 #ifdef __solaris__ |
|
461 /* |
|
462 * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH |
|
463 * variables: |
|
464 * |
|
465 * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if |
|
466 * data-model specific variables are not set. |
|
467 * |
|
468 * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH |
|
469 * for 64-bit binaries. |
|
470 * The vm uses LD_LIBRARY_PATH to set the java.library.path system |
|
471 * property. To shield the vm from the complication of multiple |
|
472 * LD_LIBRARY_PATH variables, if the appropriate data model |
|
473 * specific variable is set, we will act as if LD_LIBRARY_PATH had |
|
474 * the value of the data model specific variant and the data model |
|
475 * specific variant will be unset. Note that the variable for the |
|
476 * *wanted* data model must be used (if it is set), not simply the |
|
477 * current running data model. |
|
478 */ |
|
479 |
|
480 switch (wanted) { |
|
481 case 0: |
|
482 case 64: |
|
483 dmpath = getenv("LD_LIBRARY_PATH_64"); |
|
484 wanted = 64; |
|
485 break; |
|
486 |
|
487 default: |
|
488 JLI_ReportErrorMessage(JRE_ERROR3, __LINE__); |
|
489 exit(1); /* unknown value in wanted */ |
|
490 break; |
|
491 } |
|
492 |
|
493 /* |
|
494 * If dmpath is NULL, the relevant data model specific variable is |
|
495 * not set and normal LD_LIBRARY_PATH should be used. |
|
496 */ |
|
497 if (dmpath == NULL) { |
|
498 runpath = getenv("LD_LIBRARY_PATH"); |
|
499 } else { |
|
500 runpath = dmpath; |
|
501 } |
|
502 #else /* ! __solaris__ */ |
|
503 /* |
|
504 * If not on Solaris, assume only a single LD_LIBRARY_PATH |
|
505 * variable. |
|
506 */ |
|
507 runpath = getenv(LD_LIBRARY_PATH); |
|
508 #endif /* __solaris__ */ |
|
509 |
|
510 /* runpath contains current effective LD_LIBRARY_PATH setting */ |
|
511 { /* New scope to declare local variable */ |
|
512 char *new_jvmpath = JLI_StringDup(jvmpath); |
|
513 new_runpath_size = ((runpath != NULL) ? JLI_StrLen(runpath) : 0) + |
|
514 2 * JLI_StrLen(jrepath) + |
|
515 #ifdef AIX |
|
516 /* On AIX we additionally need 'jli' in the path because ld doesn't support $ORIGIN. */ |
|
517 JLI_StrLen(jrepath) + JLI_StrLen("/lib//jli:") + |
|
518 #endif |
|
519 JLI_StrLen(new_jvmpath) + 52; |
|
520 new_runpath = JLI_MemAlloc(new_runpath_size); |
|
521 newpath = new_runpath + JLI_StrLen(LD_LIBRARY_PATH "="); |
|
522 |
|
523 |
|
524 /* |
|
525 * Create desired LD_LIBRARY_PATH value for target data model. |
|
526 */ |
|
527 { |
|
528 /* remove the name of the .so from the JVM path */ |
390 /* remove the name of the .so from the JVM path */ |
529 lastslash = JLI_StrRChr(new_jvmpath, '/'); |
391 lastslash = JLI_StrRChr(new_jvmpath, '/'); |
530 if (lastslash) |
392 if (lastslash) |
531 *lastslash = '\0'; |
393 *lastslash = '\0'; |
532 |
394 |
553 * checks if the desired runpath exists, this logic does a more |
415 * checks if the desired runpath exists, this logic does a more |
554 * comprehensive check. |
416 * comprehensive check. |
555 */ |
417 */ |
556 if (runpath != NULL && |
418 if (runpath != NULL && |
557 JLI_StrNCmp(newpath, runpath, JLI_StrLen(newpath)) == 0 && |
419 JLI_StrNCmp(newpath, runpath, JLI_StrLen(newpath)) == 0 && |
558 (runpath[JLI_StrLen(newpath)] == 0 || runpath[JLI_StrLen(newpath)] == ':') && |
420 (runpath[JLI_StrLen(newpath)] == 0 || |
559 (running == wanted) /* data model does not have to be changed */ |
421 runpath[JLI_StrLen(newpath)] == ':')) { |
560 #ifdef __solaris__ |
|
561 && (dmpath == NULL) /* data model specific variables not set */ |
|
562 #endif /* __solaris__ */ |
|
563 ) { |
|
564 JLI_MemFree(newargv); |
|
565 JLI_MemFree(new_runpath); |
422 JLI_MemFree(new_runpath); |
566 return; |
423 return; |
567 } |
424 } |
568 } |
|
569 } |
425 } |
570 |
426 } |
571 /* |
427 |
572 * Place the desired environment setting onto the prefix of |
428 /* |
573 * LD_LIBRARY_PATH. Note that this prevents any possible infinite |
429 * Place the desired environment setting onto the prefix of |
574 * loop of execv() because we test for the prefix, above. |
430 * LD_LIBRARY_PATH. Note that this prevents any possible infinite |
575 */ |
431 * loop of execv() because we test for the prefix, above. |
576 if (runpath != 0) { |
432 */ |
577 /* ensure storage for runpath + colon + NULL */ |
433 if (runpath != 0) { |
578 if ((JLI_StrLen(runpath) + 1 + 1) > new_runpath_size) { |
434 /* ensure storage for runpath + colon + NULL */ |
579 JLI_ReportErrorMessageSys(JRE_ERROR11); |
435 if ((JLI_StrLen(runpath) + 1 + 1) > new_runpath_size) { |
580 exit(1); |
436 JLI_ReportErrorMessageSys(JRE_ERROR11); |
581 } |
437 exit(1); |
582 JLI_StrCat(new_runpath, ":"); |
|
583 JLI_StrCat(new_runpath, runpath); |
|
584 } |
438 } |
585 |
439 JLI_StrCat(new_runpath, ":"); |
586 if (putenv(new_runpath) != 0) { |
440 JLI_StrCat(new_runpath, runpath); |
587 exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set |
441 } |
588 properly */ |
442 |
589 } |
443 if (putenv(new_runpath) != 0) { |
590 |
444 /* problem allocating memory; LD_LIBRARY_PATH not set properly */ |
591 /* |
445 exit(1); |
592 * Unix systems document that they look at LD_LIBRARY_PATH only |
446 } |
593 * once at startup, so we have to re-exec the current executable |
447 |
594 * to get the changed environment variable to have an effect. |
448 /* |
595 */ |
449 * Unix systems document that they look at LD_LIBRARY_PATH only |
596 |
450 * once at startup, so we have to re-exec the current executable |
597 #ifdef __solaris__ |
451 * to get the changed environment variable to have an effect. |
598 /* |
452 */ |
599 * If dmpath is not NULL, remove the data model specific string |
453 |
600 * in the environment for the exec'ed child. |
454 newenvp = environ; |
601 */ |
455 } |
602 if (dmpath != NULL) |
|
603 (void)UnsetEnv("LD_LIBRARY_PATH_64"); |
|
604 #endif /* __solaris */ |
|
605 |
|
606 newenvp = environ; |
|
607 } |
|
608 #endif /* SETENV_REQUIRED */ |
456 #endif /* SETENV_REQUIRED */ |
609 { |
457 { |
610 char *newexec = execname; |
458 char *newexec = execname; |
611 JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n"); |
459 JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n"); |
612 (void) fflush(stdout); |
460 (void) fflush(stdout); |
613 (void) fflush(stderr); |
461 (void) fflush(stderr); |
614 #ifdef SETENV_REQUIRED |
462 #ifdef SETENV_REQUIRED |
615 if (mustsetenv) { |
463 if (mustsetenv) { |
616 execve(newexec, argv, newenvp); |
464 execve(newexec, argv, newenvp); |
617 } else { |
465 } else { |
618 execv(newexec, argv); |
466 execv(newexec, argv); |
619 } |
467 } |
620 #else /* !SETENV_REQUIRED */ |
468 #else /* !SETENV_REQUIRED */ |
621 execv(newexec, argv); |
469 execv(newexec, argv); |
622 #endif /* SETENV_REQUIRED */ |
470 #endif /* SETENV_REQUIRED */ |
623 JLI_ReportErrorMessageSys(JRE_ERROR4, newexec); |
471 JLI_ReportErrorMessageSys(JRE_ERROR4, newexec); |
624 } |
472 } |
625 exit(1); |
473 exit(1); |
626 } |
474 } |
627 } |
475 |
628 |
476 |
629 /* |
|
630 * On Solaris VM choosing is done by the launcher (java.c), |
|
631 * bitsWanted is used by MacOSX, on Solaris and Linux this. |
|
632 * parameter is unused. |
|
633 */ |
|
634 static jboolean |
477 static jboolean |
635 GetJVMPath(const char *jrepath, const char *jvmtype, |
478 GetJVMPath(const char *jrepath, const char *jvmtype, |
636 char *jvmpath, jint jvmpathsize, int bitsWanted) |
479 char *jvmpath, jint jvmpathsize) |
637 { |
480 { |
638 struct stat s; |
481 struct stat s; |
639 |
482 |
640 if (JLI_StrChr(jvmtype, '/')) { |
483 if (JLI_StrChr(jvmtype, '/')) { |
641 JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype); |
484 JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype); |