/** * Looks up an option in the option dictionary by the given name. Creates a new option and adds it to * the options dictionary if not found */ static _option* _query_or_new(hashtable* options, const char* name) { _option_wrapper* option_wrapper; _option* option; option = _query(options, name); if (!option) { /* Not found, create and insert */ option = (_option*)malloc(sizeof(_option)); memset(option, 0, sizeof(_option)); option->name = xp_strdup(name); /* Key by the long name */ option_wrapper = (_option_wrapper*)malloc(sizeof(_option_wrapper)); memset(option_wrapper, 0, sizeof(_option_wrapper)); option_wrapper->key = xp_strdup(name); option_wrapper->alias = 0; /* We own the option */ option_wrapper->o = option; ht_insert(options, (void*)option_wrapper); /* Key by the short name */ _set_shortname(options, name, name[0]); } return option; }
/** * Adds the given option to the options list * * options - The options dictionary to which to add the option * name - The long name of the option (example "velocity") * description - The human readable description, used to print usage * has_default - 1 if the value in intptr has a valid default at startup, 0 if a value must be supplied * option_type - The data type of the option (OPTION_INT/OPTION_FLOAT/...) * valptr - Pointer to a variable that will receive the parsed option * * NOTES: * - Calling the function with a null options dictionary has no effect * - If the option has already been added, it will be replaced */ static void _add_option(hashtable* options, const char* name, const char* description, int has_default, int option_type, void* valptr) { _option* option; if (!options) { return; } option = _query_or_new(options, name); option->type = option_type; option->has_default = has_default; option->accepts_value = option->type == OPTION_INT || option->type == OPTION_FLOAT || option->type == OPTION_STRING; if (option->description) { /* Free previous description */ free(option->description); option->description = 0; } if (description) { option->description = xp_strdup(description); } option->value.valptr = valptr; }
/** * Sets the one-character shortname of the given option * * options - The options dictionary which contains the option * name - The (full) name of the option * shortname - The one-character short name of the option * * NOTES: * - It is not necessary to call this function unless you wish to override the default short name, which * is the first letter of the long name * - If an existing short name exists (including the default), it will be removed and replaced * - If an identical short name exists, it will be replaced with this one, even if it is for a different * option */ void _set_shortname(hashtable* options, const char* name, char shortname) { _option* option; _option_wrapper* wrapper, *query_wrapper; char* str_shortname; if (!options) { return; } option = _query(options, name); if (!option) { return; } xp_asprintf(&str_shortname, "%c", shortname); wrapper = (_option_wrapper*)malloc(sizeof(_option_wrapper)); wrapper->key = str_shortname; wrapper->alias = 1; /* We don't own the option */ query_wrapper = wrapper; if (ht_lookup(options, (void*)&wrapper) != 0) { /* It's not in there, just add it */ wrapper->key = xp_strdup(str_shortname); ht_insert(options, (void*)wrapper); } else { /* Already in there */ free(query_wrapper->key); free(query_wrapper); } wrapper->o = option; }
/** * Sets the given usage text that will be shown when arguments do not match and as the top line of the * help */ void optin_set_usage_text(optin* o, const char* usage) { if (!o) { return; } if (o->usage) { free(o->usage); } if (usage) { o->usage = xp_strdup(usage); } }
/* * Modify an option during the game. * * Options which can be modified have a so called tuner function, * which checks the validity of the new option value, and possibly * does something extra depending upon the option in question. * Options which don't need such a tuner function set it to 'tuner_dummy'. * Options which cannot be modified have the tuner set to 'tuner_none'. */ int Tune_option(char *name, char *val) { int ival; double fval; option_desc *opt; if (!(opt = Find_option_by_name(name))) return -2; /* Variable not found */ if (opt->tuner == tuner_none) return -1; /* Operation undefined */ switch (opt->type) { case valInt: if (Convert_string_to_int(val, &ival) != true) return 0; *(int *)opt->variable = ival; (*opt->tuner)(); return 1; case valBool: if (ON(val)) *(bool *)opt->variable = true; else if (OFF(val)) *(bool *)opt->variable = false; else return 0; (*opt->tuner)(); return 1; case valReal: if (Convert_string_to_float(val, &fval) != true) return 0; *(double *)opt->variable = fval; (*opt->tuner)(); return 1; case valString: { char *s = xp_strdup(val); if (!s) return 0; if (*(char **)(opt->variable) != opt->defaultValue) free(*(char **)opt->variable); *(char **)opt->variable = s; (*opt->tuner)(); return 1; } default: return -1; /* Operation undefined */ } }
/** * Processes the given option as if it had been given on the command line * * o - The optin object that contains the option * opt - The long or short option name (e.g. "velocity" or "v"), do not include dashes * value - The value that the option takes (e.g "35"). Pass NULL if the option takes no value * * RETURNS: zero if the option was processed successfully, nonzero if there was an error */ int optin_process_option(optin* o, const char* opt, const char* value) { _option* option; /*fprintf(stderr, "Processing option: %s, value: %s\n", opt, value);*/ option = _query(o->options, opt); if (!option) { fprintf(stderr, "Unrecognized option: %s\n", opt); return OPTIN_ERR_INVALID_OPTION; } switch(option->type) { case OPTION_FLAG: if (option->value.intptr != 0) { *option->value.intptr = 1; } break; case OPTION_INT: if (option->value.intptr != 0) { *option->value.intptr = atoi(value); } break; case OPTION_FLOAT: if (option->value.floatptr != 0) { *option->value.floatptr = atof(value); } break; case OPTION_STRING: if (option->value.stringptr != 0) { *option->value.stringptr = xp_strdup(value); } break; } option->set = 1; return 0; }
int main(int argc, char **argv) { int timer_tick_rate; char *addr; /* world is a global now */ world = &World; if (sock_startup() < 0) { warn("Error initializing sockets\n"); return 1; } if (World_init() < 0) { warn("Error initializing world\n"); return 1; } /* * Make output always linebuffered. By default pipes * and remote shells cause stdout to be fully buffered. */ setvbuf(stdout, NULL, _IOLBF, BUFSIZ); setvbuf(stderr, NULL, _IOLBF, BUFSIZ); /* * --- Output copyright notice --- */ xpprintf(" " COPYRIGHT ".\n" " " TITLE " comes with ABSOLUTELY NO WARRANTY; " "for details see the\n" " provided COPYING file.\n\n"); init_error(argv[0]); /*seedMT((unsigned)time(NULL) * Get_process_id());*/ /* Removed seeding random number generator because of server recordings. */ Groups_init(); /* Make trigonometric tables */ Make_table(); if (!Parser(argc, argv)) exit(1); Init_recording(); /* Lock the server into memory */ plock_server(options.pLockServer); Asteroid_line_init(); Wormhole_line_init(); Walls_init(); /* Allocate memory for players, shots and messages */ Alloc_players(Num_bases() + MAX_PSEUDO_PLAYERS + MAX_SPECTATORS); spectatorStart = Num_bases() + MAX_PSEUDO_PLAYERS; Alloc_shots(MAX_TOTAL_SHOTS); Alloc_cells(); Move_init(); Robot_init(); Treasure_init(); Hitmasks_init(); Rank_init_saved_scores(); /* * Get server's official name. */ if (options.serverHost) { addr = sock_get_addr_by_name(options.serverHost); if (addr == NULL) { warn("Failed name lookup on: %s", options.serverHost); exit(1); } serverAddr = xp_strdup(addr); strlcpy(Server.host, options.serverHost, sizeof(Server.host)); } else sock_get_local_hostname(Server.host, sizeof Server.host, (options.reportToMetaServer != 0 && options.searchDomainForXPilot != 0)); Get_login_name(Server.owner, sizeof Server.owner); /* Log, if enabled. */ Log_game("START"); if (!Contact_init()) End_game(); Meta_init(); Timing_setup(); Check_playerlimit(); if (Setup_net_server() == -1) End_game(); #ifndef _WINDOWS if (options.NoQuit) signal(SIGHUP, SIG_IGN); else signal(SIGHUP, Handle_signal); signal(SIGTERM, Handle_signal); signal(SIGINT, Handle_signal); signal(SIGPIPE, SIG_IGN); #ifdef IGNORE_FPE signal(SIGFPE, SIG_IGN); #endif #endif /* _WINDOWS */ /* * Set the time the server started */ serverStartTime = time(NULL); xpprintf("%s Server runs at %d frames per second\n", showtime(), options.framesPerSecond); teamcup_init(); #ifdef SELECT_SCHED install_timer_tick(Main_loop, FPS); #else if (options.timerResolution > 0) timer_tick_rate = options.timerResolution; else timer_tick_rate = FPS; # ifdef _WINDOWS /* Windows returns here, we let the worker thread call sched() */ install_timer_tick(ServerThreadTimerProc, timer_tick_rate); # else install_timer_tick(Main_loop, timer_tick_rate); # endif #endif sched(); End_game(); /* NOT REACHED */ abort(); }