From 151dcad8fa1da3190b5afbc39ae338022697dfb9 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Tue, 16 Jan 2007 04:54:38 +0000 Subject: [PATCH] hangup revamp (trunk only) [See cvs log for src/cmd.c for more complete description.] This turns clearlocks() into a no-op during the period when the UNIX port is asking the user to confirm whether to overwrite an existing game. Also, this removes the duplication of code and function between hangup() and end_of_input(), and it simplifies the check for whether hangups are supported by adding new macro HANGUPHANDLING. (I don't think global.h is the best place to be defining that but I couldn't figure out where else it would fit, other than repeating for individual xxxconf.h files.) And adds a couple more done_hup checks to try to cope with situations where rhack() is being bypassed. Lastly, having readchar() return EOF was ignored for non-UNIX configs; now everybody gets ESC instead of letting EOF be seen further inside the core. --- doc/fixes35.0 | 2 ++ include/decl.h | 5 +++-- include/extern.h | 7 ++++--- include/global.h | 9 ++++++++- src/allmain.c | 5 ++++- src/files.c | 10 +++++++++- src/mon.c | 8 +++++++- src/save.c | 34 +++------------------------------- sys/unix/unixmain.c | 2 ++ sys/unix/unixunix.c | 3 ++- sys/vms/vmsmain.c | 17 +++++++++-------- 11 files changed, 53 insertions(+), 49 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index aeb5014c9..582ff5513 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -189,6 +189,8 @@ can't drop part of a stack of N weapons welded to hero's hand Platform- and/or Interface-Specific Fixes ----------------------------------------- unix: new -wwindowtype option +unix: don't clobber old level files if 2nd hangup/disconnect occurs while + reconnected user is responding to the "destroy old game?" prompt win32gui: better handling of "more" prompt for messages that would have scrolled off the window win32gui: set correct checkmark on "Lock Windows" menu item on startup diff --git a/include/decl.h b/include/decl.h index c4b4db3ed..3c8b85bb7 100644 --- a/include/decl.h +++ b/include/decl.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)decl.h 3.5 2005/11/19 */ +/* SCCS Id: @(#)decl.h 3.5 2007/01/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -145,9 +145,10 @@ E struct linfo level_info[MAXLINFO]; E NEARDATA struct sinfo { int gameover; /* self explanatory? */ int stopprint; /* inhibit further end of game disclosure */ -#if defined(UNIX) || defined(VMS) || defined (__EMX__) || defined(WIN32) +#ifdef HANGUPHANDLING volatile int done_hup; /* SIGHUP or moral equivalent received * -- no more screen output */ + int preserve_locks; /* don't remove level files prior to exit */ #endif int something_worth_saving; /* in case of panic */ int panicking; /* `panic' is in progress */ diff --git a/include/extern.h b/include/extern.h index 6ceeba1d7..8e5ccc499 100644 --- a/include/extern.h +++ b/include/extern.h @@ -197,6 +197,10 @@ E void NDECL(confdir); E int FDECL(isok, (int,int)); E int FDECL(get_adjacent_loc, (const char *, const char *, XCHAR_P, XCHAR_P, coord *)); E const char *FDECL(click_to_cmd, (int,int,int)); +#ifdef HANGUPHANDLING +E void FDECL(hangup, (int)); +E void NDECL(end_of_input); +#endif E char NDECL(readchar); #ifdef WIZARD E void NDECL(sanity_check); @@ -1937,9 +1941,6 @@ E void NDECL(rumor_check); /* ### save.c ### */ E int NDECL(dosave); -#if defined(UNIX) || defined(VMS) || defined(__EMX__) || defined(WIN32) -E void FDECL(hangup, (int)); -#endif E int NDECL(dosave0); #ifdef INSURANCE E void NDECL(savestateinlock); diff --git a/include/global.h b/include/global.h index 3c5b55242..f98c53936 100644 --- a/include/global.h +++ b/include/global.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)global.h 3.5 2006/10/17 */ +/* SCCS Id: @(#)global.h 3.5 2007/01/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -269,6 +269,13 @@ typedef char nhptext; # endif #endif +#if defined(UNIX) || defined(VMS) || defined(__EMX__) || defined(WIN32) +# define HANGUPHANDLING +#endif +#if defined(SAFERHANGUP) && !defined(HANGUPHANDLING) +# undef SAFERHANGUP +#endif + #define Sprintf (void) sprintf #define Strcat (void) strcat diff --git a/src/allmain.c b/src/allmain.c index 899ab7fb3..de890cac6 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)allmain.c 3.5 2006/11/27 */ +/* SCCS Id: @(#)allmain.c 3.5 2007/01/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -72,6 +72,9 @@ boolean resuming; context.move = 0; for(;;) { +#ifdef SAFERHANGUP + if (program_state.done_hup) end_of_input(); +#endif get_nh_event(); #ifdef POSITIONBAR do_positionbar(); diff --git a/src/files.c b/src/files.c index 4ab5aeeb6..6466b0087 100644 --- a/src/files.c +++ b/src/files.c @@ -556,20 +556,28 @@ int lev; void clearlocks() { +#ifdef HANGUPHANDLING + if (program_state.preserve_locks) return; +#endif #if !defined(PC_LOCKING) && defined(MFLOPPY) && !defined(AMIGA) eraseall(levels, alllevels); if (ramdisk) eraseall(permbones, alllevels); #else + { register int x; +# ifndef NO_SIGNAL + (void) signal(SIGINT, SIG_IGN); +# endif # if defined(UNIX) || defined(VMS) sethanguphandler((void FDECL((*),(int)))SIG_IGN); # endif /* can't access maxledgerno() before dungeons are created -dlc */ for (x = (n_dgns ? maxledgerno() : 0); x >= 0; x--) delete_levelfile(x); /* not all levels need be present */ -#endif + } +#endif /* ?PC_LOCKING,&c */ } #if defined(SELECTSAVED) diff --git a/src/mon.c b/src/mon.c index f9ad7902a..d5103a162 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mon.c 3.5 2006/10/20 */ +/* SCCS Id: @(#)mon.c 3.5 2007/01/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -581,6 +581,12 @@ movemon() */ for(mtmp = fmon; mtmp; mtmp = nmtmp) { +#ifdef SAFERHANGUP + if (program_state.done_hup) { + somebody_can_move = FALSE; + break; + } +#endif nmtmp = mtmp->nmon; if (DEADMONSTER(mtmp)) continue; diff --git a/src/save.c b/src/save.c index 4db45bf26..3316db5ec 100644 --- a/src/save.c +++ b/src/save.c @@ -119,7 +119,6 @@ dosave() program_state.done_hup = 0; #endif if(dosave0()) { - program_state.something_worth_saving = 0; u.uhp = -1; /* universal game's over indicator */ /* make sure they see the Saving message */ display_nhwindow(WIN_MESSAGE, TRUE); @@ -130,35 +129,6 @@ dosave() return 0; } - -#if defined(UNIX) || defined(VMS) || defined (__EMX__) || defined(WIN32) -/*ARGSUSED*/ -void -hangup(sig_unused) /* called as signal() handler, so sent at least one arg */ -int sig_unused; -{ -# ifdef NOSAVEONHANGUP - (void) signal(SIGINT, SIG_IGN); - clearlocks(); - terminate(EXIT_FAILURE); -# else /* SAVEONHANGUP */ - if (!program_state.done_hup++) { -# ifndef SAFERHANGUP - /* When using SAFERHANGUP, the done_hup flag it tested in rhack - * and actual hangup behavior occurs then. This is 'safer' - * because it disallows certain cheats and also protects - * against losing objects in the process of being thrown. */ - if (program_state.something_worth_saving) - (void) dosave0(); - - clearlocks(); - terminate(EXIT_FAILURE); -# endif /* !SAFERHANGUP */ - } -# endif /* !NOSAVEONHANGUP */ -} -#endif - /* returns 1 if save successful */ int dosave0() @@ -169,7 +139,7 @@ dosave0() d_level uz_save; char whynot[BUFSZ]; - if (!SAVEF[0]) + if (!program_state.something_worth_saving || !SAVEF[0]) return 0; fq_save = fqname(SAVEF, SAVEPREFIX, 1); /* level files take 0 */ @@ -316,6 +286,8 @@ dosave0() delete_levelfile(ledger_no(&u.uz)); delete_levelfile(0); nh_compress(fq_save); + /* this should probably come sooner... */ + program_state.something_worth_saving = 0; return(1); } diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 11c340ef7..18f1fea18 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -157,6 +157,7 @@ char *argv[]; * It seems you really want to play. */ u.uhp = 1; /* prevent RIP on early quits */ + program_state.preserve_locks = 1; sethanguphandler((SIG_RET_TYPE)hangup); process_options(argc, argv); /* command line options */ @@ -212,6 +213,7 @@ char *argv[]; getlock(); } #endif /* WIZARD */ + program_state.preserve_locks = 0; /* after getlock() */ dlb_init(); /* must be before newgame() */ diff --git a/sys/unix/unixunix.c b/sys/unix/unixunix.c index 9f04b540b..e333e4ae1 100644 --- a/sys/unix/unixunix.c +++ b/sys/unix/unixunix.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)unixunix.c 3.5 1994/11/07 */ +/* SCCS Id: @(#)unixunix.c 3.5 2007/01/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -71,6 +71,7 @@ eraseoldlocks() { register int i; + program_state.preserve_locks = 0; /* not required but shows intent */ /* cannot use maxledgerno() here, because we need to find a lock name * before starting everything (including the dungeon initialization * that sets astral_level, needed for maxledgerno()) up diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c index 5a3796693..379464535 100644 --- a/sys/vms/vmsmain.c +++ b/sys/vms/vmsmain.c @@ -379,11 +379,7 @@ whoami() static void byebye() { - /* Different versions of both VAX C and GNU C use different return types - for signal functions. Return type 'int' along with the explicit casts - below satisfy the most combinations of compiler vs . - */ - int (*hup)(); + void FDECL((*hup), (int)); #ifdef SHELL extern unsigned long dosh_pid, mail_pid; extern unsigned long FDECL(sys$delprc,(unsigned long *,const genericptr_t)); @@ -394,10 +390,15 @@ byebye() #endif /* SIGHUP doesn't seem to do anything on VMS, so we fudge it here... */ - hup = (int(*)()) signal(SIGHUP, SIG_IGN); + hup = (void FDECL((*),(int))) signal(SIGHUP, SIG_IGN); if (!program_state.exiting++ && - hup != (int(*)()) SIG_DFL && hup != (int(*)()) SIG_IGN) - (void) (*hup)(); + hup != (void FDECL((*),(int))) SIG_DFL && + hup != (void FDECL((*),(int))) SIG_IGN) { + (*hup)(SIGHUP); +#ifdef SAFERHANGUP + end_of_input(); +#endif + } #ifdef CHDIR (void) chdir(getenv("PATH"));