Bug Summary

File:src/usr.bin/ftp/small.c
Warning:line 296, column 2
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

Annotated Source Code

Press '?' to see keyboard shortcuts

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/* $OpenBSD: small.c,v 1.13 2023/03/08 04:43:11 guenther Exp $ */
2/* $NetBSD: cmds.c,v 1.27 1997/08/18 10:20:15 lukem Exp $ */
3
4/*
5 * Copyright (C) 1997 and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1985, 1989, 1993, 1994
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62/*
63 * FTP User Program -- Command Routines.
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(*__errno()).h>
81
82#include "ftp_var.h"
83#include "pathnames.h"
84#include "small.h"
85
86jmp_buf jabort;
87char *mname;
88char *home = "/";
89
90struct types {
91 char *t_name;
92 char *t_mode;
93 int t_type;
94} types[] = {
95 { "ascii", "A", TYPE_A1 },
96 { "binary", "I", TYPE_I3 },
97 { "image", "I", TYPE_I3 },
98 { NULL((void *)0) }
99};
100
101/*
102 * Set transfer type.
103 */
104void
105settype(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 == COMPLETE2) {
138 (void)strlcpy(typename, p->t_name, sizeof typename);
139 curtype = type = p->t_type;
140 }
141}
142
143/*
144 * Internal form of settype; changes current type in use with server
145 * without changing our notion of the type for data transfers.
146 * Used to change to and from ascii for listings.
147 */
148void
149changetype(int newtype, int show)
150{
151 struct types *p;
152 int comret, oldverbose = verbose;
153
154 if (newtype == 0)
155 newtype = TYPE_I3;
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_L4 && 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 == COMPLETE2)
176 curtype = newtype;
177 verbose = oldverbose;
178}
179
180char *stype[] = {
181 "type",
182 "",
183 0
184};
185
186/*
187 * Set binary transfer type.
188 */
189void
190setbinary(int argc, char *argv[])
191{
192
193 stype[1] = "binary";
194 settype(2, stype);
195}
196
197void
198get(int argc, char *argv[])
199{
200
201 (void)getit(argc, argv, 0, restart_point ? "a+w" : "w" );
202}
203
204/*
205 * Receive one file.
206 */
207int
208getit(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
19.1
'argc' is equal to 2
== 2) {
20
Taking true branch
215 argc++;
216 argv[2] = argv[1];
217 loc++;
218 }
219#ifndef SMALL
220 if (argc
20.1
'argc' is >= 2
< 2 && !another(&argc, &argv, "remote-file"))
221 goto usage;
222 if ((argc
20.2
'argc' is >= 3
< 3 && !another(&argc, &argv, "local-file")) || argc
20.3
'argc' is <= 3
> 3) {
21
Taking false branch
223usage:
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
23
Taking false branch
233 code = -1;
234 return (0);
235 }
236 globargv2 = argv[2];
237 if (loc
23.1
'loc' is 1
&& mcase) {
24
Assuming 'mcase' is not equal to 0
25
Taking true branch
238 char *tp = argv[1], *tp2, tmpbuf[PATH_MAX1024];
239
240 while (*tp && !islower((unsigned char)*tp)) {
26
Assuming the condition is false
241 tp++;
242 }
243 if (!*tp) {
27
Taking true branch
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
29.1
'loc' is 1
&& ntflag)
30
Assuming 'ntflag' is 0
257 argv[2] = dotrans(argv[2]);
258 if (loc
30.1
'loc' is 1
&& mapflag)
31
Assuming 'mapflag' is 0
32
Taking false branch
259 argv[2] = domap(argv[2]);
260#ifndef SMALL
261 if (restartit
32.1
'restartit' is 0
) {
33
Taking false branch
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_mtimest_mtim.tv_sec >= 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
292freegetit:
293#endif
294 if (oldargv2 != globargv2) /* free up after globulize() */
35
Assuming 'oldargv2' is equal to 'globargv2'
36
Taking false branch
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/* XXX - Signal race. */
300void
301mabort(int signo)
302{
303 int save_errno = errno(*__errno());
304
305 alarmtimer(0);
306 (void) write(fileno(ttyout)(!__isthreaded ? ((ttyout)->_file) : (fileno)(ttyout)), "\n\r", 2);
307#ifndef SMALL
308 if (mflag && fromatty) {
309 /* XXX signal race, crazy unbelievable stdio misuse */
310 if (confirm(mname, NULL((void *)0))) {
311 errno(*__errno()) = save_errno;
312 longjmp(jabort, 1);
313 }
314 }
315#endif /* !SMALL */
316 mflag = 0;
317 errno(*__errno()) = save_errno;
318 longjmp(jabort, 1);
319}
320
321/*
322 * Get multiple files.
323 */
324void
325mget(int argc, char *argv[])
326{
327 extern int optind, optreset;
328 sig_t oldintr;
329 int xargc = 2;
330 char *cp, localcwd[PATH_MAX1024], *xargv[] = { argv[0], NULL((void *)0), NULL((void *)0) };
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((void *)0) };
337 FILE *ftemp = NULL((void *)0);
338 static int depth = 0, max_depth = 0;
339
340 optind = optreset = 1;
341
342 if (depth
0.1
'depth' is 0
)
1
Taking false branch
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_MAX0x7fffffff, &errstr);
352 if (errstr != NULL((void *)0)) {
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
371usage:
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((void *)0))
4
Assuming the condition is false
5
Taking false branch
386 err(1, "can't get cwd");
387
388 oldintr = signal(SIGINT2, mabort);
389 (void)setjmp(jabort);
390 while ((cp =
7
Assuming the condition is true
391#ifdef SMALL
392 remglob(argv, proxy, NULL((void *)0))) != NULL((void *)0)
393 ) {
394#else /* SMALL */
395 depth
5.1
'depth' is 0
? remglob2(dummyargv, proxy, NULL((void *)0), &ftemp, &type) :
6
'?' condition is false
396 remglob(argv, proxy, NULL((void *)0))) != NULL((void *)0)
397 || (mflag && depth && ++i < argc)
398 ) {
399 if (cp
7.1
'cp' is not equal to NULL
== NULL((void *)0))
8
Taking false branch
400 continue;
401#endif /* SMALL */
402 if (*cp == '\0') {
9
Assuming the condition is false
10
Taking false branch
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
11.1
'depth' is 0
&& fnmatch(argv[i], cp, FNM_PATHNAME0x02) != 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
14
Taking false branch
421 continue;
422 if (type == 'd') {
15
Taking false branch
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
444out:
445 if (chdir("..") != 0) {
446 warn("local: %s", cp);
447 mflag = 0;
448 }
449 continue;
450 }
451 if (type == 's')
16
Taking false branch
452 /* Currently ignored. */
453 continue;
454#endif /* !SMALL */
455 xargv[1] = cp;
456 (void)getit(xargc, xargv, restartit,
19
Calling 'getit'
457 (restartit
16.1
'restartit' is not equal to 1
== 1 || restart_point) ? "a+w" : "w")
;
17
Assuming 'restart_point' is 0
18
'?' condition is false
458#ifndef SMALL
459 if (!mflag && fromatty) {
460 if (confirm(argv[0], NULL((void *)0)))
461 mflag = 1;
462 }
463#endif /* !SMALL */
464 }
465 (void)signal(SIGINT2, 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 * Set current working directory on remote machine.
478 */
479void
480cd(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 == ERROR5 && 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 == ERROR5 && code == 550) {
499 dirchange = 0;
500 return;
501 }
502 if (r == COMPLETE2)
503 dirchange = 1;
504}
505
506/*
507 * Terminate session, but don't exit.
508 */
509void
510disconnect(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((void *)0);
520 connected = 0;
521 data = -1;
522#ifndef SMALL
523 if (!proxy) {
524 macnum = 0;
525 }
526#endif /* !SMALL */
527}
528
529char *
530dotrans(char *name)
531{
532 static char new[PATH_MAX1024];
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
557char *
558domap(char *name)
559{
560 static char new[PATH_MAX1024];
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 /* FALLTHROUGH */
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) /* last token mismatch */
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 '[':
617LOOP:
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 /* FALLTHROUGH */
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