Example #1
0
/** Check for CHARGES on thing and, if present, lower.
 * \param thing object being used.
 * \retval 0 charges was set to 0
 * \retval 1 charges not set, or was > 0
 */
int
charge_action(dbref thing)
{
  ATTR *b;
  char tbuf2[BUFFER_LEN];
  int num;

  /* check if object has # of charges */
  b = atr_get_noparent(thing, "CHARGES");

  if (!b) {
    return 1;                   /* no CHARGES */
  } else {
    strcpy(tbuf2, atr_value(b));
    num = atoi(tbuf2);
    if (num > 0) {
      /* charges left, decrement and execute */
      (void) atr_add(thing, "CHARGES", tprintf("%d", num - 1),
                     Owner(b->creator), 0);
      return 1;
    } else {
      /* no charges left, try to execute runout */
      return 0;
    }
  }
}
Example #2
0
// Gets an attribute from an object and stores the value
// in the buffer.  It returns false if the attribute was
// not found.  Otherwise, true.
HS_BOOL8 CHSInterface::AtrGet(int obj, const char *atrname)
{
#ifdef PENNMUSH
    ATTR *a;

    a = atr_get(obj, atrname);
    if (!a)
    {
        return false;
    }

    strcpy_s(m_buffer, atr_value(a));
    return true;
#endif

#if defined(TM3) || defined(MUX)
    char *a;
    a = my_atr_get(obj, atrname);
    if (a && *a)
    {
        strcpy(m_buffer, a);
        return true;
    }
    else
        return false;
#endif
}
Example #3
0
/** Retrieve the amount of quote remaining to a player.
 * Figure out a player's quota. Add the RQUOTA attribute if he doesn't
 * have one already. This function returns the REMAINING quota, not
 * the TOTAL limit.
 * \param who player to check.
 * \return player's remaining quota.
 */
int
get_current_quota(dbref who)
{
  ATTR *a;
  int i;
  int limit;
  int owned = 0;

  /* if he's got an RQUOTA attribute, his remaining quota is that */
  a = atr_get_noparent(Owner(who), "RQUOTA");
  if (a)
    return parse_integer(atr_value(a));

  /* else, count up his objects. If he has less than the START_QUOTA,
   * then his remaining quota is that minus his number of current objects.
   * Otherwise, it's his current number of objects. Add the attribute
   * if he doesn't have it.
   */

  for (i = 0; i < db_top; i++)
    if (Owner(i) == Owner(who))
      owned++;
  owned--;                      /* don't count the player himself */

  if (owned <= START_QUOTA)
    limit = START_QUOTA - owned;
  else
    limit = owned;

  (void) atr_add(Owner(who), "RQUOTA", tprintf("%d", limit), GOD, 0);

  return limit;
}
Example #4
0
/** Since enum adds a delim before and after the string, edit them out. */
const char *
display_attr_limit(ATTR *ap)
{
  char *ptr;
  char *s;

  if (ap->data && (ap->flags & AF_ENUM)) {
    ptr = atr_value(ap);
    *(ptr++) = '\0';
    s = ptr + strlen(ptr);
    s--;
    *(s) = '\0';
    return ptr;
  } else if (ap->data && (ap->flags & AF_RLIMIT)) {
    return atr_value(ap);
  }
  return "unset";
}
Example #5
0
/** Processing related to players' last connections.
 * Here we check to see if a player gets a paycheck, tell them their
 * last connection site, and update all their LAST* attributes.
 * \param player dbref of player.
 * \param host hostname of player's current connection.
 * \param ip ip address of player's current connection.
 */
void
check_last(dbref player, const char *host, const char *ip)
{
  char *s;
  ATTR *a;
  ATTR *h;
  char last_time[MAX_COMMAND_LEN / 8];
  char last_place[MAX_COMMAND_LEN];

  /* compare to last connect see if player gets salary */
  s = show_time(mudtime, 0);
  a = atr_get_noparent(player, "LAST");
  if (a && (strncmp(atr_value(a), s, 10) != 0))
    giveto(player, Paycheck(player));
  /* tell the player where he last connected from */
  if (!Guest(player)) {
    h = atr_get_noparent(player, "LASTSITE");
    if (h && a) {
      strcpy(last_place, atr_value(h));
      strcpy(last_time, atr_value(a));
      notify_format(player, T("Last connect was from %s on %s."), last_place,
                    last_time);
    }
    /* How about last failed connection */
    h = atr_get_noparent(player, "LASTFAILED");
    if (h && a) {
      strcpy(last_place, atr_value(h));
      if (strlen(last_place) > 2)
        notify_format(player, T("Last FAILED connect was from %s."),
                      last_place);
    }
  }
  /* if there is no Lastsite, then the player is newly created.
   * the extra variables are a kludge to work around some weird
   * behavior involving uncompress.
   */

  /* set the new attributes */
  (void) atr_add(player, "LAST", s, GOD, 0);
  (void) atr_add(player, "LASTSITE", host, GOD, 0);
  (void) atr_add(player, "LASTIP", ip, GOD, 0);
  (void) atr_add(player, "LASTFAILED", " ", GOD, 0);
}
Example #6
0
char *unparse_class (int x)
{
	ATTR *a;
	static char buffer[20];

	a = atr_get(sdb[x].object, CLASS_ATTR_NAME);
	if (a == NULL)
		return (char *) "#-1 BAD CLASS";

	strncpy(buffer, atr_value(a), sizeof(buffer) - 1);

	return (buffer);
}
Example #7
0
/* board a ship through the ship object */
void board_ship(dbref player, char *which, char *code)
{
  ATTR *a;
  char *bcode;
  dbref obj, nav, bay;
  int security;
  
  /* find the shipobj */
  obj = match_result(player, which, TYPE_THING, MAT_NEAR_THINGS);
  if (!IsShipObj(obj))
  {
    notify(player, "Can't find that ship.");
    return;
  }
  
  /* see if it's got an HSNAV */
  nav = atr_parse_dbref(obj, "HSNAV");
  if (!IsShip(nav))
  {
    notify(player, "That is not a valid ship object.");
    return;
  }
  
  /* check the boarding code, if necessary */
  security = atr_parse_integer(nav, "SECURITY", 0);
  if (security)
  {
    a = atr_get(nav, "BOARDING_CODE");
    if (a)
    {
      bcode = atr_value(a);
      if (strcmp(bcode, code))
      {
        notify(player, "Invalid boarding code.");
        return;
      }
    }
  }
  
  /* check for a BAY on the nav, otherwise go to the nav's location */
  bay = atr_parse_dbref(nav, "BAY");
  if (!RealGoodObject(bay))
  {
    bay = Location(nav);
  }
  
  atr_add(player, "HSPACE", unparse_dbref(nav), hs_options.space_wiz, 0);
  notify_except(obj, Location(player), player, tprintf("%s boards the %s.", Name(player), Name(obj)), 0);
  notify_except(obj, bay, player, tprintf("%s boards through the main hatch.", Name(player)), 0);
  moveto(player, bay, hs_options.space_wiz, NULL);
}
Example #8
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;
}
Example #9
0
void
attr_write_all(PENNFILE *f)
{
  int attrcount = 0, aliascount = 0;
  ATTR *a;
  const char *attrname;
  char *data;

  for (a = ptab_firstentry_new(&ptab_attrib, &attrname); a;
       a = ptab_nextentry_new(&ptab_attrib, &attrname)) {
    if (!strcmp(attrname, AL_NAME(a)))
      attrcount++;
    else
      aliascount++;
  }

  db_write_labeled_int(f, "attrcount", attrcount);
  for (a = ptab_firstentry_new(&ptab_attrib, &attrname); a;
       a = ptab_nextentry_new(&ptab_attrib, &attrname)) {
    if (strcmp(attrname, AL_NAME(a)))
      continue;                 /* skip aliases */
    db_write_labeled_string(f, " name", AL_NAME(a));
    db_write_labeled_string(f, "  flags",
                            privs_to_string(attr_privs_db, AL_FLAGS(a)));
    db_write_labeled_dbref(f, "  creator", AL_CREATOR(a));
    data = atr_value(a);
    db_write_labeled_string(f, "  data", data);
  }

  db_write_labeled_int(f, "attraliascount", aliascount);
  for (a = ptab_firstentry_new(&ptab_attrib, &attrname); a;
       a = ptab_nextentry_new(&ptab_attrib, &attrname)) {
    if (!strcmp(attrname, AL_NAME(a)))
      continue;                 /* skip non-aliases */
    db_write_labeled_string(f, " name", AL_NAME(a));
    db_write_labeled_string(f, "  alias", attrname);
  }

}
Example #10
0
/** Reset all of a player's player list entries (names/aliases).
 * This is called when a player changes name or alias.
 * We remove all their old entries, and add back their new ones.
 * \param player dbref of player
 * \param oldname player's former name (NULL if not changing)
 * \param oldalias player's former aliases (NULL if not changing)
 * \param name player's new name
 * \param alias player's new aliases
 */
void
reset_player_list(dbref player, const char *oldname, const char *oldalias,
                  const char *name, const char *alias)
{
  char tbuf1[BUFFER_LEN];
  char tbuf2[BUFFER_LEN];
  if (!oldname)
    name = Name(player);
  if (oldalias) {
    mush_strncpy(tbuf1, oldalias, BUFFER_LEN);
    if (alias) {
      strncpy(tbuf2, alias, BUFFER_LEN - 1);
      tbuf2[BUFFER_LEN - 1] = '\0';
    } else {
      tbuf2[0] = '\0';
    }
  } else {
    /* We are not changing aliases, just name, but we need to get the
     * aliases anyway, since we may change name to something that's
     * in the alias, and thus must not be deleted.
     */
    ATTR *a = atr_get_noparent(player, "ALIAS");
    if (a) {
      mush_strncpy(tbuf1, atr_value(a), BUFFER_LEN);
    } else {
      tbuf1[0] = '\0';
    }
    strcpy(tbuf2, tbuf1);
  }
  /* Delete all the old stuff */
  delete_player(player, tbuf1);
  delete_player(player, NULL);
  /* Add in the new stuff */
  add_player_alias(player, name);
  add_player_alias(player, tbuf2);
}
Example #11
0
static void
ct_exit(dbref player, dbref i, warn_type flags)
{
    dbref j, src, dst;
    int count = 0;
    int lt;

    /* i must be an exit, must be in a valid room, and must lead to a
     * different room
     * Remember, for exit i, Exits(i) = source room
     * and Location(i) = destination room
     */

    dst = Destination(i);
    if ((flags & W_EXIT_UNLINKED) && (dst == NOTHING))
        complain(player, i, "exit-unlinked",
                 T("exit is unlinked; anyone can steal it"));

    if ((flags & W_EXIT_UNLINKED) && dst == AMBIGUOUS) {
        ATTR *a;
        const char *var = "DESTINATION";
        a = atr_get(i, "DESTINATION");
        if (!a)
            a = atr_get(i, "EXITTO");
        if (a)
            var = "EXITTO";
        if (!a)
            complain(player, i, "exit-unlinked",
                     T("Variable exit has no %s attribute"), var);
        else {
            const char *x = atr_value(a);
            if (!x || !*x)
                complain(player, i, "exit-unlinked",
                         T("Variable exit has empty %s attribute"), var);
        }
    }

    if (!Dark(i)) {
        if (flags & W_EXIT_MSGS) {
            lt = warning_lock_type(getlock(i, Basic_Lock));
            if ((lt & W_UNLOCKED) &&
                    (!atr_get(i, "OSUCCESS") || !atr_get(i, "ODROP") ||
                     !atr_get(i, "SUCCESS")))
                complain(player, i, "exit-msgs",
                         T("possibly unlocked exit missing succ/osucc/odrop"));
            if ((lt & W_LOCKED) && !atr_get(i, "FAILURE"))
                complain(player, i, "exit-msgs",
                         T("possibly locked exit missing fail"));
        }
        if (flags & W_EXIT_DESC) {
            if (!atr_get(i, "DESCRIBE"))
                complain(player, i, "exit-desc", T("exit is missing description"));
        }
    }
    src = Source(i);
    if (!GoodObject(src) || !IsRoom(src))
        return;
    if (src == dst)
        return;
    /* Don't complain about exits linked to HOME or variable exits. */
    if (!GoodObject(dst))
        return;

    for (j = Exits(dst); GoodObject(j); j = Next(j))
        if (Location(j) == src) {
            if (!(flags & W_EXIT_MULTIPLE))
                return;
            else
                count++;
        }
    if ((count == 0) && (flags & W_EXIT_ONEWAY))
        complain(player, i, "exit-oneway", T("exit has no return exit"));
    else if ((count > 1) && (flags & W_EXIT_MULTIPLE))
        complain(player, i, "exit-multiple",
                 T("exit has multiple (%d) return exits"), count);
}
Example #12
0
/* leave a flying ship through the escape pod */
void emergency_eject(dbref player)
{
  dbref nav, pad;
  hship *ship;
  hcelestial *cel, *min_cel;
  ATTR *a;
  char *r, *s;
  char buff[512];
  double dist, min_dist;
  dbref min_pad;
  hship *sptr, *min_ship;
  
  /* check for a BAY */
  a = atr_get(Location(player), "BAY");
  if (!a)
  {
    /* no BAY, see if we're next to the nav console */
    ship = find_ship(player);
    if (ship)
    {
      if (Location(ship->objnum) != Location(player))
      {
        notify(player, "You can't eject from here.");
        return;
      }
    }
  }
  else
  {
    /* there's a BAY, see if the ship is valid */
    nav = parse_dbref(atr_value(a));
    if (!IsShip(nav))
    {
      notify(player, "You can't eject from here.");
      return;
    }

    ship = find_ship_by_nav(nav);
  }
  
  if (!ship)
  {
    notify(player, "You can't eject from here.");
    return;
  }

  /* only eject when flying, not when landing or docking */
  if (!ship->uid || ship->landed || ship->docked)
  {
    notify(player, "You may only eject while flying.");
    return;
  }
  
  /* find a planet with a drop pad */
  min_pad = NOTHING;
  min_dist = 1000000.0;
  min_cel = NULL;
  for (cel = ship->uid->head_celestial; cel; cel = cel->next)
  {
    if (!HasFlag(cel->type, HS_PLANET))
      continue;
    
    pad = atr_parse_dbref(cel->objnum, "DROPPADS");
    if (!RealGoodObject(pad))
      continue;

    dist = ship_celestial_distance(ship, cel);

    if (dist < min_dist)
    {
      min_dist = dist;
      min_pad = pad;
      min_cel = cel;
    }
  }
  
  min_ship = NULL;
  for (sptr = ship->uid->head_ship; sptr; sptr = sptr->next)
  {
    if (min_cel)
      break;
    
    if (!HasFlag(sptr->type, HS_STATION | HS_CAPITAL))
      continue;
    
    pad = atr_parse_dbref(sptr->objnum, "BAY");
    if (!RealGoodObject(pad))
      continue;
    
    dist = ship_distance(ship, sptr);

    if (dist < min_dist)
    {
      min_cel = NULL;
      min_ship = sptr;
      min_dist = dist;
      min_pad = pad;
    }
  }
  
  if (!RealGoodObject(min_pad))
  {
    notify(player, "There is nowhere to eject to!");
    return;
  }

  /* finish up by setting HSPACE and notifying everybody of the move */
  if (min_ship)
  {
    atr_add(player, "HSPACE", unparse_dbref(min_ship->objnum), hs_options.space_wiz, 0);
  }
  else if (min_cel)
  {
    atr_add(player, "HSPACE", unparse_dbref(min_cel->objnum), hs_options.space_wiz, 0);
  }
  else
  {
    SPACEWALL("Weird problem in eject.");
    notify(player, "Bad space object. Contact an administrator.");
    return;
  }

  notify_except(Location(player), Location(player), player, tprintf("%s ejects in an emergency escape pod!", Name(player)), 0);
  notify_except(min_pad, min_pad, player, tprintf("%s crash lands in an emergency escape pod!", Name(player)), 0);
  if (min_ship)
  {
    notify_consoles(min_ship, tprintf("%s%s-%s Emergency ejection pod automatically tractored into the docking back.",
          ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL));
  }
  moveto(player, min_pad, hs_options.space_wiz, NULL);
}
Example #13
0
/* leave a landed/docked ship through the hatch */
void disembark(dbref player)
{
  dbref nav, obj, newobj;
  hship *ship;
  ATTR *a;
  int security;
  
  /* check if we can disembark from here */
  a = atr_get(Location(player), "BAY");
  if (!a)
  {
    /* no BAY, check if we're near the nav console */
    ship = find_ship(player);
    if (ship)
    {
      if (Location(ship->objnum) != Location(player))
      {
        notify(player, "You can't disembark from here.");
        return;
      }
    }
  }
  else
  {
    /* there's a BAY here, make sure it's a good one */
    nav = parse_dbref(atr_value(a));
    if (!IsShip(nav))
    {
      notify(player, "You can't disembark from here.");
      return;
    }
  
    ship = find_ship_by_nav(nav);
  }
  
  if (!ship)
  {
    notify(player, "You can't disembark from here.");
    return;
  }
  
  /* no ditching in space, or early after launching, or prematurely when landing */
  if ((ship->uid || ship->landing || ship->launching) && !ship->linked)
  {
    notify(player, "You can't disembark while in space.");
    return;
  }
  
  obj = atr_parse_dbref(ship->objnum, "SHIPOBJ");
  if (!RealGoodObject(obj))
  {
    notify(player, "This ship can not be disembarked.");
    return;
  }
  
  /* check whether we're docking or landing, save the new space object */
  if (ship->landed)
  {
    newobj = ship->landed->objnum;
  }
  else if (ship->docked)
  {
    newobj = ship->docked->objnum;
  }
  else if (ship->linked)
  {
    newobj = ship->linked->objnum;
  } else {
    notify(player, "You can't disembark while in space.");
    return;
  }
  
  if (ship->linked)
  {
    /* check the boarding code, if necessary */
    security = atr_parse_integer(ship->linked->objnum, "SECURITY", 0);
    if (security)
    {
      notify(player, "Unable to use boarding link while the other ship has security enabled.");
      return;
    }
    
    security = atr_parse_integer(ship->objnum, "SECURITY", 0);
    if (security)
    {
      notify(player, "Unable to use boarding link while security is enabled.");
      return;
    }
    
    obj = atr_parse_dbref(ship->linked->objnum, "BAY");
    if (!RealGoodObject(obj))
      obj = Location(ship->linked->objnum);
      
    moveto(player, obj, hs_options.space_wiz, NULL);
  } else {
    moveto(player, Location(obj), hs_options.space_wiz, NULL);
  }
  
  /* finish up by setting HSPACE attribute and notifying everybody about the move */
  atr_add(player, "HSPACE", unparse_dbref(newobj), hs_options.space_wiz, 0);
  notify_except(obj, Location(player), player, tprintf("%s disembarks through the main hatch.", Name(player)), 0);
  notify_except(obj, Location(obj), player, tprintf("%s disembarks from the %s.", Name(player), Name(obj)), 0);
  
  return;
}
Example #14
0
/* send a standard radio communication */
void send_com(dbref from, char *arg_left, char *arg_right)
{
  dbref com, obj;
  hship *ship;
  hcelestial *cel;
  huniverse *uid;
  
  double xmit, rcv;
  char contact[32];
  char *r, *s;
  char buff[128];
  ATTR *a;
  double sx, sy, sz, tx, ty, tz, dist;
  char pre[128];
  char *mesg;
  int sent_to_from, send_to_com;
  
  if (!IsComm(from))
  {
    notify(from, "You do not have the HS_COMM flag.");
    return;
  }
  
  uid = NULL;
  obj = atr_parse_dbref(from, "HSPACE");
  if (!RealGoodObject(obj))
  {
    notify(from, "You do not have a valid space id. Board, disembark, eject, or man a console.");
    return;
  }
  
  if (IsShip(obj))
  {
    ship = find_ship_by_nav(obj);
    if (!ship)
    {
      notify(from, "Your space id is not a valid ship.");
      return;
    }
    
    if (ship->uid)
    {
      sx = ship->x;
      sy = ship->y;
      sz = ship->z;
      uid = ship->uid;
    }
    else if (ship->landed)
    {
      sx = ship->landed->x;
      sy = ship->landed->y;
      sz = ship->landed->z;
      uid = ship->landed->uid;
    }
    else if (ship->docked)
    {
      sx = ship->docked->x;
      sy = ship->docked->y;
      sz = ship->docked->z;
      uid = ship->docked->uid;
    }
    
    strncpy(contact, ship_name(ship), 10);
  }
  else if (IsCelestial(obj))
  {
    cel = find_celestial(obj);
    if (!cel)
    {
      notify(from, "Your space id is not a valid celestial.");
      return;
    }
    
    sx = cel->x;
    sy = cel->y;
    sz = cel->z;
    uid = cel->uid;

    strncpy(contact, celestial_name(cel), 10);
  }
  contact[10] = '\0';
  
  if (!uid)
  {
    notify(from, "Your space id does not have a valid uid.");
    return;
  }
  
  if (arg_left && arg_right && *arg_right)
  {
    xmit = strtod(arg_left, &s);
    
    if (s && *s)
    {
      return;
    }
    mesg = arg_right;
  } else {
    xmit = atr_parse_double(from, "TRANSMIT", 0.0);
    mesg = arg_left;
  }
  if (xmit < 100.0 || xmit > 999.9)
  {
    notify(from, "Transmission frequency must be between 100 and 999 MHz.");
    return;
  }
  
  a = atr_get(from, "CALLSIGN");
  if (!a)
  {
    snprintf(pre, 127,
         "%s%s[%s%5.1f MHz%s%s]-[%s%-10s%s]-[%s ",
         ANSI_HILITE, ANSI_BLUE, ANSI_NORMAL, xmit, ANSI_HILITE, ANSI_BLUE, ANSI_GREEN, contact,
         ANSI_BLUE, ANSI_NORMAL);
  }
  else
  {
    snprintf(pre, 127,
         "%s%s[%s%5.1f MHz%s%s]-[%s%-10s%s]-[%s %s<%s%s%s>%s ",
         ANSI_HILITE, ANSI_BLUE, ANSI_NORMAL, xmit, ANSI_HILITE, ANSI_BLUE, ANSI_GREEN, contact,
         ANSI_BLUE, ANSI_NORMAL, ANSI_CYAN, ANSI_NORMAL, atr_value(a), ANSI_CYAN, ANSI_NORMAL);
  }

  /* go through the comm list and check each one */
  sent_to_from = 0;
  for (com = 0; com < db_top; com++)
  {
    if (!IsComm(com))
      continue;
    
    /* check if the user is in the same uid */
    obj = atr_parse_dbref(com, "HSPACE");
    if (IsShip(obj))
    {
      ship = find_ship_by_nav(obj);
      if (!ship)
        continue;
      
      if (ship->uid && ship->uid != uid)
        continue;
      else if (ship->landed && ship->landed->uid != uid)
        continue;
      else if (ship->docked && ship->docked->uid != uid)
        continue;
      
      if (ship->uid)
      {
        tx = ship->x;
        ty = ship->y;
        tz = ship->z;
      }
      else if (ship->landed)
      {
        tx = ship->landed->x;
        ty = ship->landed->y;
        tz = ship->landed->z;
      }
      else if (ship->docked)
      {
        tx = ship->docked->x;
        ty = ship->docked->y;
        tz = ship->docked->z;
      }
    }
    else if (IsCelestial(obj))
    {
      cel = find_celestial(obj);
      if (!cel)
        continue;
      
      if (cel->uid != uid)
        continue;
      
      tx = cel->x;
      ty = cel->y;
      tz = cel->z;
    } else {
      continue;
    }
    
    dist = dist3d(sx, sy, sz, tx, ty, tz) / hs_options.max_comm_dist;
    if (dist > 1.0)
      continue;

    a = atr_get(com, "FREQUENCY");
    if (!a)
      continue;
    
    /* check all frequencies to see if we need to send to this com */
    send_to_com = 0;
    snprintf(buff, 127, atr_value(a));
    s = buff;
    while (s)
    {
      r = split_token(&s, ' ');
      rcv = parse_number(r);
      
      /* check to see if we're on the right frequency */
      if (fabs(rcv - xmit) < 0.1)
      {
        send_to_com = 1;
        break;
      }
    }
    
    if (send_to_com)
    {
      if (com == from)
        sent_to_from = 1;
      
      notify_format(com, "%s%s%s%s]%s", pre, decay_msg(mesg, dist), ANSI_HILITE, ANSI_BLUE, ANSI_NORMAL);
    }
  }
  
  if (!sent_to_from)
  {
    notify_format(from, "You send \"%s\" on frequency %5.1f.", mesg, xmit);
  }
}
Example #15
0
static int
grep_helper(dbref player, dbref thing __attribute__ ((__unused__)),
            dbref parent __attribute__ ((__unused__)),
            char const *pattern
            __attribute__ ((__unused__)), ATTR *attr, void *args)
{
  struct grep_data *gd = args;
  char *s;
  char buff[BUFFER_LEN];
  char *bp = buff;
  int matched = 0;
  int cs;
  ansi_string *aval = NULL, *repl = NULL;

  cs = ((gd->flags & GREP_NOCASE) == 0);
  s = atr_value(attr);

  if (gd->flags & GREP_WILD) {
    if ((matched = quick_wild_new(gd->findstr, s, cs))) {
      /* Since, in order for a wildcard match to succeed, the _entire
         attribute_ value had to match the pattern, not just a substring,
         highlighting is totally pointless */
      strcpy(buff, s);
    }
  } else {
    aval = parse_ansi_string(s);
    s = aval->text;
    repl =
      parse_ansi_string(tprintf("%s%s%s", ANSI_HILITE, gd->findstr, ANSI_END));
    while (s && *s) {
      if (!
Example #16
0
/** Attempt to register a new player at the connect screen.
 * If registration is allowed, a new player object is created with
 * a random password which is emailed to the registering player.
 * \param name name of player to register.
 * \param email email address to send registration details.
 * \param host host from which registration is being attempted.
 * \param ip ip address from which registration is being attempted.
 * \return dbref of created player or NOTHING if creation failed.
 */
dbref
email_register_player(DESC *d, const char *name, const char *email,
                      const char *host, const char *ip)
{
  char *p;
  char passwd[20];
  static char elems[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  int i, len;
  bool resend = 0;
  dbref player = NOTHING;
  FILE *fp;
  size_t NELEMS = sizeof(elems) - 1;
  char sbuff[260];

  if (!check_fails(ip)) {
    return NOTHING;
  }

  if (strlen(options.sendmail_prog) == 0)
    return NOTHING;

  if (!ok_player_name(name, NOTHING, NOTHING)) {
    /* Check for re-registration request */
    player = lookup_player(name);
    if (GoodObject(player)) {
      ATTR *a;
      a = atr_get(player, "LASTLOGOUT");
      if (!a) {
        a = atr_get(player, "REGISTERED_EMAIL");
        if (a && !strcasecmp(atr_value(a), email))
          resend = 1;
      }
    }
    if (!resend) {
      do_log(LT_CONN, 0, 0, "Failed registration (bad name) from %s", host);
      queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                  d->descriptor, ip, mark_failed(ip), "register: bad name",
                  name);
      return NOTHING;
    }
  }
  if (!resend) {
    /* Make sure that the email address is kind of valid. A valid
     * address must contain a @. Let the mailer sort it out beyond
     * that.  Also, to prevent someone from using the MUSH to mailbomb
     * another site, let's make sure that the site to which the user
     * wants the email sent is also allowed to use the register
     * command.  If there's an @, we check whatever's after the last @
     * (since @foo.bar:user@host is a valid email).
     */
    if ((p = strrchr(email, '@'))) {
      p++;
      if (!Site_Can_Register(p)) {
        if (!Deny_Silent_Site(p, AMBIGUOUS)) {
          do_log(LT_CONN, 0, 0,
                 "Failed registration (bad site in email: %s) from %s", email,
                 host);
          queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                      d->descriptor, ip, mark_failed(ip),
                      "register: bad site in email", name);
        }
        return NOTHING;
      }
    } else {
      if (!Deny_Silent_Site(host, AMBIGUOUS)) {
        do_log(LT_CONN, 0, 0, "Failed registration (bad email: %s) from %s",
               email, host);
        queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                    d->descriptor, ip, mark_failed(ip),
                    "register: sitelocked host", name);
      }
      return NOTHING;
    }

    if (DBTOP_MAX && (db_top >= DBTOP_MAX + 1) && (first_free == NOTHING)) {
      /* Oops, out of db space! */
      do_log(LT_CONN, 0, 0, "Failed registration (no db space) from %s", host);
      queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                  d->descriptor, ip, count_failed(ip),
                  "register: no db space left to create!", name);
      return NOTHING;
    }
  }

  /* Come up with a random password of length 7-12 chars */
  len = get_random_u32(7, 12);
  for (i = 0; i < len; i++)
    passwd[i] = elems[get_random_u32(0, NELEMS - 1)];
  passwd[len] = '\0';

  /* If we've made it here, we can send the email and create the
   * character. Email first, since that's more likely to go bad.
   * Some security precautions we'll take:
   *  1) We'll use sendmail -t, so we don't pass user-given values to a shell.
   *  2) We'll cross our fingers and hope nobody uses this to spam.
   */

  release_fd();
  snprintf(sbuff, sizeof sbuff, "%s -t", options.sendmail_prog);
  if ((fp = popen(sbuff, "w")) == NULL) {
    do_log(LT_CONN, 0, 0,
           "Failed registration of %s by %s: unable to open sendmail", name,
           email);
    queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s,%d",
                d->descriptor, ip, count_failed(ip),
                "register: Unable to open sendmail!", name, 1);
    reserve_fd();
    return NOTHING;
  }
  fprintf(fp, "Subject: ");
  fprintf(fp, T("[%s] Registration of %s\n"), MUDNAME, name);
  fprintf(fp, "To: %s\n", email);
  fprintf(fp, "Precedence: junk\n");
  fprintf(fp, "\n");
  fprintf(fp, T("This is an automated message.\n"));
  fprintf(fp, "\n");
  fprintf(fp, T("Your requested player, %s, has been created.\n"), name);
  fprintf(fp, T("The password is %s\n"), passwd);
  fprintf(fp, "\n");
  fprintf(fp, T("To access this character, connect to %s and type:\n"),
          MUDNAME);
  fprintf(fp, "\tconnect \"%s\" %s\n", name, passwd);
  fprintf(fp, "\n");
  i = pclose(fp);
  reserve_fd();

  if (i != 0) {
    /* Mailer exited with an error code. Log it. */
    do_rawlog(
      LT_CONN,
      "When attempting to email a password to a newly registered player,\n"
      "\tthe mailer exited with error code %d.\n"
      "\t(Check /usr/include/sysexits.h if present for the meaning.)",
      i);
    queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s,%d",
                d->descriptor, ip, count_failed(ip),
                "register: Unable to send email", name, i);
    return NOTHING;
  } else if (resend) {
    /* Reset the password */
    (void) atr_add(player, pword_attr, password_hash(passwd, NULL), GOD, 0);
    return player;
  } else {
    /* Ok, all's well, make a player */
    player = make_player(name, passwd, host, ip);
    queue_event(SYSEVENT, "PLAYER`CREATE", "%s,%s,%s,%d,%s",
                unparse_objid(player), name, "register", d->descriptor, email);
    (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, 0);
    return player;
  }
}
Example #17
0
/** 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;
}
Example #18
0
/** Populate a ufun_attrib struct from an obj/attr pair.
 * \verbatim Given an attribute [<object>/]<name> pair (which may include #lambda),
 * fetch its value, owner (thing), and pe_flags, and store in the struct
 * pointed to by ufun
 * \endverbatim
 * \param attrstring The obj/name of attribute.
 * \param executor Dbref of the executing object.
 * \param ufun Pointer to an allocated ufun_attrib struct to fill in.
 * \param flags A bitwise or of desired UFUN_* flags.
 * \return 0 on failure, true on success.
 */
bool
fetch_ufun_attrib(const char *attrstring, dbref executor, ufun_attrib * ufun,
                  int flags)
{
  char *thingname, *attrname;
  char astring[BUFFER_LEN];
  ATTR *attrib;

  if (!ufun)
    return 0;

  ufun->contents[0] = '\0';
  ufun->errmess = (char *) "";
  ufun->thing = executor;
  ufun->pe_flags = PE_UDEFAULT;
  ufun->ufun_flags = flags;

  ufun->thing = executor;
  thingname = NULL;

  if (!attrstring)
    return 0;
  strncpy(astring, attrstring, BUFFER_LEN);

  /* Split obj/attr */
  if ((flags & UFUN_OBJECT) && ((attrname = strchr(astring, '/')) != NULL)) {
    thingname = astring;
    *(attrname++) = '\0';
  } else {
    attrname = astring;
  }

  if (thingname && (flags & UFUN_LAMBDA)
      && (strcasecmp(thingname, "#lambda") == 0
          || strncasecmp(thingname, "#apply", 6) == 0)) {
    /* It's a lambda. */

    ufun->ufun_flags &= ~UFUN_NAME;
    ufun->thing = executor;
    if (strcasecmp(thingname, "#lambda") == 0)
      mush_strncpy(ufun->contents, attrname, BUFFER_LEN);
    else {                      /* #apply */
      char *ucb = ufun->contents;
      unsigned nargs = 1, n;

      thingname += 6;

      if (*thingname)
        nargs = parse_uinteger(thingname);

      /* Limit between 1 and 10 arguments (%0-%9) */
      if (nargs == 0)
        nargs = 1;
      if (nargs > 10)
        nargs = 10;

      safe_str(attrname, ufun->contents, &ucb);
      safe_chr('(', ufun->contents, &ucb);
      for (n = 0; n < nargs; n++) {
        if (n > 0)
          safe_chr(',', ufun->contents, &ucb);
        safe_format(ufun->contents, &ucb, "%%%u", n);
      }
      safe_chr(')', ufun->contents, &ucb);
      *ucb = '\0';
    }

    ufun->attrname[0] = '\0';
    return 1;
  }

  if (thingname) {
    /* Attribute is on something else. */
    ufun->thing =
      noisy_match_result(executor, thingname, NOTYPE, MAT_EVERYTHING);
    if (!GoodObject(ufun->thing)) {
      ufun->errmess = (char *) "#-1 INVALID OBJECT";
      return 0;
    }
  }

  attrib = (ATTR *) atr_get(ufun->thing, upcasestr(attrname));
  if (attrib && AF_Internal(attrib)) {
    /* Regardless of whether we're doing permission checks, we should
     * never be showing internal attributes here */
    attrib = NULL;
  }

  /* An empty attrib is the same as no attrib. */
  if (attrib == NULL) {
    if (flags & UFUN_REQUIRE_ATTR) {
      if (!(flags & UFUN_IGNORE_PERMS) && !Can_Examine(executor, ufun->thing))
        ufun->errmess = e_atrperm;
      return 0;
    } else {
      mush_strncpy(ufun->attrname, attrname, ATTRIBUTE_NAME_LIMIT + 1);
      return 1;
    }
  }
  if (!(flags & UFUN_IGNORE_PERMS)
      && !Can_Read_Attr(executor, ufun->thing, attrib)) {
    ufun->errmess = e_atrperm;
    return 0;
  }
  if (!(flags & UFUN_IGNORE_PERMS)
      && !CanEvalAttr(executor, ufun->thing, attrib)) {
    ufun->errmess = e_perm;
    return 0;
  }

  /* DEBUG attributes */
  if (AF_NoDebug(attrib))
    ufun->pe_flags |= PE_NODEBUG;       /* No_Debug overrides Debug */
  else if (AF_Debug(attrib))
    ufun->pe_flags |= PE_DEBUG;

  if (flags & UFUN_NAME) {
    if (attrib->flags & AF_NONAME)
      ufun->ufun_flags &= ~UFUN_NAME;
    else if (attrib->flags & AF_NOSPACE)
      ufun->ufun_flags |= UFUN_NAME_NOSPACE;
  }

  /* Populate the ufun object */
  mush_strncpy(ufun->contents, atr_value(attrib), BUFFER_LEN);
  mush_strncpy(ufun->attrname, AL_NAME(attrib), ATTRIBUTE_NAME_LIMIT + 1);

  /* We're good */
  return 1;
}
Example #19
0
/** Check an attribute's value against /limit or /enum restrictions.
 * \param player Player attempting to set the attribute. Used for notify()
 * \param name the attribute name.
 * \param value The desired attribute value.
 * \retval The new value to set if valid, NULL if not.
 */
const char *
check_attr_value(dbref player, const char *name, const char *value)
{
  /* Check for attribute limits and enums. */
  ATTR *ap;
  char *attrval;
  pcre *re;
  int subpatterns;
  const char *errptr;
  int erroffset;
  char *ptr, *ptr2;
  char delim;
  int len;
  static char buff[BUFFER_LEN];
  char vbuff[BUFFER_LEN];

  if (!name || !*name)
    return value;
  if (!value)
    return value;

  upcasestr((char *) name);
  ap = (ATTR *) ptab_find_exact(&ptab_attrib, name);
  if (!ap)
    return value;

  attrval = atr_value(ap);
  if (!attrval) {
    return value;
  }

  if (ap->flags & AF_RLIMIT) {
    re = pcre_compile(remove_markup(attrval, NULL), PCRE_CASELESS,
                      &errptr, &erroffset, tables);
    if (!re)
      return value;

    subpatterns = pcre_exec(re, default_match_limit(), value, strlen(value),
                            0, 0, NULL, 0);
    free(re);

    if (subpatterns >= 0) {
      return value;
    } else {
      notify(player, T("Attribute value does not match the /limit regexp."));
      return NULL;
    }
  } else if (ap->flags & AF_ENUM) {
    /* Delimiter is always the first character of the enum string.
     * and the value cannot have the delimiter in it. */
    delim = *attrval;
    if (!*value || strchr(value, delim)) {
      notify_format(player,
                    T("Value for %s needs to be one of: %s"),
                    ap->name, display_attr_limit(ap));
      return NULL;
    }

    /* We match the enum case-insensitively, BUT we use the case
     * that is defined in the enum, so we copy the attr value
     * to buff and use that. */
    snprintf(buff, BUFFER_LEN, "%s", attrval);
    upcasestr(buff);

    len = strlen(value);
    snprintf(vbuff, BUFFER_LEN, "%c%s%c", delim, value, delim);
    upcasestr(vbuff);

    ptr = strstr(buff, vbuff);
    if (!ptr) {
      *(vbuff + len + 1) = '\0';        /* Remove the second delim */
      ptr = strstr(buff, vbuff);
    }

    /* Do we have a match? */
    if (ptr) {
      /* ptr is pointing at the delim before the value. */
      ptr++;
      ptr2 = strchr(ptr, delim);
      if (!ptr2)
        return NULL;            /* Shouldn't happen, but sanity check. */

      /* Now we need to copy over the _original case_ version of the
       * enumerated string. Nasty pointer arithmetic. */
      strncpy(buff, attrval + (ptr - buff), (int) (ptr2 - ptr));
      buff[ptr2 - ptr] = '\0';
      return buff;
    } else {
      notify_format(player,
                    T("Value for %s needs to be one of: %s"),
                    ap->name, display_attr_limit(ap));
      return NULL;
    }
  }
  return value;
}