2 * Copyright (c) 1997 Ben Harrison, and others
4 * This software may be copied and distributed for educational, research,
5 * and not for profit purposes provided that this copyright and statement
6 * are included in all such copies.
9 #include "autopick/autopick-pref-processor.h"
10 #include "core/asking-player.h"
11 #include "core/game-play.h"
12 #include "core/scores.h"
13 #include "game-option/runtime-arguments.h"
14 #include "io/chuukei.h"
15 #include "io/files-util.h"
17 #include "io/signal-handlers.h"
18 #include "io/uid-checker.h"
19 #include "main/angband-initializer.h"
20 #include "player/process-name.h"
21 #include "system/angband-version.h"
22 #include "system/angband.h"
23 #include "system/system-variables.h"
24 #include "term/gameterm.h"
25 #include "term/term-color-types.h"
26 #include "util/angband-files.h"
27 #include "util/string-processor.h"
30 * Available graphic modes
32 #define GRAPHICS_NONE 0
33 #define GRAPHICS_ORIGINAL 1
34 #define GRAPHICS_ADAM_BOLT 2
35 #define GRAPHICS_HENGBAND 3
38 * Some machines have a "main()" function in their "main-xxx.c" file,
39 * all the others use this file for their "main()" function.
44 * A hook for "quit()".
46 * Close down, then fall back into "quit()".
48 static void quit_hook(concptr s)
56 for (j = 8 - 1; j >= 0; j--) {
62 term_nuke(angband_term[j]);
67 * Set the stack size and overlay buffer (see main-286.c")
69 #ifdef PRIVATE_USER_PATH
72 * Create an ".angband/" directory in the users home directory.
74 * ToDo: Add error handling.
75 * ToDo: Only create the directories when actually writing files.
77 static void create_user_dir(void)
80 char subdirpath[1024];
82 /* Get an absolute path from the filename */
83 path_parse(dirpath, 1024, PRIVATE_USER_PATH);
85 /* Create the ~/.angband/ directory */
88 /* Build the path to the variant-specific sub-directory */
89 path_build(subdirpath, sizeof(subdirpath), dirpath, VERSION_NAME);
91 /* Create the directory */
92 mkdir(subdirpath, 0700);
95 #endif /* PRIVATE_USER_PATH */
98 * Initialize and verify the file paths, and the score file.
100 * Use the ANGBAND_PATH environment var if possible, else use
101 * DEFAULT_PATH, and in either case, branch off appropriately.
103 * First, we'll look for the ANGBAND_PATH environment variable,
104 * and then look for the files in there. If that doesn't work,
105 * we'll try the DEFAULT_PATH constant. So be sure that one of
106 * these two things works...
108 * We must ensure that the path ends with "PATH_SEP" if needed,
109 * since the "init_file_paths()" function will simply append the
110 * relevant "sub-directory names" to the given path.
112 * Make sure that the path doesn't overflow the buffer. We have
113 * to leave enough space for the path separator, directory, and
116 static void init_stuff(void)
122 /* Get the environment variable */
123 tail = getenv("ANGBAND_PATH");
125 /* Use the angband_path, or a default */
126 strncpy(path, tail ? tail : DEFAULT_PATH, 511);
128 /* Make sure it's terminated */
131 /* Hack -- Add a path separator (only if needed) */
132 if (!suffix(path, PATH_SEP))
133 strcat(path, PATH_SEP);
136 init_file_paths(path);
140 * Handle a "-d<what>=<path>" option
142 * The "<what>" can be any string starting with the same letter as the
143 * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
145 * The "<path>" can be any legal path for the given system, and should
146 * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
148 static void change_path(concptr info)
152 /* Find equal sign */
153 s = angband_strchr(info, '=');
155 /* Verify equal sign */
157 quit_fmt("Try '-d<what>=<path>' not '-d%s'", info);
160 switch (tolower(info[0])) {
162 string_free(ANGBAND_DIR_APEX);
163 ANGBAND_DIR_APEX = string_make(s + 1);
168 string_free(ANGBAND_DIR_FILE);
169 ANGBAND_DIR_FILE = string_make(s + 1);
174 string_free(ANGBAND_DIR_HELP);
175 ANGBAND_DIR_HELP = string_make(s + 1);
180 string_free(ANGBAND_DIR_INFO);
181 ANGBAND_DIR_INFO = string_make(s + 1);
186 string_free(ANGBAND_DIR_USER);
187 ANGBAND_DIR_USER = string_make(s + 1);
192 string_free(ANGBAND_DIR_XTRA);
193 ANGBAND_DIR_XTRA = string_make(s + 1);
198 string_free(ANGBAND_DIR_BONE);
199 ANGBAND_DIR_BONE = string_make(s + 1);
204 string_free(ANGBAND_DIR_DATA);
205 ANGBAND_DIR_DATA = string_make(s + 1);
210 string_free(ANGBAND_DIR_EDIT);
211 ANGBAND_DIR_EDIT = string_make(s + 1);
216 string_free(ANGBAND_DIR_SAVE);
217 ANGBAND_DIR_SAVE = string_make(s + 1);
222 string_free(ANGBAND_DIR_SCRIPT);
223 ANGBAND_DIR_SCRIPT = string_make(s + 1);
228 quit_fmt("Bad semantics in '-d%s'", info);
233 static void display_usage(void)
235 /* Dump usage information */
236 puts("Usage: angband [options] [-- subopts]");
237 puts(" -n Start a new character");
238 puts(" -f Request fiddle mode");
239 puts(" -w Request wizard mode");
240 puts(" -b Request BGM mode");
241 puts(" -v Request sound mode");
242 puts(" -g Request graphics mode");
243 puts(" -o Request original keyset");
244 puts(" -r Request rogue-like keyset");
245 puts(" -M Request monochrome mode");
246 puts(" -s<num> Show <num> high scores");
247 puts(" -u<who> Use your <who> savefile");
248 puts(" -m<sys> Force 'main-<sys>.c' usage");
249 puts(" -d<def> Define a 'lib' dir sub-path");
253 puts(" -mx11 To use X11");
254 puts(" -- Sub options");
255 puts(" -- -d Set display name");
256 puts(" -- -o Request old 8x8 tile graphics");
257 puts(" -- -a Request Adam Bolt 16x16 tile graphics");
258 puts(" -- -b Request Bigtile graphics mode");
259 puts(" -- -s Turn off smoothscaling graphics");
260 puts(" -- -n# Number of terms to use");
265 puts(" -mgcu To use GCU (GNU Curses)");
269 puts(" -mcap To use CAP (\"Termcap\" calls)");
272 /* Actually abort the process */
277 * Simple "main" function for multiple platforms.
279 * Note the special "--" option which terminates the processing of
280 * standard options. All non-standard options (if any) are passed
281 * directly to the "init_xxx()" function.
283 int main(int argc, char *argv[])
288 bool new_game = FALSE;
293 /* Save the "program name" XXX XXX XXX */
298 /* Default permissions on files */
303 /* Get the file paths */
308 /* Get the user id (?) */
309 p_ptr->player_uid = getuid();
312 /* Mega-Hack -- Factor group id */
313 p_ptr->player_uid += (getgid() * 1000);
318 #ifdef _POSIX_SAVED_IDS
320 /* Save some info for later */
321 p_ptr->player_euid = geteuid();
322 p_ptr->player_egid = getegid();
330 /* Drop permissions */
335 /* Acquire the "user name" as a default player name */
336 user_name(p_ptr->name, p_ptr->player_uid);
338 #ifdef PRIVATE_USER_PATH
340 /* Create a directory for the users files. */
343 #endif /* PRIVATE_USER_PATH */
347 /* Process the command line arguments */
348 bool browsing_movie = FALSE;
349 for (i = 1; args && (i < argc); i++) {
350 /* Require proper options */
351 if (argv[i][0] != '-') {
357 bool is_usage_needed = FALSE;
358 switch (argv[i][1]) {
386 /* HACK - Graphics mode switches on the original tiles */
387 arg_graphics = GRAPHICS_ORIGINAL;
392 arg_force_roguelike = TRUE;
397 arg_force_original = TRUE;
402 show_score = atoi(&argv[i][2]);
410 is_usage_needed = TRUE;
414 strcpy(p_ptr->name, &argv[i][2]);
419 is_usage_needed = TRUE;
427 arg_monochrome = TRUE;
432 change_path(&argv[i][2]);
437 is_usage_needed = TRUE;
441 prepare_browse_movie_with_path_build(&argv[i][2]);
442 browsing_movie = TRUE;
453 is_usage_needed = TRUE;
458 if (!is_usage_needed)
464 /* Hack -- Forget standard args */
470 /* Process the player name */
471 process_player_name(p_ptr, TRUE);
473 /* Install "quit" hook */
474 quit_aux = quit_hook;
477 /* Attempt to use the "main-xaw.c" support */
478 if (!done && (!mstr || (streq(mstr, "xaw")))) {
479 extern errr init_xaw(int, char **);
480 if (0 == init_xaw(argc, argv)) {
488 /* Attempt to use the "main-x11.c" support */
489 if (!done && (!mstr || (streq(mstr, "x11")))) {
490 extern errr init_x11(int, char **);
491 if (0 == init_x11(argc, argv)) {
499 /* Attempt to use the "main-gcu.c" support */
500 if (!done && (!mstr || (streq(mstr, "gcu")))) {
501 extern errr init_gcu(int, char **);
502 if (0 == init_gcu(argc, argv)) {
510 /* Attempt to use the "main-cap.c" support */
511 if (!done && (!mstr || (streq(mstr, "cap")))) {
512 extern errr init_cap(int, char **);
513 if (0 == init_cap(argc, argv)) {
520 /* Make sure we have a display! */
522 quit("Unable to prepare any 'display module'!");
524 /* Hack -- If requested, display scores and quit */
526 display_scores(0, show_score);
528 /* Catch nasty signals */
532 init_angband(p_ptr, process_autopick_file_command);
534 /* Wait for response */
538 play_game(p_ptr, new_game, browsing_movie);