]> granicus.if.org Git - nethack/commitdiff
*** empty log message ***
authorjwalz <jwalz>
Sat, 5 Jan 2002 21:05:59 +0000 (21:05 +0000)
committerjwalz <jwalz>
Sat, 5 Jan 2002 21:05:59 +0000 (21:05 +0000)
sys/unix/unixmain.c [new file with mode: 0644]

diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c
new file mode 100644 (file)
index 0000000..6e58a48
--- /dev/null
@@ -0,0 +1,511 @@
+/*     SCCS Id: @(#)unixmain.c 3.3     97/01/22        */
+/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+/* main.c - Unix NetHack */
+
+#include "hack.h"
+#include "dlb.h"
+
+#include <sys/stat.h>
+#include <signal.h>
+#include <pwd.h>
+#ifndef O_RDONLY
+#include <fcntl.h>
+#endif
+
+#if !defined(_BULL_SOURCE) && !defined(__sgi) && !defined(_M_UNIX)
+# if !defined(SUNOS4) && !(defined(ULTRIX) && defined(__GNUC__))
+#  if defined(POSIX_TYPES) || defined(SVR4) || defined(HPUX)
+extern struct passwd *FDECL(getpwuid,(uid_t));
+#  else
+extern struct passwd *FDECL(getpwuid,(int));
+#  endif
+# endif
+#endif
+extern struct passwd *FDECL(getpwnam,(const char *));
+#ifdef CHDIR
+static void FDECL(chdirx, (const char *,BOOLEAN_P));
+#endif /* CHDIR */
+static boolean NDECL(whoami);
+static void FDECL(process_options, (int, char **));
+
+#ifdef _M_UNIX
+extern void NDECL(check_sco_console);
+extern void NDECL(init_sco_cons);
+#endif
+#ifdef __linux__
+extern void NDECL(check_linux_console);
+extern void NDECL(init_linux_cons);
+#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
+       boolean exact_username;
+
+       hname = argv[0];
+       hackpid = getpid();
+       (void) umask(0777 & ~FCMASK);
+
+       choose_windows(DEFAULT_WINDOW_SYS);
+
+#ifdef CHDIR                   /* otherwise no chdir() */
+       /*
+        * See if we must change directory to the playground.
+        * (Perhaps hack runs suid and playground is inaccessible
+        *  for the player.)
+        * The environment variable 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().  Exclude `-style' - it's a Qt option.
+            */
+           if (!strncmp(argv[1], "-s", 2) && strncmp(argv[1], "-style", 6)) {
+#ifdef CHDIR
+               chdirx(dir,0);
+#endif
+               prscore(argc, argv);
+               exit(EXIT_SUCCESS);
+           }
+       }
+
+       /*
+        * Change directories before we initialize the window system so
+        * we can find the tile file.
+        */
+#ifdef CHDIR
+       chdirx(dir,1);
+#endif
+
+#ifdef _M_UNIX
+       check_sco_console();
+#endif
+#ifdef __linux__
+       check_linux_console();
+#endif
+       initoptions();
+       init_nhwindows(&argc,argv);
+       exact_username = whoami();
+#ifdef _M_UNIX
+       init_sco_cons();
+#endif
+#ifdef __linux__
+       init_linux_cons();
+#endif
+
+       /*
+        * It seems you really want to play.
+        */
+       u.uhp = 1;      /* prevent RIP on early quits */
+       (void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
+#ifdef SIGXCPU
+       (void) signal(SIGXCPU, (SIG_RET_TYPE) hangup);
+#endif
+
+       process_options(argc, argv);    /* command line options */
+
+#ifdef DEF_PAGER
+       if(!(catmore = nh_getenv("HACKPAGER")) && !(catmore = nh_getenv("PAGER")))
+               catmore = DEF_PAGER;
+#endif
+#ifdef MAIL
+       getmailstatus();
+#endif
+#ifdef WIZARD
+       if (wizard)
+               Strcpy(plname, "wizard");
+       else
+#endif
+       if(!*plname || !strncmp(plname, "player", 4)
+                   || !strncmp(plname, "games", 4)) {
+               askname();
+       } else if (exact_username) {
+               /* guard against user names with hyphens in them */
+               int len = strlen(plname);
+               /* append the current role, if any, so that last dash is ours */
+               if (++len < sizeof plname)
+                       (void)strncat(strcat(plname, "-"),
+                                     pl_character, sizeof plname - len - 1);
+       }
+       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, "%d%s", (int)getuid(), plname);
+               getlock();
+#ifdef WIZARD
+       } else {
+               Sprintf(lock, "%d%s", (int)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 */
+                           compress(fq_save);
+                       }
+               }
+               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
+                       {
+                         char *user;
+                         int uid;
+                         struct passwd *pw = (struct passwd *)0;
+
+                         uid = getuid();
+                         user = getlogin();
+                         if (user) {
+                             pw = getpwnam(user);
+                             if (pw && (pw->pw_uid != uid)) pw = 0;
+                         }
+                         if (pw == 0) {
+                             user = nh_getenv("USER");
+                             if (user) {
+                                 pw = getpwnam(user);
+                                 if (pw && (pw->pw_uid != uid)) pw = 0;
+                             }
+                             if (pw == 0) {
+                                 pw = getpwuid(uid);
+                             }
+                         }
+                         if (pw && !strcmp(pw->pw_name,WIZARD)) {
+                             wizard = TRUE;
+                             break;
+                         }
+                       }
+                       /* otherwise fall thru to discover */
+                       wiz_error_flag = TRUE;
+#endif
+               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
+static void
+chdirx(dir, wr)
+const char *dir;
+boolean wr;
+{
+       if (dir                                 /* User specified directory? */
+# ifdef HACKDIR
+              && strcmp(dir, HACKDIR)          /* and not the default? */
+# endif
+               ) {
+# ifdef SECURE
+           (void) setgid(getgid());
+           (void) setuid(getuid());            /* Ron Wessels */
+# endif
+       } else {
+           /* non-default data files is a sign that scores may not be
+            * compatible, or perhaps that a binary not fitting this
+            * system's layout is being used.
+            */
+# ifdef VAR_PLAYGROUND
+           int len = strlen(VAR_PLAYGROUND);
+
+           fqn_prefix[SCOREPREFIX] = (char *)alloc(len+2);
+           Strcpy(fqn_prefix[SCOREPREFIX], VAR_PLAYGROUND);
+           if (fqn_prefix[SCOREPREFIX][len-1] != '/') {
+               fqn_prefix[SCOREPREFIX][len] = '/';
+               fqn_prefix[SCOREPREFIX][len+1] = '\0';
+           }
+# endif
+       }
+
+# ifdef HACKDIR
+       if (dir == (const char *)0)
+           dir = HACKDIR;
+# 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 */
+       /* perhaps we should also test whether . is writable */
+       /* unfortunately the access system-call is worthless */
+       if (wr) {
+# ifdef VAR_PLAYGROUND
+           fqn_prefix[LEVELPREFIX] = fqn_prefix[SCOREPREFIX];
+           fqn_prefix[SAVEPREFIX] = fqn_prefix[SCOREPREFIX];
+           fqn_prefix[BONESPREFIX] = fqn_prefix[SCOREPREFIX];
+           fqn_prefix[LOCKPREFIX] = fqn_prefix[SCOREPREFIX];
+# endif
+           check_recordfile(dir);
+       }
+}
+#endif /* CHDIR */
+
+static boolean
+whoami() {
+       /*
+        * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
+        *                      2. Use $USER or $LOGNAME        (if 1. fails)
+        *                      3. Use getlogin()               (if 2. fails)
+        * The resulting name is overridden by command line options.
+        * If everything fails, or if the resulting name is some generic
+        * account like "games", "play", "player", "hack" 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) return FALSE;
+       if(/* !*plname && */ (s = nh_getenv("USER")))
+               (void) strncpy(plname, s, sizeof(plname)-1);
+       if(!*plname && (s = nh_getenv("LOGNAME")))
+               (void) strncpy(plname, s, sizeof(plname)-1);
+       if(!*plname && (s = getlogin()))
+               (void) strncpy(plname, s, sizeof(plname)-1);
+       return TRUE;
+}
+
+#ifdef PORT_HELP
+void
+port_help()
+{
+       /*
+        * Display unix-specific help.   Just show contents of the helpfile
+        * named by PORT_HELP.
+        */
+       display_file(PORT_HELP, TRUE);
+}
+#endif
+
+static void
+wd_message()
+{
+#ifdef WIZARD
+       if (wiz_error_flag) {
+               pline("Only user \"%s\" may access debug (wizard) mode.",
+# ifndef KR1ED
+                       WIZARD);
+# else
+                       WIZARD_NAME);
+# endif
+               pline("Entering discovery mode instead.");
+       } else
+#endif
+       if (discover)
+               You("are in non-scoring discovery mode.");
+}
+
+/*
+ * Add a backslash to any name not ending in /. There must
+ * be room for the /
+ */
+void
+append_slash(name)
+char *name;
+{
+       char *ptr;
+
+       if (!*name)
+               return;
+       ptr = name + (strlen(name) - 1);
+       if (*ptr != '/') {
+               *++ptr = '/';
+               *++ptr = '\0';
+       }
+       return;
+}
+
+/*unixmain.c*/