From f26a82b033bc5d298fa67eaa2188c6d8285f3453 Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Sat, 17 Apr 2021 18:52:56 -0700
Subject: [PATCH] Update sound (WAV) file play-on-event support in Windows
 build

A "hack attempt" sound file is now supported in the Terminal Server, Mail Server,  and Services.

"login" and "logoff" sound files are now supported in the Terminal Server, FTP Server, Web Server, Mail Server, and Services.
This enhancement fixes Issue #157

The following sound files may now be configured in the [Global] section of the ctrl/sbbs.ini file, if desired to set the default sound files for all servers/services in on place:
- AnswerSound
- LoginSound
- LogoutSound
- HangupSound
- HackAttemptSound
---
 src/sbbs3/ctrl/FtpCfgDlgUnit.cpp      |  12 +--
 src/sbbs3/ctrl/ServicesCfgDlgUnit.cpp |   8 +-
 src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp   |   8 +-
 src/sbbs3/ctrl/WebCfgDlgUnit.cpp      |  12 +--
 src/sbbs3/ftpsrvr.c                   |  21 +++--
 src/sbbs3/ftpsrvr.h                   |  11 ++-
 src/sbbs3/login.cpp                   |   9 +++
 src/sbbs3/logout.cpp                  |   5 ++
 src/sbbs3/mailsrvr.c                  |  31 +++++++-
 src/sbbs3/mailsrvr.h                  |  18 +++--
 src/sbbs3/main.cpp                    |   8 +-
 src/sbbs3/sbbs_ini.c                  | 108 +++++++++++++++++---------
 src/sbbs3/services.c                  |  31 ++++++--
 src/sbbs3/services.h                  |  10 +--
 src/sbbs3/startup.h                   |  22 ++++--
 src/sbbs3/websrvr.c                   |  26 +++++--
 src/sbbs3/websrvr.h                   |  25 +++---
 src/sbbs3/xtrn_sec.cpp                |   2 +-
 18 files changed, 242 insertions(+), 125 deletions(-)

diff --git a/src/sbbs3/ctrl/FtpCfgDlgUnit.cpp b/src/sbbs3/ctrl/FtpCfgDlgUnit.cpp
index 62ff5fcafc..57610c4e42 100644
--- a/src/sbbs3/ctrl/FtpCfgDlgUnit.cpp
+++ b/src/sbbs3/ctrl/FtpCfgDlgUnit.cpp
@@ -72,9 +72,9 @@ void __fastcall TFtpCfgDlg::FormShow(TObject *Sender)
     MaxConConEdit->Text = AnsiString((int)MainForm->ftp_startup.max_concurrent_connections);
 
     IndexFileNameEdit->Text=AnsiString(MainForm->ftp_startup.index_file_name);
-    AnswerSoundEdit->Text=AnsiString(MainForm->ftp_startup.answer_sound);
-    HangupSoundEdit->Text=AnsiString(MainForm->ftp_startup.hangup_sound);
-    HackAttemptSoundEdit->Text=AnsiString(MainForm->ftp_startup.hack_sound);    
+    AnswerSoundEdit->Text=AnsiString(MainForm->ftp_startup.sound.answer);
+    HangupSoundEdit->Text=AnsiString(MainForm->ftp_startup.sound.hangup);
+    HackAttemptSoundEdit->Text=AnsiString(MainForm->ftp_startup.sound.hack);    
     CmdLogCheckBox->Checked=MainForm->ftp_startup.options&FTP_OPT_DEBUG_RX;
 	DebugTxCheckBox->Checked=MainForm->ftp_startup.options&FTP_OPT_DEBUG_TX;
 	DebugDataCheckBox->Checked=MainForm->ftp_startup.options&FTP_OPT_DEBUG_DATA;
@@ -135,11 +135,11 @@ void __fastcall TFtpCfgDlg::OKBtnClick(TObject *Sender)
     SAFECOPY(MainForm->ftp_startup.index_file_name
         ,IndexFileNameEdit->Text.c_str());
 
-    SAFECOPY(MainForm->ftp_startup.answer_sound
+    SAFECOPY(MainForm->ftp_startup.sound.answer
         ,AnswerSoundEdit->Text.c_str());
-    SAFECOPY(MainForm->ftp_startup.hangup_sound
+    SAFECOPY(MainForm->ftp_startup.sound.hangup
         ,HangupSoundEdit->Text.c_str());
-    SAFECOPY(MainForm->ftp_startup.hack_sound
+    SAFECOPY(MainForm->ftp_startup.sound.hack
         ,HackAttemptSoundEdit->Text.c_str());
 
 	if(DebugTxCheckBox->Checked==true)
diff --git a/src/sbbs3/ctrl/ServicesCfgDlgUnit.cpp b/src/sbbs3/ctrl/ServicesCfgDlgUnit.cpp
index a146979cc5..f12a7b76f4 100644
--- a/src/sbbs3/ctrl/ServicesCfgDlgUnit.cpp
+++ b/src/sbbs3/ctrl/ServicesCfgDlgUnit.cpp
@@ -32,8 +32,8 @@ void __fastcall TServicesCfgDlg::FormShow(TObject *Sender)
     }
     AutoStartCheckBox->Checked=MainForm->ServicesAutoStart;
 
-    AnswerSoundEdit->Text=AnsiString(MainForm->services_startup.answer_sound);
-    HangupSoundEdit->Text=AnsiString(MainForm->services_startup.hangup_sound);
+    AnswerSoundEdit->Text=AnsiString(MainForm->services_startup.sound.answer);
+    HangupSoundEdit->Text=AnsiString(MainForm->services_startup.sound.hangup);
     HostnameCheckBox->Checked
         =!(MainForm->services_startup.options&BBS_OPT_NO_HOST_LOOKUP);
 
@@ -82,9 +82,9 @@ void __fastcall TServicesCfgDlg::OKButtonClick(TObject *Sender)
 
     MainForm->ServicesAutoStart=AutoStartCheckBox->Checked;
 
-    SAFECOPY(MainForm->services_startup.answer_sound
+    SAFECOPY(MainForm->services_startup.sound.answer
         ,AnswerSoundEdit->Text.c_str());
-    SAFECOPY(MainForm->services_startup.hangup_sound
+    SAFECOPY(MainForm->services_startup.sound.hangup
         ,HangupSoundEdit->Text.c_str());
 
 	if(HostnameCheckBox->Checked==false)
diff --git a/src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp b/src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp
index 60e9ab7ff8..8c230c360e 100644
--- a/src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp
+++ b/src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp
@@ -88,8 +88,8 @@ void __fastcall TTelnetCfgDlg::FormShow(TObject *Sender)
     else
         MaxConConEdit->Text=AnsiString((int)MainForm->bbs_startup.max_concurrent_connections);
     AutoStartCheckBox->Checked=MainForm->SysAutoStart;
-    AnswerSoundEdit->Text=AnsiString(MainForm->bbs_startup.answer_sound);
-    HangupSoundEdit->Text=AnsiString(MainForm->bbs_startup.hangup_sound);
+    AnswerSoundEdit->Text=AnsiString(MainForm->bbs_startup.sound.answer);
+    HangupSoundEdit->Text=AnsiString(MainForm->bbs_startup.sound.hangup);
     CmdLogCheckBox->Checked=MainForm->bbs_startup.options&BBS_OPT_DEBUG_TELNET;
     TelnetGaCheckBox->Checked
     	=!(MainForm->bbs_startup.options&BBS_OPT_NO_TELNET_GA);
@@ -137,9 +137,9 @@ void __fastcall TTelnetCfgDlg::OKBtnClick(TObject *Sender)
     MainForm->bbs_startup.max_concurrent_connections=MaxConConEdit->Text.ToIntDef(0);
 
     MainForm->SysAutoStart=AutoStartCheckBox->Checked;
-    SAFECOPY(MainForm->bbs_startup.answer_sound
+    SAFECOPY(MainForm->bbs_startup.sound.answer
         ,AnswerSoundEdit->Text.c_str());
-    SAFECOPY(MainForm->bbs_startup.hangup_sound
+    SAFECOPY(MainForm->bbs_startup.sound.hangup
         ,HangupSoundEdit->Text.c_str());
 	if(TelnetGaCheckBox->Checked==false)
     	MainForm->bbs_startup.options|=BBS_OPT_NO_TELNET_GA;
diff --git a/src/sbbs3/ctrl/WebCfgDlgUnit.cpp b/src/sbbs3/ctrl/WebCfgDlgUnit.cpp
index b6dc232e1f..cad6925513 100644
--- a/src/sbbs3/ctrl/WebCfgDlgUnit.cpp
+++ b/src/sbbs3/ctrl/WebCfgDlgUnit.cpp
@@ -104,9 +104,9 @@ void __fastcall TWebCfgDlg::FormShow(TObject *Sender)
 
     CGICheckBox->Checked=!(MainForm->web_startup.options&WEB_OPT_NO_CGI);
 
-    AnswerSoundEdit->Text=AnsiString(MainForm->web_startup.answer_sound);
-    HangupSoundEdit->Text=AnsiString(MainForm->web_startup.hangup_sound);
-    HackAttemptSoundEdit->Text=AnsiString(MainForm->web_startup.hack_sound);
+    AnswerSoundEdit->Text=AnsiString(MainForm->web_startup.sound.answer);
+    HangupSoundEdit->Text=AnsiString(MainForm->web_startup.sound.hangup);
+    HackAttemptSoundEdit->Text=AnsiString(MainForm->web_startup.sound.hack);
 
 	DebugTxCheckBox->Checked=MainForm->web_startup.options&WEB_OPT_DEBUG_TX;
 	DebugRxCheckBox->Checked=MainForm->web_startup.options&WEB_OPT_DEBUG_RX;
@@ -173,11 +173,11 @@ void __fastcall TWebCfgDlg::OKBtnClick(TObject *Sender)
     else
 	    MainForm->web_startup.options&=~WEB_OPT_NO_CGI;
 
-    SAFECOPY(MainForm->web_startup.answer_sound
+    SAFECOPY(MainForm->web_startup.sound.answer
         ,AnswerSoundEdit->Text.c_str());
-    SAFECOPY(MainForm->web_startup.hangup_sound
+    SAFECOPY(MainForm->web_startup.sound.hangup
         ,HangupSoundEdit->Text.c_str());
-    SAFECOPY(MainForm->web_startup.hack_sound
+    SAFECOPY(MainForm->web_startup.sound.hack
         ,HackAttemptSoundEdit->Text.c_str());
 
 	if(DebugTxCheckBox->Checked==true)
diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index 72a579685f..68324b0966 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -1724,8 +1724,8 @@ void ftp_printfile(SOCKET sock, CRYPT_SESSION sess, const char* name, unsigned c
 static BOOL ftp_hacklog(char* prot, char* user, char* text, char* host, union xp_sockaddr* addr)
 {
 #ifdef _WIN32
-	if(startup->hack_sound[0] && !(startup->options&FTP_OPT_MUTE)) 
-		PlaySound(startup->hack_sound, NULL, SND_ASYNC|SND_FILENAME);
+	if(startup->sound.hack[0] && !(startup->options&FTP_OPT_MUTE)) 
+		PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 	return hacklog(&scfg, prot, user, text, host, addr);
@@ -2198,8 +2198,8 @@ static void ctrl_thread(void* arg)
 	free(arg);
 
 #ifdef _WIN32
-	if(startup->answer_sound[0] && !(startup->options&FTP_OPT_MUTE)) 
-		PlaySound(startup->answer_sound, NULL, SND_ASYNC|SND_FILENAME);
+	if(startup->sound.answer[0] && !(startup->options&FTP_OPT_MUTE)) 
+		PlaySound(startup->sound.answer, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 	transfer_inprogress = FALSE;
@@ -2565,6 +2565,10 @@ static void ctrl_thread(void* arg)
 			user.logontime=(time32_t)logintime;
 			putuserdat(&scfg, &user);
 
+#ifdef _WIN32
+			if(startup->sound.login[0] && !(startup->options&FTP_OPT_MUTE)) 
+				PlaySound(startup->sound.login, NULL, SND_ASYNC|SND_FILENAME);
+#endif
 			continue;
 		}
 		if (!strnicmp(cmd, "AUTH ", 5)) {
@@ -4802,11 +4806,16 @@ static void ctrl_thread(void* arg)
 		if(!logoutuserdat(&scfg, &user, time(NULL), logintime))
 			lprintf(LOG_ERR,"%04d <%s> !ERROR in logoutuserdat", sock, user.alias);
 		lprintf(LOG_INFO,"%04d <%s> logged off", sock, user.alias);
+#ifdef _WIN32
+		if(startup->sound.logout[0] && !(startup->options&FTP_OPT_MUTE)) 
+			PlaySound(startup->sound.logout, NULL, SND_ASYNC|SND_FILENAME);
+#endif
+
 	}
 
 #ifdef _WIN32
-	if(startup->hangup_sound[0] && !(startup->options&FTP_OPT_MUTE)) 
-		PlaySound(startup->hangup_sound, NULL, SND_ASYNC|SND_FILENAME);
+	if(startup->sound.hangup[0] && !(startup->options&FTP_OPT_MUTE)) 
+		PlaySound(startup->sound.hangup, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 /*	status(STATUS_WFC); server thread should control status display */
diff --git a/src/sbbs3/ftpsrvr.h b/src/sbbs3/ftpsrvr.h
index cd98196ad1..f02bd49d08 100644
--- a/src/sbbs3/ftpsrvr.h
+++ b/src/sbbs3/ftpsrvr.h
@@ -63,13 +63,10 @@ typedef struct {
     BOOL	(*setuid)(BOOL force);
 
 	/* Paths */
-    char    ctrl_dir[128];
+    char    ctrl_dir[INI_MAX_VALUE_LEN];
     char	index_file_name[64];
-    char	temp_dir[128];
-	char	answer_sound[128];
-	char	hangup_sound[128];
-    char	hack_sound[128];
-	char	ini_fname[128];
+    char	temp_dir[INI_MAX_VALUE_LEN];
+	char	ini_fname[INI_MAX_VALUE_LEN];
 
 	/* Misc */
     char	host_name[128];
@@ -79,6 +76,8 @@ typedef struct {
 	uint	bind_retry_count;		/* Number of times to retry bind() calls */
 	uint	bind_retry_delay;		/* Time to wait between each bind() retry */
 
+	struct startup_sound_settings sound;
+
 	/* Login Attempt parameters */
 	struct login_attempt_settings login_attempt;
 	link_list_t* login_attempt_list;
diff --git a/src/sbbs3/login.cpp b/src/sbbs3/login.cpp
index 7432b23b30..094684302f 100644
--- a/src/sbbs3/login.cpp
+++ b/src/sbbs3/login.cpp
@@ -146,6 +146,11 @@ int sbbs_t::login(char *username, char *pw_prompt, const char* user_pw, const ch
 		} 
 	}
 
+#ifdef _WIN32
+	if(startup->sound.login[0] && !(startup->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.login, NULL, SND_ASYNC|SND_FILENAME);
+#endif
+
 	return(LOGIC_TRUE);
 }
 
@@ -167,6 +172,10 @@ void sbbs_t::badlogin(char* user, char* passwd, const char* protocol, xp_sockadd
 	if(user!=NULL && startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 		getnameinfo(&addr->addr, addr_len, host_name, sizeof(host_name), NULL, 0, NI_NAMEREQD);
 		::hacklog(&cfg, reason, user, passwd, host_name, addr);
+#ifdef _WIN32
+		if(startup->sound.hack[0] && !(startup->options&BBS_OPT_MUTE))
+			PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
+#endif
 	}
 	if(startup->login_attempt.filter_threshold && count>=startup->login_attempt.filter_threshold) {
 		char ipaddr[INET6_ADDRSTRLEN];
diff --git a/src/sbbs3/logout.cpp b/src/sbbs3/logout.cpp
index 01861f0909..d2df4e4d22 100644
--- a/src/sbbs3/logout.cpp
+++ b/src/sbbs3/logout.cpp
@@ -148,6 +148,11 @@ void sbbs_t::logout()
 	sys_status&=~SS_USERON;
 	answertime=now; // In case we're re-logging on
 
+#ifdef _WIN32
+	if(startup->sound.logout[0] && !(startup->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.logout, NULL, SND_ASYNC|SND_FILENAME);
+#endif
+
 	lprintf(LOG_DEBUG, "logout completed");
 }
 
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 06cc3cc36a..1134be59bf 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -955,8 +955,13 @@ static void badlogin(SOCKET sock, CRYPT_SESSION sess, const char* prot, const ch
 	if(addr!=NULL) {
 		SAFEPRINTF(reason,"%s LOGIN", prot);
 		count=loginFailure(startup->login_attempt_list, addr, prot, user, passwd);
-		if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold)
+		if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 			hacklog(&scfg, reason, user, passwd, host, addr);
+#ifdef _WIN32
+			if(startup->sound.hack[0] && !(startup->options&MAIL_OPT_MUTE)) 
+				PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
+#endif
+		}
 		inet_addrtop(addr, ip, sizeof(ip));
 		if(startup->login_attempt.filter_threshold && count>=startup->login_attempt.filter_threshold) {
 			SAFEPRINTF(reason, "- TOO MANY CONSECUTIVE FAILED LOGIN ATTEMPTS (%lu)", count);
@@ -1338,7 +1343,10 @@ static void pop3_thread(void* arg)
 			lprintf(LOG_INFO,"%04d %s [%s] %s logged-in %s", socket, client.protocol, host_ip, user.alias, apop ? "via APOP":"");
 		SAFEPRINTF2(str,"%s: %s", client.protocol, user.alias);
 		status(str);
-
+#ifdef _WIN32
+		if(startup->sound.login[0] && !(startup->options&MAIL_OPT_MUTE)) 
+			PlaySound(startup->sound.login, NULL, SND_ASYNC|SND_FILENAME);
+#endif
 		SAFEPRINTF(smb.file,"%smail",scfg.data_dir);
 		if(smb_islocked(&smb)) {
 			lprintf(LOG_WARNING,"%04d %s <%s> !MAIL BASE LOCKED: %s",socket, client.protocol, user.alias, smb.last_error);
@@ -1706,6 +1714,10 @@ static void pop3_thread(void* arg)
 			sockprintf(socket,client.protocol,session,"-ERR UNSUPPORTED COMMAND: %s",buf);
 		}
 		if(user.number) {
+#ifdef _WIN32
+			if(startup->sound.logout[0] && !(startup->options&MAIL_OPT_MUTE)) 
+				PlaySound(startup->sound.logout, NULL, SND_ASYNC|SND_FILENAME);
+#endif
 			if(!logoutuserdat(&scfg,&user,time(NULL),client.time))
 				lprintf(LOG_ERR,"%04d %s <%s> !ERROR in logoutuserdat", socket, client.protocol, user.alias);
 		}
@@ -4205,6 +4217,10 @@ static void smtp_thread(void* arg)
 				,socket,client.protocol, client_id, relay_user.alias, auth_login ? "LOGIN" : "PLAIN");
 			SAFEPRINTF(client_id, "<%s>", relay_user.alias);
 			sockprintf(socket,client.protocol,session,auth_ok);
+#ifdef _WIN32
+			if(startup->sound.login[0] && !(startup->options&MAIL_OPT_MUTE)) 
+				PlaySound(startup->sound.login, NULL, SND_ASYNC|SND_FILENAME);
+#endif
 			continue;
 		}
 		if(!stricmp(buf,"AUTH CRAM-MD5")) {
@@ -4299,6 +4315,10 @@ static void smtp_thread(void* arg)
 				,socket, client.protocol, client_id, relay_user.alias);
 			SAFEPRINTF(client_id, "<%s>", relay_user.alias);
 			sockprintf(socket,client.protocol,session,auth_ok);
+#ifdef _WIN32
+			if(startup->sound.login[0] && !(startup->options&MAIL_OPT_MUTE)) 
+				PlaySound(startup->sound.login, NULL, SND_ASYNC|SND_FILENAME);
+#endif
 			continue;
 		}
 		if(!strnicmp(buf,"AUTH",4)) {
@@ -5015,6 +5035,13 @@ static void smtp_thread(void* arg)
 	}
 	free(mailproc_to_match);
 
+#ifdef _WIN32
+	if(relay_user.number) {
+		if(startup->sound.logout[0] && !(startup->options&MAIL_OPT_MUTE)) 
+			PlaySound(startup->sound.logout, NULL, SND_ASYNC|SND_FILENAME);
+	}
+#endif
+
 	/* Must be last */
 	mail_close_socket(&socket, &session);
 }
diff --git a/src/sbbs3/mailsrvr.h b/src/sbbs3/mailsrvr.h
index 2dac0e8a8d..11327d965d 100644
--- a/src/sbbs3/mailsrvr.h
+++ b/src/sbbs3/mailsrvr.h
@@ -75,20 +75,20 @@ typedef struct {
 	BOOL	(*setuid)(BOOL force);
 
 	/* Paths */
-    char    ctrl_dir[128];
-	char    temp_dir[128];
-	char	ini_fname[128];
+    char    ctrl_dir[INI_MAX_VALUE_LEN];
+	char    temp_dir[INI_MAX_VALUE_LEN];
+	char	ini_fname[INI_MAX_VALUE_LEN];
 
 	/* Strings */
     char	dns_server[128];
     char	default_user[128];
     char	dnsbl_tag[32];		// Tag to add to blacklisted subject
 	char	dnsbl_hdr[32];		// Header field to add to msg header
-	char	inbound_sound[128];
-	char	outbound_sound[128];
-    char	pop3_sound[128];
-	char	newmail_notice[256];
-	char	forward_notice[256];
+	char	inbound_sound[INI_MAX_VALUE_LEN];
+	char	outbound_sound[INI_MAX_VALUE_LEN];
+    char	pop3_sound[INI_MAX_VALUE_LEN];
+	char	newmail_notice[INI_MAX_VALUE_LEN];
+	char	forward_notice[INI_MAX_VALUE_LEN];
 
 	/* Misc */
     char	host_name[128];
@@ -107,6 +107,8 @@ typedef struct {
 	/* JavaScript operating parameters */
 	js_startup_t js;
 
+	struct startup_sound_settings sound;
+
 	/* Login Attempt parameters */
 	struct login_attempt_settings login_attempt;
 	link_list_t* login_attempt_list;
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index e5b6d9874a..3e9c2ca292 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -4386,8 +4386,8 @@ void node_thread(void* arg)
 	}
 
 #ifdef _WIN32
-	if(startup->hangup_sound[0] && !(startup->options&BBS_OPT_MUTE))
-		PlaySound(startup->hangup_sound, NULL, SND_ASYNC|SND_FILENAME);
+	if(startup->sound.hangup[0] && !(startup->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.hangup, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 	sbbs->hangup();	/* closes sockets, calls client_off, and shuts down the output_thread */
@@ -5337,8 +5337,8 @@ NO_SSH:
 		}
 
 #ifdef _WIN32
-		if(startup->answer_sound[0] && !(startup->options&BBS_OPT_MUTE))
-			PlaySound(startup->answer_sound, NULL, SND_ASYNC|SND_FILENAME);
+		if(startup->sound.answer[0] && !(startup->options&BBS_OPT_MUTE))
+			PlaySound(startup->sound.answer, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 		/* Purge (flush) any pending input or output data */
diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c
index ba01198d0b..a66c4b3e52 100644
--- a/src/sbbs3/sbbs_ini.c
+++ b/src/sbbs3/sbbs_ini.c
@@ -46,6 +46,8 @@ static const char*	strBindRetryCount="BindRetryCount";
 static const char*	strBindRetryDelay="BindRetryDelay";
 static const char*	strAnswerSound="AnswerSound";
 static const char*	strHangupSound="HangupSound";
+static const char*	strLoginSound="LoginSound";
+static const char*	strLogoutSound="LogoutSound";
 static const char*	strHackAttemptSound="HackAttemptSound";
 static const char*	strLoginAttemptDelay="LoginAttemptDelay";
 static const char*	strLoginAttemptThrottle="LoginAttemptThrottle";
@@ -87,6 +89,16 @@ void sbbs_get_ini_fname(char* ini_file, char* ctrl_dir, char* pHostName)
 #endif
 }
 
+static BOOL iniSetStringWithGlobalDefault(str_list_t* lp, const char* section, const char* key
+	,const char* value, const char* global_value, ini_style_t* style)
+{
+	if(strcmp(value, global_value) == 0) {
+		iniRemoveKey(lp, section, key);
+		return iniKeyExists(*lp, section, key) == FALSE;
+	}
+	return iniSetString(lp, section, key, value, style) != NULL;
+}
+
 static void sbbs_fix_js_settings(js_startup_t* js)
 {
 	/* Some sanity checking here */
@@ -169,6 +181,48 @@ BOOL sbbs_set_js_settings(
 	return(!failure);
 }
 
+void sbbs_get_sound_settings(str_list_t list, const char* section, struct startup_sound_settings* sound
+	,struct startup_sound_settings* defaults)
+{
+	char	value[INI_MAX_VALUE_LEN];
+    char*   p;
+
+	if((p = iniGetString(list, section, strAnswerSound, defaults->answer, value)) != NULL && *p != '\0')
+        SAFECOPY(sound->answer, value);
+
+	if((p = iniGetString(list, section, strLoginSound, defaults->login, value)) != NULL && *p != '\0')
+        SAFECOPY(sound->login, value);
+
+	if((p = iniGetString(list, section, strLogoutSound, defaults->logout, value)) != NULL && *p != '\0')
+        SAFECOPY(sound->logout, value);
+
+	if((p = iniGetString(list, section, strHangupSound, defaults->hangup, value)) != NULL && *p != '\0')
+        SAFECOPY(sound->hangup, value);
+
+	if((p = iniGetString(list, section, strHackAttemptSound, defaults->hack, value)) != NULL && *p != '\0')
+        SAFECOPY(sound->hack, value);
+}
+
+BOOL sbbs_set_sound_settings(
+	 str_list_t* lp
+	,const char* section
+	,struct startup_sound_settings* sound
+	,struct startup_sound_settings* defaults
+	,ini_style_t* style)
+{
+	if(!iniSetStringWithGlobalDefault(lp ,section, strAnswerSound, sound->answer, defaults->answer, style))
+		return FALSE;
+	if(!iniSetStringWithGlobalDefault(lp, section, strLoginSound, sound->login, defaults->login, style))
+		return FALSE;
+	if(!iniSetStringWithGlobalDefault(lp, section, strLogoutSound, sound->logout, defaults->logout, style))
+		return FALSE;
+	if(!iniSetStringWithGlobalDefault(lp, section, strHangupSound, sound->hangup, defaults->logout, style))
+		return FALSE;
+	if(!iniSetStringWithGlobalDefault(lp, section, strHackAttemptSound, sound->hack, defaults->hack, style))
+		return FALSE;
+	return TRUE;
+}
+
 static struct login_attempt_settings get_login_attempt_settings(str_list_t list, const char* section, global_startup_t* global)
 {
 	struct login_attempt_settings settings;
@@ -233,8 +287,8 @@ static void get_ini_globals(str_list_t list, global_startup_t* global)
 	global->js.options			= JAVASCRIPT_OPTIONS;
     SAFECOPY(global->js.load_path, JAVASCRIPT_LOAD_PATH);
 
-	/* Read .ini values here */
 	sbbs_get_js_settings(list, section, &global->js, &global->js);
+	sbbs_get_sound_settings(list, section, &global->sound, &global->sound);
 }
 
 
@@ -388,10 +442,7 @@ void sbbs_read_ini(
 			,iniGetString(list,section,"DOSemuPath",default_dosemu_path,value));
 	#endif
 
-		SAFECOPY(bbs->answer_sound
-			,iniGetString(list,section,strAnswerSound,nulstr,value));
-		SAFECOPY(bbs->hangup_sound
-			,iniGetString(list,section,strHangupSound,nulstr,value));
+		sbbs_get_sound_settings(list, section, &bbs->sound, &global->sound);
 
 		bbs->log_level
 			=iniGetLogLevel(list,section,strLogLevel,global->log_level);
@@ -452,12 +503,7 @@ void sbbs_read_ini(
 		SAFECOPY(ftp->index_file_name
 			,iniGetString(list,section,"IndexFileName","00index",value));
 
-		SAFECOPY(ftp->answer_sound
-			,iniGetString(list,section,strAnswerSound,nulstr,value));
-		SAFECOPY(ftp->hangup_sound
-			,iniGetString(list,section,strHangupSound,nulstr,value));
-		SAFECOPY(ftp->hack_sound
-			,iniGetString(list,section,strHackAttemptSound,nulstr,value));
+		sbbs_get_sound_settings(list, section, &ftp->sound, &global->sound);
 
 		SAFECOPY(ftp->temp_dir
 			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
@@ -555,6 +601,7 @@ void sbbs_read_ini(
 			,iniGetString(list,section,"InboundSound",nulstr,value));
 		SAFECOPY(mail->outbound_sound
 			,iniGetString(list,section,"OutboundSound",nulstr,value));
+		sbbs_get_sound_settings(list, section, &mail->sound, &global->sound);
 
 		SAFECOPY(mail->newmail_notice
 			,iniGetString(list,section,"NewMailNotice","%.0s\1n\1mNew e-mail from \1h%s \1n<\1h%s\1n>\r\n", value));
@@ -607,10 +654,7 @@ void sbbs_read_ini(
 		SAFECOPY(services->services_ini
 			,iniGetString(list, section, strIniFileName, "services.ini", value));
 
-		SAFECOPY(services->answer_sound
-			,iniGetString(list,section,strAnswerSound,nulstr,value));
-		SAFECOPY(services->hangup_sound
-			,iniGetString(list,section,strHangupSound,nulstr,value));
+		sbbs_get_sound_settings(list, section, &services->sound, &global->sound);
 
 		services->log_level
 			=iniGetLogLevel(list,section,strLogLevel,global->log_level);
@@ -683,12 +727,7 @@ void sbbs_read_ini(
 		web->max_cgi_inactivity
 			=iniGetShortInt(list,section,"MaxCgiInactivity",WEB_DEFAULT_MAX_CGI_INACTIVITY);	/* seconds */
 
-		SAFECOPY(web->answer_sound
-			,iniGetString(list,section,strAnswerSound,nulstr,value));
-		SAFECOPY(web->hangup_sound
-			,iniGetString(list,section,strHangupSound,nulstr,value));
-		SAFECOPY(web->hack_sound
-			,iniGetString(list,section,strHackAttemptSound,nulstr,value));
+		sbbs_get_sound_settings(list, section, &web->sound, &global->sound);
 
 		web->log_level
 			=iniGetLogLevel(list,section,strLogLevel,global->log_level);
@@ -734,7 +773,7 @@ BOOL sbbs_write_ini(
 
 	memset(&style, 0, sizeof(style));
 	style.key_prefix = "\t";
-	style.section_separator = "";
+style.section_separator = "";
 	style.value_separator = " = ";
 	style.bit_separator = " | ";
 
@@ -859,9 +898,8 @@ BOOL sbbs_write_ini(
 			break;
 #endif
 #endif
-		if(!iniSetString(lp,section,strAnswerSound,bbs->answer_sound,&style))
-			break;
-		if(!iniSetString(lp,section,strHangupSound,bbs->hangup_sound,&style))
+
+		if(!sbbs_set_sound_settings(lp, section, &bbs->sound, &global->sound, &style))
 			break;
 
 		if(!iniSetBitField(lp,section,strOptions,bbs_options,bbs->options,&style))
@@ -948,11 +986,7 @@ BOOL sbbs_write_ini(
 		if(!iniSetString(lp,section,"IndexFileName",ftp->index_file_name,&style))
 			break;
 
-		if(!iniSetString(lp,section,strAnswerSound,ftp->answer_sound,&style))
-			break;
-		if(!iniSetString(lp,section,strHangupSound,ftp->hangup_sound,&style))
-			break;
-		if(!iniSetString(lp,section,strHackAttemptSound,ftp->hack_sound,&style))
+		if(!sbbs_set_sound_settings(lp, section, &ftp->sound, &global->sound, &style))
 			break;
 	
 		if(!iniSetBitField(lp,section,strOptions,ftp_options,ftp->options,&style))
@@ -1069,6 +1103,10 @@ BOOL sbbs_write_ini(
 			break;
 		if(!iniSetString(lp,section,"OutboundSound",mail->outbound_sound,&style))
 			break;
+
+		if(!sbbs_set_sound_settings(lp, section, &mail->sound, &global->sound, &style))
+			break;
+
 #if 0
 		if(!iniSetStringLiteral(lp,section,"NewMailNotice",mail->newmail_notice,&style))
 			break;
@@ -1140,9 +1178,7 @@ BOOL sbbs_write_ini(
 		else if(!iniSetString(lp,section,strTempDirectory,services->temp_dir,&style))
 			break;
 
-		if(!iniSetString(lp,section,strAnswerSound,services->answer_sound,&style))
-			break;
-		if(!iniSetString(lp,section,strHangupSound,services->hangup_sound,&style))
+		if(!sbbs_set_sound_settings(lp, section, &services->sound, &global->sound, &style))
 			break;
 
 		if(!iniSetString(lp, section, strIniFileName, services->services_ini, &style))
@@ -1240,11 +1276,7 @@ BOOL sbbs_write_ini(
 		if(!iniSetShortInt(lp,section,"MaxCgiInactivity",web->max_cgi_inactivity,&style))
 			break;
 
-		if(!iniSetString(lp,section,strAnswerSound,web->answer_sound,&style))
-			break;
-		if(!iniSetString(lp,section,strHangupSound,web->hangup_sound,&style))
-			break;
-		if(!iniSetString(lp,section,strHackAttemptSound,web->hack_sound,&style))
+		if(!sbbs_set_sound_settings(lp, section, &web->sound, &global->sound, &style))
 			break;
 
 		if(!iniSetBitField(lp,section,strOptions,web_options,web->options,&style))
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 9b27f70719..30b5aa81dd 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -323,8 +323,13 @@ static void badlogin(SOCKET sock, char* prot, char* user, char* passwd, char* ho
 
 	SAFEPRINTF(reason,"%s LOGIN", prot);
 	count=loginFailure(startup->login_attempt_list, addr, prot, user, passwd);
-	if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold)
+	if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 		hacklog(&scfg, reason, user, passwd, host, addr);
+#ifdef _WIN32
+		if(startup->sound.hack[0] && !(startup->options&BBS_OPT_MUTE))
+			PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
+#endif
+	}
 	if(startup->login_attempt.filter_threshold && count>=startup->login_attempt.filter_threshold) {
 		inet_addrtop(addr, addr_ip, sizeof(addr_ip));
 		SAFEPRINTF(reason, "- TOO MANY CONSECUTIVE FAILED LOGIN ATTEMPTS (%lu)", count);
@@ -454,6 +459,12 @@ js_login(JSContext *cx, uintN argc, jsval *arglist)
 
 	JS_SET_RVAL(cx, arglist,BOOLEAN_TO_JSVAL(JS_TRUE));
 
+#ifdef _WIN32
+	if(startup->sound.login[0] && !(startup->options&BBS_OPT_MUTE)
+		&& !(service->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.login, NULL, SND_ASYNC|SND_FILENAME);
+#endif
+
 	return(JS_TRUE);
 }
 
@@ -1176,6 +1187,12 @@ static void js_service_thread(void* arg)
 			lprintf(LOG_INFO,"%04d %s Logging out %s"
 				,socket, service->protocol, service_client.user.alias);
 		logoutuserdat(&scfg,&service_client.user,time(NULL),service_client.logintime);
+
+#ifdef _WIN32
+		if(startup->sound.logout[0] && !(startup->options&BBS_OPT_MUTE)
+			&& !(service->options&BBS_OPT_MUTE))
+			PlaySound(startup->sound.logout, NULL, SND_ASYNC|SND_FILENAME);
+#endif
 	}
 	FREE_AND_NULL(service_client.subscan);
 
@@ -1183,9 +1200,9 @@ static void js_service_thread(void* arg)
 	update_clients();
 
 #ifdef _WIN32
-	if(startup->hangup_sound[0] && !(startup->options&BBS_OPT_MUTE)
+	if(startup->sound.hangup[0] && !(startup->options&BBS_OPT_MUTE)
 		&& !(service->options&BBS_OPT_MUTE))
-		PlaySound(startup->hangup_sound, NULL, SND_ASYNC|SND_FILENAME);
+		PlaySound(startup->sound.hangup, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 	thread_down();
@@ -1505,9 +1522,9 @@ static void native_service_thread(void* arg)
 	update_clients();
 
 #ifdef _WIN32
-	if(startup->hangup_sound[0] && !(startup->options&BBS_OPT_MUTE)
+	if(startup->sound.hangup[0] && !(startup->options&BBS_OPT_MUTE)
 		&& !(service->options&BBS_OPT_MUTE))
-		PlaySound(startup->hangup_sound, NULL, SND_ASYNC|SND_FILENAME);
+		PlaySound(startup->sound.hangup, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 	thread_down();
@@ -2275,9 +2292,9 @@ void services_thread(void* arg)
 					}
 
 	#ifdef _WIN32
-					if(startup->answer_sound[0] && !(startup->options&BBS_OPT_MUTE)
+					if(startup->sound.answer[0] && !(startup->options&BBS_OPT_MUTE)
 						&& !(service[i].options&BBS_OPT_MUTE))
-						PlaySound(startup->answer_sound, NULL, SND_ASYNC|SND_FILENAME);
+						PlaySound(startup->sound.answer, NULL, SND_ASYNC|SND_FILENAME);
 	#endif
 
 					if((client=malloc(sizeof(service_client_t)))==NULL) {
diff --git a/src/sbbs3/services.h b/src/sbbs3/services.h
index c26b0607fe..62bd368087 100644
--- a/src/sbbs3/services.h
+++ b/src/sbbs3/services.h
@@ -48,11 +48,9 @@ typedef struct {
 	BOOL	(*setuid)(BOOL force);
 
 	/* Paths */
-    char    ctrl_dir[128];
-	char    temp_dir[128];
-	char	answer_sound[128];
-	char	hangup_sound[128];
-	char	ini_fname[128];		// sbbs.ini path/filename
+    char    ctrl_dir[INI_MAX_VALUE_LEN];
+	char    temp_dir[INI_MAX_VALUE_LEN];
+	char	ini_fname[INI_MAX_VALUE_LEN];		// sbbs.ini path/filename
 	char	services_ini[128];	// services.ini filename
 
 	/* Misc */
@@ -63,6 +61,8 @@ typedef struct {
 	uint	bind_retry_count;		/* Number of times to retry bind() calls */
 	uint	bind_retry_delay;		/* Time to wait between each bind() retry */
 
+	struct startup_sound_settings sound;
+
 	/* JavaScript operating parameters */
 	js_startup_t js;
 
diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h
index 165bc8cbd7..a4365ce55a 100644
--- a/src/sbbs3/startup.h
+++ b/src/sbbs3/startup.h
@@ -52,6 +52,14 @@ struct login_attempt_settings {
 	ulong	filter_threshold;
 };
 
+struct startup_sound_settings {
+	char	answer[INI_MAX_VALUE_LEN];
+	char	login[INI_MAX_VALUE_LEN];
+	char	logout[INI_MAX_VALUE_LEN];
+	char	hangup[INI_MAX_VALUE_LEN];
+	char	hack[INI_MAX_VALUE_LEN];
+};
+
 typedef struct {
 
 	char	ctrl_dir[INI_MAX_VALUE_LEN];
@@ -66,6 +74,7 @@ typedef struct {
 	uint	bind_retry_count;		/* Number of times to retry bind() calls */
 	uint	bind_retry_delay;		/* Time to wait between each bind() retry */
 	struct login_attempt_settings login_attempt;
+	struct startup_sound_settings sound;
 
 } global_startup_t;
 
@@ -112,13 +121,11 @@ typedef struct {
 	BOOL	(*setuid)(BOOL force);
 
 	/* Paths */
-    char    ctrl_dir[128];
-    char	dosemu_path[128];
-    char    dosemuconf_path[128];
-    char	temp_dir[128];
-	char	answer_sound[128];
-	char	hangup_sound[128];
-	char	ini_fname[128];
+    char    ctrl_dir[INI_MAX_VALUE_LEN];
+    char	dosemu_path[INI_MAX_VALUE_LEN];
+    char    dosemuconf_path[INI_MAX_VALUE_LEN];
+    char	temp_dir[INI_MAX_VALUE_LEN];
+	char	ini_fname[INI_MAX_VALUE_LEN];
 
 	/* Miscellaneous */
 	BOOL    usedosemu;
@@ -134,6 +141,7 @@ typedef struct {
 	/* JavaScript operating parameters */
 	js_startup_t js;
 
+	struct startup_sound_settings sound;
 	struct login_attempt_settings login_attempt;
 	link_list_t* login_attempt_list;
 	uint	max_concurrent_connections;
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 5fbe1a9238..1674fed09d 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -1617,6 +1617,11 @@ void http_logoff(http_session_t* session, SOCKET socket, int line)
 		lprintf(LOG_ERR,"%04d !ERROR in logoutuserdat", socket);
 	memset(&session->user,0,sizeof(session->user));
 	session->last_user_num=session->user.number;
+
+#ifdef _WIN32
+	if(startup->sound.logout[0] && !(startup->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.logout, NULL, SND_ASYNC|SND_FILENAME);
+#endif
 }
 
 BOOL http_checkuser(http_session_t * session)
@@ -1842,8 +1847,8 @@ static void badlogin(SOCKET sock, const char* prot, const char* user, const char
 	if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 		hacklog(&scfg, reason, user, passwd, host, addr);
 #ifdef _WIN32
-		if(startup->hack_sound[0] && !(startup->options&BBS_OPT_MUTE))
-			PlaySound(startup->hack_sound, NULL, SND_ASYNC|SND_FILENAME);
+		if(startup->sound.hack[0] && !(startup->options&BBS_OPT_MUTE))
+			PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 	}
 	if(startup->login_attempt.filter_threshold && count>=startup->login_attempt.filter_threshold) {
@@ -2010,8 +2015,8 @@ static BOOL check_ars(http_session_t * session)
 		,session->socket,session->req.auth.username,session->req.ars);
 
 #ifdef _WIN32
-	if(startup->hack_sound[0] && !(startup->options&BBS_OPT_MUTE))
-		PlaySound(startup->hack_sound, NULL, SND_ASYNC|SND_FILENAME);
+	if(startup->sound.hack[0] && !(startup->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 	return(FALSE);
@@ -5441,6 +5446,11 @@ js_login(JSContext *cx, uintN argc, jsval *arglist)
 
 	JS_SET_RVAL(cx, arglist,BOOLEAN_TO_JSVAL(JS_TRUE));
 
+#ifdef _WIN32
+	if(startup->sound.login[0] && !(startup->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.login, NULL, SND_ASYNC|SND_FILENAME);
+#endif
+
 	return(JS_TRUE);
 }
 
@@ -6373,8 +6383,8 @@ void http_session_thread(void* arg)
 		lprintf(LOG_DEBUG,"%04d !!! DANGER WILL ROBINSON, DANGER !!!", session.socket);
 
 #ifdef _WIN32
-	if(startup->answer_sound[0] && !(startup->options&BBS_OPT_MUTE))
-		PlaySound(startup->answer_sound, NULL, SND_ASYNC|SND_FILENAME);
+	if(startup->sound.answer[0] && !(startup->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.answer, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 	session.finished=FALSE;
@@ -6611,8 +6621,8 @@ void http_session_thread(void* arg)
 	}
 
 #ifdef _WIN32
-	if(startup->hangup_sound[0] && !(startup->options&BBS_OPT_MUTE))
-		PlaySound(startup->hangup_sound, NULL, SND_ASYNC|SND_FILENAME);
+	if(startup->sound.hangup[0] && !(startup->options&BBS_OPT_MUTE))
+		PlaySound(startup->sound.hangup, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 
 	close_session_socket(&session);
diff --git a/src/sbbs3/websrvr.h b/src/sbbs3/websrvr.h
index 70dd1861ac..ea2b63e017 100644
--- a/src/sbbs3/websrvr.h
+++ b/src/sbbs3/websrvr.h
@@ -58,19 +58,16 @@ typedef struct {
 	BOOL	(*setuid)(BOOL);
 
 	/* Paths */
-	char	ssjs_ext[16];			/* Server-Side JavaScript file extension */
-	char**	cgi_ext;				/* CGI Extensions */
-	char	cgi_dir[128];			/* relative to root_dir (all files executable) */
-    char    ctrl_dir[128];
-    char	root_dir[128];			/* HTML root directory */
-    char	error_dir[128];			/* relative to root_dir */
-    char	temp_dir[128];
-    char**	index_file_name;		/* Index filenames */
-	char	logfile_base[128];		/* Logfile base name (date is appended) */
-	char	answer_sound[128];
-	char	hangup_sound[128];
-    char	hack_sound[128];
-	char	ini_fname[128];
+	char	ssjs_ext[16];							/* Server-Side JavaScript file extension */
+	char**	cgi_ext;								/* CGI Extensions */
+	char	cgi_dir[INI_MAX_VALUE_LEN];				/* relative to root_dir (all files executable) */
+    char    ctrl_dir[INI_MAX_VALUE_LEN];
+    char	root_dir[INI_MAX_VALUE_LEN];			/* HTML root directory */
+    char	error_dir[INI_MAX_VALUE_LEN];			/* relative to root_dir */
+    char	temp_dir[INI_MAX_VALUE_LEN];
+    char**	index_file_name;						/* Index filenames */
+	char	logfile_base[INI_MAX_VALUE_LEN];		/* Logfile base name (date is appended) */
+	char	ini_fname[INI_MAX_VALUE_LEN];
 
 	/* Misc */
     char	host_name[128];
@@ -84,6 +81,8 @@ typedef struct {
 	char	default_auth_list[128];
 	uint16_t	outbuf_drain_timeout;
 
+	struct startup_sound_settings sound;
+
 	/* JavaScript operating parameters */
 	js_startup_t js;
 
diff --git a/src/sbbs3/xtrn_sec.cpp b/src/sbbs3/xtrn_sec.cpp
index b36266b572..92f6602723 100644
--- a/src/sbbs3/xtrn_sec.cpp
+++ b/src/sbbs3/xtrn_sec.cpp
@@ -799,7 +799,7 @@ void sbbs_t::xtrndat(const char *name, const char *dropdir, uchar type, ulong tl
 			,-1 								/* Display on/off */
 			,0									/* Printer on/off */
 			,sys_status&SS_SYSPAGE ? -1:0		/* Page Bell on/off */
-			,startup->answer_sound[0] ? -1:0	/* Caller Alarm on/off */
+			,startup->sound.answer[0] ? -1:0	/* Caller Alarm on/off */
 			,' ' 								/* Sysop next flag */
 			,0									/* Error corrected */
 			,(term & NO_EXASCII) ? '7'			/* Graphics mode */
-- 
GitLab