diff --git a/src/sbbs3/chat.cpp b/src/sbbs3/chat.cpp
index a51f9ca959f3add2953e50894eb07aec922dff6f..bdaef4aa7d28691e29cb4d6a56205a39d3effc6e 100644
--- a/src/sbbs3/chat.cpp
+++ b/src/sbbs3/chat.cpp
@@ -1354,9 +1354,14 @@ void sbbs_t::nodemsg()
 
 	if(nodemsg_inside>1)	/* nested once only */
 		return;
+	nodemsg_inside++;
+	if(cfg.privatemsg_mod[0] != '\0') {
+		exec_bin(cfg.privatemsg_mod, &main_csi);
+		nodemsg_inside--;
+		return;
+	}
 	sys_status|=SS_IN_CTRLP;
 	getnodedat(cfg.node_num,&savenode,0);
-	nodemsg_inside++;
 	wordwrap[0]=0;
 	while(online && !done) {
 		if(useron.rest&FLAG('C')) {
diff --git a/src/sbbs3/getnode.cpp b/src/sbbs3/getnode.cpp
index 2578176e6e78a7f3548b7d3d87265a6c14ff1280..b6d6617308be7361d49704abbbe1099517a65652 100644
--- a/src/sbbs3/getnode.cpp
+++ b/src/sbbs3/getnode.cpp
@@ -377,6 +377,10 @@ int sbbs_t::whos_online(bool listself)
     int		i,j;
     node_t	node;
 
+	if(cfg.whosonline_mod[0] != '\0') {
+		return exec_bin(cfg.whosonline_mod, &main_csi);
+	}
+
 	CRLF;
 	bputs(text[NodeLstHdr]);
 	for(j=0,i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
@@ -402,6 +406,11 @@ void sbbs_t::nodelist(void)
 {
 	node_t	node;
 
+	if(cfg.nodelist_mod[0] != '\0') {
+		exec_bin(cfg.nodelist_mod, &main_csi);
+		return;
+	}
+
 	CRLF;
 	bputs(text[NodeLstHdr]);
 	for(int i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
diff --git a/src/sbbs3/scfgdefs.h b/src/sbbs3/scfgdefs.h
index 8a224a4d08806e7102cc446ebfafcfa8ca91f64a..e26f83733017b6047ae653e71103fbf5199382cc 100644
--- a/src/sbbs3/scfgdefs.h
+++ b/src/sbbs3/scfgdefs.h
@@ -601,6 +601,9 @@ typedef struct
 	char			scanposts_mod[LEN_CMD+1];	/* Scanning posts (in a single sub) module */
 	char			scansubs_mod[LEN_CMD+1];	/* Scanning sub-boards module */
 	char			listmsgs_mod[LEN_CMD+1];	/* Listing messages module */
+	char			nodelist_mod[LEN_CMD+1];
+	char			whosonline_mod[LEN_CMD+1];
+	char			privatemsg_mod[LEN_CMD+1];
 	char			scfg_cmd[LEN_CMD+1];	/* SCFG command line - unused! */
 	uchar			smb_retry_time; 		/* Seconds to retry on SMBs */
 	uint16_t		sec_warn;				/* Seconds before inactivity warning */
diff --git a/src/sbbs3/scfglib1.c b/src/sbbs3/scfglib1.c
index 68f41b1611dc3d1e61cbe056a4dcac70e5b8e04a..9614750837e289e961c55e35a60ced0226406b2b 100644
--- a/src/sbbs3/scfglib1.c
+++ b/src/sbbs3/scfglib1.c
@@ -313,7 +313,16 @@ BOOL read_main_cfg(scfg_t* cfg, char* error)
 	get_int(c, instream);
 	for(i=0;i<21;i++)					/* unused - initialized to NULL */
 		get_int(n,instream);
-	for(i=0;i<254;i++)					/* unused - initialized to 0xff */
+	get_str(cfg->nodelist_mod,instream);
+	if(cfg->nodelist_mod[0] == '\xff')
+		SAFECOPY(cfg->nodelist_mod, "nodelist");
+	get_str(cfg->whosonline_mod,instream);
+	if(cfg->whosonline_mod[0] == '\xff')
+		SAFECOPY(cfg->whosonline_mod, "nodelist -active");
+	get_str(cfg->privatemsg_mod,instream);
+	if(cfg->privatemsg_mod[0] == '\xff')
+		SAFECOPY(cfg->privatemsg_mod, "privatemsg");
+	for(i=0;i<158;i++)					/* unused - initialized to 0xff */
 		get_int(n,instream);
 
 	get_int(cfg->user_backup_level,instream);
diff --git a/src/sbbs3/scfgsave.c b/src/sbbs3/scfgsave.c
index de53d49e2f7ea7073db5783397efe93fed626831..8eb6de7a18a55d103eafb4dbde651d17895a17ff 100644
--- a/src/sbbs3/scfgsave.c
+++ b/src/sbbs3/scfgsave.c
@@ -277,8 +277,11 @@ BOOL DLLCALL write_main_cfg(scfg_t* cfg, int backup_level)
 	n=0;
 	for(i=0;i<26;i++)
 		put_int(n,stream);
+	put_str(cfg->nodelist_mod, stream);
+	put_str(cfg->whosonline_mod, stream);
+	put_str(cfg->privatemsg_mod, stream);
 	n=0xffff;
-	for(i=0;i<254;i++)
+	for(i=0;i<158;i++)
 		put_int(n,stream);
 
 	put_int(cfg->user_backup_level,stream);