From 6dea05c94096b0e9d6ef46f42cdb916f05dc1fa0 Mon Sep 17 00:00:00 2001 From: jwalz Date: Sat, 5 Jan 2002 21:05:59 +0000 Subject: [PATCH] *** empty log message *** --- sys/unix/unixmain.c | 511 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 511 insertions(+) create mode 100644 sys/unix/unixmain.c diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c new file mode 100644 index 000000000..6e58a4890 --- /dev/null +++ b/sys/unix/unixmain.c @@ -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 +#include +#include +#ifndef O_RDONLY +#include +#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*/