From 8c9f4cf302a6a47f0e90f6a3385c9ba34c1c9403 Mon Sep 17 00:00:00 2001 From: deuce <> Date: Fri, 6 Feb 2009 05:32:12 +0000 Subject: [PATCH] Add xpdoor, a cross-platform doorkit which supports the conio API. --- src/xpdoor/GNUmakefile | 20 ++++ src/xpdoor/example.c | 9 ++ src/xpdoor/objects.mk | 8 ++ src/xpdoor/targets.mk | 8 ++ src/xpdoor/xpdoor.c | 259 +++++++++++++++++++++++++++++++++++++++++ src/xpdoor/xpdoor.h | 128 ++++++++++++++++++++ 6 files changed, 432 insertions(+) create mode 100644 src/xpdoor/GNUmakefile create mode 100644 src/xpdoor/example.c create mode 100644 src/xpdoor/objects.mk create mode 100644 src/xpdoor/targets.mk create mode 100644 src/xpdoor/xpdoor.c create mode 100644 src/xpdoor/xpdoor.h diff --git a/src/xpdoor/GNUmakefile b/src/xpdoor/GNUmakefile new file mode 100644 index 0000000000..54e4bebfbb --- /dev/null +++ b/src/xpdoor/GNUmakefile @@ -0,0 +1,20 @@ +SRC_ROOT := .. +include ${SRC_ROOT}/build/Common.gmake + +CFLAGS += $(UIFC-MT_CFLAGS) $(CIOLIB-MT_CFLAGS) $(XPDEV-MT_CFLAGS) -I../sbbs3 -I../smblib -I../comio +LDFLAGS += $(UIFC-MT_LDFLAGS) $(CIOLIB-MT_LDFLAGS) $(XPDEV-MT_LDFLAGS) +EXTRA_LIBS += $(XPDOOR) + +OBJS += $(MTOBJODIR)$(DIRSEP)comio_nix$(OFILE) + +vpath %.c ../sbbs3 ../uifc ../conio ../comio + +$(XPDOOR): $(LIBODIR) $(OBJS) $(BUILD_DEPENDS) + @echo Creating $@ + $(QUIET)$(AR) rc $@ $(OBJS) + $(QUIET)$(RANLIB) $@ + +$(EXAMPLE): $(XPDOOR) $(EXEODIR) $(EX_OBJS) $(BUILD_DEPENDS) + @echo Linking $@ + ${QUIET}$(CC) $(LDFLAGS) $(MT_LDFLAGS) $(EX_OBJS) -o $@ $(XPDOOR) $(UIFC-MT_LIBS) $(CIOLIB-MT_LIBS) $(WXLIBS) $(XPDEV-MT_LIBS) + diff --git a/src/xpdoor/example.c b/src/xpdoor/example.c new file mode 100644 index 0000000000..d81b47831a --- /dev/null +++ b/src/xpdoor/example.c @@ -0,0 +1,9 @@ +#include "xpdoor.h" + +int main(int argc, char **argv) +{ + xpd_parse_cmdline(argc, argv); + xpd_parse_dropfile(); + xpd_init(); + return(1); +} diff --git a/src/xpdoor/objects.mk b/src/xpdoor/objects.mk new file mode 100644 index 0000000000..85cccfe6a9 --- /dev/null +++ b/src/xpdoor/objects.mk @@ -0,0 +1,8 @@ +OBJS = \ + $(MTOBJODIR)$(DIRSEP)comio$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)telnet$(OFILE) \ + $(MTOBJODIR)$(DIRSEP)xpdoor$(OFILE) + +EX_OBJS = \ + $(MTOBJODIR)$(DIRSEP)example$(OFILE) + diff --git a/src/xpdoor/targets.mk b/src/xpdoor/targets.mk new file mode 100644 index 0000000000..049c6e0646 --- /dev/null +++ b/src/xpdoor/targets.mk @@ -0,0 +1,8 @@ +XPDOOR = $(LIBODIR)$(DIRSEP)xpdoor$(LIBFILE) +EXAMPLE = $(EXEODIR)$(DIRSEP)example$(EXEFILE) + +all: xpdev-mt ciolib-mt uifc-mt $(MTOBJODIR) $(LIBODIR) $(XPDOOR) $(EXEODIR) $(EXAMPLE) + +$(XPDOOR): $(XPDEV-MT_LIB) $(CIOLIB-MT) $(UIFCLIB-MT) + +$(EXAMPLE): $(XPDOOR) diff --git a/src/xpdoor/xpdoor.c b/src/xpdoor/xpdoor.c new file mode 100644 index 0000000000..d7ed48c4fa --- /dev/null +++ b/src/xpdoor/xpdoor.c @@ -0,0 +1,259 @@ +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +#include "xpdoor.h" +#include <ansi_cio.h> +#include <comio.h> +#include <genwrap.h> +#include <cterm.h> +#include <dirwrap.h> + +struct xpd_info xpd_info; + +static int xpd_ansi_readbyte_cb(void) +{ + unsigned char ch; + + switch(xpd_info.io_type) { + case XPD_IO_STDIO: + return(ansi_readbyte_cb()); + case XPD_IO_COM: + if(!comReadByte(xpd_info.io.com, &ch)) { + if(comGetModemStatus(xpd_info.io.com)&COM_DCD==0) + return(-2); + return(-1); + } + return(ch); + case XPD_IO_SOCKET: + { + BOOL can_read; + + if(!socket_check(xpd_info.io.sock, &can_read, NULL, 1000)) + return(-2); + if(can_read) { + if(recv(xpd_info.io.sock, &ch, 1, 0)==1) + return(ch); + return(-2); + } + return(-1); + } + case XPD_IO_TELNET: + { + BOOL can_read; + + // TODO: Proper telnet stuff... + if(!socket_check(xpd_info.io.telnet.sock, &can_read, NULL, 1000)) + return(-2); + if(can_read) { + if(recv(xpd_info.io.telnet.sock, &ch, 1, 0)==1) + return(ch); + return(-2); + } + return(-1); + } + } + return(-2); +} + +static int xpd_ansi_writebyte_cb(unsigned char ch) +{ + switch(xpd_info.io_type) { + case XPD_IO_STDIO: + return(ansi_writebyte_cb(ch)); + case XPD_IO_COM: + if(comWriteByte(xpd_info.io.com, ch)) + return(1); + return(-1); + case XPD_IO_SOCKET: + { + BOOL can_write; + + if(!socket_check(xpd_info.io.sock, NULL, &can_write, 580000)) + return(-2); + if(can_write) { + if(send(xpd_info.io.sock, &ch, 1, 0)==1) + return(ch); + return(-2); + } + return(-1); + } + case XPD_IO_TELNET: + { + BOOL can_write; + + // TODO: Proper telnet stuff... + if(!socket_check(xpd_info.io.sock, NULL, &can_write, 580000)) + return(-2); + if(can_write) { + if(send(xpd_info.io.sock, &ch, 1, 0)==1) + return(ch); + return(-2); + } + return(-1); + } + } + return(-2); +} + +static int xpd_ansi_initio_cb(void) +{ + switch(xpd_info.io_type) { + case XPD_IO_STDIO: + return(ansi_initio_cb()); + case XPD_IO_COM: + case XPD_IO_SOCKET: + case XPD_IO_TELNET: + // TODO: Init stuff... (enable Nagle, Disable non-blocking, etc) + break; + } + return(0); +} + +static int xpd_ansi_writestr_cb(unsigned char *str, size_t len) +{ + int i; + + // TODO: Quit being silly. + switch(xpd_info.io_type) { + case XPD_IO_STDIO: + return(ansi_writestr_cb(str,len)); + case XPD_IO_COM: + case XPD_IO_SOCKET: + case XPD_IO_TELNET: + for(i=0; i<len; i++) { + if(xpd_ansi_writebyte_cb((unsigned char)str[i])<0) + return(-2); + } + } + return(-2); +} + +void xpd_parse_cmdline(int argc, char **argv) +{ + int i; + + for(i=0; i<argc; i++) { + if(strncmp(argv[i],"--io-type=",10)) { + if(stricmp(argv[i]+10, "stdio")) + xpd_info.io_type=XPD_IO_STDIO; + else if(stricmp(argv[i]+10, "com")) + xpd_info.io_type=XPD_IO_COM; + else if(stricmp(argv[i]+10, "socket")) + xpd_info.io_type=XPD_IO_SOCKET; + else if(stricmp(argv[i]+10, "telnet")) + xpd_info.io_type=XPD_IO_TELNET; + else if(stricmp(argv[i]+10, "local")) + xpd_info.io_type=XPD_IO_LOCAL; + } + } +} + +int xpd_init() +{ + struct text_info ti; + + if(xpd_info.io_type == XPD_IO_LOCAL) { + if(initciolib(CIOLIB_MODE_AUTO)) + return(-1); + } + else { + ciolib_ansi_readbyte_cb=xpd_ansi_readbyte_cb; + ciolib_ansi_writebyte_cb=xpd_ansi_writebyte_cb; + ciolib_ansi_initio_cb=xpd_ansi_initio_cb; + ciolib_ansi_writestr_cb=xpd_ansi_writestr_cb; + if(initciolib(CIOLIB_MODE_ANSI)) + return(-1); + ansi_ciolib_setdoorway(1); + } + gettextinfo(&ti); + cterm_init(ti.screenheight, ti.screenwidth, 1, 1, 0, NULL, CTERM_EMULATION_ANSI_BBS); +} + +#define GETBUF() if(fgets(buf,sizeof(buf),df)==NULL) goto done_parsing +#define GETIBUF(x) if(fgets(buf,sizeof(buf),df)==NULL) goto done_parsing; x = atoi(buf) +#define GETSBUF(x) if(fgets(buf,sizeof(buf),df)==NULL) goto done_parsing; x = strdup(buf) +#define GETDBUF(x) if(fgets(buf,sizeof(buf),df)==NULL) goto done_parsing; { \ + int m,d,y; \ + char *p; \ + p=strtok(buf,"/-"); \ + if(p) { \ + m=strtol(buf,NULL,10); p=strtok(NULL, "/-"); \ + if(p) { \ + d=strtol(buf,NULL,10); p=strtok(NULL, "/-"); \ + if(p) { \ + y=strtol(buf,NULL,10); y+=(y<100?2000:1900); if(y > xpDateTime_now().date.year) y-=100; x = isoDate_create(y,m,d); \ + }}}} + +int xpd_parse_dropfile() +{ + FILE *df=NULL; + char *p; + char buf[1024]; + + if(xpd_info.drop.path==NULL) + goto error_return; + df=fopen(xpd_info.drop.path,"r"); + if(df==NULL) + goto error_return; + p=getfname(xpd_info.drop.path); + if(p==NULL) + goto error_return; + if(stricmp(p,"door.sys")) { + /* COM0:, COM1:, COM0:STDIO, COM0:SOCKET123 */ + GETBUF(); + if(strcmp(buf,"COM0:STDIO"==0)) { + xpd_info.io_type=XPD_IO_STDIO; + } + else if(strncmp(buf,"COM0:SOCKET",11)==0) { + xpd_info.io_type=XPD_IO_SOCKET; + xpd_info.io.sock=atoi(buf+11); + } + GETIBUF(xpd_info.drop.baud); + GETIBUF(xpd_info.drop.parity); + GETIBUF(xpd_info.drop.node); + GETBUF(); + GETBUF(); + GETBUF(); + GETBUF(); + GETSBUF(xpd_info.drop.user.full_name); + GETSBUF(xpd_info.drop.user.location); + GETSBUF(xpd_info.drop.user.home_phone); + GETSBUF(xpd_info.drop.user.work_phone); + GETSBUF(xpd_info.drop.user.password); + GETIBUF(xpd_info.drop.user.level); + GETIBUF(xpd_info.drop.user.times_on); + GETDBUF(xpd_info.drop.user.last_call_date); + } + +error_return: + if(df) + fclose(df); + return(-1); + +done_parsing: + if(ferror(df)) { + fclose(df); + return(-1); + } + if(feof(df)) { + fclose(df); + return(0); + } +} + +int xpd_rwrite(const char *data, int data_len) +{ + struct text_info ti; + /* Set up cterm to match conio */ + gettextinfo(&ti); + cterm.x=ti.winleft+ti.curx-1; + cterm.y=ti.wintop+ti.cury-1; + cterm.attr=ti.attribute; + cterm.quiet=TRUE; + /* Send data to cterm */ + cterm_write(data, data_len, NULL, 0, NULL); + /* Set conio to match cterm */ + gotoxy(cterm.x-ti.winleft+1, cterm.y-ti.winright+1); + textattr(cterm.attr); +} diff --git a/src/xpdoor/xpdoor.h b/src/xpdoor/xpdoor.h new file mode 100644 index 0000000000..aba52d7688 --- /dev/null +++ b/src/xpdoor/xpdoor.h @@ -0,0 +1,128 @@ +#ifndef _XPDOOR_H_ +#define _XPDOOR_H_ + +#include <comio.h> +#include <sockwrap.h> +#include <xpdatetime.h> +#include <ciolib.h> + +#define XPD_CP437_SUPPORTED (1<<0) +#define XPD_ANSI_SUPPORTED (1<<1) + +struct xpd_user_info { + char *full_name; + char *location; // AKA Calling From + char *home_phone; + char *work_phone; + char *password; + int level; + unsigned int times_on; + isoDate_t last_call_date; + unsigned int seconds_remaining; + int dflags; + int rows; + BOOL expert; + isoDate_t expiration; + int user_num; + char protocol; + int uploads; + int downloads; + int download_k_today; // KiB downloaded today + isoDate_t birthday; + char *alias; + isoTime_t call_time; + isoTime_t last_call_time; + int max_files_per_day; + int downloads_today; + int total_upload_k; + int total_download_k; + char *comment; + int total_doors; + int total_messages; + int credits; + BOOL female; + char *address; + char *postal; +}; + +struct xpd_system_info { + char *main_dir; + char *gen_dir; + char *sysop_name; + int default_attr; + char *name; + char *ctrl_dir; + char *data_dir; + int total_nodes; + char *exec_dir; + char *text_dir; + char *temp_dir; + char *qwk_id; +}; + +struct xpd_dropfile_info { + char *path; + int baud; + int parity; + int node; + int dte; + struct xpd_user_info user; + struct xpd_system_info sys; +}; + +enum io_type { + XPD_IO_STDIO + ,XPD_IO_COM + ,XPD_IO_SOCKET + ,XPD_IO_TELNET + ,XPD_IO_LOCAL +}; + +struct xpd_telnet_io { + SOCKET sock; + int cmdlen; + char cmd[64]; + char terminal[64]; + uchar local_option[0x100]; + uchar remote_option[0x100]; + uchar orig_local_option[0x100]; + BOOL orig_local_option_set; + uchar orig_remote_option[0x100]; + BOOL orig_remote_option_set; +}; + +struct xpd_info { + enum io_type io_type; + int io_flags; + union { + COM_HANDLE com; + SOCKET sock; + struct xpd_telnet_io telnet; + } io; + time_t end_time; /* -1 if there is no limit */ + struct xpd_dropfile_info drop; +}; + +extern struct xpd_info xpd_info; + +/* + * Parse command line + */ +void xpd_parse_cmdline(int argc, char **argv); + +/* + * Initialize + */ +int xpd_init(); + +/* + * Parse dropfile + */ +int xpd_parse_dropfile(void); + +/* + * Write "raw" (ie: May include ANSI sequences etc) + */ +int xpd_rwrite(const char *data, int data_len); + +#endif -- GitLab