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