recalculate nvis after move
[unix-history] / usr / src / usr.bin / ftp / cmds.c
CommitLineData
59d0d309 1#ifndef lint
7136ef0a 2static char sccsid[] = "@(#)cmds.c 4.9 (Berkeley) %G%";
59d0d309
SL
3#endif
4
5/*
6 * FTP User Program -- Command Routines.
7 */
cf8133c7 8#include <sys/param.h>
19371098 9#include <sys/stat.h>
59d0d309
SL
10#include <sys/socket.h>
11
62c4a390
SL
12#include <arpa/ftp.h>
13
59d0d309
SL
14#include <signal.h>
15#include <stdio.h>
16#include <errno.h>
17#include <netdb.h>
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{
614e24b6 246 register int i;
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 }
614e24b6
SL
260 for (i = 1; i < argc; i++) {
261 register char **cpp, **gargs;
262
263 if (!doglob) {
264 if (confirm(argv[0], argv[i]))
265 sendrequest("STOR", argv[i], argv[i]);
266 continue;
267 }
268 gargs = glob(argv[i]);
cf8133c7 269 if (globerr != NULL) {
5ac6fc46
SL
270 printf("%s\n", globerr);
271 if (gargs)
272 blkfree(gargs);
614e24b6 273 continue;
cf8133c7 274 }
614e24b6
SL
275 for (cpp = gargs; cpp && *cpp != NULL; cpp++)
276 if (confirm(argv[0], *cpp))
277 sendrequest("STOR", *cpp, *cpp);
278 if (gargs != NULL)
279 blkfree(gargs);
cf8133c7
SL
280 }
281}
282
283/*
284 * Receive one file.
59d0d309
SL
285 */
286get(argc, argv)
287 char *argv[];
288{
59d0d309 289
59d0d309
SL
290 if (argc == 2)
291 argc++, argv[2] = argv[1];
292 if (argc < 2) {
293 strcat(line, " ");
294 printf("(remote-file) ");
295 gets(&line[strlen(line)]);
296 makeargv();
297 argc = margc;
298 argv = margv;
299 }
300 if (argc < 2) {
301usage:
cf8133c7 302 printf("%s remote-file [ local-file ]\n", argv[0]);
59d0d309
SL
303 return;
304 }
305 if (argc < 3) {
306 strcat(line, " ");
307 printf("(local-file) ");
308 gets(&line[strlen(line)]);
309 makeargv();
310 argc = margc;
311 argv = margv;
312 }
313 if (argc < 3)
314 goto usage;
cf8133c7
SL
315 if (!globulize(&argv[2]))
316 return;
5ac6fc46 317 recvrequest("RETR", argv[2], argv[1], "w");
59d0d309
SL
318}
319
cf8133c7
SL
320/*
321 * Get multiple files.
322 */
323mget(argc, argv)
324 char *argv[];
325{
9072bd8a 326 char *cp;
cf8133c7 327
cf8133c7
SL
328 if (argc < 2) {
329 strcat(line, " ");
9072bd8a 330 printf("(remote-files) ");
cf8133c7
SL
331 gets(&line[strlen(line)]);
332 makeargv();
333 argc = margc;
334 argv = margv;
335 }
336 if (argc < 2) {
5ac6fc46 337 printf("%s remote-files\n", argv[0]);
cf8133c7
SL
338 return;
339 }
5ac6fc46
SL
340 while ((cp = remglob(argc, argv)) != NULL)
341 if (confirm(argv[0], cp))
342 recvrequest("RETR", cp, cp, "w");
343}
cf8133c7 344
5ac6fc46
SL
345char *
346remglob(argc, argv)
347 char *argv[];
348{
9072bd8a 349 char temp[16];
5ac6fc46
SL
350 static char buf[MAXPATHLEN];
351 static FILE *ftemp = NULL;
352 static char **args;
614e24b6 353 int oldverbose, oldhash;
9072bd8a 354 char *cp, *mode;
5ac6fc46
SL
355
356 if (!doglob) {
9072bd8a 357 if (args == NULL)
5ac6fc46
SL
358 args = argv;
359 if ((cp = *++args) == NULL)
360 args = NULL;
361 return (cp);
cf8133c7 362 }
cf8133c7 363 if (ftemp == NULL) {
5ac6fc46
SL
364 strcpy(temp, "/tmp/ftpXXXXXX");
365 mktemp(temp);
366 oldverbose = verbose, verbose = 0;
614e24b6 367 oldhash = hash, hash = 0;
9072bd8a
SL
368 for (mode = "w"; *++argv != NULL; mode = "a")
369 recvrequest ("NLST", temp, *argv, mode);
614e24b6 370 verbose = oldverbose; hash = oldhash;
5ac6fc46
SL
371 ftemp = fopen(temp, "r");
372 unlink(temp);
373 if (ftemp == NULL) {
374 printf("can't find list of remote files, oops\n");
9072bd8a 375 return (NULL);
5ac6fc46 376 }
cf8133c7 377 }
5ac6fc46
SL
378 if (fgets(buf, sizeof (buf), ftemp) == NULL) {
379 fclose(ftemp), ftemp = NULL;
380 return (NULL);
cf8133c7 381 }
5ac6fc46
SL
382 if ((cp = index(buf, '\n')) != NULL)
383 *cp = '\0';
384 return (buf);
cf8133c7
SL
385}
386
59d0d309
SL
387char *
388onoff(bool)
389 int bool;
390{
391
392 return (bool ? "on" : "off");
393}
394
395/*
396 * Show status.
397 */
398status(argc, argv)
399 char *argv[];
400{
401
402 if (connected)
403 printf("Connected to %s.\n", hostname);
404 else
405 printf("Not connected.\n");
406 printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
407 modename, typename, formname, structname);
cf8133c7
SL
408 printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
409 onoff(verbose), onoff(bell), onoff(interactive),
410 onoff(doglob));
7136ef0a
SL
411 printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
412 onoff(hash), onoff(sendport));
59d0d309
SL
413}
414
415/*
416 * Set beep on cmd completed mode.
417 */
418/*VARARGS*/
419setbell()
420{
421
422 bell = !bell;
423 printf("Bell mode %s.\n", onoff(bell));
424}
425
426/*
427 * Turn on packet tracing.
428 */
429/*VARARGS*/
430settrace()
431{
432
433 trace = !trace;
434 printf("Packet tracing %s.\n", onoff(trace));
435}
436
5ac6fc46
SL
437/*
438 * Toggle hash mark printing during transfers.
439 */
440/*VARARGS*/
441sethash()
442{
443
444 hash = !hash;
445 printf("Hash mark printing %s", onoff(hash));
446 if (hash)
447 printf(" (%d bytes/hash mark)", BUFSIZ);
448 printf(".\n");
449}
450
59d0d309
SL
451/*
452 * Turn on printing of server echo's.
453 */
454/*VARARGS*/
455setverbose()
456{
457
458 verbose = !verbose;
459 printf("Verbose mode %s.\n", onoff(verbose));
460}
461
5ac6fc46
SL
462/*
463 * Toggle PORT cmd use before each data connection.
464 */
465/*VARARGS*/
466setport()
467{
468
469 sendport = !sendport;
470 printf("Use of PORT cmds %s.\n", onoff(sendport));
471}
472
59d0d309
SL
473/*
474 * Turn on interactive prompting
475 * during mget, mput, and mdelete.
476 */
477/*VARARGS*/
478setprompt()
479{
480
481 interactive = !interactive;
482 printf("Interactive mode %s.\n", onoff(interactive));
483}
484
cf8133c7
SL
485/*
486 * Toggle metacharacter interpretation
487 * on local file names.
488 */
489/*VARARGS*/
490setglob()
491{
492
493 doglob = !doglob;
494 printf("Globbing %s.\n", onoff(doglob));
495}
496
59d0d309
SL
497/*
498 * Set debugging mode on/off and/or
499 * set level of debugging.
500 */
9072bd8a 501/*VARARGS*/
59d0d309
SL
502setdebug(argc, argv)
503 char *argv[];
504{
505 int val;
506
507 if (argc > 1) {
508 val = atoi(argv[1]);
509 if (val < 0) {
510 printf("%s: bad debugging value.\n", argv[1]);
511 return;
512 }
513 } else
514 val = !debug;
515 debug = val;
516 if (debug)
517 options |= SO_DEBUG;
518 else
519 options &= ~SO_DEBUG;
520 printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
521}
522
523/*
524 * Set current working directory
525 * on remote machine.
526 */
527cd(argc, argv)
528 char *argv[];
529{
530
59d0d309
SL
531 if (argc < 2) {
532 strcat(line, " ");
533 printf("(remote-directory) ");
534 gets(&line[strlen(line)]);
535 makeargv();
536 argc = margc;
537 argv = margv;
538 }
539 if (argc < 2) {
540 printf("%s remote-directory\n", argv[0]);
541 return;
542 }
543 (void) command("CWD %s", argv[1]);
544}
545
59d0d309
SL
546/*
547 * Set current working directory
548 * on local machine.
549 */
550lcd(argc, argv)
551 char *argv[];
552{
cf8133c7 553 char buf[MAXPATHLEN];
59d0d309 554
cf8133c7
SL
555 if (argc < 2)
556 argc++, argv[1] = home;
59d0d309
SL
557 if (argc != 2) {
558 printf("%s local-directory\n", argv[0]);
559 return;
560 }
cf8133c7
SL
561 if (!globulize(&argv[1]))
562 return;
563 if (chdir(argv[1]) < 0) {
59d0d309 564 perror(argv[1]);
cf8133c7
SL
565 return;
566 }
567 printf("Local directory now %s\n", getwd(buf));
59d0d309
SL
568}
569
570/*
571 * Delete a single file.
572 */
573delete(argc, argv)
574 char *argv[];
575{
576
577 if (argc < 2) {
578 strcat(line, " ");
579 printf("(remote-file) ");
580 gets(&line[strlen(line)]);
581 makeargv();
582 argc = margc;
583 argv = margv;
584 }
585 if (argc < 2) {
586 printf("%s remote-file\n", argv[0]);
587 return;
588 }
589 (void) command("DELE %s", argv[1]);
590}
591
5ac6fc46
SL
592/*
593 * Delete multiple files.
594 */
595mdelete(argc, argv)
596 char *argv[];
597{
598 char *cp;
599
600 if (argc < 2) {
601 strcat(line, " ");
602 printf("(remote-files) ");
603 gets(&line[strlen(line)]);
604 makeargv();
605 argc = margc;
606 argv = margv;
607 }
608 if (argc < 2) {
609 printf("%s remote-files\n", argv[0]);
610 return;
611 }
612 while ((cp = remglob(argc, argv)) != NULL)
613 if (confirm(argv[0], cp))
614 (void) command("DELE %s", cp);
615}
9072bd8a 616
59d0d309
SL
617/*
618 * Rename a remote file.
619 */
620renamefile(argc, argv)
621 char *argv[];
622{
623
624 if (argc < 2) {
625 strcat(line, " ");
626 printf("(from-name) ");
627 gets(&line[strlen(line)]);
628 makeargv();
629 argc = margc;
630 argv = margv;
631 }
632 if (argc < 2) {
633usage:
634 printf("%s from-name to-name\n", argv[0]);
635 return;
636 }
637 if (argc < 3) {
638 strcat(line, " ");
639 printf("(to-name) ");
640 gets(&line[strlen(line)]);
641 makeargv();
642 argc = margc;
643 argv = margv;
644 }
645 if (argc < 3)
646 goto usage;
647 if (command("RNFR %s", argv[1]) == CONTINUE)
648 (void) command("RNTO %s", argv[2]);
649}
650
651/*
652 * Get a directory listing
653 * of remote files.
654 */
655ls(argc, argv)
656 char *argv[];
657{
9072bd8a 658 char *cmd;
59d0d309
SL
659
660 if (argc < 2)
661 argc++, argv[1] = NULL;
662 if (argc < 3)
663 argc++, argv[2] = "-";
9072bd8a
SL
664 if (argc > 3) {
665 printf("usage: %s remote-directory local-file\n", argv[0]);
666 return;
667 }
59d0d309 668 cmd = argv[0][0] == 'l' ? "NLST" : "LIST";
cf8133c7
SL
669 if (strcmp(argv[2], "-") && !globulize(&argv[2]))
670 return;
9072bd8a
SL
671 recvrequest(cmd, argv[2], argv[1], "w");
672}
673
674/*
675 * Get a directory listing
676 * of multiple remote files.
677 */
678mls(argc, argv)
679 char *argv[];
680{
614e24b6 681 char *cmd, *mode, *cp, *dest;
9072bd8a 682
614e24b6
SL
683 if (argc < 2) {
684 strcat(line, " ");
685 printf("(remote-files) ");
686 gets(&line[strlen(line)]);
687 makeargv();
688 argc = margc;
689 argv = margv;
690 }
691 if (argc < 3) {
692 strcat(line, " ");
693 printf("(local-file) ");
694 gets(&line[strlen(line)]);
695 makeargv();
696 argc = margc;
697 argv = margv;
698 }
699 if (argc < 3) {
700 printf("%s remote-files local-file\n", argv[0]);
701 return;
702 }
703 dest = argv[argc - 1];
704 argv[argc - 1] = NULL;
705 if (strcmp(dest, "-"))
706 if (globulize(&dest) && confirm("local-file", dest))
9072bd8a 707 return;
614e24b6
SL
708 cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
709 for (mode = "w"; cp = remglob(argc, argv); mode = "a")
710 if (confirm(argv[0], cp))
711 recvrequest(cmd, dest, cp, mode);
59d0d309
SL
712}
713
714/*
715 * Do a shell escape
716 */
717shell(argc, argv)
718 char *argv[];
719{
9072bd8a
SL
720 int pid, status, (*old1)(), (*old2)();
721 char shellnam[40], *shell, *namep;
722 char **cpp, **gargs;
723
724 old1 = signal (SIGINT, SIG_IGN);
725 old2 = signal (SIGQUIT, SIG_IGN);
726 if ((pid = fork()) == 0) {
727 for (pid = 3; pid < 20; pid++)
728 close(pid);
729 signal(SIGINT, SIG_DFL);
730 signal(SIGQUIT, SIG_DFL);
731 if (argc <= 1) {
732 shell = getenv("SHELL");
733 if (shell == NULL)
734 shell = "/bin/sh";
735 namep = rindex(shell,'/');
736 if (namep == NULL)
737 namep = shell;
738 strcpy(shellnam,"-");
739 strcat(shellnam, ++namep);
740 if (strcmp(namep, "sh") != 0)
741 shellnam[0] = '+';
742 if (debug) {
743 printf ("%s\n", shell);
744 fflush (stdout);
745 }
746 execl(shell, shellnam, 0);
747 perror(shell);
748 exit(1);
749 }
750 cpp = &argv[1];
751 if (argc > 2) {
752 if ((gargs = glob(cpp)) != NULL)
753 cpp = gargs;
754 if (globerr != NULL) {
755 printf("%s\n", globerr);
756 exit(1);
757 }
758 }
759 if (debug) {
760 register char **zip = cpp;
761
762 printf("%s", *zip);
763 while (*++zip != NULL)
764 printf(" %s", *zip);
765 printf("\n");
766 fflush(stdout);
767 }
768 execvp(argv[1], cpp);
769 perror(argv[1]);
770 exit(1);
771 }
772 if (pid > 0)
773 while (wait(&status) != pid)
774 ;
775 signal(SIGINT, old1);
776 signal(SIGQUIT, old2);
777 if (pid == -1)
778 perror("Try again later");
779 return (0);
59d0d309
SL
780}
781
782/*
783 * Send new user information (re-login)
784 */
785user(argc, argv)
786 int argc;
787 char **argv;
788{
789 char acct[80], *getpass();
790 int n;
791
792 if (argc < 2) {
793 strcat(line, " ");
794 printf("(username) ");
795 gets(&line[strlen(line)]);
796 makeargv();
797 argc = margc;
798 argv = margv;
799 }
800 if (argc > 4) {
801 printf("usage: %s username [password] [account]\n", argv[0]);
9072bd8a 802 return (0);
59d0d309
SL
803 }
804 n = command("USER %s", argv[1]);
805 if (n == CONTINUE) {
806 if (argc < 3 )
807 argv[2] = getpass("Password: "), argc++;
808 n = command("PASS %s", argv[2]);
809 }
810 if (n == CONTINUE) {
811 if (argc < 4) {
812 printf("Account: "); (void) fflush(stdout);
813 (void) fgets(acct, sizeof(acct) - 1, stdin);
814 acct[strlen(acct) - 1] = '\0';
815 argv[3] = acct; argc++;
816 }
817 n = command("ACCT %s", acct);
818 }
819 if (n != COMPLETE) {
820 fprintf(stderr, "Login failed.\n");
821 return (0);
822 }
823 return (1);
824}
825
826/*
827 * Print working directory.
828 */
829/*VARARGS*/
830pwd()
831{
9072bd8a 832
59d0d309
SL
833 (void) command("XPWD");
834}
835
836/*
837 * Make a directory.
838 */
839makedir(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("XMKD %s", argv[1]);
856}
857
858/*
859 * Remove a directory.
860 */
861removedir(argc, argv)
862 char *argv[];
863{
864
865 if (argc < 2) {
866 strcat(line, " ");
867 printf("(directory-name) ");
868 gets(&line[strlen(line)]);
869 makeargv();
870 argc = margc;
871 argv = margv;
872 }
873 if (argc < 2) {
874 printf("%s directory-name\n", argv[0]);
875 return;
876 }
877 (void) command("XRMD %s", argv[1]);
878}
879
880/*
881 * Send a line, verbatim, to the remote machine.
882 */
883quote(argc, argv)
884 char *argv[];
885{
886 int i;
887 char buf[BUFSIZ];
888
889 if (argc < 2) {
890 strcat(line, " ");
891 printf("(command line to send) ");
892 gets(&line[strlen(line)]);
893 makeargv();
894 argc = margc;
895 argv = margv;
896 }
897 if (argc < 2) {
898 printf("usage: %s line-to-send\n", argv[0]);
899 return;
900 }
901 strcpy(buf, argv[1]);
902 for (i = 2; i < argc; i++) {
903 strcat(buf, " ");
904 strcat(buf, argv[i]);
905 }
906 (void) command(buf);
907}
908
909/*
910 * Ask the other side for help.
911 */
912rmthelp(argc, argv)
913 char *argv[];
914{
915 int oldverbose = verbose;
916
917 verbose = 1;
918 (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
919 verbose = oldverbose;
920}
921
922/*
923 * Terminate session and exit.
924 */
925/*VARARGS*/
926quit()
927{
928
929 disconnect();
930 exit(0);
931}
932
933/*
934 * Terminate session, but don't exit.
935 */
936disconnect()
937{
938 extern FILE *cout;
939 extern int data;
940
941 if (!connected)
942 return;
943 (void) command("QUIT");
944 (void) fclose(cout);
945 cout = NULL;
946 connected = 0;
947 data = -1;
948}
cf8133c7 949
5ac6fc46 950confirm(cmd, file)
cf8133c7
SL
951 char *cmd, *file;
952{
953 char line[BUFSIZ];
954
955 if (!interactive)
5ac6fc46 956 return (1);
cf8133c7
SL
957 printf("%s %s? ", cmd, file);
958 fflush(stdout);
959 gets(line);
5ac6fc46 960 return (*line != 'n' && *line != 'N');
cf8133c7
SL
961}
962
963fatal(msg)
964 char *msg;
965{
966
967 fprintf(stderr, "ftp: %s\n");
968 exit(1);
969}
970
971/*
972 * Glob a local file name specification with
973 * the expectation of a single return value.
974 * Can't control multiple values being expanded
975 * from the expression, we return only the first.
976 */
977globulize(cpp)
978 char **cpp;
979{
980 char **globbed;
981
982 if (!doglob)
983 return (1);
984 globbed = glob(*cpp);
985 if (globerr != NULL) {
986 printf("%s: %s\n", *cpp, globerr);
987 if (globbed)
988 blkfree(globbed);
989 return (0);
990 }
991 if (globbed) {
992 *cpp = *globbed++;
993 /* don't waste too much memory */
994 if (*globbed)
995 blkfree(globbed);
996 }
997 return (1);
998}