1.4.5 (????/??/??)
* Reset offset if necessary to show at least one game to avoid things
like "(15-14 of 14)".
+ * Backup the savefile before starting nethack to help prevent more
+ lost games. Note this must be explicitly configured in the
+ configuration file.
1.4.4 (2004/03/07)
* Show total number of games in progress below the list, useful if
"rc_template" { return TYPE_PATH_CANNED; }
"passwd" { return TYPE_PATH_PASSWD; }
"lockfile" { return TYPE_PATH_LOCKFILE; }
+"savefilefmt" { return TYPE_PATH_SAVEFILEFMT; }
\n { line++; col = 0; }
%token TYPE_SUSER TYPE_SGROUP TYPE_SGID TYPE_SUID TYPE_MAX
%token TYPE_PATH_NETHACK TYPE_PATH_DGLDIR TYPE_PATH_SPOOL
%token TYPE_PATH_BANNER TYPE_PATH_CANNED TYPE_PATH_CHROOT
-%token TYPE_PATH_PASSWD TYPE_PATH_LOCKFILE TYPE_MALSTRING
+%token TYPE_PATH_PASSWD TYPE_PATH_LOCKFILE TYPE_PATH_SAVEFILEFMT
+%token TYPE_MALSTRING
%token <s> TYPE_VALUE
%token <i> TYPE_NUMBER
%type <kt> KeyType
myconfig->passwd = strdup($3);
break;
+ case TYPE_PATH_SAVEFILEFMT:
+ if (myconfig->savefilefmt) free(myconfig->savefilefmt);
+ myconfig->savefilefmt = strdup($3);
+ break;
+
default:
fprintf(stderr, "%s:%d: token %s does not take a string, bailing out\n",
config, line, lookup_token($1));
| TYPE_PATH_CANNED { $$ = TYPE_PATH_CANNED; }
| TYPE_PATH_PASSWD { $$ = TYPE_PATH_PASSWD; }
| TYPE_PATH_LOCKFILE { $$ = TYPE_PATH_LOCKFILE; }
+ | TYPE_PATH_SAVEFILEFMT { $$ = TYPE_PATH_SAVEFILEFMT; }
;
%%
Ignored; solely for compatibility with
.B
login(1)
-.SH CRASH RECOVERY
+.SH "CRASH RECOVERY"
.PP
If a user somehow disconnects in an unclean way,
.I
.I
dgamelaunch
will ask the user for permission to send it the SIGTERM signal, which causes
-nethack to terminate quickly.
+nethack to terminate quickly (without leaving a savefile usually).
+.PP
+In some cases (e.g. at "Restoring save file...--More--") nethack doesn't leave
+a savefile if sent SIGHUP. To avoid loss of games,
+.I
+dgamelaunch
+can backup the savefile. A human must then restore the backup if necessary.
+This must be configured with the
+.B
+savefilefmt
+option in the configuration file.
.SH AUTHORS
.PP
M. Drew Streib wrote the original version.
/* ************************************************************* */
/* ************************************************************* */
+/*
+ * Backup the savefile, if configured.
+ * Returns non-zero if successful, otherwise an error message has been
+ * given already.
+ */
+int
+backup_savefile (void)
+{
+ char buf[1024];
+ char *f, *p, *end;
+ int ispercent = 0, n;
+ int in, out;
+
+ f = myconfig->savefilefmt;
+
+ if (*f == '\0')
+ return 1;
+ if (me == NULL)
+ graceful_exit (147);
+
+ p = buf;
+ end = buf + sizeof(buf) - 10; /* make sure we can add .bak */
+ while (*f)
+ {
+ if (ispercent)
+ {
+ switch (*f)
+ {
+ case 'u':
+ snprintf (p, end + 1 - p, "%d", myconfig->shed_uid);
+ while (*p != '\0')
+ p++;
+ break;
+ case 'n':
+ snprintf (p, end + 1 - p, "%s", me->username);
+ while (*p != '\0')
+ p++;
+ break;
+ default:
+ *p = *f;
+ if (p < end)
+ p++;
+ }
+ ispercent = 0;
+ }
+ else
+ {
+ if (*f == '%')
+ ispercent = 1;
+ else
+ {
+ *p = *f;
+ if (p < end)
+ p++;
+ }
+ }
+ f++;
+ }
+ *p = '\0';
+
+ /*fprintf(stderr, "***\n[SAVEFILE=%s]\n***\n", buf);
+ sleep(3);*/
+ in = open (buf, O_RDONLY);
+ if (in == -1)
+ {
+ if (errno == ENOENT)
+ return 1; /* Nothing to back up */
+ else
+ {
+ fprintf (stderr, "Cannot open savefile '%s'\n", buf);
+ perror ("for input");
+ return 0;
+ }
+ }
+ strcpy (p, ".bak");
+ out = open (buf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (out == -1)
+ {
+ close (in);
+ fprintf (stderr, "Cannot open backup savefile '%s'\n", buf);
+ perror ("for output");
+ return 0;
+ }
+
+ while ((n = read (in, buf, sizeof(buf))) > 0)
+ {
+ n = write (out, buf, n);
+ if (n < 0)
+ break;
+ }
+ close (out);
+ close (in);
+ if (n < 0)
+ perror ("I/O error while backing up savefile");
+ return n >= 0;
+}
+
/* TODO: Some of the messages here (sorry no nethack for you!) are nethack specific
* as may be some code... don't think so though. Globalize it. */
int
endwin ();
signal(SIGWINCH, SIG_DFL);
+ if (!backup_savefile ())
+ graceful_exit (5);
+
/* environment */
snprintf (atrcfilename, 81, "@%s", rcfilename);
passwd = "/dgl-login"
lockfile = "/dgl-lock"
+
+# From inside the jail, the path to the savefile. %u is replaced by the
+# decimal representation of shed_uid, %n is replaced by the player's
+# user name. Before starting the game, this file is copied to its name
+# with ".bak" appended. Set to an empty string to disable this copying.
+savefilefmt = "/var/games/nethack/save/%u%n.gz"
uid_t shed_uid;
gid_t shed_gid;
unsigned long max;
+ char* savefilefmt;
};
/* Global variables */
/* shed_group = */ "games",
/* shed_uid = */ 5,
/* shed_gid = */ 60, /* games:games in Debian */
- /* max = */ 64000
+ /* max = */ 64000,
+ /* savefilefmt = */ "" /* don't do this by default */
};
char* config = NULL;
if (!myconfig->spool) myconfig->spool = defconfig.spool;
if (!myconfig->passwd) myconfig->passwd = defconfig.passwd;
if (!myconfig->lockfile) myconfig->lockfile = defconfig.lockfile;
+ if (!myconfig->savefilefmt) myconfig->savefilefmt = defconfig.savefilefmt;
}