1 /* |
1 /* |
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
67 |
71 |
68 #define NOT_FOUND -1 |
72 #define NOT_FOUND -1 |
69 static int firstAppArgIndex = NOT_FOUND; |
73 static int firstAppArgIndex = NOT_FOUND; |
70 |
74 |
71 static jboolean expectingNoDashArg = JNI_FALSE; |
75 static jboolean expectingNoDashArg = JNI_FALSE; |
72 static size_t argsCount = 0; |
76 // Initialize to 1, as the first argument is the app name and not preprocessed |
|
77 static size_t argsCount = 1; |
73 static jboolean stopExpansion = JNI_FALSE; |
78 static jboolean stopExpansion = JNI_FALSE; |
|
79 static jboolean relaunch = JNI_FALSE; |
74 |
80 |
75 void JLI_InitArgProcessing(jboolean isJava, jboolean disableArgFile) { |
81 void JLI_InitArgProcessing(jboolean isJava, jboolean disableArgFile) { |
76 // No expansion for relaunch |
82 // No expansion for relaunch |
77 if (argsCount != 0) { |
83 if (argsCount != 1) { |
|
84 relaunch = JNI_TRUE; |
78 stopExpansion = JNI_TRUE; |
85 stopExpansion = JNI_TRUE; |
79 argsCount = 0; |
86 argsCount = 1; |
80 } else { |
87 } else { |
81 stopExpansion = disableArgFile; |
88 stopExpansion = disableArgFile; |
82 } |
89 } |
83 |
90 |
84 expectingNoDashArg = JNI_FALSE; |
91 expectingNoDashArg = JNI_FALSE; |
93 } |
100 } |
94 |
101 |
95 static void checkArg(const char *arg) { |
102 static void checkArg(const char *arg) { |
96 size_t idx = 0; |
103 size_t idx = 0; |
97 argsCount++; |
104 argsCount++; |
98 if (argsCount == 1) { |
|
99 // ignore first argument, the application name |
|
100 return; |
|
101 } |
|
102 |
105 |
103 // All arguments arrive here must be a launcher argument, |
106 // All arguments arrive here must be a launcher argument, |
104 // ie. by now, all argfile expansions must have been performed. |
107 // ie. by now, all argfile expansions must have been performed. |
105 if (*arg == '-') { |
108 if (*arg == '-') { |
106 expectingNoDashArg = JNI_FALSE; |
109 expectingNoDashArg = JNI_FALSE; |
107 if (IsWhiteSpaceOption(arg)) { |
110 if (IsWhiteSpaceOption(arg)) { |
108 // expect an argument |
111 // expect an argument |
109 expectingNoDashArg = JNI_TRUE; |
112 expectingNoDashArg = JNI_TRUE; |
110 |
113 |
111 if (JLI_StrCmp(arg, "-jar") == 0 || |
114 if (JLI_StrCmp(arg, "-jar") == 0 || |
|
115 JLI_StrCmp(arg, "--module") == 0 || |
112 JLI_StrCmp(arg, "-m") == 0) { |
116 JLI_StrCmp(arg, "-m") == 0) { |
113 // This is tricky, we do expect NoDashArg |
117 // This is tricky, we do expect NoDashArg |
114 // But that is considered main class to stop expansion |
118 // But that is considered main class to stop expansion |
115 expectingNoDashArg = JNI_FALSE; |
119 expectingNoDashArg = JNI_FALSE; |
116 // We can not just update the idx here because if -jar @file |
120 // We can not just update the idx here because if -jar @file |
117 // still need expansion of @file to get the argument for -jar |
121 // still need expansion of @file to get the argument for -jar |
118 } |
122 } |
119 } else if (JLI_StrCmp(arg, "-Xdisable-@files") == 0) { |
123 } else if (JLI_StrCmp(arg, "--disable-@files") == 0) { |
120 stopExpansion = JNI_TRUE; |
124 stopExpansion = JNI_TRUE; |
121 } |
125 } |
122 } else { |
126 } else { |
123 if (!expectingNoDashArg) { |
127 if (!expectingNoDashArg) { |
124 // this is main class, argsCount is index to next arg |
128 // this is main class, argsCount is index to next arg |
405 rv = expandArgFile(arg); |
409 rv = expandArgFile(arg); |
406 } |
410 } |
407 return rv; |
411 return rv; |
408 } |
412 } |
409 |
413 |
|
414 int isTerminalOpt(char *arg) { |
|
415 return JLI_StrCmp(arg, "-jar") == 0 || |
|
416 JLI_StrCmp(arg, "-m") == 0 || |
|
417 JLI_StrCmp(arg, "--module") == 0 || |
|
418 JLI_StrCmp(arg, "--dry-run") == 0 || |
|
419 JLI_StrCmp(arg, "-h") == 0 || |
|
420 JLI_StrCmp(arg, "-?") == 0 || |
|
421 JLI_StrCmp(arg, "-help") == 0 || |
|
422 JLI_StrCmp(arg, "--help") == 0 || |
|
423 JLI_StrCmp(arg, "-X") == 0 || |
|
424 JLI_StrCmp(arg, "--help-extra") == 0 || |
|
425 JLI_StrCmp(arg, "-version") == 0 || |
|
426 JLI_StrCmp(arg, "--version") == 0 || |
|
427 JLI_StrCmp(arg, "-fullversion") == 0 || |
|
428 JLI_StrCmp(arg, "--full-version") == 0; |
|
429 } |
|
430 |
|
431 jboolean JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { |
|
432 char *env = getenv(var_name); |
|
433 char *p, *arg; |
|
434 char quote; |
|
435 JLI_List argsInFile; |
|
436 |
|
437 if (firstAppArgIndex == 0) { |
|
438 // Not 'java', return |
|
439 return JNI_FALSE; |
|
440 } |
|
441 |
|
442 if (relaunch) { |
|
443 return JNI_FALSE; |
|
444 } |
|
445 |
|
446 if (NULL == env) { |
|
447 return JNI_FALSE; |
|
448 } |
|
449 |
|
450 JLI_ReportMessage(ARG_INFO_ENVVAR, var_name, env); |
|
451 |
|
452 // This is retained until the process terminates as it is saved as the args |
|
453 p = JLI_MemAlloc(JLI_StrLen(env) + 1); |
|
454 while (*env != '\0') { |
|
455 while (*env != '\0' && isspace(*env)) { |
|
456 env++; |
|
457 } |
|
458 |
|
459 arg = p; |
|
460 while (*env != '\0' && !isspace(*env)) { |
|
461 if (*env == '"' || *env == '\'') { |
|
462 quote = *env++; |
|
463 while (*env != quote && *env != '\0') { |
|
464 *p++ = *env++; |
|
465 } |
|
466 |
|
467 if (*env == '\0') { |
|
468 JLI_ReportMessage(ARG_ERROR8, var_name); |
|
469 exit(1); |
|
470 } |
|
471 env++; |
|
472 } else { |
|
473 *p++ = *env++; |
|
474 } |
|
475 } |
|
476 |
|
477 *p++ = '\0'; |
|
478 |
|
479 argsInFile = JLI_PreprocessArg(arg); |
|
480 |
|
481 if (NULL == argsInFile) { |
|
482 if (isTerminalOpt(arg)) { |
|
483 JLI_ReportMessage(ARG_ERROR9, arg, var_name); |
|
484 exit(1); |
|
485 } |
|
486 JLI_List_add(args, arg); |
|
487 } else { |
|
488 size_t cnt, idx; |
|
489 char *argFile = arg; |
|
490 cnt = argsInFile->size; |
|
491 for (idx = 0; idx < cnt; idx++) { |
|
492 arg = argsInFile->elements[idx]; |
|
493 if (isTerminalOpt(arg)) { |
|
494 JLI_ReportMessage(ARG_ERROR10, arg, argFile, var_name); |
|
495 exit(1); |
|
496 } |
|
497 JLI_List_add(args, arg); |
|
498 } |
|
499 // Shallow free, we reuse the string to avoid copy |
|
500 JLI_MemFree(argsInFile->elements); |
|
501 JLI_MemFree(argsInFile); |
|
502 } |
|
503 /* |
|
504 * Check if main-class is specified after argument being checked. It |
|
505 * must always appear after expansion, as a main-class could be specified |
|
506 * indirectly into environment variable via an @argfile, and it must be |
|
507 * caught now. |
|
508 */ |
|
509 if (firstAppArgIndex != NOT_FOUND) { |
|
510 JLI_ReportMessage(ARG_ERROR11, var_name); |
|
511 exit(1); |
|
512 } |
|
513 |
|
514 assert (*env == '\0' || isspace(*env)); |
|
515 } |
|
516 |
|
517 return JNI_TRUE; |
|
518 } |
|
519 |
410 #ifdef DEBUG_ARGFILE |
520 #ifdef DEBUG_ARGFILE |
411 /* |
521 /* |
412 * Stand-alone sanity test, build with following command line |
522 * Stand-alone sanity test, build with following command line |
413 * $ CC -DDEBUG_ARGFILE -DNO_JNI -g args.c jli_util.c |
523 * $ CC -DDEBUG_ARGFILE -DNO_JNI -g args.c jli_util.c |
414 */ |
524 */ |