musicmud-2.1.6/data/
musicmud-2.1.6/data/help/
musicmud-2.1.6/data/policy/
musicmud-2.1.6/data/wild/
musicmud-2.1.6/data/world/
musicmud-2.1.6/doc/
musicmud-2.1.6/src/ident/
musicmud-2.1.6/src/lua/
musicmud-2.1.6/src/lua/include/
musicmud-2.1.6/src/lua/src/lib/
musicmud-2.1.6/src/lua/src/lua/
musicmud-2.1.6/src/lua/src/luac/
/* 
 * MusicMUD - Action Making module
 * Copyright (C) 1998-2003 Abigail Brady
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 */
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <ctype.h>

#ifdef CONFIG_THREAD
#include <pthread.h>
#endif

#include "musicmud.h"
#include "State.h"
#include "verbs.h"
#include "util.h"
#include "zoneload.h"
#include "misc.h"
#include "msi.h"
#include "Socket.h"
#include "pflags.h"
#include "paths.h"
#include "emsg.h"
#include "actions.h"

#define MODULE "actions"

	string Action::*asrings[] = {
	  &Action::u_me,
	  &Action::u_rest,
	  &Action::t_me,
	  &Action::t_rest,
	  &Action::t_you,
	  &Action::x_me,
	  &Action::x_rest,
	  &Action::o_me,
	  &Action::o_rest,
	};

static bool verb_actions(MudObject *who, int argc, const char **argv) {
  if (argc==1) {
    Divert d(who, "actions");
    Header h(who, "Actions Index", 1);
    
    Verb *v;
    int i;

    size_t maxlen = 0;
    
    foreach_alpha(verbs, v, i) {
      if (!streq(v->get("module"), "action"))
	continue;
      if (strlen(v->id)>maxlen)
	maxlen = strlen(v->id);
    }

    int cols = columns(who);
    cols /= (maxlen + 1);
    cols--;
    
    if (cols<2)
      cols = 2;

    int j = 0;

    foreach_alpha(verbs, v, i) {
      if (!streq(v->get("module"), "action"))
	continue;
      if (j == (cols)) {
	j = 0;
	who->printf("\n");
      }
      who->printf("%-*s ", maxlen, v->id);
      j++;
    }

    who->printf("\n");
    return true;
  }

  Object *testing = verbs->get(argv[1]);

  if (!testing && (strchr(argv[1], '?') ||
		   strchr(argv[1], '*'))) {
    Verb *v;
    int i;
    int found = 0;
    string s;
    foreach_alpha(verbs, v, i) {
      if (!streq(v->get("module"), "action"))
	  continue;

      int f = 0;
      if (wcmatch(make_lower(argv[1]).c_str(), 
		  make_lower(v->id).c_str())) {
	f = 1;
      }

      if (!f) {
	Action a(v->id);

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

	for (size_t i=0;i<ARRAY_SIZE(asrings);i++) {
	  if (wcmatch(make_lower(argv[1]).c_str(), 

		      make_lower(lose_colour((a.*asrings[i]).c_str())
				 .c_str()).c_str())) {
	    f = 1;
	    continue;
	  }
      }
      }

      if (f) {
	s += ssprintf("%s ", v->id);
	found = 1;
      }
    }
    if (found) {
      who->printf("All actions matching '%s'.\n\n    ^Z%s\n", argv[1], s.c_str());
      return true;
    }
  }
  
  if (testing && streq(testing->get("module"), "action")) {
    Action a(argv[1]);

    string title = "help ";
    title += argv[1];
    who->printf("%s\n\n", title_for(title.c_str(), who).c_str());

    if (a.u_me.length()) {
      who->printf("^WUntargetted:^n\n");
      who->printf("  to you    : ^Z%s\n", sprinta(who, a.u_me.c_str(), who, 0, 0, 2));      
      who->printf("  to others : ^Z%s\n\n", sprinta(0, a.u_rest.c_str(), who, 0));
    }

    if (a.x_me.length()) {
      who->printf("^WUntargetted (with text):^n\n");
      who->printf("  to you    : ^Z%s\n", sprinta(who, a.x_me.c_str(), who, 0, "[some text]", 2));      
      who->printf("  to others : ^Z%s\n\n", sprinta(0, a.x_rest.c_str(), who, 0, "[some text]"));
    }

    if (a.s_me.length()) {
      who->printf("^WTargetted at person:^n\n");
      MudObject tmp("@tmp");
      who->printf("  to you    : ^Z%s\n", sprinta(who, a.s_me.c_str(), who, 0, "[some text]", 2));  
      who->printf("  to target : ^Z%s\n", sprinta(&tmp, a.s_you.c_str(), who, &tmp, "[some text]", 2));
      who->printf("  to others : ^Z%s\n\n", sprinta(0, a.s_rest.c_str(), who, 0, "[some text]"));
    }

    if (a.t_me.length()) {
      who->printf("^WTargetted at person:^n\n");
      MudObject tmp("@tmp");
      who->printf("  to you    : ^Z%s\n", sprinta(who, a.t_me.c_str(), who, 0, 0, 2));
      who->printf("  to target : ^Z%s\n", sprinta(&tmp, a.t_you.c_str(), who, &tmp, 0, 2));
      who->printf("  to others : ^Z%s\n\n", sprinta(0, a.t_rest.c_str(), who, 0));
    }

    if (a.p_me.length()) {
      who->printf("^WTargetted with prop:^n\n");
      MudObject tmp("@tmp");
      who->printf("  to you    : ^Z%s\n", sprinta(who, a.p_me.c_str(), who, 0, 0, 2));
      who->printf("  to target : ^Z%s\n", sprinta(&tmp, a.p_you.c_str(), who, &tmp, 0, 2));
      who->printf("  to others : ^Z%s\n\n", sprinta(0, a.p_rest.c_str(), who, 0));
    }

    if (a.o_me.length()) {
      who->printf("^WTargetted at object:^n\n");
      who->printf("  to you    : ^Z%s\n", sprinta(who, a.o_me.c_str(), who, 0, 0, 2));
      who->printf("  to others : ^Z%s\n\n", sprinta(0, a.o_rest.c_str(), who, 0));
    }

    who->printf("%s\n", footer_for(who).c_str());

    return true;
  }
  who->printf("Cannot find action : %s.\n", argv[1]);      
  return true;
}

static bool verb_addaction(Player *who, int, const char **) {
  who->push_state("action.name");
  return true;
}

static void state_action_name(Player *who, const char *what) {
  if (!what || !*what) {
    who->pop_state();
    who->printf("Ok then.\n");
    return;
  }

  const char *w = what;
  while (*w) {
    if (!isalpha(*w)) {
      who->printf("Actions can only have letters in their names.\n");
      who->pop_state();
      return;
    }
    w++;
  }
  
  int can_obj = 1;
  int can_tar = 1;
  int can_txt = 1;
  int can_unt = 1;
  int can_xto = 1;

  Action act;

  try {
    Action a(what);
    act = a;
  } catch (emsg e) {
    if (verbs->get(what)) {
      who->printf("There's already a non-action verb called that.\n");
      return;
    }
  }

  if (act.x_rest.length()) {
    can_obj = 0;
    can_txt = 0;
    can_tar = 0;
  }

  if (act.u_rest.length()) {
    can_unt = 0;
  }

  if (act.t_rest.length()) {
    can_txt = 0;
    can_tar = 0;
  }

  if (act.o_rest.length()) {
    can_txt = 0;
    can_obj = 0;
  }

  if (act.s_rest.length()) {
    can_xto = 0;
  }

  if (!(can_obj || can_tar || can_txt || can_unt)) {
    who->printf("Action is full.\n");
    who->pop_state();
    return;
  }

  int types = can_unt | can_tar<<1 | can_txt<<2 | can_obj<<3 | can_xto<<4;

  who->set_state("action.type");
  who->set("!action.types", types);

  if (can_unt) who->printf("1 - untargetted.\n");
  if (can_tar) who->printf("2 - targetted at person.\n");
  if (can_txt) who->printf("3 - with text.\n");
  if (can_obj) who->printf("4 - targetted at object.\n");
  if (can_xto) who->printf("5 - at person with text.\n");

  who->set("!action.name", what);
}

static void state_action_type(Player *who, const char *what) {
	int which = atoi(what);
	
	int avail = who->get_int("!action.types");

	switch(which) {
	 case 0:
		who->pop_state();
		return;
	 case 1:
	   if (!(avail & 1)) {
	     who->printf("Can't.\n");
	     who->pop_state();
	     return;
	   }
		who->printf("%%1 == name of sender\n"
			    "%%2 == he/she/they/it\n"
			    "%%3 == him/her/them/it\n"
			    "%%4 == his/her/their/its\n"
			    "%%5 == his/hers/theirs/its\n"
			    "%%6 == himself/herself/theirself/itself\n");
		who->set_state("action.unt.others");
		break;
	 case 2:
	   if (!(avail & 2)) {
	     who->printf("Can't.\n");
	     who->pop_state();
	     return;
	   }
		who->printf("%%1 == name of sender                          %%a == name of target\n"
			    "%%2 == he/she/they/it                          %%b == he/she/they/it\n"
			    "%%3 == him/her/them/it                         %%c == him/her/them/it\n"
			    "%%4 == his/her/their/its                       %%d == his/her/their/its\n"
			    "%%5 == his/hers/theirs/its                     %%e == his/hers/theirs/its\n"
			    "%%6 == himself/herself/theirself/itself        %%f == himself/herself/theirself/itself\n");
		who->set_state("action.tar.others");
		break;
	 case 3:
	   if (!(avail & 4)) {
	     who->printf("Can't.\n");
	     who->pop_state();
	     return;
	   }
		who->printf("%%s == text passed to action\n"
			    "%%1 == name of sender\n"
			    "%%2 == he/she/they/it\n"
			    "%%3 == him/her/them/it\n"
			    "%%4 == his/her/their/its\n"
			    "%%5 == his/hers/their/its\n"
			    "%%6 == himself/herself/theirself/itself\n");
		who->set_state("action.txt.others");
		return;
	case 4:
	  if (!(avail & 8)) {
	    who->printf("Can't.\n");
	    who->pop_state();
	     return;
	  }
	  who->set_state("action.obj.others");
	  break;

	case 5:
	  if (!(avail & 16)) {
	    who->printf("Can't.\n");
	    who->pop_state();
	    return;
	  }
	  who->set_state("action.xto.others");
	  break;

	 default:
		who->printf("Unhandled action type: %i\n", which);
		who->pop_state();
		return;
	}
	who->set("!action.type", which);
}

static void state_action_unt_user(Player *who, const char *what) {
  if (what) {
    if (*what)
      who->set("!action.unt.user", what);
    else
      who->set("!action.unt.user", who->get("!action.unt.others"));
    who->set_state("action.unt.confirm");
  } else {
    who->pop_state();
  }
}

static void state_action_unt_others(Player *who, const char *what) {
  if (what && *what) {
    who->set("!action.unt.others", what);
    who->set_state("action.unt.user");
  } else {
    who->pop_state();
  }
}

static void state_action_unt_confirm(Player *who, const char *what) {
	if (no(what) || !who->get("!action.name")) {
		who->printf("OK then, I won't..\n");
		who->pop_state();
		who->unset("!action.name");
		who->unset("!action.unt.user");
		who->unset("!action.unt.others");
		return;
	}
	
	const char *actname = who->get("!action.name");

	try {
	  Action act(actname, 1);
	  act.u_me = who->get("!action.unt.user");
	  act.u_rest = who->get("!action.unt.others");
	  act.output(actname);
	} catch (emsg &e) {
	  who->printf("Couldn't open the action file.\n");
	  who->pop_state();
	  who->unset("!action.unt.user");
	  who->unset("!action.unt.others");
	  return;
	}
	
	log(PFL_SEEINFO, 0, "action", "new untargetted : %s", actname);

	who->pop_state();
	who->ilc++;
	who->interpret("rescan");
	who->ilc--;
	who->unset("!action.unt.user");
	who->unset("!action.unt.others");
}

static void state_action_obj_user(Player *who, const char *what) {
  if (what) {
    if (*what)
      who->set("!action.obj.user", what);
    else
      who->set("!action.obj.user", who->get("!action.obj.others"));
    who->set_state("action.obj.confirm");
  } else {
    who->pop_state();
  }
}

static void state_action_obj_others(Player *who, const char *what) {
  if (what && *what) {
    who->set("!action.obj.others", what);
    who->set_state("action.obj.user");
  } else {
    who->pop_state();
  }
}

static void state_action_obj_confirm(Player *who, const char *what) {
	if (no(what) || !who->get("!action.name")) {
		who->printf("OK then, I won't..\n");
		who->pop_state();
		who->unset("!action.name");
		who->unset("!action.obj.user");
		who->unset("!action.obj.others");
		return;
	}
	
	const char *actname = who->get("!action.name");

	try {
	  Action act(actname, 1);
	  act.o_me = who->get("!action.obj.user");
	  act.o_rest = who->get("!action.obj.others");
	  act.output(actname);
	} catch (emsg &e) {
	  who->printf("Couldn't open the action file.\n");
	  who->pop_state();
	  who->unset("!action.obj.user");
	  who->unset("!action.obj.others");
	  return;
	}

	log(PFL_SEEINFO, 0, "action", "new targetted-at-object : %s", actname);

	who->pop_state();
	who->ilc++;
	who->interpret("rescan");
	who->ilc--;
	who->unset("!action.obj.user");
	who->unset("!action.obj.others");
}

static void state_action_tar_user(Player *who, const char *what) {
  if (what) {
    if (*what)
      who->set("!action.tar.user", what);
    else
      who->set("!action.tar.user", who->get("!action.tar.others"));
    who->set_state("action.tar.target");
  } else {
    who->pop_state();
  }
}

static void state_action_tar_target(Player *who, const char *what) {
  if (what) {
    if (*what)
      who->set("!action.tar.target", what);
    else
      who->set("!action.tar.target", who->get("!action.tar.others"));
    who->set_state("action.tar.confirm");
  } else {
    who->pop_state();
  }
}


static void state_action_tar_others(Player *who, const char *what) {
  if (what && *what) {
    who->set("!action.tar.others", what);
    who->set_state("action.tar.user");
  } else {
    who->pop_state();
  }
}

static void state_action_tar_confirm(Player *who, const char *what) {
	if (no(what) || !who->get("!action.name")) {
		who->printf("OK then, I won't..\n");
		who->pop_state();
		who->unset("!action.name");
		who->unset("!action.tar.user");
		who->unset("!action.tar.target");
		who->unset("!action.tar.others");
		return;
	}

	const char *actname = who->get("!action.name");


	try {
	  Action act(actname, 1);
	  act.t_me = who->get("!action.tar.user");
	  act.t_you = who->get("!action.tar.target");
	  act.t_rest = who->get("!action.tar.others");
	  act.output(actname);
	} catch (emsg &e) {
	  who->printf("Couldn't open the action file.\n");
	  who->pop_state();
	  who->unset("!action.tar.user");
	  who->unset("!action.tar.target");
	  who->unset("!action.tar.others");
	  return;
	}

	log(PFL_SEEINFO, 0, "action", "new targetted-at-person : %s", actname);

	who->pop_state();
	who->ilc++;
	who->interpret("rescan");
	who->ilc--;
	who->unset("!action.tar.user");
	who->unset("!action.tar.target");
	who->unset("!action.tar.others");
}


static void state_action_xto_others(Player *who, const char *what) {
  if (*what) {
    who->set("!action.xto.others", what);
    who->set_state("action.xto.user");
  } else {
    who->pop_state();
  }
}

static void state_action_xto_user(Player *who, const char *what) {
  if (*what)
    who->set("!action.xto.user", what);
  else
    who->set("!action.xto.user", who->get("!action.xto.others"));
  who->set_state("action.xto.target");
}

static void state_action_xto_target(Player *who, const char *what) {
  if (*what)
    who->set("!action.xto.target", what);
  else
    who->set("!action.xto.target", who->get("!action.xto.others"));
  who->set_state("action.xto.error");
}

static void state_action_xto_error(Player *who, const char *what) {
  if (!*what)
    return;

  who->set("!action.xto.error", what);

  who->set_state("action.xto.confirm");
}

static void state_action_xto_confirm(Player *who, const char *what) {
  if (no(what) || !who->get("!action.name")) {
    who->printf("OK then, I won't..\n");
    who->pop_state();
    who->unset("!action.name");
    who->unset("!action.xto.user");
    who->unset("!action.xto.target");
    who->unset("!action.xto.others");
    return;
  }

  const char *actname = who->get("!action.name");
  
  try {
    Action act(actname, 1);
    act.s_me = who->get("!action.xto.user");
    act.s_you = who->get("!action.xto.target");
    act.s_rest = who->get("!action.xto.others");
    act.s_err = who->get("!action.xto.error");
    act.output(actname);
  } catch (emsg &e) {
    who->printf("Couldn't open the action file.\n");
    who->pop_state();
    who->unset("!action.xto.user");
    who->unset("!action.xto.target");
    who->unset("!action.xto.others");
    return;
  }
  
  log(PFL_SEEINFO, 0, "action", "new targetted-at-person-with-text : %s", actname);
  
  who->pop_state();
  who->ilc++;
  who->interpret("rescan");
  who->ilc--;
  who->unset("!action.xto.user");
  who->unset("!action.xto.target");
  who->unset("!action.xto.others");
}



static void state_action_txt_user(Player *who, const char *what) {
  if (what) {
    if (*what)
      who->set("!action.txt.user", what);
    else
      who->set("!action.txt.user", who->get("!action.txt.others"));
    who->set_state("action.txt.error");
  } else {
    who->pop_state();
  }
}

static void state_action_txt_others(Player *who, const char *what) {
  if (what && *what) {
    who->set("!action.txt.others", what);
    who->set_state("action.txt.user");
  } else {
    who->pop_state();
  }
}

static void state_action_txt_error(Player *who, const char *what) {
  if (what && *what) {
    who->set("!action.txt.error", what);
    who->set_state("action.txt.confirm");
  } else {
    who->pop_state();
  }
}

static void state_action_txt_confirm(Player *who, const char *what) {
	if (no(what) || !who->get("!action.name")) {
		who->printf("OK then, I won't..\n");
		who->pop_state();
		who->unset("!action.name");
		who->unset("!action.txt.user");
		who->unset("!action.txt.other");
		who->unset("!action.txt.error");
		return;
	}


	const char *actname = who->get("!action.name");


	try {
	  Action act(actname, 1);
	  act.x_me = who->get("!action.txt.user");
	  act.x_err = who->get("!action.txt.error");
	  act.x_rest = who->get("!action.txt.others");
	  act.output(actname);
	} catch (emsg &e) {
	  who->printf("Couldn't open the action file.\n");
	  who->pop_state();
	  who->unset("!action.txt.user");
	  who->unset("!action.txt.error");
	  who->unset("!action.txt.others");
	  return;
	}

	log(PFL_SEEINFO, 0, "action", "new untargetted-text : %s", actname);

	who->pop_state();
	who->ilc++;
	who->interpret("rescan");
	who->ilc--;
	who->unset("!action.txt.user");
	who->unset("!action.txt.error");
	who->unset("!action.txt.others");
}

static bool is_compressed(MudObject *who)
{
#ifndef NOCOMPRESS
  Player *p = (Player *)who;
  if (p->p && p->p->compress)
    return 1;
#endif
  return 0;
}

static bool verb_compile(MudObject *who, int, const char **) {
	if (!is_player(who)) {
		who->printf("no way..\n");
		return true;
	}
	if (is_compressed(who)) {
	  who->printf("You can't do on a compressed line.\n");
	  return true;
	}
	if (!who->get_priv(PFL_CODER)) {
		who->printf("Only Coders can do that.\n");
		return true;
	}
    pid_t child;
	
	if ((child=fork())) {
		/* we are the parent... */
//		who->interpret("quit");
	} else {
		/* we are the child.. */
	    dup2(((Player *)who)->p->socket->getfd(), 1);
	    fcntl(0, F_SETFL, 0);
	    dup2(1, 2);
	    fcntl(0, F_SETFD, 0);
	    fcntl(1, F_SETFD, 0);
	    fcntl(2, F_SETFD, 0);
#ifdef CONFIG_THREAD
	    pthread_kill_other_threads_np();
#endif
	    execl("/bin/sh", "sh", "-c", "make", "2>&1", NULL);
	}
    return true;
}


static bool verb_cvsupdate(MudObject *who, int, const char**) {
	if (!is_player(who)) {
		who->printf("no way..\n");
		return true;
	}
	if (is_compressed(who)) {
	  who->printf("You can't do on a compressed line.\n");
	  return true;
	}
	if (!who->get_priv(PFL_CODER)) {
		who->printf("Only Coders can do that.\n");
		return true;
	}
    pid_t child;
	
	if ((child=fork())) {
		/* we are the parent... */
//		who->interpret("quit");
	} else {
		/* we are the child.. */
	    dup2(((Player *)who)->p->socket->getfd(), 1);
	    fcntl(0, F_SETFL, 0);
	    dup2(1, 2);
	    fcntl(0, F_SETFD, 0);
	    fcntl(1, F_SETFD, 0);
	    fcntl(2, F_SETFD, 0);
#ifdef CONFIG_THREAD
	    pthread_kill_other_threads_np();
#endif
	    putenv("CVS_RSH=ssh");
	    execl("/bin/sh", "sh", "-c", "cvs update -d", NULL);
	}
    return true;
}


static bool verb_commit(MudObject *who, int argc, const char**argv) {
	if (!is_player(who)) {
		who->printf("no way..\n");
		return true;
	}
	if (is_compressed(who)) {
	  who->printf("You can't do on a compressed line.\n");
	  return true;
	}
	if (!who->get_priv(PFL_CODER)) {
		who->printf("Only Coders can do that.\n");
		return true;
	}
	pid_t child;
	
	if (argc < 3) {
	  who->printf("What zone do you want to commit, and what message?\n");
	  return true;
	}
	
	if (!zones->get(argv[1])) {
	  who->printf("No such zone.\n");
	  return true;
	}

	who->interpretf("stz %s", argv[1]);

	if ((child=fork())) {
		/* we are the parent... */
	} else {
		/* we are the child.. */
	    dup2(((Player *)who)->p->socket->getfd(), 1);
	    fcntl(0, F_SETFL, 0);
	    dup2(1, 2);
	    fcntl(0, F_SETFD, 0);
	    fcntl(1, F_SETFD, 0);
	    fcntl(2, F_SETFD, 0);
#ifdef CONFIG_THREAD
	    pthread_kill_other_threads_np();
#endif
	    string fn = "log.";
	    fn += who->id;
	    XFILE *f = xopen("tmp", fn.c_str(), "w+");
	    fprintf(f, "%s\n", the_rest(argc, argv, 2).c_str());
	    fprintf(f, "\n");
	    fprintf(f, "[%s]\n", bwname(who));
	    xclose(f);

	    string cmd = 
	      ssprintf("cvs commit -F tmp/log.%s data/world/%s",
		       who->id,
		       argv[1]);

	    execl("/bin/sh", "sh", "-c", cmd.c_str(), NULL);
	    exit(0);
	}
    return true;
}


static bool verb_update(MudObject *who, int argc, const char **argv) {
	if (!is_player(who)) {
		who->printf("no way..\n");
		return true;
	}
	if (is_compressed(who)) {
	  who->printf("You can't do on a compressed line.\n");
	  return true;
	}
	if (!who->get_priv(PFL_CODER)) {
		who->printf("Only Coders can do that.\n");
		return true;
	}
        if (argc < 2) {
          who->printf("Usage: update wizlist\n");
          return true;
        }
        if (strcasecmp(argv[1], "wizlist")!=0) {
                 who->printf("Usage: update nwizlist\n");
          return true;
        }
    pid_t child;
	
	if ((child=fork())) {
		/* we are the parent... */
//		who->interpret("quit");
	} else {
		/* we are the child.. */
	    dup2(((Player *)who)->p->socket->getfd(), 1);
	    fcntl(0, F_SETFL, 0);
	    dup2(1, 2);
	    fcntl(0, F_SETFD, 0);
	    fcntl(1, F_SETFD, 0);
	    fcntl(2, F_SETFD, 0);
#ifdef CONFIG_THREAD
	    pthread_kill_other_threads_np();
#endif
            chdir("src");
            if (strcmp(argv[1], "wizlist")==0) {
         	    execl("/bin/sh", "sh", "-c", "make wizlist", "2>&1", ">", "/dev/null", NULL);
            }
	}
    return true;
}

static bool verb_acdel(MudObject *who, int argc, const char **argv) {
  if (!argv[1]) {
    who->printf("Delete from what action?\n");
    return true;
  }

  Action a(argv[1]);

  if (a.lua.length()) {
    who->printf("This action has lua and bits cannot be deleted manually.\n");
    return true;
  }

  if (!argv[2]) {
    string s = "";
    if (a.x_rest.length()) s += ", text";
    if (a.o_rest.length()) s += ", obj";
    if (a.u_rest.length()) s += ", unt";
    if (a.t_rest.length()) s += ", tar";
    if (s.length()) 
      s = s.substr(2);
    who->printf("Delete which component of this action? It has %s.\n", s.c_str());
    return true;
  }

  if (streq(argv[2], "text")) {
    if (a.x_rest.length()) {
      a.x_rest = "";
      a.x_err = "";
      a.x_me = "";
    } else {
      who->printf("No text component.\n");
      return true;
    }
  }

  if (streq(argv[2], "obj")) {
    if (a.o_rest.length()) {
      a.o_rest = "";
      a.o_me = "";
    } else {
      who->printf("No object component.\n");
      return true;
    }
  }

  if (streq(argv[2], "unt")) {
    if (a.u_rest.length()) {
      a.u_rest = "";
      a.u_me = "";
    } else {
      who->printf("No untargetted component.\n");
      return true;
    }
  }

  if (streq(argv[2], "tar")) {
    if (a.t_rest.length()) {
      a.t_rest = "";
      a.t_you = "";
      a.t_me = "";
    } else {
      who->printf("No targetted component.\n");
      return true;
    }
  }

  a.output(argv[1]);

  who->interpret("rescan");

  return true;
}

#include "verbmodule.h"
void startup() {

  AUTO_VERB(actions, 2, 0, PFL_NONE);
  AUTO_VERB(addaction, 4, 0, PFL_ACTIONS);
  AUTO_VERB(commit, 5, 0, PFL_CODER);
  AUTO_VERB(compile, 5, 0, PFL_CODER);
  AUTO_VERB(cvsupdate, 4, 0, PFL_CODER);
  AUTO_VERB(update, 6, 0, PFL_CODER);
  AUTO_VERB(acdel, 5, 0, PFL_ACTIONS);

  ADD_STATE("action.name", "Action command: ", state_action_name, false);

  ADD_STATE("action.type", "Type of action : ", state_action_type, false);

  ADD_STATE("action.unt.user", "Message to You: (opt) ", state_action_unt_user, false);
  ADD_STATE("action.unt.others", "Message to Others: ", state_action_unt_others, false);
  ADD_STATE("action.unt.confirm", "Confirm Action: ", state_action_unt_confirm, false);

  ADD_STATE("action.tar.user", "Message to You: (opt) ", state_action_tar_user, false);
  ADD_STATE("action.tar.target", "Message to Target: (opt) ", state_action_tar_target, false);
  ADD_STATE("action.tar.others", "Message to Others: ", state_action_tar_others, false);
  ADD_STATE("action.tar.confirm", "Confirm Action: ", state_action_tar_confirm, false);

  ADD_STATE("action.txt.user", "Message to You: (opt) ", state_action_txt_user, false);
  ADD_STATE("action.txt.others", "Message to Others: ", state_action_txt_others, false);
  ADD_STATE("action.txt.error", "No text error: ", state_action_txt_error, false);
  ADD_STATE("action.txt.confirm", "Confirm Action: ", state_action_txt_confirm, false);

  ADD_STATE("action.obj.user", "Message to You: (opt) ", state_action_obj_user, false);
  ADD_STATE("action.obj.others", "Message to Others: ", state_action_obj_others, false);
  ADD_STATE("action.obj.confirm", "Confirm Action: ", state_action_obj_confirm, false);

  ADD_STATE("action.xto.user", "Message to You: (opt) ", state_action_xto_user, false);
  ADD_STATE("action.xto.target", "Message to Target: (opt) ", state_action_xto_target, false);
  ADD_STATE("action.xto.others", "Message to Others: ", state_action_xto_others, false);
  ADD_STATE("action.xto.error", "No text error: ", state_action_xto_error, false);
  ADD_STATE("action.xto.confirm", "Confirm Action: ", state_action_xto_confirm, false);
}