fixed some minor bugs, tested
[unix-history] / usr / src / usr.bin / ftp / cmds.c
CommitLineData
59d0d309 1#ifndef lint
19371098 2static char sccsid[] = "@(#)cmds.c 4.8 (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));
614e24b6
SL
411 printf("Hash mark printing: %s; Use of PORT cmds: %s; Linger: %s\n",
412 onoff(hash), onoff(sendport), onoff(linger));
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
614e24b6
SL
523/*
524 * Set linger on data connections on/off.
525 */
526/*VARARGS*/
527setlinger(argc, argv)
528 char *argv[];
529{
530
531 if (argc == 1)
532 linger = !linger;
533 else
534 linger = atoi(argv[1]);
535 if (argc == 1 || linger == 0) {
536 printf("Linger on data connection close %s.\n", onoff(linger));
537 return;
538 }
539 printf("Will linger for %d seconds on close of data connections.\n",
540 linger);
541}
542
59d0d309
SL
543/*
544 * Set current working directory
545 * on remote machine.
546 */
547cd(argc, argv)
548 char *argv[];
549{
550
59d0d309
SL
551 if (argc < 2) {
552 strcat(line, " ");
553 printf("(remote-directory) ");
554 gets(&line[strlen(line)]);
555 makeargv();
556 argc = margc;
557 argv = margv;
558 }
559 if (argc < 2) {
560 printf("%s remote-directory\n", argv[0]);
561 return;
562 }
563 (void) command("CWD %s", argv[1]);
564}
565
59d0d309
SL
566/*
567 * Set current working directory
568 * on local machine.
569 */
570lcd(argc, argv)
571 char *argv[];
572{
cf8133c7 573 char buf[MAXPATHLEN];
59d0d309 574
cf8133c7
SL
575 if (argc < 2)
576 argc++, argv[1] = home;
59d0d309
SL
577 if (argc != 2) {
578 printf("%s local-directory\n", argv[0]);
579 return;
580 }
cf8133c7
SL
581 if (!globulize(&argv[1]))
582 return;
583 if (chdir(argv[1]) < 0) {
59d0d309 584 perror(argv[1]);
cf8133c7
SL
585 return;
586 }
587 printf("Local directory now %s\n", getwd(buf));
59d0d309
SL
588}
589
590/*
591 * Delete a single file.
592 */
593delete(argc, argv)
594 char *argv[];
595{
596
597 if (argc < 2) {
598 strcat(line, " ");
599 printf("(remote-file) ");
600 gets(&line[strlen(line)]);
601 makeargv();
602 argc = margc;
603 argv = margv;
604 }
605 if (argc < 2) {
606 printf("%s remote-file\n", argv[0]);
607 return;
608 }
609 (void) command("DELE %s", argv[1]);
610}
611
5ac6fc46
SL
612/*
613 * Delete multiple files.
614 */
615mdelete(argc, argv)
616 char *argv[];
617{
618 char *cp;
619
620 if (argc < 2) {
621 strcat(line, " ");
622 printf("(remote-files) ");
623 gets(&line[strlen(line)]);
624 makeargv();
625 argc = margc;
626 argv = margv;
627 }
628 if (argc < 2) {
629 printf("%s remote-files\n", argv[0]);
630 return;
631 }
632 while ((cp = remglob(argc, argv)) != NULL)
633 if (confirm(argv[0], cp))
634 (void) command("DELE %s", cp);
635}
9072bd8a 636
59d0d309
SL
637/*
638 * Rename a remote file.
639 */
640renamefile(argc, argv)
641 char *argv[];
642{
643
644 if (argc < 2) {
645 strcat(line, " ");
646 printf("(from-name) ");
647 gets(&line[strlen(line)]);
648 makeargv();
649 argc = margc;
650 argv = margv;
651 }
652 if (argc < 2) {
653usage:
654 printf("%s from-name to-name\n", argv[0]);
655 return;
656 }
657 if (argc < 3) {
658 strcat(line, " ");
659 printf("(to-name) ");
660 gets(&line[strlen(line)]);
661 makeargv();
662 argc = margc;
663 argv = margv;
664 }
665 if (argc < 3)
666 goto usage;
667 if (command("RNFR %s", argv[1]) == CONTINUE)
668 (void) command("RNTO %s", argv[2]);
669}
670
671/*
672 * Get a directory listing
673 * of remote files.
674 */
675ls(argc, argv)
676 char *argv[];
677{
9072bd8a 678 char *cmd;
59d0d309
SL
679
680 if (argc < 2)
681 argc++, argv[1] = NULL;
682 if (argc < 3)
683 argc++, argv[2] = "-";
9072bd8a
SL
684 if (argc > 3) {
685 printf("usage: %s remote-directory local-file\n", argv[0]);
686 return;
687 }
59d0d309 688 cmd = argv[0][0] == 'l' ? "NLST" : "LIST";
cf8133c7
SL
689 if (strcmp(argv[2], "-") && !globulize(&argv[2]))
690 return;
9072bd8a
SL
691 recvrequest(cmd, argv[2], argv[1], "w");
692}
693
694/*
695 * Get a directory listing
696 * of multiple remote files.
697 */
698mls(argc, argv)
699 char *argv[];
700{
614e24b6 701 char *cmd, *mode, *cp, *dest;
9072bd8a 702
614e24b6
SL
703 if (argc < 2) {
704 strcat(line, " ");
705 printf("(remote-files) ");
706 gets(&line[strlen(line)]);
707 makeargv();
708 argc = margc;
709 argv = margv;
710 }
711 if (argc < 3) {
712 strcat(line, " ");
713 printf("(local-file) ");
714 gets(&line[strlen(line)]);
715 makeargv();
716 argc = margc;
717 argv = margv;
718 }
719 if (argc < 3) {
720 printf("%s remote-files local-file\n", argv[0]);
721 return;
722 }
723 dest = argv[argc - 1];
724 argv[argc - 1] = NULL;
725 if (strcmp(dest, "-"))
726 if (globulize(&dest) && confirm("local-file", dest))
9072bd8a 727 return;
614e24b6
SL
728 cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
729 for (mode = "w"; cp = remglob(argc, argv); mode = "a")
730 if (confirm(argv[0], cp))
731 recvrequest(cmd, dest, cp, mode);
59d0d309
SL
732}
733
734/*
735 * Do a shell escape
736 */
737shell(argc, argv)
738 char *argv[];
739{
9072bd8a
SL
740 int pid, status, (*old1)(), (*old2)();
741 char shellnam[40], *shell, *namep;
742 char **cpp, **gargs;
743
744 old1 = signal (SIGINT, SIG_IGN);
745 old2 = signal (SIGQUIT, SIG_IGN);
746 if ((pid = fork()) == 0) {
747 for (pid = 3; pid < 20; pid++)
748 close(pid);
749 signal(SIGINT, SIG_DFL);
750 signal(SIGQUIT, SIG_DFL);
751 if (argc <= 1) {
752 shell = getenv("SHELL");
753 if (shell == NULL)
754 shell = "/bin/sh";
755 namep = rindex(shell,'/');
756 if (namep == NULL)
757 namep = shell;
758 strcpy(shellnam,"-");
759 strcat(shellnam, ++namep);
760 if (strcmp(namep, "sh") != 0)
761 shellnam[0] = '+';
762 if (debug) {
763 printf ("%s\n", shell);
764 fflush (stdout);
765 }
766 execl(shell, shellnam, 0);
767 perror(shell);
768 exit(1);
769 }
770 cpp = &argv[1];
771 if (argc > 2) {
772 if ((gargs = glob(cpp)) != NULL)
773 cpp = gargs;
774 if (globerr != NULL) {
775 printf("%s\n", globerr);
776 exit(1);
777 }
778 }
779 if (debug) {
780 register char **zip = cpp;
781
782 printf("%s", *zip);
783 while (*++zip != NULL)
784 printf(" %s", *zip);
785 printf("\n");
786 fflush(stdout);
787 }
788 execvp(argv[1], cpp);
789 perror(argv[1]);
790 exit(1);
791 }
792 if (pid > 0)
793 while (wait(&status) != pid)
794 ;
795 signal(SIGINT, old1);
796 signal(SIGQUIT, old2);
797 if (pid == -1)
798 perror("Try again later");
799 return (0);
59d0d309
SL
800}
801
802/*
803 * Send new user information (re-login)
804 */
805user(argc, argv)
806 int argc;
807 char **argv;
808{
809 char acct[80], *getpass();
810 int n;
811
812 if (argc < 2) {
813 strcat(line, " ");
814 printf("(username) ");
815 gets(&line[strlen(line)]);
816 makeargv();
817 argc = margc;
818 argv = margv;
819 }
820 if (argc > 4) {
821 printf("usage: %s username [password] [account]\n", argv[0]);
9072bd8a 822 return (0);
59d0d309
SL
823 }
824 n = command("USER %s", argv[1]);
825 if (n == CONTINUE) {
826 if (argc < 3 )
827 argv[2] = getpass("Password: "), argc++;
828 n = command("PASS %s", argv[2]);
829 }
830 if (n == CONTINUE) {
831 if (argc < 4) {
832 printf("Account: "); (void) fflush(stdout);
833 (void) fgets(acct, sizeof(acct) - 1, stdin);
834 acct[strlen(acct) - 1] = '\0';
835 argv[3] = acct; argc++;
836 }
837 n = command("ACCT %s", acct);
838 }
839 if (n != COMPLETE) {
840 fprintf(stderr, "Login failed.\n");
841 return (0);
842 }
843 return (1);
844}
845
846/*
847 * Print working directory.
848 */
849/*VARARGS*/
850pwd()
851{
9072bd8a 852
59d0d309
SL
853 (void) command("XPWD");
854}
855
856/*
857 * Make a directory.
858 */
859makedir(argc, argv)
860 char *argv[];
861{
862
863 if (argc < 2) {
864 strcat(line, " ");
865 printf("(directory-name) ");
866 gets(&line[strlen(line)]);
867 makeargv();
868 argc = margc;
869 argv = margv;
870 }
871 if (argc < 2) {
872 printf("%s directory-name\n", argv[0]);
873 return;
874 }
875 (void) command("XMKD %s", argv[1]);
876}
877
878/*
879 * Remove a directory.
880 */
881removedir(argc, argv)
882 char *argv[];
883{
884
885 if (argc < 2) {
886 strcat(line, " ");
887 printf("(directory-name) ");
888 gets(&line[strlen(line)]);
889 makeargv();
890 argc = margc;
891 argv = margv;
892 }
893 if (argc < 2) {
894 printf("%s directory-name\n", argv[0]);
895 return;
896 }
897 (void) command("XRMD %s", argv[1]);
898}
899
900/*
901 * Send a line, verbatim, to the remote machine.
902 */
903quote(argc, argv)
904 char *argv[];
905{
906 int i;
907 char buf[BUFSIZ];
908
909 if (argc < 2) {
910 strcat(line, " ");
911 printf("(command line to send) ");
912 gets(&line[strlen(line)]);
913 makeargv();
914 argc = margc;
915 argv = margv;
916 }
917 if (argc < 2) {
918 printf("usage: %s line-to-send\n", argv[0]);
919 return;
920 }
921 strcpy(buf, argv[1]);
922 for (i = 2; i < argc; i++) {
923 strcat(buf, " ");
924 strcat(buf, argv[i]);
925 }
926 (void) command(buf);
927}
928
929/*
930 * Ask the other side for help.
931 */
932rmthelp(argc, argv)
933 char *argv[];
934{
935 int oldverbose = verbose;
936
937 verbose = 1;
938 (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
939 verbose = oldverbose;
940}
941
942/*
943 * Terminate session and exit.
944 */
945/*VARARGS*/
946quit()
947{
948
949 disconnect();
950 exit(0);
951}
952
953/*
954 * Terminate session, but don't exit.
955 */
956disconnect()
957{
958 extern FILE *cout;
959 extern int data;
960
961 if (!connected)
962 return;
963 (void) command("QUIT");
964 (void) fclose(cout);
965 cout = NULL;
966 connected = 0;
967 data = -1;
968}
cf8133c7 969
5ac6fc46 970confirm(cmd, file)
cf8133c7
SL
971 char *cmd, *file;
972{
973 char line[BUFSIZ];
974
975 if (!interactive)
5ac6fc46 976 return (1);
cf8133c7
SL
977 printf("%s %s? ", cmd, file);
978 fflush(stdout);
979 gets(line);
5ac6fc46 980 return (*line != 'n' && *line != 'N');
cf8133c7
SL
981}
982
983fatal(msg)
984 char *msg;
985{
986
987 fprintf(stderr, "ftp: %s\n");
988 exit(1);
989}
990
991/*
992 * Glob a local file name specification with
993 * the expectation of a single return value.
994 * Can't control multiple values being expanded
995 * from the expression, we return only the first.
996 */
997globulize(cpp)
998 char **cpp;
999{
1000 char **globbed;
1001
1002 if (!doglob)
1003 return (1);
1004 globbed = glob(*cpp);
1005 if (globerr != NULL) {
1006 printf("%s: %s\n", *cpp, globerr);
1007 if (globbed)
1008 blkfree(globbed);
1009 return (0);
1010 }
1011 if (globbed) {
1012 *cpp = *globbed++;
1013 /* don't waste too much memory */
1014 if (*globbed)
1015 blkfree(globbed);
1016 }
1017 return (1);
1018}