/
umud/DOC/
umud/DOC/U/
umud/DOC/U/U-examples/
umud/DOC/internals/
umud/DOC/wizard/
umud/MISC/
umud/MISC/dbchk/
umud/RWHO/rwhod/
/*
	Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

#ifndef	lint
static	char	RCSid[] = "$Header: /home/mjr/hacks/umud/RCS/cmd.c,v 1.12 92/05/09 18:53:39 mjr Exp $";
#endif


/* configure all options BEFORE including system stuff. */
#include	"config.h"

#ifndef VMS
#include	<sys/param.h>
#endif


#include	"mud.h"
#include	"cmd.h"
#include	"vars.h"

/* standard commands */
extern	int	cmd_build();
extern	int	cmd_do();
extern	int	cmd_drop();
extern	int	cmd_go();
extern	int	cmd_help();		/* in cmd.c (this file) */
extern	int	cmd__if();
extern	int	cmd_inv();
extern	int	cmd_look();
extern	int	cmd_NEWS();
extern	int	cmd_QUIT();
extern	int	cmd_WHO();		/* in tcpio.c (net-specific) */
extern	int	cmd_page();
extern	int	cmd_password();
extern	int	cmd__password();	/* wiz-only */
extern	int	cmd__rand();
extern	int	cmd_read();
extern	int	cmd_say();
extern	int	cmd_set();		/* in vars.c */
extern	int	cmd_unset();		/* in vars.c */
extern	int	cmd_take();
extern	int	cmd_telep();
extern	int	cmd_use();
extern	int	cmd_unwear();
extern	int	cmd_wear();
extern	int	cmd__wall();
extern	int	cmd_which();
extern	int	cmd_whisper();
extern	int	cmd_destroy();
extern	int	cmd_examine();
/* wiz internal debug functions */
extern	int	cmd__dump();
extern	int	cmd__echo();
extern	int	cmd__force();
extern	int	cmd__cacheconfig();	/* in cache.c */
extern	int	cmd__wizard();
extern	int	cmd__mark();
extern	int	cmd__cronconfig();	/* in cron.c */
extern	int	cmd__mudconfig();	/* in mud.c */
extern	int	cmd__netconfig();	/* in tcpio.c or whatever net module */

#ifdef	COMBAT
extern	int	cmd__combat();		/* in combat.c */
extern	int	cmd__attack();		/* in combat.c */
extern	int	cmd_wield();		/* in combat.c */
/* usermode cron stuff */
extern	int	cmd__cron();		/* in cron.c */
extern	int	cmd__cronlist();	/* in cron.c */
extern	int	cmd__crondel();		/* in cron.c */
#endif



/*
MASTER command table. THIS IS SEARCHED LINEARLY, WHICH IS WHY YOU
SHOULD MAKE SURE THAT MOST FREQENTLY USED COMMANDS ARE NEAREST TO
THE TOP OF THE TABLE.

(linear search is faster in the case of a MUD than a binary search,
since we can predict that 90% of ops will fall between emote/say)
*/
static Cmd	ctab[] = {


{ /* blather something in a TinyMUD-like manner */
"say",			1,	CM_EXACT|CM_NOPLY,	cmd_say,
	"say \"string\""
},


{ /* emote command - TinyMUD-like emote (do and emote are aliases) */
"do",			1,	CM_EXACT|CM_NOPLY,	cmd_do,
	"do \"string\""
},


{ /* look around */
"look",			1,	CM_NOFLG,		cmd_look,
	"look [thing1] ..."
},


{ /* go */
"go",			2,	CM_FIXARG|CM_EXACT|CM_NOPLY,	cmd_go,
	"go place"
},


{ /* whisper */
"whisper",		3,	CM_FIXARG|CM_NOPLY,	cmd_whisper,
	"whisper player message"
},


{ /* page */
"page",			2,	CM_NOFLG|CM_NOPLY,	cmd_page,
	"page player [message]"
},


{ /* echo back to user */
"_echo",		2,	CM_NOFLG,		cmd__echo,
	"_echo text"
},


{ /* inventory */
"inventory",		1,	CM_NOFLG,		cmd_inv,
	"inventory [thing] ..."
},


{ /* take */
"take",			2,	CM_NOFLG,		cmd_take,
	"take thing [thing2] ..."
},


{ /* read text off of something */
"read",			2,	CM_FIXARG,		cmd_read,
	"read [thing] ..."
},


{ /* get - an alias for take */
"get",			2,	CM_EXACT,		cmd_take,
	"get thing [thing2] ..."
},


{ /* drop */
"drop",			2,	CM_NOFLG,		cmd_drop,
	"drop thing [thing2] ..."
},


{ /* examine object(s) */
"examine",		1,	CM_NOFLG,		cmd_examine,
	"examine [thing1] ..."
},


{
"set",			2,	CM_EXACT,		cmd_set,
	"set thing [type] attribute value (or \"set help\" for help)"
},


{
"unset",		3,	CM_FIXARG,		cmd_unset,
	"unset thing attribute"
},


{ /* hold */
"hold",			1,	CM_EXACT,		cmd_use,
	"hold thing (or nothing to stop holding current object)"
},


{ /* use */
"use",			1,	CM_EXACT,		cmd_use,
	"use thing (or nothing to stop using current object)"
},


{ /* wear */
"wear",			2,	CM_EXACT|CM_FIXARG,	cmd_wear,
	"wear thing"
},


{ /* unwear */
"unwear",		2,	CM_EXACT|CM_FIXARG,	cmd_unwear,
	"unwear thing"
},


#ifdef	COMBAT
{ /* combat various supporting functions */
"_combat",		1,	CM_NOPLY,		cmd__combat,
	"_combat [options]"
},


{
"_attack",		5,	CM_NOPLY,		cmd__attack,
	"_attack target attribute value risk [success-string] [failure-string]"
},


{ /* wield */
"wield",		1,	CM_EXACT,		cmd_wield,
	"wield thing (or nothing to stop using current weapon)"
},


{ /* _cron */
"_cron",		3,	CM_EXACT,		cmd__cron,
	"_cron second-count command [repeats] [object-actor]",
},


{ /* _Ucron */
"_Ucron",		3,	CM_EXACT,		cmd__cron,
	"_Ucron second-count command [repeats] [object-actor]",
},


{ /* _cronlist */
"_cronlist",		1,	CM_EXACT|CM_FIXARG,	cmd__cronlist,
	"_cronlist",
},


{ /* _crondel */
"_crondel",		2,	CM_EXACT|CM_FIXARG,	cmd__crondel,
	"_crondel event",
},
#endif


{ /* create a new ?? */
#ifdef	BUILD_WIZ_ONLY
"build",		2,	CM_PRIV,		cmd_build,
#else
"build",		2,	CM_NOFLG,		cmd_build,
#endif
	"build object-type [object-specific options] (or \"build help\")"
},


{ /* which */
"which",		2,	CM_NOFLG,		cmd_which,
	"which [object-type] thing-to-match"
},


{ /* randomly pick a command */
"_rand",		2,	CM_NOFLG,		cmd__rand,
	"_rand [cmd1] [cmd2] [...cmdN]"
},


{ /* conditional (of sorts) */
"_if",			2,	CM_NOFLG,		cmd__if,
	"_if boolean-expression cmd [\"else\" cmd]"
},


{ /* teleport */
"teleport",		3,	CM_FIXARG,		cmd_telep,
	"teleport [thing] [destination]"
},


{ /* destroy an object ; command name must match exactly */
#ifdef	BUILD_WIZ_ONLY
"destroy",	2,		CM_EXACT|CM_PRIV,	cmd_destroy,
#else
"destroy",	2,		CM_EXACT,		cmd_destroy,
#endif
	"destroy object-type object (or \"destroy help\")"
},


{ /* NEWS */
"NEWS",			1,	CM_NOFLG|CM_NOPLY,	cmd_NEWS,
	"NEWS [action] [article] (or \"NEWS help\")"
},


{ /* QUIT command */
"QUIT",			1,	CM_EXACT|CM_NOWHERE,	cmd_QUIT,
	"QUIT"
},


{ /* WHO command */
"WHO",			1,	CM_NOWHERE,		cmd_WHO,
	"WHO [who] ..."
},


{ /* dump command list/summary */
"help",			1,	CM_NOWHERE,		cmd_help,
	"help [cmd] ..."
},


{ /* dump object to controlling terminal in OIF format */
"_dump",		2,	CM_NOFLG,		cmd__dump,
	"_dump objid"
},


{ /* submit a command as someone else */
"_force",		3,	CM_PRIV,		cmd__force,
	"_force who command"
},


{ /* shout */
"_wall",		1,	CM_PRIV,		cmd__wall,
	"_wall message"
},


{ /* set a thing's password */
"password",		3,	CM_FIXARG,		cmd_password,
	"password oldpassword newpassword"
},


{ /* wiz set a thing's password */
"_password",		3,	CM_FIXARG|CM_PRIV,	cmd__password,
	"_password thing password"
},


{ /* cache-specific commands [implementation dependent] */
"_cacheconfig",		2,	CM_PRIV,		cmd__cacheconfig,
	"_cacheconfig [options] (or \"_cacheconfig help\")"
},


{ /* permanent database specific commands [implementation dependent] */
"_dbconfig",		2,	CM_PRIV,		CMD__DBCONFIG,
	"_dbconfig [options] (or \"_dbconfig help\")"
},


{ /* output a text mark for 'bots. echo back first arg with an '@' */
"_mark",		1,	CM_NOFLG,		cmd__mark,
	"_mark \"string\""
},


{ /* mud server specific commands [somewhat implementation dependent] */
"_mudconfig",		2,	CM_PRIV|CM_NOWHERE,	cmd__mudconfig,
	"_mudconfig [options] (or \"_mudconfig help\")"
},


{ /* cron execution specific commands [somewhat implementation dependent] */
"_cronconfig",		2,	CM_PRIV|CM_NOWHERE,	cmd__cronconfig,
	"_cronconfig [options] (or \"_cronconfig help\")"
},


{ /* network layer specific commands [somewhat implementation dependent] */
"_netconfig",		2,	CM_PRIV,		cmd__netconfig,
	"_netconfig [options] (or \"_netconfig help\")"
},


{ /* wizard management */
"_wizard",		2,	CM_NOFLG,		cmd__wizard,
	"_wizard [options] (or \"_wizard help\")"
},


/* list terminator */
0,0,0,0,0
};




Cmd	*
cmdlookup(s)
char	*s;
{
	Cmd	*p = ctab;
	int	x;

	x = strlen(s);

	while(p->name != (char *)0) {
		if((p->flgs & CM_EXACT) && *s == *p->name && !strcmp(s,p->name))
			return(p);
		if(!(p->flgs & CM_EXACT) && *s == *p->name && !strncmp(s,p->name,x))
			return(p);
		p++;
	}
	return(0);
}



Cmd	*
u_cmdlookup(s)
char	*s;
{
	Cmd	*ret;
	for(ret = ctab; ret->name != (char *)0; ret++)
		if(!strcmp(s,ret->name))
			return(ret);
	return((Cmd *)0);
}




/* ARGSUSED */
cmd_help(argc,argv,who,aswho)
int	argc;
char	*argv[];
char	*who;
char	*aswho;
{
	Cmd	*p = ctab;
	int	x;
	int	wiz;

	wiz = ut_flagged(who,var_wiz);

	if(argc <= 1) {
		while(p->name != (char *)0) {
			if(wiz || !(p->flgs & CM_PRIV))
				say(who,p->usage,"\n",(char *)0);
			p++;
		}
		return(0);
	}
	for(x = 1; x < argc; x++) {
		char	fnuf[MAXPATHLEN];
		char	*jnk;

		jnk = argv[x];
		while((jnk = index(jnk,'.')) != (char *)0) {
			if(*(jnk + 1) == '.') {
				say(who, "nice try: \"",argv[x],"\"\n",
			    	(char *)0);
				return(1);
			}
			jnk++;
		}

		if (strlen(argv[x]) >= MAXPATHLEN) {
			say(who, "impossible command: \"",argv[x],"\"\n",
			    (char *)0);
			continue;
		}
		sprintf(fnuf,"HELP/%s",argv[x]);

		if((p = cmdlookup(argv[x])) != (Cmd *)0) {
			if(wiz || !(p->flgs & CM_PRIV)) {
				say(who,"usage: ",p->usage,"\n",(char *)0);
			}
			if(say_file(who,fnuf))
				say(who,"no help file available.\n",(char *)0);
		} else {
			if(say_file(who,fnuf))
				say(who,"unknown command: \"",argv[x],"\"\n",(char *)0);
		}
	}
	return(0);
}