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