[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.6

1.6     ! krw         1: /*     $OpenBSD: small.c,v 1.5 2015/10/18 03:04:11 mmcc 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.
                      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>
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: /*ARGSUSED*/
                    190: void
                    191: setbinary(int argc, char *argv[])
                    192: {
                    193:
                    194:        stype[1] = "binary";
                    195:        settype(2, stype);
                    196: }
                    197:
                    198: void
                    199: get(int argc, char *argv[])
                    200: {
                    201:
                    202:        (void)getit(argc, argv, 0, restart_point ? "a+w" : "w" );
                    203: }
                    204:
                    205: /*
                    206:  * Receive one file.
                    207:  */
                    208: int
                    209: getit(int argc, char *argv[], int restartit, const char *mode)
                    210: {
                    211:        int loc = 0;
                    212:        int rval = 0;
                    213:        char *oldargv1, *oldargv2, *globargv2;
                    214:
                    215:        if (argc == 2) {
                    216:                argc++;
                    217:                argv[2] = argv[1];
                    218:                loc++;
                    219:        }
                    220: #ifndef SMALL
                    221:        if (argc < 2 && !another(&argc, &argv, "remote-file"))
                    222:                goto usage;
                    223:        if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) {
                    224: usage:
                    225:                fprintf(ttyout, "usage: %s remote-file [local-file]\n",
                    226:                    argv[0]);
                    227:                code = -1;
                    228:                return (0);
                    229:        }
                    230: #endif /* !SMALL */
                    231:        oldargv1 = argv[1];
                    232:        oldargv2 = argv[2];
                    233:        if (!globulize(&argv[2])) {
                    234:                code = -1;
                    235:                return (0);
                    236:        }
                    237:        globargv2 = argv[2];
                    238:        if (loc && mcase) {
1.3       deraadt   239:                char *tp = argv[1], *tp2, tmpbuf[PATH_MAX];
1.1       martynas  240:
1.5       mmcc      241:                while (*tp && !islower((unsigned char)*tp)) {
1.1       martynas  242:                        tp++;
                    243:                }
                    244:                if (!*tp) {
                    245:                        tp = argv[2];
                    246:                        tp2 = tmpbuf;
                    247:                        while ((*tp2 = *tp) != '\0') {
1.5       mmcc      248:                                if (isupper((unsigned char)*tp2)) {
                    249:                                        *tp2 = tolower((unsigned char)*tp2);
1.1       martynas  250:                                }
                    251:                                tp++;
                    252:                                tp2++;
                    253:                        }
                    254:                        argv[2] = tmpbuf;
                    255:                }
                    256:        }
                    257:        if (loc && ntflag)
                    258:                argv[2] = dotrans(argv[2]);
                    259:        if (loc && mapflag)
                    260:                argv[2] = domap(argv[2]);
                    261: #ifndef SMALL
                    262:        if (restartit) {
                    263:                struct stat stbuf;
                    264:                int ret;
                    265:
                    266:                ret = stat(argv[2], &stbuf);
                    267:                if (restartit == 1) {
                    268:                        restart_point = (ret < 0) ? 0 : stbuf.st_size;
                    269:                } else {
                    270:                        if (ret == 0) {
                    271:                                time_t mtime;
                    272:
                    273:                                mtime = remotemodtime(argv[1], 0);
                    274:                                if (mtime == -1)
                    275:                                        goto freegetit;
                    276:                                if (stbuf.st_mtime >= mtime) {
                    277:                                        rval = 1;
1.6     ! krw       278:                                        fprintf(ttyout,
        !           279:                                                "Local file \"%s\" is newer "\
        !           280:                                                "than remote file \"%s\".\n",
        !           281:                                                argv[2], argv[1]);
1.1       martynas  282:                                        goto freegetit;
                    283:                                }
                    284:                        }
                    285:                }
                    286:        }
                    287: #endif /* !SMALL */
                    288:
                    289:        recvrequest("RETR", argv[2], argv[1], mode,
                    290:            argv[1] != oldargv1 || argv[2] != oldargv2 || !interactive, loc);
                    291:        restart_point = 0;
                    292: freegetit:
                    293:        if (oldargv2 != globargv2)      /* free up after globulize() */
                    294:                free(globargv2);
                    295:        return (rval);
                    296: }
                    297:
                    298: /* XXX - Signal race. */
                    299: /* ARGSUSED */
                    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;
                    329:        int ch, 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;
                    335:        int 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) {
                    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: /* ARGSUSED */
                    510: void
                    511: disconnect(int argc, char *argv[])
                    512: {
                    513:
                    514:        if (!connected)
                    515:                return;
                    516:        (void)command("QUIT");
                    517:        if (cout) {
                    518:                (void)fclose(cout);
                    519:        }
                    520:        cout = NULL;
                    521:        connected = 0;
                    522:        data = -1;
                    523: #ifndef SMALL
                    524:        if (!proxy) {
                    525:                macnum = 0;
                    526:        }
                    527: #endif /* !SMALL */
                    528: }
                    529:
                    530: char *
                    531: dotrans(char *name)
                    532: {
1.3       deraadt   533:        static char new[PATH_MAX];
1.1       martynas  534:        char *cp1, *cp2 = new;
                    535:        int i, ostop, found;
                    536:
                    537:        for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
                    538:                continue;
                    539:        for (cp1 = name; *cp1; cp1++) {
                    540:                found = 0;
                    541:                for (i = 0; *(ntin + i) && i < 16; i++) {
                    542:                        if (*cp1 == *(ntin + i)) {
                    543:                                found++;
                    544:                                if (i < ostop) {
                    545:                                        *cp2++ = *(ntout + i);
                    546:                                }
                    547:                                break;
                    548:                        }
                    549:                }
                    550:                if (!found) {
                    551:                        *cp2++ = *cp1;
                    552:                }
                    553:        }
                    554:        *cp2 = '\0';
                    555:        return (new);
                    556: }
                    557:
                    558: char *
                    559: domap(char *name)
                    560: {
1.3       deraadt   561:        static char new[PATH_MAX];
1.1       martynas  562:        char *cp1 = name, *cp2 = mapin;
                    563:        char *tp[9], *te[9];
                    564:        int i, toks[9], toknum = 0, match = 1;
                    565:
                    566:        for (i=0; i < 9; ++i) {
                    567:                toks[i] = 0;
                    568:        }
                    569:        while (match && *cp1 && *cp2) {
                    570:                switch (*cp2) {
                    571:                        case '\\':
                    572:                                if (*++cp2 != *cp1) {
                    573:                                        match = 0;
                    574:                                }
                    575:                                break;
                    576:                        case '$':
                    577:                                if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
                    578:                                        if (*cp1 != *(++cp2+1)) {
                    579:                                                toks[toknum = *cp2 - '1']++;
                    580:                                                tp[toknum] = cp1;
                    581:                                                while (*++cp1 && *(cp2+1)
                    582:                                                        != *cp1);
                    583:                                                te[toknum] = cp1;
                    584:                                        }
                    585:                                        cp2++;
                    586:                                        break;
                    587:                                }
                    588:                                /* FALLTHROUGH */
                    589:                        default:
                    590:                                if (*cp2 != *cp1) {
                    591:                                        match = 0;
                    592:                                }
                    593:                                break;
                    594:                }
                    595:                if (match && *cp1) {
                    596:                        cp1++;
                    597:                }
                    598:                if (match && *cp2) {
                    599:                        cp2++;
                    600:                }
                    601:        }
                    602:        if (!match && *cp1) /* last token mismatch */
                    603:        {
                    604:                toks[toknum] = 0;
                    605:        }
                    606:        cp1 = new;
                    607:        *cp1 = '\0';
                    608:        cp2 = mapout;
                    609:        while (*cp2) {
                    610:                match = 0;
                    611:                switch (*cp2) {
                    612:                        case '\\':
                    613:                                if (*(cp2 + 1)) {
                    614:                                        *cp1++ = *++cp2;
                    615:                                }
                    616:                                break;
                    617:                        case '[':
                    618: LOOP:
1.5       mmcc      619:                                if (*++cp2 == '$' && isdigit((unsigned char)*(cp2 + 1))) {
1.1       martynas  620:                                        if (*++cp2 == '0') {
                    621:                                                char *cp3 = name;
                    622:
                    623:                                                while (*cp3) {
                    624:                                                        *cp1++ = *cp3++;
                    625:                                                }
                    626:                                                match = 1;
                    627:                                        }
                    628:                                        else if (toks[toknum = *cp2 - '1']) {
                    629:                                                char *cp3 = tp[toknum];
                    630:
                    631:                                                while (cp3 != te[toknum]) {
                    632:                                                        *cp1++ = *cp3++;
                    633:                                                }
                    634:                                                match = 1;
                    635:                                        }
                    636:                                }
                    637:                                else {
                    638:                                        while (*cp2 && *cp2 != ',' &&
                    639:                                            *cp2 != ']') {
                    640:                                                if (*cp2 == '\\') {
                    641:                                                        cp2++;
                    642:                                                }
                    643:                                                else if (*cp2 == '$' &&
1.5       mmcc      644:                                                        isdigit((unsigned char)*(cp2 + 1))) {
1.1       martynas  645:                                                        if (*++cp2 == '0') {
                    646:                                                           char *cp3 = name;
                    647:
                    648:                                                           while (*cp3) {
                    649:                                                                *cp1++ = *cp3++;
                    650:                                                           }
                    651:                                                        }
                    652:                                                        else if (toks[toknum =
                    653:                                                            *cp2 - '1']) {
                    654:                                                           char *cp3=tp[toknum];
                    655:
                    656:                                                           while (cp3 !=
                    657:                                                                  te[toknum]) {
                    658:                                                                *cp1++ = *cp3++;
                    659:                                                           }
                    660:                                                        }
                    661:                                                }
                    662:                                                else if (*cp2) {
                    663:                                                        *cp1++ = *cp2++;
                    664:                                                }
                    665:                                        }
                    666:                                        if (!*cp2) {
                    667:                                                fputs(
                    668: "nmap: unbalanced brackets.\n", ttyout);
                    669:                                                return (name);
                    670:                                        }
                    671:                                        match = 1;
                    672:                                        cp2--;
                    673:                                }
                    674:                                if (match) {
                    675:                                        while (*++cp2 && *cp2 != ']') {
                    676:                                              if (*cp2 == '\\' && *(cp2 + 1)) {
                    677:                                                        cp2++;
                    678:                                              }
                    679:                                        }
                    680:                                        if (!*cp2) {
                    681:                                                fputs(
                    682: "nmap: unbalanced brackets.\n", ttyout);
                    683:                                                return (name);
                    684:                                        }
                    685:                                        break;
                    686:                                }
                    687:                                switch (*++cp2) {
                    688:                                        case ',':
                    689:                                                goto LOOP;
                    690:                                        case ']':
                    691:                                                break;
                    692:                                        default:
                    693:                                                cp2--;
                    694:                                                goto LOOP;
                    695:                                }
                    696:                                break;
                    697:                        case '$':
1.5       mmcc      698:                                if (isdigit((unsigned char)*(cp2 + 1))) {
1.1       martynas  699:                                        if (*++cp2 == '0') {
                    700:                                                char *cp3 = name;
                    701:
                    702:                                                while (*cp3) {
                    703:                                                        *cp1++ = *cp3++;
                    704:                                                }
                    705:                                        }
                    706:                                        else if (toks[toknum = *cp2 - '1']) {
                    707:                                                char *cp3 = tp[toknum];
                    708:
                    709:                                                while (cp3 != te[toknum]) {
                    710:                                                        *cp1++ = *cp3++;
                    711:                                                }
                    712:                                        }
                    713:                                        break;
                    714:                                }
                    715:                                /* FALLTHROUGH */
                    716:                        default:
                    717:                                *cp1++ = *cp2;
                    718:                                break;
                    719:                }
                    720:                cp2++;
                    721:        }
                    722:        *cp1 = '\0';
                    723:        if (!*new) {
                    724:                return (name);
                    725:        }
                    726:        return (new);
                    727: }
                    728: