summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pttbbs/include/cmsys.h9
-rw-r--r--pttbbs/include/convert.h12
-rw-r--r--pttbbs/include/proto.h4
-rw-r--r--pttbbs/mbbsd/convert.c165
-rw-r--r--pttbbs/mbbsd/io.c183
-rw-r--r--pttbbs/mbbsd/mbbsd.c22
-rw-r--r--pttbbs/pttbbs.mk9
7 files changed, 155 insertions, 249 deletions
diff --git a/pttbbs/include/cmsys.h b/pttbbs/include/cmsys.h
index f80bbd8d..28b1bd3c 100644
--- a/pttbbs/include/cmsys.h
+++ b/pttbbs/include/cmsys.h
@@ -294,4 +294,13 @@ extern void telnet_ctx_set_ttype_arg (TelnetCtx *ctx, void *arg);
extern ssize_t telnet_process (TelnetCtx *ctx, unsigned char *buf, ssize_t size);
+/* utf8.c */
+extern int ucs2utf(uint16_t ucs2, uint8_t *utf8);
+extern int utf2ucs(uint8_t *utf8, uint16_t *pucs);
+
+/* big5.c */
+extern const uint16_t const b2u_table[];
+extern const uint16_t const u2b_table[];
+
+
#endif
diff --git a/pttbbs/include/convert.h b/pttbbs/include/convert.h
index 73e6192b..835cf28b 100644
--- a/pttbbs/include/convert.h
+++ b/pttbbs/include/convert.h
@@ -7,18 +7,14 @@
enum ConvertMode {
CONV_NORMAL,
- CONV_GB,
- CONV_UTF8
+ CONV_UTF8,
};
-typedef ssize_t (*read_write_type)(int, void *, size_t);
-typedef ssize_t (*convert_type)(void *, ssize_t);
-
-extern read_write_type write_type;
-extern read_write_type read_type;
-extern convert_type input_type;
+extern int (*convert_write)(VBUF *v, char c);
+extern int (*convert_read)(VBUF *v, const void* buf, size_t len);
extern void init_convert(void);
+extern void set_converting_type(int which);
#endif // CONVERT
#endif // _BBS_CONVERT_H
diff --git a/pttbbs/include/proto.h b/pttbbs/include/proto.h
index f335c1b7..9afcbe71 100644
--- a/pttbbs/include/proto.h
+++ b/pttbbs/include/proto.h
@@ -281,10 +281,8 @@ ChessInfo* gomoku_replay(FILE* fp);
/* guess */
int guess_main(void);
-/* convert */
-void set_converting_type(int which);
-
/* io */
+int init_io();
// output
int ochar(int c);
diff --git a/pttbbs/mbbsd/convert.c b/pttbbs/mbbsd/convert.c
index 611e54ac..15b62ec1 100644
--- a/pttbbs/mbbsd/convert.c
+++ b/pttbbs/mbbsd/convert.c
@@ -2,106 +2,72 @@
#include "bbs.h"
#ifdef CONVERT
+int (*convert_write)(VBUF *v, char c) = vbuf_add;
+int (*convert_read)(VBUF *v, const void *buf, size_t len) = vbuf_putblk;
-#ifdef CONVERT
-extern void big2gb_init(void*);
-extern void gb2big_init(void*);
-extern void big2uni_init(void*);
-extern void uni2big_init(void*);
-#endif
-
-extern unsigned char *gb2big(unsigned char *, int *, int);
-extern unsigned char *big2gb(unsigned char *, int *, int);
-extern unsigned char *utf8_uni(unsigned char *, int *, int);
-extern unsigned char *uni_utf8(unsigned char *, int *, int);
-extern unsigned char *uni2big(unsigned char *, int *, int);
-extern unsigned char *big2uni(unsigned char *, int *, int);
-
-static ssize_t
-gb_input(void *buf, ssize_t icount)
-{
- /* is sizeof(ssize_t) == sizeof(int)? not sure */
- int ic = (int) icount;
- gb2big((unsigned char *)buf, &ic, 0);
- return (ssize_t)ic;
-}
-
-static ssize_t
-gb_read(int fd, void *buf, size_t count)
-{
- ssize_t icount = read(fd, buf, count);
- if (icount > 0)
- icount = gb_input(buf, icount);
- return icount;
-}
-
-static ssize_t
-gb_write(int fd, void *buf, size_t count)
-{
- int icount = (int)count;
- big2gb((unsigned char *)buf, &icount, 0);
- if(icount > 0)
- return write(fd, buf, (size_t)icount);
- else
- return count; /* fake */
-}
+int
+convert_write_utf8(VBUF *v, char c) {
+ static char trail[2] = {0};
+ static uint8_t utf8[4];
-static ssize_t
-utf8_input (void *buf, ssize_t icount)
-{
- /* is sizeof(ssize_t) == sizeof(int)? not sure */
- int ic = (int) icount;
- utf8_uni(buf, &ic, 0);
- uni2big(buf, &ic, 0);
- return (ssize_t)ic;
-}
+ // trail must be little endian.
+ if (trail[1]) {
+ trail[0] = c;
+ int len, i;
+ uint16_t ucs = b2u_table[*(uint16_t*)trail];
-static ssize_t
-utf8_read(int fd, void *buf, size_t count)
-{
- ssize_t icount = read(fd, buf, count);
- if (icount > 0)
- icount = utf8_input(buf, icount);
- return icount;
-}
+ len = ucs2utf(ucs, utf8);
+ utf8[len] = 0;
-static ssize_t
-utf8_write(int fd, void *buf, size_t count)
-{
- int icount = (int)count;
- static unsigned char *mybuf = NULL;
- static int cmybuf = 0;
+ // assert(len > 0 && len < 4);
+ for (i = 0; i < len; i++)
+ vbuf_add(v, utf8[i]);
- /* utf8 output is a special case because
- * we need larger buffer which can be
- * tripple or more in size.
- * Current implementation uses 128 for each block.
- */
+ trail[1] = 0;
+ return 1;
+ }
- if(cmybuf < count * 4) {
- cmybuf = (count*4+0x80) & (~0x7f) ;
- mybuf = (unsigned char*) realloc (mybuf, cmybuf);
+ if (isascii(c)) {
+ vbuf_add(v, c);
+ return 1;
}
- memcpy(mybuf, buf, count);
- big2uni(mybuf, &icount, 0);
- uni_utf8(mybuf, &icount, 0);
- if(icount > 0)
- return write(fd, mybuf, (size_t)icount);
- else
- return count; /* fake */
+ trail[1] = c;
+ return 0;
}
-static ssize_t
-norm_input(void *buf, ssize_t icount)
-{
- return icount;
+int convert_read_utf8(VBUF *v, const void *buf, size_t len) {
+ static uint8_t trail[6];
+ static int ctrail = 0;
+ uint16_t ucs;
+ uint8_t c;
+ int written = 0;
+
+ while (len-- > 0) {
+ c = *(uint8_t*)buf ++;
+ if (ctrail) {
+ trail[ctrail++] = c;
+ // TODO this may create invalid chars.
+ if (utf2ucs(trail, &ucs) > ctrail)
+ continue;
+ ucs = u2b_table[ucs];
+ vbuf_add(v, ucs >> 8);
+ vbuf_add(v, ucs & 0xFF);
+ written += 2;
+ ctrail = 0;
+ continue;
+ }
+
+ if (isascii(c)) {
+ vbuf_add(v, c);
+ written++;
+ } else {
+ trail[0] = c;
+ ctrail = 1;
+ }
+ }
+ return written;
}
-/* global function pointers */
-read_write_type write_type = (read_write_type)write;
-read_write_type read_type = read;
-convert_type input_type = norm_input;
-
// enable this in case some day we want to detect
// current type. but right now disable for less memory cost
// int bbs_convert_type = CONV_NORMAL;
@@ -109,30 +75,17 @@ convert_type input_type = norm_input;
void set_converting_type(int which)
{
if (which == CONV_NORMAL) {
- read_type = read;
- write_type = (read_write_type)write;
- /* for speed up, NULL is better.. */
- input_type = NULL; /* norm_input; */
- }
- else if (which == CONV_GB) {
- read_type = gb_read;
- write_type = gb_write;
- input_type = gb_input;
+ convert_read = vbuf_putblk;
+ convert_write = vbuf_add;
}
else if (which == CONV_UTF8) {
- read_type = utf8_read;
- write_type = utf8_write;
- input_type = utf8_input;
+ convert_read = convert_read_utf8;
+ convert_write = convert_write_utf8;
}
- // bbs_convert_type = which;
}
void init_convert()
{
- big2gb_init(NULL);
- gb2big_init(NULL);
- big2uni_init(NULL);
- uni2big_init(NULL);
}
#endif
diff --git a/pttbbs/mbbsd/io.c b/pttbbs/mbbsd/io.c
index 75de3537..a3e2578a 100644
--- a/pttbbs/mbbsd/io.c
+++ b/pttbbs/mbbsd/io.c
@@ -6,29 +6,20 @@
#define OBUFSIZE 3072
#define IBUFSIZE 128
-/* realXbuf is Xbuf+3 because hz convert library requires buf[-2]. */
-#define CVTGAP (3)
+// Size of space to be preserved, usually for char convertion.
+#define BUF_PRESERVE_SPACE_SIZE (4)
#ifdef DEBUG
#define register
+#define inline
// #define DBG_OUTRPT
#endif
-static unsigned char real_outbuf[OBUFSIZE + CVTGAP*2] = " ";
-static unsigned char real_inbuf [IBUFSIZE + CVTGAP*2] = " ";
+static VBUF vout, *pvout = &vout, vin, *pvin = &vin;
// we've seen such pattern - make it accessible for movie mode.
#define CLIENT_ANTI_IDLE_STR ESC_STR "OA" ESC_STR "OB"
-// use defines instead - it is discovered that sometimes the input/output buffer was overflow,
-// without knowing why.
-// static unsigned char *outbuf = real_outbuf + 3, *inbuf = real_inbuf + 3;
-#define inbuf (real_inbuf +CVTGAP)
-#define outbuf (real_outbuf+CVTGAP)
-
-static int obufsize = 0;
-static int ibufsize = 0, icurrchar = 0;
-
#ifdef DBG_OUTRPT
// output counter
static unsigned long szTotalOutput = 0, szLastOutput = 0;
@@ -48,35 +39,6 @@ static unsigned char fakeEscFilter(unsigned char c)
#endif // DBG_OUTRPT
/* ----------------------------------------------------- */
-/* convert routines */
-/* ----------------------------------------------------- */
-#ifdef CONVERT
-
-static inline ssize_t input_wrapper(void *buf, ssize_t count) {
- /* input_wrapper is a special case.
- * because we may do nothing,
- * a if-branch is better than a function-pointer call.
- */
- if(input_type)
- return (*input_type)(buf, count);
- else
- return count;
-}
-
-static inline int read_wrapper(int fd, void *buf, size_t count) {
- return (*read_type)(fd, buf, count);
-}
-
-static inline int write_wrapper(int fd, void *buf, size_t count) {
- return (*write_type)(fd, buf, count);
-}
-#else
-#define write_wrapper write
-#define read_wrapper read
-// #define input_wrapper(buf,count) count
-#endif
-
-/* ----------------------------------------------------- */
/* debug reporting */
/* ----------------------------------------------------- */
@@ -115,6 +77,15 @@ debug_print_input_buffer(char *s, size_t len)
move_ansi(y, x);
}
#endif
+/* ----------------------------------------------------- */
+/* Input Output System */
+/* ----------------------------------------------------- */
+int
+init_io() {
+ vbuf_new(pvout, OBUFSIZE + BUF_PRESERVE_SPACE_SIZE);
+ vbuf_new(pvin, IBUFSIZE + BUF_PRESERVE_SPACE_SIZE);
+ return 0;
+}
/* ----------------------------------------------------- */
/* output routines */
@@ -122,14 +93,12 @@ debug_print_input_buffer(char *s, size_t len)
void
oflush(void)
{
- if (obufsize) {
- STATINC(STAT_SYSWRITESOCKET);
- write_wrapper(1, outbuf, obufsize);
- obufsize = 0;
+ if (!vbuf_is_empty(pvout)) {
+ STATINC(STAT_SYSWRITESOCKET);
+ vbuf_write(pvout, 1, VBUF_RWSZ_ALL);
}
#ifdef DBG_OUTRPT
- // if (0)
{
static char xbuf[128];
sprintf(xbuf, ESC_STR "[s" ESC_STR "[H" " [%lu/%lu] " ESC_STR "[u",
@@ -144,48 +113,32 @@ oflush(void)
// fsync(1);
}
-void
+inline void
output(const char *s, int len)
{
-#ifdef DBG_OUTRPT
- int i = 0;
- if (fakeEscape)
- for (i = 0; i < obufsize; i++)
- outbuf[i] = fakeEscFilter(outbuf[i]);
-
- szTotalOutput += len;
- szLastOutput += len;
-#endif // DBG_OUTRPT
-
- /* Invalid if len >= OBUFSIZE */
- assert(len<OBUFSIZE);
-
- if (obufsize + len > OBUFSIZE) {
- STATINC(STAT_SYSWRITESOCKET);
- write_wrapper(1, outbuf, obufsize);
- obufsize = 0;
- }
- memcpy(outbuf + obufsize, s, len);
- obufsize += len;
+ while (len-- > 0)
+ ochar(*s++);
}
int
ochar(int c)
{
-
#ifdef DBG_OUTRPT
+ // TODO we can support converted output in future.
c = fakeEscFilter(c);
szTotalOutput ++;
szLastOutput ++;
#endif // DBG_OUTRPT
- if (obufsize > OBUFSIZE - 1) {
- STATINC(STAT_SYSWRITESOCKET);
- /* suppose one byte data doesn't need to be converted. */
- write(1, outbuf, obufsize);
- obufsize = 0;
- }
- outbuf[obufsize++] = c;
+ if (vbuf_is_full(pvout) || vbuf_size(pvout) >= OBUFSIZE)
+ oflush();
+
+#ifdef CONVERT
+ convert_write(pvout, c);
+#else
+ vbuf_add(pvout, c);
+#endif
+
return 0;
}
@@ -388,45 +341,47 @@ add_io(int fd, int timeout)
inline int
num_in_buf(void)
{
- if (ibufsize <= icurrchar)
- return 0;
- return ibufsize - icurrchar;
+ return vbuf_size(pvin);
}
static inline int
input_isfull(void)
{
- return ibufsize >= IBUFSIZE;
+ return vbuf_size(pvin) >= IBUFSIZE;
}
static inline void
drop_input(void)
{
- icurrchar = ibufsize = 0;
+ vbuf_clear(pvin);
}
+/* returns:
+ * >0 if read something
+ * =0 if nothing read
+ * <0 if need to read again
+ */
static inline ssize_t
-wrapped_tty_read(unsigned char *buf, size_t max)
-{
+read_vin() {
+ unsigned char buf[IBUFSIZE];
/* tty_read will handle abort_bbs.
* len <= 0: read more */
- ssize_t len = tty_read(buf, max);
+ ssize_t len = tty_read(buf, vbuf_space(pvin));
if (len <= 0)
- return len;
+ return len;
// apply additional converts
#ifdef DBCSAWARE
if (ISDBCSAWARE() && HasUserFlag(UF_DBCS_DROP_REPEAT))
len = vtkbd_ignore_dbcs_evil_repeats(buf, len);
+ if (len <= 0)
+ return len;
#endif
-#ifdef CONVERT
- len = input_wrapper(inbuf, len);
-#endif
-#ifdef DBG_OUTRPT
+#ifdef DBG_OUTRPT
#if 1
if (len > 0)
- debug_print_input_buffer((char*)inbuf, len);
+ debug_print_input_buffer(buf, len);
#else
{
static char xbuf[128];
@@ -435,15 +390,21 @@ wrapped_tty_read(unsigned char *buf, size_t max)
write(1, xbuf, strlen(xbuf));
}
#endif
-
#endif // DBG_OUTRPT
+
+ // len = 1 if success
+#ifdef CONVERT
+ len = convert_read(pvin, buf, len);
+#else
+ len = vbuf_putblk(pvin, buf, len);
+#endif
return len;
}
/*
* dogetch() is not reentrant-safe. SIGUSR[12] might happen at any time, and
- * dogetch() might be called again, and then ibufsize/icurrchar/inbuf might
- * be inconsistent. We try to not segfault here...
+ * dogetch() might be called again, and then input buffer state may be
+ * inconsistent. We try to not segfault here...
*/
static int
@@ -451,8 +412,8 @@ dogetch(void)
{
ssize_t len;
static time4_t lastact;
- if (ibufsize <= icurrchar) {
+ while (vbuf_is_empty(pvin)) {
refresh();
if (i_newfd) {
@@ -498,11 +459,9 @@ dogetch(void)
STATINC(STAT_SYSREADSOCKET);
do {
- len = wrapped_tty_read(inbuf, IBUFSIZE);
+ len = read_vin();
+ // warning: len is 1/0/-1 now, not real length.
} while (len <= 0);
-
- ibufsize = len;
- icurrchar = 0;
}
if (currutmp) {
@@ -515,15 +474,15 @@ dogetch(void)
}
// see vtkbd.c for CR/LF Rules
+ assert(!vbuf_is_empty(pvin));
{
- unsigned char c = (unsigned char) inbuf[icurrchar++];
-
+ unsigned char c = vbuf_pop(pvin);
// CR LF are treated as one.
if (c == KEY_CR)
{
- // peak next character.
- if (icurrchar < ibufsize && inbuf[icurrchar] == KEY_LF)
- icurrchar ++;
+ // peak next character. (peek return EOF for empty)
+ if (vbuf_peek(pvin) == KEY_LF)
+ vbuf_pop(pvin);
return KEY_ENTER;
}
else if (c == KEY_LF)
@@ -662,22 +621,16 @@ wait_input(float f, int bIgnoreBuf)
inline int
peek_input(float f, int c)
{
- int i = 0;
assert (c == EOF || (c > 0 && c < ' ')); // only ^x keys are safe to be detected.
// other keys may fall into escape sequence.
- if (wait_input(f, 1) && (IBUFSIZE > ibufsize))
- {
- int len = wrapped_tty_read(inbuf + ibufsize, IBUFSIZE - ibufsize);
- if (len > 0)
- ibufsize += len;
- }
+ if (wait_input(f, 1) && vbuf_size(pvin) < IBUFSIZE)
+ read_vin();
+
if (c == EOF)
return 0;
- // scan inbuf
- for (i = icurrchar; i < ibufsize && inbuf[i] != c; i++) ;
- return i < ibufsize ? 1 : 0;
+ return vbuf_strchr(pvin, c) >= 0 ? 1 : 0;
}
@@ -705,12 +658,12 @@ inline void
vkey_purge(void)
{
int max_try = 64;
- unsigned char garbage[4096];
drop_input();
STATINC(STAT_SYSREADSOCKET);
while (wait_input(0.01, 1) && max_try-- > 0) {
- wrapped_tty_read(garbage, sizeof(garbage));
+ read_vin();
+ drop_input();
}
}
diff --git a/pttbbs/mbbsd/mbbsd.c b/pttbbs/mbbsd/mbbsd.c
index 45bfdaff..b12dbc07 100644
--- a/pttbbs/mbbsd/mbbsd.c
+++ b/pttbbs/mbbsd/mbbsd.c
@@ -795,16 +795,15 @@ login_query(char *ruid)
#ifdef CONVERT
/* switch to gb mode if uid end with '.' */
len = strlen(uid);
- if (uid[0] && uid[len - 1] == '.') {
- set_converting_type(CONV_GB);
- uid[len - 1] = 0;
- redrawwin();
- }
- else if (uid[0] && uid[len - 1] == ',') {
+ if (uid[0] && uid[len - 1] == ',') {
set_converting_type(CONV_UTF8);
uid[len - 1] = 0;
redrawwin();
}
+ else if (uid[0] && uid[len - 1] == '.') {
+ outs("Sorry, GB encoding is not supported anymore. Please use UTF-8 (id,)");
+ continue;
+ }
else if (len >= IDLEN + 1)
uid[IDLEN] = 0;
#endif
@@ -1532,6 +1531,10 @@ static int check_banip (char *host);
static void init(void)
{
start_time = time(NULL);
+ init_io();
+#ifdef CONVERT
+ init_convert();
+#endif
/* avoid SIGPIPE */
Signal(SIGPIPE, SIG_IGN);
@@ -1552,9 +1555,6 @@ static void init(void)
mallopt (M_TOP_PAD, MY__TOP_PAD);
#endif
-#ifdef CONVERT
- init_convert();
-#endif
}
@@ -1578,7 +1578,7 @@ static void usage(char *argv0)
"\n"
"flags\n"
"\t-t type terminal mode, telnet | tty\n"
- "\t-e encoding encoding (default big5), big5 | gb | utf8\n"
+ "\t-e encoding encoding (default big5), big5 | utf8\n"
"\n"
"testing flags\n"
"\t-F don't fork\n"
@@ -1709,8 +1709,6 @@ bool parse_argv(int argc, char *argv[], struct ProgramOption *option)
#ifdef CONVERT
if (strcmp(optarg, "big5") == 0) {
set_converting_type(CONV_NORMAL);
- } else if (strcmp(optarg, "gb") == 0) {
- set_converting_type(CONV_GB);
} else if (strcmp(optarg, "utf8") == 0) {
set_converting_type(CONV_UTF8);
} else {
diff --git a/pttbbs/pttbbs.mk b/pttbbs/pttbbs.mk
index b3aef2c4..90c1124e 100644
--- a/pttbbs/pttbbs.mk
+++ b/pttbbs/pttbbs.mk
@@ -3,12 +3,14 @@
BBSHOME?= $(HOME)
BBSHOME?= /home/bbs
+WITH_PFTERM=1
+
SRCROOT?= .
OSTYPE!= uname
-CC:= gcc
-CXX:= g++
+#CC:= clang -Qunused-arguments
+#CXX:= clang -Qunused-arguments
CCACHE!= which ccache|sed -e 's/^.*\///'
WANTS_CONVERT!= sh -c 'grep "^\#define CONVERT" $(SRCROOT)/pttbbs.conf || echo NO'
@@ -20,9 +22,6 @@ CXX:= ccache $(CXX)
PTT_CFLAGS:= -W -Wall -Wunused -pipe -DBBSHOME='"$(BBSHOME)"' -I$(SRCROOT)/include
PTT_CXXFLAGS:= -W -Wall -Wunused -pipe -DBBSHOME='"$(BBSHOME)"' -I$(SRCROOT)/include
PTT_LDFLAGS:= -Wl,--as-needed
-.if $(WANTS_CONVERT) != "NO"
-PTT_LDLIBS+= -lhz
-.endif
# enable assert()
#PTT_CFLAGS+= -DNDEBUG