ftpsbr.c

来自「早期freebsd实现」· C语言 代码 · 共 626 行

C
626
字号
/* ftpsbr.c - simple FTP client library (why doesn't BSD have one?!?) */#ifndef	lintstatic char ident[] = "@(#)$Id: ftpsbr.c,v 1.13 1993/08/25 17:25:27 jromine Exp $";#endif#include "../h/mh.h"#include "../h/mhn.h"#ifdef	FTP#include <ctype.h>#ifdef SVR4#undef NULLVP          /* stdio.h */#endif#include <stdio.h>#include <arpa/ftp.h>#ifdef __STDC__#include <stdarg.h>#else#include <varargs.h>#endif#ifdef __STDC__static int	command(int arg1, ...);#elsestatic int	command();#endifstatic int  ftp_quit(), ftp_read(), initconn(),	    dataconn(), _command(), getreply();/*    DATA */#define	v_debug		debugsw#define	v_verbose	verboswstatic	int	ftp_fd = NOTOK;static	int	data_fd = NOTOK;static	int	v_noise;extern	int	v_debug;extern	int	v_verbose;/*  */#if	defined(SYS5) && defined(AUX)#define u_short ushort#define u_long  ulong#endif#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#if	defined(BIND) && !defined(h_addr)#define	h_addr	h_addr_list[0]#endif#define	inaddr_copy(hp,sin) \    bcopy ((hp) -> h_addr, (char *) &((sin) -> sin_addr), (hp) -> h_length)struct hostent *gethostbystring ();/*  */extern	int	errno;#ifndef	BSD44extern	int	sys_nerr;extern	char   *sys_errlist[];#endif#define	start_tcp_client(sock,priv) \    	socket (AF_INET, SOCK_STREAM, 0)#define	join_tcp_server(fd, sock) \    	connect ((fd), (struct sockaddr *) (sock), sizeof *(sock))/* ARGSUSED */static int  start_tcp_server (sock, backlog, opt1, opt2)struct sockaddr_in *sock;int	backlog,	opt1,	opt2;{    int	    eindex,	    sd;    if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK)	return NOTOK;    if (bind (sd, (struct sockaddr *) sock, sizeof *sock) == NOTOK) {	eindex = errno;	(void) close (sd);	errno = eindex;    }    else	(void) listen (sd, backlog);    return sd;}static	int	__len__;#define	join_tcp_client(fd,sock) \    	accept ((fd), (struct sockaddr *) (sock), \		(__len__ = sizeof *(sock), &__len__))#define	read_tcp_socket		read#define	write_tcp_socket	write#define	close_tcp_socket	close/*  */static void  _asprintf (bp, what, ap)	/* fmt, args, ... */register char *bp;char   *what;va_list	ap;{    register int    eindex;    char   *fmt;    eindex = errno;    *bp = '\0';    fmt = va_arg (ap, char *);    if (fmt) {#ifndef	VSPRINTF	struct _iobuf iob;#endif#ifndef	VSPRINTF#ifdef	pyr	bzero ((char *) &iob, sizeof iob);	iob._file = _NFILE;#endif	iob._flag = _IOWRT | _IOSTRG;#if	!defined(vax) && !defined(pyr) && !defined(sequent)	iob._ptr = (unsigned char *) bp;#else	iob._ptr = bp;#endif	iob._cnt = BUFSIZ;	_doprnt (fmt, ap, &iob);	(void) putc ('\0', &iob);#else	(void) vsprintf (bp, fmt, ap);#endif	bp += strlen (bp);    }    if (what) {	if (*what) {	    (void) sprintf (bp, " %s: ", what);	    bp += strlen (bp);	}	if (0 < eindex && eindex < sys_nerr)	    (void) strcpy (bp, sys_errlist[eindex]);	else	    (void) sprintf (bp, "Error %d", eindex);	bp += strlen (bp);    }    errno = eindex;}/*  */int	ftp_get (host, user, password, cwd, remote, local, ascii, stayopen)char   *host,       *user,       *password,       *cwd,       *remote,       *local;int	ascii,	stayopen;{    return ftp_trans (host, user, password, cwd, remote, local, "RETR", ascii,		      stayopen);}/*  */int	ftp_trans (host, user, password, cwd, remote, local, cmd, ascii,		   stayopen)char   *host,       *user,       *password,       *cwd,       *remote,       *local,       *cmd;int	ascii,	stayopen;{    int	    result;    if (stayopen <= 0) {	result = ftp_quit ();	if (host == NULL)	    return result;    }    if (ftp_fd == NOTOK) {	struct sockaddr_in in_socket;	register struct hostent *hp;	register struct servent *sp;	if ((sp = getservbyname ("ftp", "tcp")) == NULL) {	    fprintf (stderr, "tcp/ftp: unknown service");	    return NOTOK;	}	if ((hp = gethostbystring (host)) == NULL) {	    fprintf (stderr, "%s: unknown host\n", host);	    return NOTOK;	}	in_socket.sin_family = hp -> h_addrtype;	inaddr_copy (hp, &in_socket);	in_socket.sin_port = sp -> s_port;	if ((ftp_fd = start_tcp_client ((struct sockaddr_in *) NULL, 0))	        == NOTOK) {	    perror (host);	    return NOTOK;	}	if (join_tcp_server (ftp_fd, &in_socket) == NOTOK) {	    perror (host);	    (void) close_tcp_socket (ftp_fd), ftp_fd = NOTOK;	    return NOTOK;	}	(void) getreply (1, 0);	if (v_verbose) {	    fprintf (stdout, "Connected to %s\n", host);	    (void) fflush (stdout);	}	if (user) {	    if ((result = command (0, "USER %s", user)) == CONTINUE)		result = command (1, "PASS %s", password);	    if (result != COMPLETE) {		result = NOTOK;		goto out;	    }	}	if (remote == NULL)	    return OK;    }    if (cwd && ((result = command (0, "CWD %s", cwd)) != COMPLETE		    && result != CONTINUE)) {	result = NOTOK;	goto out;    }    if (command (1, ascii ? "TYPE A" : "TYPE I") != COMPLETE) {	result = NOTOK;	goto out;    }    result = ftp_read (remote, local, cmd, ascii);out: ;    if (result != OK || !stayopen)	(void) ftp_quit ();    return result;}/*  */static int  ftp_quit (){    int	    n;    if (ftp_fd == NOTOK)	return OK;    n = command (1, "QUIT");    (void) close_tcp_socket (ftp_fd), ftp_fd = NOTOK;    return (n == 0 || n == COMPLETE ? OK : NOTOK);}/*  */static int  ftp_read (remote, local, cmd, ascii)char    *remote,	*local,	*cmd;int	ascii;{    int	    istdio = 0,	    istore;    register int    cc;    int	    expectingreply = 0;    char    buffer[BUFSIZ];    FILE   *fp = NULL;    if (initconn () == NOTOK)	goto bad;    v_noise = v_verbose;    if (command (-1, *remote ? "%s %s" : "%s", cmd, remote) != PRELIM)	goto bad;    expectingreply++;    if (dataconn () == NOTOK) {bad: ;        if (fp && !istdio)	    (void) fclose (fp);	if (data_fd != NOTOK)	    (void) close_tcp_socket (data_fd), data_fd = NOTOK;	if (expectingreply)	    (void) getreply (-2, 0);	return NOTOK;    }    istore = !strcmp (cmd, "STOR");    if (istdio = !strcmp (local, "-"))	fp = istore ? stdin : stdout;    else	if ((fp = fopen (local, istore ? "r" : "w")) == NULL) {	    perror (local);	    goto bad;	}    if (istore) {	if (ascii) {	    int	    c;	    FILE   *out;	    if (!(out = fdopen (data_fd, "w"))) {		perror ("fdopen");		goto bad;	    }	    while ((c = getc (fp)) != EOF) {		if (c == '\n')		    (void) putc ('\r', out);		if (putc (c, out) == EOF) {		    perror ("putc");		    (void) fclose (out);		    data_fd = NOTOK;		    goto bad;		}	    }	    (void) fclose (out);	    data_fd = NOTOK;	}	else {	    while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, fp)) >0)		if (write_tcp_socket (data_fd, buffer, cc) != cc) {		    perror ("write_tcp_socket");		    goto bad;		}	    (void) close_tcp_socket (data_fd), data_fd = NOTOK;	}    }    else {	if (ascii) {	    int	    c;	    FILE   *in;	    if (!(in = fdopen (data_fd, "r"))) {		perror ("fdopen");		goto bad;	    }	    while ((c = getc (in)) != EOF) {		if (c == '\r')		    switch (c = getc (in)) {		        case EOF:		        case '\0':		            c = '\r';			    break;			case '\n':			    break;			default:			    (void) putc ('\r', fp);			    break;			}		if (putc (c, fp) == EOF) {		    perror ("putc");		    (void) fclose (in);		    data_fd = NOTOK;		    goto bad;		}	    }	    (void) fclose (in);	    data_fd = NOTOK;	}	else {	    while ((cc = read_tcp_socket (data_fd, buffer, sizeof buffer)) > 0)		if (fwrite (buffer, sizeof *buffer, cc, fp) == 0) {		    perror ("fwrite");		    goto bad;		}	    if (cc < 0) {		perror ("read_tcp_socket");		goto bad;	    }	    (void) close_tcp_socket (data_fd), data_fd = NOTOK;	}    }    if (!istdio)	(void) fclose (fp);    v_noise = v_verbose;    return (getreply (1, 0) == COMPLETE ? OK : NOTOK);}/*  */static int  initconn (){    int	    len;    register char  *a,		   *p;    struct sockaddr_in in_socket;    if (getsockname (ftp_fd, (struct sockaddr *) &in_socket,		     (len = sizeof in_socket, &len)) == NOTOK) {	perror ("getsockname");	return NOTOK;    }    in_socket.sin_port = 0;    if ((data_fd = start_tcp_server (&in_socket, 1, 0, 0)) == NOTOK) {	perror ("start_tcp_server");	return NOTOK;    }    if (getsockname (data_fd, (struct sockaddr *) &in_socket,		     (len = sizeof in_socket, &len)) == NOTOK) {	perror ("getsockname");	return NOTOK;    }    a = (char *) &in_socket.sin_addr;    p = (char *) &in_socket.sin_port;#define	UC(b)	(((int) b) & 0xff)    if (command (1, "PORT %d,%d,%d,%d,%d,%d",		      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),		      UC(p[0]), UC(p[1])) == COMPLETE)	return OK;    return NOTOK;}/*  */static int  dataconn (){    int	    fd;    struct sockaddr_in in_socket;        if ((fd = join_tcp_client (data_fd, &in_socket)) == NOTOK) {	perror ("join_tcp_client");	return NOTOK;    }    (void) close_tcp_socket (data_fd);    data_fd = fd;    return OK;}/*  */#ifndef	lint#ifdef __STDC__static int  command (int arg1, ...){    int	    val;    va_list ap;    va_start (ap, arg1);    val = _command (arg1, ap);    va_end (ap);    return val;}#elsestatic int  command (va_alist)va_dcl{    int	    val;    va_list ap;    va_start (ap);    val = va_arg (ap, int);    val = _command (val, ap);    va_end (ap);    return val;}#endifstatic int  _command (complete, ap)int complete;va_list ap;{    int	    len;    char    buffer[BUFSIZ];    if (ftp_fd == NOTOK)	return NOTOK;    _asprintf (buffer, NULLCP, ap);    if (v_debug)	fprintf (stderr, "<--- %s\n", buffer);    (void) strcat (buffer, "\r\n");    len = strlen (buffer);    if (write_tcp_socket (ftp_fd, buffer, len) != len) {	perror ("write_tcp_socket");	return NOTOK;    }    return (getreply (complete, !strcmp (buffer, "QUIT")));}#else/* VARARGS2 */static int  command (complete, fmt)int	complete;char   *fmt;{    return command (complete, fmt);}#endif/*  */static int  getreply (complete, expecteof)int	complete,	expecteof;{    for (;;) {	register int code,		     dig,		     n;	int	continuation;	register char *bp;	char    buffer[BUFSIZ];	code = dig = n = continuation = 0;	bp = buffer;	for (;;) {	    char    c;	    if (read_tcp_socket (ftp_fd, &c, 1) < 1) {		if (expecteof)		    return OK;		perror ("read_tcp_socket");		return DONE;	    }	    if (c == '\n')		break;	    *bp++ = c != '\r' ? c : '\0';	    dig++;	    if (dig < 4) {		if (isdigit(c))		    code = code * 10 + (c - '0');		else				/* XXX: naughty FTP... */		    if (isspace (c))			continuation++;	    }	    else		if (dig == 4 && c == '-')		    continuation++;	    if (n == 0)		n = c;	}	if (v_debug)	    fprintf (stderr, "---> %s\n", buffer);	if (continuation)	    continue;	n -= '0';	if (v_noise) {	    fprintf (stdout, "%s\n", buffer);	    (void) fflush (stdout);	    v_noise = 0;	}	else	    if ((complete == -1 && n != PRELIM)		    || (complete == 0 && n != CONTINUE && n != COMPLETE)		    || (complete == 1 && n != COMPLETE))		fprintf (stderr, "%s\n", buffer);	return n;    }}#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?