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