OSDN Git Service

upgrade to 3.6.2
[jnethack/source.git] / sys / unix / unixmain.c
index 63edf1c..f23de9b 100644 (file)
@@ -1,5 +1,6 @@
 /* NetHack 3.6 unixmain.c      $NHDT-Date: 1432512788 2015/05/25 00:13:08 $  $NHDT-Branch: master $:$NHDT-Revision: 1.52 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* main.c - Unix NetHack */
@@ -59,9 +60,14 @@ char *argv[];
 #endif
     boolean exact_username;
     boolean resuming = FALSE; /* assume new game */
+    boolean plsel_once = FALSE;
 
     sys_early_init();
 
+#if 1 /*JP*//* iconv\82Ì\8f\89\8aú\89»\82Ì\82½\82ß\82É\88ê\93x\82Í\8cÄ\82Ñ\8fo\82·\95K\97v\82ª\82 \82é */
+    setkcode('U');
+#endif
+
 #ifdef XI18N
     setlocale(LC_ALL, "");
 #endif
@@ -104,20 +110,27 @@ char *argv[];
     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)
-              */
+    /*
+     * 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') {
+        if (argcheck(argc, argv, ARG_VERSION) == 2)
+            exit(EXIT_SUCCESS);
+
+        if (argcheck(argc, argv, ARG_DEBUG) == 1) {
+            argc--;
+            argv++;
+       }
+
+        if (argc > 1 && !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
              */
@@ -134,37 +147,40 @@ char *argv[];
             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)) {
+    if (argc > 1) {
+        /*
+         * 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);
+            chdirx(dir, 0);
 #endif
 #ifdef SYSCF
-                initoptions();
+            initoptions();
 #endif
 #ifdef PANICTRACE
-                ARGV0 = argv[0]; /* save for possible stack trace */
+            ARGV0 = hname; /* save for possible stack trace */
 #ifndef NO_SIGNAL
-                panictrace_setsignals(TRUE);
+            panictrace_setsignals(TRUE);
 #endif
 #endif
 #if 0 /*JP*/
-                prscore(argc, argv);
+            prscore(argc, argv);
 #else
-                setkcode('I');
-                initoptions();
-                prscore(argc, argv);
-                jputchar('\0'); /* reset */
-#endif
-                exit(EXIT_SUCCESS);
-            }
-    }
+            setkcode('I');
+            initoptions();
+            prscore(argc, argv);
+            jputchar('\0'); /* reset */
+#endif
+            /* FIXME: shouldn't this be using nh_terminate() to free
+               up any memory allocated by initoptions() */
+            exit(EXIT_SUCCESS);
+        }
+    } /* argc > 1 */
 
 /*
  * Change directories before we initialize the window system so
@@ -180,16 +196,9 @@ char *argv[];
 #ifdef __linux__
     check_linux_console();
 #endif
-#if 1 /*JP*/
-    /* Line like "OPTIONS=name:foo-@" may exist in config file.
-     * In this case, need to select random class,
-     * so must call setrandom() before initoptions().
-     */
-    setrandom();
-#endif
     initoptions();
 #ifdef PANICTRACE
-    ARGV0 = argv[0]; /* save for possible stack trace */
+    ARGV0 = hname; /* save for possible stack trace */
 #ifndef NO_SIGNAL
     panictrace_setsignals(TRUE);
 #endif
@@ -238,7 +247,7 @@ char *argv[];
          * dash matches role, race, gender, or alignment.
          */
         /* guard against user names with hyphens in them */
-        int len = strlen(plname);
+        int len = (int) strlen(plname);
         /* append the current role, if any, so that last dash is ours */
         if (++len < (int) sizeof plname)
             (void) strncat(strcat(plname, "-"), pl_character,
@@ -256,6 +265,23 @@ char *argv[];
         (void) signal(SIGQUIT, SIG_IGN);
         (void) signal(SIGINT, SIG_IGN);
     }
+
+    dlb_init(); /* must be before newgame() */
+
+    /*
+     * 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();
+
+    /*
+     * First, try to find and restore a save file for specified character.
+     * We'll return here if new game player_selection() renames the hero.
+     */
+attempt_restore:
+
     /*
      * getlock() complains and quits if there is already a game
      * in progress for current character name (when locknum == 0)
@@ -267,25 +293,12 @@ char *argv[];
      * clock, &c not currently in use in the playground directory
      * (for locknum > 0).
      */
-    getlock();
-    program_state.preserve_locks = 0; /* after getlock() */
-
-    dlb_init(); /* must be before newgame() */
-
-    /*
-     *  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 (*plname) {
+        getlock();
+        program_state.preserve_locks = 0; /* after getlock() */
+    }
 
-/*
- * First, try to find and restore a save file for specified character.
- * We'll return here if new game player_selection() renames the hero.
- */
-attempt_restore:
-    if ((fd = restore_saved_game()) >= 0) {
+    if (*plname && (fd = restore_saved_game()) >= 0) {
         const char *fq_save = fqname(SAVEF, SAVEPREFIX, 1);
 
         (void) chmod(fq_save, 0); /* disallow parallel restores */
@@ -307,12 +320,13 @@ attempt_restore:
             resuming = TRUE; /* not starting new game */
             wd_message();
             if (discover || wizard) {
+                /* this seems like a candidate for paranoid_confirmation... */
 /*JP
-                if (yn("Do you want to keep the save file?") == 'n')
+                if (yn("Do you want to keep the save file?") == 'n') {
 */
-                if (yn("\83Z\81[\83u\83t\83@\83C\83\8b\82ð\8ec\82µ\82Ä\82¨\82«\82Ü\82·\82©\81H") == 'n')
+                if (yn("\83Z\81[\83u\83t\83@\83C\83\8b\82ð\8ec\82µ\82Ä\82¨\82«\82Ü\82·\82©\81H") == 'n') {
                     (void) delete_savefile();
-                else {
+                else {
                     (void) chmod(fq_save, FCMASK); /* back to readable */
                     nh_compress(fq_save);
                 }
@@ -321,12 +335,17 @@ attempt_restore:
     }
 
     if (!resuming) {
+        boolean neednewlock = (!*plname);
         /* new game:  start by choosing role, race, etc;
            player might change the hero's name while doing that,
            in which case we try to restore under the new name
            and skip selection this time if that didn't succeed */
-        if (!iflags.renameinprogress) {
-            player_selection();
+        if (!iflags.renameinprogress || iflags.defer_plname || neednewlock) {
+            if (!plsel_once)
+                player_selection();
+            plsel_once = TRUE;
+            if (neednewlock && *plname)
+                goto attempt_restore;
             if (iflags.renameinprogress) {
                 /* player has renamed the hero while selecting role;
                    if locking alphabetically, the existing lock file
@@ -343,10 +362,12 @@ attempt_restore:
         wd_message();
     }
 
+    /* moveloop() never returns but isn't flagged NORETURN */
     moveloop(resuming);
+
     exit(EXIT_SUCCESS);
     /*NOTREACHED*/
-    return (0);
+    return 0;
 }
 
 static void
@@ -390,14 +411,23 @@ char *argv[];
             break;
 #endif
         case 'u':
-            if (argv[0][2])
-                (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
-            else if (argc > 1) {
+            if (argv[0][2]) {
+#if 0 /*JP*/
+                (void) strncpy(plname, argv[0] + 2, sizeof plname - 1);
+#else
+                (void) strncpy(plname, str2ic(argv[0] + 2), sizeof(plname) - 1);
+#endif
+            } else if (argc > 1) {
                 argc--;
                 argv++;
-                (void) strncpy(plname, argv[0], sizeof(plname) - 1);
-            } else
+#if 0 /*JP*/
+                (void) strncpy(plname, argv[0], sizeof plname - 1);
+#else
+                (void) strncpy(plname, str2ic(argv[0]), sizeof(plname) - 1);
+#endif
+            } else {
                 raw_print("Player name expected after -u");
+            }
             break;
         case 'I':
         case 'i':
@@ -432,7 +462,9 @@ char *argv[];
             }
             break;
         case 'w': /* windowtype */
+            config_error_init(FALSE, "command line", FALSE);
             choose_windows(&argv[0][2]);
+            config_error_done();
             break;
         case '@':
             flags.randomall = 1;
@@ -446,10 +478,14 @@ char *argv[];
         }
     }
 
-    /* XXX This is deprecated in favor of SYSCF with MAXPLAYERS.  Make
-     * an error in next release. */
+#ifdef SYSCF
+    if (argc > 1)
+        raw_printf("MAXPLAYERS are set in sysconf file.\n");
+#else
+    /* XXX This is deprecated in favor of SYSCF with MAXPLAYERS */
     if (argc > 1)
         locknum = atoi(argv[1]);
+#endif
 #ifdef MAX_NR_OF_PLAYERS
     /* limit to compile-time limit */
     if (!locknum || locknum > MAX_NR_OF_PLAYERS)
@@ -474,17 +510,16 @@ boolean wr;
 #endif
         ) {
 #ifdef SECURE
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-result"
+_pragma_ignore(-Wunused-result)
         (void) setgid(getgid());
         (void) setuid(getuid()); /* Ron Wessels */
-#pragma GCC diagnostic pop
+_pragma_pop
 #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.
- */
+        /* 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);
 
@@ -507,9 +542,10 @@ boolean wr;
         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 */
+    /* 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];
@@ -600,6 +636,7 @@ boolean
 authorize_wizard_mode()
 {
     struct passwd *pw = get_unix_pw();
+
     if (pw && sysopt.wizards && sysopt.wizards[0]) {
         if (check_user_string(sysopt.wizards))
             return TRUE;
@@ -662,11 +699,17 @@ char *optstr;
     struct passwd *pw = get_unix_pw();
     int pwlen;
     char *eop, *w;
+    char *pwname;
+
     if (optstr[0] == '*')
         return TRUE; /* allow any user */
     if (!pw)
         return FALSE;
-    pwlen = strlen(pw->pw_name);
+    if (sysopt.check_plname)
+        pwname = plname;
+    else
+        pwname = pw->pw_name;
+    pwlen = strlen(pwname);
     eop = eos(optstr);
     w = optstr;
     while (w + pwlen <= eop) {
@@ -676,7 +719,7 @@ char *optstr;
             w++;
             continue;
         }
-        if (!strncmp(w, pw->pw_name, pwlen)) {
+        if (!strncmp(w, pwname, pwlen)) {
             if (!w[pwlen] || isspace(w[pwlen]))
                 return TRUE;
         }
@@ -717,4 +760,86 @@ get_unix_pw()
     return pw;
 }
 
+char *
+get_login_name()
+{
+    static char buf[BUFSZ];
+    struct passwd *pw = get_unix_pw();
+
+    buf[0] = '\0';
+
+    if (pw)
+        (void)strcpy(buf, pw->pw_name);
+
+    return buf;
+}
+
+#ifdef __APPLE__
+extern int errno;
+
+void
+port_insert_pastebuf(buf)
+char *buf;
+{
+    /* This should be replaced when there is a Cocoa port. */
+    const char *errfmt;
+    size_t len;
+    FILE *PB = popen("/usr/bin/pbcopy","w");
+    if(!PB){
+       errfmt = "Unable to start pbcopy (%d)\n";
+       goto error;
+    }
+
+    len = strlen(buf);
+    /* Remove the trailing \n, carefully. */
+    if(buf[len-1] == '\n') len--;
+
+    /* XXX Sorry, I'm too lazy to write a loop for output this short. */
+    if(len!=fwrite(buf,1,len,PB)){
+       errfmt = "Error sending data to pbcopy (%d)\n";
+       goto error;
+    }
+
+    if(pclose(PB)!=-1){
+       return;
+    }
+    errfmt = "Error finishing pbcopy (%d)\n";
+
+error:
+    raw_printf(errfmt,strerror(errno));
+}
+#endif
+
+unsigned long
+sys_random_seed()
+{
+    unsigned long seed = 0L;
+    unsigned long pid = (unsigned long) getpid();
+    boolean no_seed = TRUE;
+#ifdef DEV_RANDOM
+    FILE *fptr;
+
+    fptr = fopen(DEV_RANDOM, "r");
+    if (fptr) {
+        fread(&seed, sizeof (long), 1, fptr);
+        has_strong_rngseed = TRUE;  /* decl.c */
+        no_seed = FALSE;
+        (void) fclose(fptr);
+    } else {
+        /* leaves clue, doesn't exit */
+        paniclog("sys_random_seed", "falling back to weak seed");
+    }
+#endif
+    if (no_seed) {
+        seed = (unsigned long) getnow(); /* time((TIME_type) 0) */
+        /* Quick dirty band-aid to prevent PRNG prediction */
+        if (pid) {
+            if (!(pid & 3L))
+                pid -= 1L;
+            seed *= pid;
+        }
+    }
+    return seed;
+}
+
 /*unixmain.c*/