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