home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / vms / vmsmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-24  |  9.6 KB  |  407 lines

  1. /*    SCCS Id: @(#)vmsmain.c    3.1    93/01/24    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4. /* main.c - VMS NetHack */
  5.  
  6. #include "hack.h"
  7.  
  8. #include <signal.h>
  9.  
  10. static void NDECL(whoami);
  11. static void FDECL(process_options, (int, char **));
  12. static void NDECL(byebye);
  13. #ifndef SAVE_ON_FATAL_ERROR
  14. # ifndef __DECC
  15. extern void FDECL(VAXC$ESTABLISH, (int (*)(genericptr_t,genericptr_t)));
  16. # endif
  17. static int FDECL(vms_handler, (genericptr_t,genericptr_t));
  18. #include <ssdef.h>    /* system service status codes */
  19. #endif
  20.  
  21. int
  22. main(argc,argv)
  23. int argc;
  24. char *argv[];
  25. {
  26.     register int fd;
  27. #ifdef CHDIR
  28.     register char *dir;
  29. #endif
  30.  
  31. #ifdef SECURE    /* this should be the very first code executed */
  32.     privoff();
  33.     fflush((FILE *)0);    /* force stdio to init itself */
  34.     privon();
  35. #endif
  36.  
  37.     atexit(byebye);
  38.     hname = argv[0];
  39.     gethdate(hname);        /* find executable's creation date */
  40.     hname = basename(hname);    /* name used in 'usage' type messages */
  41.     hackpid = getpid();
  42.     (void) umask(0);
  43.  
  44.     choose_windows(DEFAULT_WINDOW_SYS);
  45.  
  46. #ifdef CHDIR            /* otherwise no chdir() */
  47.     /*
  48.      * See if we must change directory to the playground.
  49.      * (Perhaps hack is installed with privs and playground is
  50.      *  inaccessible for the player.)
  51.      * The logical name HACKDIR is overridden by a
  52.      *  -d command line option (must be the first option given)
  53.      */
  54.     dir = getenv("NETHACKDIR");
  55.     if (!dir) dir = getenv("HACKDIR");
  56. #endif
  57.     if(argc > 1) {
  58. #ifdef CHDIR
  59.         if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
  60.         /* avoid matching "-dec" for DECgraphics; since the man page
  61.          * says -d directory, hope nobody's using -desomething_else
  62.          */
  63.         argc--;
  64.         argv++;
  65.         dir = argv[0]+2;
  66.         if(*dir == '=' || *dir == ':') dir++;
  67.         if(!*dir && argc > 1) {
  68.             argc--;
  69.             argv++;
  70.             dir = argv[0];
  71.         }
  72.         if(!*dir)
  73.             error("Flag -d must be followed by a directory name.");
  74.         } else
  75. #endif /* CHDIR */
  76.  
  77.     /*
  78.      * Now we know the directory containing 'record' and
  79.      * may do a prscore().
  80.      */
  81.         if (!strncmp(argv[1], "-s", 2)) {
  82. #ifdef CHDIR
  83.         chdirx(dir, FALSE);
  84. #endif
  85.         prscore(argc, argv);
  86.         exit(0);
  87.         }
  88.     }
  89.  
  90. #ifdef CHDIR
  91.     /* move to the playground directory; 'termcap' might be found there */
  92.     chdirx(dir, TRUE);
  93. #endif
  94.  
  95.     initoptions();
  96.     init_nhwindows();
  97.     whoami();
  98.  
  99.     /*
  100.      * It seems you really want to play.
  101.      */
  102.     setrandom();
  103.     u.uhp = 1;    /* prevent RIP on early quits */
  104. #ifndef SAVE_ON_FATAL_ERROR
  105.     /* used to clear hangup stuff while still giving standard traceback */
  106.     VAXC$ESTABLISH(vms_handler);
  107. #endif
  108.     (void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
  109.  
  110.     process_options(argc, argv);    /* command line options */
  111.  
  112. #ifdef WIZARD
  113.     if (wizard)
  114.         Strcpy(plname, "wizard");
  115.     else
  116. #endif
  117.     if(!*plname || !strncmp(plname, "games", 4))
  118.         askname();
  119.     plnamesuffix();        /* strip suffix from name; calls askname() */
  120.                 /* again if suffix was whole name */
  121.                 /* accepts any suffix */
  122. #ifdef WIZARD
  123.     if(!wizard) {
  124. #endif
  125.         /*
  126.          * check for multiple games under the same name
  127.          * (if !locknum) or check max nr of players (otherwise)
  128.          */
  129.         (void) signal(SIGQUIT,SIG_IGN);
  130.         (void) signal(SIGINT,SIG_IGN);
  131.         if(!locknum)
  132.             Sprintf(lock, "_%u%s", (unsigned)getuid(), plname);
  133.         getlock();
  134. #ifdef WIZARD
  135.     } else {
  136.         Sprintf(lock, "_%u%s", (unsigned)getuid(), plname);
  137.         getlock();
  138.     }
  139. #endif /* WIZARD */
  140.  
  141.     /*
  142.      * Initialisation of the boundaries of the mazes
  143.      * Both boundaries have to be even.
  144.      */
  145.  
  146.     x_maze_max = COLNO-1;
  147.     if (x_maze_max % 2)
  148.         x_maze_max--;
  149.     y_maze_max = ROWNO-1;
  150.     if (y_maze_max % 2)
  151.         y_maze_max--;
  152.  
  153.     /*
  154.      *  Initialize the vision system.  This must be before mklev() on a
  155.      *  new game or before a level restore on a saved game.
  156.      */
  157.     vision_init();
  158.  
  159.     display_gamewindows();
  160.  
  161.     set_savefile_name();
  162.     if((fd = open_savefile()) >= 0 &&
  163.        /* if not up-to-date, quietly unlink file via false condition */
  164.        (uptodate(fd) || delete_savefile())) {
  165. #ifdef WIZARD
  166.         /* Since wizard is actually flags.debug, restoring might
  167.          * overwrite it.
  168.          */
  169.         boolean remember_wiz_mode = wizard;
  170. #endif
  171.         (void) chmod(SAVEF,0);    /* disallow parallel restores */
  172.         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  173. #ifdef NEWS
  174.         if(flags.news) display_file(NEWS, FALSE);
  175. #endif
  176.         pline("Restoring save file...");
  177.         mark_synch();    /* flush output */
  178.         if(!dorecover(fd))
  179.             goto not_recovered;
  180. #ifdef WIZARD
  181.         if(!wizard && remember_wiz_mode) wizard = TRUE;
  182. #endif
  183.         pline("Hello %s, welcome back to NetHack!", plname);
  184.         check_special_room(FALSE);
  185. #ifdef EXPLORE_MODE
  186.         if (discover)
  187.             You("are in non-scoring discovery mode.");
  188. #endif
  189. #if defined(EXPLORE_MODE) || defined(WIZARD)
  190.         if (discover || wizard) {
  191.             if (yn("Do you want to keep the save file?") == 'n')
  192.                 (void) delete_savefile();
  193.             else
  194.                 (void) chmod(SAVEF,FCMASK); /* back to readable */
  195.         }
  196. #endif
  197.         flags.move = 0;
  198.     } else {
  199. not_recovered:
  200.         player_selection();
  201.         newgame();
  202.         /* give welcome message before pickup messages */
  203.         pline("Hello %s, welcome to NetHack!", plname);
  204. #ifdef EXPLORE_MODE
  205.         if (discover)
  206.             You("are in non-scoring discovery mode.");
  207. #endif
  208.         flags.move = 0;
  209.         set_wear();
  210.         pickup(1);
  211.     }
  212.  
  213.     flags.moonphase = phase_of_the_moon();
  214.     if(flags.moonphase == FULL_MOON) {
  215.         You("are lucky!  Full moon tonight.");
  216.         change_luck(1);
  217.     } else if(flags.moonphase == NEW_MOON) {
  218.         pline("Be careful!  New moon tonight.");
  219.     }
  220.     if ((flags.friday13 = friday_13th()) != 0) {
  221.         pline("Watch out!  Bad things can happen on Friday the 13th.");
  222.         change_luck(-1);
  223.     }
  224.  
  225.     initrack();
  226.  
  227.     moveloop();
  228.     return(0);
  229. }
  230.  
  231. static void
  232. process_options(argc, argv)
  233. int argc;
  234. char *argv[];
  235. {
  236.     /*
  237.      * Process options.
  238.      */
  239.     while(argc > 1 && argv[1][0] == '-'){
  240.         argv++;
  241.         argc--;
  242.         switch(argv[0][1]){
  243. #if defined(WIZARD) || defined(EXPLORE_MODE)
  244. # ifndef EXPLORE_MODE
  245.         case 'X':
  246.         case 'x':
  247. # endif
  248.         case 'D':
  249. # ifdef WIZARD
  250.             if(!strcmpi(getenv("USER"), WIZARD_NAME)) {
  251.                 wizard = TRUE;
  252.                 break;
  253.             }
  254.             /* otherwise fall thru to discover */
  255. # endif
  256. # ifdef EXPLORE_MODE
  257.         case 'X':
  258.         case 'x':
  259.             discover = TRUE;
  260. # endif
  261.             break;
  262. #endif
  263. #ifdef NEWS
  264.         case 'n':
  265.             flags.news = FALSE;
  266.             break;
  267. #endif
  268.         case 'u':
  269.             if(argv[0][2])
  270.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  271.             else if(argc > 1) {
  272.               argc--;
  273.               argv++;
  274.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  275.             } else
  276.                 raw_print("Player name expected after -u");
  277.             break;
  278.         case 'I':
  279.         case 'i':
  280.             if (!strncmpi(argv[0]+1, "IBM", 3))
  281.                 switch_graphics(IBM_GRAPHICS);
  282.             break;
  283.         /*  case 'D': */
  284.         case 'd':
  285.             if (!strncmpi(argv[0]+1, "DEC", 3))
  286.                 switch_graphics(DEC_GRAPHICS);
  287.             break;
  288.         default:
  289.             /* allow -T for Tourist, etc. */
  290.             (void) strncpy(pl_character, argv[0]+1,
  291.                 sizeof(pl_character)-1);
  292.  
  293.             /* raw_printf("Unknown option: %s", *argv); */
  294.         }
  295.     }
  296.  
  297.     if(argc > 1)
  298.         locknum = atoi(argv[1]);
  299. #ifdef MAX_NR_OF_PLAYERS
  300.     if(!locknum || locknum > MAX_NR_OF_PLAYERS)
  301.         locknum = MAX_NR_OF_PLAYERS;
  302. #endif
  303. }
  304.  
  305. #ifdef CHDIR
  306. void
  307. chdirx(dir, wr)
  308. char *dir;
  309. boolean wr;
  310. {
  311. # ifndef HACKDIR
  312.     static char *defdir = ".";
  313. # else
  314.     static char *defdir = HACKDIR;
  315.  
  316.     if(dir == NULL)
  317.         dir = defdir;
  318.     else if (wr && !same_dir(HACKDIR, dir))
  319.         /* If we're playing anywhere other than HACKDIR, turn off any
  320.            privs we may have been installed with. */
  321.         privoff();
  322. # endif
  323.  
  324.     if(dir && chdir(dir) < 0) {
  325.         perror(dir);
  326.         error("Cannot chdir to %s.", dir);
  327.     }
  328.  
  329.     /* warn the player if we can't write the record file */
  330.     if (wr) check_recordfile(dir);
  331.  
  332.     defdir = dir;
  333. }
  334. #endif /* CHDIR */
  335.  
  336. static void
  337. whoami()
  338. {
  339.     /*
  340.      * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
  341.      *            2. Use lowercase of $USER  (if 1. fails)
  342.      * The resulting name is overridden by command line options.
  343.      * If everything fails, or if the resulting name is some generic
  344.      * account like "games" then eventually we'll ask him.
  345.      * Note that we trust the user here; it is possible to play under
  346.      * somebody else's name.
  347.      */
  348.     register char *s;
  349.  
  350.     if (!*plname && (s = getenv("USER")))
  351.         (void) lcase(strncpy(plname, s, sizeof(plname)-1));
  352. }
  353.  
  354. static void
  355. byebye()
  356. {
  357.     /*    Different versions of both VAX C and GNU C use different return types
  358.     for signal functions.  Return type 'int' along with the explicit casts
  359.     below satisfy the most combinations of compiler vs <signal.h>.
  360.      */
  361.     int (*hup)();
  362. #ifdef SHELL
  363.     extern unsigned long dosh_pid, mail_pid;
  364.     extern unsigned long FDECL(SYS$DELPRC,(unsigned long *,const genericptr_t));
  365.  
  366.     /* clean up any subprocess we've spawned that may still be hanging around */
  367.     if (dosh_pid) (void) SYS$DELPRC(&dosh_pid, 0), dosh_pid = 0;
  368.     if (mail_pid) (void) SYS$DELPRC(&mail_pid, 0), mail_pid = 0;
  369. #endif
  370.  
  371.     /* SIGHUP doesn't seem to do anything on VMS, so we fudge it here... */
  372.     hup = (int(*)()) signal(SIGHUP, SIG_IGN);
  373.     if (hup != (int(*)()) SIG_DFL && hup != (int(*)()) SIG_IGN)
  374.     (void) (*hup)();
  375.  
  376. #ifdef CHDIR
  377.     (void) chdir(getenv("PATH"));
  378. #endif
  379. }
  380.  
  381. #ifndef SAVE_ON_FATAL_ERROR
  382. /* Condition handler to prevent byebye's hangup simulation
  383.    from saving the game after a fatal error has occurred.  */
  384. static int            /* should be `unsigned long', but the -*/
  385. vms_handler(sigargs, mechargs)    /*+ prototype in <signal.h> is screwed */
  386. genericptr_t sigargs, mechargs;    /* [0] is argc, [1..argc] are the real args */
  387. {
  388.     extern boolean hu;        /* src/save.c */
  389.     unsigned long condition = ((unsigned long *)sigargs)[1];
  390.  
  391.     if (condition == SS$_ACCVIO        /* access violation */
  392.      || (condition >= SS$_ASTFLT && condition <= SS$_TBIT)
  393.      || (condition >= SS$_ARTRES && condition <= SS$_INHCHME)) {
  394.     hu = TRUE;    /* pretend that hangup has already been attempted */
  395. # if defined(WIZARD) && !defined(BETA)
  396.     if (wizard)
  397. # endif /*WIZARD && !BETA*/
  398. # if defined(WIZARD) ||  defined(BETA)
  399.         abort();    /* enter the debugger */
  400. # endif /*WIZARD || BETA*/
  401.     }
  402.     return SS$_RESIGNAL;
  403. }
  404. #endif
  405.  
  406. /*vmsmain.c*/
  407.