1 /* $FreeBSD: src/usr.bin/ftp/main.c,v 1.25.2.4 2002/08/27 09:55:08 yar Exp $ */
2 /* $DragonFly: src/usr.bin/ftp/Attic/main.c,v 1.2 2003/06/17 04:29:26 dillon Exp $ */
3 /* $NetBSD: main.c,v 1.26 1997/10/14 16:31:22 christos Exp $ */
6 * Copyright (c) 1985, 1989, 1993, 1994
7 * The Regents of the University of California. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * @(#) Copyright (c) 1985, 1989, 1993, 1994 \tThe Regents of the University of California. All rights reserved.
38 * @(#)main.c 8.6 (Berkeley) 10/9/94
39 * $NetBSD: main.c,v 1.26 1997/10/14 16:31:22 christos Exp $
40 * $FreeBSD: src/usr.bin/ftp/main.c,v 1.25.2.4 2002/08/27 09:55:08 yar Exp $
43 #include <sys/cdefs.h>
46 * FTP User Program -- Command Interface.
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
64 #include "pathnames.h"
66 int family = AF_UNSPEC;
68 int main __P((int, char **));
76 struct passwd *pw = NULL;
77 char *cp, homedir[MAXPATHLEN], *s;
79 char *src_addr = NULL;
81 (void) setlocale(LC_ALL, "");
86 cp = getenv("FTPSERVERPORT");
88 asprintf(&gateport, "%s", cp);
90 asprintf(&gateport, "ftpgate");
96 try_epsv = epsv4; /* so status w/o connection isn't bogus */
97 restricted_data_ports = 1;
109 if ((tmpdir = getenv("TMPDIR")) == NULL)
112 cp = strrchr(argv[0], '/');
113 cp = (cp == NULL) ? argv[0] : cp + 1;
114 if ((s = getenv("FTP_PASSIVE_MODE")) != NULL
115 && strcasecmp(s, "no") != 0)
117 if (strcmp(cp, "pftp") == 0)
119 else if (strcmp(cp, "gate-ftp") == 0)
122 gateserver = getenv("FTPSERVER");
123 if (gateserver == NULL || *gateserver == '\0')
124 gateserver = GATE_SERVER;
126 if (*gateserver == '\0') {
128 "Neither $FTPSERVER nor GATE_SERVER is defined; disabling gate-ftp");
134 if (cp == NULL || strcmp(cp, "dumb") == 0)
138 fromatty = isatty(fileno(stdin));
140 verbose = 1; /* verbose if from a tty */
143 editing = 1; /* editing mode on if tty is usable */
146 if (isatty(fileno(stdout)) && !dumbterm)
147 progress = 1; /* progress bar on if tty is usable */
149 while ((ch = getopt(argc, argv, "46adeginpP:s:tUvV")) != -1) {
204 restricted_data_ports = 0;
222 cpend = 0; /* no pending replies */
223 proxy = 0; /* proxy not active */
224 crflag = 1; /* strip c.r. on ascii gets */
225 sendport = -1; /* not using ports */
228 struct addrinfo hints;
229 struct addrinfo *res;
232 memset(&hints, 0, sizeof(hints));
233 hints.ai_family = family;
234 hints.ai_socktype = SOCK_STREAM;
235 error = getaddrinfo(src_addr, NULL, &hints, &res);
237 warnx("%s: %s", src_addr, gai_strerror(error));
238 if (error == EAI_SYSTEM)
239 warnx("%s", strerror(errno));
246 * Set up the home directory in case we're globbing.
253 pw = getpwuid(getuid());
256 (void)strcpy(home, pw->pw_dir);
260 (void)signal(SIGWINCH, setttywidth);
262 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
268 if (strchr(argv[0], ':') != NULL && ! isipv6addr(argv[0])) {
269 anonftp = 1; /* Handle "automatic" transfers. */
270 rval = auto_fetch(argc, argv);
271 if (rval >= 0) /* -1 == connected and cd-ed */
274 char *xargv[4], **xargp = xargv;
276 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
279 if (setjmp(toplevel))
281 (void)signal(SIGINT, (sig_t)intr);
282 (void)signal(SIGPIPE, (sig_t)lostpeer);
283 *xargp++ = __progname;
284 *xargp++ = argv[0]; /* host */
286 *xargp++ = argv[1]; /* port */
288 setpeer(xargp-xargv, xargv);
294 top = setjmp(toplevel) == 0;
296 (void)signal(SIGINT, (sig_t)intr);
297 (void)signal(SIGPIPE, (sig_t)lostpeer);
310 longjmp(toplevel, 1);
320 (void)shutdown(fileno(cout), 1+1);
325 (void)shutdown(data, 1+1);
334 (void)shutdown(fileno(cout), 1+1);
374 fputs(prompt(), stdout);
375 (void)fflush(stdout);
377 if (fgets(line, sizeof(line), stdin) == NULL)
382 if (line[--num] == '\n') {
386 } else if (num == sizeof(line) - 2) {
387 puts("sorry, input line too long.");
388 while ((num = getchar()) != '\n' && num != EOF)
391 } /* else it was a line without a newline */
397 if ((buf = el_gets(el, &num)) == NULL || num == 0)
399 if (buf[--num] == '\n') {
402 } else if (num >= sizeof(line)) {
403 puts("sorry, input line too long.");
406 memcpy(line, buf, num);
408 history(hist, H_ENTER, buf);
415 #if 0 && !defined(SMALL) /* XXX: don't want el_parse */
417 * el_parse returns -1 to signal that it's not been handled
420 if (el_parse(el, margc, margv) != -1)
423 c = getcmd(margv[0]);
424 if (c == (struct cmd *)-1) {
425 puts("?Ambiguous command.");
429 puts("?Invalid command.");
432 if (c->c_conn && !connected) {
433 puts("Not connected.");
437 (*c->c_handler)(margc, margv);
438 if (bell && c->c_bell)
439 (void)putchar('\007');
440 if (c->c_handler != help)
443 (void)signal(SIGINT, (sig_t)intr);
444 (void)signal(SIGPIPE, (sig_t)lostpeer);
452 struct cmd *c, *found;
453 int nmatches, longest;
461 for (c = cmdtab; (p = c->c_name) != NULL; c++) {
462 for (q = name; *q == *p++; q++)
463 if (*q == 0) /* exact match? */
465 if (!*q) { /* the name was a prefix */
466 if (q - name > longest) {
470 } else if (q - name == longest)
475 return ((struct cmd *)-1);
480 * Slice a string up into argc/argv.
490 stringbase = line; /* scan from first of buffer */
491 argbase = argbuf; /* store from first of buffer */
493 marg_sl->sl_cur = 0; /* reset to start of marg_sl */
494 for (margc = 0; ; margc++) {
495 argp = slurpstring();
496 sl_add(marg_sl, argp);
501 if (cursor_pos == line) {
504 } else if (cursor_pos != NULL) {
506 cursor_argo = strlen(margv[margc-1]);
512 #define INC_CHKCURSOR(x) (x)++
514 #define INC_CHKCURSOR(x) { (x)++ ; \
515 if (x == cursor_pos) { \
516 cursor_argc = margc; \
517 cursor_argo = ap-argbase; \
524 * Parse string into argbuf;
525 * implemented with FSM to
526 * handle quoting and strings
532 char *sb = stringbase;
534 char *tmp = argbase; /* will return this if token found */
536 if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */
537 switch (slrflag) { /* and $ as token for macro invoke */
540 INC_CHKCURSOR(stringbase);
541 return ((*sb == '!') ? "!" : "$");
584 goto OUT; /* end of token */
588 goto S2; /* slurp next character */
592 goto S3; /* slurp quoted string */
595 *ap = *sb; /* add character to token */
637 argbase = ap; /* update storage pointer */
638 stringbase = sb; /* update scan pointer */
658 * Call each command handler with argc == 0 and argv[0] == name.
671 printf("%sommands may be abbreviated. Commands are:\n\n",
672 proxy ? "Proxy c" : "C");
673 for (c = cmdtab; c < &cmdtab[NCMDS]; c++)
674 if (c->c_name && (!proxy || c->c_proxy))
675 sl_add(buf, c->c_name);
681 #define HELPINDENT ((int) sizeof("disconnect"))
688 if (c == (struct cmd *)-1)
689 printf("?Ambiguous help command %s\n", arg);
690 else if (c == (struct cmd *)0)
691 printf("?Invalid help command %s\n", arg);
693 printf("%-*s\t%s\n", HELPINDENT,
694 c->c_name, c->c_help);
701 (void)fprintf(stderr,
702 "usage: %s [-46adeginptUvV] [-P port] [-s src_addr] [host [port]]\n"
704 " %s ftp://host[:port]/path[/]\n"
705 " %s http://host[:port]/file\n",
706 __progname, __progname, __progname, __progname);