/* attrutils.c */
#include "config.h"
/*
* This file is part of TeenyMUD II.
* Copyright(C) 1993, 1994, 1995 by Jason Downs.
* All rights reserved.
*
* TeenyMUD II 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.
*
* TeenyMUD II 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 (see the file 'COPYING'); if not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*
*/
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif /* HAVE_STRING_H */
#include <ctype.h>
#include "conf.h"
#include "teeny.h"
#include "attrs.h"
#include "externs.h"
/* mud-level attribute utilities. */
int attr_copy(source, dest, match)
int source, dest;
char *match;
{
struct attr *curr;
struct asearch srch;
if (!exists_object(source) || !exists_object(dest) || (source == dest))
return (-1);
for (curr = attr_first(source, &srch); curr != (struct attr *)NULL;
curr = attr_next(source, &srch)) {
if (curr->type == ATTR_STRING) {
if(((match != (char *)NULL) && quick_wild_prefix(match, curr->name))
|| (match == (char *)NULL)) {
if (attr_add(dest, curr->name, (curr->dat).str, curr->flags) != 0)
return (-1);
}
}
}
return (0);
}
char *attr_match(obj, str)
int obj;
char *str;
{
struct attr *curr;
struct asearch srch;
char *match = (char *) NULL;
if (!exists_object(obj))
return ((char *) NULL);
for (curr = attr_first(obj, &srch); curr != (struct attr *)NULL;
curr = attr_next(obj, &srch)) {
if (quick_wild_prefix(str, curr->name)) {
if ((match == (char *) NULL) || (strlen(curr->name) > strlen(match)))
match = curr->name;
}
}
return (match);
}
/* This code needs to be refined a bit more. */
#if defined(__STDC__)
static int attr_wildparse(int object, int cause, bool multi, char token,
char *string, char **aname, char **adata,
int *aflags, int limit, int *argc, char *argv[])
#else
static int attr_wildparse(object, cause, multi, token, string,
aname, adata, aflags, limit, argc, argv)
int object, cause;
bool multi;
char token, *string, **aname, **adata;
int *aflags, limit, *argc;
char *argv[];
#endif
{
char **eargv;
register int idx, i;
int count = 0, depth = 0;
struct asearch srch;
register struct attr *curr;
char buff[MAXATTRNAME + 1];
if(!exists_object(object))
return(0);
do {
for(curr = attr_first(object, &srch); curr != (struct attr *)NULL;
curr = attr_next(object, &srch)) {
if((curr->type == ATTR_STRING) && (((curr->dat).str)[0] == token)) {
/* Find the colon. */
for(i = 1; (((curr->dat).str)[i] != ':') && (i < sizeof(buff)); i++)
buff[i - 1] = ((curr->dat).str)[i];
buff[i - 1] = '\0';
/* If it matches, do it. */
if(wild(buff, string, limit, argc, argv)) {
/* Set these up for later. */
*aname = curr->name;
*adata = (curr->dat).str;
*aflags = curr->flags;
/* Parse and shove in the queue. */
while((*adata)[0] && ((*adata)[0] != ':'))
(*adata)++;
(*adata)++;
while((*adata)[0] && isspace((*adata)[0]))
(*adata)++;
/* dup off the arguments */
if(*argc > 0) {
eargv = (char **)ty_malloc(sizeof(char *) * (*argc),
"attr_wildparse");
for(idx = 0; idx < *argc; idx++)
eargv[idx] = argv[idx];
} else
eargv = (char **)NULL;
queue_add(object, cause, 1, -1, *adata, *argc, eargv);
count++;
if(!multi) /* Return now. */
return(count);
}
}
}
if(get_int_elt(object, PARENT, &object) == -1) {
logfile(LOG_ERROR, "attr_wildparse: bas parent ref on object #%d\n",
object);
return(count);
}
depth++;
} while((object != -1) && (depth <= mudconf.parent_depth));
return(count);
}
/* parse out listening attributes. */
#if defined(__STDC__)
int attr_listen(int player, int cause, char token, char *str)
#else
int attr_listen(player, cause, token, str)
int player, cause;
char token;
char *str;
#endif
{
char *aname, *adata;
int aflags, argc;
char *argv[MAXARGS];
if((player == cause) || islocked(cause, cause, player, ULOCK))
return(0);
if(attr_wildparse(player, cause, 1, token, str, &aname, &adata, &aflags,
MAXARGS, &argc, argv))
return(1);
return(0);
}
/*
* Parse out attribute defined commands.
*
* Unlike MUSH, we do this in almost the order as we do exits.
* (I like it better this way.)
*/
#if defined(__STDC__)
int attr_command(int player, int cause, char token, char *cmd)
#else
int attr_command(player, cause, token, cmd)
int player, cause;
char token;
char *cmd;
#endif
{
char *aname, *adata;
int loc, list, aflags, rloc;
int argc;
int depth = 0;
char *argv[MAXARGS];
/* Check player first. */
if(!isHALT(player) && !isNOCHECK(player)
&& !islocked(cause, cause, player, ULOCK)) {
if(attr_wildparse(player, cause, 0, token, cmd, &aname, &adata, &aflags,
MAXARGS, &argc, argv))
return(1);
}
/* Next, check player's inventory. */
if(get_int_elt(player, CONTENTS, &list) == -1) {
logfile(LOG_ERROR, "attr_command: bad contents list on object #%d\n",
player);
return(0);
}
while(list != -1) {
if((list != player) && !isHALT(list) && !isNOCHECK(list)
&& !islocked(cause, cause, list, ULOCK)) {
if(attr_wildparse(list, cause, 0, token, cmd, &aname, &adata, &aflags,
MAXARGS, &argc, argv))
return(1);
}
if(get_int_elt(list, NEXT, &list) == -1) {
logfile(LOG_ERROR, "attr_command: bad next reference on object #%d\n",
list);
return(0);
}
}
/* Next, check location, *if* it's a room, then it's contents. */
if((get_int_elt(player, LOC, &loc) == -1) || !exists_object(loc)) {
logfile(LOG_ERROR, "attr_command: bad location on object #%d\n", player);
return(0);
}
/* (Abort both checks if they're inside themselves.) */
if(loc != player) {
if(isROOM(loc) && !isHALT(loc) && !isNOCHECK(loc)
&& !islocked(cause, cause, player, ULOCK)) {
if(attr_wildparse(loc, cause, 0, token, cmd, &aname, &adata, &aflags,
MAXARGS, &argc, argv))
return(1);
}
/* Now, locations contents. */
if(get_int_elt(loc, CONTENTS, &list) == -1) {
logfile(LOG_ERROR, "attr_command: bad contents on object #%d\n", loc);
return(0);
}
while(list != -1) {
if((list != player) && !isHALT(list) && !isNOCHECK(list)
&& !islocked(cause, cause, list, ULOCK)) {
if(attr_wildparse(list, cause, 0, token, cmd, &aname, &adata, &aflags,
MAXARGS, &argc, argv))
return(1);
}
if(get_int_elt(list, NEXT, &list) == -1) {
logfile(LOG_ERROR, "attr_command: bad next reference on object #%d\n",
list);
return(0);
}
}
}
/*
* If they're not in a room, find their real (room) location, and
* then search up the room tree, just like for exits. Only include
* contents, as well.
*
* The is extremely inefficient, and just as insecure. Sigh.
*/
rloc = loc;
while(!isROOM(rloc) && (depth <= mudconf.room_depth)) {
if((get_int_elt(rloc, LOC, &rloc) == -1) || !exists_object(rloc)) {
logfile(LOG_ERROR, "attr_command: bad location for object #%d\n", rloc);
return(0);
}
}
if(depth > mudconf.room_depth) {
logfile(LOG_ERROR, "attr_command: exceeded room_depth in location #%d\n",
loc);
return(0);
}
depth = 0; /* Reset counter. */
do {
/* Current location was already checked, if it was a room. */
if(rloc != loc) {
if(get_int_elt(rloc, LOC, &rloc) == -1) {
logfile(LOG_ERROR, "attr_command: bad location ref on object #%d\n",
rloc);
return(0);
}
} else
loc = -1; /* Loop prevention. */
/* Check room locations. Yow. */
if(!isHALT(rloc) && !isNOCHECK(rloc)
&& !islocked(cause, cause, rloc, ULOCK)) {
if(attr_wildparse(rloc, cause, 0, token, cmd, &aname, &adata, &aflags,
MAXARGS, &argc, argv))
return(1);
}
/* Check current room's contents. */
if(get_int_elt(rloc, CONTENTS, &list) == -1) {
logfile(LOG_ERROR, "attr_command: bad contents list on object #%d\n",
rloc);
return(0);
}
while(list != -1) {
if((list != player) && !isHALT(list) && !isNOCHECK(list)
&& !islocked(cause, cause, list, ULOCK)) {
if(attr_wildparse(list, cause, 0, token, cmd, &aname, &adata, &aflags,
MAXARGS, &argc, argv))
return(1);
}
if(get_int_elt(list, NEXT, &list) == -1) {
logfile(LOG_ERROR, "attr_command: bad next reference on object #%d\n",
list);
return(0);
}
}
depth++;
} while((depth <= mudconf.room_depth)
&& (rloc != mudconf.root_location));
/* Done! */
return(0);
}