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