Add server admin messaging functionality

It's occasionally important for public servers to notify
all the players. Sending a mail is not reliable, as not everyone
wants to break conduct, or have mail on.

This adds a compile-time defined filename, which NetHack
will monitor. The contents of the file are in the same
format as SIMPLE_MAIL: "sender:message" on one line.
This commit is contained in:
Pasi Kallinen
2016-01-04 23:04:59 +02:00
parent 89e4d5e9fa
commit e9b0fa23d2
4 changed files with 93 additions and 31 deletions
+1
View File
@@ -1062,6 +1062,7 @@ E void FDECL(nocmov, (int x, int y));
#ifdef UNIX #ifdef UNIX
E void NDECL(getmailstatus); E void NDECL(getmailstatus);
#endif #endif
E void NDECL(ck_server_admin_msg);
E void NDECL(ckmailstatus); E void NDECL(ckmailstatus);
E void FDECL(readmail, (struct obj *)); E void FDECL(readmail, (struct obj *));
#endif /* MAIL */ #endif /* MAIL */
+13 -1
View File
@@ -193,7 +193,9 @@
/* If SIMPLE_MAIL is defined, the mail spool file format is /* If SIMPLE_MAIL is defined, the mail spool file format is
"sender:message", one mail per line, and mails are "sender:message", one mail per line, and mails are
read within game, from demon-delivered mail scrolls */ read within game, from demon-delivered mail scrolls.
The mail spool file will be deleted once the player
has read the message. */
/* #define SIMPLE_MAIL */ /* #define SIMPLE_MAIL */
#ifndef MAILCKFREQ #ifndef MAILCKFREQ
@@ -203,6 +205,16 @@
#endif /* MAIL */ #endif /* MAIL */
/* If SERVER_ADMIN_MSG is defined and the file exists, players get
a message from the user defined in the file. The file format
is "sender:message" all in one line. */
/* #define SERVER_ADMIN_MSG "adminmsg" */
#ifndef SERVER_ADMIN_MSG_CKFREQ
/* How often admin message file is checked for new messages, in turns */
#define SERVER_ADMIN_MSG_CKFREQ 25
#endif
/* /*
* Some terminals or terminal emulators send two character sequence "ESC c" * Some terminals or terminal emulators send two character sequence "ESC c"
* when Alt+c is pressed. The altmeta run-time option allows the user to * when Alt+c is pressed. The altmeta run-time option allows the user to
+1
View File
@@ -455,6 +455,7 @@ boolean resuming;
rhack(save_cm); rhack(save_cm);
} }
} else if (multi == 0) { } else if (multi == 0) {
ck_server_admin_msg();
#ifdef MAIL #ifdef MAIL
ckmailstatus(); ckmailstatus();
#endif #endif
+78 -30
View File
@@ -502,35 +502,50 @@ ckmailstatus()
} }
} }
#ifdef SIMPLE_MAIL #if defined(SIMPLE_MAIL) || defined(SERVER_ADMIN_MSG)
void void
read_simplemail() read_simplemail(mbox, adminmsg)
char *mbox;
boolean adminmsg;
{ {
FILE* mb = fopen(mailbox, "r"); FILE* mb = fopen(mbox, "r");
char curline[102], *msg; char curline[128], *msg;
boolean seen_one_already = FALSE; boolean seen_one_already = FALSE;
#ifdef SIMPLE_MAIL
struct flock fl = { 0 }; struct flock fl = { 0 };
#endif
fl.l_type = F_RDLCK; const char *msgfrom = adminmsg
fl.l_whence = SEEK_SET; ? "The voice of %s booms through the caverns:"
fl.l_start = 0; : "This message is from '%s'.";
fl.l_len = 0;
if (!mb) if (!mb)
goto bail; goto bail;
#ifdef SIMPLE_MAIL
fl.l_type = F_RDLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
errno = 0;
#endif
/* Allow this call to block. */ /* Allow this call to block. */
if (fcntl (fileno (mb), F_SETLKW, &fl) == -1) if (!adminmsg
#ifdef SIMPLE_MAIL
&& fcntl (fileno (mb), F_SETLKW, &fl) == -1
#endif
)
goto bail; goto bail;
errno = 0; while (fgets(curline, 128, mb) != NULL) {
while (fgets(curline, 102, mb) != NULL) { if (!adminmsg) {
fl.l_type = F_UNLCK; #ifdef SIMPLE_MAIL
fcntl (fileno(mb), F_UNLCK, &fl); fl.l_type = F_UNLCK;
fcntl (fileno(mb), F_UNLCK, &fl);
pline("There is a%s message on this scroll.", #endif
seen_one_already ? "nother" : ""); pline("There is a%s message on this scroll.",
seen_one_already ? "nother" : "");
}
msg = strchr(curline, ':'); msg = strchr(curline, ':');
if (!msg) if (!msg)
@@ -538,28 +553,61 @@ read_simplemail()
*msg = '\0'; *msg = '\0';
msg++; msg++;
pline("This message is from '%s'.", curline);
msg[strlen(msg) - 1] = '\0'; /* kill newline */ msg[strlen(msg) - 1] = '\0'; /* kill newline */
pline ("It reads: \"%s\".", msg);
pline(msgfrom, curline);
if (adminmsg)
verbalize(msg);
else
pline("It reads: \"%s\".", msg);
seen_one_already = TRUE; seen_one_already = TRUE;
#ifdef SIMPLE_MAIL
errno = 0; errno = 0;
if (!adminmsg) {
fl.l_type = F_RDLCK; fl.l_type = F_RDLCK;
fcntl(fileno(mb), F_SETLKW, &fl); fcntl(fileno(mb), F_SETLKW, &fl);
}
#endif
} }
fl.l_type = F_UNLCK; #ifdef SIMPLE_MAIL
fcntl(fileno(mb), F_UNLCK, &fl); if (!adminmsg) {
fl.l_type = F_UNLCK;
fcntl(fileno(mb), F_UNLCK, &fl);
}
#endif
fclose(mb); fclose(mb);
unlink(mailbox); if (adminmsg)
display_nhwindow(WIN_MESSAGE, TRUE);
else
unlink(mailbox);
return;
bail: bail:
pline("It appears to be all gibberish."); /* bail out _professionally_ */ /* bail out _professionally_ */
if (!adminmsg)
pline("It appears to be all gibberish.");
} }
#endif /* SIMPLE_MAIL */ #endif /* SIMPLE_MAIL */
void
ck_server_admin_msg()
{
#ifdef SERVER_ADMIN_MSG
static struct stat ost,nst;
static long lastchk = 0;
if (moves < lastchk + SERVER_ADMIN_MSG_CKFREQ) return;
lastchk = moves;
if (!stat(SERVER_ADMIN_MSG, &nst)) {
if (nst.st_mtime > ost.st_mtime)
read_simplemail(SERVER_ADMIN_MSG, TRUE);
ost.st_mtime = nst.st_mtime;
}
#endif /* SERVER_ADMIN_MSG */
}
/*ARGSUSED*/ /*ARGSUSED*/
void void
readmail(otmp) readmail(otmp)
@@ -569,7 +617,7 @@ struct obj *otmp UNUSED;
register const char *mr = 0; register const char *mr = 0;
#endif /* DEF_MAILREADER */ #endif /* DEF_MAILREADER */
#ifdef SIMPLE_MAIL #ifdef SIMPLE_MAIL
read_simplemail(); read_simplemail(mailbox, FALSE);
return; return;
#endif /* SIMPLE_MAIL */ #endif /* SIMPLE_MAIL */
#ifdef DEF_MAILREADER /* This implies that UNIX is defined */ #ifdef DEF_MAILREADER /* This implies that UNIX is defined */