1 /* 2 * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 /* 28 * Converts a single string command line to the traditional argc, argv. 29 * There are rules which govern the breaking of the arguments, and 30 * these rules are embodied in the regression tests below, and duplicated 31 * in the jdk regression tests. 32 */ 33 34 #include <assert.h> 35 36 #ifndef IDE_STANDALONE 37 #include "java.h" 38 #include "jli_util.h" 39 #else /* IDE_STANDALONE */ 40 // The defines we need for stand alone testing 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <Windows.h> 44 #define JNI_TRUE TRUE 45 #define JNI_FALSE FALSE 46 #define JLI_MemRealloc realloc 47 #define JLI_StringDup _strdup 48 #define JLI_MemFree free 49 #define jboolean boolean 50 typedef struct { 51 char* arg; 52 boolean has_wildcard; 53 } StdArg ; 54 #endif 55 static StdArg *stdargs; 56 static int stdargc; 57 58 static int copyCh(USHORT ch, char* dest) { 59 if (HIBYTE(ch) == 0) { 60 *dest = (char)ch; 61 return 1; 62 } else { 63 *((USHORT *)dest) = ch; 64 return 2; 65 } 66 } 67 68 static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) { 69 70 char* src = cmdline; 71 char* dest = arg; 72 jboolean separator = JNI_FALSE; 73 int quotes = 0; 74 int slashes = 0; 75 76 // "prev"/"ch" may contain either a single byte, or a double byte 77 // character encoded in CP_ACP. 78 USHORT prev = 0; 79 USHORT ch = 0; 80 int i; 81 jboolean done = JNI_FALSE; 82 ptrdiff_t charLength; 83 84 *wildcard = JNI_FALSE; 85 while (!done) { 86 charLength = CharNextExA(CP_ACP, src, 0) - src; 87 if (charLength == 0) { 88 break; 89 } else if (charLength == 1) { 90 ch = (USHORT)(UCHAR)src[0]; 91 } else { 92 ch = ((USHORT *)src)[0]; 93 } 94 95 switch (ch) { 96 case L'"': 97 if (separator) { 98 done = JNI_TRUE; 99 break; 100 } 101 if (prev == L'\\') { 102 for (i = 1; i < slashes; i += 2) { 103 dest += copyCh(prev, dest); 104 } 105 if (slashes % 2 == 1) { 106 dest += copyCh(ch, dest); 107 } else { 108 quotes++; 109 } 110 } else if (prev == L'"' && quotes % 2 == 0) { 111 quotes++; 112 dest += copyCh(ch, dest); // emit every other consecutive quote 113 } else if (quotes == 0) { 114 quotes++; // starting quote 115 } else { 116 quotes--; // matching quote 117 } 118 slashes = 0; 119 break; 120 121 case L'\\': 122 slashes++; 123 if (separator) { 124 done = JNI_TRUE; 125 separator = JNI_FALSE; 126 } 127 break; 128 129 case L' ': 130 case L'\t': 131 if (prev == L'\\') { 132 for (i = 0 ; i < slashes; i++) { 133 dest += copyCh(prev, dest); 134 } 135 } 136 if (quotes % 2 == 1) { 137 dest += copyCh(ch, dest); 138 } else { 139 separator = JNI_TRUE; 140 } 141 slashes = 0; 142 break; 143 144 case L'*': 145 case L'?': 146 if (separator) { 147 done = JNI_TRUE; 148 separator = JNI_FALSE; 149 break; 150 } 151 if (quotes % 2 == 0) { 152 *wildcard = JNI_TRUE; 153 } 154 if (prev == L'\\') { 155 for (i = 0 ; i < slashes ; i++) { 156 dest += copyCh(prev, dest); 157 } 158 } 159 dest += copyCh(ch, dest); 160 slashes = 0; 161 break; 162 163 default: 164 if (prev == L'\\') { 165 for (i = 0 ; i < slashes ; i++) { 166 dest += copyCh(prev, dest); 167 } 168 dest += copyCh(ch, dest); 169 } else if (separator) { 170 done = JNI_TRUE; 171 } else { 172 dest += copyCh(ch, dest); 173 } 174 slashes = 0; 175 } 176 177 if (!done) { 178 prev = ch; 179 src += charLength; 180 } 181 } 182 if (prev == L'\\') { 183 for (i = 0; i < slashes; i++) { 184 dest += copyCh(prev, dest); 185 } 186 } 187 *dest = 0; 188 return done ? src : NULL; 189 } 190 191 int JLI_GetStdArgc() { 192 return stdargc; 193 } 194 195 StdArg* JLI_GetStdArgs() { 196 return stdargs; 197 } 198 199 void JLI_CmdToArgs(char* cmdline) { 200 int nargs = 0; 201 StdArg* argv = NULL; 202 jboolean wildcard = JNI_FALSE; 203 char* src = cmdline, *arg = NULL; 204 JLI_List argsInFile; 205 size_t i, cnt; 206 207 JLI_List envArgs = JLI_List_new(1); 208 if (JLI_AddArgsFromEnvVar(envArgs, JAVA_OPTIONS)) { 209 // JLI_SetTraceLauncher is not called yet 210 // Show _JAVA_OPTIONS content along with JAVA_OPTIONS to aid diagnosis 211 if (getenv(JLDEBUG_ENV_ENTRY)) { 212 char *tmp = getenv("_JAVA_OPTIONS"); 213 if (NULL != tmp) { 214 JLI_ReportMessage(ARG_INFO_ENVVAR, "_JAVA_OPTIONS", tmp); 215 } 216 } 217 } 218 cnt = envArgs->size + 1; 219 argv = JLI_MemAlloc(cnt * sizeof(StdArg)); 220 221 // allocate arg buffer with sufficient space to receive the largest arg 222 arg = JLI_StringDup(cmdline); 223 224 src = next_arg(src, arg, &wildcard); 225 // first argument is the app name, do not preprocess and make sure remains first 226 argv[0].arg = JLI_StringDup(arg); 227 argv[0].has_wildcard = wildcard; 228 nargs++; 229 230 for (i = 1; i < cnt; i++) { 231 argv[i].arg = envArgs->elements[i - 1]; 232 // wildcard is not supported in argfile 233 argv[i].has_wildcard = JNI_FALSE; 234 nargs++; 235 } 236 JLI_MemFree(envArgs->elements); 237 JLI_MemFree(envArgs); 238 239 assert ((size_t) nargs == cnt); 240 *arg = '\0'; 241 242 // iterate through rest of command line 243 while (src != NULL) { 244 src = next_arg(src, arg, &wildcard); 245 argsInFile = JLI_PreprocessArg(arg); 246 if (argsInFile != NULL) { 247 // resize to accommodate another Arg 248 cnt = argsInFile->size; 249 argv = (StdArg*) JLI_MemRealloc(argv, (nargs + cnt) * sizeof(StdArg)); 250 for (i = 0; i < cnt; i++) { 251 argv[nargs].arg = argsInFile->elements[i]; 252 // wildcard is not supported in argfile 253 argv[nargs].has_wildcard = JNI_FALSE; 254 nargs++; 255 } 256 // Shallow free, we reuse the string to avoid copy 257 JLI_MemFree(argsInFile->elements); 258 JLI_MemFree(argsInFile); 259 } else { 260 // resize to accommodate another Arg 261 argv = (StdArg*) JLI_MemRealloc(argv, (nargs+1) * sizeof(StdArg)); 262 argv[nargs].arg = JLI_StringDup(arg); 263 argv[nargs].has_wildcard = wildcard; 264 *arg = '\0'; 265 nargs++; 266 } 267 *arg = '\0'; 268 } 269 270 JLI_MemFree(arg); 271 272 stdargc = nargs; 273 stdargs = argv; 274 } 275 276 #ifdef IDE_STANDALONE 277 void doexit(int rv) { 278 printf("Hit any key to quit\n"); 279 int c = getchar(); 280 exit(rv); 281 } 282 283 void doabort() { 284 doexit(1); 285 } 286 287 class Vector { 288 public: 289 char* cmdline; 290 int argc; 291 char* argv[10]; 292 boolean wildcard[10]; 293 boolean enabled; 294 295 Vector(){} 296 // Initialize our test vector with the program name, argv[0] 297 // and the single string command line. 298 Vector(char* pname, char* cline) { 299 argv[0] = pname; 300 wildcard[0] = FALSE; 301 cmdline = cline; 302 argc = 1; 303 enabled = TRUE; 304 } 305 306 // add our expected strings, the program name has already been 307 // added so ignore that 308 void add(char* arg, boolean w) { 309 argv[argc] = arg; 310 wildcard[argc] = w; 311 argc++; 312 } 313 314 void disable() { 315 enabled = FALSE; 316 } 317 318 // validate the returned arguments with the expected arguments, using the 319 // new CmdToArgs method. 320 bool check() { 321 // "pgmname" rest of cmdline ie. pgmname + 2 double quotes + space + cmdline from windows 322 char* cptr = (char*) malloc(strlen(argv[0]) + sizeof(char) * 3 + strlen(cmdline) + 1); 323 _snprintf(cptr, MAX_PATH, "\"%s\" %s", argv[0], cmdline); 324 JLI_CmdToArgs(cptr); 325 free(cptr); 326 StdArg *kargv = JLI_GetStdArgs(); 327 int kargc = JLI_GetStdArgc(); 328 bool retval = true; 329 printf("\n===========================\n"); 330 printf("cmdline=%s\n", cmdline); 331 if (argc != kargc) { 332 printf("*** argument count does not match\n"); 333 printme(); 334 printtest(kargc, kargv); 335 doabort(); 336 } 337 for (int i = 0 ; i < argc && retval == true ; i++) { 338 if (strcmp(argv[i], kargv[i].arg) != 0) { 339 printf("*** argument at [%d] don't match\n got: %s\n exp: %s\n", 340 i, kargv[i].arg, argv[i]); 341 doabort(); 342 } 343 } 344 for (int i = 0 ; i < argc && retval == true ; i++) { 345 if (wildcard[i] != kargv[i].has_wildcard) { 346 printf("*** expansion flag at [%d] doesn't match\n got: %d\n exp: %d\n", 347 i, kargv[i].has_wildcard, wildcard[i]); 348 doabort(); 349 } 350 } 351 for (int i = 0 ; i < kargc ; i++) { 352 printf("k[%d]=%s\n", i, kargv[i].arg); 353 printf(" [%d]=%s\n", i, argv[i]); 354 } 355 return retval; 356 } 357 void printtest(int kargc, StdArg* kargv) { 358 for (int i = 0 ; i < kargc ; i++) { 359 printf("k[%d]=%s\n", i, kargv[i].arg); 360 } 361 } 362 void printme() { 363 for (int i = 0 ; i < argc ; i++) { 364 printf(" [%d]=%s\n", i, argv[i]); 365 } 366 } 367 }; 368 369 void dotest(Vector** vectors) { 370 Vector* v = vectors[0]; 371 for (int i = 0 ; v != NULL;) { 372 if (v->enabled) { 373 v->check(); 374 } 375 v = vectors[++i]; 376 } 377 } 378 379 #define MAXV 128 380 int main(int argc, char* argv[]) { 381 382 int n; 383 for (n=1; n < argc; n++) { 384 printf("%d %s\n", n, argv[n]); 385 } 386 if (n > 1) { 387 JLI_CmdToArgs(GetCommandLine()); 388 for (n = 0; n < stdargc; n++) { 389 printf(" [%d]=%s\n", n, stdargs[n].arg); 390 printf(" [%d]=%s\n", n, stdargs[n].has_wildcard ? "TRUE" : "FALSE"); 391 } 392 doexit(0); 393 } 394 395 Vector *vectors[MAXV]; 396 397 memset(vectors, 0, sizeof(vectors)); 398 int i = 0; 399 Vector* v = new Vector(argv[0], "abcd"); 400 v->add("abcd", FALSE); 401 // v->disable(); 402 vectors[i++] = v; 403 404 405 v = new Vector(argv[0], "\"a b c d\""); 406 v->add("a b c d", FALSE); 407 // v->disable(); 408 vectors[i++] = v; 409 410 411 v = new Vector(argv[0], "a\"b c d\"e"); 412 v->add("ab c de", FALSE); 413 // v->disable(); 414 vectors[i++] = v; 415 416 417 v = new Vector(argv[0], "ab\\\"cd"); 418 v->add("ab\"cd", FALSE); 419 // v->disable(); 420 vectors[i++] = v; 421 422 423 v = new Vector(argv[0], "\"a b c d\\\\\""); 424 v->add("a b c d\\", FALSE); 425 // v->disable(); 426 vectors[i++] = v; 427 428 429 v = new Vector(argv[0], "ab\\\\\\\"cd"); 430 v->add("ab\\\"cd", FALSE); 431 // v->disable(); 432 vectors[i++] = v; 433 434 435 // Windows tests 436 v = new Vector(argv[0], "a\\\\\\c"); 437 v->add("a\\\\\\c", FALSE); 438 // v->disable(); 439 vectors[i++] = v; 440 441 442 v = new Vector(argv[0], "\"a\\\\\\d\""); 443 v->add("a\\\\\\d", FALSE); 444 // v->disable(); 445 vectors[i++] = v; 446 447 448 v = new Vector(argv[0], "\"a b c\" d e"); 449 v->add("a b c", FALSE); 450 v->add("d", FALSE); 451 v->add("e", FALSE); 452 // v->disable(); 453 vectors[i++] = v; 454 455 456 v = new Vector(argv[0], "\"ab\\\"c\" \"\\\\\" d"); 457 v->add("ab\"c", FALSE); 458 v->add("\\", FALSE); 459 v->add("d", FALSE); 460 // v->disable(); 461 vectors[i++] = v; 462 463 464 v = new Vector(argv[0], "a\\\\\\c d\"e f\"g h"); 465 v->add("a\\\\\\c", FALSE); 466 v->add("de fg", FALSE); 467 v->add("h", FALSE); 468 // v->disable(); 469 vectors[i++] = v; 470 471 472 v = new Vector(argv[0], "a\\\\\\\"b c d"); 473 v->add("a\\\"b", FALSE); // XXX "a\\\\\\\"b" 474 v->add("c", FALSE); 475 v->add("d", FALSE); 476 // v->disable(); 477 vectors[i++] = v; 478 479 480 v = new Vector(argv[0], "a\\\\\\\\\"g c\" d e"); // XXX "a\\\\\\\\\"b c\" d e" 481 v->add("a\\\\\g c", FALSE); // XXX "a\\\\\\\\\"b c" 482 v->add("d", FALSE); 483 v->add("e", FALSE); 484 // v->disable(); 485 vectors[i++] = v; 486 487 488 // Additional tests 489 v = new Vector(argv[0], "\"a b c\"\""); 490 v->add("a b c\"", FALSE); 491 // v->disable(); 492 vectors[i++] = v; 493 494 495 v = new Vector(argv[0], "\"\"a b c\"\""); 496 v->add("a", FALSE); 497 v->add("b", FALSE); 498 v->add("c", FALSE); 499 // v->disable(); 500 vectors[i++] = v; 501 502 503 v = new Vector(argv[0], "\"\"\"a b c\"\"\""); 504 v->add("\"a b c\"", FALSE); 505 // v->disable(); 506 vectors[i++] = v; 507 508 509 v = new Vector(argv[0], "\"\"\"\"a b c\"\"\"\""); 510 v->add("\"a", FALSE); 511 v->add("b", FALSE); 512 v->add("c\"", FALSE); 513 // v->disable(); 514 vectors[i++] = v; 515 516 517 v = new Vector(argv[0], "\"\"\"\"\"a b c\"\"\"\"\""); 518 v->add("\"\"a b c\"\"", FALSE); 519 // v->disable(); 520 vectors[i++] = v; 521 522 523 v = new Vector(argv[0], "\"C:\\TEST A\\\\\""); 524 v->add("C:\\TEST A\\", FALSE); 525 // v->disable(); 526 vectors[i++] = v; 527 528 529 v = new Vector(argv[0], "\"\"C:\\TEST A\\\\\"\""); 530 v->add("C:\\TEST", FALSE); 531 v->add("A\\", FALSE); 532 // v->disable(); 533 vectors[i++] = v; 534 535 536 // test if a wildcard is present 537 v = new Vector(argv[0], "abc*def"); 538 v->add("abc*def", TRUE); 539 // v->disable(); 540 vectors[i++] = v; 541 542 543 v = new Vector(argv[0], "\"abc*def\""); 544 v->add("abc*def", FALSE); 545 // v->disable(); 546 vectors[i++] = v; 547 548 549 v = new Vector(argv[0], "*.abc"); 550 v->add("*.abc", TRUE); 551 // v->disable(); 552 vectors[i++] = v; 553 554 555 v = new Vector(argv[0], "\"*.abc\""); 556 v->add("*.abc", FALSE); 557 // v->disable(); 558 vectors[i++] = v; 559 560 561 v = new Vector(argv[0], "x.???"); 562 v->add("x.???", TRUE); 563 // v->disable(); 564 vectors[i++] = v; 565 566 567 v = new Vector(argv[0], "\"x.???\""); 568 v->add("x.???", FALSE); 569 // v->disable(); 570 vectors[i++] = v; 571 572 573 v = new Vector(argv[0], "Debug\\*"); 574 v->add("Debug\\*", TRUE); 575 // v->disable(); 576 vectors[i++] = v; 577 578 579 v = new Vector(argv[0], "Debug\\f?a"); 580 v->add("Debug\\f?a", TRUE); 581 // v->disable(); 582 vectors[i++] = v; 583 584 585 v = new Vector(argv[0], "Debug\\?a.java"); 586 v->add("Debug\\?a.java", TRUE); 587 // v->disable(); 588 vectors[i++] = v; 589 590 591 v = new Vector(argv[0], "foo *.noexts"); 592 v->add("foo", FALSE); 593 v->add("*.noexts", TRUE); 594 // v->disable(); 595 vectors[i++] = v; 596 597 598 v = new Vector(argv[0], "X\\Y\\Z"); 599 v->add("X\\Y\\Z", FALSE); 600 // v->disable(); 601 vectors[i++] = v; 602 603 604 v = new Vector(argv[0], "\\X\\Y\\Z"); 605 v->add("\\X\\Y\\Z", FALSE); 606 // v->disable(); 607 vectors[i++] = v; 608 609 610 v = new Vector(argv[0], "a b"); 611 v->add("a", FALSE); 612 v->add("b", FALSE); 613 // v->disable(); 614 vectors[i++] = v; 615 616 617 v = new Vector(argv[0], "a\tb"); 618 v->add("a", FALSE); 619 v->add("b", FALSE); 620 // v->disable(); 621 vectors[i++] = v; 622 623 624 v = new Vector(argv[0], "a \t b"); 625 v->add("a", FALSE); 626 v->add("b", FALSE); 627 // v->disable(); 628 vectors[i++] = v; 629 630 v = new Vector(argv[0], "*\\"); 631 v->add("*\\", TRUE); 632 // v->disable(); 633 vectors[i++] = v; 634 635 v = new Vector(argv[0], "*/"); 636 v->add("*/", TRUE); 637 // v->disable(); 638 vectors[i++] = v; 639 640 v = new Vector(argv[0], ".\\*"); 641 v->add(".\\*", TRUE); 642 // v->disable(); 643 vectors[i++] = v; 644 645 v = new Vector(argv[0], "./*"); 646 v->add("./*", TRUE); 647 // v->disable(); 648 vectors[i++] = v; 649 650 v = new Vector(argv[0], ".\\*"); 651 v->add(".\\*", TRUE); 652 // v->disable(); 653 vectors[i++] = v; 654 655 v = new Vector(argv[0], ".//*"); 656 v->add(".//*", TRUE); 657 // v->disable(); 658 vectors[i++] = v; 659 660 v = new Vector(argv[0], "..\\..\\*"); 661 v->add("..\\..\\*", TRUE); 662 // v->disable(); 663 vectors[i++] = v; 664 665 v = new Vector(argv[0], "../../*"); 666 v->add("../../*", TRUE); 667 // v->disable(); 668 vectors[i++] = v; 669 670 v = new Vector(argv[0], "..\\..\\"); 671 v->add("..\\..\\", FALSE); 672 // v->disable(); 673 vectors[i++] = v; 674 675 v = new Vector(argv[0], "../../"); 676 v->add("../../", FALSE); 677 // v->disable(); 678 vectors[i++] = v; 679 680 v= new Vector(argv[0], "a b\\\\ d"); 681 v->add("a", FALSE); 682 v->add("b\\\\", FALSE); 683 v->add("d", FALSE); 684 vectors[i++] = v; 685 686 v= new Vector(argv[0], "\\\\?"); 687 v->add("\\\\?", TRUE); 688 vectors[i++] = v; 689 690 v= new Vector(argv[0], "\\\\*"); 691 v->add("\\\\*", TRUE); 692 vectors[i++] = v; 693 694 dotest(vectors); 695 printf("All tests pass [%d]\n", i); 696 doexit(0); 697 } 698 #endif /* IDE_STANDALONE */