/* 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 */
#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
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
*/
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
#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
* 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,
(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)
* 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 */
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);
}
}
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
wd_message();
}
+ /* moveloop() never returns but isn't flagged NORETURN */
moveloop(resuming);
+
exit(EXIT_SUCCESS);
/*NOTREACHED*/
- return (0);
+ return 0;
}
static void
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':
}
break;
case 'w': /* windowtype */
+ config_error_init(FALSE, "command line", FALSE);
choose_windows(&argv[0][2]);
+ config_error_done();
break;
case '@':
flags.randomall = 1;
}
}
- /* 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)
#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);
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];
authorize_wizard_mode()
{
struct passwd *pw = get_unix_pw();
+
if (pw && sysopt.wizards && sysopt.wizards[0]) {
if (check_user_string(sysopt.wizards))
return TRUE;
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) {
w++;
continue;
}
- if (!strncmp(w, pw->pw_name, pwlen)) {
+ if (!strncmp(w, pwname, pwlen)) {
if (!w[pwlen] || isspace(w[pwlen]))
return TRUE;
}
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*/