2 * Copyright (c) 1985, 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * FTP User Program -- Command Interface.
44 static int version_flag
;
45 static int debug_flag
;
47 struct getargs getargs
[] = {
48 { NULL
, 'd', arg_flag
, &debug_flag
,
50 { NULL
, 'g', arg_negative_flag
, &doglob
,
51 "disables globbing", NULL
},
52 { NULL
, 'i', arg_negative_flag
, &interactive
,
53 "Turn off interactive prompting", NULL
},
54 { NULL
, 'l', arg_negative_flag
, &lineedit
,
55 "Turn off line editing", NULL
},
56 { NULL
, 'n', arg_negative_flag
, &autologin
,
57 "Turn off auto-login", NULL
},
58 { NULL
, 'p', arg_flag
, &passivemode
,
59 "passive mode", NULL
},
60 { NULL
, 't', arg_counter
, &trace
,
61 "Packet tracing", NULL
},
63 { "gss-bindings", 0, arg_negative_flag
, &ftp_do_gss_bindings
,
64 "Don't use GSS-API bindings", NULL
},
65 { "gss-delegate", 0, arg_negative_flag
, &ftp_do_gss_delegate
,
66 "Disable delegation of GSS-API credentials", NULL
},
68 { NULL
, 'v', arg_counter
, &verbose
,
70 { NULL
, 'K', arg_negative_flag
, &use_kerberos
,
71 "Disable kerberos authentication", NULL
},
72 { "encrypt", 'x', arg_flag
, &doencrypt
,
73 "Encrypt command and data channel if possible" },
74 { "version", 0, arg_flag
, &version_flag
},
75 { "help", 'h', arg_flag
, &help_flag
},
78 static int num_args
= sizeof(getargs
) / sizeof(getargs
[0]);
83 arg_printusage(getargs
, num_args
, NULL
, "[host [port]]");
88 main(int argc
, char **argv
)
91 struct passwd
*pw
= NULL
;
92 char homedir
[MaxPathLen
];
98 sp
= getservbyname("ftp", "tcp");
100 errx(1, "ftp/tcp: unknown service");
105 passivemode
= 0; /* passive mode not active */
108 ftp_do_gss_bindings
= 1;
111 if(getarg(getargs
, num_args
, argc
, argv
, &optind
))
128 fromatty
= isatty(fileno(stdin
));
131 cpend
= 0; /* no pending replies */
132 proxy
= 0; /* proxy not active */
133 crflag
= 1; /* strip c.r. on ascii gets */
134 sendport
= -1; /* not using ports */
136 * Set up the home directory in case we're globbing.
138 pw
= k_getpwuid(getuid());
140 strlcpy(homedir
, pw
->pw_dir
, sizeof(homedir
));
146 if (setjmp(toplevel
))
148 signal(SIGINT
, intr
);
149 signal(SIGPIPE
, lostpeer
);
150 xargv
[0] = (char*)getprogname();
155 setpeer(argc
+1, xargv
);
157 if(setjmp(toplevel
) == 0)
162 signal(SIGINT
, intr
);
163 signal(SIGPIPE
, lostpeer
);
175 longjmp(toplevel
, 1);
188 shutdown(fileno(cout
), SHUT_RDWR
);
193 shutdown(data
, SHUT_RDWR
);
202 shutdown(fileno(cout
), SHUT_RDWR
);
222 s = strrchr(filename, '/');
234 simple_readline(char *prompt
)
237 printf ("%s", prompt
);
239 if(fgets(buf
, sizeof(buf
), stdin
) == NULL
)
241 if (buf
[strlen(buf
) - 1] == '\n')
242 buf
[strlen(buf
) - 1] = '\0';
246 #ifndef HAVE_READLINE
249 readline(char *prompt
)
251 return simple_readline (prompt
);
261 /* These should not really be here */
263 char *readline(char *);
264 void add_history(char *);
283 p
= readline("ftp> ");
285 p
= simple_readline("ftp> ");
290 strlcpy(line
, p
, sizeof(line
));
295 if (fgets(line
, sizeof line
, stdin
) == NULL
)
298 /* XXX will break on long lines */
302 if (line
[--l
] == '\n') {
306 } else if (l
== sizeof(line
) - 2) {
307 printf("sorry, input line too long\n");
308 while ((l
= getchar()) != '\n' && l
!= EOF
)
311 } /* else it was a line without a newline */
316 c
= getcmd(margv
[0]);
317 if (c
== (struct cmd
*)-1) {
318 printf("?Ambiguous command\n");
322 printf("?Invalid command\n");
325 if (c
->c_conn
&& !connected
) {
326 printf("Not connected.\n");
329 (*c
->c_handler
)(margc
, margv
);
330 if (bell
&& c
->c_bell
)
332 if (c
->c_handler
!= help
)
335 signal(SIGINT
, intr
);
336 signal(SIGPIPE
, lostpeer
);
343 struct cmd
*c
, *found
;
344 int nmatches
, longest
;
349 for (c
= cmdtab
; (p
= c
->c_name
); c
++) {
350 for (q
= name
; *q
== *p
++; q
++)
351 if (*q
== 0) /* exact match? */
353 if (!*q
) { /* the name was a prefix */
354 if (q
- name
> longest
) {
358 } else if (q
- name
== longest
)
363 return ((struct cmd
*)-1);
368 * Slice a string up into argc/argv.
379 stringbase
= line
; /* scan from first of buffer */
380 argbase
= argbuf
; /* store from first of buffer */
382 for (margc
= 0; ; margc
++) {
383 /* Expand array if necessary */
384 if (margc
== margvlen
) {
387 margv
= (margvlen
== 0)
388 ? (char **)malloc(20 * sizeof(char *))
389 : (char **)realloc(margv
,
390 (margvlen
+ 20)*sizeof(char *));
392 errx(1, "cannot realloc argv array");
393 for(i
= margvlen
; i
< margvlen
+ 20; ++i
)
396 argp
= margv
+ margc
;
399 if ((*argp
++ = slurpstring()) == NULL
)
406 * Parse string into argbuf;
407 * implemented with FSM to
408 * handle quoting and strings
414 char *sb
= stringbase
;
416 char *tmp
= argbase
; /* will return this if token found */
418 if (*sb
== '!' || *sb
== '$') { /* recognize ! as a token for shell */
419 switch (slrflag
) { /* and $ as token for macro invoke */
423 return ((*sb
== '!') ? "!" : "$");
465 goto OUT
; /* end of token */
468 sb
++; goto S2
; /* slurp next character */
471 sb
++; goto S3
; /* slurp quoted string */
474 *ap
++ = *sb
++; /* add character to token */
509 argbase
= ap
; /* update storage pointer */
510 stringbase
= sb
; /* update scan pointer */
528 #define HELPINDENT ((int) sizeof ("directory"))
532 * Call each command handler with argc == 0 and argv[0] == name.
535 help(int argc
, char **argv
)
541 int columns
, width
= 0, lines
;
543 printf("Commands may be abbreviated. Commands are:\n\n");
544 for (c
= cmdtab
; c
< &cmdtab
[NCMDS
]; c
++) {
545 int len
= strlen(c
->c_name
);
550 width
= (width
+ 8) &~ 7;
551 columns
= 80 / width
;
554 lines
= (NCMDS
+ columns
- 1) / columns
;
555 for (i
= 0; i
< lines
; i
++) {
556 for (j
= 0; j
< columns
; j
++) {
557 c
= cmdtab
+ j
* lines
+ i
;
558 if ((!proxy
|| c
->c_proxy
)) {
559 printf("%s", c
->c_name
);
561 for (k
=0; k
< strlen(c
->c_name
); k
++) {
565 if (c
+ lines
>= &cmdtab
[NCMDS
]) {
569 w
= strlen(c
->c_name
);
582 if (c
== (struct cmd
*)-1)
583 printf("?Ambiguous help command %s\n", arg
);
584 else if (c
== (struct cmd
*)0)
585 printf("?Invalid help command %s\n", arg
);
587 printf("%-*s\t%s\n", HELPINDENT
,
588 c
->c_name
, c
->c_help
);