boolean nh_exit_game(int exit_type) { boolean log_disabled = iflags.disable_log; if (!api_entry_checkpoint()) { /* not sure anything in here can actually call panic */ iflags.disable_log = log_disabled; return TRUE; /* terminate was called, so exit is successful */ } program_state.forced_exit = TRUE; /* clean up after viewing a game replay */ if (program_state.viewing) nh_view_replay_finish(); xmalloc_cleanup(); iflags.disable_log = TRUE; if (program_state.game_running) { switch (exit_type) { case EXIT_REQUEST_SAVE: dosave(); /* will ask "really save?" and, if 'y', eventually call terminate. */ break; case EXIT_FORCE_SAVE: dosave0(TRUE); terminate(); break; case EXIT_REQUEST_QUIT: done2(); break; case EXIT_FORCE_QUIT: done(QUIT); break; /* not reached */ case EXIT_PANIC: /* freeing things should be safe */ freedynamicdata(); dlb_cleanup(); panic("UI problem."); break; } iflags.disable_log = log_disabled; api_exit(); return FALSE; } iflags.disable_log = log_disabled; /* calling terminate() will get us out of nested contexts safely, eg: * UI_cmdloop -> nh_command -> UI_update_screen (problem happens here) -> nh_exit_game * will jump all the way back to UI_cmdloop */ terminate(); api_exit(); /* not reached */ return TRUE; }
nh_bool nhnet_exit_game(int exit_type) { json_t *jmsg; int ret; if (!nhnet_active()) return nh_exit_game(exit_type); xmalloc_cleanup(); if (!api_entry()) return 0; jmsg = json_pack("{si}", "exit_type", exit_type); jmsg = send_receive_msg("exit_game", jmsg); if (json_unpack(jmsg, "{si!}", "return", &ret) == -1) { print_error("Incorrect return object in nhnet_exit_game"); ret = 0; } json_decref(jmsg); current_game = 0; api_exit(); return ret; }
void nhnet_describe_pos(int x, int y, struct nh_desc_buf *bufs) { const char *bgdesc, *trapdesc, *objdesc, *mondesc, *invisdesc, *effectdesc; json_t *jmsg; if (!nhnet_active()) return nh_describe_pos(x, y, bufs); if (!api_entry()) return; jmsg = send_receive_msg("describe_pos", json_pack("{si,si}", "x", x, "y", y)); json_unpack(jmsg, "{ss,ss,ss,ss,ss,ss,si!}", "bgdesc", &bgdesc, "trapdesc", &trapdesc, "objdesc", &objdesc, "mondesc", &mondesc, "invisdesc", &invisdesc,"effectdesc", &effectdesc, "objcount", &bufs->objcount); strncpy(bufs->bgdesc, bgdesc, BUFSZ-1); strncpy(bufs->trapdesc, trapdesc, BUFSZ-1); strncpy(bufs->objdesc, objdesc, BUFSZ-1); strncpy(bufs->mondesc, mondesc, BUFSZ-1); strncpy(bufs->invisdesc, invisdesc, BUFSZ-1); strncpy(bufs->effectdesc, effectdesc, BUFSZ-1); json_decref(jmsg); api_exit(); }
/* * ======== dsp_deinit ======== * Frees the resources allocated for bridge. */ bool dsp_deinit(u32 device_context) { bool ret = true; u32 device_node; struct mgr_object *mgr_obj = NULL; struct drv_data *drv_datap = dev_get_drvdata(bridge); while ((device_node = drv_get_first_dev_extension()) != 0) { (void)dev_remove_device((struct cfg_devnode *)device_node); (void)drv_release_resources((u32) device_node, (struct drv_object *)device_context); } (void)drv_destroy((struct drv_object *)device_context); /* Get the Manager Object from driver data * MGR Destroy will unload the DCD dll */ if (drv_datap && drv_datap->mgr_object) { mgr_obj = drv_datap->mgr_object; (void)mgr_destroy(mgr_obj); } else { pr_err("%s: Failed to retrieve the object handle\n", __func__); } api_exit(); return ret; }
const char *nhnet_root_plselection_prompt(char *buf, int buflen, int rolenum, int racenum, int gendnum, int alignnum) { json_t *jmsg; char *str, *ret; if (!nhnet_active()) return nh_root_plselection_prompt(buf, buflen, rolenum, racenum, gendnum, alignnum); if (!api_entry()) return NULL; jmsg = json_pack("{si,si,si,si}", "role", rolenum, "race", racenum, "gend", gendnum, "align", alignnum); jmsg = send_receive_msg("get_root_pl_prompt", jmsg); if (json_unpack(jmsg, "{ss!}", "prompt", &str) == -1) { print_error("Incorrect return object in nhnet_root_plselection_prompt"); ret = NULL; } else { strncpy(buf, str, buflen-1); buf[buflen-1] = '\0'; ret = buf; } json_decref(jmsg); api_exit(); return ret; }
void nh_describe_pos(int x, int y, struct nh_desc_buf *bufs) { int monid = dbuf_get_mon(x, y); bufs->bgdesc[0] = '\0'; bufs->trapdesc[0] = '\0'; bufs->objdesc[0] = '\0'; bufs->mondesc[0] = '\0'; bufs->invisdesc[0] = '\0'; bufs->effectdesc[0] = '\0'; bufs->objcount = -1; if (!program_state.game_running || !api_entry_checkpoint()) return; describe_bg(x, y, level->locations[x][y].mem_bg, bufs->bgdesc); if (level->locations[x][y].mem_trap) strcpy(bufs->trapdesc, trapexplain[level->locations[x][y].mem_trap - 1]); bufs->objcount = describe_object(x, y, level->locations[x][y].mem_obj - 1, bufs->objdesc); describe_mon(x, y, monid - 1, bufs->mondesc); if (level->locations[x][y].mem_invis) strcpy(bufs->invisdesc, invisexplain); if (u.uswallow && (x != u.ux || y != u.uy)) { /* all locations when swallowed other than the hero are the monster */ sprintf(bufs->effectdesc, "interior of %s", Blind ? "a monster" : a_monnam(u.ustuck)); } api_exit(); }
nh_bool nhnet_view_replay_start(int fd, struct nh_window_procs *rwinprocs, struct nh_replay_info *info) { int ret; json_t *jmsg; const char *nextcmd; if (!nhnet_active()) return nh_view_replay_start(fd, rwinprocs, info); if (!api_entry()) return FALSE; alt_windowprocs = *rwinprocs; jmsg = send_receive_msg("view_start", json_pack("{si}", "gameid", fd)); if (json_unpack(jmsg, "{si,s:{ss,si,si,si,si}}", "return", &ret, "info", "nextcmd", &nextcmd, "actions", &info->actions, "max_actions", &info->max_actions, "moves", &info->moves, "max_moves", &info->max_moves) == -1) { print_error("Incorrect return object in nhnet_view_replay_step"); ret = 0; } else strncpy(info->nextcmd, nextcmd, sizeof(info->nextcmd) - 1); api_exit(); return ret; }
nh_bool nhnet_view_replay_step(struct nh_replay_info *info, enum replay_control action, int count) { int ret; json_t *jmsg; const char *nextcmd; if (!nhnet_active()) return nh_view_replay_step(info, action, count); if (!api_entry()) return FALSE; jmsg = send_receive_msg("view_step", json_pack("{si,si,s:{si,si,si,si}}", "action", action, "count", count, "info", "actions", info->actions, "max_actions", info->max_actions, "moves", info->moves, "max_moves", info->max_moves)); if (json_unpack(jmsg, "{si,s:{ss,si,si,si,si}}", "return", &ret, "info", "nextcmd", &nextcmd, "actions", &info->actions, "max_actions", &info->max_actions, "moves", &info->moves, "max_moves", &info->max_moves) == -1) { print_error("Incorrect return object in nhnet_view_replay_step"); } else strncpy(info->nextcmd, nextcmd, sizeof(info->nextcmd) - 1); api_exit(); return ret; }
nh_bool nhnet_set_option(const char *name, union nh_optvalue value, nh_bool isstr) { int ret, i; json_t *jmsg, *joval, *jobj; struct nh_option_desc *gameopts, *birthopts, *opt; struct nh_autopickup_rule *r; ret = nh_set_option(name, value, isstr); if (!nhnet_active()) return ret; if (!api_entry()) return FALSE; gameopts = nhnet_get_options(GAME_OPTIONS); birthopts = nhnet_get_options(CURRENT_BIRTH_OPTIONS); opt = NULL; for (i = 0; gameopts[i].name && !opt; i++) if (!strcmp(name, gameopts[i].name)) opt = &gameopts[i]; for (i = 0; birthopts[i].name && !opt; i++) if (!strcmp(name, birthopts[i].name)) opt = &birthopts[i]; if (opt) { if (isstr || opt->type == OPTTYPE_STRING) joval = json_string(value.s); else if (opt->type == OPTTYPE_INT || opt->type == OPTTYPE_ENUM || opt->type == OPTTYPE_BOOL) { joval = json_integer(value.i); } else if (opt->type == OPTTYPE_AUTOPICKUP_RULES) { joval = json_array(); for (i = 0; value.ar && i < value.ar->num_rules; i++) { r = &value.ar->rules[i]; jobj = json_pack("{ss,si,si,si}", "pattern", r->pattern, "oclass", r->oclass, "buc", r->buc, "action", r->action); json_array_append_new(joval, jobj); } } jmsg = json_pack("{ss,so,si}", "name", name, "value", joval, "isstr", isstr); jmsg = send_receive_msg("set_option", jmsg); if (json_unpack(jmsg, "{si,so!}", "return", &ret, "option", &jobj) == -1) { print_error("Bad response in nhnet_set_option"); } else { free_option_data(opt); read_json_option(jobj, opt); } json_decref(jmsg); } api_exit(); return ret; }
struct nhnet_game *nhnet_list_games(int done, int show_all, int *count) { int i, has_amulet; json_t *jmsg, *jarr, *jobj; struct nhnet_game *gb; struct nhnet_game *gamebuf = NULL; const char *plname, *plrole, *plrace, *plgend, *plalign, *level_desc, *death; if (!api_entry()) return NULL; jmsg = json_pack("{si,si,si}", "limit", 0, "completed", done, "show_all", show_all); jmsg = send_receive_msg("list_games", jmsg); if (json_unpack(jmsg, "{so!}", "games", &jarr) == -1 || !json_is_array(jarr)) { print_error("Incorrect return object in nhnet_list_games"); *count = 0; } else { *count = json_array_size(jarr); gamebuf = xmalloc(*count * sizeof(struct nhnet_game)); for (i = 0; i < *count; i++) { gb = &gamebuf[i]; memset(gb, 0, sizeof(struct nhnet_game)); jobj = json_array_get(jarr, i); if (json_unpack(jobj, "{si,si,si,ss,ss,ss,ss,ss*}", "gameid", &gb->gameid, "status", &gb->status, "playmode", &gb->i.playmode, "plname", &plname, "plrole", &plrole, "plrace", &plrace, "plgend", &plgend, "plalign", &plalign) == -1) { print_error("Invalid game info object."); continue; } strncpy(gb->i.name, plname, PL_NSIZ-1); strncpy(gb->i.plrole, plrole, PLRBUFSZ-1); strncpy(gb->i.plrace, plrace, PLRBUFSZ-1); strncpy(gb->i.plgend, plgend, PLRBUFSZ-1); strncpy(gb->i.plalign, plalign, PLRBUFSZ-1); if (gb->status == LS_SAVED) { json_unpack(jobj, "{ss,si,si,si*}", "level_desc", &level_desc, "moves", &gb->i.moves, "depth", &gb->i.depth, "has_amulet", &has_amulet); gb->i.has_amulet = has_amulet; strncpy(gb->i.level_desc, level_desc, sizeof(gb->i.level_desc)-1); } else if (gb->status == LS_DONE) { json_unpack(jobj, "{ss,si,si*}", "death", &death, "moves", &gb->i.moves, "depth", &gb->i.depth); strncpy(gb->i.death, death, sizeof(gb->i.death)-1); } } } json_decref(jmsg); api_exit(); return gamebuf; }
boolean nh_start_game(int fd, const char *name, int irole, int irace, int igend, int ialign, enum nh_game_modes playmode) { unsigned int seed = 0; if (!api_entry_checkpoint()) return FALSE; /* init failed; programmer error! */ if (fd == -1 || !name || !*name) goto err_out; if (!program_state.restoring) { turntime = (unsigned long long)time(NULL); seed = turntime ^ get_seedval(); /* initialize the random number generator */ mt_srand(seed); } /* else: turntime and rng seeding are done in logreplay.c */ startup_common(name, playmode); if (!validrole(irole) || !validrace(irole, irace) || !validgend(irole, irace, igend) || !validalign(irole, irace, ialign)) goto err_out; u.initrole = irole; u.initrace = irace; u.initgend = igend; u.initalign = ialign; /* write out a new logfile header "NHGAME ..." with all the initial details */ log_init(); log_newgame(fd, turntime, seed, playmode); newgame(); was_on_elbereth = !sengr_at("Elbereth", u.ux, u.uy); /* force botl update later */ wd_message(); api_exit(); return TRUE; err_out: api_exit(); return FALSE; }
boolean nh_set_option(const char *name, union nh_optvalue value, boolean isstring) { boolean rv; if (!api_entry_checkpoint()) return FALSE; rv = set_option(name, value, isstring); api_exit(); return rv; }
struct nh_drawing_info * nhnet_get_drawing_info(void) { json_t *jmsg, *jbg, *jtraps, *jobjs, *jmons, *jwarn, *jexpt, *jzapt, *jzaps, *jeff, *jexps, *jswal, *jinvis; struct nh_drawing_info *di; if (!nhnet_active()) return nh_get_drawing_info(); if (!api_entry()) return 0; jmsg = send_receive_msg("get_drawing_info", json_object()); di = xmalloc(sizeof (struct nh_drawing_info)); if (json_unpack (jmsg, "{si,si,si,si,si,si,si,si,si,so,so,so,so,so,so,so,so,so,so,so,so!}", "num_bgelements", &di->num_bgelements, "num_traps", &di->num_traps, "num_objects", &di->num_objects, "num_monsters", &di->num_monsters, "num_warnings", &di->num_warnings, "num_expltypes", &di->num_expltypes, "num_zaptypes", &di->num_zaptypes, "num_effects", &di->num_effects, "feature_offset", &di->bg_feature_offset, "bgelements", &jbg, "traps", &jtraps, "objects", &jobjs, "monsters", &jmons, "warnings", &jwarn, "expltypes", &jexpt, "zaptypes", &jzapt, "effects", &jeff, "explsyms", &jexps, "zapsyms", &jzaps, "swallowsyms", &jswal, "invis", &jinvis) == -1 || !json_is_array(jbg) || !json_is_array(jobjs) || !json_is_array(jmons) || !json_is_array(jwarn) || !json_is_array(jexpt) || !json_is_array(jzapt) || !json_is_array(jeff) || !json_is_array(jexps) || !json_is_array(jswal) || !json_is_array(jinvis)) { print_error("Incorrect return object in nhnet_get_drawing_info"); di = NULL; } else { di->bgelements = read_symdef_array(jbg); di->traps = read_symdef_array(jtraps); di->objects = read_symdef_array(jobjs); di->monsters = read_symdef_array(jmons); di->warnings = read_symdef_array(jwarn); di->expltypes = read_symdef_array(jexpt); di->zaptypes = read_symdef_array(jzapt); di->effects = read_symdef_array(jeff); di->explsyms = read_symdef_array(jexps); di->zapsyms = read_symdef_array(jzaps); di->swallowsyms = read_symdef_array(jswal); di->invis = read_symdef_array(jinvis); } json_decref(jmsg); api_exit(); return di; }
struct nh_roles_info *nhnet_get_roles(void) { struct nh_roles_info *ri = NULL; json_t *jmsg, *jroles_m, *jroles_f, *jraces, *jgenders, *jaligns, *jmatrix; nh_bool *matrix; int i, size; if (!nhnet_active()) return nh_get_roles(); if (!api_entry()) return NULL; jmsg = send_receive_msg("get_roles", json_object()); ri = xmalloc(sizeof(struct nh_roles_info)); if (json_unpack(jmsg, "{si,si,si,si,si,si,si,si,so,so,so,so,so,so}", "num_roles", &ri->num_roles, "num_races", &ri->num_races, "num_genders", &ri->num_genders, "num_aligns", &ri->num_aligns, "def_role", &ri->def_role, "def_race", &ri->def_race, "def_gend", &ri->def_gend, "def_align", &ri->def_align, "rolenames_m", &jroles_m, "rolenames_f", &jroles_f, "racenames", &jraces, "gendnames", &jgenders, "alignnames", &jaligns, "matrix", &jmatrix) == -1 || !json_is_array(jroles_m) || !json_is_array(jroles_f) || !json_is_array(jraces) || !json_is_array(jgenders) || !json_is_array(jaligns) || !json_is_array(jmatrix) || json_array_size(jroles_m) != ri->num_roles || json_array_size(jroles_f) != ri->num_roles || json_array_size(jraces) != ri->num_races || json_array_size(jgenders) != ri->num_genders || json_array_size(jaligns) != ri->num_aligns) { print_error("Incorrect return object in nhnet_get_roles"); ri = NULL; } else { ri->rolenames_m = read_string_array(jroles_m); ri->rolenames_f = read_string_array(jroles_f); ri->racenames = read_string_array(jraces); ri->gendnames = read_string_array(jgenders); ri->alignnames = read_string_array(jaligns); size = json_array_size(jmatrix); matrix = xmalloc(size * sizeof(nh_bool)); for (i = 0; i < size; i++) matrix[i] = json_integer_value(json_array_get(jmatrix, i)); ri->matrix = matrix; } json_decref(jmsg); api_exit(); return ri; }
int nhnet_command(const char *cmd, int rep, struct nh_cmd_arg *arg) { int ret; json_t *jmsg, *jarg; if (!nhnet_active()) return nh_command(cmd, rep, arg); if (!api_entry()) return ERR_NETWORK_ERROR; xmalloc_cleanup(); switch (arg->argtype) { case CMD_ARG_DIR: jarg = json_pack("{si,si}", "argtype", arg->argtype, "d", arg->d); break; case CMD_ARG_POS: jarg = json_pack("{si,si,si}", "argtype", arg->argtype, "x", arg->pos.x, "y", arg->pos.y); break; case CMD_ARG_OBJ: jarg = json_pack("{si,si}", "argtype", arg->argtype, "invlet", arg->invlet); break; case CMD_ARG_NONE: default: jarg = json_pack("{si}", "argtype", arg->argtype); break; } jmsg = json_pack("{ss,so,si}", "command", cmd ? cmd : "", "arg", jarg, "count", rep); jmsg = send_receive_msg("game_command", jmsg); if (json_unpack(jmsg, "{si!}", "return", &ret) == -1) { print_error("Incorrect return object in nhnet_command"); ret = 0; } json_decref(jmsg); api_exit(); return ret; }
void nhnet_view_replay_finish(void) { if (!nhnet_active()) return nh_view_replay_finish(); xmalloc_cleanup(); alt_windowprocs = windowprocs; if (!api_entry()) return; send_receive_msg("view_finish", json_object()); api_exit(); }
void nh_lib_init(const struct nh_window_procs *procs, char **paths) { int i; if (!api_entry_checkpoint()) /* not sure anything in here can actually call panic */ return; windowprocs = *procs; for (i = 0; i < PREFIX_COUNT; i++) fqn_prefix[i] = strdup(paths[i]); u.uhp = 1; /* prevent RIP on early quits */ init_opt_struct(); turntime = 0; current_timezone = get_tz_offset(); api_exit(); }
struct nh_cmd_desc *nhnet_get_object_commands(int *count, char invlet) { int i, defkey, altkey; json_t *jmsg, *jarr, *jobj; struct nh_cmd_desc *cmdlist = NULL; const char *name, *desc; if (!nhnet_active()) return nh_get_object_commands(count, invlet); if (!api_entry()) return 0; jmsg = json_pack("{si}", "invlet", invlet); jmsg = send_receive_msg("get_obj_commands", jmsg); if (json_unpack(jmsg, "{so!}", "cmdlist", &jarr) == -1 || !json_is_array(jarr)) { print_error("Incorrect return object in nhnet_get_object_commands"); } else { *count = json_array_size(jarr); cmdlist = xmalloc(*count * sizeof(struct nh_cmd_desc)); for (i = 0; i < *count; i++) { jobj = json_array_get(jarr, i); json_unpack(jobj, "{ss,ss,si,si,si!}", "name", &name, "desc", &desc, "def", &defkey, "alt", &altkey, "flags", &cmdlist[i].flags); strcpy(cmdlist[i].name, name); strcpy(cmdlist[i].desc, desc); cmdlist[i].defkey = defkey; cmdlist[i].altkey = altkey; } } json_decref(jmsg); api_exit(); return cmdlist; }
nh_bool nhnet_start_game(const char *name, int role, int race, int gend, int align, enum nh_game_modes playmode) { int ret; json_t *jmsg; if (!api_entry()) return 0; jmsg = json_pack("{ss,si,si,si,si,si}", "name", name, "role", role, "race", race, "gender", gend, "alignment", align, "mode", playmode); jmsg = send_receive_msg("start_game", jmsg); if (json_unpack(jmsg, "{si,si!}", "return", &ret, "gameid", ¤t_game) == -1) { print_error("Incorrect return object in nhnet_start_game"); ret = 0; } json_decref(jmsg); api_exit(); return ret; }
struct nh_option_desc * nhnet_get_options(enum nh_option_list list) { struct nh_option_desc *olist; json_t *jmsg, *jarr, *jobj; int count, i; if (!nhnet_active()) return nh_get_options(list); if (list >= 0 && list < OPTION_LIST_COUNT && option_lists[list]) return option_lists[list]; if (!api_entry()) { olist = xmalloc(sizeof (struct nh_option_desc)); memset(olist, 0, sizeof (struct nh_option_desc)); return olist; } jmsg = send_receive_msg("get_options", json_pack("{si}", "list", list)); if (json_unpack(jmsg, "{so!}", "options", &jarr) == -1 || !json_is_array(jarr)) { print_error("Incorrect return object in nhnet_get_options"); olist = xmalloc(sizeof (struct nh_option_desc)); memset(olist, 0, sizeof (struct nh_option_desc)); } else { count = json_array_size(jarr); option_lists[list] = olist = malloc(sizeof (struct nh_option_desc) * (count + 1)); memset(olist, 0, sizeof (struct nh_option_desc) * (count + 1)); for (i = 0; i < count; i++) { jobj = json_array_get(jarr, i); read_json_option(jobj, &olist[i]); } } json_decref(jmsg); api_exit(); return olist; }
int nhnet_restore_game(int gid, struct nh_window_procs *rwinprocs) { int ret; json_t *jmsg; if (!api_entry()) return ERR_NETWORK_ERROR; jmsg = json_pack("{si}", "gameid", gid); jmsg = send_receive_msg("restore_game", jmsg); if (json_unpack(jmsg, "{si!}", "return", &ret) == -1) { print_error("Incorrect return object in nhnet_restore_game"); ret = ERR_NETWORK_ERROR; /* we don't know the error actually was, any error code will do */ } json_decref(jmsg); if (ret == GAME_RESTORED) current_game = gid; api_exit(); return ret; }
/* * ======== dsp_deinit ======== * Frees the resources allocated for bridge. */ bool dsp_deinit(u32 device_context) { bool ret = true; u32 device_node; struct mgr_object *mgr_obj = NULL; while ((device_node = drv_get_first_dev_extension()) != 0) { (void)dev_remove_device((struct cfg_devnode *)device_node); (void)drv_release_resources((u32) device_node, (struct drv_object *)device_context); } (void)drv_destroy((struct drv_object *)device_context); /* Get the Manager Object from Registry * MGR Destroy will unload the DCD dll */ if (!cfg_get_object((u32 *) &mgr_obj, REG_MGR_OBJECT)) (void)mgr_destroy(mgr_obj); api_exit(); return ret; }
int main(int argc, char **argv) { int exit_code = EXIT_FAILURE; int i; bool help = false; bool version = false; bool check_config = false; bool daemon = false; const char *debug_filter = NULL; int pid_fd = -1; for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "--help") == 0) { help = true; } else if (strcmp(argv[i], "--version") == 0) { version = true; } else if (strcmp(argv[i], "--check-config") == 0) { check_config = true; } else if (strcmp(argv[i], "--daemon") == 0) { daemon = true; } else if (strcmp(argv[i], "--debug") == 0) { if (i + 1 < argc && strncmp(argv[i + 1], "--", 2) != 0) { debug_filter = argv[++i]; } else { debug_filter = ""; } } else { fprintf(stderr, "Unknown option '%s'\n\n", argv[i]); print_usage(); return EXIT_FAILURE; } } if (help) { print_usage(); return EXIT_SUCCESS; } if (version) { printf("%s\n", VERSION_STRING); return EXIT_SUCCESS; } read_image_version(); _x11_enabled = access("/etc/tf_x11_enabled", F_OK) == 0; if (prepare_paths() < 0) { return EXIT_FAILURE; } if (check_config) { return config_check(_config_filename) < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } config_init(_config_filename); if (config_has_error()) { fprintf(stderr, "Error(s) occurred while reading config file '%s'", _config_filename); goto error_config; } log_init(); if (daemon) { pid_fd = daemon_start(_log_filename, _pid_filename, 1); } else { pid_fd = pid_file_acquire(_pid_filename, getpid()); if (pid_fd == PID_FILE_ALREADY_ACQUIRED) { fprintf(stderr, "Already running according to '%s'\n", _pid_filename); } } if (pid_fd < 0) { goto error_pid_file; } if (daemon && _x11_enabled) { log_info("RED Brick API Daemon %s started (daemonized, X11 enabled) on %s image", VERSION_STRING, _image_version); } else if (daemon) { log_info("RED Brick API Daemon %s started (daemonized) on %s image", VERSION_STRING, _image_version); } else if (_x11_enabled) { log_info("RED Brick API Daemon %s started (X11 enabled) on %s image", VERSION_STRING, _image_version); } else { log_info("RED Brick API Daemon %s started on %s image", VERSION_STRING, _image_version); } if (debug_filter != NULL) { log_enable_debug_override(debug_filter); } if (config_has_warning()) { log_warn("Warning(s) in config file '%s', run with --check-config option for details", _config_filename); } if (event_init() < 0) { goto error_event; } if (signal_init(handle_sighup, NULL) < 0) { goto error_signal; } if (process_monitor_init() < 0) { goto error_process_monitor; } if (cron_init() < 0) { goto error_cron; } if (inventory_init() < 0) { goto error_inventory; } if (api_init() < 0) { goto error_api; } if (network_init(_brickd_socket_filename, _cron_socket_filename) < 0) { goto error_network; } if (inventory_load_programs() < 0) { goto error_load_programs; } if (event_run(network_cleanup_brickd_and_socats) < 0) { goto error_run; } exit_code = EXIT_SUCCESS; error_run: inventory_unload_programs(); error_load_programs: network_exit(); error_network: api_exit(); error_api: inventory_exit(); error_inventory: cron_exit(); error_cron: process_monitor_exit(); error_process_monitor: signal_exit(); error_signal: event_exit(); error_event: log_info("RED Brick API Daemon %s stopped", VERSION_STRING); error_pid_file: if (pid_fd >= 0) { pid_file_release(_pid_filename, pid_fd); } log_exit(); error_config: config_exit(); return exit_code; }
/** * RESCH APIs are called through write() system call. * See api.h for details. * Do not use timespec_to_jiffies(), since it rounds up the value. */ static ssize_t resch_write (struct file *file, const char *buf, size_t count, loff_t *offset) { int res = RES_SUCCESS; struct api_struct a; unsigned long us; /* copy data to kernel buffer. */ if (copy_from_user(&a, buf, count)) { printk(KERN_WARNING "RESCH: failed to copy data.\n"); return -EFAULT; } switch (a.api) { /* PORT I: preemptive periodic real-time scheduling.*/ case API_INIT: res = api_init(); break; case API_EXIT: res = api_exit(a.rid); break; case API_RUN: us = timespec_to_usecs(&a.arg.ts); res = api_run(a.rid, usecs_to_jiffies(us)); break; case API_WAIT_PERIOD: res = api_wait_for_period(a.rid); break; case API_WAIT_INTERVAL: us = timespec_to_usecs(&a.arg.ts); res = api_wait_for_interval(a.rid, usecs_to_jiffies(us)); break; case API_SET_PERIOD: us = timespec_to_usecs(&a.arg.ts); res = api_set_period(a.rid, usecs_to_jiffies(us)); break; case API_SET_DEADLINE: us = timespec_to_usecs(&a.arg.ts); res = api_set_deadline(a.rid, usecs_to_jiffies(us)); break; case API_SET_WCET: us = timespec_to_usecs(&a.arg.ts); res = api_set_wcet(a.rid, us); break; case API_SET_RUNTIME: us = timespec_to_usecs(&a.arg.ts); res = api_set_runtime(a.rid, us); break; case API_SET_PRIORITY: res = api_set_priority(a.rid, a.arg.val); break; case API_SET_SCHEDULER: res = api_set_scheduler(a.rid, a.arg.val); break; case API_BACKGROUND: res = api_background(a.rid); break; /* PORT II: event-driven asynchrous scheduling.*/ case API_SLEEP: us = timespec_to_usecs(&a.arg.ts); res = api_sleep(a.rid, usecs_to_jiffies(us)); break; case API_SUSPEND: res = api_suspend(a.rid); break; case API_WAKE_UP: res = api_wake_up(a.arg.val); break; /* PORT III: reservation-based scheduling.*/ case API_RESERVE_START: us = timespec_to_usecs(&a.arg.ts); res = api_reserve_start(a.rid, usecs_to_jiffies(us), false); break; case API_RESERVE_START_XCPU: us = timespec_to_usecs(&a.arg.ts); res = api_reserve_start(a.rid, usecs_to_jiffies(us), true); break; case API_RESERVE_STOP: res = api_reserve_stop(a.rid); break; case API_RESERVE_EXPIRE: res = api_reserve_expire(a.rid); break; case API_SERVER_RUN: res = api_server_run(a.rid); break; /* PORT IV.*/ /* PORT V: hierarchical scheduling.*/ case API_COMPONENT_CREATE: res = api_component_create(); break; case API_COMPONENT_DESTROY: res = api_component_destroy(a.arg.val); break; case API_COMPOSE: res = api_compose(a.rid, a.arg.val); break; case API_DECOMPOSE: res = api_decompose(a.rid); break; default: /* illegal api identifier. */ res = RES_ILLEGAL; printk(KERN_WARNING "RESCH: illegal API identifier.\n"); break; } return res; }
struct nh_topten_entry *nhnet_get_topten(int *out_len, char *statusbuf, const char *player, int top, int around, nh_bool own) { struct nh_topten_entry *ttlist; json_t *jmsg, *jarr, *jobj; const char *msg, *plrole, *plrace, *plgend, *plalign, *name, *death, *entrytxt; int len, i, highlight; if (!nhnet_active()) return nh_get_topten(out_len, statusbuf, player, top, around, own); *out_len = 0; if (!api_entry()) return NULL; jmsg = json_pack("{ss,si,si,si}", "player", player ? player : "", "top", top, "around", around, "own", own); jmsg = send_receive_msg("get_topten", jmsg); if (json_unpack(jmsg, "{so,ss!}", "toplist", &jarr, "msg", &msg) == -1 || !json_is_array(jarr)) { print_error("Incorrect return object in nhnet_get_topten"); ttlist = NULL; } else { len = json_array_size(jarr); strncpy(statusbuf, msg, BUFSZ-1); *out_len = len; ttlist = xmalloc((len+1) * sizeof(struct nh_topten_entry)); memset(ttlist, 0, (len+1) * sizeof(struct nh_topten_entry)); for (i = 0; i < len; i++) { jobj = json_array_get(jarr, i); json_unpack(jobj, "{si,si,si,si,si,si,si,si,si,si,si,si,si,ss,ss,ss,ss,ss,ss,ss,si!}", "rank", &ttlist[i].rank, "points", &ttlist[i].points, "maxlvl", &ttlist[i].maxlvl, "hp", &ttlist[i].hp, "maxhp", &ttlist[i].maxhp, "deaths", &ttlist[i].deaths, "ver_major", &ttlist[i].ver_major, "ver_minor", &ttlist[i].ver_minor, "patchlevel", &ttlist[i].patchlevel, "deathdate", &ttlist[i].deathdate, "birthdate", &ttlist[i].birthdate, "moves", &ttlist[i].moves, "end_how", &ttlist[i].end_how, "plrole", &plrole, "plrace", &plrace, "plgend", &plgend, "plalign", &plalign, "name", &name, "death", &death, "entrytxt", &entrytxt, "highlight", &highlight); strncpy(ttlist[i].plrole, plrole, PLRBUFSZ - 1); strncpy(ttlist[i].plrace, plrace, PLRBUFSZ - 1); strncpy(ttlist[i].plgend, plgend, PLRBUFSZ - 1); strncpy(ttlist[i].plalign, plalign, PLRBUFSZ - 1); strncpy(ttlist[i].name, name, PL_NSIZ - 1); strncpy(ttlist[i].death, death, BUFSZ - 1); strncpy(ttlist[i].entrytxt, entrytxt, BUFSZ - 1); ttlist[i].highlight = highlight; } } json_decref(jmsg); api_exit(); return ttlist; }
/* command wrapper function: make sure the game is able to run commands, perform * logging and generate reasonable return values for api clients with no access * to internal state */ int nh_command(const char *cmd, int rep, struct nh_cmd_arg *arg) { int cmdidx, cmdresult, pre_moves; unsigned int pre_rngstate; if (!program_state.game_running) return ERR_GAME_NOT_RUNNING; cmdidx = get_command_idx(cmd); if (program_state.viewing && (cmdidx < 0 || !(cmdlist[cmdidx].flags & CMD_NOTIME))) return ERR_COMMAND_FORBIDDEN; /* */ if (!api_entry_checkpoint()) { /* terminate() in end.c will arrive here */ if (program_state.panicking) return GAME_PANICKED; if (!program_state.gameover) return GAME_SAVED; if (program_state.forced_exit) return ERR_FORCED_EXIT; return GAME_OVER; } /* if the game is being restored, turntime is set in restore_read_command */ turntime = time(NULL); log_command(cmdidx, rep, arg); pre_rngstate = mt_nextstate(); pre_moves = moves; /* do the deed. command_input returns -1 if the command completed normally */ cmdresult = command_input(cmdidx, rep, arg); /* make sure we actually want this command to be logged */ if (cmdidx >= 0 && (cmdlist[cmdidx].flags & CMD_NOTIME) && pre_rngstate == mt_nextstate() && pre_moves == moves) log_revert_command(); /* nope, cut it out of the log */ else log_command_result(); /* log the result */ api_exit(); /* no unsafe operations after this point */ if (cmdresult != -1) return cmdresult; /* * performing a command can put the game into several different states: * - the command completes immediately: a simple move or an attack etc * multi == 0, occupation == NULL * - if a count is given, the command will (usually) take count turns * multi == count (> 0), occupation == NULL * - the command may cause a delay: for ex. putting on or removing armor * multi == -delay (< 0), occupation == NULL * multi is incremented in you_moved * - the command may take multiple moves, and require a callback to be * run for each move. example: forcing a lock * multi >= 0, occupation == callback */ if (multi >= 0 && occupation) return OCCUPATION_IN_PROGRESS; else if (multi > 0) return MULTI_IN_PROGRESS; else if (multi < 0) return POST_ACTION_DELAY; return READY_FOR_INPUT; }
struct nh_topten_entry * nh_get_topten(int *out_len, char *statusbuf, const char * volatile player, int top, int around, boolean own) { struct toptenentry *ttlist, newtt; struct nh_topten_entry *score_list; boolean game_inited = (wiz1_level.dlevel != 0); boolean game_complete = game_inited && moves && program_state.gameover; int rank = -1; /* index of the completed game in the topten list */ int fd, i, j, sel_count; boolean *selected, off_list = FALSE; statusbuf[0] = '\0'; *out_len = 0; if (!api_entry_checkpoint()) return NULL; if (!game_inited) { /* If nh_get_topten() isn't called after a game, we never went through initialization. */ dlb_init(); init_dungeons(); } if (!player) { if (game_complete) player = plname; else player = ""; } fd = open_datafile(RECORD, O_RDONLY, SCOREPREFIX); ttlist = read_topten(fd, TTLISTLEN); close(fd); if (!ttlist) { strcpy(statusbuf, "Cannot open record file!"); api_exit(); return NULL; } /* find the rank of a completed game in the score list */ if (game_complete && !strcmp(player, plname)) { fill_topten_entry(&newtt, end_how); /* find this entry in the list */ for (i = 0; i < TTLISTLEN && validentry(ttlist[i]); i++) if (!memcmp(&ttlist[i], &newtt, sizeof (struct toptenentry))) rank = i; if (wizard || discover) sprintf(statusbuf, "Since you were in %s mode, your game was not " "added to the score list.", wizard ? "wizard" : "discover"); else if (rank >= 0 && rank < 10) sprintf(statusbuf, "You made the top ten list!"); else if (rank) sprintf(statusbuf, "You reached the %d%s place on the score list.", rank + 1, ordin(rank + 1)); } /* select scores for display */ sel_count = 0; selected = calloc(TTLISTLEN, sizeof (boolean)); for (i = 0; i < TTLISTLEN && validentry(ttlist[i]); i++) { if (top == -1 || i < top) selected[i] = TRUE; if (own && !strcmp(player, ttlist[i].name)) selected[i] = TRUE; if (rank != -1 && rank - around <= i && i <= rank + around) selected[i] = TRUE; if (selected[i]) sel_count++; } if (game_complete && sel_count == 0) { /* didn't make it onto the list and nothing else is selected */ ttlist[0] = newtt; selected[0] = TRUE; sel_count++; off_list = TRUE; } score_list = xmalloc(sel_count * sizeof (struct nh_topten_entry)); memset(score_list, 0, sel_count * sizeof (struct nh_topten_entry)); *out_len = sel_count; j = 0; for (i = 0; i < TTLISTLEN && validentry(ttlist[i]); i++) { if (selected[i]) fill_nh_score_entry(&ttlist[i], &score_list[j++], i + 1, i == rank); } if (off_list) { score_list[0].rank = -1; score_list[0].highlight = TRUE; } if (!game_inited) { free_dungeon(); dlb_cleanup(); } free(selected); free(ttlist); api_exit(); return score_list; }
enum nh_restore_status nh_restore_game(int fd, struct nh_window_procs *rwinprocs, boolean force_replay) { int playmode, irole, irace, igend, ialign; char namebuf[PL_NSIZ]; /* some compilers can't cope with the fact that all subsequent stores to error * are not dead, but become important if the error handler longjumps back * volatile is required to prevent invalid optimization based on that wrong * assumption. */ volatile enum nh_restore_status error = GAME_RESTORED; if (fd == -1) return ERR_BAD_ARGS; switch (nh_get_savegame_status(fd, NULL)) { case LS_INVALID: return ERR_BAD_FILE; case LS_DONE: return ERR_GAME_OVER; case LS_CRASHED: force_replay = TRUE; break; case LS_IN_PROGRESS: return ERR_IN_PROGRESS; case LS_SAVED: break; /* default, everything is A-OK */ } if (!api_entry_checkpoint()) goto error_out; error = ERR_BAD_FILE; replay_set_logfile(fd); /* store the fd and try to get a lock or exit */ replay_begin(); program_state.restoring = TRUE; iflags.disable_log = TRUE; /* don't log any of the commands, they're already in the log */ /* Read the log header for this game. */ replay_read_newgame(&turntime, &playmode, namebuf, &irole, &irace, &igend, &ialign); /* set special windowprocs which will autofill requests for user input * with data from the log file */ replay_setup_windowprocs(rwinprocs); startup_common(namebuf, playmode); u.initrole = irole; u.initrace = irace; u.initgend = igend; u.initalign = ialign; if (!force_replay) { error = ERR_RESTORE_FAILED; replay_run_cmdloop(TRUE, FALSE, TRUE); replay_jump_to_endpos(); if (!dorecover_fd(fd)) { replay_undo_jump_to_endpos(); goto error_out2; } replay_undo_jump_to_endpos(); wd_message(); program_state.game_running = 1; post_init_tasks(); } else { replay_run_cmdloop(TRUE, TRUE, FALSE); /* option setup only */ newgame(); /* try replaying instead */ error = ERR_REPLAY_FAILED; replay_run_cmdloop(FALSE, FALSE, TRUE); replay_sync_save(); } /* restore standard window procs */ replay_restore_windowprocs(); program_state.restoring = FALSE; iflags.disable_log = FALSE; /* clean up data used for replay */ replay_end(); log_truncate(); log_init(); /* must be called before we start writing to the log */ /* info might not have reached the ui while alternate window procs were set */ doredraw(); /* nh_start_game() does this via newgame(), but since this function doesn't * call newgame(), we have to do it here instead. */ notify_levelchange(NULL); bot(); flush_screen(); was_on_elbereth = !sengr_at("Elbereth", u.ux, u.uy); /* force botl update later */ welcome(FALSE); realtime_messages(TRUE, TRUE); update_inventory(); api_exit(); return GAME_RESTORED; error_out2: api_exit(); error_out: replay_restore_windowprocs(); program_state.restoring = FALSE; iflags.disable_log = FALSE; replay_end(); unlock_fd(fd); if (error == ERR_RESTORE_FAILED) { raw_printf("Restore failed. Attempting to replay instead.\n"); error = nh_restore_game(fd, rwinprocs, TRUE); } return error; }
void do_shutdown(shutop_t op) { touch(SYNC_SHUTDOWN); if (sdown) run_interactive(sdown, "Calling shutdown hook: %s", sdown); /* Update UTMP db */ utmp_set_halt(); /* * Tell all remaining non-monitored processes to exit, give them * some time to exit gracefully, 2 sec is customary. */ do_kill(SIGTERM); do_sleep(2); do_kill(SIGKILL); /* Exit plugins and API gracefully */ plugin_exit(); api_exit(); /* Reap 'em */ while (waitpid(-1, NULL, WNOHANG) > 0) ; /* Close all local non-console descriptors */ for (int fd = 3; fd < 128; fd++) close(fd); if (vfork()) { /* * Put PID 1 aside and let child perform reboot/halt * kernel may exit child and we don't want to exit PID 1 * ... causing "aiii killing init" during reboot ... */ return; } /* Unmount any tmpfs before unmounting swap ... */ unmount_tmpfs(); run("/sbin/swapoff -e -a"); /* ... unmount remaining regular file systems. */ unmount_regular(); /* We sit on / so we must remount it ro, try all the things! */ sync(); run("/bin/mount -n -o remount,ro -t dummytype dummydev /"); run("/bin/mount -n -o remount,ro dummydev /"); run("/bin/mount -n -o remount,ro /"); /* Call mdadm to mark any RAID array(s) as clean before halting. */ mdadm_wait(); /* Reboot via watchdog or kernel, or shutdown? */ if (op == SHUT_REBOOT) { if (wdogpid) { int timeout = 10; /* Wait here until the WDT reboots, or timeout with fallback */ print(kill(wdogpid, SIGPWR) == 1, "Pending watchdog reboot"); while (timeout--) do_sleep(1); } _d("Rebooting ..."); reboot(RB_AUTOBOOT); } else if (op == SHUT_OFF) { _d("Powering down ..."); reboot(RB_POWER_OFF); } /* Also fallback if any of the other two fails */ _d("Halting ..."); reboot(RB_HALT_SYSTEM); }
/* * ======== dsp_init ======== * Allocates bridge resources. Loads a base image onto DSP, if specified. */ u32 dsp_init(u32 *init_status) { char dev_node[MAXREGPATHLENGTH] = "TIOMAP1510"; int status = -EPERM; struct drv_object *drv_obj = NULL; u32 device_node; u32 device_node_string; if (!api_init()) goto func_cont; status = drv_create(&drv_obj); if (status) { api_exit(); goto func_cont; } /* End drv_create */ /* Request Resources */ status = drv_request_resources((u32) &dev_node, &device_node_string); if (!status) { /* Attempt to Start the Device */ status = dev_start_device((struct cfg_devnode *) device_node_string); if (status) (void)drv_release_resources ((u32) device_node_string, drv_obj); } else { dev_dbg(bridge, "%s: drv_request_resources Failed\n", __func__); status = -EPERM; } /* Unwind whatever was loaded */ if (status) { /* irrespective of the status of dev_remove_device we conitinue * unloading. Get the Driver Object iterate through and remove. * Reset the status to E_FAIL to avoid going through * api_init_complete2. */ for (device_node = drv_get_first_dev_extension(); device_node != 0; device_node = drv_get_next_dev_extension(device_node)) { (void)dev_remove_device((struct cfg_devnode *) device_node); (void)drv_release_resources((u32) device_node, drv_obj); } /* Remove the Driver Object */ (void)drv_destroy(drv_obj); drv_obj = NULL; api_exit(); dev_dbg(bridge, "%s: Logical device failed init\n", __func__); } /* Unwinding the loaded drivers */ func_cont: /* Attempt to Start the Board */ if (!status) { /* BRD_AutoStart could fail if the dsp execuetable is not the * correct one. We should not propagate that error * into the device loader. */ (void)api_init_complete2(); } else { dev_dbg(bridge, "%s: Failed\n", __func__); } /* End api_init_complete2 */ DBC_ENSURE((!status && drv_obj != NULL) || (status && drv_obj == NULL)); *init_status = status; /* Return the Driver Object */ return (u32) drv_obj; }