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