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 "core/asking-player.h"
10 #include "core/game-play.h"
11 #include "core/scores.h"
12 #include "game-option/runtime-arguments.h"
13 #include "io/files-util.h"
14 #include "io/record-play-movie.h"
15 #include "io/signal-handlers.h"
16 #include "io/uid-checker.h"
17 #include "main-unix/unix-user-ids.h"
18 #include "main/angband-initializer.h"
19 #include "player/process-name.h"
20 #include "system/angband-version.h"
21 #include "system/angband.h"
22 #include "system/player-type-definition.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"
28 #include "view/display-scores.h"
29 #include "wizard/spoiler-util.h"
30 #include "wizard/wizard-spoiler.h"
35 * Available graphic modes
37 #define GRAPHICS_NONE 0
38 #define GRAPHICS_ORIGINAL 1
39 #define GRAPHICS_ADAM_BOLT 2
40 #define GRAPHICS_HENGBAND 3
43 * Some machines have a "main()" function in their "main-xxx.c" file,
44 * all the others use this file for their "main()" function.
49 * A hook for "quit()".
51 * Close down, then fall back into "quit()".
53 static void quit_hook(concptr s)
59 for (auto it = angband_terms.rbegin(); it != angband_terms.rend(); ++it) {
62 if (term == nullptr) {
72 * Set the stack size and overlay buffer (see main-286.c")
74 #ifdef PRIVATE_USER_PATH
77 * Create an ".angband/" directory in the users home directory.
79 * ToDo: Add error handling.
80 * ToDo: Only create the directories when actually writing files.
82 static void create_user_dir(void)
84 const auto &dirpath = path_parse(PRIVATE_USER_PATH);
85 const auto &dir_str = dirpath.string();
86 mkdir(dir_str.data(), 0700);
88 const auto &subdirpath = path_build(dirpath, VARIANT_NAME);
89 const auto &subdir_str = subdirpath.string();
90 mkdir(subdir_str.data(), 0700);
93 #endif /* PRIVATE_USER_PATH */
95 static void init_stuff()
98 const auto tail = getenv("ANGBAND_PATH");
99 strncpy(libpath, tail ? tail : DEFAULT_LIB_PATH, 511);
100 if (!suffix(libpath, PATH_SEP)) {
101 strcat(libpath, PATH_SEP);
104 init_file_paths(libpath);
108 * Handle a "-d<what>=<path>" option
110 * The "<what>" can be any string starting with the same letter as the
111 * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
113 * The "<path>" can be any legal path for the given system, and should
114 * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
116 static void change_path(concptr info)
118 const auto s = angband_strchr(info, '=');
120 /* Verify equal sign */
122 quit_fmt("Try '-d<what>=<path>' not '-d%s'", info);
125 switch (tolower(info[0])) {
127 ANGBAND_DIR_APEX = s + 1;
130 ANGBAND_DIR_FILE = s + 1;
133 ANGBAND_DIR_HELP = s + 1;
136 ANGBAND_DIR_INFO = s + 1;
139 ANGBAND_DIR_USER = s + 1;
142 ANGBAND_DIR_XTRA = s + 1;
145 ANGBAND_DIR_BONE = s + 1;
148 ANGBAND_DIR_DATA = s + 1;
151 ANGBAND_DIR_EDIT = s + 1;
154 ANGBAND_DIR_SAVE = s + 1;
157 ANGBAND_DIR_SCRIPT = s + 1;
160 quit_fmt("Bad semantics in '-d%s'", info);
164 static void display_usage(const char *program)
166 /* Dump usage information */
167 printf("Usage: %s [options] [-- subopts]\n", program);
168 puts(" -n Start a new character");
169 puts(" -f Request fiddle mode");
170 puts(" -w Request wizard mode");
171 puts(" -b Request BGM mode");
172 puts(" -v Request sound mode");
173 puts(" -g Request graphics mode");
174 puts(" -o Request original keyset");
175 puts(" -r Request rogue-like keyset");
176 puts(" -M Request monochrome mode");
177 puts(" -s<num> Show <num> high scores");
178 puts(" -u<who> Use your <who> savefile");
179 puts(" -m<sys> Force 'main-<sys>.c' usage");
180 puts(" -d<def> Define a 'lib' dir sub-path");
181 puts(" --output-spoilers");
182 puts(" Output auto generated spoilers and exit");
186 puts(" -mx11 To use X11");
187 puts(" -- Sub options");
188 puts(" -- -d Set display name");
189 puts(" -- -o Request old 8x8 tile graphics");
190 puts(" -- -a Request Adam Bolt 16x16 tile graphics");
191 puts(" -- -b Request Bigtile graphics mode");
192 puts(" -- -s Turn off smoothscaling graphics");
193 puts(" -- -n# Number of terms to use");
198 puts(" -mgcu To use GCU (GNU Curses)");
199 puts(" -- Sub options");
200 puts(" -- -o old subwindow layout (no bigscreen)");
204 puts(" -mcap To use CAP (\"Termcap\" calls)");
207 /* Actually abort the process */
212 * @brief 2文字以上のコマンドライン引数 (オプション)を実行する
213 * @param opt コマンドライン引数
214 * @return Usageを表示する必要があるか否か
215 * @details v3.0.0 Alpha21時点では、スポイラー出力モードの判定及び実行を行う
217 static bool parse_long_opt(const char *opt)
219 if (strcmp(opt + 2, "output-spoilers") != 0) {
224 init_angband(p_ptr, true);
225 switch (output_all_spoilers()) {
226 case SpoilerOutputResultType::SUCCESSFUL:
227 puts("Successfully created a spoiler file.");
230 case SpoilerOutputResultType::FILE_OPEN_FAILED:
231 quit("Cannot create spoiler file.");
233 case SpoilerOutputResultType::FILE_CLOSE_FAILED:
234 quit("Cannot close spoiler file.");
244 * Simple "main" function for multiple platforms.
246 * Note the special "--" option which terminates the processing of
247 * standard options. All non-standard options (if any) are passed
248 * directly to the "init_xxx()" function.
250 int main(int argc, char *argv[])
253 auto new_game = false;
255 concptr mstr = nullptr;
260 /* Default permissions on files */
265 auto &ids = UnixUserIds::get_instance();
267 ids.set_user_id(getuid());
269 ids.mod_user_id(getgid() * 1000);
272 #if defined(SAFE_SETUID) && defined(_POSIX_SAVED_IDS)
273 ids.set_effective_user_id(geteuid());
274 ids.set_effective_group_id(getegid());
281 user_name(p_ptr->name, ids.get_user_id());
282 #ifdef PRIVATE_USER_PATH
284 #endif /* PRIVATE_USER_PATH */
287 auto browsing_movie = false;
288 for (auto i = 1; args && (i < argc); i++) {
289 if (argv[i][0] != '-') {
290 display_usage(argv[0]);
294 auto is_usage_needed = false;
295 switch (argv[i][1]) {
310 arg_graphics = GRAPHICS_ORIGINAL;
314 arg_force_roguelike = true;
318 arg_force_original = true;
322 show_score = atoi(&argv[i][2]);
323 if (show_score <= 0) {
331 is_usage_needed = true;
335 strcpy(p_ptr->name, &argv[i][2]);
339 is_usage_needed = true;
346 arg_monochrome = true;
350 change_path(&argv[i][2]);
354 is_usage_needed = true;
358 prepare_browse_movie_with_path_build(&argv[i][2]);
359 browsing_movie = true;
362 if (argv[i][2] == '\0') {
368 is_usage_needed = parse_long_opt(argv[i]);
373 is_usage_needed = true;
377 if (!is_usage_needed) {
381 display_usage(argv[0]);
389 process_player_name(p_ptr, true);
390 quit_aux = quit_hook;
393 if (!done && (!mstr || (streq(mstr, "x11")))) {
394 extern errr init_x11(int, char **);
395 if (0 == init_x11(argc, argv)) {
403 if (!done && (!mstr || (streq(mstr, "gcu")))) {
404 extern errr init_gcu(int, char **);
405 if (0 == init_gcu(argc, argv)) {
413 if (!done && (!mstr || (streq(mstr, "cap")))) {
414 extern errr init_cap(int, char **);
415 if (0 == init_cap(argc, argv)) {
423 quit("Unable to prepare any 'display module'!");
426 if (show_score > 0) {
427 display_scores(0, show_score);
433 TermCenteredOffsetSetter tcos(MAIN_TERM_MIN_COLS, MAIN_TERM_MIN_ROWS);
434 init_angband(p_ptr, false);
435 pause_line(MAIN_TERM_MIN_ROWS - 1);
438 play_game(p_ptr, new_game, browsing_movie);