home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / unix / unixmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  9.1 KB  |  421 lines

  1. /*    SCCS Id: @(#)unixmain.c    3.1    92/12/04    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* main.c - Unix NetHack */
  6.  
  7. #include "hack.h"
  8.  
  9. #include <signal.h>
  10. #include <pwd.h>
  11. #ifndef O_RDONLY
  12. #include <fcntl.h>
  13. #endif
  14.  
  15. #if !defined(_BULL_SOURCE) && !defined(sgi)
  16. # if defined(POSIX_TYPES) || defined(SVR4)
  17. extern struct passwd *FDECL(getpwuid,(uid_t));
  18. # else
  19. extern struct passwd *FDECL(getpwuid,(int));
  20. # endif
  21. #endif
  22. extern struct passwd *FDECL(getpwnam,(const char *));
  23. #ifdef CHDIR
  24. static void chdirx();
  25. #endif /* CHDIR */
  26. static boolean whoami();
  27. static void FDECL(process_options, (int, char **));
  28.  
  29. int
  30. main(argc,argv)
  31. int argc;
  32. char *argv[];
  33. {
  34.     register int fd;
  35. #ifdef CHDIR
  36.     register char *dir;
  37. #endif
  38.     boolean exact_username;
  39.  
  40.     hname = argv[0];
  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 runs suid and playground is inaccessible
  50.      *  for the player.)
  51.      * The environment variable 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,0);
  84. #endif
  85.         prscore(argc, argv);
  86.         exit(0);
  87.         }
  88.     }
  89.  
  90.     initoptions();
  91.     init_nhwindows();
  92.     exact_username = whoami();
  93.  
  94.     /*
  95.      * It seems you really want to play.
  96.      */
  97.     setrandom();
  98.     u.uhp = 1;    /* prevent RIP on early quits */
  99.     (void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
  100. #ifdef SIGXCPU
  101.     (void) signal(SIGXCPU, (SIG_RET_TYPE) hangup);
  102. #endif
  103.  
  104.     /*
  105.      * Find the creation date of this game,
  106.      * so as to avoid restoring outdated savefiles.
  107.      */
  108.     gethdate(hname);
  109.  
  110.     /*
  111.      * We cannot do chdir earlier, otherwise gethdate will fail.
  112.      */
  113. #ifdef CHDIR
  114.     chdirx(dir,1);
  115. #endif
  116.  
  117.     process_options(argc, argv);    /* command line options */
  118.  
  119. #ifdef DEF_PAGER
  120.     if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
  121.         catmore = DEF_PAGER;
  122. #endif
  123. #ifdef MAIL
  124.     getmailstatus();
  125. #endif
  126. #ifdef WIZARD
  127.     if (wizard)
  128.         Strcpy(plname, "wizard");
  129.     else
  130. #endif
  131.     if(!*plname || !strncmp(plname, "player", 4)
  132.             || !strncmp(plname, "games", 4)) {
  133.         exact_username = FALSE;
  134.         askname();
  135.     }
  136.     if (!exact_username) /* what if their LOGNAME looks suffixed-like? */
  137.         plnamesuffix();    /* strip suffix from name; calls askname() */
  138.                 /* again if suffix was whole name */
  139.                 /* accepts any suffix */
  140. #ifdef WIZARD
  141.     if(!wizard) {
  142. #endif
  143.         /*
  144.          * check for multiple games under the same name
  145.          * (if !locknum) or check max nr of players (otherwise)
  146.          */
  147.         (void) signal(SIGQUIT,SIG_IGN);
  148.         (void) signal(SIGINT,SIG_IGN);
  149.         if(!locknum)
  150.             Sprintf(lock, "%d%s", (int)getuid(), plname);
  151.         getlock();
  152. #ifdef WIZARD
  153.     } else {
  154.         Sprintf(lock, "%d%s", (int)getuid(), plname);
  155.         getlock();
  156.     }
  157. #endif /* WIZARD /**/
  158.  
  159.     /*
  160.      * Initialisation of the boundaries of the mazes
  161.      * Both boundaries have to be even.
  162.      */
  163.  
  164.     x_maze_max = COLNO-1;
  165.     if (x_maze_max % 2)
  166.         x_maze_max--;
  167.     y_maze_max = ROWNO-1;
  168.     if (y_maze_max % 2)
  169.         y_maze_max--;
  170.  
  171.     /*
  172.      *  Initialize the vision system.  This must be before mklev() on a
  173.      *  new game or before a level restore on a saved game.
  174.      */
  175.     vision_init();
  176.  
  177.     display_gamewindows();
  178.  
  179.     set_savefile_name();
  180.     uncompress(SAVEF);
  181.  
  182.     if((fd = open_savefile()) >= 0 &&
  183.        /* if not up-to-date, quietly delete file via false condition */
  184.        (uptodate(fd) || delete_savefile())) {
  185. #ifdef WIZARD
  186.         /* Since wizard is actually flags.debug, restoring might
  187.          * overwrite it.
  188.          */
  189.         boolean remember_wiz_mode = wizard;
  190. #endif
  191.         (void) chmod(SAVEF,0);    /* disallow parallel restores */
  192.         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  193. #ifdef NEWS
  194.         if(flags.news) display_file(NEWS, FALSE);
  195. #endif
  196.         pline("Restoring save file...");
  197.         mark_synch();    /* flush output */
  198.         if(!dorecover(fd))
  199.             goto not_recovered;
  200. #ifdef WIZARD
  201.         if(!wizard && remember_wiz_mode) wizard = TRUE;
  202. #endif
  203.         pline("Hello %s, welcome back to NetHack!", plname);
  204.         check_special_room(FALSE);
  205. #ifdef EXPLORE_MODE
  206.         if (discover)
  207.             You("are in non-scoring discovery mode.");
  208. #endif
  209. #if defined(EXPLORE_MODE) || defined(WIZARD)
  210.         if (discover || wizard) {
  211.             if(yn("Do you want to keep the save file?") == 'n')
  212.                 (void) delete_savefile();
  213.             else {
  214.                 (void) chmod(SAVEF,FCMASK); /* back to readable */
  215.                 compress(SAVEF);
  216.             }
  217.         }
  218. #endif
  219.         flags.move = 0;
  220.     } else {
  221. not_recovered:
  222.         player_selection();
  223.         newgame();
  224.         /* give welcome message before pickup messages */
  225.         pline("Hello %s, welcome to NetHack!", plname);
  226. #ifdef EXPLORE_MODE
  227.         if (discover)
  228.             You("are in non-scoring discovery mode.");
  229. #endif
  230.         flags.move = 0;
  231.         set_wear();
  232.         pickup(1);
  233.     }
  234.  
  235.     flags.moonphase = phase_of_the_moon();
  236.     if(flags.moonphase == FULL_MOON) {
  237.         You("are lucky!  Full moon tonight.");
  238.         change_luck(1);
  239.     } else if(flags.moonphase == NEW_MOON) {
  240.         pline("Be careful!  New moon tonight.");
  241.     }
  242.     if(flags.friday13 = friday_13th()) {
  243.         pline("Watch out!  Bad things can happen on Friday the 13th.");
  244.         change_luck(-1);
  245.     }
  246.  
  247.     initrack();
  248.  
  249.     moveloop();
  250.     return(0);
  251. }
  252.  
  253. static void
  254. process_options(argc, argv)
  255. int argc;
  256. char *argv[];
  257. {
  258.     /*
  259.      * Process options.
  260.      */
  261.     while(argc > 1 && argv[1][0] == '-'){
  262.         argv++;
  263.         argc--;
  264.         switch(argv[0][1]){
  265. #if defined(WIZARD) || defined(EXPLORE_MODE)
  266. # ifndef EXPLORE_MODE
  267.         case 'X':
  268. # endif
  269.         case 'D':
  270. # ifdef WIZARD
  271.             {
  272.               char *user;
  273.               int uid;
  274.               struct passwd *pw = (struct passwd *)0;
  275.  
  276.               uid = getuid();
  277.               user = getlogin();
  278.               if (user) {
  279.                   pw = getpwnam(user);
  280.                   if (pw && (pw->pw_uid != uid)) pw = 0;
  281.               }
  282.               if (pw == 0) {
  283.                   user = getenv("USER");
  284.                   if (user) {
  285.                   pw = getpwnam(user);
  286.                   if (pw && (pw->pw_uid != uid)) pw = 0;
  287.                   }
  288.                   if (pw == 0) {
  289.                   pw = getpwuid(uid);
  290.                   }
  291.               }
  292.               if (pw && !strcmp(pw->pw_name,WIZARD)) {
  293.                   wizard = TRUE;
  294.                   break;
  295.               }
  296.             }
  297.             /* otherwise fall thru to discover */
  298. # endif
  299. # ifdef EXPLORE_MODE
  300.         case 'X':
  301.             discover = TRUE;
  302. # endif
  303.             break;
  304. #endif
  305. #ifdef NEWS
  306.         case 'n':
  307.             flags.news = FALSE;
  308.             break;
  309. #endif
  310.         case 'u':
  311.             if(argv[0][2])
  312.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  313.             else if(argc > 1) {
  314.               argc--;
  315.               argv++;
  316.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  317.             } else
  318.                 raw_print("Player name expected after -u");
  319.             plnamesuffix();
  320.             break;
  321.         case 'I':
  322.         case 'i':
  323.             if (!strncmpi(argv[0]+1, "IBM", 3))
  324.                 switch_graphics(IBM_GRAPHICS);
  325.             break;
  326.         /*  case 'D': */
  327.         case 'd':
  328.             if (!strncmpi(argv[0]+1, "DEC", 3))
  329.                 switch_graphics(DEC_GRAPHICS);
  330.             break;
  331.         default:
  332.             /* allow -T for Tourist, etc. */
  333.             (void) strncpy(pl_character, argv[0]+1,
  334.                 sizeof(pl_character)-1);
  335.  
  336.             /* raw_printf("Unknown option: %s", *argv); */
  337.         }
  338.     }
  339.  
  340.     if(argc > 1)
  341.         locknum = atoi(argv[1]);
  342. #ifdef MAX_NR_OF_PLAYERS
  343.     if(!locknum || locknum > MAX_NR_OF_PLAYERS)
  344.         locknum = MAX_NR_OF_PLAYERS;
  345. #endif
  346. }
  347.  
  348. #ifdef CHDIR
  349. static void
  350. chdirx(dir, wr)
  351. const char *dir;
  352. boolean wr;
  353. {
  354.  
  355. # ifdef SECURE
  356.     if(dir                    /* User specified directory? */
  357. #  ifdef HACKDIR
  358.            && strcmp(dir, HACKDIR)        /* and not the default? */
  359. #  endif
  360.         ) {
  361.         (void) setgid(getgid());
  362.         (void) setuid(getuid());        /* Ron Wessels */
  363.     }
  364. # endif
  365.  
  366. # ifdef HACKDIR
  367.     if(dir == NULL)
  368.         dir = HACKDIR;
  369. # endif
  370.  
  371.     if(dir && chdir(dir) < 0) {
  372.         perror(dir);
  373.         error("Cannot chdir to %s.", dir);
  374.     }
  375.  
  376.     /* warn the player if we can't write the record file */
  377.     /* perhaps we should also test whether . is writable */
  378.     /* unfortunately the access system-call is worthless */
  379.     if (wr) check_recordfile(dir);
  380. }
  381. #endif /* CHDIR /**/
  382.  
  383. static boolean
  384. whoami() {
  385.     /*
  386.      * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
  387.      *            2. Use $USER or $LOGNAME    (if 1. fails)
  388.      *            3. Use getlogin()        (if 2. fails)
  389.      * The resulting name is overridden by command line options.
  390.      * If everything fails, or if the resulting name is some generic
  391.      * account like "games", "play", "player", "hack" then eventually
  392.      * we'll ask him.
  393.      * Note that we trust the user here; it is possible to play under
  394.      * somebody else's name.
  395.      */
  396.     register char *s;
  397.  
  398.     if (*plname) return FALSE;
  399.     if(/* !*plname && */ (s = getenv("USER")))
  400.         (void) strncpy(plname, s, sizeof(plname)-1);
  401.     if(!*plname && (s = getenv("LOGNAME")))
  402.         (void) strncpy(plname, s, sizeof(plname)-1);
  403.     if(!*plname && (s = getlogin()))
  404.         (void) strncpy(plname, s, sizeof(plname)-1);
  405.     return TRUE;
  406. }
  407.  
  408. #ifdef PORT_HELP
  409. void
  410. port_help()
  411. {
  412.     /*
  413.      * Display unix-specific help.   Just show contents of the helpfile
  414.      * named by PORT_HELP.
  415.      */
  416.     display_file(PORT_HELP, TRUE);
  417. }
  418. #endif
  419.  
  420. /*unixmain.c*/
  421.