/* * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
static jboolean expectingNoDashArg = JNI_FALSE; // Initialize to 1, as the first argument is the app name and not preprocessed static size_t argsCount = 1; static jboolean stopExpansion = JNI_FALSE; static jboolean relaunch = JNI_FALSE;
// All arguments arrive here must be a launcher argument, // ie. by now, all argfile expansions must have been performed. if (*arg == '-') {
expectingNoDashArg = JNI_FALSE; if (IsWhiteSpaceOption(arg)) { // expect an argument
expectingNoDashArg = JNI_TRUE;
if (JLI_StrCmp(arg, "-jar") == 0 ||
JLI_StrCmp(arg, "--module") == 0 ||
JLI_StrCmp(arg, "-m") == 0) { // This is tricky, we do expect NoDashArg // But that is considered main class to stop expansion
expectingNoDashArg = JNI_FALSE; // We can not just update the idx here because if -jar @file // still need expansion of @file to get the argument for -jar
}
} elseif (JLI_StrCmp(arg, "--disable-@files") == 0) {
stopExpansion = JNI_TRUE;
} elseif (JLI_StrCCmp(arg, "--module=") == 0) {
idx = argsCount;
}
} else { if (!expectingNoDashArg) { // this is main class, argsCount is index to next arg
idx = argsCount;
}
expectingNoDashArg = JNI_FALSE;
} // only update on java mode and not yet found main class if (firstAppArgIndex == NOT_FOUND && idx != 0) {
firstAppArgIndex = (int) idx;
}
}
assert(nextc == eob); // Only need partial token, not comment or whitespaces if (pctx->state == IN_TOKEN || pctx->state == IN_QUOTE) { if (anchor < nextc) { // not yet return until end of stream, we have part of a token.
JLI_List_addSubstring(pctx->parts, anchor, nextc - anchor);
}
} return NULL;
}
ctx.state = FIND_NEXT;
ctx.parts = JLI_List_new(4); // initialize to avoid -Werror=maybe-uninitialized issues from gcc 7.3 onwards.
ctx.quote_char = '"';
/* arbitrarily pick 8, seems to be a reasonable number of arguments */
rv = JLI_List_new(8);
while (!feof(file)) {
size = fread(buf, sizeof(char), sizeof(buf), file); if (ferror(file)) {
JLI_List_free(rv); return NULL;
}
/* nextc is next character to read from the buffer * eob is the end of input * token is the copied token value, NULL if no a complete token
*/
ctx.cptr = buf;
ctx.eob = buf + size;
token = nextToken(&ctx); while (token != NULL) {
checkArg(token);
JLI_List_add(rv, token);
token = nextToken(&ctx);
}
}
/* * if the arg represent a file, that is, prefix with a single '@', * return a list of arguments from the file. * otherwise, return NULL.
*/ static JLI_List expandArgFile(constchar *arg) {
JLI_List rv; struct stat st;
FILE *fptr = fopen(arg, "r");
/* arg file cannot be opened */ if (fptr == NULL || fstat(fileno(fptr), &st) != 0) {
JLI_ReportMessage(CFG_ERROR6, arg); exit(1);
} else { if (st.st_size > MAX_ARGF_SIZE) {
JLI_ReportMessage(CFG_ERROR10, MAX_ARGF_SIZE); exit(1);
}
}
rv = readArgFile(fptr);
/* error occurred reading the file */ if (rv == NULL) {
JLI_ReportMessage(DLL_ERROR4, arg); exit(1);
}
fclose(fptr);
return rv;
}
/* * expand a string into a list of words separated by whitespace.
*/ static JLI_List expandArg(constchar *arg) {
JLI_List rv;
/* arbitrarily pick 8, seems to be a reasonable number of arguments */
rv = JLI_List_new(8);
/* * Expand a string into a list of args. * If the string is the result of looking up an environment variable, * var_name should be set to the name of that environment variable, * for use if needed in error messages.
*/
// This is retained until the process terminates as it is saved as the args
p = JLI_MemAlloc(JLI_StrLen(str) + 1); while (*str != '\0') { while (*str != '\0' && isspace(*str)) {
str++;
}
if (NULL == argsInFile) { if (isTerminalOpt(arg)) { if (inEnvVar) {
JLI_ReportMessage(ARG_ERROR9, arg, var_name);
} else {
JLI_ReportMessage(ARG_ERROR15, arg);
} exit(1);
}
JLI_List_add(args, arg);
} else {
size_t cnt, idx; char *argFile = arg;
cnt = argsInFile->size; for (idx = 0; idx < cnt; idx++) {
arg = argsInFile->elements[idx]; if (isTerminalOpt(arg)) { if (inEnvVar) {
JLI_ReportMessage(ARG_ERROR10, arg, argFile, var_name);
} else {
JLI_ReportMessage(ARG_ERROR16, arg, argFile);
} exit(1);
}
JLI_List_add(args, arg);
} // Shallow free, we reuse the string to avoid copy
JLI_MemFree(argsInFile->elements);
JLI_MemFree(argsInFile);
} /* * Check if main-class is specified after argument being checked. It * must always appear after expansion, as a main-class could be specified * indirectly into environment variable via an @argfile, and it must be * caught now.
*/ if (firstAppArgIndex != NOT_FOUND) { if (inEnvVar) {
JLI_ReportMessage(ARG_ERROR11, var_name);
} else {
JLI_ReportMessage(ARG_ERROR17);
} exit(1);
}
assert (*str == '\0' || isspace(*str));
}
return JNI_TRUE;
}
#ifdef DEBUG_ARGFILE /* * Stand-alone sanity test, build with following command line * $ CC -DDEBUG_ARGFILE -DNO_JNI -g args.c jli_util.c
*/
for (token = nextToken(&ctx); token != NULL; token = nextToken(&ctx)) { // should not have more tokens than expected if (actual_cnt >= cnt_tokens) {
printf("FAILED: Extra token detected: <%s>\n", token); exit(2);
} if (JLI_StrCmp(token, tokens[actual_cnt]) != 0) {
fail(tokens[actual_cnt], token, actual_cnt);
}
actual_cnt++;
}
char* last = NULL; if (ctx.parts->size != 0) {
last = JLI_List_combine(ctx.parts);
}
JLI_List_free(ctx.parts);
if (actual_cnt >= cnt_tokens) { // same number of tokens, should have nothing left to parse if (last != NULL) { if (*last != '#') {
printf("Leftover detected: %s", last); exit(2);
}
}
} else { if (JLI_StrCmp(last, tokens[actual_cnt]) != 0) {
fail(tokens[actual_cnt], last, actual_cnt);
}
actual_cnt++;
} if (actual_cnt != cnt_tokens) {
printf("FAILED: Number of tokens not match, expected %lu, got %lu\n",
cnt_tokens, actual_cnt); exit(3);
}
printf("PASS\n");
}
#define DO_CASE(name) \
test_case(name[0], name + 1, sizeof(name)/sizeof(char*) - 1)
// note the open quote at the end char* case2[] = { "com.foo.Panda \"Furious 5\"\fand\t'Shi Fu' \"escape\tprison", "com.foo.Panda", "Furious 5", "and", "Shi Fu", "escape\tprison"};
DO_CASE(case2);
char* mixed_quote[] = { "\"mix 'single quote' in double\" 'mix \"double quote\" in single' partial\"quote me\"this", "mix 'single quote' in double", "mix \"double quote\" in single", "partialquote methis"};
DO_CASE(mixed_quote);
char* comments[] = { "line one #comment\n'line #2' #rest are comment\r\n#comment on line 3\nline 4 #comment to eof", "line", "one", "line #2", "line", "4"};
DO_CASE(comments);
char* open_quote[] = { "This is an \"open quote \n across line\n\t, note for WS.", "This", "is", "an", "open quote ", "across", "line", ",", "note", "for", "WS." };
DO_CASE(open_quote);
char* escape_in_open_quote[] = { "Try \"this \\\\\\\\ escape\\n double quote \\\" in open quote", "Try", "this \\\\ escape\n double quote \" in open quote" };
DO_CASE(escape_in_open_quote);
char* quote[] = { "'-Dmy.quote.single'='Property in single quote. Here a double quote\" Add some slashes \\\\/'", "-Dmy.quote.single=Property in single quote. Here a double quote\" Add some slashes \\/" };
DO_CASE(quote);
char* multi[] = { "\"Open quote to \n new \"line \\\n\r third\\\n\r\\\tand\ffourth\"", "Open quote to ", "new", "line third\tand\ffourth" };
DO_CASE(multi);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.