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