PennMUSH Community

root/1.8.3/trunk/src/fundb.c

Revision 1167, 52.8 kB (checked in by shawnw, 8 months ago)

Merge devel into trunk for p6 release

Line 
1 /**
2  * \file fundb.c
3  *
4  * \brief Dbref-related functions for mushcode.
5  *
6  *
7  */
8
9 #include "copyrite.h"
10
11 #include "config.h"
12 #include <string.h>
13 #include "conf.h"
14 #include "externs.h"
15 #include "dbdefs.h"
16 #include "flags.h"
17
18 #include "match.h"
19 #include "parse.h"
20 #include "command.h"
21 #include "game.h"
22 #include "mushdb.h"
23 #include "privtab.h"
24 #include "lock.h"
25 #include "log.h"
26 #include "attrib.h"
27 #include "function.h"
28 #include "confmagic.h"
29
30 #ifdef WIN32
31 #pragma warning( disable : 4761)        /* NJG: disable warning re conversion */
32 #endif
33
34 extern PRIV attr_privs_view[];
35 static lock_type get_locktype(char *str);
36 extern struct db_stat_info *get_stats(dbref owner);
37 static int lattr_helper(dbref player, dbref thing, dbref parent,
38                         char const *pattern, ATTR *atr, void *args);
39 static dbref
40  dbwalk(char *buff, char **bp, dbref executor, dbref enactor,
41         int type, dbref loc, dbref after, int skipdark,
42         int start, int count, int *retcount);
43
44
45 const char *
46 do_get_attrib(dbref executor, dbref thing, const char *attrib)
47 {
48   ATTR *a;
49   char const *value;
50
51   a = atr_get(thing, strupper(attrib));
52   if (a) {
53     if (Can_Read_Attr(executor, thing, a)) {
54       if (strlen(value = atr_value(a)) < BUFFER_LEN)
55         return value;
56       else
57         return T("#-1 ATTRIBUTE LENGTH TOO LONG");
58     }
59     return T(e_atrperm);
60   }
61   a = atr_match(attrib);
62   if (a) {
63     if (Can_Read_Attr(executor, thing, a))
64       return "";
65     return T(e_atrperm);
66   }
67   if (!Can_Examine(executor, thing))
68     return T(e_atrperm);
69   return "";
70 }
71
72 /** Structure containing arguments for lattr_helper */
73 struct lh_args {
74   int first;            /**< Is this is the first attribute, or later? */
75   int nattr;
76   int start;            /**< Where do we start counting? */
77   int count;            /**< How many do we count? */
78   char *buff;           /**< Buffer to store output */
79   char **bp;            /**< Pointer to address of insertion point in buff */
80   char delim;           /**< Delimiter */
81 };
82
83 /* this function produces a space-separated list of attributes that are
84  * on an object.
85  */
86 /* ARGSUSED */
87 static int
88 lattr_helper(dbref player __attribute__ ((__unused__)),
89              dbref thing __attribute__ ((__unused__)),
90              dbref parent __attribute__ ((__unused__)),
91              char const *pattern __attribute__ ((__unused__)),
92              ATTR *atr, void *args)
93 {
94   struct lh_args *lh = args;
95   lh->nattr++;
96   if (lh->count < 1
97       || (lh->nattr >= lh->start && lh->nattr < (lh->count + lh->start))) {
98     if (lh->first)
99       lh->first = 0;
100     else
101       safe_chr(lh->delim, lh->buff, lh->bp);
102     safe_str(AL_NAME(atr), lh->buff, lh->bp);
103     return 1;
104   }
105   return 1;
106 }
107
108 /* ARGSUSED */
109 FUNCTION(fun_nattr)
110 {
111   dbref thing;
112   int doparent;
113   static const char *matchall = "**";   /* count atrees by default too */
114   char *pattern;
115
116   pattern = strchr(args[0], '/');
117   if (pattern)
118     *pattern++ = '\0';
119   else
120     pattern = (char *) matchall;        /* match anything */
121
122   thing = match_thing(executor, args[0]);
123   if (!GoodObject(thing)) {
124     safe_str(T(e_notvis), buff, bp);
125     return;
126   }
127
128   doparent = strchr(called_as, 'P') ? 1 : 0;
129
130   if (!doparent && pattern == matchall && Can_Examine(executor, thing)) {
131     safe_integer(AttrCount(thing), buff, bp);
132   } else {
133     safe_integer(atr_pattern_count(executor, thing, pattern, doparent,
134                                    !Can_Examine(executor, thing)), buff, bp);
135   }
136 }
137
138 /* ARGSUSED */
139 FUNCTION(fun_lattr)
140 {
141   dbref thing;
142   char *pattern;
143   struct lh_args lh;
144   char delim;
145
146   lh.nattr = lh.start = lh.count = 0;
147
148   if (*called_as == 'X') {
149     if (!is_strict_integer(args[1]) || !is_strict_integer(args[2])) {
150       safe_str(T(e_int), buff, bp);
151       return;
152     }
153
154     lh.start = parse_integer(args[1]);
155     lh.count = parse_integer(args[2]);
156
157     if (lh.start < 1 || lh.count < 1) {
158       safe_str(T("#-1 ARGUMENT OUT OF RANGE"), buff, bp);
159       return;
160     }
161
162     if (!delim_check(buff, bp, nargs, args, 4, &delim))
163       return;
164   } else {
165     /* lattr()/lattrp*( */
166     if (!delim_check(buff, bp, nargs, args, 2, &delim))
167       return;
168   }
169
170   pattern = strchr(args[0], '/');
171   if (pattern)
172     *pattern++ = '\0';
173   else
174     pattern = (char *) "*";     /* match anything */
175
176   thing = match_thing(executor, args[0]);
177   if (!GoodObject(thing)) {
178     safe_str(T(e_notvis), buff, bp);
179     return;
180   }
181   lh.first = 1;
182   lh.buff = buff;
183   lh.bp = bp;
184   lh.delim = delim;
185
186   if (strchr(called_as, 'P')) {
187     (void) atr_iter_get_parent(executor, thing, pattern,
188                                !Can_Examine(executor, thing), lattr_helper,
189                                &lh);
190   } else {
191     (void) atr_iter_get(executor, thing, pattern,
192                         !Can_Examine(executor, thing), lattr_helper, &lh);
193   }
194 }
195
196 /* ARGSUSED */
197 FUNCTION(fun_hasattr)
198 {
199   dbref thing;
200   ATTR *a;
201
202   thing = match_thing(executor, args[0]);
203   if (!GoodObject(thing)) {
204     safe_str(T(e_notvis), buff, bp);
205     return;
206   }
207   if (strchr(called_as, 'P'))
208     a = atr_get(thing, upcasestr(args[1]));
209   else
210     a = atr_get_noparent(thing, upcasestr(args[1]));
211   if (a && Can_Read_Attr(executor, thing, a)) {
212     if (strchr(called_as, 'V'))
213       safe_chr(*AL_STR(a) ? '1' : '0', buff, bp);
214     else
215       safe_chr('1', buff, bp);
216     return;
217   } else if (a || !Can_Examine(executor, thing)) {
218     safe_str(T(e_perm), buff, bp);
219     return;
220   }
221   safe_chr('0', buff, bp);
222 }
223
224 /* ARGSUSED */
225 FUNCTION(fun_get)
226 {
227   dbref thing;
228   char *s;
229
230   s = strchr(args[0], '/');
231   if (!s) {
232     safe_str(T("#-1 BAD ARGUMENT FORMAT TO GET"), buff, bp);
233     return;
234   }
235   *s++ = '\0';
236   thing = match_thing(executor, args[0]);
237   if (!GoodObject(thing)) {
238     safe_str(T(e_notvis), buff, bp);
239     return;
240   }
241   safe_str(do_get_attrib(executor, thing, s), buff, bp);
242 }
243
244 /* Functions like get, but uses the standard way of passing arguments */
245 /* to a function, and thus doesn't choke on nested functions within.  */
246
247 /* ARGSUSED */
248 FUNCTION(fun_xget)
249 {
250   dbref thing;
251
252   thing = match_thing(executor, args[0]);
253   if (!GoodObject(thing)) {
254     safe_str(T(e_notvis), buff, bp);
255     return;
256   }
257   safe_str(do_get_attrib(executor, thing, args[1]), buff, bp);
258 }
259
260 /* Functions like get, but includes a default response if the
261  * attribute isn't present or is null
262  */
263 /* ARGSUSED */
264 FUNCTION(fun_default)
265 {
266   dbref thing;
267   ATTR *attrib;
268   char *dp;
269   const char *sp;
270   char mstr[BUFFER_LEN];
271   int i;
272   /* find our object and attribute */
273   for (i = 1; i < nargs; i++) {
274     mstr[0] = '\0';
275     dp = mstr;
276     sp = args[i - 1];
277     process_expression(mstr, &dp, &sp, executor, caller, enactor, PE_DEFAULT,
278                        PT_DEFAULT, pe_info);
279     *dp = '\0';
280     parse_attrib(executor, mstr, &thing, &attrib);
281     if (GoodObject(thing) && attrib && Can_Read_Attr(executor, thing, attrib)) {
282       /* Ok, we've got it */
283       dp = safe_atr_value(attrib);
284       safe_str(dp, buff, bp);
285       free(dp);
286       return;
287     }
288   }
289   /* We couldn't get it. Evaluate the last arg and return it */
290   sp = args[nargs - 1];
291   process_expression(buff, bp, &sp, executor, caller, enactor,
292                      PE_DEFAULT, PT_DEFAULT, pe_info);
293   return;
294 }
295
296 /* ARGSUSED */
297 FUNCTION(fun_eval)
298 {
299   /* like xget, except pronoun substitution is done */
300
301   dbref thing;
302   char *tbuf;
303   char const *tp;
304   ATTR *a;
305
306   thing = match_thing(executor, args[0]);
307   if (!GoodObject(thing)) {
308     safe_str(T(e_notvis), buff, bp);
309     return;
310   }
311   a = atr_get(thing, upcasestr(args[1]));
312   if (a && Can_Read_Attr(executor, thing, a)) {
313     if (!CanEvalAttr(executor, thing, a)) {
314       safe_str(T(e_perm), buff, bp);
315       return;
316     }
317     tp = tbuf = safe_atr_value(a);
318     add_check("fun_eval.attr_value");
319     process_expression(buff, bp, &tp, thing, executor, executor,
320                        PE_DEFAULT, PT_DEFAULT, pe_info);
321     mush_free((Malloc_t) tbuf, "fun_eval.attr_value");
322     return;
323   } else if (a || !Can_Examine(executor, thing)) {
324     safe_str(T(e_atrperm), buff, bp);
325     return;
326   }
327   return;
328 }
329
330 /* ARGSUSED */
331 FUNCTION(fun_get_eval)
332 {
333   /* like eval, except uses obj/attr syntax. 2.x compatibility */
334
335   dbref thing;
336   char *tbuf, *s;
337   char const *tp;
338   ATTR *a;
339
340   s = strchr(args[0], '/');
341   if (!s) {
342     safe_str(T("#-1 BAD ARGUMENT FORMAT TO GET_EVAL"), buff, bp);
343     return;
344   }
345   *s++ = '\0';
346   thing = match_thing(executor, args[0]);
347   if (!GoodObject(thing)) {
348     safe_str(T(e_notvis), buff, bp);
349     return;
350   }
351   a = atr_get(thing, upcasestr(s));
352   if (a && Can_Read_Attr(executor, thing, a)) {
353     if (!CanEvalAttr(executor, thing, a)) {
354       safe_str(T(e_perm), buff, bp);
355       return;
356     }
357     tp = tbuf = safe_atr_value(a);
358     add_check("fun_eval.attr_value");
359     process_expression(buff, bp, &tp, thing, executor, executor,
360                        PE_DEFAULT, PT_DEFAULT, pe_info);
361     mush_free((Malloc_t) tbuf, "fun_eval.attr_value");
362     return;
363   } else if (a || !Can_Examine(executor, thing)) {
364     safe_str(T(e_atrperm), buff, bp);
365     return;
366   }
367   return;
368 }
369
370 /* Functions like eval, but includes a default response if the
371  * attribute isn't present or is null
372  */
373 /* ARGSUSED */
374 FUNCTION(fun_edefault)
375 {
376   dbref thing;
377   ATTR *attrib;
378   char *dp, *sbuf;
379   char const *sp;
380   char mstr[BUFFER_LEN];
381   /* find our object and attribute */
382   dp = mstr;
383   sp = args[0];
384   process_expression(mstr, &dp, &sp, executor, caller, enactor,
385                      PE_DEFAULT, PT_DEFAULT, pe_info);
386   *dp = '\0';
387   parse_attrib(executor, mstr, &thing, &attrib);
388   if (GoodObject(thing) && attrib && Can_Read_Attr(executor, thing, attrib)) {
389     if (!CanEvalAttr(executor, thing, attrib)) {
390       safe_str(T(e_perm), buff, bp);
391       return;
392     }
393     /* Ok, we've got it */
394     sp = sbuf = safe_atr_value(attrib);
395     add_check("fun_edefault.attr_value");
396     process_expression(buff, bp, &sp, thing, executor, executor,
397                        PE_DEFAULT, PT_DEFAULT, pe_info);
398     mush_free((Malloc_t) sbuf, "fun_edefault.attr_value");
399     return;
400   }
401   /* We couldn't get it. Evaluate args[1] and return it */
402   sp = args[1];
403   process_expression(buff, bp, &sp, executor, caller, enactor,
404                      PE_DEFAULT, PT_DEFAULT, pe_info);
405   return;
406 }
407
408 /* ARGSUSED */
409 FUNCTION(fun_v)
410 {
411   /* handle 0-9, va-vz, n, l, # */
412
413   int c;
414
415   if (args[0][0] && !args[0][1]) {
416     switch (c = args[0][0]) {
417     case '0':
418     case '1':
419     case '2':
420     case '3':
421     case '4':
422     case '5':
423     case '6':
424     case '7':
425     case '8':
426     case '9':
427       if (global_eval_context.wenv[c - '0'])
428         safe_str(global_eval_context.wenv[c - '0'], buff, bp);
429       return;
430     case '#':
431       /* enactor dbref */
432       safe_dbref(enactor, buff, bp);
433       return;
434     case '@':
435       /* caller dbref */
436       safe_dbref(caller, buff, bp);
437       return;
438     case '!':
439       /* executor dbref */
440       safe_dbref(executor, buff, bp);
441       return;
442     case 'n':
443     case 'N':
444       /* enactor name */
445       safe_str(Name(enactor), buff, bp);
446       return;
447     case 'l':
448     case 'L':
449       /* giving the location does not violate security,
450        * since the object is the enactor.  */
451       safe_dbref(Location(enactor), buff, bp);
452       return;
453     case 'c':
454     case 'C':
455       safe_str(global_eval_context.ccom, buff, bp);
456       return;
457     }
458   }
459   safe_str(do_get_attrib(executor, executor, args[0]), buff, bp);
460 }
461
462 /* ARGSUSED */
463 FUNCTION(fun_flags)
464 {
465   dbref thing;
466   char *p;
467   ATTR *a;
468   if (nargs == 0) {
469     safe_str(list_all_flags("FLAG", NULL, executor, 0x1), buff, bp);
470     return;
471   }
472   if ((p = strchr(args[0], '/')))
473     *p++ = '\0';
474   thing = match_thing(executor, args[0]);
475   if (!GoodObject(thing)) {
476     safe_str(T(e_notvis), buff, bp);
477     return;
478   }
479   if (p) {
480     /* Attribute flags, you must be able to read the attribute */
481     a = atr_get_noparent(thing, upcasestr(p));
482     if (!a || !Can_Read_Attr(executor, thing, a)) {
483       safe_str("#-1", buff, bp);
484       return;
485     }
486     safe_str(privs_to_letters(attr_privs_view, AL_FLAGS(a)), buff, bp);
487     if (atr_sub_branch(a))
488       safe_chr('`', buff, bp);
489   } else {
490     /* Object flags, visible to all */
491     safe_str(unparse_flags(thing, executor), buff, bp);
492   }
493 }
494
495 /* ARGSUSED */
496 FUNCTION(fun_lflags)
497 {
498   dbref thing;
499   char *p;
500   ATTR *a;
501   if (nargs == 0) {
502     safe_str(list_all_flags("FLAG", NULL, executor, 0x2), buff, bp);
503     return;
504   }
505   if ((p = strchr(args[0], '/')))
506     *p++ = '\0';
507   thing = match_thing(executor, args[0]);
508   if (!GoodObject(thing)) {
509     safe_str(T(e_notvis), buff, bp);
510     return;
511   }
512   if (p) {<