void config_open(const char *filename) { if (!file_exists(filename)) config_save(filename); STRINGBUFFER *cmd = stringbuffer_new(); #ifdef SYSTEM_OS_TYPE_WINDOW stringbuffer_append(cmd, "notepad.exe"); #else if (file_exists("/usr/bin/vim")) stringbuffer_append(cmd, "/usr/bin/vim"); else if (file_exists("/usr/bin/emacs")) stringbuffer_append(cmd, "/usr/bin/emacs"); else if (file_exists("/usr/bin/nano")) stringbuffer_append(cmd, "/usr/bin/nano"); else if (file_exists("/bin/vi")) stringbuffer_append(cmd, "/bin/vi"); else message_error("no editor found"); #endif stringbuffer_append(cmd, " "); stringbuffer_append(cmd, filename); system(stringbuffer_getTextPointer(cmd)); stringbuffer_free(cmd); config_load(filename); }
TOOLKIT_DEINIT_FUNC_FINISH /** * Joins two path components, eg, '/usr' and 'bin' -> '/usr/bin'. * @param path * First path component. * @param path2 * Second path component. * @return * The joined path; should be freed when no longer needed. */ char *path_join(const char *path, const char *path2) { StringBuffer *sb; size_t len; char *cp; TOOLKIT_PROTECT(); sb = stringbuffer_new(); stringbuffer_append_string(sb, path); len = strlen(path); if (len && path[len - 1] != '/') { stringbuffer_append_string(sb, "/"); } stringbuffer_append_string(sb, path2); cp = stringbuffer_finish(sb); return cp; }
void initConfig() { _config_param = parameter_new(); /* config-dir */ char *home = getenv("HOME"); if (home == NULL) { error_set(ERROR_CONFIG_HOME, "Unable to get home directory."); return; } STRINGBUFFER *tmp_cfg = stringbuffer_new(); /* config-directory */ stringbuffer_append(tmp_cfg, home); stringbuffer_append(tmp_cfg, SEPARATOR); stringbuffer_append(tmp_cfg, CONFIG_DIRECTORY); _config_directory = stringbuffer_clone(tmp_cfg); /* config-file */ stringbuffer_append(tmp_cfg, SEPARATOR); stringbuffer_append(tmp_cfg, CONFIG_FILE); _config_file = stringbuffer_clone(tmp_cfg); printf ( "CONFIGFILE:\t%s\n", stringbuffer_getTextPointer(_config_file) ); stringbuffer_free(tmp_cfg); /* load config */ _config_param = parameter_new(); parameter_loadFromFile(_config_param, stringbuffer_getTextPointer(_config_file)); checkParameter(CONFIG_DIRECTORY_STORE_KEY, CONFIG_DIRECTORY_STORE_VALUE); checkParameter(CONFIG_DIRECTORY_RESTORE_KEY, CONFIG_DIRECTORY_RESTORE_VALUE); checkParameter(CONFIG_DIRECTORY_KEY_KEY, CONFIG_DIRECTORY_KEY_VALUE); /* make directories */ char *tmp_dir; /* make store directory */ tmp_dir = parameter_get(_config_param, CONFIG_DIRECTORY_STORE_KEY); assert(tmp_dir); if (!directory_exists(tmp_dir)) directory_create(tmp_dir); free(tmp_dir); /* make restore directory */ tmp_dir = parameter_get(_config_param, CONFIG_DIRECTORY_RESTORE_KEY); assert(tmp_dir); if (!directory_exists(tmp_dir)) directory_create(tmp_dir); free(tmp_dir); /* make key directory */ tmp_dir = parameter_get(_config_param, CONFIG_DIRECTORY_KEY_KEY); assert(tmp_dir); if (!directory_exists(tmp_dir)) directory_create(tmp_dir); free(tmp_dir); }
/** * Normalize a path, eg, foo//bar, foo/foo2/../bar, foo/./bar all become * foo/bar. * * If the path begins with either a forward slash or a dot *and* a forward * slash, they will be preserved. * @param path * Path to normalize. * @return * The normalized path; never NULL. Must be freed. */ char *path_normalize(const char *path) { StringBuffer *sb; size_t pos, startsbpos; char component[MAX_BUF]; ssize_t last_slash; TOOLKIT_PROTECT(); if (string_isempty(path)) { return estrdup("."); } sb = stringbuffer_new(); pos = 0; if (string_startswith(path, "/")) { stringbuffer_append_string(sb, "/"); } else if (string_startswith(path, "./")) { stringbuffer_append_string(sb, "./"); } startsbpos = stringbuffer_length(sb); while (string_get_word(path, &pos, '/', component, sizeof(component), 0)) { if (strcmp(component, ".") == 0) { continue; } if (strcmp(component, "..") == 0) { if (stringbuffer_length(sb) > startsbpos) { last_slash = stringbuffer_rindex(sb, '/'); if (last_slash == -1) { LOG(BUG, "Should have found a forward slash, but didn't: %s", path); continue; } stringbuffer_seek(sb, last_slash); } } else { size_t len = stringbuffer_length(sb); if (len == 0 || stringbuffer_data(sb)[len - 1] != '/') { stringbuffer_append_string(sb, "/"); } stringbuffer_append_string(sb, component); } } if (stringbuffer_length(sb) == 0) { stringbuffer_append_string(sb, "."); } return stringbuffer_finish(sb); }
/** * Get absolute path to the specified relative path. This path will typically * point to the to client data directory (which is usually located in the user's * home/appdata directory), but depending on the specified mode, extra actions * may be performed. These ensure that if you're trying to access a file that * does not yet exist in the client data directory, it will be read from the * client installation directory instead (unless it's being appended to, in * which case it will be copied to the client data directory first). * * Generally, you should almost always use this when you need to construct a * path, or use one of the many @ref file_wrapper_functions. * @param fname * The file path. * @param mode * File mode. * @return * The absolute path. Must be freed. */ char *file_path(const char *path, const char *mode) { bool is_write, is_append; StringBuffer *sb; char version[MAX_BUF], client_path[HUGE_BUF], *new_path; HARD_ASSERT(path != NULL); HARD_ASSERT(mode != NULL); SOFT_ASSERT_RC(path[0] != '/', estrdup(path), "Path is already absolute: %s", path); sb = stringbuffer_new(); stringbuffer_append_printf(sb, "%s/.atrinik/%s/%s", get_config_dir(), package_get_version_partial(VS(version)), path); new_path = stringbuffer_sub(sb, 0, 0); is_write = is_append = false; if (strchr(mode, 'w') != NULL) { is_write = true; } else if (strchr(mode, '+') != NULL || strchr(mode, 'a') != NULL) { is_append = true; } if (is_write || is_append) { if (access(new_path, W_OK) != 0) { char *dirname; /* Ensure directories exist if we're going to use this path for * writing/appending. */ dirname = path_dirname(new_path); mkdir_recurse(dirname); efree(dirname); if (is_append) { get_data_dir_file(VS(client_path), path); copy_file(client_path, new_path); } } } else { if (access(new_path, R_OK) != 0) { get_data_dir_file(VS(client_path), path); stringbuffer_seek(sb, 0); stringbuffer_append_string(sb, client_path); } } efree(new_path); return stringbuffer_finish(sb); }
void initList(int strc, char **strv) { if ( strc <= 0) return; STRINGBUFFER *sb = stringbuffer_new(); int i; for (i = 0; i < strc; ++i) { stringbuffer_append(sb, strv[i]); stringbuffer_append(sb, " "); } gList = stringbuffer_text(sb); stringbuffer_free(sb); }
/** * Constructs a path leading to the chosen server settings directory. Used * internally by file_path_player() and file_path_server(). * @return * */ static StringBuffer *file_path_server_internal(void) { StringBuffer *sb; sb = stringbuffer_new(); stringbuffer_append_string(sb, "settings/"); SOFT_ASSERT_RC(selected_server != NULL, sb, "Selected server is NULL."); SOFT_ASSERT_RC(!string_isempty(selected_server->hostname), sb, "Selected server has empty hostname."); stringbuffer_append_printf(sb, "servers/%s-%d/", selected_server->hostname, selected_server->port); return sb; }
void doUpdate() { STRINGBUFFER *sb = stringbuffer_new(); stringbuffer_append(sb, gPath); stringbuffer_append(sb, "/"); switch (gSystem) { case SYSTEM_YUM: stringbuffer_append(sb, "yum update"); break; case SYSTEM_APT: stringbuffer_append(sb, "apt-get update"); break; default: fprintf(stderr, "ERROR: Undefined system.\n"); exit(EXIT_FAILURE); } stringbuffer_append(sb, " "); stringbuffer_append(sb, gList); system(stringbuffer_getTextPointer(sb)); stringbuffer_free(sb); }
/** * Load the entire contents of file 'path' into a StringBuffer instance, * then return the created string. * @param path * File to load contents of. * @return * The loaded contents. Must be freed. */ char *path_file_contents(const char *path) { FILE *fp; StringBuffer *sb; char buf[MAX_BUF]; TOOLKIT_PROTECT(); fp = fopen(path, "rb"); if (!fp) { return NULL; } sb = stringbuffer_new(); while (fgets(buf, sizeof(buf), fp)) { stringbuffer_append_string(sb, buf); } fclose(fp); return stringbuffer_finish(sb); }
stringbuffer::stringbuffer() { this->obj = stringbuffer_new(); }
STRINGBUFFER *stringbuffer_clone(STRINGBUFFER *ptr) { STRINGBUFFER *new_ptr = stringbuffer_new(); stringbuffer_append(new_ptr, ptr->text); return new_ptr; }
/** * Generate a message detailing the properties of 1-6 artifacts drawn * sequentially from the artifact list. * @param level Level of the book * @param buf Buffer to contain the description. * @param booksize Length of the book. * @return 'buf'. */ static char *artifact_msg(int level, char *buf, size_t booksize) { artifactlist *al; artifact *art; int chance, i, type, index; int book_entries = level > 5 ? RANDOM () % 3 + RANDOM () % 3 + 2 : RANDOM () % level + 1; char *final, *ch; object *tmp = NULL; StringBuffer *desc; /* Values greater than 5 create msg buffers that are too big! */ if (book_entries > 5) { book_entries = 5; } /* Let's determine what kind of artifact type randomly. * Right now legal artifacts only come from those listed * in art_name_array. Also, we check to be sure an artifactlist * for that type exists! */ i = 0; do { index = rndm(1, arraysize(art_name_array)) - 1; type = art_name_array[index].type; al = find_artifactlist(type); i++; } while (al == NULL && i < 10); /* Unable to find a message */ if (i == 10) { snprintf(buf, booksize, "None"); return buf; } /* There is no reason to start on the artifact list at the begining. Lets * take our starting position randomly... */ art = al->items; for (i = rndm(1, level) + rndm(0, 1); i > 0; i--) { /* Out of stuff, loop back around */ if (art == NULL) { art = al->items; } art = art->next; } /* Ok, let's print out the contents */ snprintf(buf, booksize, "<t t=\"Magical %s\">Herein %s detailed %s...\n", art_name_array[index].name, book_entries > 1 ? "are" : "is", book_entries > 1 ? "some artifacts" : "an artifact"); /* Artifact msg attributes loop. Let's keep adding entries to the 'book' * as long as we have space up to the allowed max # (book_entires) */ while (book_entries > 0) { if (art == NULL) { art = al->items; } desc = stringbuffer_new(); tmp = get_archetype(art->def_at_name); give_artifact_abilities(tmp, art); SET_FLAG(tmp, FLAG_IDENTIFIED); stringbuffer_append_printf(desc, "\n<t t=\"%s %s\">It is ", tmp->name, tmp->title ? tmp->title : ""); /* Chance of finding. */ chance = 100 * ((float) art->chance / al->total_chance); if (chance >= 20) { stringbuffer_append_string(desc, "an uncommon"); } else if (chance >= 10) { stringbuffer_append_string(desc, "an unusual"); } else if (chance >= 5) { stringbuffer_append_string(desc, "a rare"); } else { stringbuffer_append_string(desc, "a very rare"); } /* Value of artifact. */ stringbuffer_append_printf(desc, " item with a value of %s.", cost_string_from_value(tmp->value)); if ((ch = describe_item(tmp)) && strlen(ch) > 1) { stringbuffer_append_printf(desc, "\nProperties of this artifact include:\n %s", ch); } final = stringbuffer_finish(desc); /* Add the buf if it will fit. */ if (book_overflow(buf, final, booksize)) { free(final); break; } snprintf(buf + strlen(buf), booksize - strlen(buf), "%s", final); free(final); art = art->next; book_entries--; }
/** * Analyze /cmd type commands the player has typed in the console or bound to a * key. * Sort out the "client intern" commands and expand or pre process them for the * server. * @param cmd * Command to check * @return * 0 to send command to server, 1 to not send it */ int client_command_check(const char *cmd) { if (cmd_aliases_handle(cmd)) { return 1; } else if (strncasecmp(cmd, "/ready_spell", 12) == 0) { cmd = strchr(cmd, ' '); if (!cmd || *++cmd == '\0') { draw_info(COLOR_RED, "Usage: /ready_spell <spell name>"); return 1; } else { object *tmp; for (tmp = cpl.ob->inv; tmp; tmp = tmp->next) { if (tmp->itype == TYPE_SPELL && strncasecmp(tmp->s_name, cmd, strlen(cmd)) == 0) { if (!(tmp->flags & CS_FLAG_APPLIED)) { client_send_apply(tmp); } return 1; } } } draw_info(COLOR_RED, "Unknown spell."); return 1; } else if (strncasecmp(cmd, "/ready_skill", 12) == 0) { cmd = strchr(cmd, ' '); if (!cmd || *++cmd == '\0') { draw_info(COLOR_RED, "Usage: /ready_skill <skill name>"); return 1; } else { object *tmp; for (tmp = cpl.ob->inv; tmp; tmp = tmp->next) { if (tmp->itype == TYPE_SKILL && strncasecmp(tmp->s_name, cmd, strlen(cmd)) == 0) { if (!(tmp->flags & CS_FLAG_APPLIED)) { client_send_apply(tmp); } return 1; } } } draw_info(COLOR_RED, "Unknown skill."); return 1; } else if (!strncmp(cmd, "/help", 5)) { cmd += 5; if (*cmd == '\0') { help_show("main"); } else { help_show(cmd + 1); } return 1; } else if (!strncmp(cmd, "/resetwidgets", 13)) { widgets_reset(); return 1; } else if (!strncmp(cmd, "/effect ", 8)) { if (!strcmp(cmd + 8, "none")) { effect_stop(); draw_info(COLOR_GREEN, "Stopped effect."); return 1; } if (effect_start(cmd + 8)) { draw_info_format(COLOR_GREEN, "Started effect %s.", cmd + 8); } else { draw_info_format(COLOR_RED, "No such effect %s.", cmd + 8); } return 1; } else if (!strncmp(cmd, "/d_effect ", 10)) { effect_debug(cmd + 10); return 1; } else if (!strncmp(cmd, "/music_pause", 12)) { sound_pause_music(); return 1; } else if (!strncmp(cmd, "/music_resume", 13)) { sound_resume_music(); return 1; } else if (!strncmp(cmd, "/party joinpassword ", 20)) { cmd += 20; if (cpl.partyjoin[0] != '\0') { char buf[MAX_BUF]; snprintf(VS(buf), "/party join %s\t%s", cpl.partyjoin, cmd); send_command(buf); } return 1; } else if (!strncmp(cmd, "/invfilter ", 11)) { inventory_filter_set_names(cmd + 11); return 1; } else if (!strncasecmp(cmd, "/screenshot", 11)) { SDL_Surface *surface_save; cmd += 11; if (!strncasecmp(cmd, " map", 4)) { surface_save = cur_widget[MAP_ID]->surface; } else { surface_save = ScreenSurface; } if (!surface_save) { draw_info(COLOR_RED, "No surface to save."); return 1; } screenshot_create(surface_save); return 1; } else if (!strncasecmp(cmd, "/console-load ", 14)) { FILE *fp; char path[HUGE_BUF], buf[HUGE_BUF * 4], *cp; StringBuffer *sb; cmd += 14; snprintf(path, sizeof(path), "%s/.atrinik/console/%s", get_config_dir(), cmd); fp = fopen(path, "r"); if (!fp) { draw_info_format(COLOR_RED, "Could not read %s.", path); return 1; } send_command("/console noinf::"); while (fgets(buf, sizeof(buf) - 1, fp)) { cp = strchr(buf, '\n'); if (cp) { *cp = '\0'; } sb = stringbuffer_new(); stringbuffer_append_string(sb, "/console noinf::"); stringbuffer_append_string(sb, buf); cp = stringbuffer_finish(sb); send_command(cp); efree(cp); } send_command("/console noinf::"); fclose(fp); return 1; } else if (strncasecmp(cmd, "/console-obj", 11) == 0) { menu_inventory_loadtoconsole(cpl.inventory_focus, NULL, NULL); return 1; } else if (strncasecmp(cmd, "/patch-obj", 11) == 0) { menu_inventory_patch(cpl.inventory_focus, NULL, NULL); return 1; } else if (string_startswith(cmd, "/cast ") || string_startswith(cmd, "/use_skill ")) { object *tmp; uint8_t type; type = string_startswith(cmd, "/cast ") ? TYPE_SPELL : TYPE_SKILL; cmd = strchr(cmd, ' ') + 1; if (string_isempty(cmd)) { return 1; } for (tmp = cpl.ob->inv; tmp; tmp = tmp->next) { if (tmp->itype == type && strncasecmp(tmp->s_name, cmd, strlen(cmd)) == 0) { client_send_fire(5, tmp->tag); return 1; } } draw_info_format(COLOR_RED, "Unknown %s.", type == TYPE_SPELL ? "spell" : "skill"); return 1; } else if (strncasecmp(cmd, "/clearcache", 11) == 0) { cmd += 12; if (string_isempty(cmd)) { return 1; } if (strcasecmp(cmd, "sound") == 0) { sound_clear_cache(); draw_info(COLOR_GREEN, "Sound cache cleared."); } else if (strcasecmp(cmd, "textures") == 0) { texture_reload(); draw_info(COLOR_GREEN, "Textures reloaded."); } return 1; } else if (string_startswith(cmd, "/droptag ") || string_startswith(cmd, "/gettag ")) { char *cps[3]; unsigned long int loc, tag, num; if (string_split(strchr(cmd, ' ') + 1, cps, arraysize(cps), ' ') != arraysize(cps)) { return 1; } loc = strtoul(cps[0], NULL, 10); tag = strtoul(cps[1], NULL, 10); num = strtoul(cps[2], NULL, 10); client_send_move(loc, tag, num); if (string_startswith(cmd, "/gettag ")) { sound_play_effect("get.ogg", 100); } else { sound_play_effect("drop.ogg", 100); } return 1; } else if (string_startswith(cmd, "/talk")) { char type[MAX_BUF], npc_name[MAX_BUF]; size_t pos; uint8_t type_num; packet_struct *packet; pos = 5; if (!string_get_word(cmd, &pos, ' ', type, sizeof(type), 0) || string_isempty(cmd + pos)) { return 1; } type_num = atoi(type); if (type_num == CMD_TALK_NPC_NAME && (!string_get_word(cmd, &pos, ' ', npc_name, sizeof(npc_name), '"') || string_isempty(cmd + pos))) { return 1; } packet = packet_new(SERVER_CMD_TALK, 64, 64); packet_append_uint8(packet, type_num); if (type_num == CMD_TALK_NPC || type_num == CMD_TALK_NPC_NAME) { if (type_num == CMD_TALK_NPC_NAME) { packet_append_string_terminated(packet, npc_name); } packet_append_string_terminated(packet, cmd + pos); } else { char tag[MAX_BUF]; if (!string_get_word(cmd, &pos, ' ', tag, sizeof(tag), 0) || string_isempty(cmd + pos)) { packet_free(packet); return 1; } packet_append_uint32(packet, atoi(tag)); packet_append_string_terminated(packet, cmd + pos); } socket_send_packet(packet); return 1; } else if (string_startswith(cmd, "/widget_toggle")) { size_t pos; char word[MAX_BUF], *cps[2]; int widget_id; pos = 14; while (string_get_word(cmd, &pos, ' ', word, sizeof(word), 0)) { if (string_split(word, cps, arraysize(cps), ':') < 1) { continue; } widget_id = widget_id_from_name(cps[0]); /* Invalid widget ID */ if (widget_id == -1) { continue; } /* Redraw all or a specific one identified by its UID */ if (cps[1] == NULL) { WIDGET_SHOW_TOGGLE_ALL(widget_id); } else { widgetdata *widget; widget = widget_find(NULL, widget_id, cps[1], NULL); if (widget) { WIDGET_SHOW_TOGGLE(widget); } } } return 1; } else if (string_startswith(cmd, "/widget_focus")) { size_t pos; char word[MAX_BUF], *cps[2]; int widget_id; pos = 14; while (string_get_word(cmd, &pos, ' ', word, sizeof(word), 0)) { if (string_split(word, cps, arraysize(cps), ':') < 1) { continue; } widget_id = widget_id_from_name(cps[0]); if (widget_id == -1) { /* Invalid widget ID */ continue; } widget_switch_focus(widget_id, cps[1]); } return 1; } else if (string_startswith(cmd, "/ping")) { keepalive_ping_stats(); return 1; } else if (string_startswith(cmd, "/region_map")) { region_map_open(); return 1; } return 0; }
/** * Parse the metaserver certificate information. * * @param server * Metaserver entry. * @return * True on success, false on failure. */ static bool parse_metaserver_cert (server_struct *server) { HARD_ASSERT(server != NULL); if (server->cert == NULL || server->cert_sig == NULL) { /* No certificate. */ return true; } /* Generate a SHA512 hash of the certificate's contents. */ unsigned char cert_digest[SHA512_DIGEST_LENGTH]; if (SHA512((unsigned char *) server->cert, strlen(server->cert), cert_digest) == NULL) { LOG(ERROR, "SHA512() failed: %s", ERR_error_string(ERR_get_error(), NULL)); return false; } char cert_hash[SHA512_DIGEST_LENGTH * 2 + 1]; SOFT_ASSERT_RC(string_tohex(VS(cert_digest), VS(cert_hash), false) == sizeof(cert_hash) - 1, false, "string_tohex failed"); string_tolower(cert_hash); /* Verify the signature. */ if (!curl_verify(CURL_PKEY_TRUST_ULTIMATE, cert_hash, strlen(cert_hash), server->cert_sig, server->cert_sig_len)) { LOG(ERROR, "Failed to verify signature"); return false; } server_cert_info_t *info = ecalloc(1, sizeof(*info)); char buf[MAX_BUF]; size_t pos = 0; bool in_info = false; while (string_get_word(server->cert, &pos, '\n', VS(buf), 0)) { char *cp = buf; string_skip_whitespace(cp); string_strip_newline(cp); if (*cp == '\0') { continue; } if (strcmp(cp, cert_begin_str) == 0) { in_info = true; continue; } else if (!in_info) { continue; } else if (strcmp(cp, cert_end_str) == 0) { break; } char *cps[2]; if (string_split(cp, cps, arraysize(cps), ':') != arraysize(cps)) { LOG(ERROR, "Parsing error"); continue; } string_tolower(cps[0]); string_skip_whitespace(cps[1]); const char *key = cps[0]; const char *value = cps[1]; char **content = NULL; if (strcmp(key, "name") == 0) { content = &info->name; } else if (strcmp(key, "hostname") == 0) { content = &info->hostname; } else if (strcmp(key, "ipv4 address") == 0) { content = &info->ipv4_address; } else if (strcmp(key, "ipv6 address") == 0) { content = &info->ipv6_address; } else if (strcmp(key, "public key") == 0) { content = &info->pubkey; } else if (strcmp(key, "port") == 0) { info->port = atoi(value); } else if (strcmp(key, "crypto port") == 0) { info->port_crypto = atoi(value); } else { LOG(DEVEL, "Unrecognized key: %s", key); continue; } if (content != NULL) { StringBuffer *sb = stringbuffer_new(); if (*content != NULL) { stringbuffer_append_string(sb, *content); stringbuffer_append_char(sb, '\n'); efree(*content); } stringbuffer_append_string(sb, value); *content = stringbuffer_finish(sb); } } /* Ensure we got the data we need. */ if (info->name == NULL || info->hostname == NULL || info->pubkey == NULL || info->port_crypto <= 0 || (info->ipv4_address == NULL) != (info->ipv6_address == NULL)) { LOG(ERROR, "Certificate is missing required data."); goto error; } /* Ensure certificate attributes match the advertised ones. */ if (strcmp(info->hostname, server->hostname) != 0) { LOG(ERROR, "Certificate hostname does not match advertised hostname."); goto error; } if (strcmp(info->name, server->name) != 0) { LOG(ERROR, "Certificate name does not match advertised name."); goto error; } if (info->port != server->port) { LOG(ERROR, "Certificate port does not match advertised port."); goto error; } if (info->port_crypto != server->port_crypto) { LOG(ERROR, "Certificate crypto port does not match advertised crypto port."); goto error; } server->cert_info = info; return true; error: metaserver_cert_free(info); return false; }
BOOL active_server_callCommandExternal(ACTIVE_SERVER *self, const char *cmd, const char *arg) { assert(self); assert(cmd); char *tmp; tmp = active_server_correct_path(self->root, cmd); STRINGBUFFER *bin = stringbuffer_new(); stringbuffer_append(bin, tmp); free(tmp); #ifdef SYSTEM_OS_TYPE_WINDOWS stringbuffer_append(bin, ".exe"); #endif if (!file_exists(stringbuffer_getTextPointer(bin))) { network_writeStatus(NET, FALSE); exception_setLong(ERR, -1, "binary file not found", stringbuffer_getTextPointer(bin), "check the command"); exception_throwCallback(ERR); stringbuffer_free(bin); return FALSE; } else { network_writeStatus(NET, TRUE); } /* get client OK */ if (!network_readStatus(NET)) { exception_setShort(ERR, -1, "client not ready"); exception_throwCallback(ERR); stringbuffer_free(bin); return FALSE; } /* create message-id */ STRINGBUFFER *sb = stringbuffer_new(); tmp = datetime_getTimestampAsString(); stringbuffer_append(sb, tmp); free(tmp); stringbuffer_append(sb, "_"); tmp = number_unsignedIntegerToString(rand()); stringbuffer_append(sb, tmp); free(tmp); stringbuffer_append(sb, "@"); tmp = network_getAcceptAddress(NET); stringbuffer_append(sb, tmp); free(tmp); char *id = stringbuffer_getText(sb); if (system_isDebug()) { printf ( "MESSAGE-ID:\t%s\n", id ); } network_writeString(NET, id); if (!network_readStatus(NET)) { free(id); stringbuffer_free(bin); exception_setShort(ERR, -1, "client allows id"); exception_throwCallback(ERR); return FALSE; } /* add arguments to command */ if (arg) { stringbuffer_append(bin, " "); stringbuffer_append(bin, arg); } if (system_isDebug()) { printf ( "EXECUTE:\t\t%s\n", stringbuffer_getTextPointer(bin) ); } /* redirect stderr-stream */ stringbuffer_append(bin, " 2>&1"); /* call process */ FILE *proc; proc = popen(stringbuffer_getTextPointer(bin), "r"); stringbuffer_free(bin); if (!proc) { free(id); exception_setLong(ERR, -1, "unable to start process", strerror(errno), "check command"); exception_throwCallback(ERR); return FALSE; } /* send line by line */ char line[ACTIVE_BUFFER_SIZE]; while (fgets(line, ACTIVE_BUFFER_SIZE, proc)) { network_writeString(NET, line); if (!network_readStatus(NET)) { free(id); pclose(proc); exception_setShort(ERR, -1, "client sent an error"); exception_throwCallback(ERR); return FALSE; } } /* close process */ int exitcode = pclose(proc); /* send EOF(id) */ char *eof = (char *)malloc(3 + 1 + strlen(id) + 1 + 1); strcpy(eof, "EOF("); strcat(eof, id); strcat(eof, ")"); network_writeString(NET, eof); /* read id */ char *res = network_readString(NET); BOOL ok = (strcmp(id, res) == 0); /* free */ free(res); free(eof); free(id); if (!ok) { network_writeStatus(NET, FALSE); exception_setShort(ERR, -1, "client sent an error"); exception_throwCallback(ERR); return FALSE; } network_writeStatus(NET, TRUE); /* send ok */ if (!network_readStatus(NET)) { exception_setShort(ERR, -1, "client allows id"); exception_throwCallback(ERR); return FALSE; } /* send exitcode */ network_writeNumber(NET, exitcode); return network_readStatus(NET); }
/** * Player examines some object. * @param op Player. * @param tmp Object to examine. */ void examine(object *op, object *tmp) { char buf[VERY_BIG_BUF], tmp_buf[64]; int i; if (tmp == NULL || tmp->type == CLOSE_CON) { return; } strcpy(buf, "That is "); strncat(buf, long_desc(tmp, op), VERY_BIG_BUF - strlen(buf) - 1); buf[VERY_BIG_BUF - 1] = '\0'; /* Only add this for usable items, not for objects like walls or * floors for example. */ if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED) && need_identify(tmp)) { strncat(buf, " (unidentified)", VERY_BIG_BUF - strlen(buf) - 1); } buf[VERY_BIG_BUF - 1] = '\0'; new_draw_info(NDI_UNIQUE, op, buf); buf[0] = '\0'; if (QUERY_FLAG(tmp, FLAG_MONSTER) || tmp->type == PLAYER) { new_draw_info_format(NDI_UNIQUE, op, "%s.", describe_item(tmp->head ? tmp->head : tmp)); examine_living(op, tmp); } /* We don't double use the item_xxx arch commands, so they are always valid */ else if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)) { if (QUERY_FLAG(tmp, FLAG_IS_GOOD)) { new_draw_info_format(NDI_UNIQUE, op, "It is good aligned."); } else if (QUERY_FLAG(tmp, FLAG_IS_EVIL)) { new_draw_info_format(NDI_UNIQUE, op, "It is evil aligned."); } else if (QUERY_FLAG(tmp, FLAG_IS_NEUTRAL)) { new_draw_info_format(NDI_UNIQUE, op, "It is neutral aligned."); } if (tmp->item_level) { if (tmp->item_skill) { new_draw_info_format(NDI_UNIQUE, op, "It needs a level of %d in %s to use.", tmp->item_level, find_skill_exp_skillname(tmp->item_skill)); } else { new_draw_info_format(NDI_UNIQUE, op, "It needs a level of %d to use.", tmp->item_level); } } if (tmp->item_quality) { if (QUERY_FLAG(tmp, FLAG_INDESTRUCTIBLE)) { new_draw_info_format(NDI_UNIQUE, op, "Qua: %d Con: Indestructible.", tmp->item_quality); } else { new_draw_info_format(NDI_UNIQUE, op, "Qua: %d Con: %d.", tmp->item_quality, tmp->item_condition); } } buf[0] = '\0'; } switch (tmp->type) { case SPELLBOOK: if (QUERY_FLAG(tmp, FLAG_IDENTIFIED) && tmp->stats.sp >= 0 && tmp->stats.sp <= NROFREALSPELLS) { if (tmp->sub_type == ST1_SPELLBOOK_CLERIC) { snprintf(buf, sizeof(buf), "%s is a %d level prayer.", spells[tmp->stats.sp].name, spells[tmp->stats.sp].level); } else { snprintf(buf, sizeof(buf), "%s is a %d level spell.", spells[tmp->stats.sp].name, spells[tmp->stats.sp].level); } } break; case BOOK: if (tmp->msg != NULL) { strcpy(buf, "Something is written in it."); } break; case CONTAINER: if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)) { if (tmp->race != NULL) { if (tmp->weight_limit) { snprintf(buf, sizeof(buf), "It can hold only %s and its weight limit is %.1f kg.", tmp->race, (float) tmp->weight_limit / 1000.0f); } else { snprintf(buf, sizeof(buf), "It can hold only %s.", tmp->race); } /* Has magic modifier? */ if (tmp->weapon_speed != 1.0f) { new_draw_info(NDI_UNIQUE, op, buf); /* Bad */ if (tmp->weapon_speed > 1.0f) { snprintf(buf, sizeof(buf), "It increases the weight of items inside by %.1f%%.", tmp->weapon_speed * 100.0f); } /* Good */ else { snprintf(buf, sizeof(buf), "It decreases the weight of items inside by %.1f%%.", 100.0f - (tmp->weapon_speed * 100.0f)); } } } else { if (tmp->weight_limit) { snprintf(buf, sizeof(buf), "Its weight limit is %.1f kg.", (float)tmp->weight_limit / 1000.0f); } /* Has magic modifier? */ if (tmp->weapon_speed != 1.0f) { new_draw_info(NDI_UNIQUE, op, buf); /* Bad */ if (tmp->weapon_speed > 1.0f) { snprintf(buf, sizeof(buf), "It increases the weight of items inside by %.1f%%.", tmp->weapon_speed * 100.0f); } /* Good */ else { snprintf(buf, sizeof(buf), "It decreases the weight of items inside by %.1f%%.", 100.0f - (tmp->weapon_speed * 100.0f)); } } } new_draw_info(NDI_UNIQUE, op, buf); if (tmp->weapon_speed == 1.0f) { snprintf(buf, sizeof(buf), "It contains %3.3f kg.", (float) tmp->carrying / 1000.0f); } else if (tmp->weapon_speed > 1.0f) { snprintf(buf, sizeof(buf), "It contains %3.3f kg, increased to %3.3f kg.", (float) tmp->damage_round_tag / 1000.0f, (float) tmp->carrying / 1000.0f); } else { snprintf(buf, sizeof(buf), "It contains %3.3f kg, decreased to %3.3f kg.", (float) tmp->damage_round_tag / 1000.0f, (float) tmp->carrying / 1000.0f); } } break; case WAND: if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)) { snprintf(buf, sizeof(buf), "It has %d charges left.", tmp->stats.food); } break; case POWER_CRYSTAL: /* Avoid division by zero... */ if (tmp->stats.maxsp == 0) { snprintf(buf, sizeof(buf), "It has capacity of %d.", tmp->stats.maxsp); } else { int i; /* Higher capacity crystals */ if (tmp->stats.maxsp > 1000) { i = (tmp->stats.maxsp % 1000) / 100; if (i) { snprintf(tmp_buf, sizeof(tmp_buf), "It has capacity of %d.%dk and is ", tmp->stats.maxsp / 1000, i); } else { snprintf(tmp_buf, sizeof(tmp_buf), "It has capacity of %dk and is ", tmp->stats.maxsp / 1000); } } else { snprintf(tmp_buf, sizeof(tmp_buf), "It has capacity of %d and is ", tmp->stats.maxsp); } strcat(buf, tmp_buf); i = (tmp->stats.sp * 10) / tmp->stats.maxsp; if (tmp->stats.sp == 0) { strcat(buf, "empty."); } else if (i == 0) { strcat(buf, "almost empty."); } else if (i < 3) { strcat(buf, "partially filled."); } else if (i < 6) { strcat(buf, "half full."); } else if (i < 9) { strcat(buf, "well charged."); } else if (tmp->stats.sp == tmp->stats.maxsp) { strcat(buf, "fully charged."); } else { strcat(buf, "almost full."); } } break; } if (buf[0] != '\0') { new_draw_info(NDI_UNIQUE, op, buf); } if (tmp->material && (need_identify(tmp) && QUERY_FLAG(tmp, FLAG_IDENTIFIED))) { strcpy(buf, "It is made of: "); for (i = 0; i < NROFMATERIALS; i++) { if (tmp->material & (1 << i)) { strcat(buf, material[i].name); strcat(buf, " "); } } new_draw_info(NDI_UNIQUE, op, buf); } if (tmp->weight) { float weight = (float) (tmp->nrof ? tmp->weight * (int) tmp->nrof : tmp->weight) / 1000.0f; if (tmp->type == MONSTER) { new_draw_info_format(NDI_UNIQUE, op, "%s weighs %3.3f kg.", gender_subjective_upper[object_get_gender(tmp)], weight); } else if (tmp->type == PLAYER) { new_draw_info_format(NDI_UNIQUE, op, "%s weighs %3.3f kg and is carrying %3.3f kg.", gender_subjective_upper[object_get_gender(tmp)], weight, (float) tmp->carrying / 1000.0f); } else { new_draw_info_format(NDI_UNIQUE, op, tmp->nrof > 1 ? "They weigh %3.3f kg." : "It weighs %3.3f kg.", weight); } } if (QUERY_FLAG(tmp, FLAG_STARTEQUIP)) { /* Unpaid clone shop item */ if (QUERY_FLAG(tmp, FLAG_UNPAID)) { new_draw_info_format(NDI_UNIQUE, op, "%s would cost you %s.", tmp->nrof > 1 ? "They" : "It", query_cost_string(tmp, op, F_BUY)); } /* God-given item */ else { new_draw_info_format(NDI_UNIQUE, op, "%s god-given item%s.", tmp->nrof > 1 ? "They are" : "It is a", tmp->nrof > 1 ? "s" : ""); if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)) { if (tmp->value) { new_draw_info_format(NDI_UNIQUE, op, "But %s worth %s.", tmp->nrof > 1 ? "they are" : "it is", query_cost_string(tmp, op, F_TRUE)); } else { new_draw_info_format(NDI_UNIQUE, op, "%s worthless.", tmp->nrof > 1 ? "They are" : "It is"); } } } } else if (tmp->value && !IS_LIVE(tmp)) { if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)) { if (QUERY_FLAG(tmp, FLAG_UNPAID)) { new_draw_info_format(NDI_UNIQUE, op, "%s would cost you %s.", tmp->nrof > 1 ? "They" : "It", query_cost_string(tmp, op, F_BUY)); } else { new_draw_info_format(NDI_UNIQUE, op, "%s worth %s.", tmp->nrof > 1 ? "They are" : "It is", query_cost_string(tmp, op, F_TRUE)); goto dirty_little_jump1; } } else { object *floor; dirty_little_jump1: floor = GET_MAP_OB_LAYER(op->map, op->x, op->y, 0); if (floor && floor->type == SHOP_FLOOR && tmp->type != MONEY) { /* Used for SK_BARGAINING modification */ int charisma = op->stats.Cha; /* This skill gives us a charisma boost */ if (find_skill(op, SK_BARGAINING)) { charisma += 4; if (charisma > MAX_STAT) { charisma = MAX_STAT; } } new_draw_info_format(NDI_UNIQUE, op, "This shop will pay you %s (%0.1f%%).", query_cost_string(tmp, op, F_SELL), 20.0f + 100.0f * cha_bonus[charisma]); } } } else if (!IS_LIVE(tmp)) { if (QUERY_FLAG(tmp, FLAG_IDENTIFIED)) { if (QUERY_FLAG(tmp, FLAG_UNPAID)) { new_draw_info_format(NDI_UNIQUE, op, "%s would cost nothing.", tmp->nrof > 1 ? "They" : "It"); } else { new_draw_info_format(NDI_UNIQUE, op, "%s worthless.", tmp->nrof > 1 ? "They are" : "It is"); } } } /* Does the object have a message? Don't show message for all object * types - especially if the first entry is a match */ if (tmp->msg && tmp->type != EXIT && tmp->type != BOOK && tmp->type != CORPSE && !QUERY_FLAG(tmp, FLAG_WALK_ON) && strncasecmp(tmp->msg, "@match", 7)) { /* This is just a hack so when identifying the items, we print * out the extra message */ if (need_identify(tmp) && QUERY_FLAG(tmp, FLAG_IDENTIFIED)) { new_draw_info(NDI_UNIQUE, op, "The object has a story:"); new_draw_info(NDI_UNIQUE, op, tmp->msg); } } /* Blank line */ new_draw_info(NDI_UNIQUE, op, " "); if (QUERY_FLAG(op, FLAG_WIZ)) { StringBuffer *sb = stringbuffer_new(); char *diff; stringbuffer_append_printf(sb, "count %d\n", tmp->count); dump_object(tmp, sb); diff = stringbuffer_finish(sb); new_draw_info(NDI_UNIQUE, op, diff); free(diff); } }