diff --git a/include/server.h b/include/server.h index 36b7438a..a0da6c1c 100644 --- a/include/server.h +++ b/include/server.h @@ -43,15 +43,15 @@ extern time_t update_time; extern int updating_mob; void mobility_init(void); - -/* thread entry points */ -void delete_lostitems(void *); void market_init(void); -void mobility_check(void *); -void player_kill_idle(void *); void update_main(void); void update_init(void); int update_trigger(time_t); -void shutdown_sequence(void *); +int shutdown_initiate(int); + +/* thread entry points */ +void delete_lostitems(void *); +void mobility_check(void *); +void player_kill_idle(void *); #endif diff --git a/info/shutdown.t b/info/shutdown.t index e081bf1c..811b9f16 100644 --- a/info/shutdown.t +++ b/info/shutdown.t @@ -2,7 +2,7 @@ .NA shutdown "Shut down the server" .LV Expert .SY "shutdown " -Shutdown the server in minutes. If is 0, +Shutdown the server in minutes. If is negative, then any previous shutdown request will be canceled. If the second argument is a "n" then updates will not be disabled (otherwise they will be). diff --git a/src/lib/commands/shut.c b/src/lib/commands/shut.c index c72304d7..2a21e190 100644 --- a/src/lib/commands/shut.c +++ b/src/lib/commands/shut.c @@ -49,43 +49,25 @@ shut(void) shutdown_minutes = onearg(player->argp[1], - "Time until shutdown in minutes (0 to abort shutdown sequence)? "); - if (shutdown_minutes < 0) - return RET_SYN; + "Time until shutdown in minutes (-1 to abort shutdown sequence)? "); if (!updates_disabled()) if (!(p = getstarg(player->argp[2], "Disable update [y]? ", buf)) || *p != 'n') disa(); - shutdown_was_pending = shutdown_pending; - shutdown_pending = shutdown_minutes + !!shutdown_minutes; - msgbuf[0] = '\0'; + shutdown_was_pending = shutdown_initiate(shutdown_minutes); + if (shutdown_was_pending < 0) + return RET_FAIL; + if (shutdown_was_pending) { - if (shutdown_minutes) { - sprintf(msgbuf, - ": The shutdown time has been changed to %d minutes!", - shutdown_minutes); + if (shutdown_minutes >= 0) { + pr("The shutdown time has been changed to %d minutes!", + shutdown_minutes); } else { - sprintf(msgbuf, ": The server shutdown has been cancelled!"); + pr("The server shutdown has been cancelled!"); } } else if (shutdown_minutes) { pr("Shutdown sequence begun.\n"); - logerror("Shutdown sequence begun"); - empth_create(PP_SHUTDOWN, shutdown_sequence, (50 * 1024), - 0, "shutdownSeq", "Counts down server shutdown", 0); - } - us = getnatp(player->cnum); - if (msgbuf[0]) { - sendmessage(us, 0, msgbuf, 1); - pr("%s\n", msgbuf + 2); - logerror("%s", msgbuf + 2); - } - if (shutdown_minutes) { - sprintf(msgbuf, ": The server will shut down in %d minutes!", - shutdown_minutes); - sendmessage(us, 0, msgbuf, 1); - pr("%s\n", msgbuf + 2); - logerror("%s", msgbuf + 2); } return RET_OK; } diff --git a/src/lib/subs/pr.c b/src/lib/subs/pr.c index cec1b316..d9e7a5f0 100644 --- a/src/lib/subs/pr.c +++ b/src/lib/subs/pr.c @@ -182,17 +182,26 @@ pr_inform(struct player *pl, char *format, ...) * Send C_FLASH text to everyone. * Format text to send using printf-style FORMAT and optional * arguments. It is assumed to be plain ASCII. + * Prefix text it with a header suitable for broadcast from deity. * Initiate an output queue flush, but do not wait for it to complete. */ void pr_wall(char *format, ...) { + time_t now; + struct tm *tm; char buf[4096]; /* UTF-8 */ + int n; struct player *p; va_list ap; + time(&now); + tm = localtime(&now); + n = sprintf(buf, "BROADCAST from %s @ %02d:%02d: ", + getnatp(0)->nat_cnam, tm->tm_hour, tm->tm_min); + va_start(ap, format); - (void)vsprintf(buf, format, ap); + (void)vsprintf(buf + n, format, ap); va_end(ap); for (p = player_next(0); p; p = player_next(p)) { if (p->state != PS_PLAYING) diff --git a/src/server/shutdown.c b/src/server/shutdown.c index bf819061..1086b1c6 100644 --- a/src/server/shutdown.c +++ b/src/server/shutdown.c @@ -42,46 +42,66 @@ int shutdown_pending; -void +static void shutdown_sequence(void *unused); + +int +shutdown_initiate(int mins_from_now) +{ + int old_pending = shutdown_pending; + + if (mins_from_now < 0) { + if (shutdown_pending) { + shutdown_pending = 0; + pr_wall("The server shutdown has been cancelled!\n"); + } + return old_pending; + } + + shutdown_pending = mins_from_now + 1; + + if (old_pending) { + pr_wall("The shutdown time has been changed to %d minutes!\n", + mins_from_now); + /* FIXME wake up shutdown_sequence() */ + } else { + if (!empth_create(PP_SHUTDOWN, shutdown_sequence, 50 * 1024, + 0, "shutdownSeq", "Counts down server shutdown", + NULL)) + return -1; + } + + return old_pending; +} + +static void shutdown_sequence(void *unused) { - struct natstr *god; - struct tm *tm; time_t now; - char header[100]; - if (shutdown_pending <= 0) { - shutdown_pending = 0; - logerror("shutdown called with 0 shutdown_pending"); - empth_exit(); - return; - } - god = getnatp(0); + pr_wall("The server will shut down in %d minutes!\n", + shutdown_pending - 1); + while (shutdown_pending > 0) { --shutdown_pending; time(&now); if (shutdown_pending <= 1440) { /* one day */ - tm = localtime(&now); - sprintf(header, "BROADCAST from %s @ %02d:%02d: ", - god->nat_cnam, tm->tm_hour, tm->tm_min); - if (!shutdown_pending) { - pr_wall("%sServer shutting down NOW!\n", header); + if (shutdown_pending == 0) { shutdwn(0); } else if (shutdown_pending == 1) { - pr_wall("%sServer shutting down in 1 minute!\n", header); + pr_wall("Server shutting down in 1 minute!\n"); } else if (shutdown_pending <= 5) { - pr_wall("%sServer shutting down in %d minutes!\n", - header, shutdown_pending); + pr_wall("Server shutting down in %d minutes!\n", + shutdown_pending); } else if (shutdown_pending <= 60 && shutdown_pending % 10 == 0) { - pr_wall("%sThe server will be shutting down in %d minutes!\n", - header, shutdown_pending); + pr_wall("The server will be shutting down in %d minutes!\n", + shutdown_pending); } else if (shutdown_pending % 60 == 0) { - pr_wall("%sThe server will be shutting down %d hours from now.\n", - header, shutdown_pending / 60); + pr_wall("The server will be shutting down %d hours from now.\n", + shutdown_pending / 60); } } + /* FIXME error due to late wakeup accumulates */ empth_sleep(now + 60); } - empth_exit(); }