4 * Copyright (c) 1997 Ben Harrison, and others
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies.
11 #include "system/angband.h"
12 #include "autopick/autopick-pref-processor.h"
13 #include "core/asking-player.h"
14 #include "core/game-play.h"
15 #include "core/scores.h"
16 #include "game-option/runtime-arguments.h"
17 #include "io/chuukei.h"
18 #include "io/files-util.h"
20 #include "io/signal-handlers.h"
21 #include "io/uid-checker.h"
22 #include "main/angband-initializer.h"
23 #include "player/process-name.h"
24 #include "system/angband-version.h"
25 #include "system/system-variables.h"
26 #include "term/gameterm.h"
27 #include "term/term-color-types.h"
28 #include "util/angband-files.h"
29 #include "util/string-processor.h"
32 * Available graphic modes
34 #define GRAPHICS_NONE 0
35 #define GRAPHICS_ORIGINAL 1
36 #define GRAPHICS_ADAM_BOLT 2
37 #define GRAPHICS_HENGBAND 3
40 * Some machines have a "main()" function in their "main-xxx.c" file,
41 * all the others use this file for their "main()" function.
50 static errr term_nuke(term_type *t)
55 /* Call the special "nuke" hook */
57 /* Call the "nuke" hook */
62 t->active_flag = FALSE;
64 /* Assume not mapped */
65 t->mapped_flag = FALSE;
68 /* Nuke "displayed" */
69 term_win_nuke(t->old, w, h);
71 /* Kill "displayed" */
72 KILL(t->old, term_win);
74 /* Nuke "requested" */
75 term_win_nuke(t->scr, w, h);
77 /* Kill "requested" */
78 KILL(t->scr, term_win);
82 /* Nuke "memorized" */
83 term_win_nuke(t->mem, w, h);
85 /* Kill "memorized" */
86 KILL(t->mem, term_win);
91 /* Nuke "temporary" */
92 term_win_nuke(t->tmp, w, h);
94 /* Kill "temporary" */
95 KILL(t->tmp, term_win);
98 /* Free some arrays */
99 C_KILL(t->x1, h, TERM_LEN);
100 C_KILL(t->x2, h, TERM_LEN);
102 /* Free the input queue */
103 C_KILL(t->key_queue, t->key_size, char);
108 * A hook for "quit()".
110 * Close down, then fall back into "quit()".
112 static void quit_hook(concptr s)
120 for (j = 8 - 1; j >= 0; j--)
123 if (!angband_term[j]) continue;
126 term_nuke(angband_term[j]);
132 * Set the stack size and overlay buffer (see main-286.c")
134 #ifdef PRIVATE_USER_PATH
137 * Create an ".angband/" directory in the users home directory.
139 * ToDo: Add error handling.
140 * ToDo: Only create the directories when actually writing files.
142 static void create_user_dir(void)
145 char subdirpath[1024];
147 /* Get an absolute path from the filename */
148 path_parse(dirpath, 1024, PRIVATE_USER_PATH);
150 /* Create the ~/.angband/ directory */
151 mkdir(dirpath, 0700);
153 /* Build the path to the variant-specific sub-directory */
154 path_build(subdirpath, sizeof(subdirpath), dirpath, VERSION_NAME);
156 /* Create the directory */
157 mkdir(subdirpath, 0700);
160 #endif /* PRIVATE_USER_PATH */
164 * Initialize and verify the file paths, and the score file.
166 * Use the ANGBAND_PATH environment var if possible, else use
167 * DEFAULT_PATH, and in either case, branch off appropriately.
169 * First, we'll look for the ANGBAND_PATH environment variable,
170 * and then look for the files in there. If that doesn't work,
171 * we'll try the DEFAULT_PATH constant. So be sure that one of
172 * these two things works...
174 * We must ensure that the path ends with "PATH_SEP" if needed,
175 * since the "init_file_paths()" function will simply append the
176 * relevant "sub-directory names" to the given path.
178 * Make sure that the path doesn't overflow the buffer. We have
179 * to leave enough space for the path separator, directory, and
182 static void init_stuff(void)
188 /* Get the environment variable */
189 tail = getenv("ANGBAND_PATH");
191 /* Use the angband_path, or a default */
192 strncpy(path, tail ? tail : DEFAULT_PATH, 511);
194 /* Make sure it's terminated */
197 /* Hack -- Add a path separator (only if needed) */
198 if (!suffix(path, PATH_SEP)) strcat(path, PATH_SEP);
201 init_file_paths(path);
207 * Handle a "-d<what>=<path>" option
209 * The "<what>" can be any string starting with the same letter as the
210 * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
212 * The "<path>" can be any legal path for the given system, and should
213 * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
215 static void change_path(concptr info)
219 /* Find equal sign */
220 s = angband_strchr(info, '=');
222 /* Verify equal sign */
223 if (!s) quit_fmt("Try '-d<what>=<path>' not '-d%s'", info);
226 switch (tolower(info[0]))
230 string_free(ANGBAND_DIR_APEX);
231 ANGBAND_DIR_APEX = string_make(s+1);
237 string_free(ANGBAND_DIR_FILE);
238 ANGBAND_DIR_FILE = string_make(s+1);
244 string_free(ANGBAND_DIR_HELP);
245 ANGBAND_DIR_HELP = string_make(s+1);
251 string_free(ANGBAND_DIR_INFO);
252 ANGBAND_DIR_INFO = string_make(s+1);
258 string_free(ANGBAND_DIR_USER);
259 ANGBAND_DIR_USER = string_make(s+1);
265 string_free(ANGBAND_DIR_XTRA);
266 ANGBAND_DIR_XTRA = string_make(s+1);
272 string_free(ANGBAND_DIR_BONE);
273 ANGBAND_DIR_BONE = string_make(s+1);
279 string_free(ANGBAND_DIR_DATA);
280 ANGBAND_DIR_DATA = string_make(s+1);
286 string_free(ANGBAND_DIR_EDIT);
287 ANGBAND_DIR_EDIT = string_make(s+1);
293 string_free(ANGBAND_DIR_SAVE);
294 ANGBAND_DIR_SAVE = string_make(s+1);
300 string_free(ANGBAND_DIR_SCRIPT);
301 ANGBAND_DIR_SCRIPT = string_make(s+1);
307 quit_fmt("Bad semantics in '-d%s'", info);
312 static void display_usage(void)
314 /* Dump usage information */
315 puts("Usage: angband [options] [-- subopts]");
316 puts(" -n Start a new character");
317 puts(" -f Request fiddle mode");
318 puts(" -w Request wizard mode");
319 puts(" -b Request BGM mode");
320 puts(" -v Request sound mode");
321 puts(" -g Request graphics mode");
322 puts(" -o Request original keyset");
323 puts(" -r Request rogue-like keyset");
324 puts(" -M Request monochrome mode");
325 puts(" -s<num> Show <num> high scores");
326 puts(" -u<who> Use your <who> savefile");
327 puts(" -m<sys> Force 'main-<sys>.c' usage");
328 puts(" -d<def> Define a 'lib' dir sub-path");
332 puts(" -mx11 To use X11");
333 puts(" -- Sub options");
334 puts(" -- -d Set display name");
335 puts(" -- -o Request old 8x8 tile graphics");
336 puts(" -- -a Request Adam Bolt 16x16 tile graphics");
337 puts(" -- -b Request Bigtile graphics mode");
338 puts(" -- -s Turn off smoothscaling graphics");
339 puts(" -- -n# Number of terms to use");
344 puts(" -mgcu To use GCU (GNU Curses)");
348 puts(" -mcap To use CAP (\"Termcap\" calls)");
351 /* Actually abort the process */
357 * Simple "main" function for multiple platforms.
359 * Note the special "--" option which terminates the processing of
360 * standard options. All non-standard options (if any) are passed
361 * directly to the "init_xxx()" function.
363 int main(int argc, char *argv[])
368 bool new_game = FALSE;
373 /* Save the "program name" XXX XXX XXX */
378 /* Default permissions on files */
384 /* Get the file paths */
390 /* Get the user id (?) */
391 p_ptr->player_uid = getuid();
394 /* Mega-Hack -- Factor group id */
395 p_ptr->player_uid += (getgid() * 1000);
400 # ifdef _POSIX_SAVED_IDS
402 /* Save some info for later */
403 p_ptr->player_euid = geteuid();
404 p_ptr->player_egid = getegid();
413 /* Drop permissions */
419 /* Acquire the "user name" as a default player name */
420 user_name(p_ptr->name, p_ptr->player_uid);
422 #ifdef PRIVATE_USER_PATH
424 /* Create a directory for the users files. */
427 #endif /* PRIVATE_USER_PATH */
432 /* Process the command line arguments */
433 for (i = 1; args && (i < argc); i++)
435 /* Require proper options */
436 if (argv[i][0] != '-')
443 bool is_usage_needed = FALSE;
479 /* HACK - Graphics mode switches on the original tiles */
480 arg_graphics = GRAPHICS_ORIGINAL;
486 arg_force_roguelike = TRUE;
492 arg_force_original = TRUE;
498 show_score = atoi(&argv[i][2]);
499 if (show_score <= 0) show_score = 10;
507 is_usage_needed = TRUE;
511 strcpy(p_ptr->name, &argv[i][2]);
518 is_usage_needed = TRUE;
527 arg_monochrome = TRUE;
533 change_path(&argv[i][2]);
542 is_usage_needed = TRUE;
546 chuukei_server = TRUE;
547 if (connect_chuukei_server(&argv[i][2]) < 0) chuukei_server = FALSE;
556 is_usage_needed = TRUE;
560 chuukei_client = TRUE;
561 connect_chuukei_server(&argv[i][2]);
569 is_usage_needed = TRUE;
573 prepare_browse_movie(&argv[i][2]);
586 is_usage_needed = TRUE;
591 if (!is_usage_needed) continue;
596 /* Hack -- Forget standard args */
604 /* Process the player name */
605 process_player_name(p_ptr,TRUE);
609 /* Install "quit" hook */
610 quit_aux = quit_hook;
615 /* Attempt to use the "main-xaw.c" support */
616 if (!done && (!mstr || (streq(mstr, "xaw"))))
618 extern errr init_xaw(int, char**);
619 if (0 == init_xaw(argc, argv))
628 /* Attempt to use the "main-x11.c" support */
629 if (!done && (!mstr || (streq(mstr, "x11"))))
631 extern errr init_x11(int, char**);
632 if (0 == init_x11(argc, argv))
641 /* Attempt to use the "main-gcu.c" support */
642 if (!done && (!mstr || (streq(mstr, "gcu"))))
644 extern errr init_gcu(int, char**);
645 if (0 == init_gcu(argc, argv))
654 /* Attempt to use the "main-cap.c" support */
655 if (!done && (!mstr || (streq(mstr, "cap"))))
657 extern errr init_cap(int, char**);
658 if (0 == init_cap(argc, argv))
666 /* Make sure we have a display! */
667 if (!done) quit("Unable to prepare any 'display module'!");
670 /* Hack -- If requested, display scores and quit */
671 if (show_score > 0) display_scores(0, show_score);
674 /* Catch nasty signals */
678 init_angband(p_ptr, process_autopick_file_command);
680 /* Wait for response */
684 play_game(p_ptr, new_game);