diff --git a/src/comio/comio.c b/src/comio/comio.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b3f611013ff74b440259e083d0c4f18477a4a4f
--- /dev/null
+++ b/src/comio/comio.c
@@ -0,0 +1,72 @@
+/* comio.c */
+
+/* Synchronet Serial Communications I/O Library Common Functions */
+
+/* $Id$ */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright 2007 Rob Swindell - http://www.synchro.net/copyright.html		*
+ *																			*
+ * This library is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU Lesser General Public License		*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU Lesser General Public License for more details: lgpl.txt or	*
+ * http://www.fsf.org/copyleft/lesser.html									*
+ *																			*
+ * Anonymous FTP access to the most recent released source is available at	*
+ * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
+ *																			*
+ * Anonymous CVS access to the development source and modification history	*
+ * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
+ *     (just hit return, no password is necessary)							*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * You are encouraged to submit any modifications (preferably in Unix diff	*
+ * format) via e-mail to mods@synchro.net									*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
+
+#include "comio.h"
+#include "genwrap.h"	/* msclock */
+
+size_t comReadBuf(COM_HANDLE handle, char* buf, size_t buflen, const char* terminators, int timeout)
+{
+	BYTE		ch;
+	size_t		len=0;
+	msclock_t	start=msclock();
+
+	while(len < buflen) {
+		if(!comReadByte(handle, &ch)) {
+			if(msclock()-start >= timeout)
+				break;
+			YIELD();
+			continue;
+		}
+		if(len && terminators!=NULL && strchr(terminators, ch)!=NULL)
+			break;
+		buf[len++]=ch;
+	}
+
+	return len;
+}
+
+size_t comReadLine(COM_HANDLE handle, char* buf, size_t buflen, int timeout)
+{
+	size_t	len;
+
+	len=comReadBuf(handle, buf, buflen-1, "\n", timeout);
+
+	buf[len]=0;
+
+	return len;
+}
+
diff --git a/src/comio/comio.h b/src/comio/comio.h
index 833cdac998d85ca90e8a96334c164f5b99400f11..03f87889c6941f844c0895aa770a5a04ba702d12 100644
--- a/src/comio/comio.h
+++ b/src/comio/comio.h
@@ -80,7 +80,9 @@ int			comWriteBuf(COM_HANDLE, const BYTE*, size_t buflen);
 int			comWriteString(COM_HANDLE, const char*);
 BOOL		comReadByte(COM_HANDLE, BYTE*);
 size_t		comReadBuf(COM_HANDLE, char* buf, size_t buflen
-					   ,char terminator, int timeout /* in milliseconds */);
+					    ,const char* terminators, int timeout /* in milliseconds */);
+size_t		comReadLine(COM_HANDLE, char* buf, size_t buflen
+						,int timeout /* in milliseconds */);
 BOOL		comPurgeInput(COM_HANDLE);
 BOOL		comPurgeOutput(COM_HANDLE);
 
diff --git a/src/comio/comio_win32.c b/src/comio/comio_win32.c
index 0ac57d8781b55ed937d5314dfef496b86dc24327..2324d8529838e63e427292e29e773ed29ac574b5 100644
--- a/src/comio/comio_win32.c
+++ b/src/comio/comio_win32.c
@@ -1,4 +1,6 @@
-/* comio_win32.h */
+/* comio_win32.c */
+
+/* Synchronet Serial Communications I/O Library Functions for Win32 */
 
 /* $Id$ */
 
@@ -150,27 +152,6 @@ BOOL comReadByte(COM_HANDLE handle, BYTE* ch)
 	return ReadFile(handle, ch, sizeof(BYTE), &rd, NULL) && rd==sizeof(BYTE);
 }
 
-size_t comReadBuf(COM_HANDLE handle, char* buf, size_t buflen, char terminator, int timeout)
-{
-	BYTE		ch;
-	size_t		len=0;
-	msclock_t	start=msclock();
-
-	while(len < buflen) {
-		if(!comReadByte(handle, &ch)) {
-			if(msclock()-start >= timeout)
-				break;
-			YIELD();
-			continue;
-		}
-		if(len && terminator && ch==terminator)
-			break;
-		buf[len++]=ch;
-	}
-
-	return len;
-}
-
 BOOL comPurgeInput(COM_HANDLE handle)
 {
 	return PurgeComm(handle, PURGE_RXCLEAR);