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