This is ftp.c in view mode; [Download] [Up]
/*
#define DEBUG
*/
// anonymous ftp routines.
#include <fcntl.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#ifndef NULL
#define NULL 0
#endif
#ifdef DEBUG
#define D(X) X
#else
#define D(X)
#endif
#define SERRNO 1
#define HERRNO 2
#define ERRNO 3
/*
main(argc, argv)
int argc;
char *argv[];
{
exit(ftp(argv[1], argv[2], argv[3], argv[4]));
}
*/
// ftp does an anonymous ftp from 'host' of file 'path'/'file'. Where
// 'user' is sent as password as requested by anonymous ftp server.
ftp(host, user, path, file)
char *host;
char *user;
char *path;
char *file;
{
struct servent *sp;
struct hostent *hp;
int sd, sd1;
struct sockaddr_in addr;
int len;
char cmd[256];
int code;
int reuse_addr;
int fd;
int child;
if ((fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) {
return(ERRNO);
}
if ((sp = getservbyname("ftp", "tcp")) == NULL) {
return(SERRNO);
}
addr.sin_port = sp->s_port;
if ((hp = gethostbyname(host)) == NULL) {
return(HERRNO);
}
bcopy(hp->h_addr_list[0], (char *)&addr.sin_addr, hp->h_length);
if ((sd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
return(ERRNO);
}
addr.sin_family = PF_INET;
if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
return(ERRNO);
}
if ((code = read_reply(sd)) != 220) {
return(code);
}
write(sd, "USER anonymous\r\n", 16);
if ((code = read_reply(sd)) != 331) {
write(sd, "QUIT\r\n", 6);
return(code);
}
sprintf(cmd, "PASS %s\r\n", user);
write(sd, cmd, strlen(cmd));
if ((code = read_reply(sd)) != 230) {
write(sd, "QUIT\r\n", 6);
return(code);
}
write(sd, "TYPE I\r\n", 8);
if ((code = read_reply(sd)) != 200) {
write(sd, "QUIT\r\n", 6);
return(code);
}
len = sizeof(addr);
if (getsockname(sd, &addr, &len) == -1) {
return(ERRNO);
}
if ((sd1 = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
return(ERRNO);
}
reuse_addr = 1;
if (setsockopt(sd1, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,
sizeof(reuse_addr)) == -1) {
return(ERRNO);
}
if (bind(sd1, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
return(ERRNO);
}
if (listen(sd1, 1) == -1) {
return(ERRNO);
}
if ((child = fork()) == 0) {
close(sd);
exit(data_process(sd1, fd));
} else if (child == -1) {
close(sd);
close(sd1);
return(ERRNO);
}
close(sd1);
close(fd);
D(fprintf(stderr, "sending retr command\n");)
sprintf(cmd, "retr %s\r\n", path);
write(sd, cmd, strlen(cmd));
if ((code = read_reply(sd)) != 150) {
write(sd, "QUIT\r\n", 6);
close(sd);
kill(child, SIGKILL);
return(code);
}
if ((code = read_reply(sd)) != 226) {
write(sd, "QUIT\r\n", 6);
close(sd);
kill(child, SIGKILL);
return(code);
}
write(sd, "QUIT\r\n", 6);
close(sd);
kill(child, SIGKILL);
return(0);
}
int read_reply(sd)
int sd;
{
char *line;
int code, code1;
char cont;
char *read_line();
line = read_line(sd);
sscanf(line, "%d%c", &code, &cont);
D(fprintf(stderr, "code = %d, cont = %c\n", code, cont);)
if (cont == '-') {
do {
line = read_line(sd);
sscanf(line, "%d%c", &code1, &cont);
D(fprintf(stderr, "code = %d, cont = %c\n", code1, cont);)
} while (cont != ' ' || code1 != code);
}
return(code);
}
char *read_line(sd)
int sd;
{
static char buf[4096];
static char *bufStart = NULL, *bufEnd = NULL;
int len;
char *lineStart, *lineEnd;
if (bufStart == bufEnd) {
len = read(sd, buf, sizeof(buf));
bufStart = buf;
bufEnd = buf + len;
}
begin:
if ((lineEnd = index(bufStart, '\r')) != 0) {
*lineEnd = '\0';
lineStart = bufStart;
bufStart = lineEnd + 2;
D(write(2, lineStart, strlen(lineStart));
write(2, "\n", 1);)
return(lineStart);
} else {
bcopy(bufStart, buf, bufEnd - bufStart);
len = read(sd, buf + (bufEnd - bufStart),
sizeof(buf) - (bufEnd - bufStart));
bufEnd = buf + (bufEnd - bufStart) + len;
bufStart = buf;
goto begin;
}
}
data_process(sd, fd)
int sd;
int fd;
{
int dsd;
struct sockaddr addr;
int len;
char buf[4096];
int cnt;
D(fprintf(stderr, "waiting for data connection\n");)
if ((dsd = accept(sd, &addr, &len)) == -1) {
return(-1);
}
close(sd);
D(fprintf(stderr, "data connection accepted\n");)
D(fflush(stderr);)
while ((cnt = read(dsd, buf, sizeof(buf))) != -1) {
D(write(2, buf, cnt);)
write(fd, buf, cnt);
}
close(dsd);
close(fd);
return(0);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.