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: