Esempio n. 1
0
/** Log all allocations.
 */
void
log_mem_check(void)
{
  MEM *chk;

  if (!options.mem_check)
    return;
  do_rawlog(LT_TRACE, "MEMCHECK dump starts");
  for (chk = memcheck_head->links[0]; chk; chk = chk->links[0]) {
    do_rawlog(LT_TRACE, "%s : %d", chk->ref_name, chk->ref_count);
  }
  do_rawlog(LT_TRACE, "MEMCHECK dump ends");
}
Esempio n. 2
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);
}
Esempio n. 3
0
/** Validates a timezone name to see if it fits the right format.
 * \param name The name of the time zone.
 * \return true or false
 */
bool
is_valid_tzname(const char *name)
{
  static pcre *re = NULL;
  static pcre_extra *extra = NULL;
  int len;
  int ovec[15];

  if (!re) {
    int erroffset;
    const char *errptr;

    re =
      pcre_compile("^[A-Z][\\w+-]+(?:/[A-Z][\\w+-]+)?$", 0, &errptr, &erroffset,
                   tables);

    if (!re) {
      do_rawlog(LT_ERR, "tz: Unable to compile timezone name validation RE: %s",
                errptr);
      return 0;
    }
    extra = pcre_study(re, pcre_study_flags, &errptr);
  }

  len = strlen(name);

  return pcre_exec(re, extra, name, len, 0, 0, ovec, 15) > 0;
}
Esempio n. 4
0
/** Convert a time string to a struct tm using getdate().
 * Formats for the time string are taken from the file referenced in
 * the DATEMSK environment variable.
 * \param str a time string.
 * \param ttm pointer to a struct tm to fill.
 * \retval 1 success.
 * \retval 0 failure.
 */
int
do_convtime_gd(const char *str, struct tm *ttm)
{
  /* converts time string to a struct tm. Returns 1 on success, 0 on fail.
   * Formats of the time string are taken from the file listed in the
   * DATEMSK env variable
   */
  struct tm *tc;

  tc = getdate(str);

  if (tc == NULL) {
#ifdef NEVER
    if (getdate_err <= 7)
      do_rawlog(LT_ERR, "getdate returned error code %d for %s", getdate_err,
                str);
#endif
    return 0;
  }

  memcpy(ttm, tc, sizeof(struct tm));
  ttm->tm_isdst = -1;

  return 1;
}
Esempio n. 5
0
static void
shift_bufferq(BUFFERQ *bq, int space_needed)
{
  char *p = bq->buffer;
  int size, jump;
  int skipped = 0;

  while ((space_needed > 0) && (p < bq->buffer_end)) {
    /* First 4 bytes is the size of the first string, not including \0 */
    memcpy(&size, p, sizeof(size));
    /* Jump to the start of the next string */
    jump = size + BUFFERQLINEOVERHEAD + 1;
    p += jump;
    space_needed -= jump;
    skipped++;
  }

  if ((p != bq->buffer_end) && (space_needed > 0)) {
    /* Not good. We couldn't get the space we needed even after we
     * emptied the buffer. This should never happen, but if it does,
     * we'll just log a fault and do nothing.
     */
    do_rawlog(LT_ERR, "Unable to get enough buffer queue space");
    return;
  }

  /* Shift everything here and after up to the front
   * At this point, p may be pointing at the very end of the buffer,
   * in which case, we just move it to the front with no shifting.
   */
  if (p < bq->buffer_end)
    memmove(bq->buffer, p, bq->buffer_end - p);
  bq->buffer_end -= (p - bq->buffer);
  bq->num_buffered -= skipped;
}
Esempio n. 6
0
static DH *
get_dh1024(void)
{
  static unsigned char dh1024_p[] = {
    0xB6, 0xBC, 0x30, 0x5B, 0xB4, 0xE5, 0x96, 0x62, 0x3F, 0x85, 0x5B, 0x1F,
    0x88, 0xD1, 0x12, 0xE1, 0x1D, 0x27, 0x69, 0x63, 0xAD, 0xB3, 0x4D, 0x23,
    0xB8, 0x4B, 0x1A, 0x90, 0xA6, 0x89, 0xD8, 0x5D, 0xFA, 0xF5, 0x8F, 0xFF,
    0xFF, 0xF4, 0x54, 0x3B, 0xCD, 0x5C, 0xAA, 0x79, 0x8B, 0x14, 0xBB, 0x84,
    0xAC, 0xEE, 0x94, 0x47, 0x76, 0xEC, 0x46, 0x75, 0x26, 0x48, 0x8C, 0x06,
    0x55, 0x27, 0x7F, 0xC0, 0xF1, 0xE8, 0x1F, 0xD2, 0xE4, 0x55, 0xAE, 0x78,
    0x11, 0x6E, 0xF1, 0x3B, 0xCD, 0x55, 0xE8, 0x17, 0xE9, 0x15, 0x7B, 0x05,
    0x91, 0x28, 0x9D, 0xD3, 0x40, 0x2E, 0x34, 0x03, 0x04, 0x2B, 0x2D, 0xC5,
    0x5C, 0x67, 0xC5, 0xF4, 0x28, 0x8E, 0x16, 0xAC, 0xDD, 0x68, 0x43, 0x66,
    0x51, 0xC1, 0x6F, 0x54, 0xB9, 0x22, 0xD8, 0x1A, 0x39, 0x6B, 0x0A, 0xC1,
    0x20, 0x5A, 0x9D, 0x31, 0x30, 0xE4, 0x0B, 0xC3,
  };
  static unsigned char dh1024_g[] = {
    0x02,
  };
  DH *dh;
  if ((dh = DH_new()) == NULL)
    return NULL;
  if (dh->p) {
    BN_free(dh->p);
    dh->p = NULL;
  }
  if (dh->g) {
    BN_free(dh->g);
    dh->g = NULL;
  }

  dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
  if (!dh->p) {
    do_rawlog(LT_ERR, "Error in BN_bin2bn 1");
    DH_free(dh);
    return NULL;
  }

  dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
  if (!dh->g) {
    do_rawlog(LT_ERR, "Error in BN_bin2bn 2");
    DH_free(dh);
    return NULL;
  }

  return dh;
}
Esempio n. 7
0
void
cu5_pennpy_initialize(void)
{
    FILE *main_py_fp;

    assert(cu5_pennpy_main == NULL);

    do_rawlog(LT_ERR, T("PennPy: Initializing"));

    /* Initialize Python without installing signal handlers. */
    Py_InitializeEx(0);

    /* Borrow a reference to __main__. */
    if (!(cu5_pennpy_main = PyImport_AddModule("__main__"))) {
        /* This shouldn't happen, but you never know. */
        mush_panic(T("PennPy: Can't get reference to __main__"));
    }

    cu5_pennpy_main_dict = PyModule_GetDict(cu5_pennpy_main);

    /* Initialize __pennmush__ internal module. */
    if (!cu5_pennpy_initialize_module()) {
        /* Can't initialize module. */
        mush_panic(T("PennPy: Can't initialize __pennmush__ module"));
    }

    /* Execute game/python/main.py. */
    if (!(main_py_fp = fopen(MAIN_PY, "r"))) {
        /* Can't run main.py. */
        do_rawlog(LT_ERR, T("PennPy: Can't open %s"), MAIN_PY);
        return;
    }

    if (PyRun_SimpleFile(main_py_fp, MAIN_PY) != 0) {
        /* Something wrong with main.py. */
        do_rawlog(LT_ERR, T("PennPy: Failed to execute %s"), MAIN_PY);
        fclose(main_py_fp);
        return;
    }

    fclose(main_py_fp);

    /* Ready. */
    cu5_pennpy_enabled = 1;
}
Esempio n. 8
0
/** Rebuild a help file index.
 * \verbatim
 * This command implements @readcache.
 * \endverbatim
 * \param player the enactor.
 */
void
help_reindex(dbref player)
{
  help_file *curr;

  for (curr = hash_firstentry(&help_files);
       curr; curr = hash_nextentry(&help_files)) {
    if (curr->indx) {
      mush_free(curr->indx, "help_index");
      curr->indx = NULL;
      curr->entries = 0;
    }
    help_build_index(curr, curr->admin);
  }
  if (player != NOTHING) {
    notify(player, T("Help files reindexed."));
    do_rawlog(LT_WIZ, "Help files reindexed by %s(#%d)", Name(player), player);
  } else
    do_rawlog(LT_WIZ, "Help files reindexed.");
}
Esempio n. 9
0
int
CheckDatabase(const char *path, FILETIME * modified, long *filesize)
{
  HANDLE filscan;
  WIN32_FIND_DATA fildata;
  SYSTEMTIME st;
  static const char *const months[] =
    { ">!<", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
    "Oct", "Nov", "Dec"
  };
  FILE *f;
  size_t bytes;
  filscan = FindFirstFile(path, &fildata);
  if (filscan == INVALID_HANDLE_VALUE) {
    do_rawlog(LT_ERR, "File \"%s\" not found.", path);
    return FALSE;
  }
  *modified = fildata.ftLastWriteTime;
  *filesize = fildata.nFileSizeLow;
  FindClose(filscan);
  FileTimeToSystemTime(&fildata.ftLastWriteTime, &st);
  if (st.wMonth < 1 || st.wMonth > 12)
    st.wMonth = 0;
  do_rawlog(LT_ERR,
            "File \"%s\" found, size %ld %s, modified on %02d %s %04d %02d:%02d:%02d",
            path, fildata.nFileSizeLow,
            fildata.nFileSizeLow == 1 ? "byte" : "bytes", st.wDay,
            months[st.wMonth], st.wYear, st.wHour, st.wMinute, st.wSecond);
  if (fildata.nFileSizeHigh == 0 && fildata.nFileSizeLow < 80) {
    do_rawlog(LT_ERR, "File is too small to be a MUSH database.");
    return FALSE;
  }

/* check file for validity */
  f = fopen(path, "rb");
  if (!f) {
    do_rawlog(LT_ERR, "Unable to open file %s", path);
    return FALSE;
  }
  if (fseek(f, -80, SEEK_END) != 0) {
    do_rawlog(LT_ERR, "Unable to check file %s", path);
    fclose(f);
    return FALSE;
  }
  bytes = fread(buff, 1, 80, f);
  fclose(f);
  if (bytes != 80) {
    do_rawlog(LT_ERR, "Unable to read last part of file %s", path);
    return FALSE;
  }
  if (strstr(buff, "***END OF DUMP***") == 0) {
    do_rawlog(LT_ERR, "Database not terminated correctly, file %s", path);
    return FALSE;
  }
  return TRUE;
}                               /* end of  CheckDatabase */
Esempio n. 10
0
void
cu5_pennpy_finalize(void)
{
    assert(cu5_pennpy_main != NULL);

    cu5_pennpy_enabled = 0;

    do_rawlog(LT_ERR, T("PennPy: Finalizing"));

    /* Clean up (some) Python interpreter resources.  Not exhaustive. */
    Py_Finalize();
}
Esempio n. 11
0
/** Remove an allocation check.
 * \param ref type of allocation to remove.
 * \param filename file del_check was called from
 * \param line linenumber in filename where del_check was called
 */
void
del_check(const char *ref, const char *filename, int line)
{
  MEM *chk;

  if (!options.mem_check)
    return;

  chk = lookup_check(ref);

  if (chk) {
    chk->ref_count -= 1;
    if (chk->ref_count < 0)
      do_rawlog(LT_TRACE,
                "ERROR: Deleting a check with a negative count: %s (At %s:%d)",
                ref, filename, line);
  } else {
    do_rawlog(LT_TRACE,
              "ERROR: Deleting a non-existant check: %s (At %s:%d)",
              ref, filename, line);
  }
}
Esempio n. 12
0
/* Unload one Module */
int module_close(struct module_entry_t *m) {
  int ret;

  ret =  m->unload(m); /* first run requierd unload code */
  
  if(!ret)
    return 0;

  /* next unload the modules for real */
  ret = lt_dlclose(m->handle);

  if(ret != 0) {
    do_rawlog(LT_ERR, "Could not unload module: %s/%d | %s", __FILE__, __LINE__, lt_dlerror());
    return 0;
  }

  if(!module_entry_del(m)) {
    do_rawlog(LT_ERR, "Could not unload module: %s/%d ", __FILE__, __LINE__);
    return 0;
  }

  return 1;
}
Esempio n. 13
0
/* Load Module name */
int module_open(char *path, char *name) {
  char file[BUFFER_LEN];
  int (*module_loader)(struct module_entry_t *);
  struct module_entry_t *module;
  void *handle;

  memset(file, '\0', BUFFER_LEN);
  snprintf(file, BUFFER_LEN, "%s/%s", path, name);

  handle = lt_dlopen(file);

  if(!handle) {
    do_rawlog(LT_ERR, "Error Loading Module: %s | %s ", file, lt_dlerror());
    return 0;
  }

  /* Some OSes may need symbols to be prefixed with _.. Will need to look into autoconfig code for this */
  module_loader = MODULE_FUNCRET(handle, "module_load");

  if(!module_loader) {
    do_rawlog(LT_ERR, "Error Loading Module: Could not call module_load | %s", file);
    return 0;
  }

  /* Add the module to the linked list */
  module = module_entry_add(name);
  if(module == NULL) {
    return 0;
  }
  module->handle = handle;
  module->load = module_loader;
  module->unload = MODULE_FUNCRET(handle, "module_unload");
  
  /* Grab info and version from module & put it in */
  /* Success.. Call the module */
  return module_loader(module);
}
Esempio n. 14
0
/** Resize a hash table.
 * \param htab pointer to hashtable.
 * \param primesize new size.
 * \param seed_index Index of first hash seed to use
 */
static bool
hash_resize(HASHTAB *htab, int newsize, int hashseed_offset)
{
  struct hash_bucket *oldarr;
  int oldsize, oldoffset, i;

  /* Massive overkill here */
  if (resize_calls > 150) {
    do_rawlog(LT_ERR, "Ooops. Too many attempts to resize a hash table.");
    return false;
  }

  /* If all possible hash function combos have been exhausted,
     grow the array */
  if (hashseed_offset == first_offset) {
    int newersize = next_prime_after(floor(newsize * 1.15));
    first_offset = -1;
    return hash_resize(htab, newersize, hashseed_offset);
  }

  resize_calls += 1;

  /* Save the old data we need */
  oldsize = htab->hashsize;
  oldoffset = htab->hashseed_offset;
  oldarr = htab->buckets;

  htab->buckets =
    mush_calloc(newsize, sizeof(struct hash_bucket), "hash.buckets");
  htab->hashsize = newsize;
  htab->hashseed_offset = hashseed_offset;
  for (i = 0; i < oldsize; i++) {
    if (oldarr[i].key) {
      if (!hash_insert(htab, oldarr[i].key, oldarr[i].keylen, oldarr[i].data)) {
        /* Couldn't fit an element in. Try with different hash functions. */
        mush_free(htab->buckets, "hash.buckets");
        htab->buckets = oldarr;
        htab->hashsize = oldsize;
        htab->hashseed_offset = oldoffset;
        if (first_offset == -1)
          first_offset = hashseed_offset;
        return hash_resize(htab, newsize, (hashseed_offset + 1) % NHASH_MOD);
      }
    }
  }

  mush_free(oldarr, "hash.buckets");
  return true;
}
Esempio n. 15
0
/** Check a player's password against a given string.
 *
 *  First checks new-style formatted password strings
 *  If that doesn't match, tries old-style SHA0 password
 *  strings, and upgrades the stored password.
 *  If that doesn't match, tries really-old-style crypt(3)
 *  password strings, and upgrades the stored password.
 *  If that doesn't work, you lose.
 *
 * \param player dbref of player.
 * \param password plaintext password string to check.
 * \retval 1 password matches (or player has no password).
 * \retval 0 password fails to match.
 */
bool
password_check(dbref player, const char *password)
{
  ATTR *a;
  char *saved;

  /* read the password and compare it */
  if (!(a = atr_get_noparent(player, pword_attr)))
    return 1; /* No password attribute */

  saved = strdup(atr_value(a));

  if (!saved)
    return 0;

  if (!password_comp(saved, password)) {
    /* Nope. Try SHA0. */
    char *passwd = mush_crypt_sha0(password);
    if (strcmp(saved, passwd) != 0) {
/* Not SHA0 either. Try old-school crypt(); */
#ifdef HAVE_CRYPT
      if (strcmp(crypt(password, "XX"), saved) != 0) {
/* Nope */
#endif /* HAVE_CRYPT */
        /* See if it's a MUX password */
        if (!check_mux_password(saved, password)) {
          /* As long as it's not obviously encrypted, check for a
           * plaintext password. */
          if (strlen(password) < 4 || *password == '$' ||
              (password[0] == 'X' && password[1] == 'X') ||
              strcmp(saved, password)) {
            free(saved);
            return 0;
          }
        }
#ifdef HAVE_CRYPT
      }
#endif
    }
    /* Something worked. Change password to SHS-encrypted */
    do_rawlog(LT_CONN, "Updating password format for player #%d", player);
    (void) atr_add(player, pword_attr, password_hash(password, NULL), GOD, 0);
  }
  /* Success! */
  free(saved);
  return 1;
}
Esempio n. 16
0
void
kill_ssl_slave(void)
{
    if (ssl_slave_pid > 0) {
        WAIT_TYPE my_stat;

        do_rawlog(LT_ERR, "Terminating ssl_slave pid %d", ssl_slave_pid);

        block_a_signal(SIGCHLD);
        kill(ssl_slave_pid, SIGTERM);
        mush_wait(ssl_slave_pid, &my_stat, 0);
        unblock_a_signal(SIGCHLD);
        close(ssl_slave_ctl_fd);
        ssl_slave_pid = -1;
        ssl_slave_state = SSL_SLAVE_DOWN;
    }
}
Esempio n. 17
0
static ATTR *
attr_alias_read(PENNFILE *f, char *alias)
{
  char *tmp;
  ATTR *a;

  db_read_this_labeled_string(f, "name", &tmp);
  a = aname_find_exact(tmp);
  if (!a) {
    /* Oops */
    do_rawlog(LT_ERR, "Alias of non-existant attribute '%s' in db.", tmp);
    (void) getstring_noalloc(f);
    return NULL;
  }
  db_read_this_labeled_string(f, "alias", &tmp);
  strcpy(alias, tmp);

  return a;
}
Esempio n. 18
0
/** Kill the info_slave process, typically at shutdown.
 */
void
kill_info_slave(void)
{
  WAIT_TYPE my_stat;

  if (info_slave_state != INFO_SLAVE_DOWN) {
    if (info_slave_pid > 0) {
      do_rawlog(LT_ERR, "Terminating info_slave pid %d", info_slave_pid);

      block_a_signal(SIGCHLD);
      closesocket(info_slave);
      kill(info_slave_pid, SIGTERM);
      mush_wait(info_slave_pid, &my_stat, 0);
      info_slave_pid = -1;
      unblock_a_signal(SIGCHLD);
    }
    info_slave_state = INFO_SLAVE_DOWN;
  }
}
Esempio n. 19
0
static void
cu5_pennpy_exception(char *buff, char **bp)
{
    const char *ex_name;
    PyObject *ex_type;

    /*
     * Report exception.  We don't return specifics; if you need them,
     * handle that in the Python code and return a string.
     */
    ex_name = "PYTHON"; /* catch-all exception "name" */

    ex_type = PyErr_Occurred();
    if (PyExceptionClass_Check(ex_type)) {
        /* Exception type is a valid exception class. */
        ex_name = PyExceptionClass_Name(ex_type);
        if (ex_name) {
            /* Exception class has a name. */
            char *ex_short_name = strrchr(ex_name, '.');
            if (ex_short_name) {
                /* blah.blah.ExceptionName */
                ex_name = ex_short_name + 1;
            }
        } else {
            /* Shouldn't happen, but extra cautious. */
        }
    } else {
        /*
         * This must be an old-style string exception, but those are
         * deprecated and now too rare for us to bother identifying.
         */
    }

    safe_format(buff, bp, T("#-1 %s EXCEPTION"), ex_name);

    /* Dump the stack to stderr and clear the error indicator. */
    do_rawlog(LT_ERR, "PennPy: Python exception:");
    PyErr_Print();
}
Esempio n. 20
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);
}
Esempio n. 21
0
/** Kill the info_slave process, typically at shutdown.
 */
void
kill_info_slave(void)
{
  WAIT_TYPE my_stat;

  if (info_slave_state != INFO_SLAVE_DOWN) {
    if (info_slave_pid > 0) {
      do_rawlog(LT_ERR, "Terminating info_slave pid %d", info_slave_pid);

      block_a_signal(SIGCHLD);

      closesocket(info_slave);
      kill(info_slave_pid, 15);
      /* Have to wait long enough for the info_slave to actually
         die. This will hopefully be enough time. */
      usleep(100);

      mush_wait(info_slave_pid, &my_stat, WNOHANG);
      info_slave_pid = -1;
      unblock_a_signal(SIGCHLD);
    }
    info_slave_state = INFO_SLAVE_DOWN;
  }
}
Esempio n. 22
0
/** Parse a time zone description file. */
struct tzinfo *
read_tzfile(const char *tzname)
{
  char tzfile[BUFFER_LEN];
  int fd;
  struct tzinfo *tz;

  if (!is_valid_tzname(tzname))
    return NULL;

  snprintf(tzfile, BUFFER_LEN, "%s/%s", TZDIR, tzname);

  if ((fd = open(tzfile, O_RDONLY)) < 0) {
    if (errno != ENOENT)
      do_rawlog(LT_ERR, "tz: Unable to open %s: %s\n", tzfile, strerror(errno));
    return NULL;
  }

  tz = do_read_tzfile(fd, tzfile, 4);

  close(fd);

  return tz;
}
Esempio n. 23
0
void
cu5_pennpy_timer(void)
{
    PyObject *result;

    if (!cu5_pennpy_enabled || !cu5_pennpy_timer_hook) {
        /* No timer hook available. */
        return;
    }

    /* Call timer hook. */
    result = PyObject_CallObject(cu5_pennpy_timer_hook, NULL);
    if (!result) {
        do_rawlog(LT_ERR, "PennPy: Timer hook threw exception");
        PyErr_Print();

        /* Disable timer hook.  Annoying, so don't throw exceptions. */
        cu5_pennpy_set_timer(NULL);
        return;
    }

    /* Discard result. */
    Py_DECREF(result);
}
Esempio n. 24
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++;
    if (IsPlayer(end_obj)) {
      for (mp = find_exact_starting_point(end_obj); mp; mp = mp->next)
        if (mp->msgid != NULL_CHUNK_REFERENCE)
          actual++;
    }
    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(refs, "migration reference array");
    refs =
      mush_calloc(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++;
      }
    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++;
        }
    }
    start_obj = (start_obj + 1) % db_top;
  } while (start_obj != end_obj);

  chunk_migration(actual, refs);
}
Esempio n. 25
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;
}
Esempio n. 26
0
bool
make_info_slave(void)
{
  int socks[2];
  pid_t child;
  int n;

  if (info_slave_state != INFO_SLAVE_DOWN) {
    if (info_slave_pid > 0)
      kill_info_slave();
    info_slave_state = INFO_SLAVE_DOWN;
  }

  if (startup_attempts == 0)
    time(&startup_window);

  startup_attempts += 1;

  if (startup_attempts > MAX_ATTEMPTS) {
    time_t now;

    time(&now);
    if (difftime(now, startup_window) <= 60.0) {
      /* Too many failed attempts to start info_slave in 1 minute */
      do_rawlog(LT_ERR, "Disabling info_slave due to too many errors.");
      info_slave_halted = true;
      return false;
    } else {
      /* Reset counter */
      startup_window = now;
      startup_attempts = 0;
    }
  }
#ifndef AF_LOCAL
  /* Use Posix.1g names. */
#define AF_LOCAL AF_UNIX
#endif

#ifdef HAVE_SOCKETPAIR
  if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, socks) < 0) {
    penn_perror("creating slave datagram socketpair");
    return false;
  }
  if (socks[0] >= maxd)
    maxd = socks[0] + 1;
  if (socks[1] >= maxd)
    maxd = socks[1] + 1;
#endif

  child = fork();
  if (child < 0) {
    penn_perror("forking info slave");
#ifdef HAVE_SOCKETPAIR
    closesocket(socks[0]);
    closesocket(socks[1]);
#endif
    return false;
  } else if (child > 0) {
    info_slave_state = INFO_SLAVE_READY;
    info_slave_pid = child;
#ifdef HAVE_SOCKETPAIR
    info_slave = socks[0];
    closesocket(socks[1]);
    do_rawlog(LT_ERR,
              "Spawning info slave, communicating using socketpair, pid %d.",
              child);
#endif
    make_nonblocking(info_slave);
  } else {
    int errfd = fileno(stderr);
    int dupfd;

    /* Close unneeded fds and sockets: Everything but stderr and the
       socket used to talk to the mush */
    for (n = 0; n < maxd; n++) {
      if (n == errfd)
        continue;
#ifdef HAVE_SOCKETPAIR
      if (n == socks[1])
        continue;
#endif
      close(n);
    }
    /* Reuse stdin and stdout for talking to the slave */
    dupfd = dup2(socks[1], 0);
    if (dupfd < 0) {
      penn_perror("dup2() of stdin in info_slave");
      exit(1);
    }

    dupfd = dup2(socks[1], 1);
    if (dupfd < 0) {
      penn_perror("dup2() of stdout in info_slave");
      exit(1);
    }

    close(socks[1]);

    execl("./info_slave", "info_slave", "for", MUDNAME, (char *) NULL);
    penn_perror("execing info slave");
    exit(1);
  }

  if (info_slave >= maxd)
    maxd = info_slave + 1;

  lower_priority_by(info_slave_pid, 4);

  for (n = 0; n < maxd; n++)
    if (FD_ISSET(n, &info_pending))
      query_info_slave(n);

  return true;
}
Esempio n. 27
0
/** Create a new SSL slave.
 * \param port The port to listen on for SSL connections.
 * \return 0 on success, -1 on failure
 */
int
make_ssl_slave(void)
{
    int fds[2];

    if (ssl_slave_state != SSL_SLAVE_DOWN) {
        do_rawlog(LT_ERR,
                  "Attempt to start ssl slave when a copy is already running.");
        return -1;
    }

    if (ssl_slave_halted) {
        do_rawlog(LT_ERR, "Attempt to start disabled ssl slave.");
        return -1;
    }

    if (startup_attempts == 0)
        time(&startup_window);

    startup_attempts += 1;

    if (startup_attempts > MAX_ATTEMPTS) {
        time_t now;

        time(&now);
        if (difftime(now, startup_window) <= 60.0) {
            do_rawlog(LT_ERR, "Disabling ssl_slave due to too many errors.");
            ssl_slave_halted = true;
            return -1;
        } else {
            /* Reset counter */
            startup_window = now;
            startup_attempts = 0;
        }
    }

    if (pipe(fds) < 0) {
        do_rawlog(LT_ERR, "Unable to create pipe to speak to ssl_slave: %s",
                  strerror(errno));
        return -1;
    }

    if (fds[0] >= maxd)
        maxd = fds[0] + 1;
    if (fds[1] >= maxd)
        maxd = fds[1] + 1;

    if ((ssl_slave_pid = fork()) == 0) {
        /* Set up and exec ssl_slave */
        int n, errfd = -1, connfd = -1;
        struct log_stream *lg;

        /* Close all open files but LT_CONN and LT_ERR, and assign them as
           stdout and stderr, respectively. */

        /* If called on startup, maxd is 0 but log files and such have
           been opened. Use a reasonable max descriptor. If called because
           ssl_slave went down, maxd will be set properly already. */
        if (!maxd)
            maxd = 20;

        lg = lookup_log(LT_ERR);
        if (lg)
            errfd = fileno(lg->fp);

        lg = lookup_log(LT_CONN);
        if (lg)
            connfd = fileno(lg->fp);

        dup2(fds[0], 0);            /* stdin */
        dup2(connfd, 1);            /* stdout */
        dup2(errfd, 2);             /* stderr */

        for (n = 3; n < maxd; n++)
            close(n);

        execl("./ssl_slave", "ssl_slave", "for", MUDNAME, NULL);
        penn_perror("execing ssl slave");
        return EXIT_FAILURE;
    } else if (ssl_slave_pid < 0) {
        do_rawlog(LT_ERR, "Failure to fork ssl_slave: %s", strerror(errno));
        return -1;
    } else {
        struct ssl_slave_config cf;

        ssl_slave_ctl_fd = fds[1];
        close(fds[0]);

        /* Set up arguments to the slave */
        memset(&cf, 0, sizeof cf);
        strcpy(cf.socket_file, options.socket_file);
        strcpy(cf.ssl_ip_addr, SSL_IP_ADDR);
        cf.normal_port = options.port;
        cf.ssl_port = options.ssl_port;
        strcpy(cf.private_key_file, options.ssl_private_key_file);
        strcpy(cf.ca_file, options.ssl_ca_file);
        cf.require_client_cert = options.ssl_require_client_cert;
        cf.keepalive_timeout = options.keepalive_timeout;

        if (write(ssl_slave_ctl_fd, &cf, sizeof cf) < 0) {
            do_rawlog(LT_ERR, "Unable to send ssl_slave config options: %s",
                      strerror(errno));
            return -1;
        }

        ssl_slave_state = SSL_SLAVE_RUNNING;
        do_rawlog(LT_ERR, "Spawning ssl_slave, communicating over %s, pid %d.",
                  options.socket_file, ssl_slave_pid);
        return 0;
    }

    return -1;
}
Esempio n. 28
0
static void
help_build_index(help_file *h, int restricted)
{
  long bigpos, pos = 0;
  bool in_topic;
  int i, lineno, ntopics;
  size_t n;
  char *s, *topic;
  char the_topic[TOPIC_NAME_LEN + 1];
  char line[LINE_SIZE + 1];
  FILE *rfp;
  tlist *cur;

  /* Quietly ignore null values for the file */
  if (!h || !h->file)
    return;
  if ((rfp = fopen(h->file, FOPEN_READ)) == NULL) {
    do_rawlog(LT_ERR, "Can't open %s for reading: %s", h->file,
              strerror(errno));
    return;
  }

  if (restricted)
    do_rawlog(LT_WIZ, "Indexing file %s (admin topics)", h->file);
  else
    do_rawlog(LT_WIZ, "Indexing file %s", h->file);
  topics = NULL;
  num_topics = 0;
  top_topics = 0;
  bigpos = 0L;
  lineno = 0;
  ntopics = 0;

  in_topic = 0;

#ifdef HAVE_POSIX_FADVISE
  posix_fadvise(fileno(rfp), 0, 0, POSIX_FADV_SEQUENTIAL);
#endif

  while (fgets(line, LINE_SIZE, rfp) != NULL) {
    ++lineno;
    if (ntopics == 0) {
      /* Looking for the first topic, but we'll ignore blank lines */
      if (!line[0]) {
        /* Someone's feeding us /dev/null? */
        do_rawlog(LT_ERR, "Malformed help file %s doesn't start with &",
                  h->file);
        fclose(rfp);
        return;
      }
      if (isspace(line[0]))
        continue;
      if (line[0] != '&') {
        do_rawlog(LT_ERR, "Malformed help file %s doesn't start with &",
                  h->file);
        fclose(rfp);
        return;
      }
    }
    n = strlen(line);
    if (line[n - 1] != '\n') {
      do_rawlog(LT_ERR, "Line %d of %s: line too long", lineno, h->file);
    }
    if (line[0] == '&') {
      ++ntopics;
      if (!in_topic) {
        /* Finish up last entry */
        if (ntopics > 1) {
          write_topic(pos);
        }
        in_topic = true;
      }
      /* parse out the topic */
      /* Get the beginning of the topic string */
      for (topic = &line[1];
           (*topic == ' ' || *topic == '\t') && *topic != '\0'; topic++) ;

      /* Get the topic */
      strcpy(the_topic, "");
      for (i = -1, s = topic; *s != '\n' && *s != '\0'; s++) {
        if (i >= TOPIC_NAME_LEN - 1)
          break;
        if (*s != ' ' || the_topic[i] != ' ')
          the_topic[++i] = *s;
      }
      if ((restricted && the_topic[0] == '&')
          || (!restricted && the_topic[0] != '&')) {
        the_topic[++i] = '\0';
        cur = (tlist *) malloc(sizeof(tlist));
        strcpy(cur->topic, the_topic);
        cur->next = top;
        top = cur;
      }
    } else {
      if (in_topic) {
        pos = bigpos;
      }
      in_topic = false;
    }
    bigpos = ftell(rfp);
  }

  /* Handle last topic */
  write_topic(pos);
  if (topics)
    qsort(topics, num_topics, sizeof(help_indx), topic_cmp);
  h->entries = num_topics;
  h->indx = topics;
  add_check("help_index");
  fclose(rfp);
  do_rawlog(LT_WIZ, "%d topics indexed.", num_topics);
  return;
}
Esempio n. 29
0
static void
do_new_spitfile(dbref player, char *arg1, help_file *help_dat)
{
  help_indx *entry = NULL;
  FILE *fp;
  char *p, line[LINE_SIZE + 1];
  char the_topic[LINE_SIZE + 2];
  int default_topic = 0;
  size_t n;

  if (*arg1 == '\0') {
    default_topic = 1;
    arg1 = (char *) help_dat->command;
  } else if (*arg1 == '&') {
    notify(player, T("Help topics don't start with '&'."));
    return;
  }
  if (strlen(arg1) > LINE_SIZE)
    *(arg1 + LINE_SIZE) = '\0';

  if (help_dat->admin) {
    sprintf(the_topic, "&%s", arg1);
  } else
    strcpy(the_topic, arg1);

  if (!help_dat->indx || help_dat->entries == 0) {
    notify(player, T("Sorry, that command is temporarily unvailable."));
    do_rawlog(LT_ERR, "No index for %s.", help_dat->command);
    return;
  }

  entry = help_find_entry(help_dat, the_topic);
  if (!entry && default_topic)
    entry = help_find_entry(help_dat, (help_dat->admin ? "&help" : "help"));

  if (!entry) {
    notify_format(player, T("No entry for '%s'."), arg1);
    return;
  }

  if ((fp = fopen(help_dat->file, FOPEN_READ)) == NULL) {
    notify(player, T("Sorry, that function is temporarily unavailable."));
    do_log(LT_ERR, 0, 0, "Can't open text file %s for reading", help_dat->file);
    return;
  }
  if (fseek(fp, entry->pos, 0) < 0L) {
    notify(player, T("Sorry, that function is temporarily unavailable."));
    do_rawlog(LT_ERR, "Seek error in file %s", help_dat->file);
    return;
  }
  strcpy(the_topic, strupper(entry->topic + (*entry->topic == '&')));
  /* ANSI topics */
  notify_format(player, "%s%s%s", ANSI_HILITE, the_topic, ANSI_END);

  if (SUPPORT_PUEBLO)
    notify_noenter(player, open_tag("SAMP"));
  for (n = 0; n < BUFFER_LEN; n++) {
    if (fgets(line, LINE_SIZE, fp) == NULL)
      break;
    if (line[0] == '&')
      break;
    if (line[0] == '\n') {
      notify(player, " ");
    } else {
      for (p = line; *p != '\0'; p++)
        if (*p == '\n')
          *p = '\0';
      notify(player, line);
    }
  }
  if (SUPPORT_PUEBLO)
    notify(player, close_tag("SAMP"));
  fclose(fp);
  if (n >= BUFFER_LEN)
    notify_format(player, T("%s output truncated."), help_dat->command);
}
Esempio n. 30
0
/** Read the access.cnf file.
 * Initialize the access rules linked list and read in the access.cnf file.
 * \return true if successful, false if not
 */
bool
read_access_file(void)
{
  FILE *fp;
  char buf[BUFFER_LEN];
  char *p;
  uint32_t can, cant;
  int retval;
  dbref who;
  char *comment;
  const char *errptr = NULL;

  if (access_top) {
    /* We're reloading the file, so we've got to delete any current
     * entries
     */
    free_access_list();
  }
  access_top = NULL;
  /* Be sure we have a file descriptor */
  release_fd();
  fp = fopen(ACCESS_FILE, FOPEN_READ);
  if (!fp) {
    do_rawlog(LT_ERR, "Access file %s not found.", ACCESS_FILE);
    retval = 0;
  } else {
    do_rawlog(LT_ERR, "Reading %s", ACCESS_FILE);
    while (fgets(buf, BUFFER_LEN, fp)) {
      /* Strip end of line if it's \r\n or \n */
      if ((p = strchr(buf, '\r')))
        *p = '\0';
      else if ((p = strchr(buf, '\n')))
        *p = '\0';
      /* Find beginning of line; ignore blank lines */
      p = buf;
      if (*p && isspace((unsigned char) *p))
        p++;
      if (*p && *p != '#') {
        can = cant = 0;
        comment = NULL;
        /* Is this the @sitelock entry? */
        if (!strncasecmp(p, "@sitelock", 9)) {
          if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "",
                               &errptr))
            do_log(LT_ERR, GOD, GOD, "Failed to add sitelock node: %s", errptr);
        } else {
          if ((comment = strchr(p, '#'))) {
            *comment++ = '\0';
            while (*comment && isspace((unsigned char) *comment))
              comment++;
          }
          /* Move past the host name */
          while (*p && !isspace((unsigned char) *p))
            p++;
          if (*p)
            *p++ = '\0';
          if (!parse_access_options(p, &who, &can, &cant, NOTHING))
            /* Nothing listed, so assume we can't do anything! */
            cant = ACS_DEFAULT;
          if (!add_access_node(buf, who, can, cant, comment, &errptr))
            do_log(LT_ERR, GOD, GOD, "Failed to add access node: %s", errptr);
        }
      }
    }
    retval = 1;
    fclose(fp);
  }
  reserve_fd();
  return retval;
}