head 1.13; access; symbols; locks; strict; comment @ * @; 1.13 date 93.08.25.17.25.27; author jromine; state Exp; branches; next 1.12; 1.12 date 93.08.20.15.49.47; author jromine; state Exp; branches; next 1.11; 1.11 date 93.03.17.00.18.56; author jromine; state Exp; branches; next 1.10; 1.10 date 92.12.03.16.50.27; author jromine; state Exp; branches; next 1.9; 1.9 date 92.12.03.16.28.56; author jromine; state Exp; branches; next 1.8; 1.8 date 92.11.24.18.24.30; author jromine; state Exp; branches; next 1.7; 1.7 date 92.11.12.00.41.28; author jromine; state Exp; branches; next 1.6; 1.6 date 92.11.11.20.56.53; author jromine; state Exp; branches; next 1.5; 1.5 date 92.11.02.21.35.10; author jromine; state Exp; branches; next 1.4; 1.4 date 92.11.02.17.01.49; author jromine; state Exp; branches; next 1.3; 1.3 date 92.10.20.16.31.05; author jromine; state Exp; branches; next 1.2; 1.2 date 92.05.19.21.03.01; author jromine; state Exp; branches; next 1.1; 1.1 date 92.01.31.16.28.15; author jromine; state Exp; branches; next ; desc @multimedia MH @ 1.13 log @off_t fixes for BSD44 @ text @/* ftpsbr.c - simple FTP client library (why doesn't BSD have one?!?) */ #ifndef lint static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.12 1993/08/20 15:49:47 jromine Exp jromine $"; #endif #include "../h/mh.h" #include "../h/mhn.h" #ifdef FTP #include #ifdef SVR4 #undef NULLVP /* stdio.h */ #endif #include #include #ifdef __STDC__ #include #else #include #endif #ifdef __STDC__ static int command(int arg1, ...); #else static int command(); #endif static int ftp_quit(), ftp_read(), initconn(), dataconn(), _command(), getreply(); /* DATA */ #define v_debug debugsw #define v_verbose verbosw static 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 #include #include #include #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 BSD44 extern 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; } #else static 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; } #endif static 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 @ 1.12 log @added gethostbystring() routine (deals with numbers and names) added support for writing files, etc. /mtr @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.11 1993/03/17 00:18:56 jromine Exp jromine $"; d70 1 d73 1 @ 1.11 log @fix varargs - argument passing order is not defined in C @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.10 1992/12/03 16:50:27 jromine Exp jromine $"; a51 3 /* taken from ISODE's compat/internet.c */ a63 5 #ifndef DG u_long inet_addr (); #else struct in_addr inet_addr (); #endif d65 1 a66 38 static char *empty = NULL; #ifdef h_addr static char *addrs[2] = { NULL }; #endif static struct hostent *gethostbystring (s) char *s; { register struct hostent *h; #ifndef DG static u_long iaddr; #else static struct in_addr iaddr; #endif static struct hostent hs; iaddr = inet_addr (s); #ifndef DG if (iaddr == NOTOK && strcmp (s, "255.255.255.255")) #else if (iaddr.s_addr == NOTOK && strcmp (s, "255.255.255.255")) #endif return gethostbyname (s); h = &hs; h -> h_name = s; h -> h_aliases = ∅ h -> h_addrtype = AF_INET; h -> h_length = sizeof (iaddr); #ifdef h_addr h -> h_addr_list = addrs; bzero ((char *) addrs, sizeof addrs); #endif h -> h_addr = (char *) &iaddr; return h; } d184 18 d268 1 a268 1 result = ftp_read (remote, local, ascii); d295 1 a295 1 static int ftp_read (remote, local, ascii) d297 2 a298 1 *local; d301 2 d306 1 a306 1 FILE *fp; d312 1 a312 1 if (command (-1, "RETR %s", remote) != PRELIM) d318 2 d328 1 a328 4 if ((fp = fopen (local, "w")) == NULL) { perror (local); goto bad; } d330 5 a334 6 if (ascii) { int c; FILE *in; if (!(in = fdopen (data_fd, "r"))) { perror ("fdopen"); a336 7 while ((c = getc (in)) != EOF) { if (c == '\r') switch (c = getc (in)) { case EOF: case '\0': c = '\r'; break; d338 4 a341 2 case '\n': break; d343 13 a355 3 default: (void) putc ('\r', fp); break; d357 1 d359 2 a360 6 if (putc (c, fp) == EOF) { perror ("putc"); (void) fclose (in); data_fd = NOTOK; goto bad; } d362 6 d369 2 a370 2 (void) fclose (in); data_fd = NOTOK; d373 6 a378 3 while ((cc = read_tcp_socket (data_fd, buffer, sizeof buffer)) > 0) if (fwrite (buffer, sizeof *buffer, cc, fp) == 0) { perror ("fwrite"); d381 27 a407 3 if (cc < 0) { perror ("read_tcp_socket"); goto bad; d409 10 d420 2 a421 1 (void) close_tcp_socket (data_fd), data_fd = NOTOK; d424 2 a425 1 (void) fclose (fp); @ 1.10 log @put u_short ifdef under #if AUX @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.9 1992/12/03 16:28:56 jromine Exp jromine $"; d491 2 a492 1 val = _command (va_arg (ap, int), ap); @ 1.9 log @u_short AUX changes from Jim Guyton @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.8 1992/11/24 18:24:30 jromine Exp jromine $"; d47 1 a47 1 #ifdef SYS5 @ 1.8 log @fix decl @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.7 1992/11/12 00:41:28 jromine Exp jromine $"; d46 6 @ 1.7 log @__STDC__ ifdef put iob back @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.6 1992/11/11 20:56:53 jromine Exp jromine $"; d27 3 @ 1.6 log @VSPRINTF fixups for aix @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.5 1992/11/02 21:35:10 jromine Exp jromine $"; d11 3 d22 6 d169 1 a169 4 FP iob; if ((iob = malloc(sizeof iob)) == NULL) adios(NULLCP, "unable to allocate buffer"); @ 1.5 log @iob->_ptr ifdef sequent (type problem) @ text @d1 1 a1 1 /* ftp.c - simple FTP client library (why doesn't BSD have one?!?) */ d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.4 1992/11/02 17:01:49 jromine Exp jromine $"; d160 4 a163 1 struct _iobuf iob; @ 1.4 log @fix from mtr @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.3 1992/10/20 16:31:05 jromine Exp jromine $"; d169 1 a169 1 #if !defined(vax) && !defined(pyr) @ 1.3 log @fixes from mtr @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.2 1992/05/19 21:03:01 jromine Exp $"; d551 3 @ 1.2 log @AIX @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id: ftpsbr.c,v 1.1 1992/01/31 16:28:15 jromine Exp jromine $"; a521 10 register int code, dig, n; int originalcode, continuation; register char *bp; char buffer[BUFSIZ]; originalcode = continuation = 0; bp = buffer; d523 6 a528 1 dig = n = code = 0; d530 3 d548 7 a554 4 if (dig < 4 && isdigit(c)) code = code * 10 + (c - '0'); if (dig == 4 && c == '-') continuation++; a558 5 if (continuation && code != originalcode) { if (originalcode == 0) originalcode = code; continue; } d561 2 @ 1.1 log @Initial revision @ text @d4 1 a4 1 static char ident[] = "@@(#)$Id$"; d13 3 d17 1 d155 1 a155 1 *bp = NULL; d176 1 a176 1 (void) putc (NULL, &iob); d349 1 a349 1 case NULL: d450 15 d473 1 a473 1 val = _command (ap); d479 1 d481 2 a482 1 static int _command (ap) d485 1 a485 3 int cc, complete, len; a490 2 complete = va_arg (ap, int); d547 1 a547 1 *bp++ = c != '\r' ? c : NULL; @