remove gcc34
[dragonfly.git] / crypto / heimdal-0.6.3 / appl / ftp / ftp / main.c
blob071f60127daef84b7f5720b9c2e4ee22f4194394
1 /*
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
7 * are met:
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
31 * SUCH DAMAGE.
35 * FTP User Program -- Command Interface.
38 #include "ftp_locl.h"
39 #include <getarg.h>
41 RCSID("$Id: main.c,v 1.33.2.1 2003/08/20 16:43:14 lha Exp $");
43 static int help_flag;
44 static int version_flag;
45 static int debug_flag;
47 struct getargs getargs[] = {
48 { NULL, 'd', arg_flag, &debug_flag,
49 "debug", NULL },
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},
62 #ifdef KRB5
63 { "gss-bindings", 0, arg_negative_flag, &ftp_do_gss_bindings,
64 "Use GSS-API bindings", NULL},
65 #endif
66 { NULL, 'v', arg_counter, &verbose,
67 "verbosity", NULL},
68 { NULL, 'K', arg_negative_flag, &use_kerberos,
69 "Disable kerberos authentication", NULL},
70 { "version", 0, arg_flag, &version_flag },
71 { "help", 'h', arg_flag, &help_flag },
74 static int num_args = sizeof(getargs) / sizeof(getargs[0]);
76 static void
77 usage(int ecode)
79 arg_printusage(getargs, num_args, NULL, "[host [port]]");
80 exit(ecode);
83 int
84 main(int argc, char **argv)
86 int top;
87 struct passwd *pw = NULL;
88 char homedir[MaxPathLen];
89 struct servent *sp;
90 int optind = 0;
92 setprogname(argv[0]);
94 sp = getservbyname("ftp", "tcp");
95 if (sp == 0)
96 errx(1, "ftp/tcp: unknown service");
97 doglob = 1;
98 interactive = 1;
99 autologin = 1;
100 lineedit = 1;
101 passivemode = 0; /* passive mode not active */
102 use_kerberos = 1;
103 #ifdef KRB5
104 ftp_do_gss_bindings = 1;
105 #endif
107 if(getarg(getargs, num_args, argc, argv, &optind))
108 usage(1);
109 if(help_flag)
110 usage(0);
111 if(version_flag) {
112 print_version(NULL);
113 exit(0);
116 if (debug_flag) {
117 options |= SO_DEBUG;
118 debug++;
121 argc -= optind;
122 argv += optind;
124 fromatty = isatty(fileno(stdin));
125 if (fromatty)
126 verbose++;
127 cpend = 0; /* no pending replies */
128 proxy = 0; /* proxy not active */
129 crflag = 1; /* strip c.r. on ascii gets */
130 sendport = -1; /* not using ports */
132 * Set up the home directory in case we're globbing.
134 pw = k_getpwuid(getuid());
135 if (pw != NULL) {
136 strlcpy(homedir, pw->pw_dir, sizeof(homedir));
137 home = homedir;
139 if (argc > 0) {
140 char *xargv[5];
142 if (setjmp(toplevel))
143 exit(0);
144 signal(SIGINT, intr);
145 signal(SIGPIPE, lostpeer);
146 xargv[0] = (char*)getprogname();
147 xargv[1] = argv[0];
148 xargv[2] = argv[1];
149 xargv[3] = argv[2];
150 xargv[4] = NULL;
151 setpeer(argc+1, xargv);
153 if(setjmp(toplevel) == 0)
154 top = 1;
155 else
156 top = 0;
157 if (top) {
158 signal(SIGINT, intr);
159 signal(SIGPIPE, lostpeer);
161 for (;;) {
162 cmdscanner(top);
163 top = 1;
167 void
168 intr(int sig)
171 longjmp(toplevel, 1);
174 #ifndef SHUT_RDWR
175 #define SHUT_RDWR 2
176 #endif
178 RETSIGTYPE
179 lostpeer(int sig)
182 if (connected) {
183 if (cout != NULL) {
184 shutdown(fileno(cout), SHUT_RDWR);
185 fclose(cout);
186 cout = NULL;
188 if (data >= 0) {
189 shutdown(data, SHUT_RDWR);
190 close(data);
191 data = -1;
193 connected = 0;
195 pswitch(1);
196 if (connected) {
197 if (cout != NULL) {
198 shutdown(fileno(cout), SHUT_RDWR);
199 fclose(cout);
200 cout = NULL;
202 connected = 0;
204 proxflag = 0;
205 pswitch(0);
206 sec_end();
207 SIGRETURN(0);
211 char *
212 tail(filename)
213 char *filename;
215 char *s;
217 while (*filename) {
218 s = strrchr(filename, '/');
219 if (s == NULL)
220 break;
221 if (s[1])
222 return (s + 1);
223 *s = '\0';
225 return (filename);
229 static char *
230 simple_readline(char *prompt)
232 char buf[BUFSIZ];
233 printf ("%s", prompt);
234 fflush (stdout);
235 if(fgets(buf, sizeof(buf), stdin) == NULL)
236 return NULL;
237 if (buf[strlen(buf) - 1] == '\n')
238 buf[strlen(buf) - 1] = '\0';
239 return strdup(buf);
242 #ifndef HAVE_READLINE
244 static char *
245 readline(char *prompt)
247 return simple_readline (prompt);
250 static void
251 add_history(char *p)
255 #else
257 /* These should not really be here */
259 char *readline(char *);
260 void add_history(char *);
262 #endif
265 * Command parser.
267 void
268 cmdscanner(int top)
270 struct cmd *c;
271 int l;
273 if (!top)
274 putchar('\n');
275 for (;;) {
276 if (fromatty) {
277 char *p;
278 if (lineedit)
279 p = readline("ftp> ");
280 else
281 p = simple_readline("ftp> ");
282 if(p == NULL) {
283 printf("\n");
284 quit(0, 0);
286 strlcpy(line, p, sizeof(line));
287 if (lineedit)
288 add_history(p);
289 free(p);
290 } else{
291 if (fgets(line, sizeof line, stdin) == NULL)
292 quit(0, 0);
294 /* XXX will break on long lines */
295 l = strlen(line);
296 if (l == 0)
297 break;
298 if (line[--l] == '\n') {
299 if (l == 0)
300 break;
301 line[l] = '\0';
302 } else if (l == sizeof(line) - 2) {
303 printf("sorry, input line too long\n");
304 while ((l = getchar()) != '\n' && l != EOF)
305 /* void */;
306 break;
307 } /* else it was a line without a newline */
308 makeargv();
309 if (margc == 0) {
310 continue;
312 c = getcmd(margv[0]);
313 if (c == (struct cmd *)-1) {
314 printf("?Ambiguous command\n");
315 continue;
317 if (c == 0) {
318 printf("?Invalid command\n");
319 continue;
321 if (c->c_conn && !connected) {
322 printf("Not connected.\n");
323 continue;
325 (*c->c_handler)(margc, margv);
326 if (bell && c->c_bell)
327 putchar('\007');
328 if (c->c_handler != help)
329 break;
331 signal(SIGINT, intr);
332 signal(SIGPIPE, lostpeer);
335 struct cmd *
336 getcmd(char *name)
338 char *p, *q;
339 struct cmd *c, *found;
340 int nmatches, longest;
342 longest = 0;
343 nmatches = 0;
344 found = 0;
345 for (c = cmdtab; (p = c->c_name); c++) {
346 for (q = name; *q == *p++; q++)
347 if (*q == 0) /* exact match? */
348 return (c);
349 if (!*q) { /* the name was a prefix */
350 if (q - name > longest) {
351 longest = q - name;
352 nmatches = 1;
353 found = c;
354 } else if (q - name == longest)
355 nmatches++;
358 if (nmatches > 1)
359 return ((struct cmd *)-1);
360 return (found);
364 * Slice a string up into argc/argv.
367 int slrflag;
369 void
370 makeargv(void)
372 char **argp;
374 argp = margv;
375 stringbase = line; /* scan from first of buffer */
376 argbase = argbuf; /* store from first of buffer */
377 slrflag = 0;
378 for (margc = 0; ; margc++) {
379 /* Expand array if necessary */
380 if (margc == margvlen) {
381 int i;
383 margv = (margvlen == 0)
384 ? (char **)malloc(20 * sizeof(char *))
385 : (char **)realloc(margv,
386 (margvlen + 20)*sizeof(char *));
387 if (margv == NULL)
388 errx(1, "cannot realloc argv array");
389 for(i = margvlen; i < margvlen + 20; ++i)
390 margv[i] = NULL;
391 margvlen += 20;
392 argp = margv + margc;
395 if ((*argp++ = slurpstring()) == NULL)
396 break;
402 * Parse string into argbuf;
403 * implemented with FSM to
404 * handle quoting and strings
406 char *
407 slurpstring(void)
409 int got_one = 0;
410 char *sb = stringbase;
411 char *ap = argbase;
412 char *tmp = argbase; /* will return this if token found */
414 if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */
415 switch (slrflag) { /* and $ as token for macro invoke */
416 case 0:
417 slrflag++;
418 stringbase++;
419 return ((*sb == '!') ? "!" : "$");
420 /* NOTREACHED */
421 case 1:
422 slrflag++;
423 altarg = stringbase;
424 break;
425 default:
426 break;
431 switch (*sb) {
433 case '\0':
434 goto OUT;
436 case ' ':
437 case '\t':
438 sb++; goto S0;
440 default:
441 switch (slrflag) {
442 case 0:
443 slrflag++;
444 break;
445 case 1:
446 slrflag++;
447 altarg = sb;
448 break;
449 default:
450 break;
452 goto S1;
456 switch (*sb) {
458 case ' ':
459 case '\t':
460 case '\0':
461 goto OUT; /* end of token */
463 case '\\':
464 sb++; goto S2; /* slurp next character */
466 case '"':
467 sb++; goto S3; /* slurp quoted string */
469 default:
470 *ap++ = *sb++; /* add character to token */
471 got_one = 1;
472 goto S1;
476 switch (*sb) {
478 case '\0':
479 goto OUT;
481 default:
482 *ap++ = *sb++;
483 got_one = 1;
484 goto S1;
488 switch (*sb) {
490 case '\0':
491 goto OUT;
493 case '"':
494 sb++; goto S1;
496 default:
497 *ap++ = *sb++;
498 got_one = 1;
499 goto S3;
502 OUT:
503 if (got_one)
504 *ap++ = '\0';
505 argbase = ap; /* update storage pointer */
506 stringbase = sb; /* update scan pointer */
507 if (got_one) {
508 return (tmp);
510 switch (slrflag) {
511 case 0:
512 slrflag++;
513 break;
514 case 1:
515 slrflag++;
516 altarg = (char *) 0;
517 break;
518 default:
519 break;
521 return NULL;
524 #define HELPINDENT ((int) sizeof ("directory"))
527 * Help command.
528 * Call each command handler with argc == 0 and argv[0] == name.
530 void
531 help(int argc, char **argv)
533 struct cmd *c;
535 if (argc == 1) {
536 int i, j, w, k;
537 int columns, width = 0, lines;
539 printf("Commands may be abbreviated. Commands are:\n\n");
540 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
541 int len = strlen(c->c_name);
543 if (len > width)
544 width = len;
546 width = (width + 8) &~ 7;
547 columns = 80 / width;
548 if (columns == 0)
549 columns = 1;
550 lines = (NCMDS + columns - 1) / columns;
551 for (i = 0; i < lines; i++) {
552 for (j = 0; j < columns; j++) {
553 c = cmdtab + j * lines + i;
554 if (c->c_name && (!proxy || c->c_proxy)) {
555 printf("%s", c->c_name);
557 else if (c->c_name) {
558 for (k=0; k < strlen(c->c_name); k++) {
559 putchar(' ');
562 if (c + lines >= &cmdtab[NCMDS]) {
563 printf("\n");
564 break;
566 w = strlen(c->c_name);
567 while (w < width) {
568 w = (w + 8) &~ 7;
569 putchar('\t');
573 return;
575 while (--argc > 0) {
576 char *arg;
577 arg = *++argv;
578 c = getcmd(arg);
579 if (c == (struct cmd *)-1)
580 printf("?Ambiguous help command %s\n", arg);
581 else if (c == (struct cmd *)0)
582 printf("?Invalid help command %s\n", arg);
583 else
584 printf("%-*s\t%s\n", HELPINDENT,
585 c->c_name, c->c_help);