From: jwalz Date: Sat, 5 Jan 2002 21:06:00 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: MOVE2GIT~3634 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a306da4b38162afafd8d7f76da3c60cf7eabf5c;p=nethack *** empty log message *** --- diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c new file mode 100644 index 000000000..2966a8e53 --- /dev/null +++ b/sys/vms/vmsmain.c @@ -0,0 +1,454 @@ +/* SCCS Id: @(#)vmsmain.c 3.3 2001/07/27 */ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* NetHack may be freely redistributed. See license for details. */ +/* main.c - VMS NetHack */ + +#include "hack.h" +#include "dlb.h" + +#include + +static void NDECL(whoami); +static void FDECL(process_options, (int, char **)); +static void NDECL(byebye); +#ifndef SAVE_ON_FATAL_ERROR +# ifndef __DECC +# define vms_handler_type int +# else +# define vms_handler_type unsigned int +# endif +extern void FDECL(VAXC$ESTABLISH, (vms_handler_type (*)(genericptr_t,genericptr_t))); +static vms_handler_type FDECL(vms_handler, (genericptr_t,genericptr_t)); +#include /* system service status codes */ +#endif + +static void NDECL(wd_message); +#ifdef WIZARD +static boolean wiz_error_flag = FALSE; +#endif + +int +main(argc,argv) +int argc; +char *argv[]; +{ + register int fd; +#ifdef CHDIR + register char *dir; +#endif + +#ifdef SECURE /* this should be the very first code executed */ + privoff(); + fflush((FILE *)0); /* force stdio to init itself */ + privon(); +#endif + + atexit(byebye); + hname = argv[0]; + hname = vms_basename(hname); /* name used in 'usage' type messages */ + hackpid = getpid(); + (void) umask(0); + + choose_windows(DEFAULT_WINDOW_SYS); + +#ifdef CHDIR /* otherwise no chdir() */ + /* + * See if we must change directory to the playground. + * (Perhaps hack is installed with privs and playground is + * inaccessible for the player.) + * The logical name HACKDIR is overridden by a + * -d command line option (must be the first option given) + */ + dir = nh_getenv("NETHACKDIR"); + if (!dir) dir = nh_getenv("HACKDIR"); +#endif + if(argc > 1) { +#ifdef CHDIR + if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') { + /* avoid matching "-dec" for DECgraphics; since the man page + * says -d directory, hope nobody's using -desomething_else + */ + argc--; + argv++; + dir = argv[0]+2; + if(*dir == '=' || *dir == ':') dir++; + if(!*dir && argc > 1) { + argc--; + argv++; + dir = argv[0]; + } + if(!*dir) + error("Flag -d must be followed by a directory name."); + } + if (argc > 1) +#endif /* CHDIR */ + + /* + * Now we know the directory containing 'record' and + * may do a prscore(). + */ + if (!strncmp(argv[1], "-s", 2)) { +#ifdef CHDIR + chdirx(dir, FALSE); +#endif + prscore(argc, argv); + exit(EXIT_SUCCESS); + } + } + +#ifdef CHDIR + /* move to the playground directory; 'termcap' might be found there */ + chdirx(dir, TRUE); +#endif + +#ifdef SECURE + /* disable installed privs while loading nethack.cnf and termcap, + and also while initializing terminal [$assign("TT:")]. */ + privoff(); +#endif + initoptions(); + init_nhwindows(&argc, argv); + whoami(); +#ifdef SECURE + privon(); +#endif + + /* + * It seems you really want to play. + */ + u.uhp = 1; /* prevent RIP on early quits */ +#ifndef SAVE_ON_FATAL_ERROR + /* used to clear hangup stuff while still giving standard traceback */ + VAXC$ESTABLISH(vms_handler); +#endif + (void) signal(SIGHUP, (SIG_RET_TYPE) hangup); + + process_options(argc, argv); /* command line options */ + +#ifdef WIZARD + if (wizard) + Strcpy(plname, "wizard"); + else +#endif + if (!*plname || !strncmpi(plname, "games", 4) || + !strcmpi(plname, "nethack")) + askname(); + plnamesuffix(); /* strip suffix from name; calls askname() */ + /* again if suffix was whole name */ + /* accepts any suffix */ +#ifdef WIZARD + if(!wizard) { +#endif + /* + * check for multiple games under the same name + * (if !locknum) or check max nr of players (otherwise) + */ + (void) signal(SIGQUIT,SIG_IGN); + (void) signal(SIGINT,SIG_IGN); + if(!locknum) + Sprintf(lock, "_%u%s", (unsigned)getuid(), plname); + getlock(); +#ifdef WIZARD + } else { + Sprintf(lock, "_%u%s", (unsigned)getuid(), plname); + getlock(); + } +#endif /* WIZARD */ + + dlb_init(); /* must be before newgame() */ + + /* + * Initialization of the boundaries of the mazes + * Both boundaries have to be even. + */ + x_maze_max = COLNO-1; + if (x_maze_max % 2) + x_maze_max--; + y_maze_max = ROWNO-1; + if (y_maze_max % 2) + y_maze_max--; + + /* + * Initialize the vision system. This must be before mklev() on a + * new game or before a level restore on a saved game. + */ + vision_init(); + + display_gamewindows(); + + if ((fd = restore_saved_game()) >= 0) { +#ifdef WIZARD + /* Since wizard is actually flags.debug, restoring might + * overwrite it. + */ + boolean remember_wiz_mode = wizard; +#endif + const char *fq_save = fqname(SAVEF, SAVEPREFIX, 0); + + (void) chmod(fq_save,0); /* disallow parallel restores */ + (void) signal(SIGINT, (SIG_RET_TYPE) done1); +#ifdef NEWS + if(iflags.news) { + display_file(NEWS, FALSE); + iflags.news = FALSE; /* in case dorecover() fails */ + } +#endif + pline("Restoring save file..."); + mark_synch(); /* flush output */ + if(!dorecover(fd)) + goto not_recovered; +#ifdef WIZARD + if(!wizard && remember_wiz_mode) wizard = TRUE; +#endif + check_special_room(FALSE); + wd_message(); + + if (discover || wizard) { + if (yn("Do you want to keep the save file?") == 'n') + (void) delete_savefile(); + else + (void) chmod(fq_save,FCMASK); /* back to readable */ + } + + flags.move = 0; + } else { +not_recovered: + player_selection(); + newgame(); + wd_message(); + + flags.move = 0; + set_wear(); + (void) pickup(1); + } + + moveloop(); + exit(EXIT_SUCCESS); + /*NOTREACHED*/ + return(0); +} + +static void +process_options(argc, argv) +int argc; +char *argv[]; +{ + int i; + + + /* + * Process options. + */ + while(argc > 1 && argv[1][0] == '-'){ + argv++; + argc--; + switch(argv[0][1]){ + case 'D': +#ifdef WIZARD + if(!strcmpi(nh_getenv("USER"), WIZARD_NAME)) { + wizard = TRUE; + break; + } + /* otherwise fall thru to discover */ + wiz_error_flag = TRUE; +#endif /* WIZARD */ + case 'X': + case 'x': + discover = TRUE; + break; +#ifdef NEWS + case 'n': + iflags.news = FALSE; + break; +#endif + case 'u': + if(argv[0][2]) + (void) strncpy(plname, argv[0]+2, sizeof(plname)-1); + else if(argc > 1) { + argc--; + argv++; + (void) strncpy(plname, argv[0], sizeof(plname)-1); + } else + raw_print("Player name expected after -u"); + break; + case 'I': + case 'i': + if (!strncmpi(argv[0]+1, "IBM", 3)) + switch_graphics(IBM_GRAPHICS); + break; + /* case 'D': */ + case 'd': + if (!strncmpi(argv[0]+1, "DEC", 3)) + switch_graphics(DEC_GRAPHICS); + break; + case 'p': /* profession (role) */ + if (argv[0][2]) { + if ((i = str2role(&argv[0][2])) >= 0) + flags.initrole = i; + } else if (argc > 1) { + argc--; + argv++; + if ((i = str2role(argv[0])) >= 0) + flags.initrole = i; + } + break; + case 'r': /* race */ + if (argv[0][2]) { + if ((i = str2race(&argv[0][2])) >= 0) + flags.initrace = i; + } else if (argc > 1) { + argc--; + argv++; + if ((i = str2race(argv[0])) >= 0) + flags.initrace = i; + } + break; + case '@': + flags.randomall = 1; + break; + default: + if ((i = str2role(&argv[0][1])) >= 0) { + flags.initrole = i; + break; + } + /* else raw_printf("Unknown option: %s", *argv); */ + } + } + + if(argc > 1) + locknum = atoi(argv[1]); +#ifdef MAX_NR_OF_PLAYERS + if(!locknum || locknum > MAX_NR_OF_PLAYERS) + locknum = MAX_NR_OF_PLAYERS; +#endif +} + +#ifdef CHDIR +void +chdirx(dir, wr) +const char *dir; +boolean wr; +{ +# ifndef HACKDIR + static const char *defdir = "."; +# else + static const char *defdir = HACKDIR; + + if(dir == (const char *)0) + dir = defdir; + else if (wr && !same_dir(HACKDIR, dir)) + /* If we're playing anywhere other than HACKDIR, turn off any + privs we may have been installed with. */ + privoff(); +# endif + + if(dir && chdir(dir) < 0) { + perror(dir); + error("Cannot chdir to %s.", dir); + } + + /* warn the player if we can't write the record file */ + if (wr) check_recordfile(dir); + + defdir = dir; +} +#endif /* CHDIR */ + +static void +whoami() +{ + /* + * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS + * 2. Use lowercase of $USER (if 1. fails) + * The resulting name is overridden by command line options. + * If everything fails, or if the resulting name is some generic + * account like "games" then eventually we'll ask him. + * Note that we trust the user here; it is possible to play under + * somebody else's name. + */ + register char *s; + + if (!*plname && (s = nh_getenv("USER"))) + (void) lcase(strncpy(plname, s, sizeof(plname)-1)); +} + +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)(); +#ifdef SHELL + extern unsigned long dosh_pid, mail_pid; + extern unsigned long FDECL(sys$delprc,(unsigned long *,const genericptr_t)); + + /* clean up any subprocess we've spawned that may still be hanging around */ + if (dosh_pid) (void) sys$delprc(&dosh_pid, 0), dosh_pid = 0; + if (mail_pid) (void) sys$delprc(&mail_pid, 0), mail_pid = 0; +#endif + + /* SIGHUP doesn't seem to do anything on VMS, so we fudge it here... */ + hup = (int(*)()) signal(SIGHUP, SIG_IGN); + if (!program_state.exiting++ && + hup != (int(*)()) SIG_DFL && hup != (int(*)()) SIG_IGN) + (void) (*hup)(); + +#ifdef CHDIR + (void) chdir(getenv("PATH")); +#endif +} + +#ifndef SAVE_ON_FATAL_ERROR +/* Condition handler to prevent byebye's hangup simulation + from saving the game after a fatal error has occurred. */ +/*ARGSUSED*/ +static vms_handler_type /* should be `unsigned long', but the -*/ +vms_handler(sigargs, mechargs) /*+ prototype in is screwed */ +genericptr_t sigargs, mechargs; /* [0] is argc, [1..argc] are the real args */ +{ + unsigned long condition = ((unsigned long *)sigargs)[1]; + + if (condition == SS$_ACCVIO /* access violation */ + || (condition >= SS$_ASTFLT && condition <= SS$_TBIT) + || (condition >= SS$_ARTRES && condition <= SS$_INHCHME)) { + program_state.done_hup = TRUE; /* pretend hangup has been attempted */ +# if defined(WIZARD) && !defined(BETA) + if (wizard) +# endif /*WIZARD && !BETA*/ +# if defined(WIZARD) || defined(BETA) + abort(); /* enter the debugger */ +# endif /*WIZARD || BETA*/ + } + return SS$_RESIGNAL; +} +#endif + +#ifdef PORT_HELP +void +port_help() +{ + /* + * Display VMS-specific help. Just show contents of the helpfile + * named by PORT_HELP. + */ + display_file(PORT_HELP, TRUE); +} +#endif /* PORT_HELP */ + +static void +wd_message() +{ +#ifdef WIZARD + if (wiz_error_flag) { + pline("Only user \"%s\" may access debug (wizard) mode.", + WIZARD_NAME); + pline("Entering discovery mode instead."); + } else +#endif + if (discover) + You("are in non-scoring discovery mode."); +} + +/*vmsmain.c*/