muse1.7b4/
muse1.7b4/config/
muse1.7b4/doc/
muse1.7b4/run/
muse1.7b4/run/db/
muse1.7b4/src/
muse1.7b4/src/db/
muse1.7b4/src/files/
muse1.7b4/src/io/
muse1.7b4/src/prog/
muse1.7b4/src/util/
/* set.c */
/* $Id: set.c,v 1.23 1994/01/26 22:28:27 nils Exp $ */

/* commands which set parameters */
#include <stdio.h>
#include <ctype.h>

#include "db.h"
#include "config.h"
#include "match.h"
#include "interface.h"
#include "externs.h"
#include "credits.h"

#ifdef NOCRYPT
char *crypt(s)
     char *s;
{
  return(s);
}
#endif


#ifdef DESTROY
void do_destroy(player,name)
     dbref player;
     char *name;
{
  dbref thing;
  
  if (controls(player,db[player].location,POW_MODIFY))
    init_match(player, name, NOTYPE);
  else
    init_match (player, name, TYPE_THING);
  
  if (controls(player,db[player].location,POW_MODIFY)) {
    match_exit();
  }
  
  match_everything();
  thing=match_result();
  if ( (thing != NOTHING) && (thing!=AMBIGUOUS) &&
      ! controls(player,thing,POW_MODIFY) &&
      ! ( Typeof(thing) == TYPE_THING &&
	 (db[thing].flags & THING_DEST_OK) ) ) {
    notify(player,"Permission denied.");
    return;
  }

  if (db[thing].children && (*db[thing].children) != NOTHING)
    notify (player,"Warning: It has children.");
  
  if (thing<0) { /* I hope no wizard is this stupid but just in case */
    notify(player,"I don't know what that is, sorry.");
    return;
  }
  if(thing == 0 || thing == 1 || thing == PLAYER_START || thing == GOD) {
    notify(player,"Don't you think that's sorta an odd thing to destroy?");
    return;
  }
  /* what kind of thing we are destroying? */
  switch(Typeof(thing)) {
  case TYPE_PLAYER:
    notify(player,"destroying players isn't allowed, try a @nuke instead.");
    return;
  case TYPE_THING:
  case TYPE_ROOM:
  case TYPE_EXIT: {
    char *k;
    
    k = atr_get(thing, A_DOOMSDAY);
    if (*k)
      if (db[thing].flags & GOING) {
	notify(player,tprintf("It seems it's already gunna go away in %s... if you wanna stop it, use @undestroy", time_format_2(atol(k)-time(NULL))));
	return;
      } else {
	notify(player,"Sorry, it's protected.");
      }
    else
      if (db[thing].flags & GOING) {
	notify(player,"It seems to already be destroyed.");
	return;
      } else {
	k = atr_get (player, A_DOOMSDAY);
	if (*k) {
	  destroy_obj (thing, atoi(k));
	  notify(player,tprintf("Okay, %s will go away in %s.", unparse_object (player, thing), time_format_2(atoi(k))));
	} else {
	  destroy_obj (thing, atoi(DEFAULT_DOOMSDAY));
	  notify(player, tprintf("Okay, %s will go away in %s.", unparse_object(player, thing), time_format_2(atoi(DEFAULT_DOOMSDAY))));
	}
      }
  }
  }
}

void destroy_obj (obj, no_seconds)
     dbref obj;
     int no_seconds;
{
  if (!(db[obj].flags&QUIET))
    do_pose(obj, "shakes and starts to crumble", "", 0);
  atr_add (obj, A_DOOMSDAY, int_to_str (no_seconds + time(NULL)));
  db[obj].flags |= GOING;
  do_halt (obj, "");
}
#endif /* DESTROY */

void do_name(player,name,newname, is_direct)
     dbref player;
     char *name;
     char *newname;
     int is_direct;
{
  dbref thing;
  char *password;
  
  if((thing = match_controlled(player, name,POW_MODIFY)) != NOTHING) {
    /* check for bad name */
    if(*newname == '\0') {
      notify(player, "Give it what new name?");
      return;
    }
    
    /* check for renaming a player */
    if(Typeof(thing) == TYPE_PLAYER) {
      if (!is_direct) {
	notify(player,"sorry, players must change their names directly from a net connection.");
	return;
      }
      if ( player == thing && ! power(player, POW_MEMBER))  {
	notify(player, tprintf(
			       "Sorry, only registered %s users may change their name.",
			       MUSE_NAME));
	return;
      }
      
      /* split off password */
      for(password = newname;
	  *password && !isspace(*password); password++)
	;
      
      /* eat whitespace */
      if(*password) {
	*password++ = '\0';	/* terminate name */
	while ( *password && isspace(*password) )
	  password++;
      }
      
      /* check for reserved player names */
      if ( string_prefix(newname, "guest") )  {
	notify(player, tprintf(
			       "Only guests may have names beginning with '%s'",
			       "guest"));
	return;
      }
      
      /* check for null password */
      if(!*password) {
	notify(player,
	       "You must specify a password to change a player name.");
	notify(player, "E.g.: name player = newname password");
	return;
      } else if ( *Pass(player) && strcmp(Pass(player), password) &&
		 strcmp(crypt(password, "XX"), Pass(player)) ) {
	notify(player, "Incorrect password.");
	return;
      } else if( ! ok_player_name(newname) &&
		string_compare(newname, db[player].name) ) {
	/* string_compare allows changing foo to Foo, etc. */
	notify(player, "You can't give a player that name.");
	return;
      }
      
      /* everything ok, notify */
      log_important(tprintf("NAME CHANGE: %s(#%d) to %s",
			    db[thing].name, thing, newname));
      notify_in(db[thing].location,thing,tprintf("%s is now known as %s.",db[thing].name,newname));
      delete_player(thing);
      SET(db[thing].name,newname);
      add_player(thing);
      notify(player, "Name set.");
      return;
    }

    /* we're an object. */

    if( ! ok_object_name(thing, newname) ) {
      notify(player, "That is not a reasonable name.");
      return;
    }
    
    /* everything ok, change the name */
    if(Hearer(thing))
      notify_in(db[thing].location,thing,tprintf("%s is now known as %s.",db[thing].name,newname));
    SET(db[thing].name,newname);
    check_spoofobj (player, thing);
    notify(player, "Name set.");
  }
}

void do_describe(player,name,description)
     dbref player;
 char *name;
 char *description;
{
  dbref thing;
  
  if((thing = match_controlled(player, name,POW_MODIFY)) != NOTHING) {
    s_Desc(thing,description);
    notify(player, "Description set.");
  }
}

void do_fail(player,name,message)
     dbref player;
 char *name;
 char *message;
{
  dbref thing;
  
  if((thing = match_controlled(player, name,POW_MODIFY)) != NOTHING) {
    s_Fail(thing,message);
    notify(player, "Message set.");
  }
}

void do_success(player,name,message)
     dbref player;
 char *name;
 char *message;
{
  dbref thing;
  
  if((thing = match_controlled(player, name,POW_MODIFY)) != NOTHING) {
    s_Succ(thing,message);
    notify(player, "Message set.");
  }
}

void do_osuccess(player,name,message)
     dbref player;
 char *name;
 char *message;
{
  dbref thing;
  
  if((thing = match_controlled(player, name,POW_MODIFY)) != NOTHING) {
    s_Osucc(thing,message);
    notify(player, "Message set.");
  }
}

void do_ofail(player,name,message)
     dbref player;
 char *name;
 char *message;
{
  dbref thing;
  
  if((thing = match_controlled(player, name,POW_MODIFY)) != NOTHING) {
    s_Ofail(thing,message);
    notify(player, "Message set.");
  }
}

/* void do_lock(player,name,keyname)
     dbref player;
 char *name;
 char *keyname;
{
  dbref thing;
  struct boolexp *key;
  
  init_match(player, name, NOTYPE);
  match_everything();
  
  switch(thing = match_result()) {
  case NOTHING:
    notify(player, "I don't see what you want to lock!");
    return;
  case AMBIGUOUS:
    notify(player, "I don't know which one you want to lock!");
    return;
  default:
    if(!controls(player, thing, POW_MODIFY)) {
      notify(player, "You can't lock that!");
      return;
    }
    break;
  }
  
  key = parse_boolexp(player, keyname, thing);
  if(key == TRUE_BOOLEXP) {
    notify(player, "I don't understand that key.");
  } else {
    * everything ok, do it *
    free_boolexp(db[thing].key);
    db[thing].key = key;
    notify(player, "Locked.");
  }
}


void do_unlock(player,name)
     dbref player;
 char *name;
{
  dbref thing;
  
  if((thing = match_controlled(player, name, POW_MODIFY)) != NOTHING) {
    free_boolexp(db[thing].key);
    db[thing].key = TRUE_BOOLEXP;
    notify(player, "Unlocked.");
  }
}
*/

void do_unlink(player,name)
     dbref player;
 char *name;
{
  dbref exit;
  
  init_match(player, name, TYPE_EXIT);
  match_exit();
  match_here();
  if(power(player, POW_REMOTE)) {
    match_absolute();
  }
  
  switch(exit = match_result()) {
  case NOTHING:
    notify(player, "Unlink what?");
    break;
  case AMBIGUOUS:
    notify(player, "I don't know which one you mean!");
    break;
  default:
    if(!controls(player, exit, POW_MODIFY)) {
      notify(player, "Permission denied.");
    } else {
      switch(Typeof(exit)) {
      case TYPE_EXIT:
	db[exit].link = NOTHING;
	notify(player, "Unlinked.");
	break;
      case TYPE_ROOM:
	db[exit].link = NOTHING;
	notify(player, "Dropto removed.");
	break;
      default:
	notify(player, "You can't unlink that!");
	break;
      }
    }
  }
}

void do_chown(player,name,newobj)
     dbref player;
     char *name;
     char *newobj;
{
  dbref thing;
  dbref owner;
  
  log_sensitive(tprintf("Player %s(#%d) attempts: @chown %s=%s",
			db[player].name, player, name, newobj));
  
  init_match(player, name, TYPE_THING);
  match_possession();
  match_here();
  match_exit();
  match_absolute();
  switch(thing = match_result()) {
  case NOTHING:
    notify(player, "You don't have that!");
    return;
  case AMBIGUOUS:
    notify(player, "I don't know which you mean!");
    return;
  }
  if(!*newobj || !string_compare(newobj,"me"))
    owner = def_owner(player); /* @chown thing or @chown thing=me */
  else
    if((owner = lookup_player(newobj)) == NOTHING)
      notify(player, "I couldn't find that player.");
  if (power(player,POW_SECURITY)) {
    if (Typeof(thing)==TYPE_PLAYER && db[thing].owner != thing)
      db[thing].owner = thing;
  }
  if(owner==NOTHING); /* for the else */
  /* if non-robot player */
  else if( (db[thing].owner == thing && Typeof(thing) == TYPE_PLAYER) && !power(player, POW_SECURITY))
    notify(player, "Players always own themselves.");
  
  else if (! controls(player, owner, POW_CHOWN) ||
	   ( ! controls(player, thing, POW_CHOWN) &&
	    ( ! (db[thing].flags & CHOWN_OK) ||
	     ( (Typeof(thing) == TYPE_THING) &&
	      (db[thing].location != player && !power(player,POW_CHOWN)) ) )))
    notify(player, "Permission denied.");
  
  else  {
    if ( power(player, POW_CHOWN) )  {
      /* adjust quotas */
      add_quota(db[thing].owner, QUOTA_COST);
      sub_quota(db[owner].owner, QUOTA_COST);
      /* adjust credits */
      payfor(player, OBJECT_COST);
      giveto(db[thing].owner, OBJECT_COST);
    }
    else  {
      if ( Pennies(db[player].owner) < OBJECT_COST )  {
	notify(player,"You don't have enough money.");
	return;
      }
      /* adjust quotas */
      if ( ! pay_quota(owner, QUOTA_COST) )  {
	notify(player, (player == owner) ?
	       "Your quota has run out." : "Nothing happens.");
	return;
      }
      add_quota(db[thing].owner, QUOTA_COST);
      /* adjust credits */
      payfor(player, OBJECT_COST);
      giveto(db[thing].owner, OBJECT_COST);
    }
    
    log_sensitive(tprintf("Player %s(%d) succeeds with: @chown %s=%s",db[player].name, player, unparse_object_a(thing,thing), unparse_object_a(owner,owner)));
    
    if (db[thing].flags&CHOWN_OK) {
      db[thing].flags |= HAVEN;
      db[thing].flags &= ~CHOWN_OK;
      db[thing].flags &= ~INHERIT_POWERS;
    }
    db[thing].owner = db[owner].owner;
    notify(player, "Owner changed.");
  }
}

static struct hearing {
  dbref obj;
  int did_hear;
  struct hearing *next;
} *hearing_list=NULL;

void mark_hearing(obj)
     dbref obj;
{
  int i;
  struct hearing *mine;

  mine = malloc (sizeof (struct hearing));
  mine->next = hearing_list;
  mine->did_hear = Hearer(obj);
  mine->obj = obj;

  hearing_list = mine;
  for (i=0; db[obj].children && db[obj].children[i] != NOTHING; i++) {
    mark_hearing(db[obj].children[i]);
  }
}

void check_hearing()
{
  struct hearing *mine;
  int now_hear;
  dbref obj;
  
  while (hearing_list) {
    mine = hearing_list;
    hearing_list = hearing_list->next;

    obj = mine->obj;
    now_hear = Hearer(mine->obj);

    if (now_hear && !mine->did_hear)
      notify_in(db[obj].location,obj,
		tprintf("%s grows ears and can now hear.",db[obj].name));
    if (mine->did_hear && !now_hear)
      notify_in(db[obj].location,obj,
		tprintf("%s loses its ears and is now deaf.",db[obj].name));
    free(mine);
  }
}

void do_unlock(player,name)
     dbref player;
     char *name;
{
  dbref thing;
  ATTR *attr = A_LOCK;

  if((thing = match_controlled(player, name, POW_MODIFY)) == NOTHING)
    return;
  if ( thing == GOD && player != GOD )  {
    notify(player,"Not likely.");
    return;
  }
  atr_add(thing, attr, "");
  notify(player, "Unlocked.");
}
  extern NALLOC *glurp;

void do_set(player,name,flag, allow_commands)
     dbref player;
     char *name;
     char *flag;
     int allow_commands;
{
  dbref thing;
  char *p, *q;
  object_flag_type f;
  int her;
  char buff[1024];
  
  /* find thing */
  if((thing = match_thing(player, name)) == NOTHING)
    return;
  if ( thing == GOD && player != GOD )  {
    notify(player,"Only God can set him/herself!");
    return;
  }
  
  her = Hearer(thing);

  /* check for attribute set first */
  for( p = flag; *p && (*p != ':'); p++ )
    ;
  if ( *p ) {
    ATTR *attr;

    *p++='\0';
    /* check for _ */
    if ( *p=='_' ) {
      dbref newthing;
      ATTR *newatr;
      
      strcpy(buff, p+1);
      if ( !parse_attrib(player, p+1, &newthing, &newatr, 0) ) {
	notify(player,"No match.");
	return;
      }
      if (!can_set_atr (player, newthing, newatr)) {
	notify(player,"Can't copy that attribute.");
	return;
      }
      strcpy(p=buff,atr_get(newthing,newatr));
    }
    if ( ! (attr = atr_str(player, thing, flag)) ) {
      notify(player,"Sorry that isn't a valid attribute.");
      return;
    }
    /* if ( (attr->flags & AF_WIZARD) && !((attr->obj == NOTHING)?power(player, POW_WATTR):controls(player,attr->obj,POW_WATTR))) {
      notify(player,"Sorry only Administrators can change that.");
      return;
    } */
    if (!can_set_atr(player, thing, attr)) {
      notify(player, "You can't set that attribute.");
      return;
    }
    if(attr==A_ALIAS && Typeof(thing)!=TYPE_PLAYER) {
      notify(player,"Sorry only players can have aliases.");
      return;
    }
    if(attr==A_ALIAS && !ok_player_name(p) && *p) {
      notify(player,"There is already someone with that alias.");
      return;
    }
    if(attr->flags & AF_LOCK) {
      if ((q = process_lock(player,p))) {
	db[thing].mod_time = time(NULL);
	atr_add(thing, attr, q);
	if (*q) notify(player, "Locked.");
	else notify(player, "Unlocked.");
      }
      return;
    }
    if(attr==A_ALIAS) delete_player(thing);
    mark_hearing(thing);
    if (!allow_commands && (*p == '!' || *p == '$')) {
      /* urgh. fix it. */
      char *x;
      x = na_alloc(glurp,strlen(p)+2);
      strcpy(x,"_");
      strcat(x,p);
      p = x;
    }
    db[thing].mod_time = time(NULL);
    atr_add(thing, attr,p);
    if(attr==A_ALIAS) add_player(thing);
    if(!(db[player].flags&QUIET))
      notify(player, tprintf("%s - Set.",db[thing].name));
    check_hearing();
    return;
  }
  
  /* move p past NOT_TOKEN if present */
  for( p = flag; *p && (*p == NOT_TOKEN || isspace(*p)); p++)
    ;
  
  /* identify flag */
  if(*p == '\0') {
    notify(player, "You must specify a flag to set.");
    return;
  }

  f=0;
  switch(Typeof(thing)) {
  case TYPE_THING:
    if ( string_prefix("KEY",p) )
      f=THING_KEY;
    if ( string_prefix("DESTROY_OK",p) )
      f=THING_DEST_OK;
    if ( string_prefix("LIGHT",p) )
      f=THING_LIGHT;
    /*	if ( string_prefix("ROBOT",p) )
	f=THING_ROBOT; */
    if ( string_prefix("X_OK",p) )
      f=THING_SACROK;
    break;
  case TYPE_PLAYER:
    if ( string_prefix("NEWBIE",p) || string_prefix("NOVICE",p) )
      f=PLAYER_NEWBIE;
    if ( string_prefix("SLAVE",p) )
      f=PLAYER_SLAVE;
    if ( string_prefix("TERSE",p) )
      f=PLAYER_TERSE;
    if ( string_prefix("MORTAL",p) )
      f=PLAYER_MORTAL;
    if ( string_prefix("NO_WALLS",p) )
      f=PLAYER_NO_WALLS;
    break;
  case TYPE_ROOM:
    if ( string_prefix("TEMPLE",p) )
      f=ROOM_TEMPLE;
    if ( string_prefix("ABODE",p) )
      f=ROOM_JUMP_OK;
    if ( string_prefix("AUDITORIUM",p) )
      f=ROOM_AUDITORIUM;
    if ( string_prefix("JUMP_OK", p) )
      f = ROOM_JUMP_OK;
    if ( string_prefix("FLOATING", p) )
      f = ROOM_FLOATING;
#ifdef USE_SPACE
    if ( string_prefix("ZEROG", p) )
      f = ROOM_ZEROG;
#endif
    break;
  case TYPE_EXIT:
    if ( string_prefix("LIGHT",p) )
      f=EXIT_LIGHT;
    if (string_prefix("TRANSPARENT",p))
      f = OPAQUE;
    break;
  }
  if ( ! f ) {
#ifdef DESTROY
    if ( string_prefix("GOING",p) ) {
      if (player != GOD || Typeof(thing)==TYPE_PLAYER) {
	notify(player, "I think the @[un]destroy command is more what you're looking for.");
	return;
      } else {
	notify(player, "I hope you know what you're doing.");
	f = GOING;
      }
    } else
#endif /* DESTROY */
      if (string_prefix ("BEARING", p))
	f = BEARING;
      else if( string_prefix("LINK_OK", p) )
	f = LINK_OK;
      else if ( string_prefix("QUIET",p) )
	f=QUIET;
      else if( string_prefix("DARK", p) )
	f = DARK;
      else if( string_prefix("DEBUG", p) )
	f = DARK;
      else if( string_prefix("STICKY", p) )
	f = STICKY;
      else if( string_prefix("PUPPET",p) )
	f = PUPPET;
      else if ( string_prefix("INHERIT",p) )
	f = INHERIT_POWERS;
      else if( string_prefix("ENTER_OK",p) )
	f = ENTER_OK;
      else if( string_prefix("CHOWN_OK",p) )
	f = CHOWN_OK;
      else if( string_prefix("SEE_OK",p) ) {
	notify(player,"Warning: the see_ok flag has been renamed to 'visible'");
	f = SEE_OK;
      }
      else if( string_prefix("VISIBLE",p) )
	f = SEE_OK;
    /*      else if( string_prefix("UNIVERSAL",p) )
	    f = UNIVERSAL;*/
      else if( string_prefix("OPAQUE",p) )
	f = OPAQUE;
      else if( string_prefix("HAVEN", p) || string_prefix("HALTED",p) )
	f = HAVEN;
      else {
	notify(player, "I don't recognize that flag.");
	return;
      }
  }
  
  if (f == BEARING && *flag == NOT_TOKEN) {
    int i;
    for (i=0; db[thing].children && db[thing].children[i]!=NOTHING; i++)
      if (db[db[thing].children[i]].owner != db[player].owner)
	if (!controls (player, db[thing].children[i], POW_MODIFY)) {
	  notify (player,
		  tprintf ("Sorry, you don't control its child, %s.",
			   unparse_object (player,db[thing].children[i])));
	  return;
	} else
	  if (db[db[thing].children[i]].owner != db[thing].owner)
	    notify (player,
		    tprintf ("Warning: you are locking in %s as a child.",
			     unparse_object (player, db[thing].children[i])));
  }
  /* check for restricted flag */
  if (f == HAVEN && *flag == NOT_TOKEN) {
    dbref p;
    p = starts_with_player(db[thing].name);
    if (p != NOTHING && !controls(player,p,POW_SPOOF)) {
      notify(player,"Sorry, a player holds that name.");
      return;
    }
  }
  if ( ! power(player, POW_WFLAGS) )  {
    switch(Typeof(thing)) {
    case TYPE_ROOM:
      if (f==ROOM_TEMPLE) {
	notify(player,"permission denied.");
	return;
      }
      break;
    }
  }
#ifdef USE_SPACE  /* Flag added by Eric Wallace */
  /* check for POW_SPACE for ROOM_ZEROG */
  if ( ! power(player, POW_SPACE) ) {
    switch(Typeof(thing)) {
    case TYPE_ROOM:
      if (f==ROOM_ZEROG) {
        notify(player,"permission denied.");
	return;
      }
      break;
    }
  }
#endif
  if ( Typeof(thing)==TYPE_PLAYER && f == PLAYER_SLAVE ) {
    if (!controls(player, thing, POW_SLAVE) || db[player].owner == thing) {
      notify(player,"You can't enslave/unslave that!");
      return;
    }
    log_sensitive(tprintf("%s(#%d) %sslaved %s", db[player].name, player,
			  (*flag == NOT_TOKEN) ? "un" : "en", unparse_object(thing, thing)));
  } else
    if (!controls (player, thing, POW_MODIFY)) {
      notify (player, "Permission denied! yay!");
      return;
    }
  if((Typeof(player)!=TYPE_PLAYER || !controls(player,thing,POW_SECURITY))
     && f == INHERIT_POWERS) {
    notify(player,"Sorry, you cannot do that.");
    return;
  }
  /* else everything is ok, do the set */
  if( *flag == NOT_TOKEN ) {
    /* reset the flag */
    db[thing].flags &= ~f;
    notify(player, "Flag reset.");
    if ( (f == PUPPET) && her && !Hearer(thing))
      notify_in(db[thing].location,thing,tprintf
		    ("%s loses its ears and becomes deaf.",db[thing].name));
  } else {
    /* set the flag */
    db[thing].flags |= f;
    if ( (f == PUPPET) && !her ) {
      char *buff;
      
      buff = tprintf("%s grows ears and can now hear.",
		     db[thing].name);
      notify_in(db[thing].location,thing,buff);
    }
    notify(player, "Flag set.");
  }
}


/* check for abbreviated set command */
int test_set(player,command,arg1,arg2, is_direct)
     dbref player;
     char *command;
     char *arg1;
     char *arg2;
     int is_direct;
{
  extern ATTR *builtin_atr_str P((char *));
  ATTR *a;
  char buff[2000];
  
  if (command[0]!='@')
    return(0);
  if (!(a=builtin_atr_str (command+1))) {
    init_match (player, arg1, NOTYPE);
    match_everything();
    if (match_result()!=NOTHING && match_result()!=AMBIGUOUS) {
      a=atr_str (player,match_result(), command+1);
      if (a) {
	sprintf (buff, "%s:%s",command+1,arg2);
	do_set (player, arg1, buff, is_direct);
	return(1);
      }
    }
  } else
    if (!(a->flags & AF_NOMOD)) {
      sprintf (buff,"%s:%s",command+1,arg2);
      do_set (player, arg1, buff, is_direct);
      return 1;
    }
  return(0);
}

int parse_attrib(player,s,thing,atr,withpow)
     dbref player;
     char *s;
     dbref *thing;
     ATTR **atr;
     int withpow;
{
  char buff[1024];
  strcpy(buff,s);
  /* get name up to / */
  for(s=buff;*s && (*s!='/');s++);
  if (!*s)
    return(0);
  *s++=0;
  if (withpow != 0) {
    if ((*thing=match_controlled(player,buff,withpow))==NOTHING)
      return 0;
  } else {
    init_match (player, buff, NOTYPE);
    match_everything();
    if ((*thing=match_result())==NOTHING)
      return 0;
  }

  /* rest is attrib name */
  if (!((*atr)=atr_str(player, *thing, s)))
    return(0);
  if (withpow != 0)
    if (((*atr)->flags & AF_DARK) ||
	(!controls(player,*thing,POW_SEEATR) && !((*atr)->flags & AF_OSEE)))
    return(0);
  return(1);
}

void do_edit(player,it,argv)
     dbref player;
     char *it;
     char *argv[];
{
  dbref thing;
  int d,len;
  char *r,*s,*val;
  char dest[1024];
  ATTR *attr;
  
  if (!parse_attrib(player,it,&thing,&attr,POW_MODIFY)) {
    notify(player,"No match.");
    return;
  }
  if(!attr) {
    notify(player,"Gack! Don't do that. it makes me uncomfortable.");
    return;
  }
  if((attr->flags&AF_WIZARD) && !power(player,POW_WATTR)) {
    notify(player,"Eeg! Tryin to edit a admin-only prop? hrm. don't do it.");
    return;
  }
#ifdef USE_SPACE  /*  Check added by Michael Majere  */
  if((attr->flags&AF_SPACE) && !power(player,POW_SPACE)) {
    notify(player, "Only an Overlord of time and space can do that.");
    return;
  }
#endif
  if (!controls(player,thing,POW_MODIFY)) {
    notify(player,"permission denied.");
    return;
  }
  if(attr==A_ALIAS) {
    notify(player,"To set an alias, do @alias me=<new alias>. Don't use @edit.");
    return;
  }
  if (!argv[1] || !*argv[1]) {
    notify(player,"Nothing to do.");
    return;
  }
  val=argv[1];
  r=(argv[2]) ? argv[2] : "";
  /* replace all occurances of val with r */
  s=atr_get(thing,attr);
  len=strlen(val);
  for(d=0;(d<1000) && *s;)
    if (strncmp(val,s,len)==0) {
      if ((d+strlen(r))<1000) {
	strcpy(dest+d,r);
	d+=strlen(r);
	s+=len;
      } else
	dest[d++]= *s++;
    } else
      dest[d++]= *s++;
  dest[d++]=0;
  atr_add(thing,attr,dest);
  if (!(db[player].flags&QUIET)) {
    notify(player,"set.");
    do_examine(player,it);
  }
}


void do_cut(player,thing)
     dbref player;
     char *thing;
{
  dbref object;
  if (!power(player, POW_SECURITY))
    {
      notify(player,"Sorry no cutting allowed.");
      return;
    }
  switch(object=match_controlled(player,thing,POW_SECURITY))
    {
    case NOTHING:
      notify(player,"No match.");
      return;
    case AMBIGUOUS:
      notify(player,"I don't know which one");
      break;
    default:
      db[object].next=NOTHING;
    }
  notify(player,"Cut.");
}


void do_hide(player)
     dbref player;
{
#ifdef USE_RWHO
  rwhocli_userlogout(tprintf("%d@%s",player,RWHO_MUSE_NAME));
#endif
  
  atr_add((Typeof(player)==TYPE_PLAYER)?player:db[player].owner,A_LHIDE,"me&!me");
  if(Typeof(player)==TYPE_PLAYER)
    notify(player,"Your name is HIDDEN.");
  else
    notify(player,"Your owner's name is HIDDEN.");
  return;
}

void do_unhide(play)
     dbref play;
{
  atr_add((Typeof(play)==TYPE_PLAYER)?play:db[play].owner,A_LHIDE,"");
  if(Typeof(play)==TYPE_PLAYER)
    notify(play,"Your name is back on the WHO list.");
  else
    notify(play,"Your owner's name is back on the WHO list.");
#ifdef USE_RWHO
  rwhocli_userlogin(tprintf("%d@%s",play,RWHO_MUSE_NAME),db[play].name);
#endif
  return;
}

void do_haven(player,haven)
     dbref player;
 char *haven;
{
  if (*haven == '?') {
    if (*atr_get(player,A_HAVEN)) {
      notify(player, tprintf("Your Haven message is: %s",
			     atr_get(player,A_HAVEN)));
      return;
    }
    else {
      notify(player,"You have no Haven message.");
      return;
    }
  }
  
  if (*haven =='\0') {
    atr_clr(player, A_HAVEN);
    notify(player,"Haven message removed.");
    return;
  }
  
  atr_add(player,A_HAVEN,haven);
  notify(player, tprintf("Haven message set as: %s", haven));
}

void do_idle(player,idle)
     dbref player;
 char *idle;
{
  if (*idle == '?') {
    if (*Idle(player)) {
      notify(player, tprintf("Your Idle message is: %s",
			     atr_get(player,A_IDLE)));
      return;
    }
    else {
      notify(player,"You have no Idle message.");
      return;
    }
  }
  
  if (*idle =='\0') {
    atr_clr(player, A_IDLE);
    notify(player,"Idle message removed.");
    return;
  }
  
  atr_add(player,A_IDLE,idle);
  notify(player, tprintf("Idle message set as: %s", idle));
  
}

void do_away(player,away)
     dbref player;
 char *away;
{
  if (*away == '?') {
    if (*Away(player)) {
      notify(player, tprintf("Your Away message is: %s",
			     atr_get(player,A_AWAY)));
      return;
    }
    else {
      notify(player,"You have no Away message.");
      return;
    }
  }
  
  if (*away == '\0') {
    atr_clr(player, A_AWAY);
    notify(player,"Away message removed.");
    return;
  }
  
  atr_add(player,A_AWAY,away);
  notify(player, tprintf("Away message set as: %s", away));
}