/** Add new help command. This function is * the basis for the help_command directive in mush.cnf. It creates * a new help entry for the hash table, builds a help index, * and adds the new command to the command table. * \param command_name name of help command to add. * \param filename name of the help file to use for this command. * \param admin if 1, this command reads admin topics, rather than standard. */ void add_help_file(const char *command_name, const char *filename, int admin) { help_file *h; if (help_init == 0) init_help_files(); if (!command_name || !filename || !*command_name || !*filename) return; /* If there's already an entry for it, complain */ h = hashfind(strupper(command_name), &help_files); if (h) { do_rawlog(LT_ERR, "Duplicate help_command %s ignored.", command_name); return; } h = mush_malloc(sizeof *h, "help_file.entry"); h->command = mush_strdup(strupper(command_name), "help_file.command"); h->file = mush_strdup(filename, "help_file.filename"); h->entries = 0; h->indx = NULL; h->admin = admin; help_build_index(h, h->admin); if (!h->indx) { mush_free(h->command, "help_file.command"); mush_free(h->file, "help_file.filename"); mush_free(h, "help_file.entry"); return; } (void) command_add(h->command, CMD_T_ANY | CMD_T_NOPARSE, NULL, 0, NULL, cmd_helpcmd); hashadd(h->command, h, &help_files); }
static struct access *sitelock_alloc(const char *host, dbref who, uint32_t can, uint32_t cant, const char *comment, const char **errptr) { struct access *tmp; tmp = mush_malloc(sizeof(struct access), "sitelock.rule"); if (!tmp) { static const char *memerr = "unable to allocate memory"; if (errptr) *errptr = memerr; return NULL; } tmp->who = who; tmp->can = can; tmp->cant = cant; tmp->host = mush_strdup(host, "sitelock.rule.pattern"); if (comment && *comment) tmp->comment = mush_strdup(comment, "sitelock.rule.comment"); else tmp->comment = NULL; tmp->next = NULL; if (can & ACS_REGEXP) { int erroffset = 0; tmp->re = pcre_compile(host, 0, errptr, &erroffset, tables); if (!tmp->re) { sitelock_free(tmp); return NULL; } } else tmp->re = NULL; return tmp; }
void addNewNebula(dbref executor, int index, const char* name, double radius, double x, double y, double z, char *buff, char **bp) { aspace_borders* newNebula; newNebula = im_find(nebula_map, index); if (newNebula != NULL) { safe_str("#-1 NEBULA # ALREADY IN USE", buff, bp); return; } newNebula = mush_malloc(sizeof(aspace_borders), "nebula_info"); newNebula->name = mush_strdup(name, "spacenebula_name"); newNebula->empire_id = 0; newNebula->radius = radius; newNebula->x = x; newNebula->y = y; newNebula->z = z; if( im_insert(nebula_map, index, newNebula )) { safe_str("New nebula Created.", buff, bp); write_spacelog(executor, executor, tprintf("Nebula Created: %s", newNebula->name)); } else safe_str("#-1 NEBULA NOT CREATED.", buff, bp); }
/** Add an entry to a hash table. * \param htab pointer to hash table. * \param key key string to store data under. * \param hashdata void pointer to data to be stored. * \retval false failure. * \retval true success. */ bool hash_add(HASHTAB *htab, const char *key, void *hashdata) { char *keycopy; int keylen; if (hash_find(htab, key) != NULL) return false; keycopy = mush_strdup(key, "hash.key"); keylen = strlen(keycopy); if (htab->entries == htab->hashsize) real_hash_resize(htab, next_prime_after(floor(htab->hashsize * 1.15)), htab->hashfunc_offset); htab->entries += 1; if (!hash_insert(htab, keycopy, keylen, hashdata)) { first_offset = -1; resize_calls = 0; real_hash_resize(htab, htab->hashsize, (htab->hashfunc_offset + 1) % NHASH_MOD); } return true; }
static void genrecord(s_rec *sp, dbref player, ListTypeInfo * lti) { lti->make_record(sp, player, lti->attrname); if (lti->flags & IS_CASE_INSENS && sp->memo.str.s) { if (sp->memo.str.freestr == 0) { sp->memo.str.s = mush_strdup(sp->memo.str.s, "genrecord"); sp->memo.str.freestr = 1; } upcasestr(sp->memo.str.s); } }
/** Add a new lock to the table. * \param name The name of the lock * \param flags The default flags. */ void define_lock(lock_type name, privbits flags) { lock_list *newlock; newlock = mush_malloc(sizeof *newlock, "lock"); newlock->type = mush_strdup(strupper(name), "lock.name"); newlock->flags = flags; newlock->creator = GOD; newlock->key = TRUE_BOOLEXP; newlock->next = NULL; hashadd((char *) newlock->type, newlock, &htab_locks); }
/** Add new help command. This function is * the basis for the help_command directive in mush.cnf. It creates * a new help entry for the hash table, builds a help index, * and adds the new command to the command table. * \param command_name name of help command to add. * \param filename name of the help file to use for this command. * \param admin if 1, this command reads admin topics, rather than standard. */ void add_help_file(const char *command_name, const char *filename, int admin) { help_file *h; char newfilename[256] = "\0"; /* Must use a buffer for MacOS file path conversion */ strncpy(newfilename, filename, 256); if (help_init == 0) init_help_files(); if (!command_name || !filename || !*command_name || !*newfilename) return; /* If there's already an entry for it, complain */ h = hashfind(strupper(command_name), &help_files); if (h) { do_rawlog(LT_ERR, T("Duplicate help_command %s ignored."), command_name); return; } h = mush_malloc(sizeof *h, "help_file.entry"); h->command = mush_strdup(strupper(command_name), "help_file.command"); h->file = mush_strdup(newfilename, "help_file.filename"); h->entries = 0; h->indx = NULL; h->admin = admin; help_build_index(h, h->admin); if (!h->indx) { mush_free(h->command, "help_file.command"); mush_free(h->file, "help_file.filename"); mush_free(h, "help_file.entry"); return; } (void) command_add(h->command, CMD_T_ANY | CMD_T_NOPARSE, NULL, cmd_helpcmd, NULL); hashadd(h->command, h, &help_files); }
/* Ads a module entry and returns */ struct module_entry_t *module_entry_add(char *name) { struct module_entry_t *entry; entry = (struct module_entry_t *) mush_malloc(sizeof(struct module_entry_t), "MODULE_ENTRY"); if(!entry) { return NULL; /* Should really panic here.. */ } entry->name = mush_strdup(name, "MODULE_ENTRY.NAME"); entry->info = NULL; entry->load = NULL; entry->unload = NULL; entry->next = module_list; module_list = entry; return entry; }
/** * Given a string description of a sort type, generate and return a * ListTypeInfo that can be passed to slist_* functions. * \param sort_type A string describing a sort type. * \retval ListTypeInfo containing all generating and comparison information * needed. */ ListTypeInfo * get_list_type_info(SortType sort_type) { int i, len; char *ptr = NULL; ListTypeInfo *lti; /* i is either the right one or the default, so we return it anyway. */ lti = mush_calloc(1, sizeof(ListTypeInfo), "list_type_info"); lti->sort_order = ASCENDING; if (*sort_type == '-') { lti->sort_order = DESCENDING; sort_type++; } if (!sort_type) { /* Advance i to the default */ for (i = 0; ltypelist[i].name; i++) ; } else if ((ptr = strchr(sort_type, ':'))) { len = ptr - sort_type; ptr += 1; if (!*ptr) ptr = NULL; for (i = 0; ltypelist[i].name && strncasecmp(ltypelist[i].name, sort_type, len); i++) ; } else { for (i = 0; ltypelist[i].name && strcasecmp(ltypelist[i].name, sort_type); i++) ; } lti->name = ltypelist[i].name; if (ptr) { lti->attrname = mush_strdup(ptr, "list_type_info_attrname"); } else { lti->attrname = NULL; } lti->make_record = ltypelist[i].make_record; lti->sorter = ltypelist[i].sorter; lti->flags = ltypelist[i].flags; return lti; }
/** Save the current timezone (The TZ environment variable) and set a new one. * \param newzone The new timezone. */ void save_and_set_tz(const char *newzone) { const char *tz; if (!newzone) newzone = ""; tz = getenv("TZ"); if (tz) saved_tz = mush_strdup(tz, "timezone"); else saved_tz = NULL; #ifdef WIN32 _putenv_s("TZ", newzone); #else setenv("TZ", newzone, 1); #endif tzset(); }
char * sound_hash(const char *str, int len, enum sound_hash_type type) { sqlite3 *sqldb = get_shared_db(); sqlite3_stmt *hasher; char *utf8, *result = NULL; int ulen; int status; switch (type) { case HASH_SOUNDEX: /* Classic Penn soundex turns a leading ph into f. This makes sense but isn't typical. */ hasher = prepare_statement(sqldb, "VALUES (soundex(CASE WHEN ?1 LIKE 'ph%' THEN " "printf('f%s', substr(?1, 3)) ELSE ?1 END))", "hash.soundex"); break; case HASH_PHONE: hasher = prepare_statement(sqldb, "VALUES (spellfix1_phonehash(?))", "hash.phone"); break; default: return NULL; } utf8 = latin1_to_utf8(str, len, &ulen, "string"); sqlite3_bind_text(hasher, 1, utf8, ulen, free_string); status = sqlite3_step(hasher); if (status == SQLITE_ROW) { result = mush_strdup((const char *) sqlite3_column_text(hasher, 0), "string"); } sqlite3_reset(hasher); return result; }
void edit_border(dbref executor, int border_id, const char* setting, const char* new_value, char *buff, char **bp) { aspace_borders *si = NULL; si = im_find(border_map, border_id); if (si != NULL) { switch (setting[0]) { case 'n': /* Name */ si->name = mush_strdup(new_value, "spaceborder_name"); safe_format(buff, bp, "Border Name changed for border %u to %s", border_id, si->name); break; case 'r': /* Radius */ si->radius = parse_number(new_value); safe_format(buff, bp, "Border Radius changed for border %u to %f", border_id, si->radius); break; case 'x': /* X Coordinate of Centre */ si->x = parse_number(new_value); safe_format(buff, bp, "Border CoordX changed for border %u to %f", border_id, si->x); break; case 'y': /* Y Coordinate of Centre */ si->y = parse_number(new_value); safe_format(buff, bp, "Border CoordY changed for border %u to %f", border_id, si->y); break; case 'z': /* Z Coordinate of Centre */ si->z = parse_number(new_value); safe_format(buff, bp, "Border CoordZ changed for border %u to %f", border_id, si->z); break; default: safe_str("#-1 BORDER SETTING NOT FOUND.", buff, bp); break; } } else { safe_str("#-1 BORDER NOT FOUND.", buff, bp); } }
void addNewBorder(dbref executor, int border_number, const char* name, double radius, double x, double y, double z, char *buff, char **bp) { aspace_borders* newBorder; newBorder = im_find(border_map, border_number); if (newBorder != NULL) { safe_str("#-1 BORDER ALREADY EXISTS", buff, bp); return; } newBorder = mush_malloc(sizeof(aspace_borders), "border_info"); newBorder->name = mush_strdup(name, "spaceborder_name"); newBorder->empire_id = 0; newBorder->radius = radius; newBorder->x = x; newBorder->y = y; newBorder->z = z; if( im_insert(border_map, border_number, newBorder )) { safe_str("New Border Created.", buff, bp); write_spacelog(executor, executor, tprintf("Border Created: %s", newBorder->name)); } else safe_str("#-1 BORDER NOT CREATED.", buff, bp); }
/** Rename something. * \verbatim * This implements @name. * \endverbatim * \param player the enactor. * \param name current name of object to rename. * \param newname_ new name for object. */ void do_name(dbref player, const char *name, char *newname_) { dbref thing; char oldname[BUFFER_LEN]; char *newname = NULL; char *alias = NULL; PE_REGS *pe_regs; if ((thing = match_controlled(player, name)) == NOTHING) return; /* check for bad name */ if ((*newname_ == '\0') || strchr(newname_, '[')) { notify(player, T("Give it what new name?")); return; } switch (Typeof(thing)) { case TYPE_PLAYER: switch (ok_object_name (newname_, player, thing, TYPE_PLAYER, &newname, &alias)) { case OPAE_INVALID: case OPAE_NULL: notify(player, T("You can't give a player that name or alias.")); if (newname) mush_free(newname, "name.newname"); if (alias) mush_free(alias, "name.newname"); return; case OPAE_TOOMANY: notify(player, T("Too many aliases.")); mush_free(newname, "name.newname"); return; case OPAE_SUCCESS: break; } break; case TYPE_EXIT: if (ok_object_name(newname_, player, thing, TYPE_EXIT, &newname, &alias) != OPAE_SUCCESS) { notify(player, T("That is not a reasonable name.")); if (newname) mush_free(newname, "name.newname"); if (alias) mush_free(alias, "name.newname"); return; } break; case TYPE_THING: case TYPE_ROOM: if (!ok_name(newname_, 0)) { notify(player, T("That is not a reasonable name.")); return; } newname = mush_strdup(trim_space_sep(newname_, ' '), "name.newname"); break; default: /* Should never occur */ notify(player, T("I don't see that here.")); return; } /* Actually change it */ mush_strncpy(oldname, Name(thing), BUFFER_LEN); if (IsPlayer(thing)) { do_log(LT_CONN, 0, 0, "Name change by %s(#%d) to %s", Name(thing), thing, newname); if (Suspect(thing) && strcmp(Name(thing), newname) != 0) flag_broadcast("WIZARD", 0, T("Broadcast: Suspect %s changed name to %s."), Name(thing), newname); reset_player_list(thing, Name(thing), NULL, newname, NULL); } set_name(thing, newname); if (alias) { if (*alias == ALIAS_DELIMITER) { do_set_atr(thing, "ALIAS", NULL, player, 0); } else { /* New alias to set */ do_set_atr(thing, "ALIAS", alias, player, 0); } mush_free(alias, "name.newname"); } queue_event(player, "OBJECT`RENAME", "%s,%s,%s", unparse_objid(thing), newname, oldname); if (!AreQuiet(player, thing)) notify(player, T("Name set.")); pe_regs = pe_regs_create(PE_REGS_ARG, "do_name"); pe_regs_setenv_nocopy(pe_regs, 0, oldname); pe_regs_setenv_nocopy(pe_regs, 1, newname); real_did_it(player, thing, NULL, NULL, "ONAME", NULL, "ANAME", NOTHING, pe_regs, NA_INTER_PRESENCE, AN_SYS); pe_regs_free(pe_regs); mush_free(newname, "name.newname"); }
/** Is name a valid new name for thing, when set by player? * \verbatim * Parses names and aliases for players/exits, validating each. If everything is valid, * the new name and alias are set into newname and newalias, with memory malloc'd as necessary. * For things/rooms, no parsing is done, and ok_name is called on the entire string to validate. * For players and exits, if name takes the format <name>; then newname is set to <name> and * newalias to ";", to signify that the existing alias should be cleared. If name contains a name and * valid aliases, newname and newalias are set accordingly. * \endverbatim * \param name the new name to set * \param player the player setting the name, for permission checks * \param thing object getting the name, or NOTHING for new objects * \param type type of object getting the name (necessary for new exits) * \param newname pointer to place the new name, once validated * \param newalias pointer to place the alias in, if any * \retval OPAE_SUCCESS name and any given aliases are valid * \retval OPAE_INVALID invalid name or aliases * \retval OPAE_TOOMANY too many aliases for player */ enum opa_error ok_object_name(char *name, dbref player, dbref thing, int type, char **newname, char **newalias) { char *bon, *eon; char nbuff[BUFFER_LEN], abuff[BUFFER_LEN]; char *ap = abuff; int aliases = 0; int empty = 0; strncpy(nbuff, name, BUFFER_LEN - 1); nbuff[BUFFER_LEN - 1] = '\0'; memset(abuff, 0, BUFFER_LEN); /* First, check for a quoted player name */ if (type == TYPE_PLAYER && *name == '"') { /* Quoted player name, no aliases allowed */ bon = nbuff; bon++; eon = bon; while (*eon && *eon != '"') eon++; if (*eon) *eon = '\0'; if (!ok_player_name(bon, player, thing)) return OPAE_INVALID; *newname = mush_strdup(bon, "name.newname"); return OPAE_SUCCESS; } if (type & (TYPE_THING | TYPE_ROOM)) { /* No aliases in the name */ if (!ok_name(nbuff, 0)) return OPAE_INVALID; *newname = mush_strdup(nbuff, "name.newname"); return OPAE_SUCCESS; } /* A player or exit name, with aliases allowed. * Possible things to parse: * <name> - just a new name * <name>; - new name with trailing ; to clear alias * <name>;<alias1>[;<aliasN>] - name with one or more aliases, separated by ; */ /* Validate name first */ bon = nbuff; if ((eon = strchr(bon, ALIAS_DELIMITER))) { *eon++ = '\0'; aliases++; } if (! (type == TYPE_PLAYER ? ok_player_name(bon, player, thing) : ok_name(bon, 1))) return OPAE_INVALID; *newname = mush_strdup(bon, "name.newname"); if (aliases) { /* We had aliases, so parse them */ while (eon) { if (empty) return OPAE_NULL; /* Null alias only valid as a single, final alias */ bon = eon; if ((eon = strchr(bon, ALIAS_DELIMITER))) { *eon++ = '\0'; } while (*bon && *bon == ' ') bon++; if (!*bon) { empty = 1; /* empty alias, should only happen if we have no proper aliases */ continue; } if (! (type == TYPE_PLAYER ? ok_player_name(bon, player, thing) : ok_name(bon, 1))) { *newalias = mush_strdup(bon, "name.newname"); /* So we can report the invalid alias */ return OPAE_INVALID; } if (aliases > 1) { safe_chr(ALIAS_DELIMITER, abuff, &ap); } safe_str(bon, abuff, &ap); aliases++; } } *ap = '\0'; if (aliases) { if (!Wizard(player) && type == TYPE_PLAYER && aliases > MAX_ALIASES) return OPAE_TOOMANY; if (*abuff) { /* We have actual aliases */ *newalias = mush_strdup(abuff, "name.newname"); } else { ap = abuff; safe_chr(ALIAS_DELIMITER, abuff, &ap); *ap = '\0'; /* We just want to clear the existing alias */ *newalias = mush_strdup(abuff, "name.newname"); } } return OPAE_SUCCESS; }