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.