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