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