clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name small.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ftp/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/ftp/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/ftp/small.c
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | |
| 37 | |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | |
| 59 | |
| 60 | |
| 61 | |
| 62 | |
| 63 | |
| 64 | |
| 65 | #include <sys/types.h> |
| 66 | #include <sys/socket.h> |
| 67 | #include <sys/stat.h> |
| 68 | #include <sys/wait.h> |
| 69 | #include <arpa/ftp.h> |
| 70 | |
| 71 | #include <ctype.h> |
| 72 | #include <err.h> |
| 73 | #include <fnmatch.h> |
| 74 | #include <glob.h> |
| 75 | #include <netdb.h> |
| 76 | #include <stdio.h> |
| 77 | #include <stdlib.h> |
| 78 | #include <string.h> |
| 79 | #include <unistd.h> |
| 80 | #include <errno.h> |
| 81 | |
| 82 | #include "ftp_var.h" |
| 83 | #include "pathnames.h" |
| 84 | #include "small.h" |
| 85 | |
| 86 | jmp_buf jabort; |
| 87 | char *mname; |
| 88 | char *home = "/"; |
| 89 | |
| 90 | struct types { |
| 91 | char *t_name; |
| 92 | char *t_mode; |
| 93 | int t_type; |
| 94 | } types[] = { |
| 95 | { "ascii", "A", TYPE_A }, |
| 96 | { "binary", "I", TYPE_I }, |
| 97 | { "image", "I", TYPE_I }, |
| 98 | { NULL } |
| 99 | }; |
| 100 | |
| 101 | |
| 102 | |
| 103 | |
| 104 | void |
| 105 | settype(int argc, char *argv[]) |
| 106 | { |
| 107 | struct types *p; |
| 108 | int comret; |
| 109 | |
| 110 | if (argc > 2) { |
| 111 | char *sep; |
| 112 | |
| 113 | fprintf(ttyout, "usage: %s [", argv[0]); |
| 114 | sep = ""; |
| 115 | for (p = types; p->t_name; p++) { |
| 116 | fprintf(ttyout, "%s%s", sep, p->t_name); |
| 117 | sep = " | "; |
| 118 | } |
| 119 | fputs("]\n", ttyout); |
| 120 | code = -1; |
| 121 | return; |
| 122 | } |
| 123 | if (argc < 2) { |
| 124 | fprintf(ttyout, "Using %s mode to transfer files.\n", typename); |
| 125 | code = 0; |
| 126 | return; |
| 127 | } |
| 128 | for (p = types; p->t_name; p++) |
| 129 | if (strcmp(argv[1], p->t_name) == 0) |
| 130 | break; |
| 131 | if (p->t_name == 0) { |
| 132 | fprintf(ttyout, "%s: unknown mode.\n", argv[1]); |
| 133 | code = -1; |
| 134 | return; |
| 135 | } |
| 136 | comret = command("TYPE %s", p->t_mode); |
| 137 | if (comret == COMPLETE) { |
| 138 | (void)strlcpy(typename, p->t_name, sizeof typename); |
| 139 | curtype = type = p->t_type; |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | |
| 144 | |
| 145 | |
| 146 | |
| 147 | |
| 148 | void |
| 149 | changetype(int newtype, int show) |
| 150 | { |
| 151 | struct types *p; |
| 152 | int comret, oldverbose = verbose; |
| 153 | |
| 154 | if (newtype == 0) |
| 155 | newtype = TYPE_I; |
| 156 | if (newtype == curtype) |
| 157 | return; |
| 158 | if ( |
| 159 | #ifndef SMALL |
| 160 | !debug && |
| 161 | #endif /* !SMALL */ |
| 162 | show == 0) |
| 163 | verbose = 0; |
| 164 | for (p = types; p->t_name; p++) |
| 165 | if (newtype == p->t_type) |
| 166 | break; |
| 167 | if (p->t_name == 0) { |
| 168 | warnx("internal error: unknown type %d.", newtype); |
| 169 | return; |
| 170 | } |
| 171 | if (newtype == TYPE_L && bytename[0] != '\0') |
| 172 | comret = command("TYPE %s %s", p->t_mode, bytename); |
| 173 | else |
| 174 | comret = command("TYPE %s", p->t_mode); |
| 175 | if (comret == COMPLETE) |
| 176 | curtype = newtype; |
| 177 | verbose = oldverbose; |
| 178 | } |
| 179 | |
| 180 | char *stype[] = { |
| 181 | "type", |
| 182 | "", |
| 183 | 0 |
| 184 | }; |
| 185 | |
| 186 | |
| 187 | |
| 188 | |
| 189 | void |
| 190 | setbinary(int argc, char *argv[]) |
| 191 | { |
| 192 | |
| 193 | stype[1] = "binary"; |
| 194 | settype(2, stype); |
| 195 | } |
| 196 | |
| 197 | void |
| 198 | get(int argc, char *argv[]) |
| 199 | { |
| 200 | |
| 201 | (void)getit(argc, argv, 0, restart_point ? "a+w" : "w" ); |
| 202 | } |
| 203 | |
| 204 | |
| 205 | |
| 206 | |
| 207 | int |
| 208 | getit(int argc, char *argv[], int restartit, const char *mode) |
| 209 | { |
| 210 | int loc = 0; |
| 211 | int rval = 0; |
| 212 | char *oldargv1, *oldargv2, *globargv2; |
| 213 | |
| 214 | if (argc == 2) { |
| |
| 215 | argc++; |
| 216 | argv[2] = argv[1]; |
| 217 | loc++; |
| 218 | } |
| 219 | #ifndef SMALL |
| 220 | if (argc < 2 && !another(&argc, &argv, "remote-file")) |
| 221 | goto usage; |
| 222 | if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) { |
| |
| 223 | usage: |
| 224 | fprintf(ttyout, "usage: %s remote-file [local-file]\n", |
| 225 | argv[0]); |
| 226 | code = -1; |
| 227 | return (0); |
| 228 | } |
| 229 | #endif /* !SMALL */ |
| 230 | oldargv1 = argv[1]; |
| 231 | oldargv2 = argv[2]; |
| 232 | if (!globulize(&argv[2])) { |
| 22 | | Assuming the condition is false | |
|
| |
| 233 | code = -1; |
| 234 | return (0); |
| 235 | } |
| 236 | globargv2 = argv[2]; |
| 237 | if (loc && mcase) { |
| 24 | | Assuming 'mcase' is not equal to 0 | |
|
| |
| 238 | char *tp = argv[1], *tp2, tmpbuf[PATH_MAX]; |
| 239 | |
| 240 | while (*tp && !islower((unsigned char)*tp)) { |
| 26 | | Assuming the condition is false | |
|
| 241 | tp++; |
| 242 | } |
| 243 | if (!*tp) { |
| |
| 244 | tp = argv[2]; |
| 245 | tp2 = tmpbuf; |
| 246 | while ((*tp2 = *tp) != '\0') { |
| 28 | | Assuming the condition is false | |
|
| 29 | | Loop condition is false. Execution continues on line 253 | |
|
| 247 | if (isupper((unsigned char)*tp2)) { |
| 248 | *tp2 = tolower((unsigned char)*tp2); |
| 249 | } |
| 250 | tp++; |
| 251 | tp2++; |
| 252 | } |
| 253 | argv[2] = tmpbuf; |
| 254 | } |
| 255 | } |
| 256 | if (loc && ntflag) |
| |
| 257 | argv[2] = dotrans(argv[2]); |
| 258 | if (loc && mapflag) |
| 31 | | Assuming 'mapflag' is 0 | |
|
| |
| 259 | argv[2] = domap(argv[2]); |
| 260 | #ifndef SMALL |
| 261 | if (restartit) { |
| |
| 262 | struct stat stbuf; |
| 263 | int ret; |
| 264 | |
| 265 | ret = stat(argv[2], &stbuf); |
| 266 | if (restartit == 1) { |
| 267 | restart_point = (ret < 0) ? 0 : stbuf.st_size; |
| 268 | } else { |
| 269 | if (ret == 0) { |
| 270 | time_t mtime; |
| 271 | |
| 272 | mtime = remotemodtime(argv[1], 0); |
| 273 | if (mtime == -1) |
| 274 | goto freegetit; |
| 275 | if (stbuf.st_mtime >= mtime) { |
| 276 | rval = 1; |
| 277 | fprintf(ttyout, |
| 278 | "Local file \"%s\" is newer "\ |
| 279 | "than remote file \"%s\".\n", |
| 280 | argv[2], argv[1]); |
| 281 | goto freegetit; |
| 282 | } |
| 283 | } |
| 284 | } |
| 285 | } |
| 286 | #endif /* !SMALL */ |
| 287 | |
| 288 | recvrequest("RETR", argv[2], argv[1], mode, |
| 289 | argv[1] != oldargv1 || argv[2] != oldargv2 || !interactive, loc); |
| 34 | | Assuming the condition is true | |
|
| 290 | restart_point = 0; |
| 291 | #ifndef SMALL |
| 292 | freegetit: |
| 293 | #endif |
| 294 | if (oldargv2 != globargv2) |
| 35 | | Assuming 'oldargv2' is equal to 'globargv2' | |
|
| |
| 295 | free(globargv2); |
| 296 | return (rval); |
| 37 | | Address of stack memory associated with local variable 'tmpbuf' is still referred to by the stack variable 'xargv' upon returning to the caller. This will be a dangling reference |
|
| 297 | } |
| 298 | |
| 299 | |
| 300 | void |
| 301 | mabort(int signo) |
| 302 | { |
| 303 | int save_errno = errno; |
| 304 | |
| 305 | alarmtimer(0); |
| 306 | (void) write(fileno(ttyout), "\n\r", 2); |
| 307 | #ifndef SMALL |
| 308 | if (mflag && fromatty) { |
| 309 | |
| 310 | if (confirm(mname, NULL)) { |
| 311 | errno = save_errno; |
| 312 | longjmp(jabort, 1); |
| 313 | } |
| 314 | } |
| 315 | #endif /* !SMALL */ |
| 316 | mflag = 0; |
| 317 | errno = save_errno; |
| 318 | longjmp(jabort, 1); |
| 319 | } |
| 320 | |
| 321 | |
| 322 | |
| 323 | |
| 324 | void |
| 325 | mget(int argc, char *argv[]) |
| 326 | { |
| 327 | extern int optind, optreset; |
| 328 | sig_t oldintr; |
| 329 | int xargc = 2; |
| 330 | char *cp, localcwd[PATH_MAX], *xargv[] = { argv[0], NULL, NULL }; |
| 331 | static int restartit = 0; |
| 332 | #ifndef SMALL |
| 333 | extern char *optarg; |
| 334 | const char *errstr; |
| 335 | int ch, i = 1; |
| 336 | char type = 0, *dummyargv[] = { argv[0], ".", NULL }; |
| 337 | FILE *ftemp = NULL; |
| 338 | static int depth = 0, max_depth = 0; |
| 339 | |
| 340 | optind = optreset = 1; |
| 341 | |
| 342 | if (depth) |
| |
| 343 | depth++; |
| 344 | |
| 345 | while ((ch = getopt(argc, argv, "cd:nr")) != -1) { |
| 2 | | Assuming the condition is false | |
|
| 346 | switch(ch) { |
| 347 | case 'c': |
| 348 | restartit = 1; |
| 349 | break; |
| 350 | case 'd': |
| 351 | max_depth = strtonum(optarg, 0, INT_MAX, &errstr); |
| 352 | if (errstr != NULL) { |
| 353 | fprintf(ttyout, "bad depth value, %s: %s\n", |
| 354 | errstr, optarg); |
| 355 | code = -1; |
| 356 | return; |
| 357 | } |
| 358 | break; |
| 359 | case 'n': |
| 360 | restartit = -1; |
| 361 | break; |
| 362 | case 'r': |
| 363 | depth = 1; |
| 364 | break; |
| 365 | default: |
| 366 | goto usage; |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | if (argc - optind < 1 && !another(&argc, &argv, "remote-files")) { |
| 3 | | Assuming the condition is false | |
|
| 371 | usage: |
| 372 | fprintf(ttyout, "usage: %s [-cnr] [-d depth] remote-files\n", |
| 373 | argv[0]); |
| 374 | code = -1; |
| 375 | return; |
| 376 | } |
| 377 | |
| 378 | argv[optind - 1] = argv[0]; |
| 379 | argc -= optind - 1; |
| 380 | argv += optind - 1; |
| 381 | #endif /* !SMALL */ |
| 382 | |
| 383 | mname = argv[0]; |
| 384 | mflag = 1; |
| 385 | if (getcwd(localcwd, sizeof(localcwd)) == NULL) |
| 4 | | Assuming the condition is false | |
|
| |
| 386 | err(1, "can't get cwd"); |
| 387 | |
| 388 | oldintr = signal(SIGINT, mabort); |
| 389 | (void)setjmp(jabort); |
| 390 | while ((cp = |
| 7 | | Assuming the condition is true | |
|
| 391 | #ifdef SMALL |
| 392 | remglob(argv, proxy, NULL)) != NULL |
| 393 | ) { |
| 394 | #else /* SMALL */ |
| 395 | depth ? remglob2(dummyargv, proxy, NULL, &ftemp, &type) : |
| |
| 396 | remglob(argv, proxy, NULL)) != NULL |
| 397 | || (mflag && depth && ++i < argc) |
| 398 | ) { |
| 399 | if (cp == NULL) |
| |
| 400 | continue; |
| 401 | #endif /* SMALL */ |
| 402 | if (*cp == '\0') { |
| 9 | | Assuming the condition is false | |
|
| |
| 403 | mflag = 0; |
| 404 | continue; |
| 405 | } |
| 406 | if (!mflag) |
| 11 | | Assuming 'mflag' is not equal to 0 | |
|
| 407 | continue; |
| 408 | #ifndef SMALL |
| 409 | if (depth && fnmatch(argv[i], cp, FNM_PATHNAME) != 0) |
| 410 | continue; |
| 411 | #endif /* !SMALL */ |
| 412 | if (!fileindir(cp, localcwd)) { |
| 12 | | Assuming the condition is false | |
|
| 413 | fprintf(ttyout, "Skipping non-relative filename `%s'\n", |
| 414 | cp); |
| 415 | continue; |
| 416 | } |
| 417 | #ifndef SMALL |
| 418 | if (type == 'd' && depth == max_depth) |
| 419 | continue; |
| 420 | if (!confirm(argv[0], cp)) |
| 13 | | Assuming the condition is false | |
|
| |
| 421 | continue; |
| 422 | if (type == 'd') { |
| |
| 423 | mkdir(cp, 0755); |
| 424 | if (chdir(cp) != 0) { |
| 425 | warn("local: %s", cp); |
| 426 | continue; |
| 427 | } |
| 428 | |
| 429 | xargv[1] = cp; |
| 430 | cd(xargc, xargv); |
| 431 | if (dirchange != 1) |
| 432 | goto out; |
| 433 | |
| 434 | xargv[1] = "*"; |
| 435 | mget(xargc, xargv); |
| 436 | |
| 437 | xargv[1] = ".."; |
| 438 | cd(xargc, xargv); |
| 439 | if (dirchange != 1) { |
| 440 | mflag = 0; |
| 441 | goto out; |
| 442 | } |
| 443 | |
| 444 | out: |
| 445 | if (chdir("..") != 0) { |
| 446 | warn("local: %s", cp); |
| 447 | mflag = 0; |
| 448 | } |
| 449 | continue; |
| 450 | } |
| 451 | if (type == 's') |
| |
| 452 | |
| 453 | continue; |
| 454 | #endif /* !SMALL */ |
| 455 | xargv[1] = cp; |
| 456 | (void)getit(xargc, xargv, restartit, |
| |
| 457 | (restartit == 1 || restart_point) ? "a+w" : "w"); |
| 17 | | Assuming 'restart_point' is 0 | |
|
| |
| 458 | #ifndef SMALL |
| 459 | if (!mflag && fromatty) { |
| 460 | if (confirm(argv[0], NULL)) |
| 461 | mflag = 1; |
| 462 | } |
| 463 | #endif /* !SMALL */ |
| 464 | } |
| 465 | (void)signal(SIGINT, oldintr); |
| 466 | #ifndef SMALL |
| 467 | if (depth) |
| 468 | depth--; |
| 469 | if (depth == 0 || mflag == 0) |
| 470 | depth = max_depth = mflag = restartit = 0; |
| 471 | #else /* !SMALL */ |
| 472 | mflag = 0; |
| 473 | #endif /* !SMALL */ |
| 474 | } |
| 475 | |
| 476 | |
| 477 | |
| 478 | |
| 479 | void |
| 480 | cd(int argc, char *argv[]) |
| 481 | { |
| 482 | int r; |
| 483 | |
| 484 | #ifndef SMALL |
| 485 | if ((argc < 2 && !another(&argc, &argv, "remote-directory")) || |
| 486 | argc > 2) { |
| 487 | fprintf(ttyout, "usage: %s remote-directory\n", argv[0]); |
| 488 | code = -1; |
| 489 | return; |
| 490 | } |
| 491 | #endif /* !SMALL */ |
| 492 | r = command("CWD %s", argv[1]); |
| 493 | if (r == ERROR && code == 500) { |
| 494 | if (verbose) |
| 495 | fputs("CWD command not recognized, trying XCWD.\n", ttyout); |
| 496 | r = command("XCWD %s", argv[1]); |
| 497 | } |
| 498 | if (r == ERROR && code == 550) { |
| 499 | dirchange = 0; |
| 500 | return; |
| 501 | } |
| 502 | if (r == COMPLETE) |
| 503 | dirchange = 1; |
| 504 | } |
| 505 | |
| 506 | |
| 507 | |
| 508 | |
| 509 | void |
| 510 | disconnect(int argc, char *argv[]) |
| 511 | { |
| 512 | |
| 513 | if (!connected) |
| 514 | return; |
| 515 | (void)command("QUIT"); |
| 516 | if (cout) { |
| 517 | (void)fclose(cout); |
| 518 | } |
| 519 | cout = NULL; |
| 520 | connected = 0; |
| 521 | data = -1; |
| 522 | #ifndef SMALL |
| 523 | if (!proxy) { |
| 524 | macnum = 0; |
| 525 | } |
| 526 | #endif /* !SMALL */ |
| 527 | } |
| 528 | |
| 529 | char * |
| 530 | dotrans(char *name) |
| 531 | { |
| 532 | static char new[PATH_MAX]; |
| 533 | char *cp1, *cp2 = new; |
| 534 | int i, ostop, found; |
| 535 | |
| 536 | for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++) |
| 537 | continue; |
| 538 | for (cp1 = name; *cp1; cp1++) { |
| 539 | found = 0; |
| 540 | for (i = 0; *(ntin + i) && i < 16; i++) { |
| 541 | if (*cp1 == *(ntin + i)) { |
| 542 | found++; |
| 543 | if (i < ostop) { |
| 544 | *cp2++ = *(ntout + i); |
| 545 | } |
| 546 | break; |
| 547 | } |
| 548 | } |
| 549 | if (!found) { |
| 550 | *cp2++ = *cp1; |
| 551 | } |
| 552 | } |
| 553 | *cp2 = '\0'; |
| 554 | return (new); |
| 555 | } |
| 556 | |
| 557 | char * |
| 558 | domap(char *name) |
| 559 | { |
| 560 | static char new[PATH_MAX]; |
| 561 | char *cp1 = name, *cp2 = mapin; |
| 562 | char *tp[9], *te[9]; |
| 563 | int i, toks[9], toknum = 0, match = 1; |
| 564 | |
| 565 | for (i=0; i < 9; ++i) { |
| 566 | toks[i] = 0; |
| 567 | } |
| 568 | while (match && *cp1 && *cp2) { |
| 569 | switch (*cp2) { |
| 570 | case '\\': |
| 571 | if (*++cp2 != *cp1) { |
| 572 | match = 0; |
| 573 | } |
| 574 | break; |
| 575 | case '$': |
| 576 | if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { |
| 577 | if (*cp1 != *(++cp2+1)) { |
| 578 | toks[toknum = *cp2 - '1']++; |
| 579 | tp[toknum] = cp1; |
| 580 | while (*++cp1 && *(cp2+1) |
| 581 | != *cp1); |
| 582 | te[toknum] = cp1; |
| 583 | } |
| 584 | cp2++; |
| 585 | break; |
| 586 | } |
| 587 | |
| 588 | default: |
| 589 | if (*cp2 != *cp1) { |
| 590 | match = 0; |
| 591 | } |
| 592 | break; |
| 593 | } |
| 594 | if (match && *cp1) { |
| 595 | cp1++; |
| 596 | } |
| 597 | if (match && *cp2) { |
| 598 | cp2++; |
| 599 | } |
| 600 | } |
| 601 | if (!match && *cp1) |
| 602 | { |
| 603 | toks[toknum] = 0; |
| 604 | } |
| 605 | cp1 = new; |
| 606 | *cp1 = '\0'; |
| 607 | cp2 = mapout; |
| 608 | while (*cp2) { |
| 609 | match = 0; |
| 610 | switch (*cp2) { |
| 611 | case '\\': |
| 612 | if (*(cp2 + 1)) { |
| 613 | *cp1++ = *++cp2; |
| 614 | } |
| 615 | break; |
| 616 | case '[': |
| 617 | LOOP: |
| 618 | if (*++cp2 == '$' && isdigit((unsigned char)*(cp2 + 1))) { |
| 619 | if (*++cp2 == '0') { |
| 620 | char *cp3 = name; |
| 621 | |
| 622 | while (*cp3) { |
| 623 | *cp1++ = *cp3++; |
| 624 | } |
| 625 | match = 1; |
| 626 | } else if (toks[toknum = *cp2 - '1']) { |
| 627 | char *cp3 = tp[toknum]; |
| 628 | |
| 629 | while (cp3 != te[toknum]) { |
| 630 | *cp1++ = *cp3++; |
| 631 | } |
| 632 | match = 1; |
| 633 | } |
| 634 | } else { |
| 635 | while (*cp2 && *cp2 != ',' && |
| 636 | *cp2 != ']') { |
| 637 | if (*cp2 == '\\') { |
| 638 | cp2++; |
| 639 | } else if (*cp2 == '$' && |
| 640 | isdigit((unsigned char)*(cp2 + 1))) { |
| 641 | if (*++cp2 == '0') { |
| 642 | char *cp3 = name; |
| 643 | |
| 644 | while (*cp3) { |
| 645 | *cp1++ = *cp3++; |
| 646 | } |
| 647 | } else if (toks[toknum = |
| 648 | *cp2 - '1']) { |
| 649 | char *cp3=tp[toknum]; |
| 650 | |
| 651 | while (cp3 != |
| 652 | te[toknum]) { |
| 653 | *cp1++ = *cp3++; |
| 654 | } |
| 655 | } |
| 656 | } else if (*cp2) { |
| 657 | *cp1++ = *cp2++; |
| 658 | } |
| 659 | } |
| 660 | if (!*cp2) { |
| 661 | fputs( |
| 662 | "nmap: unbalanced brackets.\n", ttyout); |
| 663 | return (name); |
| 664 | } |
| 665 | match = 1; |
| 666 | cp2--; |
| 667 | } |
| 668 | if (match) { |
| 669 | while (*++cp2 && *cp2 != ']') { |
| 670 | if (*cp2 == '\\' && *(cp2 + 1)) { |
| 671 | cp2++; |
| 672 | } |
| 673 | } |
| 674 | if (!*cp2) { |
| 675 | fputs( |
| 676 | "nmap: unbalanced brackets.\n", ttyout); |
| 677 | return (name); |
| 678 | } |
| 679 | break; |
| 680 | } |
| 681 | switch (*++cp2) { |
| 682 | case ',': |
| 683 | goto LOOP; |
| 684 | case ']': |
| 685 | break; |
| 686 | default: |
| 687 | cp2--; |
| 688 | goto LOOP; |
| 689 | } |
| 690 | break; |
| 691 | case '$': |
| 692 | if (isdigit((unsigned char)*(cp2 + 1))) { |
| 693 | if (*++cp2 == '0') { |
| 694 | char *cp3 = name; |
| 695 | |
| 696 | while (*cp3) { |
| 697 | *cp1++ = *cp3++; |
| 698 | } |
| 699 | } else if (toks[toknum = *cp2 - '1']) { |
| 700 | char *cp3 = tp[toknum]; |
| 701 | |
| 702 | while (cp3 != te[toknum]) { |
| 703 | *cp1++ = *cp3++; |
| 704 | } |
| 705 | } |
| 706 | break; |
| 707 | } |
| 708 | |
| 709 | default: |
| 710 | *cp1++ = *cp2; |
| 711 | break; |
| 712 | } |
| 713 | cp2++; |
| 714 | } |
| 715 | *cp1 = '\0'; |
| 716 | if (!*new) { |
| 717 | return (name); |
| 718 | } |
| 719 | return (new); |
| 720 | } |
| 721 | |