/** A generic comparer routine to compare two values of any sort type. * \param player Player doing the comparison * \param a Key 1 to compare * \param b Key 2 to compare * \param sort_type SortType describing what kind of comparison to make. */ int gencomp(dbref player, char *a, char *b, SortType sort_type) { char *ptr; int i, len; int result; s_rec s1, s2; ListTypeInfo *lti; ptr = NULL; 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 = get_list_type_info(sort_type); if (ltypelist[i].flags & IS_DB) { s1.db = parse_objid(a); s2.db = parse_objid(b); if (!RealGoodObject(s1.db)) s1.db = NOTHING; if (!RealGoodObject(s2.db)) s2.db = NOTHING; } else { s1.db = s2.db = 0; } s1.val = a; s2.val = b; genrecord(&s1, player, lti); genrecord(&s2, player, lti); result = lti->sorter((const void *) &s1, (const void *) &s2); if (lti->flags & IS_STRING) { if (s1.memo.str.freestr) mush_free(s1.memo.str.s, "genrecord"); if (s2.memo.str.freestr) mush_free(s2.memo.str.s, "genrecord"); } free_list_type_info(lti); return result; }
/* utility for open and link */ static dbref parse_linkable_room(dbref player, const char *room_name) { dbref room; /* parse room */ if (!strcasecmp(room_name, "here")) { room = IsExit(player) ? Source(player) : Location(player); } else if (!strcasecmp(room_name, "home")) { return HOME; /* HOME is always linkable */ } else { room = parse_objid(room_name); } /* check room */ if (!GoodObject(room)) { notify(player, T("That is not a valid object.")); return NOTHING; } else if (Going(room)) { notify(player, T("That room is being destroyed. Sorry.")); return NOTHING; } else if (!can_link_to(player, room)) { notify(player, T("You can't link to that.")); return NOTHING; } else { return room; } }
/** * Given a player dbref (For use with viewing permissions for attrs, etc), * list of keys, list of strings it maps to (sortkey()-style), * # of keys+strings and a list type info, build an array of * s_rec structures representing each item. * \param player the player executing the sort. * \param keys the array of items to sort. * \param strs If non-NULL, these are what to sort <keys> using. * \param n Number of items in <keys> and <strs> * \param lti List Type Info describing how it's sorted and built. * \retval A pointer to the first s_rec of an <n> s_rec array. */ s_rec * slist_build(dbref player, char *keys[], char *strs[], int n, ListTypeInfo * lti) { int i; s_rec *sp; sort_order = lti->sort_order; sp = mush_calloc(n, sizeof(s_rec), "do_gensort"); for (i = 0; i < n; i++) { /* Elements are 0 by default thanks to calloc. Only need to touch those that need other values. */ sp[i].val = keys[i]; if (strs) sp[i].ptr = strs[i]; if (lti->flags & IS_DB) { sp[i].db = parse_objid(keys[i]); if (!RealGoodObject(sp[i].db)) sp[i].db = NOTHING; } genrecord(&sp[i], player, lti); } return sp; }
/** Look up a player in the player list htab (or by dbref). * \param name name of player to find. * \return dbref of player, or NOTHING. */ dbref lookup_player(const char *name) { dbref d; if (!name || !*name) return NOTHING; if (*name == NUMBER_TOKEN) { d = parse_objid(name); if (GoodObject(d) && IsPlayer(d)) return d; else return NOTHING; } if (*name == LOOKUP_TOKEN) name++; return lookup_player_name(name); }
/** Parse a softcode timezone request. * * \verbatim * * If arg is a objid, look up that object's @TZ attribute and parse * that. Otherwise, parse arg. * * If an object doesn't have a @TZ set, offset is set to 0 and tznotset to 1, to be able to tell * that case apart from a UTC timezone. * * If a timezone database is present, try to read the given zone from * it. Integers are treated as 'Etc/GMT[+-]N' first. * * If no tzinfo database, or reading the given zone from one fails, * and the arg is an integer, treat it as the number of hours * difference from GMT. Otherwise fail. * * \endverbatim * * \param arg The string to parse for a dbref, number or symbolic tz name * \param when When to calculate the offset for. * \param res Structure to store the parsed results in. * \return 1 for success, 0 for failure in parsing the time zone. */ bool parse_timezone_arg(const char *arg, time_t when, struct tz_result *res) { if (!res) return 0; memset(res, 0, sizeof *res); res->tz_when = when; if (strcasecmp(arg, "UTC") == 0) { res->tz_utc = 1; return 1; } else if (is_objid(arg)) { ATTR *a; dbref thing = parse_objid(arg); if (!RealGoodObject(thing)) return 0; a = atr_get(thing, "TZ"); if (!a) { /* No timezone attribute isn't an error. Just use the server's zone. */ res->tz_attr_missing = 1; return 1; } arg = atr_value(a); } #ifdef HAVE_ZONEINFO { struct tzinfo *tz = NULL; static char tz_path[BUFFER_LEN]; if (is_valid_tzname(arg)) { tz = read_tzfile(arg); snprintf(tz_path, sizeof tz_path, ":%s", arg); } else if (is_strict_integer(arg)) { int offset; char tzname[100]; offset = parse_integer(arg); /* GMT-8 is 8 hours ahead, GMT+8 is 8 hours behind, which makes no sense to me. */ offset = -offset; snprintf(tzname, sizeof tzname, "Etc/GMT%+d", offset); tz = read_tzfile(tzname); snprintf(tz_path, sizeof tz_path, ":%s", tzname); } if (tz) { res->tz_offset = offset_for_tzinfo(tz, when); free_tzinfo(tz); res->tz_name = tz_path; res->tz_has_file = 1; return 1; } /* Fall through to gross numeric offset on failure */ } #endif if (is_strict_number(arg)) { double n = parse_number(arg); if (fabs(n) >= 24.0) return 0; res->tz_offset = floor(n * 3600.0); return 1; } return 0; }