2 * Copyright (c) 1985, 1989 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 "@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\
21 All rights reserved.\n";
25 static char sccsid
[] = "@(#)main.c based on 5.13 (Berkeley) 3/14/89";
29 * FTP User Program -- Command Interface.
33 #include <sys/socket.h>
34 #include <sys/ioctl.h>
40 #include "prototypes.h"
41 #include <sys/types.h>
52 #if defined(sun) && !defined(FD_SET)
69 /* Lot's of options... */
71 * Options and other state info.
73 int trace
; /* trace packets exchanged */
74 int hash
; /* print # for each buffer transferred */
75 //int sendport; /* use PORT cmd for each data connection */
76 int verbose
; /* print messages coming back from server */
77 int connected
; /* connected to server */
78 int fromatty
; /* input is from a terminal */
79 int interactive
; /* interactively prompt on m* cmds */
80 int debug
; /* debugging level */
81 int bell
; /* ring bell on cmd completion */
82 int doglob
; /* glob local file names */
83 int proxy
; /* proxy server connection active */
85 int proxflag
; /* proxy connection exists */
86 int sunique
; /* store files on server with unique name */
87 int runique
; /* store local files with unique name */
88 int mcase
; /* map upper to lower case for mget names */
89 int ntflag
; /* use ntin ntout tables for name translation */
90 int mapflag
; /* use mapin mapout templates on file names */
91 int code
; /* return/reply code for ftp command */
92 int crflag
; /* if 1, strip car. rets. on ascii gets */
93 char pasv
[64]; /* passive port for proxy data connection */
94 char *altarg
; /* argv[1] with no shell-like preprocessing */
95 char ntin
[17]; /* input translation table */
96 char ntout
[17]; /* output translation table */
97 // #include <sys/param.h>
98 char mapin
[MAXPATHLEN
]; /* input map template */
99 char mapout
[MAXPATHLEN
]; /* output map template */
100 char typename
[32]; /* name of file transfer type */
101 int type
; /* file transfer type */
102 char structname
[32]; /* name of file transfer structure */
103 int stru
; /* file transfer structure */
104 char formname
[32]; /* name of file transfer format */
105 int form
; /* file transfer format */
106 char modename
[32]; /* name of file transfer mode */
107 int mode
; /* file transfer mode */
108 char bytename
[32]; /* local byte size in ascii */
109 int bytesize
; /* local byte size in binary */
111 jmp_buf toplevel
; /* non-local goto stuff for cmd scanner */
113 char line
[200]; /* input line buffer */
114 char *stringbase
; /* current scan point in line buffer */
115 char argbuf
[200]; /* argument storage buffer */
116 char *argbase
; /* current storage point in arg buffer */
117 int margc
; /* count of arguments on input line */
118 const char *margv
[20]; /* args parsed from input line */
119 int cpend
; /* flag: if != 0, then pending server reply */
120 int mflag
; /* flag: if != 0, then active multi command */
122 int options
; /* used during socket creation */
124 int macnum
; /* number of defined macros */
125 struct macel macros
[16];
129 * Need to start a listen on the data channel
130 * before we send the command, otherwise the
131 * server's connect may fail.
135 static const char *slurpstring();
138 int main(int argc
, const char *argv
[])
143 char homedir
[MAXPATHLEN
];
150 struct servent
*sp
; /* service spec for tcp/ftp */
152 /* Disable output buffering, for the benefit of Emacs. */
153 //setbuf(stdout, NULL);
155 _fmode
= O_BINARY
; // This causes an error somewhere.
157 wVerReq
= MAKEWORD(1,1);
159 err
= WSAStartup(wVerReq
, &WSAData
);
162 fprintf(stderr
, "Could not initialize Windows socket interface.");
166 sp
= getservbyname("ftp", "tcp");
168 fprintf(stderr
, "ftp: ftp/tcp: unknown service\n");
172 portnum
= sp
->s_port
;
179 while (argc
> 0 && **argv
== '-') {
180 for (cp
= *argv
+ 1; *cp
; cp
++)
210 "ftp: %c: unknown option\n", *cp
);
215 // fromatty = isatty(fileno(stdin));
216 fromatty
= 1; // Strengthen this test
218 * Set up defaults for FTP.
220 (void) strcpy(typename
, "ascii"), type
= TYPE_A
;
221 (void) strcpy(formname
, "non-print"), form
= FORM_N
;
222 (void) strcpy(modename
, "stream"), mode
= MODE_S
;
223 (void) strcpy(structname
, "file"), stru
= STRU_F
;
224 (void) strcpy(bytename
, "8"), bytesize
= 8;
227 cpend
= 0; /* no pending replies */
228 proxy
= 0; /* proxy not active */
229 passivemode
= 1; /* passive mode *is* active */
230 crflag
= 1; /* strip c.r. on ascii gets */
232 * Set up the home directory in case we're globbing.
240 pw
= getpwuid(getuid());
243 (void) strcpy(home
, pw
->pw_dir
);
248 if (setjmp(toplevel
))
250 // (void) signal(SIGINT, intr);
251 // (void) signal(SIGPIPE, lostpeer);
252 setpeer(argc
+ 1, argv
- 1);
254 top
= setjmp(toplevel
) == 0;
256 // (void) signal(SIGINT, intr);
257 // (void) signal(SIGPIPE, lostpeer);
267 longjmp(toplevel
, 1);
281 (void) shutdown(data
, 1+1);
305 s = rindex(filename, '/');
318 void cmdscanner(int top
)
320 register struct cmd
*c
;
323 (void) putchar('\n');
325 (void) fflush(stdout
);
328 (void) fflush(stdout
);
330 if (gets(line
) == 0) {
331 if (feof(stdin
) || ferror(stdin
))
341 c
= getcmd(margv
[0]);
342 if (c
== (struct cmd
*)-1) {
343 printf("?Ambiguous command\n");
347 printf("?Invalid command\n");
350 if (c
->c_conn
&& !connected
) {
351 printf ("Not connected.\n");
354 (*c
->c_handler
)(margc
, margv
);
355 if (bell
&& c
->c_bell
)
356 (void) putchar('\007');
357 if (c
->c_handler
!= help
)
360 (void) fflush(stdout
);
361 // (void) signal(SIGINT, intr);
362 // (void) signal(SIGPIPE, lostpeer);
366 getcmd(const char *name
)
368 extern struct cmd cmdtab
[];
370 struct cmd
*c
, *found
;
371 int nmatches
, longest
;
376 for (c
= cmdtab
; (p
= c
->c_name
); c
++) {
377 for (q
= name
; *q
== *p
++; q
++)
378 if (*q
== 0) /* exact match? */
380 if (!*q
) { /* the name was a prefix */
381 if (q
- name
> longest
) {
385 } else if (q
- name
== longest
)
390 return ((struct cmd
*)-1);
395 * Slice a string up into argc/argv.
406 stringbase
= line
; /* scan from first of buffer */
407 argbase
= argbuf
; /* store from first of buffer */
409 while ((*argp
++ = slurpstring()))
414 * Parse string into argbuf;
415 * implemented with FSM to
416 * handle quoting and strings
422 register char *sb
= stringbase
;
423 register char *ap
= argbase
;
424 char *tmp
= argbase
; /* will return this if token found */
426 if (*sb
== '!' || *sb
== '$') { /* recognize ! as a token for shell */
427 switch (slrflag
) { /* and $ as token for macro invoke */
431 return ((*sb
== '!') ? "!" : "$");
473 goto OUT1
; /* end of token */
476 sb
++; goto S2
; /* slurp next character */
479 sb
++; goto S3
; /* slurp quoted string */
482 *ap
++ = *sb
++; /* add character to token */
517 argbase
= ap
; /* update storage pointer */
518 stringbase
= sb
; /* update scan pointer */
536 #define HELPINDENT (sizeof ("directory"))
540 * Call each command handler with argc == 0 and argv[0] == name.
542 void help(int argc
, const char *argv
[])
544 extern struct cmd cmdtab
[];
548 register int i
, j
, w
, k
;
549 int columns
, width
= 0, lines
;
552 printf("Commands may be abbreviated. Commands are:\n\n");
553 for (c
= cmdtab
; c
< &cmdtab
[NCMDS
]; c
++) {
554 int len
= strlen(c
->c_name
);
559 width
= (width
+ 8) &~ 7;
560 columns
= 80 / width
;
563 lines
= (NCMDS
+ columns
- 1) / columns
;
564 for (i
= 0; i
< lines
; i
++) {
565 for (j
= 0; j
< columns
; j
++) {
566 c
= cmdtab
+ j
* lines
+ i
;
567 if (c
->c_name
&& (!proxy
|| c
->c_proxy
)) {
568 printf("%s", c
->c_name
);
570 else if (c
->c_name
) {
571 for (k
=0; k
< (int) strlen(c
->c_name
); k
++) {
575 if (c
+ lines
>= &cmdtab
[NCMDS
]) {
579 w
= strlen(c
->c_name
);
582 (void) putchar('\t');
586 (void) fflush(stdout
);
593 if (c
== (struct cmd
*)-1)
594 printf("?Ambiguous help command %s\n", arg
);
595 else if (c
== (struct cmd
*)0)
596 printf("?Invalid help command %s\n", arg
);
598 printf("%-*s\t%s\n", (int)HELPINDENT
,
599 c
->c_name
, c
->c_help
);
601 (void) fflush(stdout
);