From ce507dbf55bd128c9a7220c76fffe0b63c8ca68a Mon Sep 17 00:00:00 2001 From: deuce <> Date: Mon, 8 Dec 2003 05:39:51 +0000 Subject: [PATCH] Added httpio.[ch] and removed ftpio.[ch] now uses HTTP rather than FTP for file fetching. --- src/sbbs3/install/GNUmakefile | 23 +- src/sbbs3/install/ftpio.c | 905 ---------------------------------- src/sbbs3/install/ftpio.h | 80 --- src/sbbs3/install/httpio.c | 206 ++++++++ src/sbbs3/install/httpio.h | 4 + src/sbbs3/install/objects.mk | 7 +- src/sbbs3/install/sbbsinst.c | 86 ++-- 7 files changed, 267 insertions(+), 1044 deletions(-) delete mode 100644 src/sbbs3/install/ftpio.c delete mode 100644 src/sbbs3/install/ftpio.h create mode 100644 src/sbbs3/install/httpio.c create mode 100644 src/sbbs3/install/httpio.h diff --git a/src/sbbs3/install/GNUmakefile b/src/sbbs3/install/GNUmakefile index 9945334679..bd95d37423 100644 --- a/src/sbbs3/install/GNUmakefile +++ b/src/sbbs3/install/GNUmakefile @@ -22,9 +22,12 @@ OFILE = o UIFC = ../../uifc XPDEV = ../../xpdev +ifdef STATIC + LDFLAGS += -static +endif + ifndef os os = $(shell uname) - $(warning OS not specified on command line, setting to '$(os)'.) endif os := $(shell echo $(os) | tr "[A-Z]" "[a-z]") # remove '/' from "os/2" @@ -36,11 +39,11 @@ LIBDIR := /usr/lib DELETE = rm -f -v OUTLIB = -o -CFLAGS += -g -#CFLAGS += -O2 +#CFLAGS += -g +CFLAGS += -O2 CFLAGS += -MMD -Wall -I$(UIFC) -I$(XPDEV) -I.. -LFLAGS := -L/usr/local/lib +LDFLAGS += -L/usr/local/lib ODIR := $(ODIR).release @@ -48,19 +51,19 @@ include targets.mk # defines all targets include objects.mk # defines $(OBJS) ifdef USE_DIALOG - LFLAGS += -L../../libdialog -ldialog -lncurses + LDFLAGS += -L../../libdialog -ldialog -lncurses CFLAGS += -I../../libdialog -DUSE_DIALOG OBJS += $(ODIR)$(SLASH)uifcd.$(OFILE) endif -ifdef USE_CURSES - LFLAGS += -lncurses +ifdef USE_CURSES + LDFLAGS += -lncurses CFLAGS += -DUSE_CURSES - OBJS += $(ODIR)$(SLASH)uifcc.$(OFILE) + OBJS += $(ODIR)$(SLASH)uifc32.$(OFILE) endif ifdef USE_FLTK - LFLAGS += -L/usr/X11R6/lib -lfltk -lX11 -lm + LDFLAGS += -L/usr/X11R6/lib -lfltk -lX11 -lm CFLAGS += -I/usr/local/include -I/usr/X11R6/include -DUSE_FLTK OBJS += $(ODIR)$(SLASH)uifcfltk.$(OFILE) endif @@ -89,7 +92,7 @@ $(SBBSINST): $(OBJS) @$(MAKE) --no-print-directory -C ../../libdialog endif @echo Linking $@ - @$(CC) -o $@ $(OBJS) $(LFLAGS) + @$(CC) -o $@ $(OBJS) $(LDFLAGS) # @strip $@ # Auto-dependency files (should go in output dir, but gcc v2.9.5 puts in cwd) diff --git a/src/sbbs3/install/ftpio.c b/src/sbbs3/install/ftpio.c deleted file mode 100644 index 46b521873f..0000000000 --- a/src/sbbs3/install/ftpio.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * - * Major Changelog: - * - * Jordan K. Hubbard - * 17 Jan 1996 - * - * Turned inside out. Now returns xfers as new file ids, not as a special - * `state' of FTP_t - * - * Stephen J. Hurd - * 23 Jan 2003 - * - * Severly mangled for use in the Synchronet installer - * - * $Id$ - * - */ - -#include <sys/types.h> -#include <sys/socket.h> - -#include <netinet/in.h> - -#include <arpa/inet.h> - -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "ftpio.h" - -#define SUCCESS 0 -#define FAILURE -1 - -#ifndef TRUE -#define TRUE (1) -#define FALSE (0) -#endif - -/* How to see by a given code whether or not the connection has timed out */ -#define FTP_TIMEOUT(code) (FtpTimedOut || code == FTP_TIMED_OUT) - -/* Internal routines - deal only with internal FTP_t type */ -static FTP_t ftp_new(void); -static int ftp_read_method(void *n, char *buf, int nbytes); -static int ftp_close_method(void *n); -static int writes(int fd, char *s); -static __inline char *get_a_line(FTP_t ftp); -static int get_a_number(FTP_t ftp, char **q); -static int botch(char *func, char *botch_state); -static int cmd(FTP_t ftp, const char *fmt, ...); -static int ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose); -static int ftp_file_op(FTP_t ftp, char *operation, char *file, ftp_FILE **, char *mode, off_t *seekto); -static int ftp_close(FTP_t ftp); -static int get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret); -static void ftp_timeout(int sig); -static void ftp_set_timeout(void); -static void ftp_clear_timeout(void); -ftp_FILE * ftpopen(void *cookie, int (*readfn)(void *, char *, int), - int (*writefn)(void *, const char *, int), - fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *)); -ftp_FILE * ftpdopen(int filedes, const char *mode); - -/* Global status variable - ick */ -int FtpTimedOut; - -/* FTP happy status codes */ -#define FTP_GENERALLY_HAPPY 200 -#define FTP_ASCII_HAPPY FTP_GENERALLY_HAPPY -#define FTP_BINARY_HAPPY FTP_GENERALLY_HAPPY -#define FTP_PORT_HAPPY FTP_GENERALLY_HAPPY -#define FTP_HAPPY_COMMENT 220 -#define FTP_QUIT_HAPPY 221 -#define FTP_TRANSFER_HAPPY 226 -#define FTP_PASSIVE_HAPPY 227 -#define FTP_LPASSIVE_HAPPY 228 -#define FTP_EPASSIVE_HAPPY 229 -#define FTP_CHDIR_HAPPY 250 - -/* FTP unhappy status codes */ -#define FTP_TIMED_OUT 421 - -/* - * XXX - * gross! evil! bad! We really need an access primitive for cookie in stdio itself. - * it's too convenient a hook to bury and it's already exported through funopen as it is, so... - * XXX - */ -#define fcookie(fp) ((fp)->_cookie) - -/* Check a return code with some lenience for back-dated garbage that might be in the buffer */ -static int -check_code(FTP_t ftp, int var, int preferred) -{ - ftp->error = 0; - while (1) { - if (var == preferred) - return 0; - else if (var == FTP_TRANSFER_HAPPY) /* last operation succeeded */ - var = get_a_number(ftp, NULL); - else if (var == FTP_HAPPY_COMMENT) /* chit-chat */ - var = get_a_number(ftp, NULL); - else if (var == FTP_GENERALLY_HAPPY) /* general success code */ - var = get_a_number(ftp, NULL); - else { - if (ftp->is_verbose) - fprintf(stderr, "!Received code %d instead of %d\n", var, preferred); - ftp->error = var; - return 1; - } - } -} - -int -ftpBinary(ftp_FILE *fp) -{ - FTP_t ftp = fcookie(fp); - int i; - - if (ftp->is_binary) - return SUCCESS; - i = cmd(ftp, "TYPE I"); - if (i < 0 || check_code(ftp, i, FTP_BINARY_HAPPY)) - return i; - ftp->is_binary = TRUE; - return SUCCESS; -} - -int -ftpChdir(ftp_FILE *fp, char *dir) -{ - int i; - FTP_t ftp = fcookie(fp); - - i = cmd(ftp, "CWD %s", dir); - if (i < 0 || check_code(ftp, i, FTP_CHDIR_HAPPY)) - return i; - return SUCCESS; -} - -int -ftpErrno(ftp_FILE *fp) -{ - FTP_t ftp = fcookie(fp); - return ftp->error; -} - -const char * -ftpErrString(int error) -{ - int k; - - if (error == -1) - return("connection in wrong state"); - if (error < 100) - /* XXX soon UNIX errnos will catch up with FTP protocol errnos */ - return strerror(error); - for (k = 0; k < ftpErrListLength; k++) - if (ftpErrList[k].num == error) - return(ftpErrList[k].string); - return("Unknown error"); -} - -off_t -ftpGetSize(ftp_FILE *fp, char *name) -{ - int i; - char p[BUFSIZ], *cp, *ep; - FTP_t ftp = fcookie(fp); - off_t size; - - if(ftp==NULL) - return (off_t)-1; - ftpPassive(fp,TRUE); - sprintf(p, "SIZE %s\r\n", name); - if (ftp->is_verbose) - fprintf(stderr, "Sending %s", p); - if (writes(ftp->fd_ctrl, p)) - return (off_t)-1; - i = get_a_number(ftp, &cp); - if (check_code(ftp, i, 213)) - return (off_t)-1; - errno = 0; /* to check for ERANGE */ - size = (off_t)strtoq(cp, &ep, 10); - if (*ep != '\0' || errno == ERANGE) - return (off_t)-1; - return size; -} - -ftp_FILE * -ftpGet(ftp_FILE *fp, char *file, off_t *seekto) -{ - ftp_FILE *fp2; - FTP_t ftp = fcookie(fp); - - ftpPassive(fp,TRUE); - if (ftpBinary(fp) != SUCCESS) - return NULL; - - if (ftp_file_op(ftp, "RETR", file, &fp2, "r", seekto) == SUCCESS) - return fp2; - return NULL; -} - -/* Returns a standard ftp_FILE pointer type representing an open control connection */ -ftp_FILE * -ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode) -{ - FTP_t n; - ftp_FILE *fp; - - if (retcode) - *retcode = 0; - - n = ftp_new(); - fp = NULL; - if (n && ftp_login_session(n, host, user, passwd, port, verbose) == SUCCESS) { - fp = ftpopen(n, ftp_read_method, NULL, NULL, ftp_close_method); /* BSD 4.4 function! */ - fp->_file = n->fd_ctrl; - } - if (retcode) { - if (!n) - *retcode = (FtpTimedOut ? FTP_TIMED_OUT : -1); - /* Poor attempt at mapping real errnos to FTP error codes */ - else switch(n->error) { - case EADDRNOTAVAIL: - *retcode = FTP_TIMED_OUT; /* Actually no such host, but we have no way of saying that. :-( */ - break; - - case ETIMEDOUT: - *retcode = FTP_TIMED_OUT; - break; - - default: - *retcode = n->error; - break; - } - } - return fp; -} - -int -ftpPassive(ftp_FILE *fp, int st) -{ - FTP_t ftp = fcookie(fp); - - if(ftp!=NULL) - ftp->is_passive = !!st; /* normalize "st" to zero or one */ - return SUCCESS; -} - -ftp_FILE * -ftpGetURL(char *url, char *user, char *passwd, int verbose, int *retcode) -{ - char host[255], name[255]; - int port; - ftp_FILE *fp2; - static ftp_FILE *fp = NULL; - static char *prev_host; - - if (retcode) - *retcode = 0; - if (get_url_info(url, host, &port, name) == SUCCESS) { - if (fp && prev_host) { - if (!strcmp(prev_host, host)) { - /* Try to use cached connection */ - fp2 = ftpGet(fp, name, NULL); - if (!fp2) { - /* Connection timed out or was no longer valid */ - fp->closefn(fp); - free(prev_host); - prev_host = NULL; - } - else - return fp2; - } - else { - /* It's a different host now, flush old */ - fp->closefn(fp); - free(prev_host); - prev_host = NULL; - } - } - fp = ftpLogin(host, user, passwd, port, verbose, retcode); - if (fp) { - fp2 = ftpGet(fp, name, NULL); - if (!fp2) { - /* Connection timed out or was no longer valid */ - if (retcode) - *retcode = ftpErrno(fp); - fp->closefn(fp); - fp = NULL; - } - else - prev_host = strdup(host); - return fp2; - } - } - return NULL; -} - -/* Internal workhorse function for dissecting URLs. Takes a URL as the first argument and returns the - result of such disection in the host, user, passwd, port and name variables. */ -static int -get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret) -{ - char *name, *host, *cp, url[BUFSIZ]; - int port; - - name = host = NULL; - /* XXX add http:// here or somewhere reasonable at some point XXX */ - if (strncmp("ftp://", url_in, 6) != 0) - return FAILURE; - /* We like to stomp a lot on the URL string in dissecting it, so copy it first */ - strncpy(url, url_in, BUFSIZ); - host = url + 6; - if ((cp = index(host, ':')) != NULL) { - *(cp++) = '\0'; - port = strtol(cp, 0, 0); - } - else - port = 0; /* use default */ - if (port_ret) - *port_ret = port; - - if ((name = index(cp ? cp : host, '/')) != NULL) - *(name++) = '\0'; - if (host_ret) - strcpy(host_ret, host); - if (name && name_ret) - strcpy(name_ret, name); - return SUCCESS; -} - -static FTP_t -ftp_new(void) -{ - FTP_t ftp; - - ftp = (FTP_t)malloc(sizeof *ftp); - if (!ftp) - return NULL; - memset(ftp, 0, sizeof *ftp); - ftp->fd_ctrl = -1; - ftp->con_state = init; - ftp->is_binary = FALSE; - ftp->is_passive = FALSE; - ftp->is_verbose = FALSE; - ftp->error = 0; - return ftp; -} - -static int -ftp_read_method(void *vp, char *buf, int nbytes) -{ - int i, fd; - FTP_t n = (FTP_t)vp; - - fd = n->fd_ctrl; - i = (fd >= 0) ? read(fd, buf, nbytes) : EOF; - return i; -} - -static int -ftp_close_method(void *n) -{ - int i; - - i = ftp_close((FTP_t)n); - free(n); - return i; -} - -static void -ftp_timeout(int sig) -{ - FtpTimedOut = TRUE; - /* Debug("ftp_pkg: ftp_timeout called - operation timed out"); */ -} - -static void -ftp_set_timeout(void) -{ - struct sigaction new; - char *cp; - int ival; - - FtpTimedOut = FALSE; - sigemptyset(&new.sa_mask); - new.sa_flags = 0; - new.sa_handler = ftp_timeout; - sigaction(SIGALRM, &new, NULL); - cp = getenv("FTP_TIMEOUT"); - if (!cp || !(ival = atoi(cp))) - ival = 120; - alarm(ival); -} - -static void -ftp_clear_timeout(void) -{ - struct sigaction new; - - alarm(0); - sigemptyset(&new.sa_mask); - new.sa_flags = 0; - new.sa_handler = SIG_DFL; - sigaction(SIGALRM, &new, NULL); -} - -static int -writes(int fd, char *s) -{ - int n, i = strlen(s); - - ftp_set_timeout(); - n = write(fd, s, i); - ftp_clear_timeout(); - if (FtpTimedOut || i != n) - return TRUE; - return FALSE; -} - -static __inline char * -get_a_line(FTP_t ftp) -{ - static char buf[BUFSIZ]; - int i,j; - - /* Debug("ftp_pkg: trying to read a line from %d", ftp->fd_ctrl); */ - for(i = 0; i < BUFSIZ;) { - ftp_set_timeout(); - j = read(ftp->fd_ctrl, buf + i, 1); - ftp_clear_timeout(); - if (FtpTimedOut || j != 1) - return NULL; - if (buf[i] == '\r' || buf[i] == '\n') { - if (!i) - continue; - buf[i] = '\0'; - if (ftp->is_verbose == TRUE) - fprintf(stderr, "%s\n",buf+4); - return buf; - } - i++; - } - /* Debug("ftp_pkg: read string \"%s\" from %d", buf, ftp->fd_ctrl); */ - return buf; -} - -static int -get_a_number(FTP_t ftp, char **q) -{ - char *p; - int i = -1, j; - - while(1) { - p = get_a_line(ftp); - if (!p) { - ftp_close(ftp); - if (FtpTimedOut) - return FTP_TIMED_OUT; - return FAILURE; - } - if (!(isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2]))) - continue; - if (i == -1 && p[3] == '-') { - i = strtol(p, 0, 0); - continue; - } - if (p[3] != ' ' && p[3] != '\t') - continue; - j = strtol(p, 0, 0); - if (i == -1) { - if (q) *q = p+4; - /* Debug("ftp_pkg: read reply %d from server (%s)", j, p); */ - return j; - } else if (j == i) { - if (q) *q = p+4; - /* Debug("ftp_pkg: read reply %d from server (%s)", j, p); */ - return j; - } - } -} - -static int -ftp_close(FTP_t ftp) -{ - int i, rcode; - - rcode = FAILURE; - if (ftp->con_state == isopen) { - ftp->con_state = quit; - /* If last operation timed out, don't try to quit - just close */ - if (ftp->error != FTP_TIMED_OUT) - i = cmd(ftp, "QUIT"); - else - i = FTP_QUIT_HAPPY; - if (!check_code(ftp, i, FTP_QUIT_HAPPY)) - rcode = SUCCESS; - close(ftp->fd_ctrl); - ftp->fd_ctrl = -1; - } - else if (ftp->con_state == quit) - rcode = SUCCESS; - return rcode; -} - -static int -botch(char *func, char *botch_state) -{ - /* Debug("ftp_pkg: botch: %s(%s)", func, botch_state); */ - return FAILURE; -} - -static int -cmd(FTP_t ftp, const char *fmt, ...) -{ - char p[BUFSIZ]; - int i; - - va_list ap; - va_start(ap, fmt); - (void)vsnprintf(p, sizeof p, fmt, ap); - va_end(ap); - - if (ftp->con_state == init) - return botch("cmd", "open"); - - strcat(p, "\r\n"); - if (ftp->is_verbose) - fprintf(stderr, "Sending: %s", p); - if (writes(ftp->fd_ctrl, p)) { - if (FtpTimedOut) - return FTP_TIMED_OUT; - return FAILURE; - } - while ((i = get_a_number(ftp, NULL)) == FTP_HAPPY_COMMENT); - return i; -} - -static u_long resolve_ip(char *addr) -{ - struct hostent* host; - char* p; - - if(*addr==0) - return(INADDR_NONE); - - for(p=addr;*p;p++) - if(*p!='.' && !isdigit(*p)) - break; - if(!(*p)) - return(inet_addr(addr)); - if((host=gethostbyname(addr))==NULL) - return(INADDR_NONE); - return(*((u_long*)host->h_addr_list[0])); -} - - -static int -ftp_login_session(FTP_t ftp, char *host, - char *user, char *passwd, int port, int verbose) -{ - struct sockaddr_in addr; - u_long ip_addr; - int s; - int i; - - if (ftp->con_state != init) { - ftp_close(ftp); - ftp->error = -1; - return FAILURE; - } - - if (!user) - user = "ftp"; - - if (!passwd) - passwd = "setup@"; - - if (!port) - port = 21; - - if((ip_addr=resolve_ip(host))==INADDR_NONE) - return FAILURE; - - if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) { - ftp->error = errno; - return FAILURE; - } - - memset(&addr,0,sizeof(addr)); - addr.sin_addr.s_addr = ip_addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - - if (connect(s, (struct sockaddr*)&addr, sizeof (addr)) < 0) { - ftp->error = errno; - close(s); - return FAILURE; - } - - ftp->addrtype = addr.sin_family; - ftp->fd_ctrl = s; - ftp->con_state = isopen; - ftp->is_verbose = verbose; - - i = cmd(ftp, "USER %s", user); - if (i >= 300 && i < 400) - i = cmd(ftp, "PASS %s", passwd); - if (i >= 299 || i < 0) { - ftp_close(ftp); - if (i > 0) - ftp->error = i; - return FAILURE; - } - return SUCCESS; -} - -static int -ftp_file_op(FTP_t ftp, char *operation, char *file, ftp_FILE **fp, char *mode, off_t *seekto) -{ - int i,l,s; - char *q; - unsigned char addr[64]; - union sockaddr_cmn { - struct sockaddr_in sin4; - struct sockaddr_in6 sin6; - } sin; - char *cmdstr; - - if (ftp->is_verbose) - fprintf(stderr, "ftp_file_op %s: %s\n", operation, file); - - if (!fp) - return FAILURE; - *fp = NULL; - - if (ftp->con_state != isopen) - return botch("ftp_file_op", "open"); - - if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) { - ftp->error = errno; - return FAILURE; - } - - if (ftp->is_passive) { - if (ftp->is_verbose) - fprintf(stderr, "Sending PASV\n"); - if (writes(ftp->fd_ctrl, "PASV\r\n")) { - ftp_close(ftp); - if (FtpTimedOut) - ftp->error = FTP_TIMED_OUT; - return FTP_TIMED_OUT; - } - i = get_a_number(ftp, &q); - if (check_code(ftp, i, FTP_PASSIVE_HAPPY)) { - ftp_close(ftp); - return i; - } - cmdstr = "PASV"; - while (*q && !isdigit(*q)) - q++; - if (!*q) { - ftp_close(ftp); - return FAILURE; - } - q--; - l = (ftp->addrtype == AF_INET ? 6 : 21); - for (i = 0; i < l; i++) { - q++; - addr[i] = strtol(q, &q, 10); - } - - sin.sin4.sin_family = ftp->addrtype; - bcopy(addr, (char *)&sin.sin4.sin_addr, 4); - bcopy(addr + 4, (char *)&sin.sin4.sin_port, 2); - if (connect(s, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { - (void)close(s); - return FAILURE; - } - - if (seekto && *seekto) { - i = cmd(ftp, "REST %d", *seekto); - if (i < 0 || FTP_TIMEOUT(i)) { - close(s); - ftp->error = i; - *seekto = (off_t)0; - return i; - } - } - i = cmd(ftp, "%s %s", operation, file); - if (i < 0 || i > 299) { - close(s); - ftp->error = i; - return i; - } - *fp = ftpdopen(s, mode); - } - else { - int fd; - -#ifdef IP_PORTRANGE - int portrange; - - if (ftp->addrtype == AF_INET) { - portrange = IP_PORTRANGE_HIGH; - if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, (char *) - &portrange, sizeof(portrange)) < 0) { - close(s); - return FAILURE; - } - } -#endif - - i = sizeof sin; - getsockname(ftp->fd_ctrl, (struct sockaddr *)&sin, &i); - sin.sin4.sin_port = 0; - i = sizeof(struct sockaddr_in); - if (bind(s, (struct sockaddr *)&sin, i) < 0) { - close(s); - return FAILURE; - } - i = sizeof sin; - getsockname(s,(struct sockaddr *)&sin,&i); - if (listen(s, 1) < 0) { - close(s); - return FAILURE; - } - if (sin.sin4.sin_family == AF_INET) { - u_long a; - a = ntohl(sin.sin4.sin_addr.s_addr); - i = cmd(ftp, "PORT %d,%d,%d,%d,%d,%d", - (a >> 24) & 0xff, - (a >> 16) & 0xff, - (a >> 8) & 0xff, - a & 0xff, - (ntohs(sin.sin4.sin_port) >> 8) & 0xff, - ntohs(sin.sin4.sin_port) & 0xff); - if (check_code(ftp, i, FTP_PORT_HAPPY)) { - close(s); - return i; - } - } - if (seekto && *seekto) { - i = cmd(ftp, "REST %d", *seekto); - if (i < 0 || FTP_TIMEOUT(i)) { - close(s); - ftp->error = i; - return i; - } - else if (i != 350) - *seekto = (off_t)0; - } - i = cmd(ftp, "%s %s", operation, file); - if (i < 0 || i > 299) { - close(s); - ftp->error = i; - return FAILURE; - } - fd = accept(s, 0, 0); - if (fd < 0) { - close(s); - ftp->error = 401; - return FAILURE; - } - close(s); - *fp = ftpdopen(fd, mode); - } - if (*fp) { - (*fp)->_cookie=ftp; - return SUCCESS; - } - else - return FAILURE; -} - -struct ftperr ftpErrList[] = { - { 110, "Restart marker reply" }, - { 120, "Service ready in a few minutes" }, - { 125, "Data connection already open; transfer starting" }, - { 150, "File status okay; about to open data connection" }, - { 200, "Command okay" }, - { 202, "Command not implemented, superfluous at this site" }, - { 211, "System status, or system help reply" }, - { 212, "Directory status" }, - { 213, "File status" }, - { 214, "Help message" }, - { 215, "Set system type" }, - { 220, "Service ready for new user" }, - { 221, "Service closing control connection" }, - { 225, "Data connection open; no transfer in progress" }, - { 226, "Requested file action successful" }, - { 227, "Entering Passive Mode" }, - { 229, "Entering Extended Passive Mode" }, - { 230, "User logged in, proceed" }, - { 250, "Requested file action okay, completed" }, - { 257, "File/directory created" }, - { 331, "User name okay, need password" }, - { 332, "Need account for login" }, - { 350, "Requested file action pending further information" }, - { 421, "Service not available, closing control connection" }, - { 425, "Can't open data connection" }, - { 426, "Connection closed; transfer aborted" }, - { 450, "File unavailable (e.g., file busy)" }, - { 451, "Requested action aborted: local error in processing" }, - { 452, "Insufficient storage space in system" }, - { 500, "Syntax error, command unrecognized" }, - { 501, "Syntax error in parameters or arguments" }, - { 502, "Command not implemented" }, - { 503, "Bad sequence of commands" }, - { 504, "Command not implemented for that parameter" }, - { 530, "Not logged in" }, - { 532, "Need account for storing files" }, - { 550, "File unavailable (e.g., file not found, no access)" }, - { 551, "Requested action aborted. Page type unknown" }, - { 552, "Exceeded storage allocation" }, - { 553, "File name not allowed" }, -}; -int const ftpErrListLength = sizeof(ftpErrList) / sizeof(*ftpErrList); - -char * -ftpgets(char *str, int size, void *stream) -{ - static char buf[BUFSIZ]; - char *p=NULL; - int i,j; - - /* Debug("ftp_pkg: trying to read a line from %d", ftp->fd_ctrl); */ - for(i = 0; i < BUFSIZ;) { - ftp_set_timeout(); - j = read(((ftp_FILE *)stream)->_file, buf + i, 1); - ftp_clear_timeout(); - if (FtpTimedOut || j != 1) { - p=NULL; - i=BUFSIZ; - } - if (buf[i] == '\n') { - buf[i+1] = '\0'; - p=buf; - i=BUFSIZ; - } - i++; - } - if(p!=NULL) { - strcpy(str,p); - return(str); - } - return(NULL); -} - -ssize_t -ftpread(void *stream, void *buf, size_t nbytes) -{ - return(read(((ftp_FILE *)stream)->_file,buf,nbytes)); -} - -ftp_FILE * -ftpopen(void *cookie, int (*readfn)(void *, char *, int), - int (*writefn)(void *, const char *, int), - fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *)) -{ - ftp_FILE *f; - - f=malloc(sizeof(ftp_FILE)); - f->_cookie=cookie; - f->readfn=readfn; - f->writefn=writefn; - f->seekfn=seekfn; - f->closefn=closefn; - f->gets=ftpgets; - f->read=ftpread; - return(f); -} - -ftp_FILE * -ftpdopen(int filedes, const char *mode) -{ - ftp_FILE *f; - - f=malloc(sizeof(ftp_FILE)); - f->_cookie=NULL; - f->_file=filedes; - f->readfn=ftp_read_method; - f->writefn=NULL; - f->seekfn=NULL; - f->closefn=ftp_close_method; - f->gets=ftpgets; - f->read=ftpread; - return(f); -} diff --git a/src/sbbs3/install/ftpio.h b/src/sbbs3/install/ftpio.h deleted file mode 100644 index ccdc8d790b..0000000000 --- a/src/sbbs3/install/ftpio.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef _FTP_H_INCLUDE -#define _FTP_H_INCLUDE - -#include <sys/types.h> -#include <sys/cdefs.h> -#include <stdio.h> -#include <time.h> - -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * - * Major Changelog: - * - * Jordan K. Hubbard - * 17 Jan 1996 - * - * Turned inside out. Now returns xfers as new file ids, not as a special - * `state' of FTP_t - * - * $FreeBSD: src/lib/libftpio/ftpio.h,v 1.17 2002/03/25 13:49:48 phk Exp $ - */ - -typedef struct { - void *_cookie; - int _file; - int (*readfn)(void *, char *, int); - int (*writefn)(void *, const char *, int); - fpos_t (*seekfn)(void *, fpos_t, int); - int (*closefn)(void *); - char* (*gets)(char *,int,void *); - ssize_t (*read)(void *, void *, size_t); -} ftp_file_t; -#define ftp_FILE ftp_file_t - -/* Internal housekeeping data structure for FTP sessions */ -typedef struct { - enum { init, isopen, quit } con_state; - int fd_ctrl; - int addrtype; - char *host; - char *file; - int error; - int is_binary; - int is_passive; - int is_verbose; -} *FTP_t; - -/* Structure we use to match FTP error codes with readable strings */ -struct ftperr { - const int num; - const char *string; -}; - -__BEGIN_DECLS -extern struct ftperr ftpErrList[]; -extern int const ftpErrListLength; - -/* Exported routines - deal only with ftp_FILE* type */ -extern ftp_FILE *ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode); -extern int ftpChdir(ftp_FILE *fp, char *dir); -extern int ftpErrno(ftp_FILE *fp); -extern off_t ftpGetSize(ftp_FILE *fp, char *file); -extern ftp_FILE *ftpGet(ftp_FILE *fp, char *file, off_t *seekto); -extern ftp_FILE *ftpPut(ftp_FILE *fp, char *file); -extern int ftpAscii(ftp_FILE *fp); -extern int ftpBinary(ftp_FILE *fp); -extern int ftpPassive(ftp_FILE *fp, int status); -extern void ftpVerbose(ftp_FILE *fp, int status); -extern ftp_FILE *ftpGetURL(char *url, char *user, char *passwd, int verbose, int *retcode); -extern ftp_FILE *ftpPutURL(char *url, char *user, char *passwd, int *retcode); -extern time_t ftpGetModtime(ftp_FILE *fp, char *s); -extern const char *ftpErrString(int error); -__END_DECLS - -#endif /* _FTP_H_INCLUDE */ diff --git a/src/sbbs3/install/httpio.c b/src/sbbs3/install/httpio.c new file mode 100644 index 0000000000..04a5f29267 --- /dev/null +++ b/src/sbbs3/install/httpio.c @@ -0,0 +1,206 @@ +#include <stdio.h> + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <ctype.h> +#include <netdb.h> +#include <netinet/in.h> +#include <stdlib.h> +#include <string.h> +#include <arpa/inet.h> + +#include "sockwrap.h" + +#define MAX_SCHEME_LEN 10 +#define MAX_HOST_LEN 128 +#define MAX_INACTIVITY 30 /* Seconds */ +#define MAX_HEADER 1024 + +u_long resolve_ip(char *addr) +{ + struct hostent* host; + char* p; + + if(*addr==0) + return(INADDR_NONE); + + for(p=addr;*p;p++) + if(*p!='.' && !isdigit(*p)) + break; + if(!(*p)) + return(inet_addr(addr)); + if((host=gethostbyname(addr))==NULL) + return(INADDR_NONE); + return(*((u_long*)host->h_addr_list[0])); +} + +int sockreadline(int sock, char *buf, size_t length, char *error) +{ + char ch; + int i; + int rd; +#if 0 + time_t start; + + start=time(NULL); + for(i=0;TRUE;) { + if(!socket_check(sock,&rd,NULL,1000)) { + if(error != NULL) + strcpy(error, "Socket error"); + return(-1); + } + + if(!rd) { + if(time(NULL)-start>MAX_INACTIVITY) { + if(error != NULL) + strcpy(error,"Timed out"); + return(-1); /* time-out */ + } + continue; /* no data */ + } + + if(recv(sock, &ch, 1, 0)!=1) + break; + + if(ch=='\n') + break; + + if(i<length) + buf[i++]=ch; + } +#else + for(i=0;1;) { + if(!socket_check(sock,&rd,NULL,60000) || !rd || recv(sock, &ch, 1, 0)!=1) { + if(error != NULL) + strcpy(error,"Timed out"); + return(-1); /* time-out */ + } + + if(ch=='\n') + break; + + if(i<length) + buf[i++]=ch; + } +#endif + + /* Terminate at length if longer */ + if(i>length) + i=length; + + if(i>0 && buf[i-1]=='\r') + buf[--i]=0; + else + buf[i]=0; + + return(i); +} + +/* Error will hold the error message on a failed return... */ +/* Must be at least 128 bytes long */ +int http_get_fd(char *URL, size_t *len, char *error) +{ + char host[MAX_HOST_LEN+1]; + ulong ip_addr; + int s=-1; + int port=80; + char *p; + char *path; + struct sockaddr_in addr; + char header[MAX_HEADER+1]; + + if(len != NULL) + *len=0; + if(error != NULL) + *error=0; + if(strncasecmp(URL, "http://", 7)) { + if(error!=NULL) + strcpy(error, "URL is not http"); + return(-1); + } + strncpy(host, URL+7, MAX_HOST_LEN); + host[MAX_HOST_LEN+1]=0; + if((p=strchr(host,'/'))==NULL) { + if(error!=NULL) + strcpy(error, "Host too long or no path info found"); + return(-1); + } + *p=0; + if((p=strchr(host,':'))!=NULL) { + *p=0; + port=atoi(p+1); + } + if((ip_addr=resolve_ip(host))==INADDR_NONE) { + if(error!=NULL) + strcpy(error, "Unable to resolve host"); + return(-1); + } + if((path=strchr(URL+7, '/'))==NULL) { + if(error!=NULL) + strcpy(error, "Path info not found"); + return(-1); + } + if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) { + if(error!=NULL) + strcpy(error, "Unable to create socket"); + return(-1); + } + memset(&addr,0,sizeof(addr)); + addr.sin_addr.s_addr = ip_addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + if (connect(s, (struct sockaddr*)&addr, sizeof (addr)) < 0) { + close(s); + if(error!=NULL) + strcpy(error, "Unable to connect"); + return(-1); + } + if(error!=NULL) + strcpy(error,"Unable to send request"); + if(write(s, "GET ", 4)!=4) { + close(s); + return(-1); + } + if(write(s, path, strlen(path))!=strlen(path)) { + close(s); + return(-1); + } + if(write(s, " HTTP/1.0\r\nHost: ", 17)!=17) { + close(s); + return(-1); + } + if(write(s, host, strlen(host))!=strlen(host)) { + close(s); + return(-1); + } + if(write(s, "\r\nConnection: close\r\n\r\n",23)!=23) { + close(s); + return(-1); + } + if(error!=NULL) + *error=0; + if(sockreadline(s, header, sizeof(header), error) < 0) { + close(s); + return(-1); + } + if(atoi(header+9)!=200) { + if(error != NULL) + strncpy(error, header, 128); + error[127]=0; + close(s); + return(-1); + } + while(header[0]) { + if(sockreadline(s, header, sizeof(header), error) < 0) { + close(s); + return(-1); + } + if(len != NULL && !strncasecmp(header,"content-length: ",16)) { + *len=atoi(header+16); + } + } + return(s); +} diff --git a/src/sbbs3/install/httpio.h b/src/sbbs3/install/httpio.h new file mode 100644 index 0000000000..a672b09afc --- /dev/null +++ b/src/sbbs3/install/httpio.h @@ -0,0 +1,4 @@ +/* Error will hold the error message on a failed return... */ +/* Must be at least 40 bytes long */ +int http_get_fd(char *URL, size_t *len, char *error); +int sockreadline(int sock, char *buf, size_t length, char *error); diff --git a/src/sbbs3/install/objects.mk b/src/sbbs3/install/objects.mk index 765873f93b..fa58cce9ae 100644 --- a/src/sbbs3/install/objects.mk +++ b/src/sbbs3/install/objects.mk @@ -8,9 +8,10 @@ OBJS = $(ODIR)$(SLASH)sbbsinst.$(OFILE)\ - $(ODIR)$(SLASH)conwrap.$(OFILE)\ + $(ODIR)$(SLASH)sockwrap.$(OFILE)\ $(ODIR)$(SLASH)genwrap.$(OFILE)\ $(ODIR)$(SLASH)dirwrap.$(OFILE)\ - $(ODIR)$(SLASH)ftpio.$(OFILE)\ + $(ODIR)$(SLASH)filewrap.$(OFILE)\ + $(ODIR)$(SLASH)ciowrap.$(OFILE)\ + $(ODIR)$(SLASH)httpio.$(OFILE)\ $(ODIR)$(SLASH)uifcx.$(OFILE) - diff --git a/src/sbbs3/install/sbbsinst.c b/src/sbbs3/install/sbbsinst.c index 035b3d0bc2..7fcf3c76b6 100644 --- a/src/sbbs3/install/sbbsinst.c +++ b/src/sbbs3/install/sbbsinst.c @@ -43,17 +43,17 @@ #include "conwrap.h" #include "uifc.h" #include "sbbs.h" -#include "ftpio.h" +#include "httpio.h" /***************/ /* Definitions */ /***************/ #define DEFAULT_CVSROOT ":pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs" -#define DIST_LIST_URL1 "ftp://ftp.synchro.net/sbbsdist.lst" -#define DIST_LIST_URL2 "ftp://rob.synchro.net/Synchronet/sbbsdist.lst" -#define DIST_LIST_URL3 "ftp://cvs.synchro.net/Synchronet/sbbsdist.lst" -#define DIST_LIST_URL4 "ftp://vert.synchro.net/Synchronet/sbbsdist.lst" -#define DIST_LIST_URL5 "ftp://freebsd.synchro.net/Synchronet/sbbsdist.lst" +#define DIST_LIST_URL1 "http://www.synchro.net/sbbsdist.lst" +#define DIST_LIST_URL2 "http://rob.synchro.net/Synchronet/sbbsdist.lst" +#define DIST_LIST_URL3 "http://cvs.synchro.net/Synchronet/sbbsdist.lst" +#define DIST_LIST_URL4 "http://vert.synchro.net/Synchronet/sbbsdist.lst" +#define DIST_LIST_URL5 "http://freebsd.synchro.net:2327/synchronet/sbbsdist.lst" #define DEFAULT_DISTFILE "sbbs_src.tgz" #define DEFAULT_LIBFILE "lib-%s.tgz" /* MUST HAVE ONE %s for system type (os-machine or just os) */ #define DEFAULT_SYSTYPE "unix" /* If no other system type available, use this one */ @@ -128,14 +128,8 @@ char revision[16]; int backup_level=5; BOOL keep_makefile=FALSE; -BOOL ftp_distlist=TRUE; -BOOL ftp_verbose=FALSE; - -/*************/ -/* Constants */ -/*************/ -char *ftp_user="anonymous"; -char *ftp_pass="new@synchro.net"; +BOOL http_distlist=TRUE; +BOOL http_verbose=FALSE; /**************/ /* Prototypes */ @@ -221,10 +215,11 @@ int main(int argc, char **argv) uifc.esc_delay=atoi(argv[i]+2); break; case 'F': - ftp_verbose=TRUE; + case 'H': + http_verbose=TRUE; break; case 'N': - ftp_distlist=FALSE; + http_distlist=FALSE; break; case 'I': uifc.mode|=UIFC_IBM; @@ -237,8 +232,8 @@ int main(int argc, char **argv) default: printf("\nusage: %s [ctrl_dir] [options]" "\n\noptions:\n\n" - "-n = do not FTP-download distribution list\n" - "-f = run in FTP-verbose (debug) mode\n" + "-n = do not HTTP-download distribution list\n" + "-h = run in HTTP-verbose (debug) mode\n" "-d = run in standard input/output/door mode\n" "-c = force color mode\n" #ifdef USE_CURSES @@ -267,7 +262,7 @@ int main(int argc, char **argv) else #elif defined(USE_CURSES) if(!door_mode) - i=uifcinic(&uifc); /* curses */ + i=uifcini32(&uifc); /* curses */ else #elif !defined(__unix__) if(!door_mode) @@ -500,9 +495,10 @@ void install_sbbs(dist_t *dist,struct server_ent_t *server) { char sbbsgroup[128]; int i; int fout,ret1,ret2; - long flen; + size_t flen; long offset; - ftp_FILE *remote; + int remote; + char http_error[128]; if(params.debug) putenv("DEBUG=1"); @@ -565,33 +561,27 @@ void install_sbbs(dist_t *dist,struct server_ent_t *server) { exit(EXIT_FAILURE); } sprintf(url,"%s%s",server->addr,fname); - if((remote=ftpGetURL(url,ftp_user,ftp_pass,ftp_verbose,&ret1))==NULL) { + if((remote=http_get_fd(url,&flen,NULL))<0) { /* retry without machine type in name */ SAFECOPY(str,fname); sprintf(fname,dist->files[i],params.name.sysname); sprintf(url,"%s%s",server->addr,fname); if(stricmp(str,fname)==0 /* no change in name? */ - || (remote=ftpGetURL(url,ftp_user,ftp_pass,ftp_verbose,&ret1))==NULL) { + || (remote=http_get_fd(url,&flen,NULL))<0) { /* retry using default system-type for system name */ sprintf(fname,dist->files[i],DEFAULT_SYSTYPE); - if((remote=ftpGetURL(url,ftp_user,ftp_pass,ftp_verbose,&ret1))==NULL) { + if((remote=http_get_fd(url,&flen,http_error))<0) { printf("Cannot get distribution file %s!\n",fname); - printf("%s\n- %s\n",url,ftpErrString(ret1)); + printf("%s\n- %s\n",url,http_error); close(fout); unlink(dstfname); exit(EXIT_FAILURE); } } } - if((flen=ftpGetSize(remote,fname))<1) { - printf("Cannot get size of distribution file: %s!\n",fname); - close(fout); - unlink(dstfname); - exit(EXIT_FAILURE); - } printf("Downloading %s ",url); offset=0; - while((ret1=remote->read(remote,buf,sizeof(buf)))>0) { + while((ret1=read(remote,buf,sizeof(buf)))>=0) { ret2=write(fout,buf,ret1); if(ret2!=ret1) { printf("\n!ERROR %d writing to %s\n",errno,dstfname); @@ -655,7 +645,6 @@ void install_sbbs(dist_t *dist,struct server_ent_t *server) { dist_t ** get_distlist(void) { - int ret1,ret2,ret3,ret4,ret5; int i; char in_line[256]; dist_t **dist; @@ -666,9 +655,14 @@ get_distlist(void) int s=0; char* p; char* tp; - ftp_FILE *list=NULL; + int list=-1; char sep[2]={'\t',0}; char str[1024]; + char error1[128]; + char error2[128]; + char error3[128]; + char error4[128]; + char error5[128]; if((dist=(dist_t **)MALLOC(sizeof(void *)*MAX_DISTRIBUTIONS))==NULL) allocfail(sizeof(void *)*MAX_DISTRIBUTIONS); @@ -702,13 +696,13 @@ get_distlist(void) strcpy(file[f++],str); } - if(ftp_distlist) { + if(http_distlist) { uifc.pop("Getting distributions"); - if((list=ftpGetURL(DIST_LIST_URL1,ftp_user,ftp_pass,ftp_verbose,&ret1))==NULL - && (list=ftpGetURL(DIST_LIST_URL2,ftp_user,ftp_pass,ftp_verbose,&ret2))==NULL - && (list=ftpGetURL(DIST_LIST_URL3,ftp_user,ftp_pass,ftp_verbose,&ret3))==NULL - && (list=ftpGetURL(DIST_LIST_URL4,ftp_user,ftp_pass,ftp_verbose,&ret4))==NULL - && (list=ftpGetURL(DIST_LIST_URL5,ftp_user,ftp_pass,ftp_verbose,&ret5))==NULL + if((list=http_get_fd(DIST_LIST_URL1,NULL,error1))<0 + && (list=http_get_fd(DIST_LIST_URL2,NULL,error2))<0 + && (list=http_get_fd(DIST_LIST_URL3,NULL,error3))<0 + && (list=http_get_fd(DIST_LIST_URL4,NULL,error4))<0 + && (list=http_get_fd(DIST_LIST_URL5,NULL,error5))<0 && r==0) { uifc.pop(NULL); uifc.bail(); @@ -718,17 +712,17 @@ get_distlist(void) "%s\n- %s\n" "%s\n- %s\n" "%s\n- %s\n" - ,DIST_LIST_URL1,ftpErrString(ret1) - ,DIST_LIST_URL2,ftpErrString(ret2) - ,DIST_LIST_URL3,ftpErrString(ret3) - ,DIST_LIST_URL4,ftpErrString(ret4) - ,DIST_LIST_URL5,ftpErrString(ret5) + ,DIST_LIST_URL1,error1 + ,DIST_LIST_URL2,error2 + ,DIST_LIST_URL3,error3 + ,DIST_LIST_URL4,error4 + ,DIST_LIST_URL5,error5 ); exit(EXIT_FAILURE); } } - while(list!=NULL && (list->gets(in_line,sizeof(in_line),list))!=NULL) { + while(list>=0 && (sockreadline(list,in_line,sizeof(in_line),NULL)>=0)) { i=strlen(in_line); while(i>0 && in_line[i]<=' ') in_line[i--]=0; -- GitLab