[BACK]Return to small.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ftp

Annotation of src/usr.bin/ftp/small.c, Revision 1.13

1.13    ! guenther    1: /*     $OpenBSD: small.c,v 1.12 2019/11/18 04:37:35 deraadt Exp $      */
1.1       martynas    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.
1.9       krw         7:  *
1.1       martynas    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.
1.9       krw        19:  *
1.1       martynas   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>
1.2       deraadt    80: #include <errno.h>
1.1       martynas   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[] = {
1.4       tedu       95:        { "ascii",      "A",    TYPE_A },
                     96:        { "binary",     "I",    TYPE_I },
                     97:        { "image",      "I",    TYPE_I },
1.1       martynas   98:        { NULL }
                     99: };
                    100:
                    101: /*
                    102:  * Set transfer type.
                    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:        }
1.4       tedu      136:        comret = command("TYPE %s", p->t_mode);
1.1       martynas  137:        if (comret == COMPLETE) {
                    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:  */
                    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:  * Set binary transfer type.
                    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:  * Receive one file.
                    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])) {
                    233:                code = -1;
                    234:                return (0);
                    235:        }
                    236:        globargv2 = argv[2];
                    237:        if (loc && mcase) {
1.3       deraadt   238:                char *tp = argv[1], *tp2, tmpbuf[PATH_MAX];
1.1       martynas  239:
1.5       mmcc      240:                while (*tp && !islower((unsigned char)*tp)) {
1.1       martynas  241:                        tp++;
                    242:                }
                    243:                if (!*tp) {
                    244:                        tp = argv[2];
                    245:                        tp2 = tmpbuf;
                    246:                        while ((*tp2 = *tp) != '\0') {
1.5       mmcc      247:                                if (isupper((unsigned char)*tp2)) {
                    248:                                        *tp2 = tolower((unsigned char)*tp2);
1.1       martynas  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)
                    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;
1.6       krw       277:                                        fprintf(ttyout,
                    278:                                                "Local file \"%s\" is newer "\
                    279:                                                "than remote file \"%s\".\n",
                    280:                                                argv[2], argv[1]);
1.1       martynas  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);
                    290:        restart_point = 0;
1.8       krw       291: #ifndef SMALL
1.1       martynas  292: freegetit:
1.8       krw       293: #endif
1.1       martynas  294:        if (oldargv2 != globargv2)      /* free up after globulize() */
                    295:                free(globargv2);
                    296:        return (rval);
                    297: }
                    298:
                    299: /* XXX - Signal race. */
                    300: void
                    301: mabort(int signo)
                    302: {
1.2       deraadt   303:        int save_errno = errno;
                    304:
1.1       martynas  305:        alarmtimer(0);
1.2       deraadt   306:        (void) write(fileno(ttyout), "\n\r", 2);
1.1       martynas  307: #ifndef SMALL
1.2       deraadt   308:        if (mflag && fromatty) {
                    309:                /* XXX signal race, crazy unbelievable stdio misuse */
                    310:                if (confirm(mname, NULL)) {
                    311:                        errno = save_errno;
1.1       martynas  312:                        longjmp(jabort, 1);
1.2       deraadt   313:                }
                    314:        }
1.1       martynas  315: #endif /* !SMALL */
                    316:        mflag = 0;
1.2       deraadt   317:        errno = save_errno;
1.1       martynas  318:        longjmp(jabort, 1);
                    319: }
                    320:
                    321: /*
                    322:  * Get multiple files.
                    323:  */
                    324: void
                    325: mget(int argc, char *argv[])
                    326: {
                    327:        extern int optind, optreset;
                    328:        sig_t oldintr;
1.7       krw       329:        int xargc = 2;
1.3       deraadt   330:        char *cp, localcwd[PATH_MAX], *xargv[] = { argv[0], NULL, NULL };
1.1       martynas  331:        static int restartit = 0;
                    332: #ifndef SMALL
                    333:        extern char *optarg;
                    334:        const char *errstr;
1.7       krw       335:        int ch, i = 1;
1.1       martynas  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) {
                    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")) {
                    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)
                    386:                err(1, "can't get cwd");
                    387:
                    388:        oldintr = signal(SIGINT, mabort);
                    389:        (void)setjmp(jabort);
                    390:        while ((cp =
                    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') {
                    403:                        mflag = 0;
                    404:                        continue;
                    405:                }
                    406:                if (!mflag)
                    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)) {
                    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))
                    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:                        /* Currently ignored. */
                    453:                        continue;
                    454: #endif /* !SMALL */
                    455:                xargv[1] = cp;
                    456:                (void)getit(xargc, xargv, restartit,
                    457:                    (restartit == 1 || restart_point) ? "a+w" : "w");
                    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:  * Set current working directory on remote machine.
                    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:  * Terminate session, but don't exit.
                    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: {
1.3       deraadt   532:        static char new[PATH_MAX];
1.1       martynas  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: {
1.3       deraadt   560:        static char new[PATH_MAX];
1.1       martynas  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 '[':
                    617: LOOP:
1.5       mmcc      618:                                if (*++cp2 == '$' && isdigit((unsigned char)*(cp2 + 1))) {
1.1       martynas  619:                                        if (*++cp2 == '0') {
                    620:                                                char *cp3 = name;
                    621:
                    622:                                                while (*cp3) {
                    623:                                                        *cp1++ = *cp3++;
                    624:                                                }
                    625:                                                match = 1;
1.12      deraadt   626:                                        } else if (toks[toknum = *cp2 - '1']) {
1.1       martynas  627:                                                char *cp3 = tp[toknum];
                    628:
                    629:                                                while (cp3 != te[toknum]) {
                    630:                                                        *cp1++ = *cp3++;
                    631:                                                }
                    632:                                                match = 1;
                    633:                                        }
1.12      deraadt   634:                                } else {
1.1       martynas  635:                                        while (*cp2 && *cp2 != ',' &&
                    636:                                            *cp2 != ']') {
                    637:                                                if (*cp2 == '\\') {
                    638:                                                        cp2++;
1.12      deraadt   639:                                                } else if (*cp2 == '$' &&
                    640:                                                    isdigit((unsigned char)*(cp2 + 1))) {
1.1       martynas  641:                                                        if (*++cp2 == '0') {
                    642:                                                           char *cp3 = name;
                    643:
                    644:                                                           while (*cp3) {
                    645:                                                                *cp1++ = *cp3++;
                    646:                                                           }
1.12      deraadt   647:                                                        } else if (toks[toknum =
1.1       martynas  648:                                                            *cp2 - '1']) {
1.12      deraadt   649:                                                                char *cp3=tp[toknum];
1.1       martynas  650:
1.12      deraadt   651:                                                                while (cp3 !=
                    652:                                                                    te[toknum]) {
                    653:                                                                        *cp1++ = *cp3++;
                    654:                                                                }
1.1       martynas  655:                                                        }
1.12      deraadt   656:                                                } else if (*cp2) {
1.1       martynas  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 != ']') {
1.12      deraadt   670:                                                if (*cp2 == '\\' && *(cp2 + 1)) {
1.1       martynas  671:                                                        cp2++;
1.12      deraadt   672:                                                }
1.1       martynas  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 '$':
1.5       mmcc      692:                                if (isdigit((unsigned char)*(cp2 + 1))) {
1.1       martynas  693:                                        if (*++cp2 == '0') {
                    694:                                                char *cp3 = name;
                    695:
                    696:                                                while (*cp3) {
                    697:                                                        *cp1++ = *cp3++;
                    698:                                                }
1.12      deraadt   699:                                        } else if (toks[toknum = *cp2 - '1']) {
1.1       martynas  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: