numerous bug fixes from sun!gorodish!guy
[unix-history] / usr / src / usr.bin / ftp / cmds.c
CommitLineData
edf71f48
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
59d0d309 7#ifndef lint
14433a73 8static char sccsid[] = "@(#)cmds.c 5.3 (Berkeley) %G%";
edf71f48 9#endif not lint
59d0d309
SL
10
11/*
12 * FTP User Program -- Command Routines.
13 */
cf8133c7 14#include <sys/param.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>
23
59d0d309
SL
24#include "ftp_var.h"
25
cf8133c7
SL
26extern char *globerr;
27extern char **glob();
9072bd8a 28extern char *home;
cf8133c7 29extern short gflag;
9072bd8a
SL
30extern char *remglob();
31extern char *getenv();
32extern char *index();
33extern char *rindex();
59d0d309
SL
34
35/*
36 * Connect to peer server and
37 * auto-login, if possible.
38 */
39setpeer(argc, argv)
40 int argc;
41 char *argv[];
42{
198ce38e 43 char *host, *hookup();
59d0d309
SL
44 int port;
45
46 if (connected) {
47 printf("Already connected to %s, use disconnect first.\n",
48 hostname);
49 return;
50 }
51 if (argc < 2) {
52 strcat(line, " ");
53 printf("(to) ");
54 gets(&line[strlen(line)]);
55 makeargv();
56 argc = margc;
57 argv = margv;
58 }
59 if (argc > 3) {
60 printf("usage: %s host-name [port]\n", argv[0]);
61 return;
62 }
63 port = sp->s_port;
64 if (argc > 2) {
d33c618b 65 port = atoi(argv[2]);
59d0d309 66 if (port <= 0) {
d33c618b
SL
67 printf("%s: bad port number-- %s\n", argv[1], argv[2]);
68 printf ("usage: %s host-name [port]\n", argv[0]);
59d0d309
SL
69 return;
70 }
71 port = htons(port);
72 }
73 host = hookup(argv[1], port);
74 if (host) {
75 connected = 1;
76 if (autologin)
77 login(host);
78 }
79}
80
81struct types {
82 char *t_name;
83 char *t_mode;
84 int t_type;
d33c618b 85 char *t_arg;
59d0d309 86} types[] = {
d33c618b
SL
87 { "ascii", "A", TYPE_A, 0 },
88 { "binary", "I", TYPE_I, 0 },
89 { "image", "I", TYPE_I, 0 },
90 { "ebcdic", "E", TYPE_E, 0 },
91 { "tenex", "L", TYPE_L, bytename },
59d0d309
SL
92 0
93};
94
95/*
96 * Set transfer type.
97 */
98settype(argc, argv)
99 char *argv[];
100{
101 register struct types *p;
d33c618b 102 int comret;
59d0d309
SL
103
104 if (argc > 2) {
105 char *sep;
106
107 printf("usage: %s [", argv[0]);
108 sep = " ";
109 for (p = types; p->t_name; p++) {
110 printf("%s%s", sep, p->t_name);
111 if (*sep == ' ')
112 sep = " | ";
113 }
114 printf(" ]\n");
115 return;
116 }
117 if (argc < 2) {
118 printf("Using %s mode to transfer files.\n", typename);
119 return;
120 }
121 for (p = types; p->t_name; p++)
122 if (strcmp(argv[1], p->t_name) == 0)
123 break;
124 if (p->t_name == 0) {
125 printf("%s: unknown mode\n", argv[1]);
126 return;
127 }
d33c618b
SL
128 if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
129 comret = command ("TYPE %s %s", p->t_mode, p->t_arg);
130 else
131 comret = command("TYPE %s", p->t_mode);
132 if (comret == COMPLETE) {
59d0d309
SL
133 strcpy(typename, p->t_name);
134 type = p->t_type;
135 }
136}
137
138/*
139 * Set binary transfer type.
140 */
141/*VARARGS*/
142setbinary()
143{
144
145 call(settype, "type", "binary", 0);
146}
147
148/*
149 * Set ascii transfer type.
150 */
151/*VARARGS*/
152setascii()
153{
154
155 call(settype, "type", "ascii", 0);
156}
157
158/*
159 * Set tenex transfer type.
160 */
161/*VARARGS*/
162settenex()
163{
164
165 call(settype, "type", "tenex", 0);
166}
167
168/*
169 * Set ebcdic transfer type.
170 */
171/*VARARGS*/
172setebcdic()
173{
174
175 call(settype, "type", "ebcdic", 0);
176}
177
178/*
179 * Set file transfer mode.
180 */
181setmode(argc, argv)
182 char *argv[];
183{
184
185 printf("We only support %s mode, sorry.\n", modename);
186}
187
188/*
189 * Set file transfer format.
190 */
191setform(argc, argv)
192 char *argv[];
193{
194
195 printf("We only support %s format, sorry.\n", formname);
196}
197
198/*
199 * Set file transfer structure.
200 */
201setstruct(argc, argv)
202 char *argv[];
203{
204
205 printf("We only support %s structure, sorry.\n", structname);
206}
207
71a655cd
RC
208/*
209 * Send a single file.
210 */
59d0d309 211put(argc, argv)
5ac6fc46
SL
212 int argc;
213 char *argv[];
214{
9072bd8a 215 char *cmd;
14433a73 216 char *oldargv1;
5ac6fc46 217
59d0d309
SL
218 if (argc == 2)
219 argc++, argv[2] = argv[1];
220 if (argc < 2) {
221 strcat(line, " ");
222 printf("(local-file) ");
223 gets(&line[strlen(line)]);
224 makeargv();
225 argc = margc;
226 argv = margv;
227 }
228 if (argc < 2) {
229usage:
230 printf("%s local-file remote-file\n", argv[0]);
231 return;
232 }
233 if (argc < 3) {
234 strcat(line, " ");
235 printf("(remote-file) ");
236 gets(&line[strlen(line)]);
237 makeargv();
238 argc = margc;
239 argv = margv;
240 }
241 if (argc < 3)
242 goto usage;
14433a73 243 oldargv1 = argv[1];
cf8133c7
SL
244 if (!globulize(&argv[1]))
245 return;
14433a73
KM
246 /*
247 * If "globulize" modifies argv[1], and argv[2] is a copy of
248 * the old argv[1], make it a copy of the new argv[1].
249 */
250 if (argv[1] != oldargv1 && argv[2] == oldargv1)
251 argv[2] = argv[1];
9072bd8a 252 cmd = (argv[0][0] == 'a') ? "APPE" : "STOR";
5ac6fc46 253 sendrequest(cmd, argv[1], argv[2]);
59d0d309
SL
254}
255
256/*
9072bd8a 257 * Send multiple files.
cf8133c7
SL
258 */
259mput(argc, argv)
260 char *argv[];
261{
614e24b6 262 register int i;
cf8133c7 263
5ac6fc46
SL
264 if (argc < 2) {
265 strcat(line, " ");
266 printf("(local-files) ");
267 gets(&line[strlen(line)]);
268 makeargv();
269 argc = margc;
270 argv = margv;
cf8133c7
SL
271 }
272 if (argc < 2) {
cf8133c7
SL
273 printf("%s local-files\n", argv[0]);
274 return;
275 }
614e24b6
SL
276 for (i = 1; i < argc; i++) {
277 register char **cpp, **gargs;
278
279 if (!doglob) {
280 if (confirm(argv[0], argv[i]))
281 sendrequest("STOR", argv[i], argv[i]);
282 continue;
283 }
284 gargs = glob(argv[i]);
cf8133c7 285 if (globerr != NULL) {
5ac6fc46
SL
286 printf("%s\n", globerr);
287 if (gargs)
288 blkfree(gargs);
614e24b6 289 continue;
cf8133c7 290 }
614e24b6
SL
291 for (cpp = gargs; cpp && *cpp != NULL; cpp++)
292 if (confirm(argv[0], *cpp))
293 sendrequest("STOR", *cpp, *cpp);
294 if (gargs != NULL)
295 blkfree(gargs);
cf8133c7
SL
296 }
297}
298
299/*
300 * Receive one file.
59d0d309
SL
301 */
302get(argc, argv)
303 char *argv[];
304{
59d0d309 305
59d0d309
SL
306 if (argc == 2)
307 argc++, argv[2] = argv[1];
308 if (argc < 2) {
309 strcat(line, " ");
310 printf("(remote-file) ");
311 gets(&line[strlen(line)]);
312 makeargv();
313 argc = margc;
314 argv = margv;
315 }
316 if (argc < 2) {
317usage:
cf8133c7 318 printf("%s remote-file [ local-file ]\n", argv[0]);
59d0d309
SL
319 return;
320 }
321 if (argc < 3) {
322 strcat(line, " ");
323 printf("(local-file) ");
324 gets(&line[strlen(line)]);
325 makeargv();
326 argc = margc;
327 argv = margv;
328 }
329 if (argc < 3)
330 goto usage;
cf8133c7
SL
331 if (!globulize(&argv[2]))
332 return;
5ac6fc46 333 recvrequest("RETR", argv[2], argv[1], "w");
59d0d309
SL
334}
335
cf8133c7
SL
336/*
337 * Get multiple files.
338 */
339mget(argc, argv)
340 char *argv[];
341{
9072bd8a 342 char *cp;
cf8133c7 343
cf8133c7
SL
344 if (argc < 2) {
345 strcat(line, " ");
9072bd8a 346 printf("(remote-files) ");
cf8133c7
SL
347 gets(&line[strlen(line)]);
348 makeargv();
349 argc = margc;
350 argv = margv;
351 }
352 if (argc < 2) {
5ac6fc46 353 printf("%s remote-files\n", argv[0]);
cf8133c7
SL
354 return;
355 }
5ac6fc46
SL
356 while ((cp = remglob(argc, argv)) != NULL)
357 if (confirm(argv[0], cp))
358 recvrequest("RETR", cp, cp, "w");
359}
cf8133c7 360
5ac6fc46
SL
361char *
362remglob(argc, argv)
363 char *argv[];
364{
9072bd8a 365 char temp[16];
5ac6fc46
SL
366 static char buf[MAXPATHLEN];
367 static FILE *ftemp = NULL;
368 static char **args;
614e24b6 369 int oldverbose, oldhash;
9072bd8a 370 char *cp, *mode;
5ac6fc46
SL
371
372 if (!doglob) {
9072bd8a 373 if (args == NULL)
5ac6fc46
SL
374 args = argv;
375 if ((cp = *++args) == NULL)
376 args = NULL;
377 return (cp);
cf8133c7 378 }
cf8133c7 379 if (ftemp == NULL) {
5ac6fc46
SL
380 strcpy(temp, "/tmp/ftpXXXXXX");
381 mktemp(temp);
382 oldverbose = verbose, verbose = 0;
614e24b6 383 oldhash = hash, hash = 0;
9072bd8a
SL
384 for (mode = "w"; *++argv != NULL; mode = "a")
385 recvrequest ("NLST", temp, *argv, mode);
614e24b6 386 verbose = oldverbose; hash = oldhash;
5ac6fc46
SL
387 ftemp = fopen(temp, "r");
388 unlink(temp);
389 if (ftemp == NULL) {
390 printf("can't find list of remote files, oops\n");
9072bd8a 391 return (NULL);
5ac6fc46 392 }
cf8133c7 393 }
5ac6fc46
SL
394 if (fgets(buf, sizeof (buf), ftemp) == NULL) {
395 fclose(ftemp), ftemp = NULL;
396 return (NULL);
cf8133c7 397 }
5ac6fc46
SL
398 if ((cp = index(buf, '\n')) != NULL)
399 *cp = '\0';
400 return (buf);
cf8133c7
SL
401}
402
59d0d309
SL
403char *
404onoff(bool)
405 int bool;
406{
407
408 return (bool ? "on" : "off");
409}
410
411/*
412 * Show status.
413 */
414status(argc, argv)
415 char *argv[];
416{
417
418 if (connected)
419 printf("Connected to %s.\n", hostname);
420 else
421 printf("Not connected.\n");
422 printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
423 modename, typename, formname, structname);
cf8133c7
SL
424 printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
425 onoff(verbose), onoff(bell), onoff(interactive),
426 onoff(doglob));
7136ef0a
SL
427 printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
428 onoff(hash), onoff(sendport));
59d0d309
SL
429}
430
431/*
432 * Set beep on cmd completed mode.
433 */
434/*VARARGS*/
435setbell()
436{
437
438 bell = !bell;
439 printf("Bell mode %s.\n", onoff(bell));
440}
441
442/*
443 * Turn on packet tracing.
444 */
445/*VARARGS*/
446settrace()
447{
448
449 trace = !trace;
450 printf("Packet tracing %s.\n", onoff(trace));
451}
452
5ac6fc46
SL
453/*
454 * Toggle hash mark printing during transfers.
455 */
456/*VARARGS*/
457sethash()
458{
459
460 hash = !hash;
461 printf("Hash mark printing %s", onoff(hash));
462 if (hash)
463 printf(" (%d bytes/hash mark)", BUFSIZ);
464 printf(".\n");
465}
466
59d0d309
SL
467/*
468 * Turn on printing of server echo's.
469 */
470/*VARARGS*/
471setverbose()
472{
473
474 verbose = !verbose;
475 printf("Verbose mode %s.\n", onoff(verbose));
476}
477
5ac6fc46
SL
478/*
479 * Toggle PORT cmd use before each data connection.
480 */
481/*VARARGS*/
482setport()
483{
484
485 sendport = !sendport;
486 printf("Use of PORT cmds %s.\n", onoff(sendport));
487}
488
59d0d309
SL
489/*
490 * Turn on interactive prompting
491 * during mget, mput, and mdelete.
492 */
493/*VARARGS*/
494setprompt()
495{
496
497 interactive = !interactive;
498 printf("Interactive mode %s.\n", onoff(interactive));
499}
500
cf8133c7
SL
501/*
502 * Toggle metacharacter interpretation
503 * on local file names.
504 */
505/*VARARGS*/
506setglob()
507{
508
509 doglob = !doglob;
510 printf("Globbing %s.\n", onoff(doglob));
511}
512
59d0d309
SL
513/*
514 * Set debugging mode on/off and/or
515 * set level of debugging.
516 */
9072bd8a 517/*VARARGS*/
59d0d309
SL
518setdebug(argc, argv)
519 char *argv[];
520{
521 int val;
522
523 if (argc > 1) {
524 val = atoi(argv[1]);
525 if (val < 0) {
526 printf("%s: bad debugging value.\n", argv[1]);
527 return;
528 }
529 } else
530 val = !debug;
531 debug = val;
532 if (debug)
533 options |= SO_DEBUG;
534 else
535 options &= ~SO_DEBUG;
536 printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
537}
538
539/*
540 * Set current working directory
541 * on remote machine.
542 */
543cd(argc, argv)
544 char *argv[];
545{
546
59d0d309
SL
547 if (argc < 2) {
548 strcat(line, " ");
549 printf("(remote-directory) ");
550 gets(&line[strlen(line)]);
551 makeargv();
552 argc = margc;
553 argv = margv;
554 }
555 if (argc < 2) {
556 printf("%s remote-directory\n", argv[0]);
557 return;
558 }
559 (void) command("CWD %s", argv[1]);
560}
561
59d0d309
SL
562/*
563 * Set current working directory
564 * on local machine.
565 */
566lcd(argc, argv)
567 char *argv[];
568{
cf8133c7 569 char buf[MAXPATHLEN];
59d0d309 570
cf8133c7
SL
571 if (argc < 2)
572 argc++, argv[1] = home;
59d0d309
SL
573 if (argc != 2) {
574 printf("%s local-directory\n", argv[0]);
575 return;
576 }
cf8133c7
SL
577 if (!globulize(&argv[1]))
578 return;
579 if (chdir(argv[1]) < 0) {
59d0d309 580 perror(argv[1]);
cf8133c7
SL
581 return;
582 }
583 printf("Local directory now %s\n", getwd(buf));
59d0d309
SL
584}
585
586/*
587 * Delete a single file.
588 */
589delete(argc, argv)
590 char *argv[];
591{
592
593 if (argc < 2) {
594 strcat(line, " ");
595 printf("(remote-file) ");
596 gets(&line[strlen(line)]);
597 makeargv();
598 argc = margc;
599 argv = margv;
600 }
601 if (argc < 2) {
602 printf("%s remote-file\n", argv[0]);
603 return;
604 }
605 (void) command("DELE %s", argv[1]);
606}
607
5ac6fc46
SL
608/*
609 * Delete multiple files.
610 */
611mdelete(argc, argv)
612 char *argv[];
613{
614 char *cp;
615
616 if (argc < 2) {
617 strcat(line, " ");
618 printf("(remote-files) ");
619 gets(&line[strlen(line)]);
620 makeargv();
621 argc = margc;
622 argv = margv;
623 }
624 if (argc < 2) {
625 printf("%s remote-files\n", argv[0]);
626 return;
627 }
628 while ((cp = remglob(argc, argv)) != NULL)
629 if (confirm(argv[0], cp))
630 (void) command("DELE %s", cp);
631}
9072bd8a 632
59d0d309
SL
633/*
634 * Rename a remote file.
635 */
636renamefile(argc, argv)
637 char *argv[];
638{
639
640 if (argc < 2) {
641 strcat(line, " ");
642 printf("(from-name) ");
643 gets(&line[strlen(line)]);
644 makeargv();
645 argc = margc;
646 argv = margv;
647 }
648 if (argc < 2) {
649usage:
650 printf("%s from-name to-name\n", argv[0]);
651 return;
652 }
653 if (argc < 3) {
654 strcat(line, " ");
655 printf("(to-name) ");
656 gets(&line[strlen(line)]);
657 makeargv();
658 argc = margc;
659 argv = margv;
660 }
661 if (argc < 3)
662 goto usage;
663 if (command("RNFR %s", argv[1]) == CONTINUE)
664 (void) command("RNTO %s", argv[2]);
665}
666
667/*
668 * Get a directory listing
669 * of remote files.
670 */
671ls(argc, argv)
672 char *argv[];
673{
9072bd8a 674 char *cmd;
59d0d309
SL
675
676 if (argc < 2)
677 argc++, argv[1] = NULL;
678 if (argc < 3)
679 argc++, argv[2] = "-";
9072bd8a
SL
680 if (argc > 3) {
681 printf("usage: %s remote-directory local-file\n", argv[0]);
682 return;
683 }
59d0d309 684 cmd = argv[0][0] == 'l' ? "NLST" : "LIST";
cf8133c7
SL
685 if (strcmp(argv[2], "-") && !globulize(&argv[2]))
686 return;
9072bd8a
SL
687 recvrequest(cmd, argv[2], argv[1], "w");
688}
689
690/*
691 * Get a directory listing
692 * of multiple remote files.
693 */
694mls(argc, argv)
695 char *argv[];
696{
614e24b6 697 char *cmd, *mode, *cp, *dest;
9072bd8a 698
614e24b6
SL
699 if (argc < 2) {
700 strcat(line, " ");
701 printf("(remote-files) ");
702 gets(&line[strlen(line)]);
703 makeargv();
704 argc = margc;
705 argv = margv;
706 }
707 if (argc < 3) {
708 strcat(line, " ");
709 printf("(local-file) ");
710 gets(&line[strlen(line)]);
711 makeargv();
712 argc = margc;
713 argv = margv;
714 }
715 if (argc < 3) {
716 printf("%s remote-files local-file\n", argv[0]);
717 return;
718 }
719 dest = argv[argc - 1];
720 argv[argc - 1] = NULL;
721 if (strcmp(dest, "-"))
ee87b73e 722 if (!globulize(&dest) || !confirm("local-file", dest))
9072bd8a 723 return;
614e24b6
SL
724 cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
725 for (mode = "w"; cp = remglob(argc, argv); mode = "a")
726 if (confirm(argv[0], cp))
727 recvrequest(cmd, dest, cp, mode);
59d0d309
SL
728}
729
730/*
731 * Do a shell escape
732 */
733shell(argc, argv)
734 char *argv[];
735{
9072bd8a
SL
736 int pid, status, (*old1)(), (*old2)();
737 char shellnam[40], *shell, *namep;
738 char **cpp, **gargs;
739
740 old1 = signal (SIGINT, SIG_IGN);
741 old2 = signal (SIGQUIT, SIG_IGN);
742 if ((pid = fork()) == 0) {
743 for (pid = 3; pid < 20; pid++)
744 close(pid);
745 signal(SIGINT, SIG_DFL);
746 signal(SIGQUIT, SIG_DFL);
14433a73
KM
747 shell = getenv("SHELL");
748 if (shell == NULL)
749 shell = "/bin/sh";
750 namep = rindex(shell,'/');
751 if (namep == NULL)
752 namep = shell;
9072bd8a 753 if (argc <= 1) {
9072bd8a
SL
754 if (debug) {
755 printf ("%s\n", shell);
756 fflush (stdout);
757 }
14433a73
KM
758 execl(shell, shell, (char *)0);
759 } else {
760 char *args[4]; /* "sh" "-c" <command> NULL */
761
762 args[0] = shell;
763 args[1] = "-c";
764 args[2] = argv[1];
765 args[3] = NULL;
766 if (debug) {
767 printf("%s -c %s\n", shell, argv[1]);
768 fflush(stdout);
9072bd8a 769 }
14433a73 770 execv(shell, args);
9072bd8a 771 }
14433a73 772 perror(shell);
9072bd8a
SL
773 exit(1);
774 }
775 if (pid > 0)
776 while (wait(&status) != pid)
777 ;
778 signal(SIGINT, old1);
779 signal(SIGQUIT, old2);
780 if (pid == -1)
781 perror("Try again later");
782 return (0);
59d0d309
SL
783}
784
785/*
786 * Send new user information (re-login)
787 */
788user(argc, argv)
789 int argc;
790 char **argv;
791{
792 char acct[80], *getpass();
793 int n;
794
795 if (argc < 2) {
796 strcat(line, " ");
797 printf("(username) ");
798 gets(&line[strlen(line)]);
799 makeargv();
800 argc = margc;
801 argv = margv;
802 }
803 if (argc > 4) {
804 printf("usage: %s username [password] [account]\n", argv[0]);
9072bd8a 805 return (0);
59d0d309
SL
806 }
807 n = command("USER %s", argv[1]);
808 if (n == CONTINUE) {
809 if (argc < 3 )
810 argv[2] = getpass("Password: "), argc++;
811 n = command("PASS %s", argv[2]);
812 }
813 if (n == CONTINUE) {
814 if (argc < 4) {
815 printf("Account: "); (void) fflush(stdout);
816 (void) fgets(acct, sizeof(acct) - 1, stdin);
817 acct[strlen(acct) - 1] = '\0';
818 argv[3] = acct; argc++;
819 }
820 n = command("ACCT %s", acct);
821 }
822 if (n != COMPLETE) {
823 fprintf(stderr, "Login failed.\n");
824 return (0);
825 }
826 return (1);
827}
828
829/*
830 * Print working directory.
831 */
832/*VARARGS*/
833pwd()
834{
9072bd8a 835
59d0d309
SL
836 (void) command("XPWD");
837}
838
839/*
840 * Make a directory.
841 */
842makedir(argc, argv)
843 char *argv[];
844{
845
846 if (argc < 2) {
847 strcat(line, " ");
848 printf("(directory-name) ");
849 gets(&line[strlen(line)]);
850 makeargv();
851 argc = margc;
852 argv = margv;
853 }
854 if (argc < 2) {
855 printf("%s directory-name\n", argv[0]);
856 return;
857 }
858 (void) command("XMKD %s", argv[1]);
859}
860
861/*
862 * Remove a directory.
863 */
864removedir(argc, argv)
865 char *argv[];
866{
867
868 if (argc < 2) {
869 strcat(line, " ");
870 printf("(directory-name) ");
871 gets(&line[strlen(line)]);
872 makeargv();
873 argc = margc;
874 argv = margv;
875 }
876 if (argc < 2) {
877 printf("%s directory-name\n", argv[0]);
878 return;
879 }
880 (void) command("XRMD %s", argv[1]);
881}
882
883/*
884 * Send a line, verbatim, to the remote machine.
885 */
886quote(argc, argv)
887 char *argv[];
888{
889 int i;
890 char buf[BUFSIZ];
891
892 if (argc < 2) {
893 strcat(line, " ");
894 printf("(command line to send) ");
895 gets(&line[strlen(line)]);
896 makeargv();
897 argc = margc;
898 argv = margv;
899 }
900 if (argc < 2) {
901 printf("usage: %s line-to-send\n", argv[0]);
902 return;
903 }
904 strcpy(buf, argv[1]);
905 for (i = 2; i < argc; i++) {
906 strcat(buf, " ");
907 strcat(buf, argv[i]);
908 }
909 (void) command(buf);
910}
911
912/*
913 * Ask the other side for help.
914 */
915rmthelp(argc, argv)
916 char *argv[];
917{
918 int oldverbose = verbose;
919
920 verbose = 1;
921 (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
922 verbose = oldverbose;
923}
924
925/*
926 * Terminate session and exit.
927 */
928/*VARARGS*/
929quit()
930{
931
71a655cd
RC
932 if (connected)
933 disconnect();
59d0d309
SL
934 exit(0);
935}
936
937/*
938 * Terminate session, but don't exit.
939 */
940disconnect()
941{
942 extern FILE *cout;
943 extern int data;
944
945 if (!connected)
946 return;
947 (void) command("QUIT");
948 (void) fclose(cout);
949 cout = NULL;
950 connected = 0;
951 data = -1;
952}
cf8133c7 953
5ac6fc46 954confirm(cmd, file)
cf8133c7
SL
955 char *cmd, *file;
956{
957 char line[BUFSIZ];
958
959 if (!interactive)
5ac6fc46 960 return (1);
cf8133c7
SL
961 printf("%s %s? ", cmd, file);
962 fflush(stdout);
963 gets(line);
5ac6fc46 964 return (*line != 'n' && *line != 'N');
cf8133c7
SL
965}
966
967fatal(msg)
968 char *msg;
969{
970
971 fprintf(stderr, "ftp: %s\n");
972 exit(1);
973}
974
975/*
976 * Glob a local file name specification with
977 * the expectation of a single return value.
978 * Can't control multiple values being expanded
979 * from the expression, we return only the first.
980 */
981globulize(cpp)
982 char **cpp;
983{
984 char **globbed;
985
986 if (!doglob)
987 return (1);
988 globbed = glob(*cpp);
989 if (globerr != NULL) {
990 printf("%s: %s\n", *cpp, globerr);
991 if (globbed)
992 blkfree(globbed);
993 return (0);
994 }
995 if (globbed) {
996 *cpp = *globbed++;
997 /* don't waste too much memory */
998 if (*globbed)
999 blkfree(globbed);
1000 }
1001 return (1);
1002}