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