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

1.5     ! mmcc        1: /*     $OpenBSD: small.c,v 1.4 2015/01/30 04:45:45 tedu 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;
                    278:                                        goto freegetit;
                    279:                                }
                    280:                        }
                    281:                }
                    282:        }
                    283: #endif /* !SMALL */
                    284:
                    285:        recvrequest("RETR", argv[2], argv[1], mode,
                    286:            argv[1] != oldargv1 || argv[2] != oldargv2 || !interactive, loc);
                    287:        restart_point = 0;
                    288: freegetit:
                    289:        if (oldargv2 != globargv2)      /* free up after globulize() */
                    290:                free(globargv2);
                    291:        return (rval);
                    292: }
                    293:
                    294: /* XXX - Signal race. */
                    295: /* ARGSUSED */
                    296: void
                    297: mabort(int signo)
                    298: {
1.2       deraadt   299:        int save_errno = errno;
                    300:
1.1       martynas  301:        alarmtimer(0);
1.2       deraadt   302:        (void) write(fileno(ttyout), "\n\r", 2);
1.1       martynas  303: #ifndef SMALL
1.2       deraadt   304:        if (mflag && fromatty) {
                    305:                /* XXX signal race, crazy unbelievable stdio misuse */
                    306:                if (confirm(mname, NULL)) {
                    307:                        errno = save_errno;
1.1       martynas  308:                        longjmp(jabort, 1);
1.2       deraadt   309:                }
                    310:        }
1.1       martynas  311: #endif /* !SMALL */
                    312:        mflag = 0;
1.2       deraadt   313:        errno = save_errno;
1.1       martynas  314:        longjmp(jabort, 1);
                    315: }
                    316:
                    317: /*
                    318:  * Get multiple files.
                    319:  */
                    320: void
                    321: mget(int argc, char *argv[])
                    322: {
                    323:        extern int optind, optreset;
                    324:        sig_t oldintr;
                    325:        int ch, xargc = 2;
1.3       deraadt   326:        char *cp, localcwd[PATH_MAX], *xargv[] = { argv[0], NULL, NULL };
1.1       martynas  327:        static int restartit = 0;
                    328: #ifndef SMALL
                    329:        extern char *optarg;
                    330:        const char *errstr;
                    331:        int i = 1;
                    332:        char type = 0, *dummyargv[] = { argv[0], ".", NULL };
                    333:        FILE *ftemp = NULL;
                    334:        static int depth = 0, max_depth = 0;
                    335:
                    336:        optind = optreset = 1;
                    337:
                    338:        if (depth)
                    339:                depth++;
                    340:
                    341:        while ((ch = getopt(argc, argv, "cd:nr")) != -1) {
                    342:                switch(ch) {
                    343:                case 'c':
                    344:                        restartit = 1;
                    345:                        break;
                    346:                case 'd':
                    347:                        max_depth = strtonum(optarg, 0, INT_MAX, &errstr);
                    348:                        if (errstr != NULL) {
                    349:                                fprintf(ttyout, "bad depth value, %s: %s\n",
                    350:                                    errstr, optarg);
                    351:                                code = -1;
                    352:                                return;
                    353:                        }
                    354:                        break;
                    355:                case 'n':
                    356:                        restartit = -1;
                    357:                        break;
                    358:                case 'r':
                    359:                        depth = 1;
                    360:                        break;
                    361:                default:
                    362:                        goto usage;
                    363:                }
                    364:        }
                    365:
                    366:        if (argc - optind < 1 && !another(&argc, &argv, "remote-files")) {
                    367: usage:
                    368:                fprintf(ttyout, "usage: %s [-cnr] [-d depth] remote-files\n",
                    369:                    argv[0]);
                    370:                code = -1;
                    371:                return;
                    372:        }
                    373:
                    374:        argv[optind - 1] = argv[0];
                    375:        argc -= optind - 1;
                    376:        argv += optind - 1;
                    377: #endif /* !SMALL */
                    378:
                    379:        mname = argv[0];
                    380:        mflag = 1;
                    381:        if (getcwd(localcwd, sizeof(localcwd)) == NULL)
                    382:                err(1, "can't get cwd");
                    383:
                    384:        oldintr = signal(SIGINT, mabort);
                    385:        (void)setjmp(jabort);
                    386:        while ((cp =
                    387: #ifdef SMALL
                    388:            remglob(argv, proxy, NULL)) != NULL
                    389:            ) {
                    390: #else /* SMALL */
                    391:            depth ? remglob2(dummyargv, proxy, NULL, &ftemp, &type) :
                    392:            remglob(argv, proxy, NULL)) != NULL
                    393:            || (mflag && depth && ++i < argc)
                    394:            ) {
                    395:                if (cp == NULL)
                    396:                        continue;
                    397: #endif /* SMALL */
                    398:                if (*cp == '\0') {
                    399:                        mflag = 0;
                    400:                        continue;
                    401:                }
                    402:                if (!mflag)
                    403:                        continue;
                    404: #ifndef SMALL
                    405:                if (depth && fnmatch(argv[i], cp, FNM_PATHNAME) != 0)
                    406:                        continue;
                    407: #endif /* !SMALL */
                    408:                if (!fileindir(cp, localcwd)) {
                    409:                        fprintf(ttyout, "Skipping non-relative filename `%s'\n",
                    410:                            cp);
                    411:                        continue;
                    412:                }
                    413: #ifndef SMALL
                    414:                if (type == 'd' && depth == max_depth)
                    415:                        continue;
                    416:                if (!confirm(argv[0], cp))
                    417:                        continue;
                    418:                if (type == 'd') {
                    419:                        mkdir(cp, 0755);
                    420:                        if (chdir(cp) != 0) {
                    421:                                warn("local: %s", cp);
                    422:                                continue;
                    423:                        }
                    424:
                    425:                        xargv[1] = cp;
                    426:                        cd(xargc, xargv);
                    427:                        if (dirchange != 1)
                    428:                                goto out;
                    429:
                    430:                        xargv[1] = "*";
                    431:                        mget(xargc, xargv);
                    432:
                    433:                        xargv[1] = "..";
                    434:                        cd(xargc, xargv);
                    435:                        if (dirchange != 1) {
                    436:                                mflag = 0;
                    437:                                goto out;
                    438:                        }
                    439:
                    440: out:
                    441:                        if (chdir("..") != 0) {
                    442:                                warn("local: %s", cp);
                    443:                                mflag = 0;
                    444:                        }
                    445:                        continue;
                    446:                }
                    447:                if (type == 's')
                    448:                        /* Currently ignored. */
                    449:                        continue;
                    450: #endif /* !SMALL */
                    451:                xargv[1] = cp;
                    452:                (void)getit(xargc, xargv, restartit,
                    453:                    (restartit == 1 || restart_point) ? "a+w" : "w");
                    454: #ifndef SMALL
                    455:                if (!mflag && fromatty) {
                    456:                        if (confirm(argv[0], NULL))
                    457:                                mflag = 1;
                    458:                }
                    459: #endif /* !SMALL */
                    460:        }
                    461:        (void)signal(SIGINT, oldintr);
                    462: #ifndef SMALL
                    463:        if (depth)
                    464:                depth--;
                    465:        if (depth == 0 || mflag == 0)
                    466:                depth = max_depth = mflag = restartit = 0;
                    467: #else /* !SMALL */
                    468:        mflag = 0;
                    469: #endif /* !SMALL */
                    470: }
                    471:
                    472: /*
                    473:  * Set current working directory on remote machine.
                    474:  */
                    475: void
                    476: cd(int argc, char *argv[])
                    477: {
                    478:        int r;
                    479:
                    480: #ifndef SMALL
                    481:        if ((argc < 2 && !another(&argc, &argv, "remote-directory")) ||
                    482:            argc > 2) {
                    483:                fprintf(ttyout, "usage: %s remote-directory\n", argv[0]);
                    484:                code = -1;
                    485:                return;
                    486:        }
                    487: #endif /* !SMALL */
                    488:        r = command("CWD %s", argv[1]);
                    489:        if (r == ERROR && code == 500) {
                    490:                if (verbose)
                    491:                        fputs("CWD command not recognized, trying XCWD.\n", ttyout);
                    492:                r = command("XCWD %s", argv[1]);
                    493:        }
                    494:        if (r == ERROR && code == 550) {
                    495:                dirchange = 0;
                    496:                return;
                    497:        }
                    498:        if (r == COMPLETE)
                    499:                dirchange = 1;
                    500: }
                    501:
                    502: /*
                    503:  * Terminate session, but don't exit.
                    504:  */
                    505: /* ARGSUSED */
                    506: void
                    507: disconnect(int argc, char *argv[])
                    508: {
                    509:
                    510:        if (!connected)
                    511:                return;
                    512:        (void)command("QUIT");
                    513:        if (cout) {
                    514:                (void)fclose(cout);
                    515:        }
                    516:        cout = NULL;
                    517:        connected = 0;
                    518:        data = -1;
                    519: #ifndef SMALL
                    520:        if (!proxy) {
                    521:                macnum = 0;
                    522:        }
                    523: #endif /* !SMALL */
                    524: }
                    525:
                    526: char *
                    527: dotrans(char *name)
                    528: {
1.3       deraadt   529:        static char new[PATH_MAX];
1.1       martynas  530:        char *cp1, *cp2 = new;
                    531:        int i, ostop, found;
                    532:
                    533:        for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
                    534:                continue;
                    535:        for (cp1 = name; *cp1; cp1++) {
                    536:                found = 0;
                    537:                for (i = 0; *(ntin + i) && i < 16; i++) {
                    538:                        if (*cp1 == *(ntin + i)) {
                    539:                                found++;
                    540:                                if (i < ostop) {
                    541:                                        *cp2++ = *(ntout + i);
                    542:                                }
                    543:                                break;
                    544:                        }
                    545:                }
                    546:                if (!found) {
                    547:                        *cp2++ = *cp1;
                    548:                }
                    549:        }
                    550:        *cp2 = '\0';
                    551:        return (new);
                    552: }
                    553:
                    554: char *
                    555: domap(char *name)
                    556: {
1.3       deraadt   557:        static char new[PATH_MAX];
1.1       martynas  558:        char *cp1 = name, *cp2 = mapin;
                    559:        char *tp[9], *te[9];
                    560:        int i, toks[9], toknum = 0, match = 1;
                    561:
                    562:        for (i=0; i < 9; ++i) {
                    563:                toks[i] = 0;
                    564:        }
                    565:        while (match && *cp1 && *cp2) {
                    566:                switch (*cp2) {
                    567:                        case '\\':
                    568:                                if (*++cp2 != *cp1) {
                    569:                                        match = 0;
                    570:                                }
                    571:                                break;
                    572:                        case '$':
                    573:                                if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
                    574:                                        if (*cp1 != *(++cp2+1)) {
                    575:                                                toks[toknum = *cp2 - '1']++;
                    576:                                                tp[toknum] = cp1;
                    577:                                                while (*++cp1 && *(cp2+1)
                    578:                                                        != *cp1);
                    579:                                                te[toknum] = cp1;
                    580:                                        }
                    581:                                        cp2++;
                    582:                                        break;
                    583:                                }
                    584:                                /* FALLTHROUGH */
                    585:                        default:
                    586:                                if (*cp2 != *cp1) {
                    587:                                        match = 0;
                    588:                                }
                    589:                                break;
                    590:                }
                    591:                if (match && *cp1) {
                    592:                        cp1++;
                    593:                }
                    594:                if (match && *cp2) {
                    595:                        cp2++;
                    596:                }
                    597:        }
                    598:        if (!match && *cp1) /* last token mismatch */
                    599:        {
                    600:                toks[toknum] = 0;
                    601:        }
                    602:        cp1 = new;
                    603:        *cp1 = '\0';
                    604:        cp2 = mapout;
                    605:        while (*cp2) {
                    606:                match = 0;
                    607:                switch (*cp2) {
                    608:                        case '\\':
                    609:                                if (*(cp2 + 1)) {
                    610:                                        *cp1++ = *++cp2;
                    611:                                }
                    612:                                break;
                    613:                        case '[':
                    614: LOOP:
1.5     ! mmcc      615:                                if (*++cp2 == '$' && isdigit((unsigned char)*(cp2 + 1))) {
1.1       martynas  616:                                        if (*++cp2 == '0') {
                    617:                                                char *cp3 = name;
                    618:
                    619:                                                while (*cp3) {
                    620:                                                        *cp1++ = *cp3++;
                    621:                                                }
                    622:                                                match = 1;
                    623:                                        }
                    624:                                        else if (toks[toknum = *cp2 - '1']) {
                    625:                                                char *cp3 = tp[toknum];
                    626:
                    627:                                                while (cp3 != te[toknum]) {
                    628:                                                        *cp1++ = *cp3++;
                    629:                                                }
                    630:                                                match = 1;
                    631:                                        }
                    632:                                }
                    633:                                else {
                    634:                                        while (*cp2 && *cp2 != ',' &&
                    635:                                            *cp2 != ']') {
                    636:                                                if (*cp2 == '\\') {
                    637:                                                        cp2++;
                    638:                                                }
                    639:                                                else if (*cp2 == '$' &&
1.5     ! mmcc      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:                                                           }
                    647:                                                        }
                    648:                                                        else if (toks[toknum =
                    649:                                                            *cp2 - '1']) {
                    650:                                                           char *cp3=tp[toknum];
                    651:
                    652:                                                           while (cp3 !=
                    653:                                                                  te[toknum]) {
                    654:                                                                *cp1++ = *cp3++;
                    655:                                                           }
                    656:                                                        }
                    657:                                                }
                    658:                                                else if (*cp2) {
                    659:                                                        *cp1++ = *cp2++;
                    660:                                                }
                    661:                                        }
                    662:                                        if (!*cp2) {
                    663:                                                fputs(
                    664: "nmap: unbalanced brackets.\n", ttyout);
                    665:                                                return (name);
                    666:                                        }
                    667:                                        match = 1;
                    668:                                        cp2--;
                    669:                                }
                    670:                                if (match) {
                    671:                                        while (*++cp2 && *cp2 != ']') {
                    672:                                              if (*cp2 == '\\' && *(cp2 + 1)) {
                    673:                                                        cp2++;
                    674:                                              }
                    675:                                        }
                    676:                                        if (!*cp2) {
                    677:                                                fputs(
                    678: "nmap: unbalanced brackets.\n", ttyout);
                    679:                                                return (name);
                    680:                                        }
                    681:                                        break;
                    682:                                }
                    683:                                switch (*++cp2) {
                    684:                                        case ',':
                    685:                                                goto LOOP;
                    686:                                        case ']':
                    687:                                                break;
                    688:                                        default:
                    689:                                                cp2--;
                    690:                                                goto LOOP;
                    691:                                }
                    692:                                break;
                    693:                        case '$':
1.5     ! mmcc      694:                                if (isdigit((unsigned char)*(cp2 + 1))) {
1.1       martynas  695:                                        if (*++cp2 == '0') {
                    696:                                                char *cp3 = name;
                    697:
                    698:                                                while (*cp3) {
                    699:                                                        *cp1++ = *cp3++;
                    700:                                                }
                    701:                                        }
                    702:                                        else if (toks[toknum = *cp2 - '1']) {
                    703:                                                char *cp3 = tp[toknum];
                    704:
                    705:                                                while (cp3 != te[toknum]) {
                    706:                                                        *cp1++ = *cp3++;
                    707:                                                }
                    708:                                        }
                    709:                                        break;
                    710:                                }
                    711:                                /* FALLTHROUGH */
                    712:                        default:
                    713:                                *cp1++ = *cp2;
                    714:                                break;
                    715:                }
                    716:                cp2++;
                    717:        }
                    718:        *cp1 = '\0';
                    719:        if (!*new) {
                    720:                return (name);
                    721:        }
                    722:        return (new);
                    723: }
                    724: