Annotation of src/usr.bin/ftp/cmds.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: cmds.c,v 1.8 1995/09/08 01:06:05 tls Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1985, 1989, 1993, 1994
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * 4. Neither the name of the University nor the names of its contributors
! 20: * may be used to endorse or promote products derived from this software
! 21: * without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: */
! 35:
! 36: #ifndef lint
! 37: #if 0
! 38: static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
! 39: #else
! 40: static char rcsid[] = "$NetBSD: cmds.c,v 1.8 1995/09/08 01:06:05 tls Exp $";
! 41: #endif
! 42: #endif /* not lint */
! 43:
! 44: /*
! 45: * FTP User Program -- Command Routines.
! 46: */
! 47: #include <sys/param.h>
! 48: #include <sys/wait.h>
! 49: #include <sys/stat.h>
! 50: #include <sys/socket.h>
! 51: #include <netinet/in.h>
! 52: #include <arpa/ftp.h>
! 53:
! 54: #include <ctype.h>
! 55: #include <err.h>
! 56: #include <glob.h>
! 57: #include <netdb.h>
! 58: #include <signal.h>
! 59: #include <stdio.h>
! 60: #include <stdlib.h>
! 61: #include <string.h>
! 62: #include <time.h>
! 63: #include <unistd.h>
! 64:
! 65: #include "ftp_var.h"
! 66: #include "pathnames.h"
! 67:
! 68: jmp_buf jabort;
! 69: char *mname;
! 70: char *home = "/";
! 71:
! 72: /*
! 73: * `Another' gets another argument, and stores the new argc and argv.
! 74: * It reverts to the top level (via main.c's intr()) on EOF/error.
! 75: *
! 76: * Returns false if no new arguments have been added.
! 77: */
! 78: int
! 79: another(pargc, pargv, prompt)
! 80: int *pargc;
! 81: char ***pargv;
! 82: char *prompt;
! 83: {
! 84: int len = strlen(line), ret;
! 85:
! 86: if (len >= sizeof(line) - 3) {
! 87: printf("sorry, arguments too long\n");
! 88: intr();
! 89: }
! 90: printf("(%s) ", prompt);
! 91: line[len++] = ' ';
! 92: if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
! 93: intr();
! 94: len += strlen(&line[len]);
! 95: if (len > 0 && line[len - 1] == '\n')
! 96: line[len - 1] = '\0';
! 97: makeargv();
! 98: ret = margc > *pargc;
! 99: *pargc = margc;
! 100: *pargv = margv;
! 101: return (ret);
! 102: }
! 103:
! 104: /*
! 105: * Connect to peer server and
! 106: * auto-login, if possible.
! 107: */
! 108: void
! 109: setpeer(argc, argv)
! 110: int argc;
! 111: char *argv[];
! 112: {
! 113: char *host;
! 114: short port;
! 115:
! 116: if (connected) {
! 117: printf("Already connected to %s, use close first.\n",
! 118: hostname);
! 119: code = -1;
! 120: return;
! 121: }
! 122: if (argc < 2)
! 123: (void) another(&argc, &argv, "to");
! 124: if (argc < 2 || argc > 3) {
! 125: printf("usage: %s host-name [port]\n", argv[0]);
! 126: code = -1;
! 127: return;
! 128: }
! 129: port = sp->s_port;
! 130: if (argc > 2) {
! 131: port = atoi(argv[2]);
! 132: if (port <= 0) {
! 133: printf("%s: bad port number-- %s\n", argv[1], argv[2]);
! 134: printf ("usage: %s host-name [port]\n", argv[0]);
! 135: code = -1;
! 136: return;
! 137: }
! 138: port = htons(port);
! 139: }
! 140: host = hookup(argv[1], port);
! 141: if (host) {
! 142: int overbose;
! 143:
! 144: connected = 1;
! 145: /*
! 146: * Set up defaults for FTP.
! 147: */
! 148: (void) strcpy(typename, "ascii"), type = TYPE_A;
! 149: curtype = TYPE_A;
! 150: (void) strcpy(formname, "non-print"), form = FORM_N;
! 151: (void) strcpy(modename, "stream"), mode = MODE_S;
! 152: (void) strcpy(structname, "file"), stru = STRU_F;
! 153: (void) strcpy(bytename, "8"), bytesize = 8;
! 154: if (autologin)
! 155: (void) login(argv[1]);
! 156:
! 157: #if defined(unix) && NBBY == 8
! 158: /*
! 159: * this ifdef is to keep someone form "porting" this to an incompatible
! 160: * system and not checking this out. This way they have to think about it.
! 161: */
! 162: overbose = verbose;
! 163: if (debug == 0)
! 164: verbose = -1;
! 165: if (command("SYST") == COMPLETE && overbose) {
! 166: char *cp, c;
! 167: cp = strchr(reply_string+4, ' ');
! 168: if (cp == NULL)
! 169: cp = strchr(reply_string+4, '\r');
! 170: if (cp) {
! 171: if (cp[-1] == '.')
! 172: cp--;
! 173: c = *cp;
! 174: *cp = '\0';
! 175: }
! 176:
! 177: printf("Remote system type is %s.\n",
! 178: reply_string+4);
! 179: if (cp)
! 180: *cp = c;
! 181: }
! 182: if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
! 183: if (proxy)
! 184: unix_proxy = 1;
! 185: else
! 186: unix_server = 1;
! 187: /*
! 188: * Set type to 0 (not specified by user),
! 189: * meaning binary by default, but don't bother
! 190: * telling server. We can use binary
! 191: * for text files unless changed by the user.
! 192: */
! 193: type = 0;
! 194: (void) strcpy(typename, "binary");
! 195: if (overbose)
! 196: printf("Using %s mode to transfer files.\n",
! 197: typename);
! 198: } else {
! 199: if (proxy)
! 200: unix_proxy = 0;
! 201: else
! 202: unix_server = 0;
! 203: if (overbose &&
! 204: !strncmp(reply_string, "215 TOPS20", 10))
! 205: printf(
! 206: "Remember to set tenex mode when transfering binary files from this machine.\n");
! 207: }
! 208: verbose = overbose;
! 209: #endif /* unix */
! 210: }
! 211: }
! 212:
! 213: struct types {
! 214: char *t_name;
! 215: char *t_mode;
! 216: int t_type;
! 217: char *t_arg;
! 218: } types[] = {
! 219: { "ascii", "A", TYPE_A, 0 },
! 220: { "binary", "I", TYPE_I, 0 },
! 221: { "image", "I", TYPE_I, 0 },
! 222: { "ebcdic", "E", TYPE_E, 0 },
! 223: { "tenex", "L", TYPE_L, bytename },
! 224: { NULL }
! 225: };
! 226:
! 227: /*
! 228: * Set transfer type.
! 229: */
! 230: void
! 231: settype(argc, argv)
! 232: int argc;
! 233: char *argv[];
! 234: {
! 235: struct types *p;
! 236: int comret;
! 237:
! 238: if (argc > 2) {
! 239: char *sep;
! 240:
! 241: printf("usage: %s [", argv[0]);
! 242: sep = " ";
! 243: for (p = types; p->t_name; p++) {
! 244: printf("%s%s", sep, p->t_name);
! 245: sep = " | ";
! 246: }
! 247: printf(" ]\n");
! 248: code = -1;
! 249: return;
! 250: }
! 251: if (argc < 2) {
! 252: printf("Using %s mode to transfer files.\n", typename);
! 253: code = 0;
! 254: return;
! 255: }
! 256: for (p = types; p->t_name; p++)
! 257: if (strcmp(argv[1], p->t_name) == 0)
! 258: break;
! 259: if (p->t_name == 0) {
! 260: printf("%s: unknown mode\n", argv[1]);
! 261: code = -1;
! 262: return;
! 263: }
! 264: if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
! 265: comret = command ("TYPE %s %s", p->t_mode, p->t_arg);
! 266: else
! 267: comret = command("TYPE %s", p->t_mode);
! 268: if (comret == COMPLETE) {
! 269: (void) strcpy(typename, p->t_name);
! 270: curtype = type = p->t_type;
! 271: }
! 272: }
! 273:
! 274: /*
! 275: * Internal form of settype; changes current type in use with server
! 276: * without changing our notion of the type for data transfers.
! 277: * Used to change to and from ascii for listings.
! 278: */
! 279: void
! 280: changetype(newtype, show)
! 281: int newtype, show;
! 282: {
! 283: struct types *p;
! 284: int comret, oldverbose = verbose;
! 285:
! 286: if (newtype == 0)
! 287: newtype = TYPE_I;
! 288: if (newtype == curtype)
! 289: return;
! 290: if (debug == 0 && show == 0)
! 291: verbose = 0;
! 292: for (p = types; p->t_name; p++)
! 293: if (newtype == p->t_type)
! 294: break;
! 295: if (p->t_name == 0) {
! 296: printf("ftp: internal error: unknown type %d\n", newtype);
! 297: return;
! 298: }
! 299: if (newtype == TYPE_L && bytename[0] != '\0')
! 300: comret = command("TYPE %s %s", p->t_mode, bytename);
! 301: else
! 302: comret = command("TYPE %s", p->t_mode);
! 303: if (comret == COMPLETE)
! 304: curtype = newtype;
! 305: verbose = oldverbose;
! 306: }
! 307:
! 308: char *stype[] = {
! 309: "type",
! 310: "",
! 311: 0
! 312: };
! 313:
! 314: /*
! 315: * Set binary transfer type.
! 316: */
! 317: /*VARARGS*/
! 318: void
! 319: setbinary(argc, argv)
! 320: int argc;
! 321: char **argv;
! 322: {
! 323:
! 324: stype[1] = "binary";
! 325: settype(2, stype);
! 326: }
! 327:
! 328: /*
! 329: * Set ascii transfer type.
! 330: */
! 331: /*VARARGS*/
! 332: void
! 333: setascii(argc, argv)
! 334: int argc;
! 335: char *argv[];
! 336: {
! 337:
! 338: stype[1] = "ascii";
! 339: settype(2, stype);
! 340: }
! 341:
! 342: /*
! 343: * Set tenex transfer type.
! 344: */
! 345: /*VARARGS*/
! 346: void
! 347: settenex(argc, argv)
! 348: int argc;
! 349: char *argv[];
! 350: {
! 351:
! 352: stype[1] = "tenex";
! 353: settype(2, stype);
! 354: }
! 355:
! 356: /*
! 357: * Set file transfer mode.
! 358: */
! 359: /*ARGSUSED*/
! 360: void
! 361: setftmode(argc, argv)
! 362: int argc;
! 363: char *argv[];
! 364: {
! 365:
! 366: printf("We only support %s mode, sorry.\n", modename);
! 367: code = -1;
! 368: }
! 369:
! 370: /*
! 371: * Set file transfer format.
! 372: */
! 373: /*ARGSUSED*/
! 374: void
! 375: setform(argc, argv)
! 376: int argc;
! 377: char *argv[];
! 378: {
! 379:
! 380: printf("We only support %s format, sorry.\n", formname);
! 381: code = -1;
! 382: }
! 383:
! 384: /*
! 385: * Set file transfer structure.
! 386: */
! 387: /*ARGSUSED*/
! 388: void
! 389: setstruct(argc, argv)
! 390: int argc;
! 391: char *argv[];
! 392: {
! 393:
! 394: printf("We only support %s structure, sorry.\n", structname);
! 395: code = -1;
! 396: }
! 397:
! 398: /*
! 399: * Send a single file.
! 400: */
! 401: void
! 402: put(argc, argv)
! 403: int argc;
! 404: char *argv[];
! 405: {
! 406: char *cmd;
! 407: int loc = 0;
! 408: char *oldargv1, *oldargv2;
! 409:
! 410: if (argc == 2) {
! 411: argc++;
! 412: argv[2] = argv[1];
! 413: loc++;
! 414: }
! 415: if (argc < 2 && !another(&argc, &argv, "local-file"))
! 416: goto usage;
! 417: if (argc < 3 && !another(&argc, &argv, "remote-file")) {
! 418: usage:
! 419: printf("usage: %s local-file remote-file\n", argv[0]);
! 420: code = -1;
! 421: return;
! 422: }
! 423: oldargv1 = argv[1];
! 424: oldargv2 = argv[2];
! 425: if (!globulize(&argv[1])) {
! 426: code = -1;
! 427: return;
! 428: }
! 429: /*
! 430: * If "globulize" modifies argv[1], and argv[2] is a copy of
! 431: * the old argv[1], make it a copy of the new argv[1].
! 432: */
! 433: if (argv[1] != oldargv1 && argv[2] == oldargv1) {
! 434: argv[2] = argv[1];
! 435: }
! 436: cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
! 437: if (loc && ntflag) {
! 438: argv[2] = dotrans(argv[2]);
! 439: }
! 440: if (loc && mapflag) {
! 441: argv[2] = domap(argv[2]);
! 442: }
! 443: sendrequest(cmd, argv[1], argv[2],
! 444: argv[1] != oldargv1 || argv[2] != oldargv2);
! 445: }
! 446:
! 447: /*
! 448: * Send multiple files.
! 449: */
! 450: void
! 451: mput(argc, argv)
! 452: int argc;
! 453: char **argv;
! 454: {
! 455: int i;
! 456: sig_t oldintr;
! 457: int ointer;
! 458: char *tp;
! 459:
! 460: if (argc < 2 && !another(&argc, &argv, "local-files")) {
! 461: printf("usage: %s local-files\n", argv[0]);
! 462: code = -1;
! 463: return;
! 464: }
! 465: mname = argv[0];
! 466: mflag = 1;
! 467: oldintr = signal(SIGINT, mabort);
! 468: (void) setjmp(jabort);
! 469: if (proxy) {
! 470: char *cp, *tp2, tmpbuf[MAXPATHLEN];
! 471:
! 472: while ((cp = remglob(argv,0)) != NULL) {
! 473: if (*cp == 0) {
! 474: mflag = 0;
! 475: continue;
! 476: }
! 477: if (mflag && confirm(argv[0], cp)) {
! 478: tp = cp;
! 479: if (mcase) {
! 480: while (*tp && !islower(*tp)) {
! 481: tp++;
! 482: }
! 483: if (!*tp) {
! 484: tp = cp;
! 485: tp2 = tmpbuf;
! 486: while ((*tp2 = *tp) != NULL) {
! 487: if (isupper(*tp2)) {
! 488: *tp2 = 'a' + *tp2 - 'A';
! 489: }
! 490: tp++;
! 491: tp2++;
! 492: }
! 493: }
! 494: tp = tmpbuf;
! 495: }
! 496: if (ntflag) {
! 497: tp = dotrans(tp);
! 498: }
! 499: if (mapflag) {
! 500: tp = domap(tp);
! 501: }
! 502: sendrequest((sunique) ? "STOU" : "STOR",
! 503: cp, tp, cp != tp || !interactive);
! 504: if (!mflag && fromatty) {
! 505: ointer = interactive;
! 506: interactive = 1;
! 507: if (confirm("Continue with","mput")) {
! 508: mflag++;
! 509: }
! 510: interactive = ointer;
! 511: }
! 512: }
! 513: }
! 514: (void) signal(SIGINT, oldintr);
! 515: mflag = 0;
! 516: return;
! 517: }
! 518: for (i = 1; i < argc; i++) {
! 519: char **cpp, **gargs;
! 520: glob_t gl;
! 521: int flags;
! 522:
! 523: if (!doglob) {
! 524: if (mflag && confirm(argv[0], argv[i])) {
! 525: tp = (ntflag) ? dotrans(argv[i]) : argv[i];
! 526: tp = (mapflag) ? domap(tp) : tp;
! 527: sendrequest((sunique) ? "STOU" : "STOR",
! 528: argv[i], tp, tp != argv[i] || !interactive);
! 529: if (!mflag && fromatty) {
! 530: ointer = interactive;
! 531: interactive = 1;
! 532: if (confirm("Continue with","mput")) {
! 533: mflag++;
! 534: }
! 535: interactive = ointer;
! 536: }
! 537: }
! 538: continue;
! 539: }
! 540:
! 541: memset(&gl, 0, sizeof(gl));
! 542: flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
! 543: if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
! 544: warnx("%s: not found", argv[i]);
! 545: globfree(&gl);
! 546: continue;
! 547: }
! 548: for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
! 549: if (mflag && confirm(argv[0], *cpp)) {
! 550: tp = (ntflag) ? dotrans(*cpp) : *cpp;
! 551: tp = (mapflag) ? domap(tp) : tp;
! 552: sendrequest((sunique) ? "STOU" : "STOR",
! 553: *cpp, tp, *cpp != tp || !interactive);
! 554: if (!mflag && fromatty) {
! 555: ointer = interactive;
! 556: interactive = 1;
! 557: if (confirm("Continue with","mput")) {
! 558: mflag++;
! 559: }
! 560: interactive = ointer;
! 561: }
! 562: }
! 563: }
! 564: globfree(&gl);
! 565: }
! 566: (void) signal(SIGINT, oldintr);
! 567: mflag = 0;
! 568: }
! 569:
! 570: void
! 571: reget(argc, argv)
! 572: int argc;
! 573: char *argv[];
! 574: {
! 575:
! 576: (void) getit(argc, argv, 1, "r+w");
! 577: }
! 578:
! 579: void
! 580: get(argc, argv)
! 581: int argc;
! 582: char *argv[];
! 583: {
! 584:
! 585: (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );
! 586: }
! 587:
! 588: /*
! 589: * Receive one file.
! 590: */
! 591: int
! 592: getit(argc, argv, restartit, mode)
! 593: int argc;
! 594: char *argv[];
! 595: char *mode;
! 596: int restartit;
! 597: {
! 598: int loc = 0;
! 599: char *oldargv1, *oldargv2;
! 600:
! 601: if (argc == 2) {
! 602: argc++;
! 603: argv[2] = argv[1];
! 604: loc++;
! 605: }
! 606: if (argc < 2 && !another(&argc, &argv, "remote-file"))
! 607: goto usage;
! 608: if (argc < 3 && !another(&argc, &argv, "local-file")) {
! 609: usage:
! 610: printf("usage: %s remote-file [ local-file ]\n", argv[0]);
! 611: code = -1;
! 612: return (0);
! 613: }
! 614: oldargv1 = argv[1];
! 615: oldargv2 = argv[2];
! 616: if (!globulize(&argv[2])) {
! 617: code = -1;
! 618: return (0);
! 619: }
! 620: if (loc && mcase) {
! 621: char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
! 622:
! 623: while (*tp && !islower(*tp)) {
! 624: tp++;
! 625: }
! 626: if (!*tp) {
! 627: tp = argv[2];
! 628: tp2 = tmpbuf;
! 629: while ((*tp2 = *tp) != NULL) {
! 630: if (isupper(*tp2)) {
! 631: *tp2 = 'a' + *tp2 - 'A';
! 632: }
! 633: tp++;
! 634: tp2++;
! 635: }
! 636: argv[2] = tmpbuf;
! 637: }
! 638: }
! 639: if (loc && ntflag)
! 640: argv[2] = dotrans(argv[2]);
! 641: if (loc && mapflag)
! 642: argv[2] = domap(argv[2]);
! 643: if (restartit) {
! 644: struct stat stbuf;
! 645: int ret;
! 646:
! 647: ret = stat(argv[2], &stbuf);
! 648: if (restartit == 1) {
! 649: if (ret < 0) {
! 650: warn("local: %s", argv[2]);
! 651: return (0);
! 652: }
! 653: restart_point = stbuf.st_size;
! 654: } else {
! 655: if (ret == 0) {
! 656: int overbose;
! 657:
! 658: overbose = verbose;
! 659: if (debug == 0)
! 660: verbose = -1;
! 661: if (command("MDTM %s", argv[1]) == COMPLETE) {
! 662: int yy, mo, day, hour, min, sec;
! 663: struct tm *tm;
! 664: verbose = overbose;
! 665: sscanf(reply_string,
! 666: "%*s %04d%02d%02d%02d%02d%02d",
! 667: &yy, &mo, &day, &hour, &min, &sec);
! 668: tm = gmtime(&stbuf.st_mtime);
! 669: tm->tm_mon++;
! 670: if (tm->tm_year > yy%100)
! 671: return (1);
! 672: if ((tm->tm_year == yy%100 &&
! 673: tm->tm_mon > mo) ||
! 674: (tm->tm_mon == mo &&
! 675: tm->tm_mday > day) ||
! 676: (tm->tm_mday == day &&
! 677: tm->tm_hour > hour) ||
! 678: (tm->tm_hour == hour &&
! 679: tm->tm_min > min) ||
! 680: (tm->tm_min == min &&
! 681: tm->tm_sec > sec))
! 682: return (1);
! 683: } else {
! 684: printf("%s\n", reply_string);
! 685: verbose = overbose;
! 686: return (0);
! 687: }
! 688: }
! 689: }
! 690: }
! 691:
! 692: recvrequest("RETR", argv[2], argv[1], mode,
! 693: argv[1] != oldargv1 || argv[2] != oldargv2);
! 694: restart_point = 0;
! 695: return (0);
! 696: }
! 697:
! 698: /* ARGSUSED */
! 699: void
! 700: mabort(signo)
! 701: int signo;
! 702: {
! 703: int ointer;
! 704:
! 705: printf("\n");
! 706: (void) fflush(stdout);
! 707: if (mflag && fromatty) {
! 708: ointer = interactive;
! 709: interactive = 1;
! 710: if (confirm("Continue with", mname)) {
! 711: interactive = ointer;
! 712: longjmp(jabort,0);
! 713: }
! 714: interactive = ointer;
! 715: }
! 716: mflag = 0;
! 717: longjmp(jabort,0);
! 718: }
! 719:
! 720: /*
! 721: * Get multiple files.
! 722: */
! 723: void
! 724: mget(argc, argv)
! 725: int argc;
! 726: char **argv;
! 727: {
! 728: sig_t oldintr;
! 729: int ch, ointer;
! 730: char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
! 731:
! 732: if (argc < 2 && !another(&argc, &argv, "remote-files")) {
! 733: printf("usage: %s remote-files\n", argv[0]);
! 734: code = -1;
! 735: return;
! 736: }
! 737: mname = argv[0];
! 738: mflag = 1;
! 739: oldintr = signal(SIGINT, mabort);
! 740: (void) setjmp(jabort);
! 741: while ((cp = remglob(argv,proxy)) != NULL) {
! 742: if (*cp == '\0') {
! 743: mflag = 0;
! 744: continue;
! 745: }
! 746: if (mflag && confirm(argv[0], cp)) {
! 747: tp = cp;
! 748: if (mcase) {
! 749: for (tp2 = tmpbuf; ch = *tp++;)
! 750: *tp2++ = isupper(ch) ? tolower(ch) : ch;
! 751: *tp2 = '\0';
! 752: tp = tmpbuf;
! 753: }
! 754: if (ntflag) {
! 755: tp = dotrans(tp);
! 756: }
! 757: if (mapflag) {
! 758: tp = domap(tp);
! 759: }
! 760: recvrequest("RETR", tp, cp, "w",
! 761: tp != cp || !interactive);
! 762: if (!mflag && fromatty) {
! 763: ointer = interactive;
! 764: interactive = 1;
! 765: if (confirm("Continue with","mget")) {
! 766: mflag++;
! 767: }
! 768: interactive = ointer;
! 769: }
! 770: }
! 771: }
! 772: (void) signal(SIGINT,oldintr);
! 773: mflag = 0;
! 774: }
! 775:
! 776: char *
! 777: remglob(argv,doswitch)
! 778: char *argv[];
! 779: int doswitch;
! 780: {
! 781: char temp[16];
! 782: static char buf[MAXPATHLEN];
! 783: static FILE *ftemp = NULL;
! 784: static char **args;
! 785: int oldverbose, oldhash;
! 786: char *cp, *mode;
! 787:
! 788: if (!mflag) {
! 789: if (!doglob) {
! 790: args = NULL;
! 791: }
! 792: else {
! 793: if (ftemp) {
! 794: (void) fclose(ftemp);
! 795: ftemp = NULL;
! 796: }
! 797: }
! 798: return (NULL);
! 799: }
! 800: if (!doglob) {
! 801: if (args == NULL)
! 802: args = argv;
! 803: if ((cp = *++args) == NULL)
! 804: args = NULL;
! 805: return (cp);
! 806: }
! 807: if (ftemp == NULL) {
! 808: (void) strcpy(temp, _PATH_TMP);
! 809: (void) mktemp(temp);
! 810: oldverbose = verbose, verbose = 0;
! 811: oldhash = hash, hash = 0;
! 812: if (doswitch) {
! 813: pswitch(!proxy);
! 814: }
! 815: for (mode = "w"; *++argv != NULL; mode = "a")
! 816: recvrequest ("NLST", temp, *argv, mode, 0);
! 817: if (doswitch) {
! 818: pswitch(!proxy);
! 819: }
! 820: verbose = oldverbose; hash = oldhash;
! 821: ftemp = fopen(temp, "r");
! 822: (void) unlink(temp);
! 823: if (ftemp == NULL) {
! 824: printf("can't find list of remote files, oops\n");
! 825: return (NULL);
! 826: }
! 827: }
! 828: if (fgets(buf, sizeof (buf), ftemp) == NULL) {
! 829: (void) fclose(ftemp), ftemp = NULL;
! 830: return (NULL);
! 831: }
! 832: if ((cp = strchr(buf, '\n')) != NULL)
! 833: *cp = '\0';
! 834: return (buf);
! 835: }
! 836:
! 837: char *
! 838: onoff(bool)
! 839: int bool;
! 840: {
! 841:
! 842: return (bool ? "on" : "off");
! 843: }
! 844:
! 845: /*
! 846: * Show status.
! 847: */
! 848: /*ARGSUSED*/
! 849: void
! 850: status(argc, argv)
! 851: int argc;
! 852: char *argv[];
! 853: {
! 854: int i;
! 855:
! 856: if (connected)
! 857: printf("Connected to %s.\n", hostname);
! 858: else
! 859: printf("Not connected.\n");
! 860: if (!proxy) {
! 861: pswitch(1);
! 862: if (connected) {
! 863: printf("Connected for proxy commands to %s.\n", hostname);
! 864: }
! 865: else {
! 866: printf("No proxy connection.\n");
! 867: }
! 868: pswitch(0);
! 869: }
! 870: printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
! 871: modename, typename, formname, structname);
! 872: printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
! 873: onoff(verbose), onoff(bell), onoff(interactive),
! 874: onoff(doglob));
! 875: printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
! 876: onoff(runique));
! 877: printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag));
! 878: if (ntflag) {
! 879: printf("Ntrans: (in) %s (out) %s\n", ntin,ntout);
! 880: }
! 881: else {
! 882: printf("Ntrans: off\n");
! 883: }
! 884: if (mapflag) {
! 885: printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
! 886: }
! 887: else {
! 888: printf("Nmap: off\n");
! 889: }
! 890: printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
! 891: onoff(hash), onoff(sendport));
! 892: if (macnum > 0) {
! 893: printf("Macros:\n");
! 894: for (i=0; i<macnum; i++) {
! 895: printf("\t%s\n",macros[i].mac_name);
! 896: }
! 897: }
! 898: code = 0;
! 899: }
! 900:
! 901: /*
! 902: * Set beep on cmd completed mode.
! 903: */
! 904: /*VARARGS*/
! 905: void
! 906: setbell(argc, argv)
! 907: int argc;
! 908: char *argv[];
! 909: {
! 910:
! 911: bell = !bell;
! 912: printf("Bell mode %s.\n", onoff(bell));
! 913: code = bell;
! 914: }
! 915:
! 916: /*
! 917: * Turn on packet tracing.
! 918: */
! 919: /*VARARGS*/
! 920: void
! 921: settrace(argc, argv)
! 922: int argc;
! 923: char *argv[];
! 924: {
! 925:
! 926: trace = !trace;
! 927: printf("Packet tracing %s.\n", onoff(trace));
! 928: code = trace;
! 929: }
! 930:
! 931: /*
! 932: * Toggle hash mark printing during transfers.
! 933: */
! 934: /*VARARGS*/
! 935: void
! 936: sethash(argc, argv)
! 937: int argc;
! 938: char *argv[];
! 939: {
! 940:
! 941: hash = !hash;
! 942: printf("Hash mark printing %s", onoff(hash));
! 943: code = hash;
! 944: if (hash)
! 945: printf(" (%d bytes/hash mark)", 1024);
! 946: printf(".\n");
! 947: }
! 948:
! 949: /*
! 950: * Turn on printing of server echo's.
! 951: */
! 952: /*VARARGS*/
! 953: void
! 954: setverbose(argc, argv)
! 955: int argc;
! 956: char *argv[];
! 957: {
! 958:
! 959: verbose = !verbose;
! 960: printf("Verbose mode %s.\n", onoff(verbose));
! 961: code = verbose;
! 962: }
! 963:
! 964: /*
! 965: * Toggle PORT cmd use before each data connection.
! 966: */
! 967: /*VARARGS*/
! 968: void
! 969: setport(argc, argv)
! 970: int argc;
! 971: char *argv[];
! 972: {
! 973:
! 974: sendport = !sendport;
! 975: printf("Use of PORT cmds %s.\n", onoff(sendport));
! 976: code = sendport;
! 977: }
! 978:
! 979: /*
! 980: * Turn on interactive prompting
! 981: * during mget, mput, and mdelete.
! 982: */
! 983: /*VARARGS*/
! 984: void
! 985: setprompt(argc, argv)
! 986: int argc;
! 987: char *argv[];
! 988: {
! 989:
! 990: interactive = !interactive;
! 991: printf("Interactive mode %s.\n", onoff(interactive));
! 992: code = interactive;
! 993: }
! 994:
! 995: /*
! 996: * Toggle metacharacter interpretation
! 997: * on local file names.
! 998: */
! 999: /*VARARGS*/
! 1000: void
! 1001: setglob(argc, argv)
! 1002: int argc;
! 1003: char *argv[];
! 1004: {
! 1005:
! 1006: doglob = !doglob;
! 1007: printf("Globbing %s.\n", onoff(doglob));
! 1008: code = doglob;
! 1009: }
! 1010:
! 1011: /*
! 1012: * Set debugging mode on/off and/or
! 1013: * set level of debugging.
! 1014: */
! 1015: /*VARARGS*/
! 1016: void
! 1017: setdebug(argc, argv)
! 1018: int argc;
! 1019: char *argv[];
! 1020: {
! 1021: int val;
! 1022:
! 1023: if (argc > 1) {
! 1024: val = atoi(argv[1]);
! 1025: if (val < 0) {
! 1026: printf("%s: bad debugging value.\n", argv[1]);
! 1027: code = -1;
! 1028: return;
! 1029: }
! 1030: } else
! 1031: val = !debug;
! 1032: debug = val;
! 1033: if (debug)
! 1034: options |= SO_DEBUG;
! 1035: else
! 1036: options &= ~SO_DEBUG;
! 1037: printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
! 1038: code = debug > 0;
! 1039: }
! 1040:
! 1041: /*
! 1042: * Set current working directory
! 1043: * on remote machine.
! 1044: */
! 1045: void
! 1046: cd(argc, argv)
! 1047: int argc;
! 1048: char *argv[];
! 1049: {
! 1050:
! 1051: if (argc < 2 && !another(&argc, &argv, "remote-directory")) {
! 1052: printf("usage: %s remote-directory\n", argv[0]);
! 1053: code = -1;
! 1054: return;
! 1055: }
! 1056: if (command("CWD %s", argv[1]) == ERROR && code == 500) {
! 1057: if (verbose)
! 1058: printf("CWD command not recognized, trying XCWD\n");
! 1059: (void) command("XCWD %s", argv[1]);
! 1060: }
! 1061: }
! 1062:
! 1063: /*
! 1064: * Set current working directory
! 1065: * on local machine.
! 1066: */
! 1067: void
! 1068: lcd(argc, argv)
! 1069: int argc;
! 1070: char *argv[];
! 1071: {
! 1072: char buf[MAXPATHLEN];
! 1073:
! 1074: if (argc < 2)
! 1075: argc++, argv[1] = home;
! 1076: if (argc != 2) {
! 1077: printf("usage: %s local-directory\n", argv[0]);
! 1078: code = -1;
! 1079: return;
! 1080: }
! 1081: if (!globulize(&argv[1])) {
! 1082: code = -1;
! 1083: return;
! 1084: }
! 1085: if (chdir(argv[1]) < 0) {
! 1086: warn("local: %s", argv[1]);
! 1087: code = -1;
! 1088: return;
! 1089: }
! 1090: if (getwd(buf) != NULL)
! 1091: printf("Local directory now %s\n", buf);
! 1092: else
! 1093: warnx("getwd: %s", buf);
! 1094: code = 0;
! 1095: }
! 1096:
! 1097: /*
! 1098: * Delete a single file.
! 1099: */
! 1100: void
! 1101: delete(argc, argv)
! 1102: int argc;
! 1103: char *argv[];
! 1104: {
! 1105:
! 1106: if (argc < 2 && !another(&argc, &argv, "remote-file")) {
! 1107: printf("usage: %s remote-file\n", argv[0]);
! 1108: code = -1;
! 1109: return;
! 1110: }
! 1111: (void) command("DELE %s", argv[1]);
! 1112: }
! 1113:
! 1114: /*
! 1115: * Delete multiple files.
! 1116: */
! 1117: void
! 1118: mdelete(argc, argv)
! 1119: int argc;
! 1120: char **argv;
! 1121: {
! 1122: sig_t oldintr;
! 1123: int ointer;
! 1124: char *cp;
! 1125:
! 1126: if (argc < 2 && !another(&argc, &argv, "remote-files")) {
! 1127: printf("usage: %s remote-files\n", argv[0]);
! 1128: code = -1;
! 1129: return;
! 1130: }
! 1131: mname = argv[0];
! 1132: mflag = 1;
! 1133: oldintr = signal(SIGINT, mabort);
! 1134: (void) setjmp(jabort);
! 1135: while ((cp = remglob(argv,0)) != NULL) {
! 1136: if (*cp == '\0') {
! 1137: mflag = 0;
! 1138: continue;
! 1139: }
! 1140: if (mflag && confirm(argv[0], cp)) {
! 1141: (void) command("DELE %s", cp);
! 1142: if (!mflag && fromatty) {
! 1143: ointer = interactive;
! 1144: interactive = 1;
! 1145: if (confirm("Continue with", "mdelete")) {
! 1146: mflag++;
! 1147: }
! 1148: interactive = ointer;
! 1149: }
! 1150: }
! 1151: }
! 1152: (void) signal(SIGINT, oldintr);
! 1153: mflag = 0;
! 1154: }
! 1155:
! 1156: /*
! 1157: * Rename a remote file.
! 1158: */
! 1159: void
! 1160: renamefile(argc, argv)
! 1161: int argc;
! 1162: char *argv[];
! 1163: {
! 1164:
! 1165: if (argc < 2 && !another(&argc, &argv, "from-name"))
! 1166: goto usage;
! 1167: if (argc < 3 && !another(&argc, &argv, "to-name")) {
! 1168: usage:
! 1169: printf("%s from-name to-name\n", argv[0]);
! 1170: code = -1;
! 1171: return;
! 1172: }
! 1173: if (command("RNFR %s", argv[1]) == CONTINUE)
! 1174: (void) command("RNTO %s", argv[2]);
! 1175: }
! 1176:
! 1177: /*
! 1178: * Get a directory listing
! 1179: * of remote files.
! 1180: */
! 1181: void
! 1182: ls(argc, argv)
! 1183: int argc;
! 1184: char *argv[];
! 1185: {
! 1186: char *cmd;
! 1187:
! 1188: if (argc < 2)
! 1189: argc++, argv[1] = NULL;
! 1190: if (argc < 3)
! 1191: argc++, argv[2] = "-";
! 1192: if (argc > 3) {
! 1193: printf("usage: %s remote-directory local-file\n", argv[0]);
! 1194: code = -1;
! 1195: return;
! 1196: }
! 1197: cmd = argv[0][0] == 'n' ? "NLST" : "LIST";
! 1198: if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
! 1199: code = -1;
! 1200: return;
! 1201: }
! 1202: if (strcmp(argv[2], "-") && *argv[2] != '|')
! 1203: if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) {
! 1204: code = -1;
! 1205: return;
! 1206: }
! 1207: recvrequest(cmd, argv[2], argv[1], "w", 0);
! 1208: }
! 1209:
! 1210: /*
! 1211: * Get a directory listing
! 1212: * of multiple remote files.
! 1213: */
! 1214: void
! 1215: mls(argc, argv)
! 1216: int argc;
! 1217: char **argv;
! 1218: {
! 1219: sig_t oldintr;
! 1220: int ointer, i;
! 1221: char *cmd, mode[1], *dest;
! 1222:
! 1223: if (argc < 2 && !another(&argc, &argv, "remote-files"))
! 1224: goto usage;
! 1225: if (argc < 3 && !another(&argc, &argv, "local-file")) {
! 1226: usage:
! 1227: printf("usage: %s remote-files local-file\n", argv[0]);
! 1228: code = -1;
! 1229: return;
! 1230: }
! 1231: dest = argv[argc - 1];
! 1232: argv[argc - 1] = NULL;
! 1233: if (strcmp(dest, "-") && *dest != '|')
! 1234: if (!globulize(&dest) ||
! 1235: !confirm("output to local-file:", dest)) {
! 1236: code = -1;
! 1237: return;
! 1238: }
! 1239: cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
! 1240: mname = argv[0];
! 1241: mflag = 1;
! 1242: oldintr = signal(SIGINT, mabort);
! 1243: (void) setjmp(jabort);
! 1244: for (i = 1; mflag && i < argc-1; ++i) {
! 1245: *mode = (i == 1) ? 'w' : 'a';
! 1246: recvrequest(cmd, dest, argv[i], mode, 0);
! 1247: if (!mflag && fromatty) {
! 1248: ointer = interactive;
! 1249: interactive = 1;
! 1250: if (confirm("Continue with", argv[0])) {
! 1251: mflag ++;
! 1252: }
! 1253: interactive = ointer;
! 1254: }
! 1255: }
! 1256: (void) signal(SIGINT, oldintr);
! 1257: mflag = 0;
! 1258: }
! 1259:
! 1260: /*
! 1261: * Do a shell escape
! 1262: */
! 1263: /*ARGSUSED*/
! 1264: void
! 1265: shell(argc, argv)
! 1266: int argc;
! 1267: char **argv;
! 1268: {
! 1269: pid_t pid;
! 1270: sig_t old1, old2;
! 1271: char shellnam[40], *shell, *namep;
! 1272: union wait status;
! 1273:
! 1274: old1 = signal (SIGINT, SIG_IGN);
! 1275: old2 = signal (SIGQUIT, SIG_IGN);
! 1276: if ((pid = fork()) == 0) {
! 1277: for (pid = 3; pid < 20; pid++)
! 1278: (void) close(pid);
! 1279: (void) signal(SIGINT, SIG_DFL);
! 1280: (void) signal(SIGQUIT, SIG_DFL);
! 1281: shell = getenv("SHELL");
! 1282: if (shell == NULL)
! 1283: shell = _PATH_BSHELL;
! 1284: namep = strrchr(shell,'/');
! 1285: if (namep == NULL)
! 1286: namep = shell;
! 1287: (void) strcpy(shellnam,"-");
! 1288: (void) strcat(shellnam, ++namep);
! 1289: if (strcmp(namep, "sh") != 0)
! 1290: shellnam[0] = '+';
! 1291: if (debug) {
! 1292: printf ("%s\n", shell);
! 1293: (void) fflush (stdout);
! 1294: }
! 1295: if (argc > 1) {
! 1296: execl(shell,shellnam,"-c",altarg,(char *)0);
! 1297: }
! 1298: else {
! 1299: execl(shell,shellnam,(char *)0);
! 1300: }
! 1301: warn("%s", shell);
! 1302: code = -1;
! 1303: exit(1);
! 1304: }
! 1305: if (pid > 0)
! 1306: while (wait((int *)&status) != pid)
! 1307: ;
! 1308: (void) signal(SIGINT, old1);
! 1309: (void) signal(SIGQUIT, old2);
! 1310: if (pid == -1) {
! 1311: warn("%s", "Try again later");
! 1312: code = -1;
! 1313: }
! 1314: else {
! 1315: code = 0;
! 1316: }
! 1317: }
! 1318:
! 1319: /*
! 1320: * Send new user information (re-login)
! 1321: */
! 1322: void
! 1323: user(argc, argv)
! 1324: int argc;
! 1325: char **argv;
! 1326: {
! 1327: char acct[80];
! 1328: int n, aflag = 0;
! 1329:
! 1330: if (argc < 2)
! 1331: (void) another(&argc, &argv, "username");
! 1332: if (argc < 2 || argc > 4) {
! 1333: printf("usage: %s username [password] [account]\n", argv[0]);
! 1334: code = -1;
! 1335: return;
! 1336: }
! 1337: n = command("USER %s", argv[1]);
! 1338: if (n == CONTINUE) {
! 1339: if (argc < 3 )
! 1340: argv[2] = getpass("Password: "), argc++;
! 1341: n = command("PASS %s", argv[2]);
! 1342: }
! 1343: if (n == CONTINUE) {
! 1344: if (argc < 4) {
! 1345: printf("Account: "); (void) fflush(stdout);
! 1346: (void) fgets(acct, sizeof(acct) - 1, stdin);
! 1347: acct[strlen(acct) - 1] = '\0';
! 1348: argv[3] = acct; argc++;
! 1349: }
! 1350: n = command("ACCT %s", argv[3]);
! 1351: aflag++;
! 1352: }
! 1353: if (n != COMPLETE) {
! 1354: fprintf(stdout, "Login failed.\n");
! 1355: return;
! 1356: }
! 1357: if (!aflag && argc == 4) {
! 1358: (void) command("ACCT %s", argv[3]);
! 1359: }
! 1360: }
! 1361:
! 1362: /*
! 1363: * Print working directory.
! 1364: */
! 1365: /*VARARGS*/
! 1366: void
! 1367: pwd(argc, argv)
! 1368: int argc;
! 1369: char *argv[];
! 1370: {
! 1371: int oldverbose = verbose;
! 1372:
! 1373: /*
! 1374: * If we aren't verbose, this doesn't do anything!
! 1375: */
! 1376: verbose = 1;
! 1377: if (command("PWD") == ERROR && code == 500) {
! 1378: printf("PWD command not recognized, trying XPWD\n");
! 1379: (void) command("XPWD");
! 1380: }
! 1381: verbose = oldverbose;
! 1382: }
! 1383:
! 1384: /*
! 1385: * Make a directory.
! 1386: */
! 1387: void
! 1388: makedir(argc, argv)
! 1389: int argc;
! 1390: char *argv[];
! 1391: {
! 1392:
! 1393: if (argc < 2 && !another(&argc, &argv, "directory-name")) {
! 1394: printf("usage: %s directory-name\n", argv[0]);
! 1395: code = -1;
! 1396: return;
! 1397: }
! 1398: if (command("MKD %s", argv[1]) == ERROR && code == 500) {
! 1399: if (verbose)
! 1400: printf("MKD command not recognized, trying XMKD\n");
! 1401: (void) command("XMKD %s", argv[1]);
! 1402: }
! 1403: }
! 1404:
! 1405: /*
! 1406: * Remove a directory.
! 1407: */
! 1408: void
! 1409: removedir(argc, argv)
! 1410: int argc;
! 1411: char *argv[];
! 1412: {
! 1413:
! 1414: if (argc < 2 && !another(&argc, &argv, "directory-name")) {
! 1415: printf("usage: %s directory-name\n", argv[0]);
! 1416: code = -1;
! 1417: return;
! 1418: }
! 1419: if (command("RMD %s", argv[1]) == ERROR && code == 500) {
! 1420: if (verbose)
! 1421: printf("RMD command not recognized, trying XRMD\n");
! 1422: (void) command("XRMD %s", argv[1]);
! 1423: }
! 1424: }
! 1425:
! 1426: /*
! 1427: * Send a line, verbatim, to the remote machine.
! 1428: */
! 1429: void
! 1430: quote(argc, argv)
! 1431: int argc;
! 1432: char *argv[];
! 1433: {
! 1434:
! 1435: if (argc < 2 && !another(&argc, &argv, "command line to send")) {
! 1436: printf("usage: %s line-to-send\n", argv[0]);
! 1437: code = -1;
! 1438: return;
! 1439: }
! 1440: quote1("", argc, argv);
! 1441: }
! 1442:
! 1443: /*
! 1444: * Send a SITE command to the remote machine. The line
! 1445: * is sent verbatim to the remote machine, except that the
! 1446: * word "SITE" is added at the front.
! 1447: */
! 1448: void
! 1449: site(argc, argv)
! 1450: int argc;
! 1451: char *argv[];
! 1452: {
! 1453:
! 1454: if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
! 1455: printf("usage: %s line-to-send\n", argv[0]);
! 1456: code = -1;
! 1457: return;
! 1458: }
! 1459: quote1("SITE ", argc, argv);
! 1460: }
! 1461:
! 1462: /*
! 1463: * Turn argv[1..argc) into a space-separated string, then prepend initial text.
! 1464: * Send the result as a one-line command and get response.
! 1465: */
! 1466: void
! 1467: quote1(initial, argc, argv)
! 1468: char *initial;
! 1469: int argc;
! 1470: char **argv;
! 1471: {
! 1472: int i, len;
! 1473: char buf[BUFSIZ]; /* must be >= sizeof(line) */
! 1474:
! 1475: (void) strcpy(buf, initial);
! 1476: if (argc > 1) {
! 1477: len = strlen(buf);
! 1478: len += strlen(strcpy(&buf[len], argv[1]));
! 1479: for (i = 2; i < argc; i++) {
! 1480: buf[len++] = ' ';
! 1481: len += strlen(strcpy(&buf[len], argv[i]));
! 1482: }
! 1483: }
! 1484: if (command(buf) == PRELIM) {
! 1485: while (getreply(0) == PRELIM)
! 1486: continue;
! 1487: }
! 1488: }
! 1489:
! 1490: void
! 1491: do_chmod(argc, argv)
! 1492: int argc;
! 1493: char *argv[];
! 1494: {
! 1495:
! 1496: if (argc < 2 && !another(&argc, &argv, "mode"))
! 1497: goto usage;
! 1498: if (argc < 3 && !another(&argc, &argv, "file-name")) {
! 1499: usage:
! 1500: printf("usage: %s mode file-name\n", argv[0]);
! 1501: code = -1;
! 1502: return;
! 1503: }
! 1504: (void) command("SITE CHMOD %s %s", argv[1], argv[2]);
! 1505: }
! 1506:
! 1507: void
! 1508: do_umask(argc, argv)
! 1509: int argc;
! 1510: char *argv[];
! 1511: {
! 1512: int oldverbose = verbose;
! 1513:
! 1514: verbose = 1;
! 1515: (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
! 1516: verbose = oldverbose;
! 1517: }
! 1518:
! 1519: void
! 1520: idle(argc, argv)
! 1521: int argc;
! 1522: char *argv[];
! 1523: {
! 1524: int oldverbose = verbose;
! 1525:
! 1526: verbose = 1;
! 1527: (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
! 1528: verbose = oldverbose;
! 1529: }
! 1530:
! 1531: /*
! 1532: * Ask the other side for help.
! 1533: */
! 1534: void
! 1535: rmthelp(argc, argv)
! 1536: int argc;
! 1537: char *argv[];
! 1538: {
! 1539: int oldverbose = verbose;
! 1540:
! 1541: verbose = 1;
! 1542: (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
! 1543: verbose = oldverbose;
! 1544: }
! 1545:
! 1546: /*
! 1547: * Terminate session and exit.
! 1548: */
! 1549: /*VARARGS*/
! 1550: void
! 1551: quit(argc, argv)
! 1552: int argc;
! 1553: char *argv[];
! 1554: {
! 1555:
! 1556: if (connected)
! 1557: disconnect(0, 0);
! 1558: pswitch(1);
! 1559: if (connected) {
! 1560: disconnect(0, 0);
! 1561: }
! 1562: exit(0);
! 1563: }
! 1564:
! 1565: /*
! 1566: * Terminate session, but don't exit.
! 1567: */
! 1568: void
! 1569: disconnect(argc, argv)
! 1570: int argc;
! 1571: char *argv[];
! 1572: {
! 1573:
! 1574: if (!connected)
! 1575: return;
! 1576: (void) command("QUIT");
! 1577: if (cout) {
! 1578: (void) fclose(cout);
! 1579: }
! 1580: cout = NULL;
! 1581: connected = 0;
! 1582: data = -1;
! 1583: if (!proxy) {
! 1584: macnum = 0;
! 1585: }
! 1586: }
! 1587:
! 1588: int
! 1589: confirm(cmd, file)
! 1590: char *cmd, *file;
! 1591: {
! 1592: char line[BUFSIZ];
! 1593:
! 1594: if (!interactive)
! 1595: return (1);
! 1596: printf("%s %s? ", cmd, file);
! 1597: (void) fflush(stdout);
! 1598: if (fgets(line, sizeof line, stdin) == NULL)
! 1599: return (0);
! 1600: return (*line != 'n' && *line != 'N');
! 1601: }
! 1602:
! 1603: void
! 1604: fatal(msg)
! 1605: char *msg;
! 1606: {
! 1607:
! 1608: errx(1, "%s", msg);
! 1609: }
! 1610:
! 1611: /*
! 1612: * Glob a local file name specification with
! 1613: * the expectation of a single return value.
! 1614: * Can't control multiple values being expanded
! 1615: * from the expression, we return only the first.
! 1616: */
! 1617: int
! 1618: globulize(cpp)
! 1619: char **cpp;
! 1620: {
! 1621: glob_t gl;
! 1622: int flags;
! 1623:
! 1624: if (!doglob)
! 1625: return (1);
! 1626:
! 1627: flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
! 1628: memset(&gl, 0, sizeof(gl));
! 1629: if (glob(*cpp, flags, NULL, &gl) ||
! 1630: gl.gl_pathc == 0) {
! 1631: warnx("%s: not found", *cpp);
! 1632: globfree(&gl);
! 1633: return (0);
! 1634: }
! 1635: *cpp = strdup(gl.gl_pathv[0]); /* XXX - wasted memory */
! 1636: globfree(&gl);
! 1637: return (1);
! 1638: }
! 1639:
! 1640: void
! 1641: account(argc,argv)
! 1642: int argc;
! 1643: char **argv;
! 1644: {
! 1645: char acct[50], *ap;
! 1646:
! 1647: if (argc > 1) {
! 1648: ++argv;
! 1649: --argc;
! 1650: (void) strncpy(acct,*argv,49);
! 1651: acct[49] = '\0';
! 1652: while (argc > 1) {
! 1653: --argc;
! 1654: ++argv;
! 1655: (void) strncat(acct,*argv, 49-strlen(acct));
! 1656: }
! 1657: ap = acct;
! 1658: }
! 1659: else {
! 1660: ap = getpass("Account:");
! 1661: }
! 1662: (void) command("ACCT %s", ap);
! 1663: }
! 1664:
! 1665: jmp_buf abortprox;
! 1666:
! 1667: void
! 1668: proxabort()
! 1669: {
! 1670:
! 1671: if (!proxy) {
! 1672: pswitch(1);
! 1673: }
! 1674: if (connected) {
! 1675: proxflag = 1;
! 1676: }
! 1677: else {
! 1678: proxflag = 0;
! 1679: }
! 1680: pswitch(0);
! 1681: longjmp(abortprox,1);
! 1682: }
! 1683:
! 1684: void
! 1685: doproxy(argc, argv)
! 1686: int argc;
! 1687: char *argv[];
! 1688: {
! 1689: struct cmd *c;
! 1690: sig_t oldintr;
! 1691:
! 1692: if (argc < 2 && !another(&argc, &argv, "command")) {
! 1693: printf("usage: %s command\n", argv[0]);
! 1694: code = -1;
! 1695: return;
! 1696: }
! 1697: c = getcmd(argv[1]);
! 1698: if (c == (struct cmd *) -1) {
! 1699: printf("?Ambiguous command\n");
! 1700: (void) fflush(stdout);
! 1701: code = -1;
! 1702: return;
! 1703: }
! 1704: if (c == 0) {
! 1705: printf("?Invalid command\n");
! 1706: (void) fflush(stdout);
! 1707: code = -1;
! 1708: return;
! 1709: }
! 1710: if (!c->c_proxy) {
! 1711: printf("?Invalid proxy command\n");
! 1712: (void) fflush(stdout);
! 1713: code = -1;
! 1714: return;
! 1715: }
! 1716: if (setjmp(abortprox)) {
! 1717: code = -1;
! 1718: return;
! 1719: }
! 1720: oldintr = signal(SIGINT, proxabort);
! 1721: pswitch(1);
! 1722: if (c->c_conn && !connected) {
! 1723: printf("Not connected\n");
! 1724: (void) fflush(stdout);
! 1725: pswitch(0);
! 1726: (void) signal(SIGINT, oldintr);
! 1727: code = -1;
! 1728: return;
! 1729: }
! 1730: (*c->c_handler)(argc-1, argv+1);
! 1731: if (connected) {
! 1732: proxflag = 1;
! 1733: }
! 1734: else {
! 1735: proxflag = 0;
! 1736: }
! 1737: pswitch(0);
! 1738: (void) signal(SIGINT, oldintr);
! 1739: }
! 1740:
! 1741: void
! 1742: setcase(argc, argv)
! 1743: int argc;
! 1744: char *argv[];
! 1745: {
! 1746:
! 1747: mcase = !mcase;
! 1748: printf("Case mapping %s.\n", onoff(mcase));
! 1749: code = mcase;
! 1750: }
! 1751:
! 1752: void
! 1753: setcr(argc, argv)
! 1754: int argc;
! 1755: char *argv[];
! 1756: {
! 1757:
! 1758: crflag = !crflag;
! 1759: printf("Carriage Return stripping %s.\n", onoff(crflag));
! 1760: code = crflag;
! 1761: }
! 1762:
! 1763: void
! 1764: setntrans(argc,argv)
! 1765: int argc;
! 1766: char *argv[];
! 1767: {
! 1768: if (argc == 1) {
! 1769: ntflag = 0;
! 1770: printf("Ntrans off.\n");
! 1771: code = ntflag;
! 1772: return;
! 1773: }
! 1774: ntflag++;
! 1775: code = ntflag;
! 1776: (void) strncpy(ntin, argv[1], 16);
! 1777: ntin[16] = '\0';
! 1778: if (argc == 2) {
! 1779: ntout[0] = '\0';
! 1780: return;
! 1781: }
! 1782: (void) strncpy(ntout, argv[2], 16);
! 1783: ntout[16] = '\0';
! 1784: }
! 1785:
! 1786: char *
! 1787: dotrans(name)
! 1788: char *name;
! 1789: {
! 1790: static char new[MAXPATHLEN];
! 1791: char *cp1, *cp2 = new;
! 1792: int i, ostop, found;
! 1793:
! 1794: for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
! 1795: continue;
! 1796: for (cp1 = name; *cp1; cp1++) {
! 1797: found = 0;
! 1798: for (i = 0; *(ntin + i) && i < 16; i++) {
! 1799: if (*cp1 == *(ntin + i)) {
! 1800: found++;
! 1801: if (i < ostop) {
! 1802: *cp2++ = *(ntout + i);
! 1803: }
! 1804: break;
! 1805: }
! 1806: }
! 1807: if (!found) {
! 1808: *cp2++ = *cp1;
! 1809: }
! 1810: }
! 1811: *cp2 = '\0';
! 1812: return (new);
! 1813: }
! 1814:
! 1815: void
! 1816: setnmap(argc, argv)
! 1817: int argc;
! 1818: char *argv[];
! 1819: {
! 1820: char *cp;
! 1821:
! 1822: if (argc == 1) {
! 1823: mapflag = 0;
! 1824: printf("Nmap off.\n");
! 1825: code = mapflag;
! 1826: return;
! 1827: }
! 1828: if (argc < 3 && !another(&argc, &argv, "mapout")) {
! 1829: printf("Usage: %s [mapin mapout]\n",argv[0]);
! 1830: code = -1;
! 1831: return;
! 1832: }
! 1833: mapflag = 1;
! 1834: code = 1;
! 1835: cp = strchr(altarg, ' ');
! 1836: if (proxy) {
! 1837: while(*++cp == ' ')
! 1838: continue;
! 1839: altarg = cp;
! 1840: cp = strchr(altarg, ' ');
! 1841: }
! 1842: *cp = '\0';
! 1843: (void) strncpy(mapin, altarg, MAXPATHLEN - 1);
! 1844: while (*++cp == ' ')
! 1845: continue;
! 1846: (void) strncpy(mapout, cp, MAXPATHLEN - 1);
! 1847: }
! 1848:
! 1849: char *
! 1850: domap(name)
! 1851: char *name;
! 1852: {
! 1853: static char new[MAXPATHLEN];
! 1854: char *cp1 = name, *cp2 = mapin;
! 1855: char *tp[9], *te[9];
! 1856: int i, toks[9], toknum = 0, match = 1;
! 1857:
! 1858: for (i=0; i < 9; ++i) {
! 1859: toks[i] = 0;
! 1860: }
! 1861: while (match && *cp1 && *cp2) {
! 1862: switch (*cp2) {
! 1863: case '\\':
! 1864: if (*++cp2 != *cp1) {
! 1865: match = 0;
! 1866: }
! 1867: break;
! 1868: case '$':
! 1869: if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
! 1870: if (*cp1 != *(++cp2+1)) {
! 1871: toks[toknum = *cp2 - '1']++;
! 1872: tp[toknum] = cp1;
! 1873: while (*++cp1 && *(cp2+1)
! 1874: != *cp1);
! 1875: te[toknum] = cp1;
! 1876: }
! 1877: cp2++;
! 1878: break;
! 1879: }
! 1880: /* FALLTHROUGH */
! 1881: default:
! 1882: if (*cp2 != *cp1) {
! 1883: match = 0;
! 1884: }
! 1885: break;
! 1886: }
! 1887: if (match && *cp1) {
! 1888: cp1++;
! 1889: }
! 1890: if (match && *cp2) {
! 1891: cp2++;
! 1892: }
! 1893: }
! 1894: if (!match && *cp1) /* last token mismatch */
! 1895: {
! 1896: toks[toknum] = 0;
! 1897: }
! 1898: cp1 = new;
! 1899: *cp1 = '\0';
! 1900: cp2 = mapout;
! 1901: while (*cp2) {
! 1902: match = 0;
! 1903: switch (*cp2) {
! 1904: case '\\':
! 1905: if (*(cp2 + 1)) {
! 1906: *cp1++ = *++cp2;
! 1907: }
! 1908: break;
! 1909: case '[':
! 1910: LOOP:
! 1911: if (*++cp2 == '$' && isdigit(*(cp2+1))) {
! 1912: if (*++cp2 == '0') {
! 1913: char *cp3 = name;
! 1914:
! 1915: while (*cp3) {
! 1916: *cp1++ = *cp3++;
! 1917: }
! 1918: match = 1;
! 1919: }
! 1920: else if (toks[toknum = *cp2 - '1']) {
! 1921: char *cp3 = tp[toknum];
! 1922:
! 1923: while (cp3 != te[toknum]) {
! 1924: *cp1++ = *cp3++;
! 1925: }
! 1926: match = 1;
! 1927: }
! 1928: }
! 1929: else {
! 1930: while (*cp2 && *cp2 != ',' &&
! 1931: *cp2 != ']') {
! 1932: if (*cp2 == '\\') {
! 1933: cp2++;
! 1934: }
! 1935: else if (*cp2 == '$' &&
! 1936: isdigit(*(cp2+1))) {
! 1937: if (*++cp2 == '0') {
! 1938: char *cp3 = name;
! 1939:
! 1940: while (*cp3) {
! 1941: *cp1++ = *cp3++;
! 1942: }
! 1943: }
! 1944: else if (toks[toknum =
! 1945: *cp2 - '1']) {
! 1946: char *cp3=tp[toknum];
! 1947:
! 1948: while (cp3 !=
! 1949: te[toknum]) {
! 1950: *cp1++ = *cp3++;
! 1951: }
! 1952: }
! 1953: }
! 1954: else if (*cp2) {
! 1955: *cp1++ = *cp2++;
! 1956: }
! 1957: }
! 1958: if (!*cp2) {
! 1959: printf("nmap: unbalanced brackets\n");
! 1960: return (name);
! 1961: }
! 1962: match = 1;
! 1963: cp2--;
! 1964: }
! 1965: if (match) {
! 1966: while (*++cp2 && *cp2 != ']') {
! 1967: if (*cp2 == '\\' && *(cp2 + 1)) {
! 1968: cp2++;
! 1969: }
! 1970: }
! 1971: if (!*cp2) {
! 1972: printf("nmap: unbalanced brackets\n");
! 1973: return (name);
! 1974: }
! 1975: break;
! 1976: }
! 1977: switch (*++cp2) {
! 1978: case ',':
! 1979: goto LOOP;
! 1980: case ']':
! 1981: break;
! 1982: default:
! 1983: cp2--;
! 1984: goto LOOP;
! 1985: }
! 1986: break;
! 1987: case '$':
! 1988: if (isdigit(*(cp2 + 1))) {
! 1989: if (*++cp2 == '0') {
! 1990: char *cp3 = name;
! 1991:
! 1992: while (*cp3) {
! 1993: *cp1++ = *cp3++;
! 1994: }
! 1995: }
! 1996: else if (toks[toknum = *cp2 - '1']) {
! 1997: char *cp3 = tp[toknum];
! 1998:
! 1999: while (cp3 != te[toknum]) {
! 2000: *cp1++ = *cp3++;
! 2001: }
! 2002: }
! 2003: break;
! 2004: }
! 2005: /* intentional drop through */
! 2006: default:
! 2007: *cp1++ = *cp2;
! 2008: break;
! 2009: }
! 2010: cp2++;
! 2011: }
! 2012: *cp1 = '\0';
! 2013: if (!*new) {
! 2014: return (name);
! 2015: }
! 2016: return (new);
! 2017: }
! 2018:
! 2019: void
! 2020: setpassive(argc, argv)
! 2021: int argc;
! 2022: char *argv[];
! 2023: {
! 2024:
! 2025: passivemode = !passivemode;
! 2026: printf("Passive mode %s.\n", onoff(passivemode));
! 2027: code = passivemode;
! 2028: }
! 2029:
! 2030: void
! 2031: setsunique(argc, argv)
! 2032: int argc;
! 2033: char *argv[];
! 2034: {
! 2035:
! 2036: sunique = !sunique;
! 2037: printf("Store unique %s.\n", onoff(sunique));
! 2038: code = sunique;
! 2039: }
! 2040:
! 2041: void
! 2042: setrunique(argc, argv)
! 2043: int argc;
! 2044: char *argv[];
! 2045: {
! 2046:
! 2047: runique = !runique;
! 2048: printf("Receive unique %s.\n", onoff(runique));
! 2049: code = runique;
! 2050: }
! 2051:
! 2052: /* change directory to perent directory */
! 2053: void
! 2054: cdup(argc, argv)
! 2055: int argc;
! 2056: char *argv[];
! 2057: {
! 2058:
! 2059: if (command("CDUP") == ERROR && code == 500) {
! 2060: if (verbose)
! 2061: printf("CDUP command not recognized, trying XCUP\n");
! 2062: (void) command("XCUP");
! 2063: }
! 2064: }
! 2065:
! 2066: /* restart transfer at specific point */
! 2067: void
! 2068: restart(argc, argv)
! 2069: int argc;
! 2070: char *argv[];
! 2071: {
! 2072:
! 2073: if (argc != 2)
! 2074: printf("restart: offset not specified\n");
! 2075: else {
! 2076: restart_point = atol(argv[1]);
! 2077: printf("restarting at %qd. %s\n", restart_point,
! 2078: "execute get, put or append to initiate transfer");
! 2079: }
! 2080: }
! 2081:
! 2082: /* show remote system type */
! 2083: void
! 2084: syst(argc, argv)
! 2085: int argc;
! 2086: char *argv[];
! 2087: {
! 2088:
! 2089: (void) command("SYST");
! 2090: }
! 2091:
! 2092: void
! 2093: macdef(argc, argv)
! 2094: int argc;
! 2095: char *argv[];
! 2096: {
! 2097: char *tmp;
! 2098: int c;
! 2099:
! 2100: if (macnum == 16) {
! 2101: printf("Limit of 16 macros have already been defined\n");
! 2102: code = -1;
! 2103: return;
! 2104: }
! 2105: if (argc < 2 && !another(&argc, &argv, "macro name")) {
! 2106: printf("Usage: %s macro_name\n",argv[0]);
! 2107: code = -1;
! 2108: return;
! 2109: }
! 2110: if (interactive) {
! 2111: printf("Enter macro line by line, terminating it with a null line\n");
! 2112: }
! 2113: (void) strncpy(macros[macnum].mac_name, argv[1], 8);
! 2114: if (macnum == 0) {
! 2115: macros[macnum].mac_start = macbuf;
! 2116: }
! 2117: else {
! 2118: macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
! 2119: }
! 2120: tmp = macros[macnum].mac_start;
! 2121: while (tmp != macbuf+4096) {
! 2122: if ((c = getchar()) == EOF) {
! 2123: printf("macdef:end of file encountered\n");
! 2124: code = -1;
! 2125: return;
! 2126: }
! 2127: if ((*tmp = c) == '\n') {
! 2128: if (tmp == macros[macnum].mac_start) {
! 2129: macros[macnum++].mac_end = tmp;
! 2130: code = 0;
! 2131: return;
! 2132: }
! 2133: if (*(tmp-1) == '\0') {
! 2134: macros[macnum++].mac_end = tmp - 1;
! 2135: code = 0;
! 2136: return;
! 2137: }
! 2138: *tmp = '\0';
! 2139: }
! 2140: tmp++;
! 2141: }
! 2142: while (1) {
! 2143: while ((c = getchar()) != '\n' && c != EOF)
! 2144: /* LOOP */;
! 2145: if (c == EOF || getchar() == '\n') {
! 2146: printf("Macro not defined - 4k buffer exceeded\n");
! 2147: code = -1;
! 2148: return;
! 2149: }
! 2150: }
! 2151: }
! 2152:
! 2153: /*
! 2154: * get size of file on remote machine
! 2155: */
! 2156: void
! 2157: sizecmd(argc, argv)
! 2158: int argc;
! 2159: char *argv[];
! 2160: {
! 2161:
! 2162: if (argc < 2 && !another(&argc, &argv, "filename")) {
! 2163: printf("usage: %s filename\n", argv[0]);
! 2164: code = -1;
! 2165: return;
! 2166: }
! 2167: (void) command("SIZE %s", argv[1]);
! 2168: }
! 2169:
! 2170: /*
! 2171: * get last modification time of file on remote machine
! 2172: */
! 2173: void
! 2174: modtime(argc, argv)
! 2175: int argc;
! 2176: char *argv[];
! 2177: {
! 2178: int overbose;
! 2179:
! 2180: if (argc < 2 && !another(&argc, &argv, "filename")) {
! 2181: printf("usage: %s filename\n", argv[0]);
! 2182: code = -1;
! 2183: return;
! 2184: }
! 2185: overbose = verbose;
! 2186: if (debug == 0)
! 2187: verbose = -1;
! 2188: if (command("MDTM %s", argv[1]) == COMPLETE) {
! 2189: int yy, mo, day, hour, min, sec;
! 2190: sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
! 2191: &day, &hour, &min, &sec);
! 2192: /* might want to print this in local time */
! 2193: printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
! 2194: mo, day, yy, hour, min, sec);
! 2195: } else
! 2196: printf("%s\n", reply_string);
! 2197: verbose = overbose;
! 2198: }
! 2199:
! 2200: /*
! 2201: * show status on reomte machine
! 2202: */
! 2203: void
! 2204: rmtstatus(argc, argv)
! 2205: int argc;
! 2206: char *argv[];
! 2207: {
! 2208:
! 2209: (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
! 2210: }
! 2211:
! 2212: /*
! 2213: * get file if modtime is more recent than current file
! 2214: */
! 2215: void
! 2216: newer(argc, argv)
! 2217: int argc;
! 2218: char *argv[];
! 2219: {
! 2220:
! 2221: if (getit(argc, argv, -1, "w"))
! 2222: printf("Local file \"%s\" is newer than remote file \"%s\"\n",
! 2223: argv[2], argv[1]);
! 2224: }