1 /*	SCCS Id: @(#)bemain.c	3.4	1998/07/15	*/
2 /* Copyright (c) Dean Luick, 1996. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 #include "dlb.h"
7 #include <fcntl.h>
8 
9 static void whoami(void);
10 static void process_options(int argc, char **argv);
11 static void chdirx(const char *dir);
12 static void getlock(void);
13 
14 #ifdef __begui__
15 	#define MAIN nhmain
16 	int nhmain(int argc, char **argv);
17 #else
18 	#define MAIN main
19 #endif
20 
21 
MAIN(int argc,char ** argv)22 int MAIN(int argc, char **argv)
23 {
24 	int fd;
25 	char *dir;
26 
27 	dir = nh_getenv("NETHACKDIR");
28 	if (!dir) dir = nh_getenv("HACKDIR");
29 
30 	choose_windows(DEFAULT_WINDOW_SYS);
31 	chdirx(dir);
32 	initoptions();
33 
34 	init_nhwindows(&argc, argv);
35 	whoami();
36 
37 	/*
38 	 * It seems you really want to play.
39 	 */
40 	u.uhp = 1;	/* prevent RIP on early quits */
41 	process_options(argc, argv);	/* command line options */
42 
43 
44 #ifdef WIZARD
45 	if (wizard)
46 		Strcpy(plname, "wizard");
47 	else
48 #endif
49 	if(!*plname || !strncmp(plname, "player", 4)
50 		    || !strncmp(plname, "games", 4))
51 		askname();
52 	plnamesuffix();		/* strip suffix from name; calls askname() */
53 						/* again if suffix was whole name */
54 						/* accepts any suffix */
55 
56 	Sprintf(lock,"%d%s", getuid(), plname);
57 	getlock();
58 
59 
60 	dlb_init();			/* must be before newgame() */
61 
62 	/*
63 	 * Initialization of the boundaries of the mazes
64 	 * Both boundaries have to be even.
65 	 */
66 	x_maze_max = COLNO-1;
67 	if (x_maze_max % 2)
68 		x_maze_max--;
69 	y_maze_max = ROWNO-1;
70 	if (y_maze_max % 2)
71 		y_maze_max--;
72 
73 	/*
74 	 * Initialize the vision system.  This must be before mklev() on a
75 	 * new game or before a level restore on a saved game.
76 	 */
77 	vision_init();
78 
79 	display_gamewindows();
80 
81 	if ((fd = restore_saved_game()) >= 0) {
82 #ifdef WIZARD
83 		/* Since wizard is actually flags.debug, restoring might
84 		 * overwrite it.
85 		 */
86 		boolean remember_wiz_mode = wizard;
87 #endif
88 #ifdef NEWS
89 		if(iflags.news) {
90 			display_file(NEWS, FALSE);
91 			iflags.news = FALSE;	/* in case dorecover() fails */
92 		}
93 #endif
94 		pline("Restoring save file...");
95 		mark_synch();	/* flush output */
96 		if(!dorecover(fd))
97 			goto not_recovered;
98 #ifdef WIZARD
99 		if(!wizard && remember_wiz_mode) wizard = TRUE;
100 #endif
101 		check_special_room(FALSE);
102 		if (discover)
103 			You("are in non-scoring discovery mode.");
104 
105 		if (discover || wizard) {
106 			if(yn("Do you want to keep the save file?") == 'n')
107 			    (void) delete_savefile();
108 			else {
109 			    compress(fqname(SAVEF, SAVEPREFIX, 0));
110 			}
111 		}
112 
113 		flags.move = 0;
114 	} else {
115 not_recovered:
116 		player_selection();
117 		newgame();
118 		if (discover)
119 			You("are in non-scoring discovery mode.");
120 
121 		flags.move = 0;
122 		set_wear();
123 		(void) pickup(1);
124 	}
125 
126 	moveloop();
127 	return 0;
128 }
129 
whoami(void)130 static void whoami(void)
131 {
132 	/*
133 	 * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
134 	 *                      2. Use $USER or $LOGNAME        (if 1. fails)
135 	 * The resulting name is overridden by command line options.
136 	 * If everything fails, or if the resulting name is some generic
137 	 * account like "games", "play", "player", "hack" then eventually
138 	 * we'll ask him.
139 	 */
140 	char *s;
141 
142 	if (*plname) return;
143 	if (s = nh_getenv("USER")) {
144 		(void) strncpy(plname, s, sizeof(plname)-1);
145 		return;
146 	}
147 	if (s = nh_getenv("LOGNAME")) {
148 		(void) strncpy(plname, s, sizeof(plname)-1);
149 		return;
150 	}
151 }
152 
153 /* normalize file name - we don't like .'s, /'s, spaces */
regularize(char * s)154 void regularize(char *s)
155 {
156 	register char *lp;
157 
158 	while((lp=strchr(s, '.')) || (lp=strchr(s, '/')) || (lp=strchr(s,' ')))
159 		*lp = '_';
160 }
161 
process_options(int argc,char ** argv)162 static void process_options(int argc, char **argv)
163 {
164 	int i;
165 
166 	while (argc > 1 && argv[1][0] == '-') {
167 		argv++;
168 		argc--;
169 		switch (argv[0][1]) {
170 		case 'D':
171 #ifdef WIZARD
172 			wizard = TRUE;
173 			break;
174 #endif
175 			/* otherwise fall thru to discover */
176 		case 'X':
177 			discover = TRUE;
178 			break;
179 #ifdef NEWS
180 		case 'n':
181 			iflags.news = FALSE;
182 			break;
183 #endif
184 		case 'u':
185 			if(argv[0][2])
186 				(void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
187 			else if (argc > 1) {
188 				argc--;
189 				argv++;
190 				(void) strncpy(plname, argv[0], sizeof(plname)-1);
191 			} else
192 				raw_print("Player name expected after -u");
193 			break;
194 		case 'p': /* profession (role) */
195 			if (argv[0][2]) {
196 			    if ((i = str2role(&argv[0][2])) >= 0)
197 			    	flags.initrole = i;
198 			} else if (argc > 1) {
199 				argc--;
200 				argv++;
201 			    if ((i = str2role(argv[0])) >= 0)
202 			    	flags.initrole = i;
203 			}
204 			break;
205 		case 'r': /* race */
206 			if (argv[0][2]) {
207 			    if ((i = str2race(&argv[0][2])) >= 0)
208 			    	flags.initrace = i;
209 			} else if (argc > 1) {
210 				argc--;
211 				argv++;
212 			    if ((i = str2race(argv[0])) >= 0)
213 			    	flags.initrace = i;
214 			}
215 			break;
216 		case '@':
217 			flags.randomall = 1;
218 			break;
219 		default:
220 			raw_printf("Unknown option: %s", *argv);
221 			break;
222 		}
223 	}
224 }
225 
chdirx(const char * dir)226 static void chdirx(const char *dir)
227 {
228 	if (!dir) dir = HACKDIR;
229 
230 	if (chdir(dir) < 0)
231 		error("Cannot chdir to %s.", dir);
232 
233 	/* Warn the player if we can't write the record file */
234 	/* perhaps we should also test whether . is writable */
235 	check_recordfile(dir);
236 }
237 
getlock(void)238 void getlock(void)
239 {
240 	int fd;
241 
242 	regularize(lock);
243 	set_levelfile_name(lock, 0);
244 	fd = creat(lock, FCMASK);
245 	if(fd == -1) {
246 		error("cannot creat lock file.");
247 	} else {
248 		if(write(fd, (genericptr_t) &hackpid, sizeof(hackpid))
249 		    != sizeof(hackpid)){
250 			error("cannot write lock");
251 		}
252 		if(close(fd) == -1) {
253 			error("cannot close lock");
254 		}
255 	}
256 }
257 
258 #ifndef __begui__
259 /*
260  * If we are not using the Be GUI, then just exit -- we don't need to
261  * do anything extra.
262  */
263 void nethack_exit(int status);
nethack_exit(int status)264 void nethack_exit(int status)
265 {
266 	exit(status);
267 }
268 #endif /* !__begui__ */
269