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

1.1     ! martynas    1: /*     $OpenBSD$       */
        !             2: /*     $NetBSD: cmds.c,v 1.27 1997/08/18 10:20:15 lukem Exp $  */
        !             3:
        !             4: /*
        !             5:  * Copyright (C) 1997 and 1998 WIDE Project.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. Neither the name of the project nor the names of its contributors
        !            17:  *    may be used to endorse or promote products derived from this software
        !            18:  *    without specific prior written permission.
        !            19:  *
        !            20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
        !            21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
        !            24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            30:  * SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: /*
        !            34:  * Copyright (c) 1985, 1989, 1993, 1994
        !            35:  *     The Regents of the University of California.  All rights reserved.
        !            36:  *
        !            37:  * Redistribution and use in source and binary forms, with or without
        !            38:  * modification, are permitted provided that the following conditions
        !            39:  * are met:
        !            40:  * 1. Redistributions of source code must retain the above copyright
        !            41:  *    notice, this list of conditions and the following disclaimer.
        !            42:  * 2. Redistributions in binary form must reproduce the above copyright
        !            43:  *    notice, this list of conditions and the following disclaimer in the
        !            44:  *    documentation and/or other materials provided with the distribution.
        !            45:  * 3. Neither the name of the University nor the names of its contributors
        !            46:  *    may be used to endorse or promote products derived from this software
        !            47:  *    without specific prior written permission.
        !            48:  *
        !            49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            59:  * SUCH DAMAGE.
        !            60:  */
        !            61:
        !            62: /*
        !            63:  * FTP User Program -- Command Routines.
        !            64:  */
        !            65: #include <sys/types.h>
        !            66: #include <sys/socket.h>
        !            67: #include <sys/stat.h>
        !            68: #include <sys/wait.h>
        !            69: #include <arpa/ftp.h>
        !            70:
        !            71: #include <ctype.h>
        !            72: #include <err.h>
        !            73: #include <fnmatch.h>
        !            74: #include <glob.h>
        !            75: #include <netdb.h>
        !            76: #include <stdio.h>
        !            77: #include <stdlib.h>
        !            78: #include <string.h>
        !            79: #include <unistd.h>
        !            80:
        !            81: #include "ftp_var.h"
        !            82: #include "pathnames.h"
        !            83: #include "small.h"
        !            84:
        !            85: jmp_buf        jabort;
        !            86: char   *mname;
        !            87: char   *home = "/";
        !            88:
        !            89: struct types {
        !            90:        char    *t_name;
        !            91:        char    *t_mode;
        !            92:        int     t_type;
        !            93:        char    *t_arg;
        !            94: } types[] = {
        !            95:        { "ascii",      "A",    TYPE_A, 0 },
        !            96:        { "binary",     "I",    TYPE_I, 0 },
        !            97:        { "image",      "I",    TYPE_I, 0 },
        !            98:        { "ebcdic",     "E",    TYPE_E, 0 },
        !            99:        { "tenex",      "L",    TYPE_L, bytename },
        !           100:        { NULL }
        !           101: };
        !           102:
        !           103: /*
        !           104:  * Set transfer type.
        !           105:  */
        !           106: void
        !           107: settype(int argc, char *argv[])
        !           108: {
        !           109:        struct types *p;
        !           110:        int comret;
        !           111:
        !           112:        if (argc > 2) {
        !           113:                char *sep;
        !           114:
        !           115:                fprintf(ttyout, "usage: %s [", argv[0]);
        !           116:                sep = "";
        !           117:                for (p = types; p->t_name; p++) {
        !           118:                        fprintf(ttyout, "%s%s", sep, p->t_name);
        !           119:                        sep = " | ";
        !           120:                }
        !           121:                fputs("]\n", ttyout);
        !           122:                code = -1;
        !           123:                return;
        !           124:        }
        !           125:        if (argc < 2) {
        !           126:                fprintf(ttyout, "Using %s mode to transfer files.\n", typename);
        !           127:                code = 0;
        !           128:                return;
        !           129:        }
        !           130:        for (p = types; p->t_name; p++)
        !           131:                if (strcmp(argv[1], p->t_name) == 0)
        !           132:                        break;
        !           133:        if (p->t_name == 0) {
        !           134:                fprintf(ttyout, "%s: unknown mode.\n", argv[1]);
        !           135:                code = -1;
        !           136:                return;
        !           137:        }
        !           138:        if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
        !           139:                comret = command("TYPE %s %s", p->t_mode, p->t_arg);
        !           140:        else
        !           141:                comret = command("TYPE %s", p->t_mode);
        !           142:        if (comret == COMPLETE) {
        !           143:                (void)strlcpy(typename, p->t_name, sizeof typename);
        !           144:                curtype = type = p->t_type;
        !           145:        }
        !           146: }
        !           147:
        !           148: /*
        !           149:  * Internal form of settype; changes current type in use with server
        !           150:  * without changing our notion of the type for data transfers.
        !           151:  * Used to change to and from ascii for listings.
        !           152:  */
        !           153: void
        !           154: changetype(int newtype, int show)
        !           155: {
        !           156:        struct types *p;
        !           157:        int comret, oldverbose = verbose;
        !           158:
        !           159:        if (newtype == 0)
        !           160:                newtype = TYPE_I;
        !           161:        if (newtype == curtype)
        !           162:                return;
        !           163:        if (
        !           164: #ifndef SMALL
        !           165:            !debug &&
        !           166: #endif /* !SMALL */
        !           167:            show == 0)
        !           168:                verbose = 0;
        !           169:        for (p = types; p->t_name; p++)
        !           170:                if (newtype == p->t_type)
        !           171:                        break;
        !           172:        if (p->t_name == 0) {
        !           173:                warnx("internal error: unknown type %d.", newtype);
        !           174:                return;
        !           175:        }
        !           176:        if (newtype == TYPE_L && bytename[0] != '\0')
        !           177:                comret = command("TYPE %s %s", p->t_mode, bytename);
        !           178:        else
        !           179:                comret = command("TYPE %s", p->t_mode);
        !           180:        if (comret == COMPLETE)
        !           181:                curtype = newtype;
        !           182:        verbose = oldverbose;
        !           183: }
        !           184:
        !           185: char *stype[] = {
        !           186:        "type",
        !           187:        "",
        !           188:        0
        !           189: };
        !           190:
        !           191: /*
        !           192:  * Set binary transfer type.
        !           193:  */
        !           194: /*ARGSUSED*/
        !           195: void
        !           196: setbinary(int argc, char *argv[])
        !           197: {
        !           198:
        !           199:        stype[1] = "binary";
        !           200:        settype(2, stype);
        !           201: }
        !           202:
        !           203: void
        !           204: get(int argc, char *argv[])
        !           205: {
        !           206:
        !           207:        (void)getit(argc, argv, 0, restart_point ? "a+w" : "w" );
        !           208: }
        !           209:
        !           210: /*
        !           211:  * Receive one file.
        !           212:  */
        !           213: int
        !           214: getit(int argc, char *argv[], int restartit, const char *mode)
        !           215: {
        !           216:        int loc = 0;
        !           217:        int rval = 0;
        !           218:        char *oldargv1, *oldargv2, *globargv2;
        !           219:
        !           220:        if (argc == 2) {
        !           221:                argc++;
        !           222:                argv[2] = argv[1];
        !           223:                loc++;
        !           224:        }
        !           225: #ifndef SMALL
        !           226:        if (argc < 2 && !another(&argc, &argv, "remote-file"))
        !           227:                goto usage;
        !           228:        if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) {
        !           229: usage:
        !           230:                fprintf(ttyout, "usage: %s remote-file [local-file]\n",
        !           231:                    argv[0]);
        !           232:                code = -1;
        !           233:                return (0);
        !           234:        }
        !           235: #endif /* !SMALL */
        !           236:        oldargv1 = argv[1];
        !           237:        oldargv2 = argv[2];
        !           238:        if (!globulize(&argv[2])) {
        !           239:                code = -1;
        !           240:                return (0);
        !           241:        }
        !           242:        globargv2 = argv[2];
        !           243:        if (loc && mcase) {
        !           244:                char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
        !           245:
        !           246:                while (*tp && !islower(*tp)) {
        !           247:                        tp++;
        !           248:                }
        !           249:                if (!*tp) {
        !           250:                        tp = argv[2];
        !           251:                        tp2 = tmpbuf;
        !           252:                        while ((*tp2 = *tp) != '\0') {
        !           253:                                if (isupper(*tp2)) {
        !           254:                                        *tp2 = tolower(*tp2);
        !           255:                                }
        !           256:                                tp++;
        !           257:                                tp2++;
        !           258:                        }
        !           259:                        argv[2] = tmpbuf;
        !           260:                }
        !           261:        }
        !           262:        if (loc && ntflag)
        !           263:                argv[2] = dotrans(argv[2]);
        !           264:        if (loc && mapflag)
        !           265:                argv[2] = domap(argv[2]);
        !           266: #ifndef SMALL
        !           267:        if (restartit) {
        !           268:                struct stat stbuf;
        !           269:                int ret;
        !           270:
        !           271:                ret = stat(argv[2], &stbuf);
        !           272:                if (restartit == 1) {
        !           273:                        restart_point = (ret < 0) ? 0 : stbuf.st_size;
        !           274:                } else {
        !           275:                        if (ret == 0) {
        !           276:                                time_t mtime;
        !           277:
        !           278:                                mtime = remotemodtime(argv[1], 0);
        !           279:                                if (mtime == -1)
        !           280:                                        goto freegetit;
        !           281:                                if (stbuf.st_mtime >= mtime) {
        !           282:                                        rval = 1;
        !           283:                                        goto freegetit;
        !           284:                                }
        !           285:                        }
        !           286:                }
        !           287:        }
        !           288: #endif /* !SMALL */
        !           289:
        !           290:        recvrequest("RETR", argv[2], argv[1], mode,
        !           291:            argv[1] != oldargv1 || argv[2] != oldargv2 || !interactive, loc);
        !           292:        restart_point = 0;
        !           293: freegetit:
        !           294:        if (oldargv2 != globargv2)      /* free up after globulize() */
        !           295:                free(globargv2);
        !           296:        return (rval);
        !           297: }
        !           298:
        !           299: /* XXX - Signal race. */
        !           300: /* ARGSUSED */
        !           301: void
        !           302: mabort(int signo)
        !           303: {
        !           304:        alarmtimer(0);
        !           305:        putc('\n', ttyout);
        !           306:        (void)fflush(ttyout);
        !           307: #ifndef SMALL
        !           308:        if (mflag && fromatty)
        !           309:                if (confirm(mname, NULL))
        !           310:                        longjmp(jabort, 1);
        !           311: #endif /* !SMALL */
        !           312:        mflag = 0;
        !           313:        longjmp(jabort, 1);
        !           314: }
        !           315:
        !           316: /*
        !           317:  * Get multiple files.
        !           318:  */
        !           319: void
        !           320: mget(int argc, char *argv[])
        !           321: {
        !           322:        extern int optind, optreset;
        !           323:        sig_t oldintr;
        !           324:        int ch, xargc = 2;
        !           325:        char *cp, localcwd[MAXPATHLEN], *xargv[] = { argv[0], NULL, NULL };
        !           326:        static int restartit = 0;
        !           327: #ifndef SMALL
        !           328:        extern char *optarg;
        !           329:        const char *errstr;
        !           330:        int i = 1;
        !           331:        char type = 0, *dummyargv[] = { argv[0], ".", NULL };
        !           332:        FILE *ftemp = NULL;
        !           333:        static int depth = 0, max_depth = 0;
        !           334:
        !           335:        optind = optreset = 1;
        !           336:
        !           337:        if (depth)
        !           338:                depth++;
        !           339:
        !           340:        while ((ch = getopt(argc, argv, "cd:nr")) != -1) {
        !           341:                switch(ch) {
        !           342:                case 'c':
        !           343:                        restartit = 1;
        !           344:                        break;
        !           345:                case 'd':
        !           346:                        max_depth = strtonum(optarg, 0, INT_MAX, &errstr);
        !           347:                        if (errstr != NULL) {
        !           348:                                fprintf(ttyout, "bad depth value, %s: %s\n",
        !           349:                                    errstr, optarg);
        !           350:                                code = -1;
        !           351:                                return;
        !           352:                        }
        !           353:                        break;
        !           354:                case 'n':
        !           355:                        restartit = -1;
        !           356:                        break;
        !           357:                case 'r':
        !           358:                        depth = 1;
        !           359:                        break;
        !           360:                default:
        !           361:                        goto usage;
        !           362:                }
        !           363:        }
        !           364:
        !           365:        if (argc - optind < 1 && !another(&argc, &argv, "remote-files")) {
        !           366: usage:
        !           367:                fprintf(ttyout, "usage: %s [-cnr] [-d depth] remote-files\n",
        !           368:                    argv[0]);
        !           369:                code = -1;
        !           370:                return;
        !           371:        }
        !           372:
        !           373:        argv[optind - 1] = argv[0];
        !           374:        argc -= optind - 1;
        !           375:        argv += optind - 1;
        !           376: #endif /* !SMALL */
        !           377:
        !           378:        mname = argv[0];
        !           379:        mflag = 1;
        !           380:        if (getcwd(localcwd, sizeof(localcwd)) == NULL)
        !           381:                err(1, "can't get cwd");
        !           382:
        !           383:        oldintr = signal(SIGINT, mabort);
        !           384:        (void)setjmp(jabort);
        !           385:        while ((cp =
        !           386: #ifdef SMALL
        !           387:            remglob(argv, proxy, NULL)) != NULL
        !           388:            ) {
        !           389: #else /* SMALL */
        !           390:            depth ? remglob2(dummyargv, proxy, NULL, &ftemp, &type) :
        !           391:            remglob(argv, proxy, NULL)) != NULL
        !           392:            || (mflag && depth && ++i < argc)
        !           393:            ) {
        !           394:                if (cp == NULL)
        !           395:                        continue;
        !           396: #endif /* SMALL */
        !           397:                if (*cp == '\0') {
        !           398:                        mflag = 0;
        !           399:                        continue;
        !           400:                }
        !           401:                if (!mflag)
        !           402:                        continue;
        !           403: #ifndef SMALL
        !           404:                if (depth && fnmatch(argv[i], cp, FNM_PATHNAME) != 0)
        !           405:                        continue;
        !           406: #endif /* !SMALL */
        !           407:                if (!fileindir(cp, localcwd)) {
        !           408:                        fprintf(ttyout, "Skipping non-relative filename `%s'\n",
        !           409:                            cp);
        !           410:                        continue;
        !           411:                }
        !           412: #ifndef SMALL
        !           413:                if (type == 'd' && depth == max_depth)
        !           414:                        continue;
        !           415:                if (!confirm(argv[0], cp))
        !           416:                        continue;
        !           417:                if (type == 'd') {
        !           418:                        mkdir(cp, 0755);
        !           419:                        if (chdir(cp) != 0) {
        !           420:                                warn("local: %s", cp);
        !           421:                                continue;
        !           422:                        }
        !           423:
        !           424:                        xargv[1] = cp;
        !           425:                        cd(xargc, xargv);
        !           426:                        if (dirchange != 1)
        !           427:                                goto out;
        !           428:
        !           429:                        xargv[1] = "*";
        !           430:                        mget(xargc, xargv);
        !           431:
        !           432:                        xargv[1] = "..";
        !           433:                        cd(xargc, xargv);
        !           434:                        if (dirchange != 1) {
        !           435:                                mflag = 0;
        !           436:                                goto out;
        !           437:                        }
        !           438:
        !           439: out:
        !           440:                        if (chdir("..") != 0) {
        !           441:                                warn("local: %s", cp);
        !           442:                                mflag = 0;
        !           443:                        }
        !           444:                        continue;
        !           445:                }
        !           446:                if (type == 's')
        !           447:                        /* Currently ignored. */
        !           448:                        continue;
        !           449: #endif /* !SMALL */
        !           450:                xargv[1] = cp;
        !           451:                (void)getit(xargc, xargv, restartit,
        !           452:                    (restartit == 1 || restart_point) ? "a+w" : "w");
        !           453: #ifndef SMALL
        !           454:                if (!mflag && fromatty) {
        !           455:                        if (confirm(argv[0], NULL))
        !           456:                                mflag = 1;
        !           457:                }
        !           458: #endif /* !SMALL */
        !           459:        }
        !           460:        (void)signal(SIGINT, oldintr);
        !           461: #ifndef SMALL
        !           462:        if (depth)
        !           463:                depth--;
        !           464:        if (depth == 0 || mflag == 0)
        !           465:                depth = max_depth = mflag = restartit = 0;
        !           466: #else /* !SMALL */
        !           467:        mflag = 0;
        !           468: #endif /* !SMALL */
        !           469: }
        !           470:
        !           471: /*
        !           472:  * Set current working directory on remote machine.
        !           473:  */
        !           474: void
        !           475: cd(int argc, char *argv[])
        !           476: {
        !           477:        int r;
        !           478:
        !           479: #ifndef SMALL
        !           480:        if ((argc < 2 && !another(&argc, &argv, "remote-directory")) ||
        !           481:            argc > 2) {
        !           482:                fprintf(ttyout, "usage: %s remote-directory\n", argv[0]);
        !           483:                code = -1;
        !           484:                return;
        !           485:        }
        !           486: #endif /* !SMALL */
        !           487:        r = command("CWD %s", argv[1]);
        !           488:        if (r == ERROR && code == 500) {
        !           489:                if (verbose)
        !           490:                        fputs("CWD command not recognized, trying XCWD.\n", ttyout);
        !           491:                r = command("XCWD %s", argv[1]);
        !           492:        }
        !           493:        if (r == ERROR && code == 550) {
        !           494:                dirchange = 0;
        !           495:                return;
        !           496:        }
        !           497:        if (r == COMPLETE)
        !           498:                dirchange = 1;
        !           499: }
        !           500:
        !           501: /*
        !           502:  * Terminate session, but don't exit.
        !           503:  */
        !           504: /* ARGSUSED */
        !           505: void
        !           506: disconnect(int argc, char *argv[])
        !           507: {
        !           508:
        !           509:        if (!connected)
        !           510:                return;
        !           511:        (void)command("QUIT");
        !           512:        if (cout) {
        !           513:                (void)fclose(cout);
        !           514:        }
        !           515:        cout = NULL;
        !           516:        connected = 0;
        !           517:        data = -1;
        !           518: #ifndef SMALL
        !           519:        if (!proxy) {
        !           520:                macnum = 0;
        !           521:        }
        !           522: #endif /* !SMALL */
        !           523: }
        !           524:
        !           525: char *
        !           526: dotrans(char *name)
        !           527: {
        !           528:        static char new[MAXPATHLEN];
        !           529:        char *cp1, *cp2 = new;
        !           530:        int i, ostop, found;
        !           531:
        !           532:        for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
        !           533:                continue;
        !           534:        for (cp1 = name; *cp1; cp1++) {
        !           535:                found = 0;
        !           536:                for (i = 0; *(ntin + i) && i < 16; i++) {
        !           537:                        if (*cp1 == *(ntin + i)) {
        !           538:                                found++;
        !           539:                                if (i < ostop) {
        !           540:                                        *cp2++ = *(ntout + i);
        !           541:                                }
        !           542:                                break;
        !           543:                        }
        !           544:                }
        !           545:                if (!found) {
        !           546:                        *cp2++ = *cp1;
        !           547:                }
        !           548:        }
        !           549:        *cp2 = '\0';
        !           550:        return (new);
        !           551: }
        !           552:
        !           553: char *
        !           554: domap(char *name)
        !           555: {
        !           556:        static char new[MAXPATHLEN];
        !           557:        char *cp1 = name, *cp2 = mapin;
        !           558:        char *tp[9], *te[9];
        !           559:        int i, toks[9], toknum = 0, match = 1;
        !           560:
        !           561:        for (i=0; i < 9; ++i) {
        !           562:                toks[i] = 0;
        !           563:        }
        !           564:        while (match && *cp1 && *cp2) {
        !           565:                switch (*cp2) {
        !           566:                        case '\\':
        !           567:                                if (*++cp2 != *cp1) {
        !           568:                                        match = 0;
        !           569:                                }
        !           570:                                break;
        !           571:                        case '$':
        !           572:                                if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
        !           573:                                        if (*cp1 != *(++cp2+1)) {
        !           574:                                                toks[toknum = *cp2 - '1']++;
        !           575:                                                tp[toknum] = cp1;
        !           576:                                                while (*++cp1 && *(cp2+1)
        !           577:                                                        != *cp1);
        !           578:                                                te[toknum] = cp1;
        !           579:                                        }
        !           580:                                        cp2++;
        !           581:                                        break;
        !           582:                                }
        !           583:                                /* FALLTHROUGH */
        !           584:                        default:
        !           585:                                if (*cp2 != *cp1) {
        !           586:                                        match = 0;
        !           587:                                }
        !           588:                                break;
        !           589:                }
        !           590:                if (match && *cp1) {
        !           591:                        cp1++;
        !           592:                }
        !           593:                if (match && *cp2) {
        !           594:                        cp2++;
        !           595:                }
        !           596:        }
        !           597:        if (!match && *cp1) /* last token mismatch */
        !           598:        {
        !           599:                toks[toknum] = 0;
        !           600:        }
        !           601:        cp1 = new;
        !           602:        *cp1 = '\0';
        !           603:        cp2 = mapout;
        !           604:        while (*cp2) {
        !           605:                match = 0;
        !           606:                switch (*cp2) {
        !           607:                        case '\\':
        !           608:                                if (*(cp2 + 1)) {
        !           609:                                        *cp1++ = *++cp2;
        !           610:                                }
        !           611:                                break;
        !           612:                        case '[':
        !           613: LOOP:
        !           614:                                if (*++cp2 == '$' && isdigit(*(cp2+1))) {
        !           615:                                        if (*++cp2 == '0') {
        !           616:                                                char *cp3 = name;
        !           617:
        !           618:                                                while (*cp3) {
        !           619:                                                        *cp1++ = *cp3++;
        !           620:                                                }
        !           621:                                                match = 1;
        !           622:                                        }
        !           623:                                        else if (toks[toknum = *cp2 - '1']) {
        !           624:                                                char *cp3 = tp[toknum];
        !           625:
        !           626:                                                while (cp3 != te[toknum]) {
        !           627:                                                        *cp1++ = *cp3++;
        !           628:                                                }
        !           629:                                                match = 1;
        !           630:                                        }
        !           631:                                }
        !           632:                                else {
        !           633:                                        while (*cp2 && *cp2 != ',' &&
        !           634:                                            *cp2 != ']') {
        !           635:                                                if (*cp2 == '\\') {
        !           636:                                                        cp2++;
        !           637:                                                }
        !           638:                                                else if (*cp2 == '$' &&
        !           639:                                                        isdigit(*(cp2+1))) {
        !           640:                                                        if (*++cp2 == '0') {
        !           641:                                                           char *cp3 = name;
        !           642:
        !           643:                                                           while (*cp3) {
        !           644:                                                                *cp1++ = *cp3++;
        !           645:                                                           }
        !           646:                                                        }
        !           647:                                                        else if (toks[toknum =
        !           648:                                                            *cp2 - '1']) {
        !           649:                                                           char *cp3=tp[toknum];
        !           650:
        !           651:                                                           while (cp3 !=
        !           652:                                                                  te[toknum]) {
        !           653:                                                                *cp1++ = *cp3++;
        !           654:                                                           }
        !           655:                                                        }
        !           656:                                                }
        !           657:                                                else if (*cp2) {
        !           658:                                                        *cp1++ = *cp2++;
        !           659:                                                }
        !           660:                                        }
        !           661:                                        if (!*cp2) {
        !           662:                                                fputs(
        !           663: "nmap: unbalanced brackets.\n", ttyout);
        !           664:                                                return (name);
        !           665:                                        }
        !           666:                                        match = 1;
        !           667:                                        cp2--;
        !           668:                                }
        !           669:                                if (match) {
        !           670:                                        while (*++cp2 && *cp2 != ']') {
        !           671:                                              if (*cp2 == '\\' && *(cp2 + 1)) {
        !           672:                                                        cp2++;
        !           673:                                              }
        !           674:                                        }
        !           675:                                        if (!*cp2) {
        !           676:                                                fputs(
        !           677: "nmap: unbalanced brackets.\n", ttyout);
        !           678:                                                return (name);
        !           679:                                        }
        !           680:                                        break;
        !           681:                                }
        !           682:                                switch (*++cp2) {
        !           683:                                        case ',':
        !           684:                                                goto LOOP;
        !           685:                                        case ']':
        !           686:                                                break;
        !           687:                                        default:
        !           688:                                                cp2--;
        !           689:                                                goto LOOP;
        !           690:                                }
        !           691:                                break;
        !           692:                        case '$':
        !           693:                                if (isdigit(*(cp2 + 1))) {
        !           694:                                        if (*++cp2 == '0') {
        !           695:                                                char *cp3 = name;
        !           696:
        !           697:                                                while (*cp3) {
        !           698:                                                        *cp1++ = *cp3++;
        !           699:                                                }
        !           700:                                        }
        !           701:                                        else if (toks[toknum = *cp2 - '1']) {
        !           702:                                                char *cp3 = tp[toknum];
        !           703:
        !           704:                                                while (cp3 != te[toknum]) {
        !           705:                                                        *cp1++ = *cp3++;
        !           706:                                                }
        !           707:                                        }
        !           708:                                        break;
        !           709:                                }
        !           710:                                /* FALLTHROUGH */
        !           711:                        default:
        !           712:                                *cp1++ = *cp2;
        !           713:                                break;
        !           714:                }
        !           715:                cp2++;
        !           716:        }
        !           717:        *cp1 = '\0';
        !           718:        if (!*new) {
        !           719:                return (name);
        !           720:        }
        !           721:        return (new);
        !           722: }
        !           723: