X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=sys%2Funix%2Funixmain.c;h=f23de9ba4931e34df07724f1015c10f5eda3a341;hb=096152cd7d9acc1d7efcc0b6fa8028bab1ff3200;hp=63edf1c4cfb669d172e656ff11d9ffc29af0677f;hpb=5da1ef68b53134394256453980b5e99b092d191b;p=jnethack%2Fsource.git diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 63edf1c..f23de9b 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -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‚̏‰Šú‰»‚Ì‚½‚߂Ɉê“x‚͌Ăяo‚·•K—v‚ª‚ ‚é */ + 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("ƒZ[ƒuƒtƒ@ƒCƒ‹‚ðŽc‚µ‚Ä‚¨‚«‚Ü‚·‚©H") == 'n') + if (yn("ƒZ[ƒuƒtƒ@ƒCƒ‹‚ðŽc‚µ‚Ä‚¨‚«‚Ü‚·‚©H") == '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*/