Пример #1
0
/* Show the 'Obvious Exits' list for a room. Used in 'look' and 'examine'.
 * \param player The player looking
 * \param loc room whose exits we're showing
 * \param exit_name "Obvious Exits" string
 * \param pe_info the pe_info to use for evaluating EXITFORMAT and interact locks
 */
static void
look_exits(dbref player, dbref loc, const char *exit_name, NEW_PE_INFO *pe_info)
{
  dbref thing;
  char *tbuf1, *tbuf2, *nbuf;
  char *s1, *s2;
  char *p;
  int exit_count, this_exit, total_count;
  int texits;
  ufun_attrib ufun;
  PUEBLOBUFF;

  /* make sure location is a room */
  if (!IsRoom(loc))
    return;

  tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string");
  tbuf2 = (char *) mush_malloc(BUFFER_LEN, "string");
  nbuf = (char *) mush_malloc(BUFFER_LEN, "string");
  if (!tbuf1 || !tbuf2 || !nbuf)
    mush_panic("Unable to allocate memory in look_exits");
  s1 = tbuf1;
  s2 = tbuf2;
  texits = exit_count = total_count = 0;
  this_exit = 1;

  if (fetch_ufun_attrib
      ("EXITFORMAT", loc, &ufun, UFUN_IGNORE_PERMS | UFUN_REQUIRE_ATTR)) {
    char *arg, *buff, *bp;
    PE_REGS *pe_regs = pe_regs_create(PE_REGS_ARG, "look_exits");

    arg = (char *) mush_malloc(BUFFER_LEN, "string");
    buff = (char *) mush_malloc(BUFFER_LEN, "string");
    if (!arg || !buff)
      mush_panic("Unable to allocate memory in look_exits");

    bp = arg;
    DOLIST(thing, Exits(loc)) {
      if (((Light(loc) || Light(thing)) || !(Dark(loc) || Dark(thing)))
          && can_interact(thing, player, INTERACT_SEE, pe_info)) {
        if (bp != arg)
          safe_chr(' ', arg, &bp);
        safe_dbref(thing, arg, &bp);
      }
    }
    *bp = '\0';
    pe_regs_setenv_nocopy(pe_regs, 0, arg);

    call_ufun(&ufun, buff, player, player, pe_info, pe_regs);

    pe_regs_free(pe_regs);
    notify_by(loc, player, buff);
    mush_free(tbuf1, "string");
    mush_free(tbuf2, "string");
    mush_free(nbuf, "string");
    mush_free(arg, "string");
    mush_free(buff, "string");
    return;
  }
Пример #2
0
/** Allocate memory for a buffer queue to hold a given number of lines.
 * \param bq pointer to buffer queue.
 * \param lines lines to allocate for buffer queue.
 * \retval address of allocated buffer queue.
 */
BUFFERQ *
allocate_bufferq(int lines)
{
  BUFFERQ *bq;
  int bytes = lines * (BUFFER_LEN + BUFFERQLINEOVERHEAD);
  bq = mush_malloc(sizeof(BUFFERQ), "bufferq");
  bq->buffer = mush_malloc(bytes, "bufferq.buffer");
  *bq->buffer = '\0';
  bq->buffer_end = bq->buffer;
  bq->num_buffered = 0;
  bq->buffer_size = bytes;
  strcpy(bq->last_string, "");
  bq->last_type = 0;
  return bq;
}
Пример #3
0
    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;
}
Пример #4
0
/** 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);
}
Пример #5
0
/* Add a new, or restrict an existing, standard attribute from cnf file */
int
cnf_attribute_access(char *attrname, char *opts)
{
  ATTR *a;
  privbits flags = 0;

  upcasestr(attrname);
  if (!good_atr_name(attrname))
    return 0;

  if (strcasecmp(opts, "none")) {
    flags = list_to_privs(attr_privs_set, opts, 0);
    if (!flags)
      return 0;
  }

  a = (ATTR *) ptab_find_exact(&ptab_attrib, attrname);
  if (a) {
    if (AF_Internal(a))
      return 0;
  } else {
    a = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR");
    if (!a)
      return 0;
    AL_NAME(a) = strdup(attrname);
    a->data = NULL_CHUNK_REFERENCE;
    ptab_insert_one(&ptab_attrib, attrname, a);
  }
  AL_FLAGS(a) = flags;
  AL_CREATOR(a) = GOD;
  return 1;
}
Пример #6
0
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);
}
Пример #7
0
/** Allocate and initialize a new integer map. */
intmap *
im_new(void)
{
  intmap *im;
  im = mush_malloc(sizeof *im, "int_map");
  if (!intmap_slab)
    intmap_slab = slab_create("patricia tree nodes", sizeof(struct patricia));
  im->count = 0;
  im->root = NULL;
  return im;
}
Пример #8
0
/** 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);
}
Пример #9
0
/* 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;
}
Пример #10
0
/** Add a new attribute. Called from db.c to add new attributes
 * to older databases which have their own attr table.
 * \param name name of attr to add
 * \param flags attribute flags (AF_*)
 */
void
add_new_attr(char *name, uint32_t flags)
{
  ATTR *ap;
  ap = (ATTR *) ptab_find_exact(&ptab_attrib, name);
  if (ap || !good_atr_name(name))
    return;

  ap = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR");
  if (!ap) {
    do_log(LT_ERR, 0, 0, "add_new_attr: unable to malloc ATTR");
    return;
  }
  AL_NAME(ap) = strdup(name);
  ap->data = NULL_CHUNK_REFERENCE;
  AL_FLAGS(ap) = flags;
  AL_CREATOR(ap) = 0;
  ptab_insert_one(&ptab_attrib, name, ap);

}
Пример #11
0
/** 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);
}
Пример #12
0
static lock_list *
next_free_lock(void)
{
  lock_list *ll;

  if (!free_list) {
    size_t n;

    ll = mush_malloc(sizeof(lock_list) * LOCKS_PER_PAGE, "lock_page");

    if (!ll)
      mush_panic("Unable to allocate memory for locks!");

    for (n = 0; n < LOCKS_PER_PAGE - 1; n++) {
      ll[n].type = NULL;
      ll[n].key = TRUE_BOOLEXP;
      ll[n].creator = NOTHING;
      ll[n].flags = 0;
      ll[n].next = &ll[n + 1];
    }

    ll[n].next = NULL;
    ll[n].type = NULL;
    ll[n].key = TRUE_BOOLEXP;
    ll[n].creator = NOTHING;
    ll[n].flags = 0;

    free_list = &ll[0];
  }

  ll = free_list;
  free_list = ll->next;

  ll->type = NULL;
  ll->key = TRUE_BOOLEXP;

  return ll;
}
Пример #13
0
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);
}
Пример #14
0
/** Add new standard attributes, or change permissions on them.
 * \verbatim
 * Given the name and permission string for an attribute, add it to
 * the attribute table (or modify the permissions if it's already
 * there). Permissions may be changed retroactively, which modifies
 * permissions on any copies of that attribute set on objects in the
 * database. This is the top-level code for @attribute/access.
 * \endverbatim
 * \param player the enactor.
 * \param name the attribute name.
 * \param perms a string of attribute permissions, space-separated.
 * \param retroactive if true, apply the permissions retroactively.
 */
void
do_attribute_access(dbref player, char *name, char *perms, int retroactive)
{
  ATTR *ap, *ap2;
  privbits flags = 0;
  int i;
  int insert = 0;

  /* Parse name and perms */
  if (!name || !*name) {
    notify(player, T("Which attribute do you mean?"));
    return;
  }
  if (strcasecmp(perms, "none")) {
    flags = list_to_privs(attr_privs_set, perms, 0);
    if (!flags) {
      notify(player, T("I don't understand those permissions."));
      return;
    }
  }
  upcasestr(name);
  /* Is this attribute already in the table? */
  ap = (ATTR *) ptab_find_exact(&ptab_attrib, name);
  if (ap) {
    if (AF_Internal(ap)) {
      /* Don't muck with internal attributes */
      notify(player, T("That attribute's permissions can not be changed."));
      return;
    }
  } else {
    /* Create fresh if the name is ok */
    if (!good_atr_name(name)) {
      notify(player, T("Invalid attribute name."));
      return;
    }
    insert = 1;
    ap = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR");
    if (!ap) {
      notify(player, T("Critical memory failure - Alert God!"));
      do_log(LT_ERR, 0, 0, "do_attribute_access: unable to malloc ATTR");
      return;
    }
    AL_NAME(ap) = strdup(name);
    ap->data = NULL_CHUNK_REFERENCE;
  }
  AL_FLAGS(ap) = flags;
  AL_CREATOR(ap) = player;

  /* Only insert when it's not already in the table */
  if (insert) {
    ptab_insert_one(&ptab_attrib, name, ap);
  }

  /* Ok, now we need to see if there are any attributes of this name
   * set on objects in the db. If so, and if we're retroactive, set
   * perms/creator
   */
  if (retroactive) {
    for (i = 0; i < db_top; i++) {
      if ((ap2 = atr_get_noparent(i, name))) {
        if (AL_FLAGS(ap2) & AF_ROOT)
          AL_FLAGS(ap2) = flags | AF_ROOT;
        else
          AL_FLAGS(ap2) = flags;
        AL_CREATOR(ap2) = player;
      }
    }
  }

  notify_format(player, T("%s -- Attribute permissions now: %s"), name,
                privs_to_string(attr_privs_view, flags));
}
Пример #15
0
/** String tree insert.  If the string is already in the tree, bump its usage
 * count and return the tree's version.  Otherwise, allocate a new tree
 * node, copy the string into the node, insert it into the tree, and
 * return the new node's string.
 * \param s string to insert in tree.
 * \param root pointer to root of string tree.
 * \return string inserted or NULL.
 */
char const *
st_insert(char const *s, StrTree *root)
{
  int tree_depth;
  StrNode *n;
  int cmp = 0;
  size_t keylen;

  assert(s);

  /* Hunt for the string in the tree. */
  tree_depth = 0;
  n = root->root;
  while (n && (cmp = strcmp(s, n->string))) {
    path[tree_depth] = n;
    tree_depth++;
    assert(tree_depth < ST_MAX_DEPTH);
    if (cmp < 0)
      n = n->left;
    else
      n = n->right;
  }

  if (n) {
    /* Found the string, so bump the usage and return. */
    if (n->info < ST_USE_LIMIT)
      n->info += ST_USE_STEP;
    return n->string;
  }

  /* Need a new node.  Allocate and initialize it. */
  keylen = strlen(s) + 1;
  n = mush_malloc(sizeof(StrNode) - BUFFER_LEN + keylen, "StrNode");
  if (!n)
    return NULL;
  memcpy(n->string, s, keylen);
  n->left = NULL;
  n->right = NULL;
  if (tree_depth == 0) {
    /* This is the first insertion!  Just stick it at the root
     * and get out of here. */
    root->root = n;
    n->info = ST_BLACK + ST_USE_STEP;
    return n->string;
  }
  n->info = ST_RED + ST_USE_STEP;

  /* Foo.  Have to do a complex insert.  Well, start by putting
   * the new node at the tip of an appropriate branch. */
  path[tree_depth] = n;
  tree_depth--;
  if (cmp < 0)
    path[tree_depth]->left = n;
  else
    path[tree_depth]->right = n;

  /* I rely on ST_RED != 0 and ST_BLACK == 0 in my bitwise ops. */
  assert(ST_RED);

  /* Sigh.  Fix the tree to maintain the red-black properties. */
  while (tree_depth > 0 && (path[tree_depth]->info & ST_COLOR) == ST_RED) {
    /* We have a double-red.  Blitch.  Now we have some mirrored
     * cases to look for, so stuff is duplicated left/right. */
    if (path[tree_depth] == path[tree_depth - 1]->left) {
      StrNode *y;
      y = path[tree_depth - 1]->right;
      if (y && (y->info & ST_COLOR) == ST_RED) {
        /* Hmph.  Uncle is red.  Push the mess up the tree. */
        path[tree_depth]->info &= ~ST_RED;
        y->info &= ~ST_RED;
        tree_depth--;
        path[tree_depth]->info |= ST_RED;
        tree_depth--;
      } else {
        /* Okay, uncle is black.  We can fix everything, now. */
        if (path[tree_depth + 1] == path[tree_depth]->right) {
          st_left_rotate(tree_depth, &root->root);
          path[tree_depth + 1]->info &= ~ST_RED;
        } else {
          path[tree_depth]->info &= ~ST_RED;
        }
        path[tree_depth - 1]->info |= ST_RED;
        st_right_rotate(tree_depth - 1, &root->root);
        break;
      }
    } else {
      StrNode *y;
      y = path[tree_depth - 1]->left;
      if (y && (y->info & ST_COLOR) == ST_RED) {
        /* Hmph.  Uncle is red.  Push the mess up the tree. */
        path[tree_depth]->info &= ~ST_RED;
        y->info &= ~ST_RED;
        tree_depth--;
        path[tree_depth]->info |= ST_RED;
        tree_depth--;
      } else {
        /* Okay, uncle is black.  We can fix everything, now. */
        if (path[tree_depth + 1] == path[tree_depth]->left) {
          st_right_rotate(tree_depth, &root->root);
          path[tree_depth + 1]->info &= ~ST_RED;
        } else {
          path[tree_depth]->info &= ~ST_RED;
        }
        path[tree_depth - 1]->info |= ST_RED;
        st_left_rotate(tree_depth - 1, &root->root);
        break;
      }
    }
  }

  /* The tree is now red-black true again.  Make the root black
   * just for convenience. */
  root->root->info &= ~ST_RED;
  root->count++;
  root->mem += strlen(s) + 1;
  return n->string;
}
Пример #16
0
static struct tzinfo *
do_read_tzfile(int fd, const char *tzfile, int time_size)
{
  struct tzinfo *tz = NULL;
  int size, n;
  bool has_64bit_times = 0;
  int isstdcnt, isgmtcnt;

  {
    char magic[5] = { '\0' };

    if (read(fd, magic, 4) != 4) {
      do_rawlog(LT_ERR, "tz: Unable to read header from %s: %s.\n", tzfile,
                strerror(errno));
      goto error;
    }

    if (memcmp(magic, TZMAGIC, 4) != 0) {
      do_rawlog(LT_ERR, "tz: %s is not a valid tzfile. Wrong magic number.\n",
                tzfile);
      goto error;
    }
  }

  {
    char version[16];
    if (read(fd, version, 16) != 16) {
      do_rawlog(LT_ERR, "tz: Unable to read chunk from %s: %s\n", tzfile,
                strerror(errno));
      goto error;
    }

    /* There's a second copy of the data using 64 bit times, following
       the chunk with 32 bit times. */
    if (version[0] == '2')
      has_64bit_times = 1;
  }

  tz = mush_malloc(sizeof *tz, "timezone");
  memset(tz, 0, sizeof *tz);

  {
    int32_t counts[6];

    READ_CHUNK(counts, sizeof counts);

    isgmtcnt = decode32(counts[0]);
    isstdcnt = decode32(counts[1]);
    tz->leapcnt = decode32(counts[2]);
    tz->timecnt = decode32(counts[3]);
    tz->typecnt = decode32(counts[4]);
    tz->charcnt = decode32(counts[5]);
  }

  /* Use 64-bit time_t version on such systems. */
  if (has_64bit_times && sizeof(time_t) == 8 && time_size == 4) {
    off_t skip = 44;            /* Header and sizes */

    skip += tz->timecnt * 5;
    skip += tz->typecnt * 6;
    skip += tz->charcnt;
    skip += tz->leapcnt * (4 + time_size);
    skip += isgmtcnt + isstdcnt;

    if (lseek(fd, skip, SEEK_SET) < 0) {
      do_rawlog(LT_ERR, "tz: Unable to seek to second section of %s: %s\n",
                tzfile, strerror(errno));
      goto error;
    }

    mush_free(tz, "timezone");
    return do_read_tzfile(fd, tzfile, 8);
  }
#define READ_TRANSITIONS(type, decode)			\
  do {							\
    type *buf;						\
    							\
    size = tz->timecnt * time_size;			\
    buf = malloc(size);						\
    READ_CHUNKF(buf, size);					\
    								\
    tz->transitions = calloc(tz->timecnt, sizeof(time_t));	\
    for (n = 0; n < tz->timecnt; n += 1)			\
      tz->transitions[n] = (time_t) decode(buf[n]);		\
    								\
    free(buf);							\
  } while (0)

  if (time_size == 4) {
    READ_TRANSITIONS(int32_t, decode32);
  } else {
    READ_TRANSITIONS(int64_t, decode64);
  }

  tz->offset_indexes = malloc(tz->timecnt);
  READ_CHUNK(tz->offset_indexes, tz->timecnt);

  {
    uint8_t *buf;
    int m, size = tz->typecnt * 6;

    buf = malloc(size);
    READ_CHUNKF(buf, size);

    tz->offsets = calloc(tz->typecnt, sizeof(struct ttinfo));

    for (n = 0, m = 0; n < tz->typecnt; n += 1, m += 6) {
      int32_t gmtoff;

      memcpy(&gmtoff, &buf[m], 4);
      tz->offsets[n].tt_gmtoff = decode32(gmtoff);
      tz->offsets[n].tt_isdst = buf[m + 4];
      tz->offsets[n].tt_abbrind = buf[m + 5];
      tz->offsets[n].tt_std = tz->offsets[n].tt_utc = 0;
    }

    free(buf);
  }

  tz->abbrevs = malloc(tz->charcnt);
  READ_CHUNK(tz->abbrevs, tz->charcnt);

#define READ_LEAPSECS(type, decode) \
  do {				    \
    type *buf;					 \
    int m, size = tz->leapcnt * (4 + time_size); \
    						 \
    buf = malloc(size);				 \
    READ_CHUNKF(buf, size);			 \
    									\
    tz->leapsecs = calloc(tz->leapcnt, sizeof(struct ttleapsecs));	\
    									\
    for (n = 0, m = 0; n < tz->leapcnt; n += 1, m += (4 + time_size)) { \
       type when;							\
      int32_t secs;							\
      									\
      memcpy(&when, buf, time_size);					\
      memcpy(&secs, buf + time_size, 4);				\
      tz->leapsecs[n].tt_when = (time_t) decode(when);			\
      tz->leapsecs[n].tt_secs = decode32(secs);				\
    }									\
    free(buf);								\
  } while (0)

  if (tz->leapcnt) {
    if (time_size == 4)
      READ_LEAPSECS(int32_t, decode32);
    else
      READ_LEAPSECS(int64_t, decode64);
  }

  {
    uint8_t *buf;
    int n;

    buf = malloc(isstdcnt);
    READ_CHUNKF(buf, isstdcnt);

    for (n = 0; n < isstdcnt; n += 1)
      tz->offsets[n].tt_std = buf[n];

    free(buf);

    buf = malloc(isgmtcnt);
    READ_CHUNKF(buf, isgmtcnt);

    for (n = 0; n < isgmtcnt; n += 1)
      tz->offsets[n].tt_utc = buf[n];

    free(buf);
  }

  return tz;

error:
  if (tz)
    free_tzinfo(tz);
  return NULL;
}
Пример #17
0
static ATTR *
attr_read(PENNFILE *f)
{
  ATTR *a;
  char *tmp;
  dbref d = GOD;
  privbits flags = 0;

  a = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR");
  if (!a) {
    mush_panic("Not enough memory to add attribute in attr_read()!");
    return NULL;
  }
  AL_NAME(a) = NULL;
  a->data = NULL_CHUNK_REFERENCE;
  AL_FLAGS(a) = 0;
  AL_CREATOR(a) = GOD;
  a->next = NULL;

  db_read_this_labeled_string(f, "name", &tmp);

  if (!good_atr_name(tmp)) {
    do_rawlog(LT_ERR, "Invalid attribute name '%s' in db.", tmp);
    (void) getstring_noalloc(f);        /* flags */
    (void) getstring_noalloc(f);        /* creator */
    (void) getstring_noalloc(f);        /* data */
    free_standard_attr(a, 0);
    return NULL;
  }

  AL_NAME(a) = strdup(tmp);
  db_read_this_labeled_string(f, "flags", &tmp);
  if (tmp && *tmp && strcasecmp(tmp, "none")) {
    flags = list_to_privs(attr_privs_db, tmp, 0);
    if (!flags) {
      do_rawlog(LT_ERR, "Invalid attribute flags for '%s' in db.", AL_NAME(a));
      free((char *) AL_NAME(a));
      (void) getstring_noalloc(f);      /* creator */
      (void) getstring_noalloc(f);      /* data */
      free_standard_attr(a, 0);
      return NULL;
    }
  }
  AL_FLAGS(a) = flags;

  db_read_this_labeled_dbref(f, "creator", &d);
  AL_CREATOR(a) = d;

  db_read_this_labeled_string(f, "data", &tmp);
  if (!tmp || !*tmp || !(AL_FLAGS(a) & (AF_ENUM | AF_RLIMIT))) {
    a->data = NULL_CHUNK_REFERENCE;
  } else if (AL_FLAGS(a) & AF_ENUM) {
    /* Store string as it is */
    char *t = compress(tmp);
    a->data = chunk_create(t, strlen(t), 0);
    free(t);
  } else if (AL_FLAGS(a) & AF_RLIMIT) {
    /* Need to validate regexp */
    char *t;
    pcre *re;
    const char *errptr;
    int erroffset;

    re = pcre_compile(tmp, PCRE_CASELESS, &errptr, &erroffset, tables);
    if (!re) {
      do_rawlog(LT_ERR, "Invalid regexp in limit for attribute '%s' in db.",
                AL_NAME(a));
      free_standard_attr(a, 0);
      return NULL;
    }
    pcre_free(re);              /* don't need it, just needed to check it */

    t = compress(tmp);
    a->data = chunk_create(t, strlen(t), 0);
    free(t);
  }

  return a;
}
Пример #18
0
/** Migrate some number of chunks.
 * The requested amount is only a guideline; the actual amount
 * migrated will be more or less due to always migrating all the
 * attributes, locks, and mail on any given object together.
 * \param amount the suggested number of attributes to migrate.
 */
static void
migrate_stuff(int amount)
{
  static int start_obj = 0;
  static chunk_reference_t **refs = NULL;
  static int refs_size = 0;
  int end_obj;
  int actual;
  ATTR *aptr;
  lock_list *lptr;
  MAIL *mp;

  if (db_top == 0)
    return;

  end_obj = start_obj;
  actual = 0;
  do {
    for (aptr = List(end_obj); aptr; aptr = AL_NEXT(aptr))
      if (aptr->data != NULL_CHUNK_REFERENCE)
        actual++;
    for (lptr = Locks(end_obj); lptr; lptr = L_NEXT(lptr))
      if (L_KEY(lptr) != NULL_CHUNK_REFERENCE)
        actual++;
#ifdef USE_MAILER
    if (IsPlayer(end_obj)) {
      for (mp = find_exact_starting_point(end_obj); mp; mp = mp->next)
        if (mp->msgid != NULL_CHUNK_REFERENCE)
          actual++;
    }
#endif
    end_obj = (end_obj + 1) % db_top;
  } while (actual < amount && end_obj != start_obj);

  if (actual == 0)
    return;

  if (!refs || actual > refs_size) {
    if (refs)
      mush_free((Malloc_t) refs, "migration reference array");
    refs =
      (chunk_reference_t **) mush_malloc(actual * sizeof(chunk_reference_t *),
                                         "migration reference array");
    refs_size = actual;
    if (!refs)
      mush_panic("Could not allocate migration reference array");
  }
#ifdef DEBUG_MIGRATE
  do_rawlog(LT_TRACE, "Migrate asked %d, actual objects #%d to #%d for %d",
            amount, start_obj, (end_obj + db_top - 1) % db_top, actual);
#endif

  actual = 0;
  do {
    for (aptr = List(start_obj); aptr; aptr = AL_NEXT(aptr))
      if (aptr->data != NULL_CHUNK_REFERENCE) {
        refs[actual] = &(aptr->data);
        actual++;
      }
    for (lptr = Locks(start_obj); lptr; lptr = L_NEXT(lptr))
      if (L_KEY(lptr) != NULL_CHUNK_REFERENCE) {
        refs[actual] = &(lptr->key);
        actual++;
      }
#ifdef USE_MAILER
    if (IsPlayer(start_obj)) {
      for (mp = find_exact_starting_point(start_obj); mp; mp = mp->next)
        if (mp->msgid != NULL_CHUNK_REFERENCE) {
          refs[actual] = &(mp->msgid);
          actual++;
        }
    }
#endif
    start_obj = (start_obj + 1) % db_top;
  } while (start_obj != end_obj);

  chunk_migration(actual, refs);
}
Пример #19
0
/** The whisper command.
 * \param player the enactor.
 * \param arg1 name of the object to whisper to.
 * \param arg2 message to whisper.
 * \param noisy if 1, others overhear that a whisper has occurred.
 * \param pe_info the pe_info for evaluating interact locks
 */
void
do_whisper(dbref player, const char *arg1, const char *arg2, int noisy,
           NEW_PE_INFO *pe_info)
{
  dbref who;
  int key;
  const char *gap;
  char *tbuf, *tp;
  char *p;
  dbref good[100];
  int gcount = 0;
  const char *head;
  int overheard;
  char *current;
  const char **start;
  char sname[BUFFER_LEN];

  if (!arg1 || !*arg1) {
    notify(player, T("Whisper to whom?"));
    return;
  }
  if (!arg2 || !*arg2) {
    notify(player, T("Whisper what?"));
    return;
  }
  tp = tbuf = (char *) mush_malloc(BUFFER_LEN, "string");
  if (!tbuf)
    mush_panic("Unable to allocate memory in do_whisper");

  overheard = 0;
  head = arg1;
  start = &head;
  /* Figure out what kind of message */
  gap = " ";
  switch (*arg2) {
  case SEMI_POSE_TOKEN:
    gap = "";
  case POSE_TOKEN:
    key = 1;
    arg2++;
    break;
  default:
    key = 2;
    break;
  }

  *tp = '\0';
  /* Make up a list of good and bad names */
  while (head && *head) {
    current = next_in_list(start);
    who = match_result(player, current, TYPE_PLAYER, MAT_NEAR_THINGS |
                       MAT_CONTAINER);
    if (!GoodObject(who) || !can_interact(player, who, INTERACT_HEAR, pe_info)) {
      safe_chr(' ', tbuf, &tp);
      safe_str_space(current, tbuf, &tp);
      if (GoodObject(who))
        notify_format(player, T("%s can't hear you."),
                      AName(who, AN_SYS, NULL));
    } else {
      /* A good whisper */
      good[gcount++] = who;
      if (gcount >= 100) {
        notify(player, T("Too many people to whisper to."));
        break;
      }
    }
  }

  *tp = '\0';
  if (*tbuf)
    notify_format(player, T("Unable to whisper to:%s"), tbuf);

  if (!gcount) {
    mush_free(tbuf, "string");
    return;
  }

  /* Drunk wizards... */
  if (Dark(player))
    noisy = 0;

  /* Set up list of good names */
  tp = tbuf;
  safe_str(T(" to "), tbuf, &tp);
  for (who = 0; who < gcount; who++) {
    if (noisy && (get_random32(0, 100) < (uint32_t) WHISPER_LOUDNESS))
      overheard = 1;
    safe_itemizer(who + 1, (who == gcount - 1), ",", T("and"), " ", tbuf, &tp);
    safe_str(AName(good[who], AN_SAY, NULL), tbuf, &tp);
  }
  *tp = '\0';

  if (key == 1) {
    notify_format(player, (gcount > 1) ? T("%s sense: %s%s%s") :
                  T("%s senses: %s%s%s"), tbuf + 4, AName(player, AN_SAY, NULL),
                  gap, arg2);
    p = tprintf("You sense: %s%s%s", AName(player, AN_SAY, NULL), gap, arg2);
  } else {
    notify_format(player, T("You whisper, \"%s\"%s."), arg2, tbuf);
    p = tprintf(T("%s whispers%s: %s"), AName(player, AN_SAY, NULL),
                gcount > 1 ? tbuf : "", arg2);
  }

  strcpy(sname, AName(player, AN_SAY, NULL));
  for (who = 0; who < gcount; who++) {
    notify_must_puppet(good[who], p);
    if (Location(good[who]) != Location(player))
      overheard = 0;
  }
  if (overheard) {
    dbref first = Contents(Location(player));
    if (!GoodObject(first))
      return;
    p = tprintf(T("%s whispers%s."), sname, tbuf);
    DOLIST(first, first) {
      overheard = 1;
      for (who = 0; who < gcount; who++) {
        if ((first == player) || (first == good[who])) {
          overheard = 0;
          break;
        }
      }
      if (overheard)
        notify_noecho(first, p);
    }
  }