PennMUSH Community

root/1.8.3/trunk/src/flags.c

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

Merge devel into trunk for p6 release

Line 
1 /**
2  * \file flags.c
3  *
4  * \brief Flags and powers (and sometimes object types) in PennMUSH
5  *
6  *
7  * Functions to cope with flags and powers (and also object types,
8  * in some cases).
9  *
10  * Flag functions actually involve with several related entities:
11  *  Flag spaces (FLAGSPACE objects)
12  *  Flag definitions (FLAG objects)
13  *  Bitmasks representing sets of flags (object_flag_type's). The
14  *    bits involved may differ between dbs.
15  *  Strings of space-separated flag names. This is a string representation
16  *    of a bitmask, suitable for display and storage
17  *  Strings of flag characters
18  *
19  */
20
21 #include "config.h"
22
23 #ifdef I_SYS_TIME
24 #include <sys/time.h>
25 #ifdef TIME_WITH_SYS_TIME
26 #include <time.h>
27 #endif
28 #else
29 #include <time.h>
30 #endif
31 #include <string.h>
32 #include <stdlib.h>
33
34 #include "conf.h"
35 #include "externs.h"
36 #include "command.h"
37 #include "attrib.h"
38 #include "mushdb.h"
39 #include "parse.h"
40 #include "match.h"
41 #include "ptab.h"
42 #include "htab.h"
43 #include "privtab.h"
44 #include "game.h"
45 #include "flags.h"
46 #include "dbdefs.h"
47 #include "lock.h"
48 #include "log.h"
49 #include "dbio.h"
50 #include "sort.h"
51 #include "mymalloc.h"
52 #include "oldflags.h"
53 #include "confmagic.h"
54
55
56 static int can_set_flag(dbref player, dbref thing, FLAG *flagp, int negate);
57 static FLAG *letter_to_flagptr(FLAGSPACE *n, char c, int type);
58 static void flag_add(FLAGSPACE *n, const char *name, FLAG *f);
59 static int has_flag_ns(FLAGSPACE *n, dbref thing, FLAG *f);
60
61 static FLAG *flag_read(FILE * in);
62 static FLAG *flag_read_oldstyle(FILE * in);
63 static void flag_read_all_oldstyle(FILE * in, const char *ns);
64 static void flag_write(FILE * out, FLAG *f, const char *name);
65 static FLAG *flag_hash_lookup(FLAGSPACE *n, const char *name, int type);
66 static FLAG *clone_flag(FLAG *f);
67 static FLAG *new_flag(void);
68 static void flag_add_additional(FLAGSPACE *n);
69 static char *list_aliases(FLAGSPACE *n, FLAG *given);
70 static void realloc_object_flag_bitmasks(FLAGSPACE *n);
71 static FLAG *match_flag_ns(FLAGSPACE *n, const char *name);
72
73 PTAB ptab_flag;                 /**< Table of flags by name, inc. aliases */
74 PTAB ptab_power;                /**< Table of powers by name, inc. aliases */
75 HASHTAB htab_flagspaces;                /**< Hash of flagspaces */
76 slab *flag_slab = NULL;
77 extern PTAB ptab_command;       /* Uses flag bitmasks */
78
79 /** Attempt to find a flagspace from its name */
80 #define Flagspace_Lookup(n,ns)  if (!(n = (FLAGSPACE *)hashfind(ns,&htab_flagspaces))) mush_panic("Unable to locate flagspace");
81
82 /** This is the old default flag table. We still use it when we have to
83  * convert old dbs, but once you have a converted db, it's the flag
84  * table in the db that counts, not this one.
85  */
86 /* Name     Letter   Type(s)   Flag   Perms   Negate_Perm */
87 static FLAG flag_table[] = {
88   {"CHOWN_OK", 'C', NOTYPE, CHOWN_OK, F_ANY, F_ANY},
89   {"DARK", 'D', NOTYPE, DARK, F_ANY, F_ANY},
90   {"GOING", 'G', NOTYPE, GOING, F_INTERNAL, F_INTERNAL},
91   {"HAVEN", 'H', NOTYPE, HAVEN, F_ANY, F_ANY},
92   {"TRUST", 'I', NOTYPE, INHERIT, F_INHERIT, F_INHERIT},
93   {"LINK_OK", 'L', NOTYPE, LINK_OK, F_ANY, F_ANY},
94   {"OPAQUE", 'O', NOTYPE, LOOK_OPAQUE, F_ANY, F_ANY},
95   {"QUIET", 'Q', NOTYPE, QUIET, F_ANY, F_ANY},
96   {"STICKY", 'S', NOTYPE, STICKY, F_ANY, F_ANY},
97   {"UNFINDABLE", 'U', NOTYPE, UNFIND, F_ANY, F_ANY},
98   {"VISUAL", 'V', NOTYPE, VISUAL, F_ANY, F_ANY},
99   {"WIZARD", 'W', NOTYPE, WIZARD, F_INHERIT | F_WIZARD | F_LOG,
100    F_INHERIT | F_WIZARD},
101   {"SAFE", 'X', NOTYPE, SAFE, F_ANY, F_ANY},
102   {"AUDIBLE", 'a', NOTYPE, AUDIBLE, F_ANY, F_ANY},
103   {"DEBUG", 'b', NOTYPE, DEBUGGING, F_ANY, F_ANY},
104   {"NO_WARN", 'w', NOTYPE, NOWARN, F_ANY, F_ANY},
105   {"ENTER_OK", 'e', NOTYPE, ENTER_OK, F_ANY, F_ANY},
106   {"HALT", 'h', NOTYPE, HALT, F_ANY, F_ANY},
107   {"NO_COMMAND", 'n', NOTYPE, NO_COMMAND, F_ANY, F_ANY},
108   {"LIGHT", 'l', NOTYPE, LIGHT, F_ANY, F_ANY},
109   {"ROYALTY", 'r', NOTYPE, ROYALTY, F_INHERIT | F_ROYAL | F_LOG,
110    F_INHERIT | F_ROYAL},
111   {"TRANSPARENT", 't', NOTYPE, TRANSPARENTED, F_ANY, F_ANY},
112   {"VERBOSE", 'v', NOTYPE, VERBOSE, F_ANY, F_ANY},
113   {"ANSI", 'A', TYPE_PLAYER, PLAYER_ANSI, F_ANY, F_ANY},
114   {"COLOR", 'C', TYPE_PLAYER, PLAYER_COLOR, F_ANY, F_ANY},
115   {"MONITOR", 'M', TYPE_PLAYER | TYPE_ROOM | TYPE_THING, 0, F_ANY, F_ANY},
116   {"NOSPOOF", '"', TYPE_PLAYER, PLAYER_NOSPOOF, F_ANY | F_ODARK,
117    F_ANY | F_ODARK},
118   {"SHARED", 'Z', TYPE_PLAYER, PLAYER_ZONE, F_ANY, F_ANY},
119   {"TRACK_MONEY", '\0', TYPE_PLAYER, 0, F_ANY, F_ANY},
120   {"CONNECTED", 'c', TYPE_PLAYER, PLAYER_CONNECT, F_INTERNAL | F_MDARK,
121    F_INTERNAL | F_MDARK},
122   {"GAGGED", 'g', TYPE_PLAYER, PLAYER_GAGGED, F_WIZARD, F_WIZARD},
123   {"MYOPIC", 'm', TYPE_PLAYER, PLAYER_MYOPIC, F_ANY, F_ANY},
124   {"TERSE", 'x', TYPE_PLAYER | TYPE_THING, PLAYER_TERSE, F_ANY, F_ANY},
125   {"JURY_OK", 'j', TYPE_PLAYER, PLAYER_JURY, F_ROYAL, F_ROYAL},
126   {"JUDGE", 'J', TYPE_PLAYER, PLAYER_JUDGE, F_ROYAL, F_ROYAL},
127   {"FIXED", 'F', TYPE_PLAYER, PLAYER_FIXED, F_WIZARD, F_WIZARD},
128   {"UNREGISTERED", '?', TYPE_PLAYER, PLAYER_UNREG, F_ROYAL, F_ROYAL},
129   {"ON-VACATION", 'o', TYPE_PLAYER, PLAYER_VACATION, F_ANY, F_ANY},
130   {"SUSPECT", 's', TYPE_PLAYER, PLAYER_SUSPECT, F_WIZARD | F_MDARK | F_LOG,
131    F_WIZARD | F_MDARK},
132   {"PARANOID", '\0', TYPE_PLAYER, PLAYER_PARANOID, F_ANY | F_ODARK,
133    F_ANY | F_ODARK},
134   {"NOACCENTS", '~', TYPE_PLAYER, PLAYER_NOACCENTS, F_ANY, F_ANY},
135   {"DESTROY_OK", 'd', TYPE_THING, THING_DEST_OK, F_ANY, F_ANY},
136   {"PUPPET", 'p', TYPE_THING, THING_PUPPET, F_ANY, F_ANY},
137   {"NO_LEAVE", 'N', TYPE_THING, THING_NOLEAVE, F_ANY, F_ANY},
138   {"LISTEN_PARENT", '^', TYPE_THING | TYPE_ROOM, 0, F_ANY, F_ANY},
139   {"Z_TEL", 'Z', TYPE_THING | TYPE_ROOM, 0, F_ANY, F_ANY},
140   {"ABODE", 'A', TYPE_ROOM, ROOM_ABODE, F_ANY, F_ANY},
141   {"FLOATING", 'F', TYPE_ROOM, ROOM_FLOATING, F_ANY, F_ANY},
142   {"JUMP_OK", 'J', TYPE_ROOM, ROOM_JUMP_OK, F_ANY, F_ANY},
143   {"NO_TEL", 'N', TYPE_ROOM, ROOM_NO_TEL, F_ANY, F_ANY},
144   {"UNINSPECTED", 'u', TYPE_ROOM, ROOM_UNINSPECT, F_ROYAL, F_ROYAL},
145   {"CLOUDY", 'x', TYPE_EXIT, EXIT_CLOUDY, F_ANY, F_ANY},
146   {"GOING_TWICE", '\0', NOTYPE, GOING_TWICE, F_INTERNAL | F_DARK,
147    F_INTERNAL | F_DARK},
148   {"KEEPALIVE", 'k', TYPE_PLAYER, 0, F_ANY, F_ANY},
149   {NULL, '\0', 0, 0, 0, 0}
150 };
151
152 /** The old table to kludge multi-type toggles. Now used only
153  * for conversion.
154  */
155 static FLAG hack_table[] = {
156   {"MONITOR", 'M', TYPE_PLAYER, PLAYER_MONITOR, F_ROYAL, F_ROYAL},
157   {"MONITOR", 'M', TYPE_THING, THING_LISTEN, F_ANY, F_ANY},
158   {"MONITOR", 'M', TYPE_ROOM, ROOM_LISTEN, F_ANY, F_ANY},
159   {"LISTEN_PARENT", '^', TYPE_THING, THING_INHEARIT, F_ANY, F_ANY},
160   {"LISTEN_PARENT", '^', TYPE_ROOM, ROOM_INHEARIT, F_ANY, F_ANY},
161   {"Z_TEL", 'Z', TYPE_THING, THING_Z_TEL, F_ANY, F_ANY},
162   {"Z_TEL", 'Z', TYPE_ROOM, ROOM_Z_TEL, F_ANY, F_ANY},
163   {NULL, '\0', 0, 0, 0, 0}
164 };
165
166
167 /** A table of types, as if they were flags. Some functions that
168  * expect flags also accept, for historical reasons, types.
169  */
170 static FLAG type_table[] = {
171   {"PLAYER", 'P', TYPE_PLAYER, TYPE_PLAYER, F_INTERNAL, F_INTERNAL},
172   {"ROOM", 'R', TYPE_ROOM, TYPE_ROOM, F_INTERNAL, F_INTERNAL},
173   {"EXIT", 'E', TYPE_EXIT, TYPE_EXIT, F_INTERNAL, F_INTERNAL},
174   {"THING", 'T', TYPE_THING, TYPE_THING, F_INTERNAL, F_INTERNAL},
175   {NULL, '\0', 0, 0, 0, 0}
176 };
177
178 /** A table of types, as privileges. */
179 static PRIV type_privs[] = {
180   {"PLAYER", 'P', TYPE_PLAYER, TYPE_PLAYER},
181   {"ROOM", 'R', TYPE_ROOM, TYPE_ROOM},
182   {"EXIT", 'E', TYPE_EXIT, TYPE_EXIT},
183   {"THING", 'T', TYPE_THING, TYPE_THING},
184   {NULL, '\0', 0, 0}
185 };
186
187 /** The old default aliases for flags. This table is only used in conversion
188  * of old databases. Once a database is converted, the alias list in the
189  * database is what counts.
190  */
191 static FLAG_ALIAS flag_alias_tab[] = {
192   {"INHERIT", "TRUST"},
193   {"TRACE", "DEBUG"},
194   {"NOWARN", "NO_WARN"},
195   {"NOCOMMAND", "NO_COMMAND"},
196   {"LISTENER", "MONITOR"},
197   {"WATCHER", "MONITOR"},
198   {"ZONE", "SHARED"},
199   {"COLOUR", "COLOR"},
200   {"JURYOK", "JURY_OK"},
201 #ifdef VACATION_FLAG
202   {"VACATION", "ON-VACATION"},
203 #endif
204   {"DEST_OK", "DESTROY_OK"},
205   {"NOLEAVE", "NO_LEAVE"},
206   {"TEL_OK", "JUMP_OK"},
207   {"TELOK", "JUMP_OK"},
208   {"TEL-OK", "JUMP_OK"},
209   {"^", "LISTEN_PARENT"},
210
211   {NULL, NULL}
212 };
213
214 /** This is the old defaultpowr table. We still use it when we
215  * have to convert old dbs, but once you have a converted db,
216  * it's the power table in the db that counts, not this one.
217  */
218 /*   Name      Flag   */
219 static FLAG power_table[] = {
220   {"Announce", '\0', NOTYPE, CAN_WALL, F_WIZARD | F_LOG, F_WIZARD},
221   {"Boot", '\0', NOTYPE, CAN_BOOT, F_WIZARD | F_LOG, F_WIZARD},
222   {"Builder", '\0', NOTYPE, CAN_BUILD, F_WIZARD | F_LOG, F_WIZARD},
223   {"Cemit", '\0', NOTYPE, CEMIT, F_WIZARD | F_LOG, F_WIZARD},
224   {"Chat_Privs", '\0', NOTYPE, CHAT_PRIVS, F_WIZARD | F_LOG, F_WIZARD},
225   {"Functions", '\0', NOTYPE, GLOBAL_FUNCS, F_WIZARD | F_LOG, F_WIZARD},
226   {"Guest", '\0', NOTYPE, IS_GUEST, F_WIZARD | F_LOG, F_WIZARD},
227   {"Halt", '\0', NOTYPE, HALT_ANYTHING, F_WIZARD | F_LOG, F_WIZARD},
228   {"Hide", '\0', NOTYPE, CAN_HIDE, F_WIZARD | F_LOG, F_WIZARD},
229   {"Idle", '\0', NOTYPE, UNLIMITED_IDLE, F_WIZARD | F_LOG, F_WIZARD},
230   {"Immortal", '\0', NOTYPE, NO_PAY | NO_QUOTA | UNKILLABLE, F_WIZARD,
231    F_WIZARD},
232   {"Link_Anywhere", '\0', NOTYPE, LINK_ANYWHERE, F_WIZARD | F_LOG, F_WIZARD},
233   {"Login", '\0', NOTYPE, LOGIN_ANYTIME, F_WIZARD | F_LOG, F_WIZARD},
234   {"Long_Fingers", '\0', NOTYPE, LONG_FINGERS, F_WIZARD | F_LOG, F_WIZARD},
235   {"No_Pay", '\0', NOTYPE, NO_PAY, F_WIZARD | F_LOG, F_WIZARD},
236   {"No_Quota", '\0', NOTYPE, NO_QUOTA, F_WIZARD | F_LOG, F_WIZARD},
237   {"Open_Anywhere", '\0', NOTYPE, OPEN_ANYWHERE, F_WIZARD | F_LOG, F_WIZARD},
238   {"Pemit_All", '\0', NOTYPE, PEMIT_ALL, F_WIZARD | F_LOG, F_WIZARD},
239   {"Player_Create", '\0', NOTYPE, CREATE_PLAYER, F_WIZARD | F_LOG, F_WIZARD},
240   {"Poll", '\0', NOTYPE, SET_POLL, F_WIZARD | F_LOG, F_WIZARD},
241   {"Queue", '\0', NOTYPE, HUGE_QUEUE, F_WIZARD | F_LOG, F_WIZARD},
242   {"Quotas", '\0', NOTYPE, CHANGE_QUOTAS, F_WIZARD | F_LOG, F_WIZARD},
243   {"Search", '\0', NOTYPE, SEARCH_EVERYTHING, F_WIZARD | F_LOG, F_WIZARD},
244   {"See_All", '\0', NOTYPE, SEE_ALL, F_WIZARD | F_LOG, F_WIZARD},
245   {"See_Queue", '\0', NOTYPE, PS_ALL, F_WIZARD | F_LOG, F_WIZARD},
246   {"Tport_Anything", '\0', NOTYPE, TEL_OTHER, F_WIZARD | F_LOG, F_WIZARD},
247   {"Tport_Anywhere", '\0', NOTYPE, TEL_ANYWHERE, F_WIZARD | F_LOG, F_WIZARD},
248   {"Unkillable", '\0', NOTYPE, UNKILLABLE, F_WIZARD | F_LOG, F_WIZARD},
249   {"Can_nspemit", '\0', NOTYPE, CAN_NSPEMIT, F_WIZARD | F_LOG, F_WIZARD},
250   {NULL, '\0', 0, 0, 0, 0}
251 };
252
253 /** A table of aliases for powers. */
254 static FLAG_ALIAS power_alias_tab[] = {
255   {"@cemit", "Cemit"},
256   {"@wall", "Announce"},
257   {"wall", "Announce"},
258   {NULL, NULL}
259 };
260
261 /** The table of flag privilege bits. */
262 static PRIV flag_privs[] = {
263   {"trusted", '\0', F_INHERIT, F_INHERIT},
264   {"owned", '\0', F_OWNED, F_OWNED},
265   {"royalty", '\0', F_ROYAL, F_ROYAL},
266   {"wizard", '\0', F_WIZARD, F_WIZARD},
267   {"god", '\0', F_GOD, F_GOD},
268   {"internal", '\0', F_INTERNAL, F_INTERNAL},
269   {"dark", '\0', F_DARK, F_DARK},
270   {"mdark", '\0', F_MDARK, F_MDARK},
271   {"odark", '\0', F_ODARK, F_ODARK},
272   {"disabled", '\0', F_DISABLED, F_DISABLED},
273   {"log", '\0', F_LOG, F_LOG},
274   {NULL, '\0', 0, 0}
275 };
276
277
278
279 /*---------------------------------------------------------------------------
280  * Flag definition functions, including flag hash table handlers
281  */
282
283 /** Convenience function to return a pointer to a flag struct
284  * given the name.
285  * \param name name of flag to find.
286  * \return poiner to flag structure, or NULL.
287  */
288 FLAG *
289 match_flag(const char *name)
290 {
291   return (FLAG *) match_flag_ns(hashfind("FLAG", &htab_flagspaces), name);
292 }
293
294 /** Convenience function to return a pointer to a flag struct
295  * given the name.
296  * \param name name of flag to find.
297  * \return poiner to flag structure, or NULL.
298  */
299 FLAG *
300 match_power(const char *name)
301 {
302   return (FLAG *) match_flag_ns(hashfind("POWER", &htab_flagspaces), name);
303 }
304
305 /** Convenience function to return a pointer to a flag struct
306  * given the name.
307  * \param name name of flag to find.
308  * \return poiner to flag structure, or NULL.
309  */
310 static FLAG *
311 match_flag_ns(FLAGSPACE *n, const char *name)
312 {
313   return (FLAG *) ptab_find(n->tab, name);
314 }
315
316 /** Given a flag name and mask of types, return a pointer to a flag struct.
317  * This function first attempts to match the flag name to a flag of the
318  * right type. If that fails, it tries to match flag characters if the
319  * name is a single character. If all else fails, it tries to match
320  * against an object type name.
321  * \param n pointer to flagspace to search.
322  * \param name name of flag to find.
323  * \param type mask of desired flag object types.
324  * \return pointer to flag structure, or NULL.
325  */
326 static FLAG *
327 flag_hash_lookup(FLAGSPACE *n, const char *name, int type)
328 {
329   FLAG *f;
330
331   f = match_flag_ns(n, name);
332   if (f && !(f->perms & F_DISABLED)) {
333     if (f->type & type)
334       return f;
335     return NULL;
336   }
337
338   /* If the name is a single character, search the flag characters */
339   if (name && *name && !*(name + 1)) {
340     if ((f = letter_to_flagptr(n, *name, type)))
341       return f;
342   }
343
344   if (n->tab == &ptab_flag) {
345     /* provided for backwards compatibility: type flag checking */
346     if (n->flag_table == flag_table) {
347       for (f = type_table; f->name != NULL; f++)
348         if (string_prefix(name, f->name))
349           return f;
350     }
351   }
352
353   return NULL;
354 }
355
356 /* Allocate a new FLAG definition */
357 static FLAG *
358 new_flag(void)
359 {
360   FLAG *f;
361
362   if (flag_slab == NULL)
363     flag_slab = slab_create("flags", sizeof(FLAG));
364   f = slab_malloc(flag_slab, NULL);
365   if (!f)
366     mush_panic("Unable to allocate memory for a new flag!\n");
367   return f;
368 }
369
370 /* Deallocate all flag-related memory */
371 static void
372 clear_all_flags(FLAGSPACE *n)
373 {
374   FLAG *f;
375
376   for (f = ptab_firstentry(n->tab); f; f = ptab_nextentry(n->tab)) {
377     f->perms = DECR_FLAG_REF(f->perms);
378     if (FLAG_REF(f->perms) == 0) {
379       mush_free((void *) f->name, "flag.name");
380       slab_free(flag_slab, f);
381     }
382   }
383
384   ptab_free(n->tab);
385
386   /* Finally, the flags array */
387   if (n->flags)
388     mush_free(n->flags, "flagspace.flags");
389   n->flags = NULL;
390   n->flagbits = 0;
391
392 }
393
394 static FLAG *
395 clone_flag(FLAG *f)
396 {
397   FLAG *clone = new_flag();
398   clone->name = mush_strdup(f->name, "flag.name");
399   clone->letter = f->letter;
400   clone->type = f->type;
401   clone->bitpos = f->bitpos;
402   clone->perms = f->perms;
403   clone->negate_perms = f->negate_perms;
404   return clone;
405 }
406
407 /* This is a stub function to add a flag. It performs no error-checking,
408  * so it's up to you to be sure you're adding a flag that's properly
409  * set up and that'll work ok. If called with autopos == 0, this
410  * auto-allocates the next bitpos. Otherwise, bitpos is ignored and
411  * f->bitpos is used.
412  */
413 static void
414 flag_add(FLAGSPACE *n, const char *name, FLAG *f)
415 {
416   /* If this flag has no bitpos assigned, assign it the next one.
417    * We could improve this algorithm to use the next available
418    * slot after deletions, too, but this will do for now.
419    */
420
421   /* Can't have more than 255 references to the same flag */
422   if (FLAG_REF(f->perms) == 0xFFU)
423     return;
424
425   if (f->bitpos < 0)
426     f->bitpos = n->flagbits;
427
428   f->perms = INCR_FLAG_REF(f->perms);
429
430   /* Insert the flag in the ptab by the given name (maybe an alias) */
431   ptab_insert_one(n->tab