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:56 +02:00
parent 89e4d5e9fa
commit e9b0fa23d2
4 changed files with 93 additions and 31 deletions

View File

@@ -1062,6 +1062,7 @@ E void FDECL(nocmov, (int x, int y));
#ifdef UNIX
E void NDECL(getmailstatus);
#endif
E void NDECL(ck_server_admin_msg);
E void NDECL(ckmailstatus);
E void FDECL(readmail, (struct obj *));
#endif /* MAIL */

View File

@@ -193,7 +193,9 @@
/* If SIMPLE_MAIL is defined, the mail spool file format is
"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 */
#ifndef MAILCKFREQ
@@ -203,6 +205,16 @@
#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"
* when Alt+c is pressed. The altmeta run-time option allows the user to

View File

@@ -455,6 +455,7 @@ boolean resuming;
rhack(save_cm);
}
} else if (multi == 0) {
ck_server_admin_msg();
#ifdef MAIL
ckmailstatus();
#endif

View File

@@ -502,35 +502,50 @@ ckmailstatus()
}
}
#ifdef SIMPLE_MAIL
#if defined(SIMPLE_MAIL) || defined(SERVER_ADMIN_MSG)
void
read_simplemail()
read_simplemail(mbox, adminmsg)
char *mbox;
boolean adminmsg;
{
FILE* mb = fopen(mailbox, "r");
char curline[102], *msg;
FILE* mb = fopen(mbox, "r");
char curline[128], *msg;
boolean seen_one_already = FALSE;
#ifdef SIMPLE_MAIL
struct flock fl = { 0 };
fl.l_type = F_RDLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
#endif
const char *msgfrom = adminmsg
? "The voice of %s booms through the caverns:"
: "This message is from '%s'.";
if (!mb)
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. */
if (fcntl (fileno (mb), F_SETLKW, &fl) == -1)
if (!adminmsg
#ifdef SIMPLE_MAIL
&& fcntl (fileno (mb), F_SETLKW, &fl) == -1
#endif
)
goto bail;
errno = 0;
while (fgets(curline, 102, mb) != NULL) {
fl.l_type = F_UNLCK;
fcntl (fileno(mb), F_UNLCK, &fl);
pline("There is a%s message on this scroll.",
seen_one_already ? "nother" : "");
while (fgets(curline, 128, mb) != NULL) {
if (!adminmsg) {
#ifdef SIMPLE_MAIL
fl.l_type = F_UNLCK;
fcntl (fileno(mb), F_UNLCK, &fl);
#endif
pline("There is a%s message on this scroll.",
seen_one_already ? "nother" : "");
}
msg = strchr(curline, ':');
if (!msg)
@@ -538,28 +553,61 @@ read_simplemail()
*msg = '\0';
msg++;
pline("This message is from '%s'.", curline);
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;
#ifdef SIMPLE_MAIL
errno = 0;
fl.l_type = F_RDLCK;
fcntl(fileno(mb), F_SETLKW, &fl);
if (!adminmsg) {
fl.l_type = F_RDLCK;
fcntl(fileno(mb), F_SETLKW, &fl);
}
#endif
}
fl.l_type = F_UNLCK;
fcntl(fileno(mb), F_UNLCK, &fl);
#ifdef SIMPLE_MAIL
if (!adminmsg) {
fl.l_type = F_UNLCK;
fcntl(fileno(mb), F_UNLCK, &fl);
}
#endif
fclose(mb);
unlink(mailbox);
if (adminmsg)
display_nhwindow(WIN_MESSAGE, TRUE);
else
unlink(mailbox);
return;
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 */
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*/
void
readmail(otmp)
@@ -569,7 +617,7 @@ struct obj *otmp UNUSED;
register const char *mr = 0;
#endif /* DEF_MAILREADER */
#ifdef SIMPLE_MAIL
read_simplemail();
read_simplemail(mailbox, FALSE);
return;
#endif /* SIMPLE_MAIL */
#ifdef DEF_MAILREADER /* This implies that UNIX is defined */