Sie sind auf Seite 1von 1492

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:53 PM

/* alloc.c - memory allocation subsystem */


/* $Id: alloc.c,v 1.23 2002/09/23 08:42:08 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
POOL pools[NUM_POOLS];
const char *poolnames[] =
{"Sbufs", "Mbufs", "Lbufs", "Bools", "Descs", "Qentries", "Pcaches"};
#define POOL_MAGICNUM 0xdeadbeef
void pool_init(poolnum, poolsize)
int poolnum, poolsize;
{
pools[poolnum].pool_size = poolsize;
pools[poolnum].free_head = NULL;
pools[poolnum].chain_head = NULL;
pools[poolnum].tot_alloc = 0;
pools[poolnum].num_alloc = 0;
pools[poolnum].max_alloc = 0;
pools[poolnum].num_lost = 0;
return;
}
static void pool_err(logsys, logflag, poolnum, tag, ph, action, reason)
int logflag, poolnum;
const char *logsys, *tag, *action, *reason;
POOLHDR *ph;
{
if (!mudstate.logging) {
STARTLOG(logflag, logsys, "ALLOC")
log_printf("%s[%d] (tag %s) %s at %lx. (%s)" ,
action, pools[poolnum].pool_size, tag,
reason, (long)ph, mudstate.debug_cmd);
ENDLOG
} else if (logflag != LOG_ALLOCATE) {
log_printf("\n***< %s[%d] (tag %s) %s at %lx. >***" ,
action, pools[poolnum].pool_size, tag, reason,
(long)ph);
}
}
static void pool_vfy(poolnum, tag)
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:53 PM

int poolnum;
const char *tag;
{
POOLHDR *ph, *lastph;
POOLFTR *pf;
char *h;
int psize;
lastph = NULL;
psize = pools[poolnum].pool_size;
for (ph = pools[poolnum].chain_head; ph; lastph = ph, ph = ph->next) {
h = (char *)ph;
h += sizeof(POOLHDR);
h += pools[poolnum].pool_size;
pf = (POOLFTR *) h;
if (ph->magicnum != POOL_MAGICNUM) {
pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph,
"Verify", "header corrupted (clearing freelist)" );
/*
* Break the header chain at this point so we don't
* generate an error for EVERY alloc and free,
* also we can't continue the scan because the
* next pointer might be trash too.
*/
if (lastph)
lastph->next = NULL;
else
pools[poolnum].chain_head = NULL;
return; /* not safe to continue */

}
if (pf->magicnum != POOL_MAGICNUM) {
pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph,
"Verify", "footer corrupted");
pf->magicnum = POOL_MAGICNUM;
}
if (ph->pool_size != psize) {
pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph,
"Verify", "header has incorrect size");
}

void pool_check(tag)
const char *tag;
{
int poolnum;
for (poolnum = 0; poolnum < NUM_POOLS; ++poolnum) {
pool_vfy(poolnum, tag);
}
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

Saturday, June 16, 2012 11:53 PM

}
char *pool_alloc(poolnum, tag)
int poolnum;
const char *tag;
{
int *p;
char *h;
POOLHDR *ph;
POOLFTR *pf;
if (mudconf.paranoid_alloc)
pool_check(tag);
do {
if (pools[poolnum].free_head == NULL) {
h = (char *)RAW_MALLOC(pools[poolnum].pool_size +
sizeof(POOLHDR) + sizeof(POOLFTR),
"pool_alloc.ph");
if (h == NULL) {
fprintf(mainlog_fp, "ABORT! alloc.c, pool_alloc() failed to get
memory.\n");
abort();
}
ph = (POOLHDR *) h;
h += sizeof(POOLHDR);
p = (int *)h;
h += pools[poolnum].pool_size;
pf = (POOLFTR *) h;
ph->next = pools[poolnum].chain_head;
ph->nxtfree = NULL;
ph->magicnum = POOL_MAGICNUM;
ph->pool_size = pools[poolnum].pool_size;
pf->magicnum = POOL_MAGICNUM;
*p = POOL_MAGICNUM;
pools[poolnum].chain_head = ph;
pools[poolnum].max_alloc++;
} else {
ph = (POOLHDR *) (pools[poolnum].free_head);
h = (char *)ph;
h += sizeof(POOLHDR);
p = (int *)h;
h += pools[poolnum].pool_size;
pf = (POOLFTR *) h;
pools[poolnum].free_head = ph->nxtfree;
/* If corrupted header we need to throw away the
* freelist as the freelist pointer may be corrupt.
*/
if (ph->magicnum != POOL_MAGICNUM) {
pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph,
"Alloc", "corrupted buffer header");

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

Saturday, June 16, 2012 11:53 PM

/* Start a new free list and record stats */


p = NULL;
pools[poolnum].free_head = NULL;
pools[poolnum].num_lost +=
(pools[poolnum].tot_alloc pools[poolnum].num_alloc);
pools[poolnum].tot_alloc =
pools[poolnum].num_alloc;

}
/* Check for corrupted footer, just report and fix
* it
*/
if (pf->magicnum != POOL_MAGICNUM) {
pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph,
"Alloc", "corrupted buffer footer");
pf->magicnum = POOL_MAGICNUM;
}

}
} while (p == NULL);

ph->buf_tag = (char *)tag;


pools[poolnum].tot_alloc++;
pools[poolnum].num_alloc++;
pool_err("DBG", LOG_ALLOCATE, poolnum, tag, ph, "Alloc", "buffer");
/* If the buffer was modified after it was last freed, log it. */

if ((*p != POOL_MAGICNUM) && (!mudstate.logging)) {


pool_err("BUG", LOG_PROBLEMS, poolnum, tag, ph, "Alloc",
"buffer modified after free");
}
*p = 0;
return (char *)p;

void pool_free(poolnum, buf)


int poolnum;
char **buf;
{
int *ibuf;
char *h;
POOLHDR *ph;
POOLFTR *pf;
ibuf = (int *)*buf;
h = (char *)ibuf;
h -= sizeof(POOLHDR);
ph = (POOLHDR *) h;
h = (char *)ibuf;
h += pools[poolnum].pool_size;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

Saturday, June 16, 2012 11:53 PM

pf = (POOLFTR *) h;
if (mudconf.paranoid_alloc)
pool_check(ph->buf_tag);
/* Make sure the buffer header is good.
* and throw away the buffer.
*/

If it isn't, log the error

if (ph->magicnum != POOL_MAGICNUM) {
pool_err("BUG", LOG_ALWAYS, poolnum, ph->buf_tag, ph, "Free",
"corrupted buffer header");
pools[poolnum].num_lost++;
pools[poolnum].num_alloc--;
pools[poolnum].tot_alloc--;
return;
}
/* Verify the buffer footer. Don't unlink if damaged, just repair */
if (pf->magicnum != POOL_MAGICNUM) {
pool_err("BUG", LOG_ALWAYS, poolnum, ph->buf_tag, ph, "Free",
"corrupted buffer footer");
pf->magicnum = POOL_MAGICNUM;
}
/* Verify that we are not trying to free someone else's buffer */
if (ph->pool_size != pools[poolnum].pool_size) {
pool_err("BUG", LOG_ALWAYS, poolnum, ph->buf_tag, ph, "Free",
"Attempt to free into a different pool." );
return;
}
pool_err("DBG", LOG_ALLOCATE, poolnum, ph->buf_tag, ph, "Free",
"buffer");
/* Make sure we aren't freeing an already free buffer. If we are,
* log an error, otherwise update the pool header and stats
*/

if (*ibuf == POOL_MAGICNUM) {
pool_err("BUG", LOG_BUGS, poolnum, ph->buf_tag, ph, "Free",
"buffer already freed");
} else {
*ibuf = POOL_MAGICNUM;
ph->nxtfree = pools[poolnum].free_head;
pools[poolnum].free_head = ph;
pools[poolnum].num_alloc--;
}

static char *pool_stats(poolnum, text)


int poolnum;
const char *text;
{
char *buf;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

Saturday, June 16, 2012 11:53 PM

buf = alloc_mbuf("pool_stats");
sprintf(buf, "%-15s %5d%9d%9d%9d%9d", text, pools[poolnum].pool_size,
pools[poolnum].num_alloc, pools[poolnum].max_alloc,
pools[poolnum].tot_alloc, pools[poolnum].num_lost);
return buf;

static void pool_trace(player, poolnum, text)


dbref player;
int poolnum;
const char *text;
{
POOLHDR *ph;
int numfree, *ibuf;
char *h;

numfree = 0;
notify(player, tprintf("----- %s -----", text));
for (ph = pools[poolnum].chain_head; ph != NULL; ph = ph->next) {
if (ph->magicnum != POOL_MAGICNUM) {
notify(player, "*** CORRUPTED BUFFER HEADER, ABORTING SCAN ***" );
notify(player,
tprintf("%d free %s (before corruption)" ,
numfree, text));
return;
}
h = (char *)ph;
h += sizeof(POOLHDR);
ibuf = (int *)h;
if (*ibuf != POOL_MAGICNUM)
notify(player, ph->buf_tag);
else
numfree++;
}
notify(player, tprintf("%d free %s", numfree, text));

void list_bufstats(player)
dbref player;
{
int i;
char *buff;
notify(player,
"Buffer Stats

Size

InUse

Total

for (i = 0; i < NUM_POOLS; i++) {


buff = pool_stats(i, poolnames[i]);
notify(player, buff);
free_mbuf(buff);
}

-6-

Allocs

Lost" );

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

Saturday, June 16, 2012 11:53 PM

void list_buftrace(player)
dbref player;
{
int i;

for (i = 0; i < NUM_POOLS; i++)


pool_trace(player, i, poolnames[i]);

void pool_reset()
{
POOLHDR *ph, *phnext, *newchain;
int i, *ibuf;
char *h;

for (i = 0; i < NUM_POOLS; i++) {


newchain = NULL;
for (ph = pools[i].chain_head; ph != NULL; ph = phnext) {
h = (char *)ph;
phnext = ph->next;
h += sizeof(POOLHDR);
ibuf = (int *)h;
if (*ibuf == POOL_MAGICNUM) {
RAW_FREE(ph, "pool_reset.ph");
} else {
if (!newchain) {
newchain = ph;
ph->next = NULL;
} else {
ph->next = newchain;
newchain = ph;
}
ph->nxtfree = NULL;
}
}
pools[i].chain_head = newchain;
pools[i].free_head = NULL;
pools[i].max_alloc = pools[i].num_alloc;
}

/* --------------------------------------------------------------------------* Track allocations that don't use the memory pools.


*/
#ifdef RAW_MEMTRACKING
static int sort_memtable(p1, p2)
const void *p1, *p2;
{
return strcmp((*(MEMTRACK **)p1)->buf_tag,
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

Saturday, June 16, 2012 11:53 PM

(*(MEMTRACK **)p2)->buf_tag);

void list_rawmemory(player)
dbref player;
{
MEMTRACK *tptr, **t_array;
int n_tags, total, c_tags, c_total, u_tags, i, j;
const char *ntmp;
n_tags = total = 0;
raw_notify(player,
"Memory Tag

Allocs

Bytes" );

for (tptr = mudstate.raw_allocs; tptr != NULL; tptr = tptr->next) {


n_tags++;
total += (int) tptr->alloc;
}
t_array = (MEMTRACK **) RAW_CALLOC(total, sizeof(MEMTRACK *),
"list_rawmemory");
for (i = 0, tptr = mudstate.raw_allocs; tptr != NULL;
i++, tptr = tptr->next) {
t_array[i] = tptr;
}
qsort((void *) t_array, n_tags, sizeof(MEMTRACK *),
(int (*)(const void *, const void *))sort_memtable);
for (i = 0; i < n_tags; ) {
u_tags++;
ntmp = t_array[i]->buf_tag;
if ((i < n_tags - 1) &&
!strcmp(ntmp, t_array[i+1]->buf_tag)) {
c_tags = 2;
c_total = (int) t_array[i]->alloc + (int) t_array[i+1]->alloc;
for (j = i + 2; (j < n_tags) &&
!strcmp(ntmp, t_array[j]->buf_tag);
j++) {
c_tags++;
c_total += (int) t_array[j]->alloc;
}
i = j;
} else {
c_tags = 1;
c_total = (int) t_array[i]->alloc;
i++;
}
raw_notify(player,
tprintf("%-35.35s %6d
%8d", ntmp, c_tags, c_total));
}
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

Saturday, June 16, 2012 11:53 PM

RAW_FREE(t_array, "list_rawmemory");

raw_notify(player,
tprintf("Total: %d raw allocations in %d unique tags. %d bytes (%d K)." ,
n_tags, u_tags, total, (int) total / 1024));

static void trace_alloc(amount, name, ptr)


size_t amount;
const char *name;
void *ptr;
{
/* We maintain an unsorted list, most recently-allocated things at
* the head, based on the belief that it's basically a stack -* when we go to free something it's usually the most recent thing
* that we've allocated.
*/
MEMTRACK *tptr;
tptr = (MEMTRACK *) RAW_MALLOC(sizeof(MEMTRACK), "trace_alloc.tptr");
if (!tptr)
return;

tptr->buf_tag = name;
tptr->bptr = ptr;
tptr->alloc = amount;
tptr->next = mudstate.raw_allocs;
mudstate.raw_allocs = tptr;

static void trace_free(name, ptr)


const char *name;
void *ptr;
{
MEMTRACK *tptr, *prev;
prev = NULL;
for (tptr = mudstate.raw_allocs; tptr != NULL; tptr = tptr->next) {
if (tptr->bptr == ptr) {
if (strcmp(tptr->buf_tag, name)) {
STARTLOG(LOG_BUGS, "MEM", "TRACE")
log_printf("Free mismatch, tag %s allocated as %s" ,
name, tptr->buf_tag);
ENDLOG
}
if (mudstate.raw_allocs == tptr)
mudstate.raw_allocs = tptr->next;
if (prev)
prev->next = tptr->next;
RAW_FREE(tptr, "trace_alloc.tptr");
return;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

Saturday, June 16, 2012 11:53 PM

}
prev = tptr;
}

STARTLOG(LOG_BUGS, "MEM", "TRACE")


log_printf("Attempt to free unknown with tag %s" , name);
ENDLOG

void *track_malloc(amount, name)


size_t amount;
const char *name;
{
void *r;

r = malloc(amount);
trace_alloc(amount, name, r);
return (r);

void *track_calloc(elems, esize, name)


size_t elems, esize;
const char *name;
{
void *r;

r = calloc(elems, esize);
trace_alloc(elems * esize, name, r);
return (r);

void *track_realloc(ptr, amount, name)


void *ptr;
size_t amount;
const char *name;
{
void *r;

trace_free(name, r);
r = realloc(ptr, amount);
trace_alloc(amount, name, r);
return (r);

char *track_strdup(str, name)


const char *str, *name;
{
char *r;

r = strdup(str);
trace_alloc(strlen(str) + 1, name, r);
return (r);

-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.c

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549

Saturday, June 16, 2012 11:53 PM

void track_free(ptr, name)


void *ptr;
const char *name;
{
trace_free(name, ptr);
free(ptr);
}
#else
void list_rawmemory(player)
dbref player;
{
notify(player, "Feature not supported.");
}
#endif /* RAW_MEMTRACKING */

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:19 PM

/* alloc.h - External definitions for memory allocation subsystem */


/* $Id: alloc.h,v 1.18 2002/09/23 04:59:36 rmg Exp $ */
#include "copyright.h"
#ifndef __ALLOC_H
#define __ALLOC_H
/* We need to 64-bit-align the end of the pool header. */
typedef struct pool_header {
int magicnum;
/* For consistency check */
int pool_size;
/* For consistency check */
struct pool_header *next;
/* Next pool header in chain */
struct pool_header *nxtfree;
/* Next pool header in freelist */
char *buf_tag;
/* Debugging/trace tag */
char align[(256 - 2 * sizeof(int) - 3 * sizeof(char *)) & 0x7];
} POOLHDR;
typedef struct pool_footer {
int magicnum;
/* For consistency check */
} POOLFTR;
typedef struct pooldata {
int pool_size;
/*
POOLHDR *free_head; /*
POOLHDR *chain_head;
int tot_alloc;
/*
int num_alloc;
/*
int max_alloc;
/*
int num_lost;
/*
} POOL;

Size in bytes of a buffer */


Buffer freelist head */
/* Buffer chain head */
Total buffers allocated */
Number of buffers currently allocated */
Max # buffers allocated at one time */
Buffers lost due to corruption */

#define
#define
#define
#define
#define
#define
#define
#define

POOL_SBUF
POOL_MBUF
POOL_LBUF
POOL_BOOL
POOL_DESC
POOL_QENTRY
POOL_PCACHE
NUM_POOLS

0
1
2
3
4
5
6
7

#define
#define
#define
#define

LBUF_SIZE
GBUF_SIZE
MBUF_SIZE
SBUF_SIZE

8000
/* standard lbuf */
1024
/* generic buffer size */
400 /* standard mbuf */
64 /* standard sbuf, short strings */

/*
#define LBUF_SIZE
#define MBUF_SIZE
#define SBUF_SIZE
*/

4000
200
32

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

Saturday, June 16, 2012 11:19 PM

/* --------------------------------------------------------------------------* Basic allocation.


*/
#define
#define
#define
#define
#define

RAW_MALLOC(x,y) (malloc(x))
RAW_CALLOC(x,z,y) (calloc((x),(z)))
RAW_REALLOC(x,z,y) (realloc((x),(z)))
RAW_STRDUP(x,y) (strdup(x))
RAW_FREE(x,y) (free((void *)(x)), (x) = NULL)

#ifdef TEST_MALLOC
extern
extern
extern
extern

int malloc_count;
int malloc_bytes;
char *malloc_str;
char *malloc_ptr;

#define XMALLOC(x,y) (fprintf(stderr,"Malloc: %s/%d\n", (y), (x)), malloc_count++, \


malloc_ptr = (char *)malloc((x) + sizeof(int)), malloc_bytes +=
(x), \
*(int *)malloc_ptr = (x), malloc_ptr + sizeof(int))
#define XCALLOC(x,z,y) (fprintf(stderr,"Calloc: %s/%d\n", (y), (x)*(z)),
malloc_count++, \
malloc_ptr = (char *)malloc((x)*(z) + sizeof(int)), malloc_bytes +=
(x)*(z), \
memset(malloc_ptr, 0, (x)*(z) + sizeof(int)), \
*(int *)malloc_ptr = (x)*(z), malloc_ptr + sizeof(int))
#define XREALLOC(x,z,y) (fprintf(stderr,"Realloc: %s/%d\n", (y), (z)), \
malloc_ptr = (char *)malloc((z) + sizeof(int)), malloc_bytes +=
(z), \
malloc_bytes -= *(int *)((char *)(x)-sizeof(int)),
memcpy(malloc_ptr + sizeof(int), (x), *(int *)((char *)(x) sizeof(int))), \
free((char *)(x) - sizeof(int)), *(int *)malloc_ptr = (z),
malloc_ptr + sizeof(int))
#define XSTRDUP(x,y) (malloc_str = (char *)(x), \
fprintf(stderr,"Strdup: %s/%d\n", (y), strlen(malloc_str)+1),
malloc_count++, \
malloc_ptr = (char *)malloc(strlen(malloc_str) + 1 + sizeof(int)), \
malloc_bytes += strlen(malloc_str) + 1, strcpy(malloc_ptr +
sizeof(int), malloc_str), \
*(int *)malloc_ptr = strlen(malloc_str) + 1, malloc_ptr +
sizeof(int))
#define XSTRNDUP(x,z,y) (malloc_str = (char *)(x), \
fprintf(stderr,"Strndup: %s/%d\n", (y), strlen(malloc_str)+1),
malloc_count++, \
malloc_ptr = (char *)malloc((z) + sizeof(int)), \
malloc_bytes += (z), strncpy(malloc_ptr + sizeof(int), malloc_str,
(z)), \
*(int *)malloc_ptr = (z), malloc_ptr + sizeof(int))
#define XFREE(x,y) (fprintf(stderr, "Free: %s/%d\n", (y), (x) ? *(int *)((char
*)(x)-sizeof(int)) : 0), \
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.h

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

Saturday, June 16, 2012 11:19 PM

((x) ? malloc_count--, malloc_bytes -= *(int *)((char


*)(x)-sizeof(int)), \
free((char *)(x) - sizeof(int)), (x)=NULL : (x)))
#else

/* ! TEST_MALLOC

*/

#ifdef RAW_MEMTRACKING
#define
#define
#define
#define
#define
extern
extern
extern
extern
extern

XMALLOC(x,y) (track_malloc((x),(y)))
XCALLOC(x,z,y) (track_calloc((x),(z),(y)))
XREALLOC(x,z,y) (track_realloc((x),(z),(y)))
XSTRDUP(x,y) (track_strdup((x),(y)))
XFREE(x,y) (track_free((void *)(x),(y)), (x) = NULL)
void
void
void
char
void

*
FDECL(track_malloc, (size_t, const char *));
*
FDECL(track_calloc, (size_t, size_t, const char *));
*
FDECL(track_realloc, (void *, size_t, const char *));
*
FDECL(track_strdup, (const char *, const char *));
FDECL(track_free, (void *, const char *));

typedef struct tracemem_header {


void *bptr;
const char *buf_tag;
size_t alloc;
struct tracemem_header *next;
} MEMTRACK;
#else
#define
#define
#define
#define
#define

XMALLOC(x,y)
RAW_MALLOC((x),(y))
XCALLOC(x,z,y) RAW_CALLOC((x),(z),(y))
XREALLOC(x,z,y) RAW_REALLOC((x),(z),(y))
XSTRDUP(x,y)
RAW_STRDUP((x),(y))
XFREE(x,y) RAW_FREE((x),(y))

#endif
#endif

/* RAW_MEMTRACKING */
/* TEST_MALLOC */

/* --------------------------------------------------------------------------* Pool allocation.


*/
extern
extern
extern
extern
extern
#define
#define
#define
#define
#define

void
char
void
void
void

FDECL(pool_init, (int, int));


*
FDECL(pool_alloc, (int, const char *));
FDECL(pool_free, (int, char **));
FDECL(list_bufstats, (dbref));
FDECL(list_buftrace, (dbref));

alloc_lbuf(s)
free_lbuf(b)
alloc_mbuf(s)
free_mbuf(b)
alloc_sbuf(s)

pool_alloc(POOL_LBUF,s)
pool_free(POOL_LBUF,((char **)&(b)))
pool_alloc(POOL_MBUF,s)
pool_free(POOL_MBUF,((char **)&(b)))
pool_alloc(POOL_SBUF,s)
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\alloc.h

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

#define
#define
#define
#define
#define
#define
#define

free_sbuf(b)
alloc_bool(s)
free_bool(b)
alloc_qentry(s)
free_qentry(b)
alloc_pcache(s)
free_pcache(b)

Saturday, June 16, 2012 11:19 PM

pool_free(POOL_SBUF,((char **)&(b)))
(struct boolexp *)pool_alloc(POOL_BOOL,s)
pool_free(POOL_BOOL,((char **)&(b)))
(BQUE *)pool_alloc(POOL_QENTRY,s)
pool_free(POOL_QENTRY,((char **)&(b)))
(PCACHE *)pool_alloc(POOL_PCACHE,s)
pool_free(POOL_PCACHE,((char **)&(b)))

#define safe_copy_chr(scc__src,scc__buff,scc__bufp,scc__max) {\
char *scc__tp;\
\
scc__tp = *scc__bufp;\
if ((scc__tp - scc__buff) < scc__max) {\
*scc__tp++ = scc__src;\
*scc__bufp = scc__tp;\
*scc__tp = '\0';\
} else {\
scc__buff[scc__max] = '\0';\
}\
}
#define
#define
#define
#define
#define
#define
#define
#define
#define

safe_str(s,b,p)
safe_copy_str((s),(b),(p),(LBUF_SIZE-1))
safe_str_fn(s,b,p) safe_copy_str_fn((s),(b),(p),(LBUF_SIZE-1))
safe_chr(c,b,p)
safe_copy_chr((c),(b),(p),(LBUF_SIZE-1))
safe_long_str(s,b,p)
safe_copy_long_str((s),(b),(p),(LBUF_SIZE-1))
safe_sb_str(s,b,p) safe_copy_str((s),(b),(p),(SBUF_SIZE-1))
safe_sb_chr(c,b,p) safe_copy_chr((c),(b),(p),(SBUF_SIZE-1))
safe_mb_str(s,b,p) safe_copy_str((s),(b),(p),(MBUF_SIZE-1))
safe_mb_chr(c,b,p) safe_copy_chr((c),(b),(p),(MBUF_SIZE-1))
safe_chr_fn(c,b,p)
safe_chr_real_fn((c),(b),(p),(LBUF_SIZE-1))

#endif

/* __ALLOC_H */

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ansi.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:19 PM

/* ansi.h - ANSI control codes for various neat-o terminal effects. */


/* $Id: ansi.h,v 1.19 2005/10/16 04:01:41 alierak Exp $ */
#include "copyright.h"
#ifndef __ANSI_H
#define __ANSI_H
#define BEEP_CHAR
#define ESC_CHAR

'\07'
'\033'

#define ANSI_CSI
#define ANSI_END

'['
'm'

#define ANSI_NORMAL

"\033[0m"

#define
#define
#define
#define

ANSI_HILITE
ANSI_INVERSE
ANSI_BLINK
ANSI_UNDER

"\033[1m"
"\033[7m"
"\033[5m"
"\033[4m"

#define
#define
#define
#define

ANSI_INV_BLINK
ANSI_INV_HILITE
ANSI_BLINK_HILITE
ANSI_INV_BLINK_HILITE

"\033[7;5m"
"\033[1;7m"
"\033[1;5m"
"\033[1;5;7m"

/* Foreground colors */
#define
#define
#define
#define
#define
#define
#define
#define

ANSI_BLACK "\033[30m"
ANSI_RED
"\033[31m"
ANSI_GREEN "\033[32m"
ANSI_YELLOW "\033[33m"
ANSI_BLUE
"\033[34m"
ANSI_MAGENTA
"\033[35m"
ANSI_CYAN
"\033[36m"
ANSI_WHITE "\033[37m"

/* Background colors */
#define
#define
#define
#define
#define
#define
#define
#define

ANSI_BBLACK "\033[40m"
ANSI_BRED
"\033[41m"
ANSI_BGREEN "\033[42m"
ANSI_BYELLOW
"\033[43m"
ANSI_BBLUE "\033[44m"
ANSI_BMAGENTA
"\033[45m"
ANSI_BCYAN "\033[46m"
ANSI_BWHITE "\033[47m"

/* Numeric-only definitions */
#define N_ANSI_NORMAL

"0"

#define N_ANSI_HILITE

"1"
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ansi.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

#define N_ANSI_INVERSE
#define N_ANSI_BLINK
#define N_ANSI_UNDER

"7"
"5"
"4"

#define
#define
#define
#define
#define
#define
#define
#define

N_ANSI_BLACK
"30"
N_ANSI_RED "31"
N_ANSI_GREEN
"32"
N_ANSI_YELLOW
"33"
N_ANSI_BLUE "34"
N_ANSI_MAGENTA "35"
N_ANSI_CYAN "36"
N_ANSI_WHITE
"37"

#define
#define
#define
#define
#define
#define
#define
#define

N_ANSI_BBLACK
"40"
N_ANSI_BRED "41"
N_ANSI_BGREEN
"42"
N_ANSI_BYELLOW "43"
N_ANSI_BBLUE
"44"
N_ANSI_BMAGENTA "45"
N_ANSI_BCYAN
"46"
N_ANSI_BWHITE
"47"

#define N_ANSI_NORMAL

Saturday, June 16, 2012 11:19 PM

"0"

/* Integers */
#define I_ANSI_NORMAL

#define
#define
#define
#define

I_ANSI_HILITE
I_ANSI_INVERSE
I_ANSI_BLINK
I_ANSI_UNDER

1
7
5
4

#define
#define
#define
#define
#define
#define
#define
#define

I_ANSI_BLACK
I_ANSI_RED 31
I_ANSI_GREEN
I_ANSI_YELLOW
I_ANSI_BLUE 34
I_ANSI_MAGENTA
I_ANSI_CYAN 36
I_ANSI_WHITE

30

#define
#define
#define
#define
#define
#define
#define
#define

I_ANSI_BBLACK
I_ANSI_BRED 41
I_ANSI_BGREEN
I_ANSI_BYELLOW
I_ANSI_BBLUE
I_ANSI_BMAGENTA
I_ANSI_BCYAN
I_ANSI_BWHITE

40

#define I_ANSI_NUM
#define I_ANSI_LIM

32
33
35
37

42
43
44
45
46
47

48
50
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ansi.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:19 PM

#define ANST_NORMAL 0x0099


#define ANST_NONE
0x1099
/* From stringutil.c */
extern int ansi_nchartab[256];
extern char ansi_lettab[I_ANSI_NUM];
extern int ansi_mask_bits[I_ANSI_LIM];
extern int ansi_bits[I_ANSI_LIM];
extern
extern
extern
extern
extern
extern
extern

char
int
char
char
char
char
int

*
FDECL(strip_ansi, (const char *));
FDECL(strip_ansi_len, (const char *));
*
FDECL(normal_to_white, (const char *));
*
FDECL(ansi_transition_esccode, (int, int));
*
FDECL(ansi_transition_mushcode, (int, int));
*
FDECL(ansi_transition_letters, (int, int));
FDECL(ansi_map_states, (const char *, int **, char **));

#define skip_esccode(s) \
++(s);
\
if (*(s) == ANSI_CSI) {
\
do {
\
++(s);
\
} while ((*(s) & 0xf0) == 0x30);
}
\
while ((*(s) & 0xf0) == 0x20) {
++(s);
\
}
\
if (*(s)) {
\
++(s);
\
}
#define copy_esccode(s, t) \
*(t)++ = *(s)++;
\
if (*(s) == ANSI_CSI) {
\
do {
\
*(t)++ = *(s)++;
\
} while ((*(s) & 0xf0) == 0x30);
}
\
while ((*(s) & 0xf0) == 0x20) {
*(t)++ = *(s)++;
\
}
\
if (*(s)) {
\
*(t)++ = *(s)++;
\
}

\
\

\
\

#define safe_copy_esccode(s, buff, bufc) \


safe_chr(*(s), (buff), (bufc));
\
++(s);
\
if (*(s) == ANSI_CSI) {
\
do {
\
safe_chr(*(s), (buff), (bufc)); \
++(s);
\
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ansi.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:19 PM

} while ((*(s) & 0xf0) == 0x30);


}
\
while ((*(s) & 0xf0) == 0x20) {
safe_chr(*(s), (buff), (bufc));
++(s);
\
}
\
if (*(s)) {
\
safe_chr(*(s), (buff), (bufc));
++(s);
\
}

\
\
\

#define track_esccode(s, ansi_state) \


do {
\
int ansi_mask = 0;
\
int ansi_diff = 0;
\
unsigned int param_val = 0;
\
\
++(s);
\
if (*(s) == ANSI_CSI) {
\
while ((*(++(s)) & 0xf0) == 0x30) {
\
if (*(s) < 0x3a) {
\
param_val <<= 1;
\
param_val += (param_val << 2) + (*(s) & 0x0f); \
} else {
\
if (param_val < I_ANSI_LIM) {
\
ansi_mask |= ansi_mask_bits[param_val]; \
ansi_diff = ((ansi_diff & ~ansi_mask_bits[param_val]) | \
ansi_bits[param_val]); \
}
\
param_val = 0;
\
}
\
}
\
}
\
while ((*(s) & 0xf0) == 0x20) {
\
++(s);
\
}
\
if (*(s) == ANSI_END) {
\
if (param_val < I_ANSI_LIM) {
\
ansi_mask |= ansi_mask_bits[param_val];
\
ansi_diff = ((ansi_diff & ~ansi_mask_bits[param_val]) | \
ansi_bits[param_val]);
\
}
\
ansi_state = (ansi_state & ~ansi_mask) | ansi_diff; \
++(s);
\
} else if (*(s)) {
\
++(s);
\
}
\
} while (0)
#define track_all_esccodes(s, p, ansi_state) \
do {
\
(p) = (s);
\
while (*(p)) {
\
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ansi.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

Saturday, June 16, 2012 11:19 PM

if (*(p) == ESC_CHAR) {
\
track_esccode((p), (ansi_state));
} else {
\
++(p);
\
}
\
}
\
} while (0)

#define safe_copy_tracking(s, p, ansi_state, buff, bufc) \


track_all_esccodes((s), (p), (ansi_state));
\
safe_known_str((s), (p) - (s), (buff), (bufc))
/* Macro for turning mushcode ansi letters into a packed ansi state.
* s is a throwaway char *, t is the sequence of ansi letters, and
* ansi_state is an int that will contain the result.
*/
#define track_ansi_letters(s, t, ansi_state) \
ansi_state = ANST_NONE; \
(s) = (t); \
while (*(s)) { \
if (*(s) == ESC_CHAR) { \
skip_esccode((s)); \
} else { \
(ansi_state) = (((ansi_state) & ~ansi_mask_bits[ansi_nchartab[(unsigned
char) *(s)]]) | \
ansi_bits[ansi_nchartab[(unsigned char) *(s)]]); \
++(s); \
} \
}
#endif /* __ANSI_H */

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\api.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:53 PM

/* api.c - functions called only by modules */


/* $Id: api.c,v 1.14 2002/05/11 16:34:39 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include
#include
#include
#include

"command.h"
"match.h" /*
"attrs.h" /*
"powers.h" /*
"functions.h"
"udb_defs.h"
"udb.h"
/*

/* required by code */
required by code */
required by code */
required by code */
/* required by code */
/* required by code */
required by code */

extern CMDENT *prefix_cmds[256];


/* --------------------------------------------------------------------------* Exporting a module's own API.
*/
void register_api(module_name, api_name, ftable)
char *module_name, *api_name;
API_FUNCTION *ftable;
{
MODULE *mp;
API_FUNCTION *afp;
void (*fn_ptr)(void *, void *);
int succ = 0;
WALK_ALL_MODULES(mp) {
if (!strcmp(module_name, mp->modname)) {
succ = 1;
break;
}
}
if (!succ)
/* no such module */
return;
for (afp = ftable; afp->name; afp++) {
fn_ptr = DLSYM(mp->handle, module_name, afp->name, (void *, void *));
if (fn_ptr != NULL) {
afp->handler = fn_ptr;
hashadd(tprintf("%s_%s", api_name, afp->name),
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\api.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

}
}

Saturday, June 16, 2012 11:53 PM

(int *) afp, &mudstate.api_func_htab, 0);

void *request_api_function(api_name, fn_name)


char *api_name, *fn_name;
{
API_FUNCTION *afp;

afp = (API_FUNCTION *) hashfind(tprintf("%s_%s", api_name, fn_name),


&mudstate.api_func_htab);
if (!afp)
return NULL;
return afp->handler;

/* --------------------------------------------------------------------------* Handle tables.


*/
void register_commands(cmdtab)
CMDENT *cmdtab;
{
CMDENT *cp;

if (cmdtab) {
for (cp = cmdtab; cp->cmdname; cp++) {
hashadd(cp->cmdname, (int *) cp, &mudstate.command_htab, 0);
hashadd(tprintf("__%s", cp->cmdname), (int *) cp, &mudstate.command_htab,
HASH_ALIAS);
}
}

void register_prefix_cmds(cmdchars)
const char *cmdchars;
{
const char *cp;
char cn[2] = "x";

if (cmdchars) {
for (cp = cmdchars; *cp; cp++) {
cn[0] = *cp;
prefix_cmds[(unsigned char)*cp] = (CMDENT *) hashfind(cn, &mudstate.
command_htab);
}
}

void register_functions(functab)
FUN *functab;
{
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\api.c

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

Saturday, June 16, 2012 11:53 PM

FUN *fp;

if (functab) {
for (fp = functab; fp->name; fp++) {
hashadd((char *)fp->name, (int *) fp, &mudstate.func_htab, 0);
}
}

void register_hashtables(htab, ntab)


MODHASHES *htab;
MODNHASHES *ntab;
{
MODHASHES *hp;
MODNHASHES *np;
if (htab) {
for (hp = htab; hp->tabname != NULL; hp++) {
hashinit(hp->htab, hp->size_factor * HASH_FACTOR, HT_STR);
}
}

if (ntab) {
for (np = ntab; np->tabname != NULL; np++) {
nhashinit(np->htab, np->size_factor * HASH_FACTOR);
}
}

/* --------------------------------------------------------------------------* Deal with additional database info.


*/
unsigned int register_dbtype(modname)
char *modname;
{
unsigned int type;
DBData key, data;
/* Find out if the module already has a registered DB type */
key.dptr = modname;
key.dsize = strlen(modname) + 1;
data = db_get(key, DBTYPE_MODULETYPE);
if (data.dptr) {
memcpy((void *)&type, (void *)data.dptr, sizeof(unsigned int));
XFREE(data.dptr, "register_dbtype");
return type;
}
/* If the type is in range, return it, else return zero as
* an error code */
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\api.c

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

Saturday, June 16, 2012 11:53 PM

if ((mudstate.moduletype_top >= DBTYPE_RESERVED) &&


(mudstate.moduletype_top < DBTYPE_END)) {
/* Write the entry to GDBM */

data.dptr = &mudstate.moduletype_top;
data.dsize = sizeof(unsigned int);
db_put(key, data, DBTYPE_MODULETYPE);
type = mudstate.moduletype_top;
mudstate.moduletype_top++;
return type;
} else {
return 0;
}

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\api.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:18 PM

/* api.h - must be included by all dynamically loaded modules */


/* $Id: api.h,v 1.15 2002/10/27 07:38:18 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#ifndef __API_H
#define __API_H
#include
#include
#include
#include

"alloc.h"
"flags.h"
"htab.h"
"mudconf.h"

#include "db.h"
#include "externs.h"
#include "interface.h"
#include
#include
#include
#include
#include
#include

/*
/*
/*
/*

required
required
required
required

by
by
by
by

mudconf */
mudconf */
mudconf */
code */

/* required by externs */
/* required by interface */
/* required by code */

"command.h"
/* required by code
"match.h"
/* required by code
"attrs.h"
/* required by code
"powers.h"
/* required by code
"ansi.h"
/* required by code */
"functions.h" /* required by code

*/
*/
*/
*/
*/

/* -----------------------------------------------------------------------* Command handler macros.


*/
#define DO_CMD_NO_ARG(name) \
void name (player, cause, key) \
dbref player, cause; \
int key;
#define DO_CMD_ONE_ARG(name) \
void name (player, cause, key, arg1) \
dbref player, cause; \
int key; \
char *arg1;
#define DO_CMD_TWO_ARG(name) \
void name (player, cause, key, arg1, arg2) \
dbref player, cause; \
int key; \
char *arg1, *arg2;
#define DO_CMD_TWO_ARG_ARGV(name) \
void name (player, cause, key, arg1, arg2_vector, vector_size) \
dbref player, cause; \
int key; \
char *arg1; \
char *arg2_vector[]; \
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\api.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

Saturday, June 16, 2012 11:18 PM

int vector_size;
/* -----------------------------------------------------------------------* API interface macros.
*/
#define SIZE_HACK 1
#define DB_GROW_MODULE(old_db,new_size,new_top,proto) \
{ \
char *dg__cp; \
proto *dg__new_db; \
int dg__i; \
dg__new_db = (proto *) XMALLOC((new_size + SIZE_HACK) * sizeof(proto),
"db_grow.mod_db"); \
if (!dg__new_db) { \
STARTLOG(LOG_ALWAYS, "ALC", "DB") \
log_printf("Could not allocate space for %d item module struct database.",
new_size); \
ENDLOG \
abort(); \
} \
if (old_db) { \
old_db -= SIZE_HACK; \
memcpy((char *) dg__new_db, (char *) old_db, \
(mudstate.db_top + SIZE_HACK) * sizeof(proto)); \
dg__cp = (char *) old_db; \
XFREE(dg__cp, "db_grow.mod_db"); \
} else { \
old_db = dg__new_db; \
for (dg__i = 0; dg__i < SIZE_HACK; dg__i++) {
/* 'NOTHING' fill */ \
OBJ_INIT_MODULE(dg__i);
/* define macro in module file */ \
} \
} \
old_db = dg__new_db + SIZE_HACK; \
for (dg__i = mudstate.db_top; dg__i < new_size; dg__i++) { \
OBJ_INIT_MODULE(dg__i); \
} \
}
/* -----------------------------------------------------------------------* API interface functions.
*/
extern void FDECL(register_api, (char *, char *, API_FUNCTION *));
extern void *FDECL(request_api_function, (char *, char *));
extern
extern
extern
extern
extern

void FDECL(register_commands, (CMDENT *));


void FDECL(register_prefix_cmds, (const char *));
void FDECL(register_functions, (FUN *));
void FDECL(register_hashtables, (MODHASHES *, MODNHASHES *));
unsigned int FDECL(register_dbtype, (char *));

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\api.h

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

Saturday, June 16, 2012 11:18 PM

/* -----------------------------------------------------------------------* External necessities.


*/
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

CF_HDCL(cf_alias);
CF_HDCL(cf_bool);
CF_HDCL(cf_const);
CF_HDCL(cf_dbref);
CF_HDCL(cf_int);
CF_HDCL(cf_int_factor);
CF_HDCL(cf_modify_bits);
CF_HDCL(cf_ntab_access);
CF_HDCL(cf_option);
CF_HDCL(cf_set_flags);
CF_HDCL(cf_string);

#endif /* __API_H */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\attrs.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:18 PM

/* attrs.h - Attribute definitions */


/* $Id: attrs.h,v 1.33 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#ifndef __ATTRS_H
#define __ATTRS_H
/* Attribute flags */
#define AF_ODARK
0x00000001 /*
#define AF_DARK
0x00000002 /*
#define AF_WIZARD
0x00000004 /*
#define AF_MDARK
0x00000008 /*
#define AF_INTERNAL 0x00000010 /*
#define AF_NOCMD
0x00000020 /*
#define AF_LOCK
0x00000040 /*
#define AF_DELETED 0x00000080 /*
#define AF_NOPROG
0x00000100 /*
#define AF_GOD
0x00000200 /*
#define AF_IS_LOCK 0x00000400 /*
#define AF_VISUAL
0x00000800 /*
#define AF_PRIVATE 0x00001000 /*
#define AF_HTML
0x00002000 /*
#define AF_NOPARSE 0x00004000 /*
#define AF_REGEXP
0x00008000 /*
#define AF_NOCLONE 0x00010000 /*
#define AF_CONST
0x00020000 /*
#define AF_CASE
0x00040000 /*
#define AF_STRUCTURE
0x00080000
#define AF_DIRTY
0x00100000 /*
#define AF_DEFAULT 0x00200000 /*
#define AF_NONAME
0x00400000 /*
#define AF_RMATCH
0x00800000 /*
#define AF_NOW
0x01000000 /*
#define AF_TRACE
0x02000000 /*
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

A_NULL
A_OSUCC
A_OFAIL
A_FAIL
A_SUCC
A_PASS
A_DESC
A_SEX
A_ODROP
A_DROP
A_OKILL
A_KILL
A_ASUCC
A_AFAIL
A_ADROP
A_AKILL
A_AUSE

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

players other than owner can't see it */


No one can see it */
only wizards can change it */
Only wizards can see it. Dark to mortals */
Don't show even to #1 */
Don't create a @ command for it */
Attribute is locked */
Attribute should be ignored */
Don't process $-commands from this attr */
Only #1 can change it */
Attribute is a lock */
Anyone can see */
Not inherited by children */
Don't HTML escape this in did_it() */
Don't evaluate when checking for $-cmds */
Do a regexp rather than wildcard match */
Don't copy this attr when cloning. */
No one can change it (set by server) */
Regexp matches are case-sensitive */
/* Attribute contains a structure */
Attribute number has been modified */
did_it() checks attr_defaults obj */
If used as oattr, no name prepend */
Set the result of match into regs */
execute match immediately */
trace ufunction */

Nothing */
Others success message */
Others fail message */
Invoker fail message */
Invoker success message */
Password (only meaningful for players) */
Description */
Sex */
Others drop message */
Invoker drop message */
Others kill message */
Invoker kill message */
Success action list */
Failure action list */
Drop action list */
Kill action list */
Use action list */
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\attrs.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

A_CHARGES
17
A_RUNOUT
18
A_STARTUP
19
A_ACLONE
20
A_APAY
21
A_OPAY
22
A_PAY
23
A_COST
24
A_MONEY
25
A_LISTEN
26
A_AAHEAR
27
A_AMHEAR
28
A_AHEAR
29
A_LAST
30
A_QUEUEMAX 31
A_IDESC
32
A_ENTER
33
A_OXENTER
34
A_AENTER
35
A_ADESC
36
A_ODESC
37
A_RQUOTA
38
A_ACONNECT 39
A_ADISCONNECT
A_ALLOWANCE 41
A_LOCK
42
A_NAME
43
A_COMMENT
44
A_USE
45
A_OUSE
46
A_SEMAPHORE 47
A_TIMEOUT
48
A_QUOTA
49
A_LEAVE
50
A_OLEAVE
51
A_ALEAVE
52
A_OENTER
53
A_OXLEAVE
54
A_MOVE
55
A_OMOVE
56
A_AMOVE
57
A_ALIAS
58
A_LENTER
59
A_LLEAVE
60
A_LPAGE
61
A_LUSE
62
A_LGIVE
63
A_EALIAS
64
A_LALIAS
65
A_EFAIL
66
A_OEFAIL
67
A_AEFAIL
68
A_LFAIL
69

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
40
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

Saturday, June 16, 2012 11:18 PM

Number of charges remaining */


Actions done when no more charges */
Actions run when game started up */
Actions run when obj is cloned */
Actions run when given COST pennies */
Others pay message */
Invoker pay message */
Number of pennies needed to invoke xPAY */
Value or Wealth (internal) */
(Wildcarded) string to listen for */
Actions to do when anyone says LISTEN str */
Actions to do when I say LISTEN str */
Actions to do when others say LISTEN str */
Date/time of last login (players only) */
Max. # of entries obj has in the queue */
Inside description (ENTER to get inside) */
Invoker enter message */
Others enter message in dest */
Enter action list */
Describe action list */
Others describe message */
Relative object quota */
Actions run when player connects */
/* Actions run when player disconnects */
Daily allowance, if diff from default */
Object lock */
Object name */
Wizard-accessible comments */
Invoker use message */
Others use message */
Semaphore control info */
Per-user disconnect timeout */
Absolute quota (to speed up @quota) */
Invoker leave message */
Others leave message in src */
Leave action list */
Others enter message in src */
Others leave message in dest */
Invoker move message */
Others move message */
Move action list */
Alias for player names */
ENTER lock */
LEAVE lock */
PAGE lock */
USE lock */
Give lock (who may give me away?) */
Alternate names for ENTER */
Alternate names for LEAVE */
Invoker entry fail message */
Others entry fail message */
Entry fail action list */
Invoker leave fail message */
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\attrs.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:18 PM

#define A_OLFAIL
70 /* Others leave fail message */
#define A_ALFAIL
71 /* Leave fail action list */
#define A_REJECT
72 /* Rejected page return message */
#define A_AWAY
73 /* Not_connected page return message */
#define A_IDLE
74 /* Success page return message */
#define A_UFAIL
75 /* Invoker use fail message */
#define A_OUFAIL
76 /* Others use fail message */
#define A_AUFAIL
77 /* Use fail action list */
/* unused
78 Formerly A_PFAIL: Invoker page fail message */
#define A_TPORT
79 /* Invoker teleport message */
#define A_OTPORT
80 /* Others teleport message in src */
#define A_OXTPORT
81 /* Others teleport message in dst */
#define A_ATPORT
82 /* Teleport action list */
/* unused
83 Formerly A_PRIVS: Individual permissions */
#define A_LOGINDATA 84 /* Recent login information */
#define A_LTPORT
85 /* Teleport lock (can others @tel to me?) */
#define A_LDROP
86 /* Drop lock (can I be dropped or @tel'ed) */
#define A_LRECEIVE 87 /* Receive lock (who may give me things?) */
#define A_LASTSITE 88 /* Last site logged in from, in cleartext */
#define A_INPREFIX 89 /* Prefix on incoming messages into objects */
#define A_PREFIX
90 /* Prefix used by exits/objects when audible */
#define A_INFILTER 91 /* Filter to zap incoming text into objects */
#define A_FILTER
92 /* Filter to zap text forwarded by audible. */
#define A_LLINK
93 /* Who may link to here */
#define A_LTELOUT
94 /* Who may teleport out from here */
#define A_FORWARDLIST
95 /* Recipients of AUDIBLE output */
#define A_MAILFOLDERS
96 /* @mail folders */
#define A_LUSER
97 /* Spare lock not referenced by server */
#define A_LPARENT
98 /* Who may @parent to me if PARENT_OK set */
#define A_LCONTROL 99 /* Who controls me if CONTROL_OK set */
#define A_VA
100 /* VA attribute (VB-VZ follow) */
/* unused
#define A_GFAIL
#define A_OGFAIL
#define A_AGFAIL
#define A_RFAIL
#define A_ORFAIL
#define A_ARFAIL
#define A_DFAIL
#define A_ODFAIL
#define A_ADFAIL
#define A_TFAIL
#define A_OTFAIL
#define A_ATFAIL
#define A_TOFAIL
#define A_OTOFAIL
#define A_ATOFAIL

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

#define
#define
#define
#define

198 /* Who is the mail Cc'ed to? */


199 /* Who is the mail Bcc'ed to? */
200
/* Player last paged */
201 /* Message echoed to sender */

A_MAILCC
A_MAILBCC
A_LASTPAGE
A_MAIL

126, 127, 128 */


/* Give fail message */
/* Others give fail message */
/* Give fail action */
/* Receive fail message */
/* Others receive fail message */
/* Receive fail action */
/* Drop fail message */
/* Others drop fail message */
/* Drop fail action */
/* Teleport (to) fail message */
/* Others teleport (to) fail message */
/* Teleport fail action */
/* Teleport (from) fail message */
/* Others teleport (from) fail message */
/* Teleport (from) fail action */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\attrs.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

A_AMAIL
A_SIGNATURE
A_DAILY
A_MAILTO
A_MAILMSG
A_MAILSUB
A_MAILCURF
A_LSPEECH
A_PROGCMD
A_MAILFLAGS
A_DESTROYER

#define
#define
#define
#define
#define
#define
#define

A_NEWOBJS
A_LCON_FMT
A_LEXITS_FMT
A_EXITVARDEST
A_LCHOWN
217
A_LASTIP
218
A_LDARK
219

Saturday, June 16, 2012 11:18 PM

202 /* Action taken when mail received */


203 /* Mail signature */
204 /* Daily attribute to be executed */
205 /* Who is the mail to? */
206 /* The mail message itself */
207 /* The mail subject */
208 /* The current @mail folder */
209 /* Speechlocks */
210 /* Command for execution by @prog */
211 /* Flags for extended mail */
212 /* Who is destroying this object? */
213
/* New object array */
214
/* Player-specified contents format */
215
/* Player-specified exits format */
216 /* Variable exit destination */
/* ChownLock */
/* Last IP address logged in from */
/* DarkLock */

#define A_VRML_URL
#define A_HTDESC

220
221

#define A_NAME_FMT

222 /* Player-specified name format */

#define
#define
#define
#define
#define
#define

223
224
225
226
227
228

A_LKNOWN
A_LHEARD
A_LMOVED
A_LKNOWS
A_LHEARS
A_LMOVES

/* URL of the VRML scene for this object */


/* HTML @desc */

/*
/*
/*
/*
/*
/*

Who
Who
Who
Who
Who
Who

is this player seen by? (presence) */


is this player heard by? (speech) */
notices this player moving? */
does this player see? (presence) */
does this player hear? (speech) */
does this player notice moving? */

#define A_SPEECHFMT 229 /* Format speech */


#define A_PAGEGROUP 230 /* Last paged as part of this group */
#define A_PROPDIR
/* unused
#define A_LIST
/* unused
#define A_TEMP

231 /* Property directory dbref list */

252 Formerly A_VLIST */


253
254 Formerly A_STRUCT */
255

#define A_USER_START
#define ATR_BUF_CHUNK
#define ATR_BUF_INCR

256 /* Start of user-named attributes */


100 /* Min size to allocate for attribute buffer */
6
/* Max size of one attribute */

#define Print_Attr_Flags(a,b,p) \
p = b; \
if (a & AF_LOCK) *p++ = '+'; \
if (a & AF_NOPROG) *p++ = '$'; \
if (a & AF_CASE) *p++ = 'C'; \
if (a & AF_DEFAULT) *p++ = 'D'; \
if (a & AF_HTML) *p++ = 'H'; \
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\attrs.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

if
if
if
if
if
if
if
if
if
if
if
if
if
if
if
*p

Saturday, June 16, 2012 11:18 PM

(a & AF_PRIVATE) *p++ = 'I'; \


(a & AF_RMATCH) *p++ = 'M'; \
(a & AF_NONAME) *p++ = 'N'; \
(a & AF_NOPARSE) *p++ = 'P'; \
(a & AF_NOW) *p++ = 'Q'; \
(a & AF_REGEXP) *p++ = 'R'; \
(a & AF_STRUCTURE) *p++ = 'S'; \
(a & AF_TRACE) *p++ = 'T'; \
(a & AF_VISUAL) *p++ = 'V'; \
(a & AF_NOCLONE) *p++ = 'c'; \
(a & AF_DARK) *p++ = 'd'; \
(a & AF_GOD) *p++ = 'g'; \
(a & AF_CONST) *p++ = 'k'; \
(a & AF_MDARK) *p++ = 'm'; \
(a & AF_WIZARD) *p++ = 'w'; \
= '\0';

#endif /* __ATTRS_H */

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bitstring.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:17 PM

/* bitstring.h */
/* $Id: bitstring.h,v 1.2 2000/05/22 21:42:27 lwl Exp $ */
/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Paul Vixie.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#)bitstring.h 5.2 (Berkeley) 4/4/90
*/
typedef unsigned char bitstr_t;
/* internal macros */
/* byte of the bitstring bit is in */
#define _bit_byte(bit) \
((bit) >> 3)
/* mask for the bit within its byte */
#define _bit_mask(bit) \
(1 << ((bit)&0x7))
/* external macros */
/* bytes in a bitstring of nbits bits */
#define bitstr_size(nbits) \
((((nbits) - 1) >> 3) + 1)
/* allocate a bitstring */
#define bit_alloc(nbits) \
(bitstr_t *)malloc(1, \
(unsigned int)bitstr_size(nbits) * sizeof(bitstr_t))
/* allocate a bitstring on the stack */
#define bit_decl(name, nbits) \
(name)[bitstr_size(nbits)]
/* is bit N of bitstring name set? */
#define bit_test(name, bit) \
((name)[_bit_byte(bit)] & _bit_mask(bit))
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bitstring.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:17 PM

/* set bit N of bitstring name */


#define bit_set(name, bit) \
(name)[_bit_byte(bit)] |= _bit_mask(bit)
/* clear bit N of bitstring name */
#define bit_clear(name, bit) \
(name)[_bit_byte(bit)] &= ~_bit_mask(bit)
/* clear bits start ... stop in bitstring */
#define bit_nclear(name, start, stop) { \
register bitstr_t *_name = name; \
register int _start = start, _stop = stop; \
register int _startbyte = _bit_byte(_start); \
register int _stopbyte = _bit_byte(_stop); \
if (_startbyte == _stopbyte) { \
_name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
(0xff << ((_stop&0x7) + 1))); \
} else { \
_name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
while (++_startbyte < _stopbyte) \
_name[_startbyte] = 0; \
_name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
} \
}
/* set bits start ... stop in bitstring */
#define bit_nset(name, start, stop) { \
register bitstr_t *_name = name; \
register int _start = start, _stop = stop; \
register int _startbyte = _bit_byte(_start); \
register int _stopbyte = _bit_byte(_stop); \
if (_startbyte == _stopbyte) { \
_name[_startbyte] |= ((0xff << (_start&0x7)) & \
(0xff >> (7 - (_stop&0x7)))); \
} else { \
_name[_startbyte] |= 0xff << ((_start)&0x7); \
while (++_startbyte < _stopbyte) \
_name[_startbyte] = 0xff; \
_name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
} \
}
/* find first bit clear in name */
#define bit_ffc(name, nbits, value) { \
register bitstr_t *_name = name; \
register int _byte, _nbits = nbits; \
register int _stopbyte = _bit_byte(_nbits), _value = -1; \
for (_byte = 0; _byte <= _stopbyte; ++_byte) \
if (_name[_byte] != 0xff) { \
_value = _byte << 3; \
for (_stopbyte = _name[_byte]; (_stopbyte&0x1); \
++_value, _stopbyte >>= 1); \
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bitstring.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

Saturday, June 16, 2012 11:17 PM

break; \
} \
*(value) = _value; \

/* find first bit set in name */


#define bit_ffs(name, nbits, value) { \
register bitstr_t *_name = name; \
register int _byte, _nbits = nbits; \
register int _stopbyte = _bit_byte(_nbits), _value = -1; \
for (_byte = 0; _byte <= _stopbyte; ++_byte) \
if (_name[_byte]) { \
_value = _byte << 3; \
for (_stopbyte = _name[_byte]; !(_stopbyte&0x1); \
++_value, _stopbyte >>= 1); \
break; \
} \
*(value) = _value; \
}

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:53 PM

/* boolexp.c */
/* $Id: boolexp.c,v 1.30 2004/02/23 04:35:14 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"match.h"
"attrs.h"
"powers.h"
"ansi.h"

/*
/*
/*
/*

required
required
required
required

by
by
by
by

code
code
code
code

*/
*/
*/
*/

static int parsing_internal = 0;


/* --------------------------------------------------------------------------* check_attr: indicate if attribute ATTR on player passes key when checked by
* the object lockobj
*/
static int check_attr(player, lockobj, attr, key)
dbref player, lockobj;
ATTR *attr;
char *key;
{
char *buff;
dbref aowner;
int aflags, alen, checkit;
buff = atr_pget(player, attr->number, &aowner, &aflags, &alen);
checkit = 0;

if (attr->number == A_LCONTROL) {
/* We can see control locks... else we'd break zones */
checkit = 1;
} else if (See_attr(lockobj, player, attr, aowner, aflags)) {
checkit = 1;
} else if (attr->number == A_NAME) {
checkit = 1;
}
if (checkit && (!wild_match(key, buff))) {
checkit = 0;
}
free_lbuf(buff);
return checkit;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:53 PM

static dbref lock_originator = NOTHING; /* grotesque hack */


int eval_boolexp(player, thing, from, b)
dbref player, thing, from;
BOOLEXP *b;
{
dbref aowner, obj, source;
int aflags, alen, c, checkit;
char *key, *buff, *buff2, *bp, *str;
ATTR *a;
GDATA *preserve;
if (b == TRUE_BOOLEXP)
return 1;
switch (b->type) {
case BOOLEXP_AND:
return (eval_boolexp(player, thing, from, b->sub1) &&
eval_boolexp(player, thing, from, b->sub2));
case BOOLEXP_OR:
return (eval_boolexp(player, thing, from, b->sub1) ||
eval_boolexp(player, thing, from, b->sub2));
case BOOLEXP_NOT:
return !eval_boolexp(player, thing, from, b->sub1);
case BOOLEXP_INDIR:
/*
* BOOLEXP_INDIR (i.e. @) is a unary operation which is replaced at
* evaluation time by the lock of the object whose number is the
* argument of the operation.
*/
mudstate.lock_nest_lev++;
if (mudstate.lock_nest_lev >= mudconf.lock_nest_lim) {
STARTLOG(LOG_BUGS, "BUG", "LOCK")
log_name_and_loc(player);
log_printf(": Lock exceeded recursion limit." );
ENDLOG
notify(player, "Sorry, broken lock!");
mudstate.lock_nest_lev--;
return (0);
}
if ((b->sub1->type != BOOLEXP_CONST) || (b->sub1->thing < 0)) {
STARTLOG(LOG_BUGS, "BUG", "LOCK")
log_name_and_loc(player);
log_printf(": Lock had bad indirection (%c, type %d)" ,
INDIR_TOKEN, b->sub1->type);
ENDLOG
notify(player, "Sorry, broken lock!");
mudstate.lock_nest_lev--;
return (0);
}
key = atr_get(b->sub1->thing, A_LOCK, &aowner, &aflags, &alen);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:53 PM

lock_originator = thing;
c = eval_boolexp_atr(player, b->sub1->thing, from, key);
lock_originator = NOTHING;
free_lbuf(key);
mudstate.lock_nest_lev--;
return (c);
case BOOLEXP_CONST:
return (b->thing == player ||
member(b->thing, Contents(player)));
case BOOLEXP_ATR:
a = atr_num(b->thing);
if (!a)
return 0;
/*
* no such attribute
*/
/*
* First check the object itself, then its contents
*/
if (check_attr(player, from, a, (char *)b->sub1))
return 1;
DOLIST(obj, Contents(player)) {
if (check_attr(obj, from, a, (char *)b->sub1))
return 1;
}
return 0;
case BOOLEXP_EVAL:
a = atr_num(b->thing);
if (!a)
return 0;
/*
* no such attribute
*/
source = from;
buff = atr_pget(from, a->number, &aowner, &aflags, &alen);
if (!*buff) {
free_lbuf(buff);
buff = atr_pget(thing, a->number, &aowner,
&aflags, &alen);
source = thing;
}
checkit = 0;
if ((a->number == A_NAME) || (a->number == A_LCONTROL)) {
checkit = 1;
} else if (Read_attr(source, source, a, aowner, aflags)) {
checkit = 1;
}
if (checkit) {
preserve = save_global_regs("eval_boolexp_save");
buff2 = bp = alloc_lbuf("eval_boolexp");
str = buff;
exec(buff2, &bp, source,
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

Saturday, June 16, 2012 11:53 PM

((lock_originator == NOTHING) ?
player : lock_originator),
player, EV_FCHECK | EV_EVAL | EV_TOP,
&str, (char **)NULL, 0);
restore_global_regs("eval_boolexp_save", preserve);
checkit = !string_compare(buff2, (char *)b->sub1);
free_lbuf(buff2);

}
free_lbuf(buff);
return checkit;
case BOOLEXP_IS:

/*
* If an object check, do that
*/
if (b->sub1->type == BOOLEXP_CONST)
return (b->sub1->thing == player);
/*
* Nope, do an attribute check
*/
a = atr_num(b->sub1->thing);
if (!a)
return 0;
return (check_attr(player, from, a, (char *)(b->sub1)->sub1));
case BOOLEXP_CARRY:
/*
* If an object check, do that
*/
if (b->sub1->type == BOOLEXP_CONST)
return (member(b->sub1->thing, Contents(player)));
/*
* Nope, do an attribute check
*/
a = atr_num(b->sub1->thing);
if (!a)
return 0;
DOLIST(obj, Contents(player)) {
if (check_attr(obj, from, a, (char *)(b->sub1)->sub1))
return 1;
}
return 0;
case BOOLEXP_OWNER:
return (Owner(b->sub1->thing) == Owner(player));
default:
fprintf(mainlog_fp, "ABORT! boolexp.c, unknown boolexp type in
eval_boolexp().\n");
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

abort();
return 0;

Saturday, June 16, 2012 11:53 PM

/* bad type */
/* NOTREACHED */

int eval_boolexp_atr(player, thing, from, key)


dbref player, thing, from;
char *key;
{
BOOLEXP *b;
int ret_value;

b = parse_boolexp(player, key, 1);


if (b == NULL) {
ret_value = 1;
} else {
ret_value = eval_boolexp(player, thing, from, b);
free_boolexp(b);
}
return (ret_value);

/* If the parser returns TRUE_BOOLEXP, you lose TRUE_BOOLEXP cannot be typed


* in by the user; use @unlock instead
*/
static char *parsebuf, *parsestore;
static dbref parse_player;
static void NDECL(skip_whitespace)
{
while (*parsebuf && isspace(*parsebuf))
parsebuf++;
}
static BOOLEXP *NDECL(parse_boolexp_E);

/* defined below */

static BOOLEXP *test_atr(s)


char *s;
{
ATTR *attrib;
BOOLEXP *b;
char *buff, *s1;
int anum, locktype;
buff = alloc_lbuf("test_atr");
StringCopy(buff, s);
for (s = buff; *s && (*s != ':') && (*s != '/'); s++) ;
if (!*s) {
free_lbuf(buff);
return ((BOOLEXP *) NULL);
}
if (*s == '/')
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

else

Saturday, June 16, 2012 11:53 PM

locktype = BOOLEXP_EVAL;
locktype = BOOLEXP_ATR;

*s++ = '\0';
/*
* see if left side is valid attribute. Access to attr is checked on
* eval. Also allow numeric references to attributes. It can't hurt
* us, and lets us import stuff that stores attr locks by number
* instead of by name.
*/
if (!(attrib = atr_str(buff))) {
/*
* Only #1 can lock on numbers
*/
if (!God(parse_player)) {
free_lbuf(buff);
return ((BOOLEXP *) NULL);
}
s1 = buff;
for (s1 = buff; isdigit(*s1); s1++) ;
if (*s1) {
free_lbuf(buff);
return ((BOOLEXP *) NULL);
}
anum = atoi(buff);
if (anum <= 0) {
free_lbuf(buff);
return ((BOOLEXP *) NULL);
}
} else {
anum = attrib->number;
}

/*
* made it now make the parse tree node
*/
b = alloc_bool("test_atr");
b->type = locktype;
b->thing = (dbref) anum;
b->sub1 = (BOOLEXP *) XSTRDUP(s, "test_atr.sub1");
free_lbuf(buff);
return (b);

/*
* L -> (E); L -> object identifier
*/
static BOOLEXP *NDECL(parse_boolexp_L)
{
BOOLEXP *b;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

Saturday, June 16, 2012 11:53 PM

char *p, *buf;


MSTATE mstate;
buf = NULL;
skip_whitespace();
switch (*parsebuf) {
case '(':
parsebuf++;
b = parse_boolexp_E();
skip_whitespace();
if (b == TRUE_BOOLEXP || *parsebuf++ != ')') {
free_boolexp(b);
return TRUE_BOOLEXP;
}
break;
default:
/* must have hit an object ref.
* buffer */

Load the name into our

buf = alloc_lbuf("parse_boolexp_L");
p = buf;
while (*parsebuf && (*parsebuf != AND_TOKEN) &&
(*parsebuf != OR_TOKEN) && (*parsebuf != ')')) {
*p++ = *parsebuf++;
}
/* strip trailing whitespace */
*p-- = '\0';
while (isspace(*p))
*p-- = '\0';
/* check for an attribute */
if ((b = test_atr(buf)) != NULL) {
free_lbuf(buf);
return (b);
}
b = alloc_bool("parse_boolexp_L");
b->type = BOOLEXP_CONST;
/* Do the match.
* If we are parsing a boolexp that was a stored lock then
* we know that object refs are all dbrefs, so we skip the
* expensive match code.
*/
if (!mudstate.standalone) {
if (parsing_internal) {
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

Saturday, June 16, 2012 11:53 PM

if (buf[0] != '#') {
free_lbuf(buf);
free_bool(b);
return TRUE_BOOLEXP;
}
b->thing = atoi(&buf[1]);
if (!Good_obj(b->thing)) {
free_lbuf(buf);
free_bool(b);
return TRUE_BOOLEXP;
}
} else {
save_match_state(&mstate);
init_match(parse_player, buf, TYPE_THING);
match_everything(MAT_EXIT_PARENTS);
b->thing = match_result();
restore_match_state(&mstate);
}
if (b->thing == NOTHING) {
notify(parse_player,
tprintf("I don't see %s here.", buf));
free_lbuf(buf);
free_bool(b);
return TRUE_BOOLEXP;
}
if (b->thing == AMBIGUOUS) {
notify(parse_player,
tprintf("I don't know which %s you mean!" ,
buf));
free_lbuf(buf);
free_bool(b);
return TRUE_BOOLEXP;
}
} else {
if (buf[0] != '#') {
free_lbuf(buf);
free_bool(b);
return TRUE_BOOLEXP;
}
b->thing = atoi(&buf[1]);
if (b->thing < 0) {
free_lbuf(buf);
free_bool(b);
return TRUE_BOOLEXP;
}
}
free_lbuf(buf);

}
return b;

/*
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

Saturday, June 16, 2012 11:53 PM

* F -> !F; F -> @L; F -> =L; F -> +L; F -> $L


*/
/*
* The argument L must be type BOOLEXP_CONST
*/
static BOOLEXP *NDECL(parse_boolexp_F)
{
BOOLEXP *b2;
skip_whitespace();
switch (*parsebuf) {
case NOT_TOKEN:
parsebuf++;
b2 = alloc_bool("parse_boolexp_F.not");
b2->type = BOOLEXP_NOT;
if ((b2->sub1 = parse_boolexp_F()) == TRUE_BOOLEXP) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else
return (b2);
case INDIR_TOKEN:
parsebuf++;
b2 = alloc_bool("parse_boolexp_F.indir");
b2->type = BOOLEXP_INDIR;
b2->sub1 = parse_boolexp_L();
if ((b2->sub1) == TRUE_BOOLEXP) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else if ((b2->sub1->type) != BOOLEXP_CONST) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else
return (b2);
case IS_TOKEN:
parsebuf++;
b2 = alloc_bool("parse_boolexp_F.is");
b2->type = BOOLEXP_IS;
b2->sub1 = parse_boolexp_L();
if ((b2->sub1) == TRUE_BOOLEXP) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else if (((b2->sub1->type) != BOOLEXP_CONST) &&
((b2->sub1->type) != BOOLEXP_ATR)) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else
return (b2);
case CARRY_TOKEN:
parsebuf++;
b2 = alloc_bool("parse_boolexp_F.carry");
b2->type = BOOLEXP_CARRY;
b2->sub1 = parse_boolexp_L();
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

Saturday, June 16, 2012 11:53 PM

if ((b2->sub1) == TRUE_BOOLEXP) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else if (((b2->sub1->type) != BOOLEXP_CONST) &&
((b2->sub1->type) != BOOLEXP_ATR)) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else
return (b2);
case OWNER_TOKEN:
parsebuf++;
b2 = alloc_bool("parse_boolexp_F.owner");
b2->type = BOOLEXP_OWNER;
b2->sub1 = parse_boolexp_L();
if ((b2->sub1) == TRUE_BOOLEXP) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else if ((b2->sub1->type) != BOOLEXP_CONST) {
free_boolexp(b2);
return (TRUE_BOOLEXP);
} else
return (b2);
default:
return (parse_boolexp_L());
}

/*
* T -> F; T -> F & T
*/
static BOOLEXP *NDECL(parse_boolexp_T)
{
BOOLEXP *b, *b2;
if ((b = parse_boolexp_F()) != TRUE_BOOLEXP) {
skip_whitespace();
if (*parsebuf == AND_TOKEN) {
parsebuf++;
b2 = alloc_bool("parse_boolexp_T");
b2->type = BOOLEXP_AND;
b2->sub1 = b;
if ((b2->sub2 = parse_boolexp_T()) == TRUE_BOOLEXP) {
free_boolexp(b2);
return TRUE_BOOLEXP;
}
b = b2;

}
}
return b;

-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582

Saturday, June 16, 2012 11:53 PM

/*
* E -> T; E -> T | E
*/
static BOOLEXP *NDECL(parse_boolexp_E)
{
BOOLEXP *b, *b2;
if ((b = parse_boolexp_T()) != TRUE_BOOLEXP) {
skip_whitespace();
if (*parsebuf == OR_TOKEN) {
parsebuf++;

b2 = alloc_bool("parse_boolexp_E");
b2->type = BOOLEXP_OR;
b2->sub1 = b;
if ((b2->sub2 = parse_boolexp_E()) == TRUE_BOOLEXP) {
free_boolexp(b2);
return TRUE_BOOLEXP;
}
b = b2;

}
return b;

BOOLEXP *parse_boolexp(player, buf, internal)


dbref player;
const char *buf;
int internal;
{
char *p;
int num_opens = 0;
BOOLEXP *ret;
if (!internal) {
/* Don't allow funky characters in locks.
* Don't allow unbalanced parentheses.
*/
for (p = (char *) buf; *p; p++) {
if ((*p == '\t') || (*p == '\r') || (*p == '\n') ||
(*p == ESC_CHAR)) {
return (TRUE_BOOLEXP);
}
if (*p == '(') {
num_opens++;
} else if (*p == ')') {
if (num_opens > 0) {
num_opens--;
} else {
return (TRUE_BOOLEXP);
}
}
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\boolexp.c

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

Saturday, June 16, 2012 11:53 PM

}
if (num_opens != 0)
return (TRUE_BOOLEXP);

if ((buf == NULL) || (*buf == '\0'))


return (TRUE_BOOLEXP);

parsestore = parsebuf = alloc_lbuf("parse_boolexp");


StringCopy(parsebuf, buf);
parse_player = player;
if (!mudstate.standalone)
parsing_internal = internal;
ret = parse_boolexp_E();
free_lbuf(parsestore);
return ret;

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:52 PM

/* bsd.c - BSD-style network and signal routines */


/* $Id: bsd.c,v 1.75 2007/10/04 22:58:20 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include <sys/file.h>
#include <sys/stat.h>
#include <signal.h>
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include "file_c.h" /* required by code */
#include "command.h"
/* required by code */
#include "attrs.h" /* required by code */
#ifndef NSIG
extern const int _sys_nsig;
#define NSIG _sys_nsig
#endif
extern void NDECL(dispatch);
int sock;
int ndescriptors = 0;
int maxd = 0;
DESC *descriptor_list = NULL;
volatile pid_t slave_pid = 0;
volatile int slave_socket = -1;
DESC *FDECL(initializesock, (int, struct sockaddr_in *));
DESC *FDECL(new_connection, (int));
int FDECL(process_output, (DESC *));
int FDECL(process_input, (DESC *));
/* Some systems are lame, and inet_addr() returns -1 on failure, despite
* the fact that it returns an unsigned long.
*/
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
/*
* get a result from the slave
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:52 PM

*/
#define GSR_SKIP_WHITESPACE(x) \
while (isspace(*(x))) \
++(x)
#define GSR_REQUIRE_CHAR(x,c) \
if (*(x) != (c)) { \
goto gsr_end; \
} \
++(x)
#define GSR_STRCHR_INC(x,y,c) \
(x) = strchr((y), (c)); \
if (!(x)) { \
goto gsr_end; \
} \
++(x)
static int get_slave_result()
{
char *buf, *host1, *hostname, *host2, *p, *userid;
int remote_port, len;
unsigned long addr;
DESC *d;
buf = alloc_lbuf("slave_buf");
len = read(slave_socket, buf, LBUF_SIZE - 1);
if (len < 0) {
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
free_lbuf(buf);
return (-1);
}
close(slave_socket);
slave_socket = -1;
free_lbuf(buf);
return (-1);
} else if (len == 0) {
free_lbuf(buf);
return (-1);
}
buf[len] = '\0';
host1 = buf;
GSR_STRCHR_INC(hostname, host1, ' ');
hostname[-1] = '\0';
GSR_STRCHR_INC(host2, hostname, '\n');
host2[-1] = '\0';
if (mudconf.use_hostname) {
for (d = descriptor_list; d; d = d->next) {
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:52 PM

if (strcmp(d->addr, host1))
continue;
if (d->player != 0) {
if (d->username[0]) {
atr_add_raw(d->player, A_LASTSITE,
tprintf("%s@%s",
d->username,
hostname));
} else {
atr_add_raw(d->player, A_LASTSITE,
hostname);
}
}
StringCopyTrunc(d->addr, hostname, 50);
d->addr[50] = '\0';

GSR_STRCHR_INC(p, host2, ' ');


p[-1] = '\0';
addr = inet_addr(host2);
if (addr == INADDR_NONE) {
goto gsr_end;
}
/* now we're into the RFC 1413 ident reply */
GSR_SKIP_WHITESPACE(p);
remote_port = 0;
while (isdigit(*p)) {
remote_port <<= 1;
remote_port += (remote_port << 2) + (*p & 0x0f);
++p;
}
GSR_SKIP_WHITESPACE(p);
GSR_REQUIRE_CHAR(p, ',');
GSR_SKIP_WHITESPACE(p);
/* skip the local port, making sure it consists of digits */
while (isdigit(*p)) {
++p;
}
GSR_SKIP_WHITESPACE(p);
GSR_REQUIRE_CHAR(p, ':');
GSR_SKIP_WHITESPACE(p);
/* identify the reply type */
if (strncmp(p, "USERID", 6)) {
/* the other standard possibility here is "ERROR" */
goto gsr_end;
}
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:52 PM

p += 6;
GSR_SKIP_WHITESPACE(p);
GSR_REQUIRE_CHAR(p, ':');
GSR_SKIP_WHITESPACE(p);
/* don't include the trailing linefeed in the userid */
GSR_STRCHR_INC(userid, p, '\n');
userid[-1] = '\0';
/* go back and skip over the "OS [, charset] : " field */
GSR_STRCHR_INC(userid, p, ':');
GSR_SKIP_WHITESPACE(userid);

for (d = descriptor_list; d; d = d->next) {


if (ntohs((d->address).sin_port) != remote_port)
continue;
if ((d->address).sin_addr.s_addr != addr)
continue;
if (d->player != 0) {
if (mudconf.use_hostname) {
atr_add_raw(d->player, A_LASTSITE,
tprintf("%s@%s", userid, hostname));
} else {
atr_add_raw(d->player, A_LASTSITE,
tprintf("%s@%s", userid, host2));
}
}
StringCopyTrunc(d->username, userid, 10);
d->username[10] = '\0';
break;
}
gsr_end:
free_lbuf(buf);
return 0;

void boot_slave()
{
int sv[2];
int i;
int maxfds;
char *s;
#ifdef HAVE_GETDTABLESIZE
maxfds = getdtablesize();
#else
maxfds = sysconf(_SC_OPEN_MAX);
#endif
if (slave_socket != -1) {
close(slave_socket);
slave_socket = -1;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:52 PM

}
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) {
return;
}
/*
* set to nonblocking
*/
#ifdef FNDELAY
if (fcntl(sv[0], F_SETFL, FNDELAY) == -1) {
#else
if (fcntl(sv[0], F_SETFL, O_NDELAY) == -1) {
#endif
close(sv[0]);
close(sv[1]);
return;
}
slave_pid = vfork();
switch (slave_pid) {
case -1:
close(sv[0]);
close(sv[1]);
return;
case 0:

/*
* child
*/
close(sv[0]);
if (dup2(sv[1], 0) == -1) {
_exit(1);
}
if (dup2(sv[1], 1) == -1) {
_exit(1);
}
for (i = 3; i < maxfds; ++i) {
close(i);
}
s=(char *) XMALLOC(MBUF_SIZE, "boot_slave");
sprintf(s, "%s/slave", mudconf.binhome);
execlp(s, "slave", NULL);
XFREE(s,"boot_slave");
_exit(1);

}
close(sv[1]);

#ifdef FNDELAY
if (fcntl(sv[0], F_SETFL, FNDELAY) == -1) {
#else
if (fcntl(sv[0], F_SETFL, O_NDELAY) == -1) {
#endif
close(sv[0]);
return;
}
slave_socket = sv[0];
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:52 PM

STARTLOG(LOG_ALWAYS, "NET", "SLAVE")


log_printf("DNS lookup slave started on fd %d" , slave_socket);
ENDLOG

int make_socket(port)
int port;
{
int s, opt;
struct sockaddr_in server;

s = socket(AF_INET, SOCK_STREAM, 0);


if (s < 0) {
log_perror("NET", "FAIL", NULL, "creating master socket");
exit(3);
}
opt = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&opt, sizeof(opt)) < 0) {
log_perror("NET", "FAIL", NULL, "setsockopt");
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = (unsigned short)htons((unsigned short)port);
if (!mudstate.restarting)
if (bind(s, (struct sockaddr *)&server, sizeof(server))) {
log_perror("NET", "FAIL", NULL, "bind");
close(s);
exit(4);
}
listen(s, 5);
return s;

void shovechars(port)
int port;
{
fd_set input_set, output_set;
struct timeval last_slice, current_time, next_slice, timeout, slice_timeout;
int found, check;
DESC *d, *dnext, *newd;
int avail_descriptors, maxfds;
struct stat fstatbuf;
#define CheckInput(x)
#define CheckOutput(x)

FD_ISSET(x, &input_set)
FD_ISSET(x, &output_set)

mudstate.debug_cmd = (char *)"< shovechars >";


if (!mudstate.restarting) {
sock = make_socket(port);
}
if (!mudstate.restarting)
maxd = sock + 1;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:52 PM

get_tod(&last_slice);
#ifdef HAVE_GETDTABLESIZE
maxfds = getdtablesize();
#else
maxfds = sysconf(_SC_OPEN_MAX);
#endif
avail_descriptors = maxfds - 7;
while (mudstate.shutdown_flag == 0) {
get_tod(&current_time);
last_slice = update_quotas(last_slice, current_time);
process_commands();
if (mudstate.shutdown_flag)
break;
/* We've gotten a signal to dump flatfiles */
if (mudstate.flatfile_flag && !mudstate.dumping) {
if (*mudconf.dump_msg)
raw_broadcast(0, "%s", mudconf.dump_msg);
mudstate.dumping = 1;
STARTLOG(LOG_DBSAVES, "DMP", "CHKPT")
log_printf("Flatfiling: %s.#%d#",
mudconf.gdbm, mudstate.epoch);
ENDLOG
dump_database_internal(DUMP_DB_FLATFILE);
mudstate.dumping = 0;

if (*mudconf.postdump_msg)
raw_broadcast(0, "%s", mudconf.postdump_msg);
mudstate.flatfile_flag = 0;

/*
* test for events
*/
dispatch();
/*
* any queued robot commands waiting?
*/
timeout.tv_sec = que_next();
timeout.tv_usec = 0;
next_slice = msec_add(last_slice, mudconf.timeslice);
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:52 PM

slice_timeout = timeval_sub(next_slice, current_time);


FD_ZERO(&input_set);
FD_ZERO(&output_set);
/*
* Listen for new connections if there are free descriptors
*/
if (ndescriptors < avail_descriptors) {
FD_SET(sock, &input_set);
}
/*
* Listen for replies from the slave socket
*/
if (slave_socket != -1) {
FD_SET(slave_socket, &input_set);
}
/*
* Mark sockets that we want to test for change in status
*/
DESC_ITER_ALL(d) {
if (!d->input_head)
FD_SET(d->descriptor, &input_set);
if (d->output_head)
FD_SET(d->descriptor, &output_set);
}
/*
* Wait for something to happen
*/
found = select(maxd, &input_set, &output_set, (fd_set *) NULL,
&timeout);
if (found < 0) {
if (errno == EBADF) {
/* This one is bad, as it results in a
* spiral of doom, unless we can figure
* out what the bad file descriptor is
* and get rid of it.
*/
log_perror("NET", "FAIL",
"checking for activity", "select");
DESC_ITER_ALL(d) {
if (fstat(d->descriptor, &fstatbuf) < 0) {
/* It's a player. Just toss the
* connection.
*/
STARTLOG(LOG_PROBLEMS, "ERR", "EBADF")
log_printf("Bad descriptor %d",
d->descriptor);
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:52 PM

ENDLOG
shutdownsock(d, R_SOCKDIED);
}

}
if ((slave_socket == -1) ||
(fstat(slave_socket, &fstatbuf) < 0)) {
/* Try to restart the slave, since
* it presumably died.
*/
STARTLOG(LOG_PROBLEMS, "ERR", "EBADF")
log_printf("Bad slave descriptor %d",
slave_socket);
ENDLOG
boot_slave();
}
if ((mudstate.sql_socket != -1) &&
(fstat(mudstate.sql_socket, &fstatbuf) < 0)) {
/* Just mark it dead. */
STARTLOG(LOG_PROBLEMS, "ERR", "EBADF")
log_printf("Bad SQL descriptor %d",
mudstate.sql_socket);
ENDLOG
mudstate.sql_socket = -1;
}
if ((sock != -1) &&
(fstat(sock, &fstatbuf) < 0)) {
/* That's it, game over. */
STARTLOG(LOG_PROBLEMS, "ERR", "EBADF")
log_printf("Bad game port descriptor %d" ,
sock);
ENDLOG
break;
}
} else if (errno != EINTR) {
log_perror("NET", "FAIL",
"checking for activity", "select");
}
continue;

}
/*
* if !found then time for robot commands
*/
if (!found) {
if (mudconf.queue_chunk)
do_top(mudconf.queue_chunk);
continue;
} else {
do_top(mudconf.active_q_chunk);
}
/*
* Get usernames and hostnames
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:52 PM

*/
if (slave_socket != -1 &&
FD_ISSET(slave_socket, &input_set)) {
while (get_slave_result() == 0) ;
}
/*
* Check for new connection requests
*/
if (CheckInput(sock)) {
newd = new_connection(sock);
if (!newd) {
check = (errno && (errno != EINTR) &&
(errno != EMFILE) &&
(errno != ENFILE));
if (check) {
log_perror("NET", "FAIL", NULL,
"new_connection");
}
} else {
if (newd->descriptor >= maxd)
maxd = newd->descriptor + 1;
}
}
/*
* Check for activity on user sockets
*/
DESC_SAFEITER_ALL(d, dnext) {
/*
* Process input from sockets with pending input
*/
if (CheckInput(d->descriptor)) {
/*
* Undo AutoDark
*/
if (d->flags & DS_AUTODARK) {
d->flags &= ~DS_AUTODARK;
s_Flags(d->player,
Flags(d->player) & ~DARK);
}
/*
* Process received data
*/
if (!process_input(d)) {
shutdownsock(d, R_SOCKDIED);
continue;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:52 PM

}
}
/*
* Process output for sockets with pending output
*/

if (CheckOutput(d->descriptor)) {
if (!process_output(d)) {
shutdownsock(d, R_SOCKDIED);
}
}

#ifdef BROKEN_GCC_PADDING
char *inet_ntoa(in)
struct in_addr in;
{
/* gcc 2.8.1 does not correctly pass/return structures which are smaller
* than 16 bytes, but are not 8 bytes. Structures get padded at the
* wrong end. gcc is consistent with itself, but if you try to link
* with library files, there's a problem. This particularly affects
* Irix 6, but also affects other 64-bit targets.
*
* There may be little/big-endian problems with this, too.
*/
static char buf[MBUF_SIZE];
long a = in.s_addr;
sprintf(buf, "%d.%d.%d.%d",
(int) ((a >> 24) & 0xff),
(int) ((a >> 16) & 0xff),
(int) ((a >> 8) & 0xff),
(int) (a & 0xff));
return buf;

}
#endif /* BROKEN_GCC_PADDING */
DESC *new_connection(sock)
int sock;
{
int newsock;
char *buff, *cmdsave;
DESC *d;
struct sockaddr_in addr;
int addr_len, len;
char *buf;

cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< new_connection >";
addr_len = sizeof(struct sockaddr);
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

Saturday, June 16, 2012 11:52 PM

newsock = accept(sock, (struct sockaddr *)&addr, &addr_len);


if (newsock < 0)
return 0;
if (site_check(addr.sin_addr, mudstate.access_list) & H_FORBIDDEN) {
STARTLOG(LOG_NET | LOG_SECURITY, "NET", "SITE")
log_printf("[%d/%s] Connection refused. (Remote port %d)" ,
newsock, inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port));
ENDLOG
fcache_rawdump(newsock, FC_CONN_SITE);
shutdown(newsock, 2);
close(newsock);
errno = 0;
d = NULL;
} else {
buff = alloc_mbuf("new_connection.address");
buf = alloc_lbuf("new_connection.write");
StringCopy(buff, inet_ntoa(addr.sin_addr));
/*
* Ask slave process for host and username
*/
if ((slave_socket != -1) && mudconf.use_hostname) {
sprintf(buf, "%s\n%s,%d,%d\n", inet_ntoa(addr.sin_addr), inet_ntoa(addr.
sin_addr), ntohs(addr.sin_port), mudconf.port);
len = strlen(buf);
if (WRITE(slave_socket, buf, len) < 0) {
close(slave_socket);
slave_socket = -1;
}
}
free_lbuf(buf);
STARTLOG(LOG_NET, "NET", "CONN")
log_printf("[%d/%s] Connection opened (remote port %d)" ,
newsock, buff, ntohs(addr.sin_port));
ENDLOG
d = initializesock(newsock, &addr);
mudstate.debug_cmd = cmdsave;
free_mbuf(buff);

}
mudstate.debug_cmd = cmdsave;
return (d);

/*
* (Dis)connect reasons that get written to the logfile
*/
const char *conn_reasons[] =
{
"Unspecified",
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

Saturday, June 16, 2012 11:52 PM

"Guest-connected to",
"Created",
"Connected to",
"Dark-connected to",

};

"Quit",
"Inactivity Timeout",
"Booted",
"Remote Close or Net Failure" ,
"Game Shutdown",
"Login Retry Limit",
"Logins Disabled",
"Logout (Connection Not Dropped)" ,
"Too Many Connected Players"

/*
* (Dis)connect reasons that get fed to A_A(DIS)CONNECT via
* announce_connattr
*/
const char *conn_messages[] =
{
"unknown",
"guest",
"create",
"connect",
"cd",

};

"quit",
"timeout",
"boot",
"netdeath",
"shutdown",
"badlogin",
"nologins",
"logout"

void shutdownsock(d, reason)


DESC *d;
int reason;
{
char *buff2;
time_t now;
int ncon;
DESC *dtemp;
if ((reason == R_LOGOUT) &&
(site_check((d->address).sin_addr, mudstate.access_list) & H_FORBIDDEN))
reason = R_QUIT;
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741

Saturday, June 16, 2012 11:52 PM

if (d->flags & DS_CONNECTED) {


/*
* Do the disconnect stuff if we aren't doing a LOGOUT
* (which keeps the connection open so the player can
* connect to a different character).
*/
if (reason != R_LOGOUT) {
if (reason != R_SOCKDIED) {
/* If the socket died, there's no reason to
* display the quit file.
*/
fcache_dump(d, FC_QUIT);
}
STARTLOG(LOG_NET | LOG_LOGIN, "NET", "DISC")
log_printf("[%d/%s] Logout by ",
d->descriptor, d->addr);
log_name(d->player);
log_printf(" <%s: %d cmds, %d bytes in, %d bytes out, %d secs>" ,
conn_reasons[reason], d->command_count,
d->input_tot, d->output_tot,
(int) (time(NULL) - d->connected_at));
ENDLOG
} else {
STARTLOG(LOG_NET | LOG_LOGIN, "NET", "LOGO")
log_printf("[%d/%s] Logout by ",
d->descriptor, d->addr);
log_name(d->player);
log_printf(" <%s: %d cmds, %d bytes in, %d bytes out, %d secs>" ,
conn_reasons[reason], d->command_count,
d->input_tot, d->output_tot,
(int) (time(NULL) - d->connected_at));
ENDLOG
}
/*
* If requested, write an accounting record of the form:
* Plyr# Flags Cmds ConnTime Loc Money [Site] <DiscRsn> Name
*/
STARTLOG(LOG_ACCOUNTING, "DIS", "ACCT")
now = mudstate.now - d->connected_at;
buff2 = unparse_flags(GOD, d->player);
log_printf("%d %s %d %d %d %d [%s] <%s> " ,
d->player, buff2, d->command_count, (int) now,
Location(d->player), Pennies(d->player),
d->addr, conn_reasons[reason]);
log_name(d->player);
free_sbuf(buff2);
ENDLOG
announce_disconnect(d->player, d, conn_messages[reason]);
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794

Saturday, June 16, 2012 11:52 PM

} else {
if (reason == R_LOGOUT)
reason = R_QUIT;
STARTLOG(LOG_SECURITY | LOG_NET, "NET", "DISC")
log_printf("[%d/%s] Connection closed, never connected. <Reason: %s>" ,
d->descriptor, d->addr, conn_reasons[reason]);
ENDLOG
}
process_output(d);
clearstrings(d);
/* If this was our only connection, get out of interactive
* mode.
*/
if (d->program_data) {
ncon = 0;
DESC_ITER_PLAYER(d->player, dtemp) ncon++;
if (ncon == 0) {
Free_RegData(d->program_data->wait_data);
XFREE(d->program_data, "do_prog");
atr_clr(d->player, A_PROGCMD);
}
d->program_data = NULL;
}
if (d->colormap) {
XFREE(d->colormap, "colormap");
d->colormap = NULL;
}
if (reason == R_LOGOUT) {
d->flags &= ~DS_CONNECTED;
d->connected_at = time(NULL);
d->retries_left = mudconf.retry_limit;
d->command_count = 0;
d->timeout = mudconf.idle_timeout;
d->player = 0;
d->doing[0] = '\0';
d->quota = mudconf.cmd_quota_max;
d->last_time = 0;
d->host_info = site_check((d->address).sin_addr,
mudstate.access_list) |
site_check((d->address).sin_addr,
mudstate.suspect_list);
d->input_tot = d->input_size;
d->output_tot = 0;
welcome_user(d);
} else {
shutdown(d->descriptor, 2);
close(d->descriptor);
freeqs(d);
*d->prev = d->next;
if (d->next)
d->next->prev = d->prev;
free_desc(d);
ndescriptors--;
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

Saturday, June 16, 2012 11:52 PM

void make_nonblocking(s)
int s;
{
#ifdef HAVE_LINGER
struct linger ling;
#endif
#ifdef FNDELAY
if (fcntl(s, F_SETFL, FNDELAY) == -1) {
log_perror("NET", "FAIL", "make_nonblocking", "fcntl");
}
#else
if (fcntl(s, F_SETFL, O_NDELAY) == -1) {
log_perror("NET", "FAIL", "make_nonblocking", "fcntl");
}
#endif
#ifdef HAVE_LINGER
ling.l_onoff = 0;
ling.l_linger = 0;
if (setsockopt(s, SOL_SOCKET, SO_LINGER,
(char *)&ling, sizeof(ling)) < 0) {
log_perror("NET", "FAIL", "linger", "setsockopt");
}
#endif
}
DESC *initializesock(s, a)
int s;
struct sockaddr_in *a;
{
DESC *d;
if (s == slave_socket) {
/* Whoa. We shouldn't be allocating this. If we got this
* descriptor, our connection with the slave must have
* died somehow. We make sure to take note appropriately.
*/
STARTLOG(LOG_ALWAYS, "ERR", "SOCK")
log_printf("Player descriptor clashes with slave fd %d" ,
slave_socket);
ENDLOG
slave_socket = -1;
}
if (s == mudstate.sql_socket) {
/* We shouldn't be allocating this either, for the same reason. */
STARTLOG(LOG_ALWAYS, "ERR", "SOCK")
log_printf("Player descriptor clashes with SQL server fd %d" ,
mudstate.sql_socket);
ENDLOG
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900

Saturday, June 16, 2012 11:52 PM

mudstate.sql_socket = -1;

ndescriptors++;
d = alloc_desc("init_sock");
d->descriptor = s;
d->flags = 0;
d->connected_at = time(NULL);
d->retries_left = mudconf.retry_limit;
d->command_count = 0;
d->timeout = mudconf.idle_timeout;
d->host_info = site_check((*a).sin_addr, mudstate.access_list) |
site_check((*a).sin_addr, mudstate.suspect_list);
d->player = 0;
/*
* be sure #0 isn't wizard. Shouldn't be.
*/

d->addr[0] = '\0';
d->doing[0] = '\0';
d->username[0] = '\0';
d->colormap = NULL;
make_nonblocking(s);
d->output_prefix = NULL;
d->output_suffix = NULL;
d->output_size = 0;
d->output_tot = 0;
d->output_lost = 0;
d->output_head = NULL;
d->output_tail = NULL;
d->input_head = NULL;
d->input_tail = NULL;
d->input_size = 0;
d->input_tot = 0;
d->input_lost = 0;
d->raw_input = NULL;
d->raw_input_at = NULL;
d->quota = mudconf.cmd_quota_max;
d->program_data = NULL;
d->last_time = 0;
d->address = *a;
/*
* added 5/3/90 SCG
*/
if (descriptor_list)
descriptor_list->prev = &d->next;
d->hashnext = NULL;
d->next = descriptor_list;
d->prev = &descriptor_list;
StringCopyTrunc(d->addr, inet_ntoa(a->sin_addr), 50);
descriptor_list = d;
welcome_user(d);
return d;

-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953

Saturday, June 16, 2012 11:52 PM

int process_output(d)
DESC *d;
{
TBLOCK *tb, *save;
int cnt;
char *cmdsave;
cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< process_output >";
tb = d->output_head;
while (tb != NULL) {
while (tb->hdr.nchars > 0) {
cnt = WRITE(d->descriptor, tb->hdr.start,
tb->hdr.nchars);
if (cnt < 0) {
mudstate.debug_cmd = cmdsave;
if (errno == EWOULDBLOCK)
return 1;
return 0;
}
d->output_size -= cnt;
tb->hdr.nchars -= cnt;
tb->hdr.start += cnt;
}
save = tb;
tb = tb->hdr.nxt;
XFREE(save, "queue_write");
d->output_head = tb;
if (tb == NULL)
d->output_tail = NULL;
}

mudstate.debug_cmd = cmdsave;
return 1;

int process_input(d)
DESC *d;
{
char *buf;
int got, in, lost;
char *p, *pend, *q, *qend;
char *cmdsave;
cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< process_input >";
buf = alloc_lbuf("process_input.buf");
got = in = READ(d->descriptor, buf, LBUF_SIZE);
if (got <= 0) {
mudstate.debug_cmd = cmdsave;
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006

Saturday, June 16, 2012 11:52 PM

free_lbuf(buf);
return 0;

}
if (!d->raw_input) {
d->raw_input = (CBLK *) alloc_lbuf("process_input.raw");
d->raw_input_at = d->raw_input->cmd;
}
p = d->raw_input_at;
pend = d->raw_input->cmd - sizeof(CBLKHDR) - 1 + LBUF_SIZE;
lost = 0;
for (q = buf, qend = buf + got; q < qend; q++) {
if (*q == '\n') {
*p = '\0';
if (p > d->raw_input->cmd) {
save_command(d, d->raw_input);
d->raw_input = (CBLK *) alloc_lbuf("process_input.raw");
p = d->raw_input_at = d->raw_input->cmd;
pend = d->raw_input->cmd - sizeof(CBLKHDR) - 1 + LBUF_SIZE;
} else {
in -= 1;
/* for newline */
}
} else if ((*q == '\b') || (*q == 127)) {
if (*q == 127)
queue_string(d, "\b \b");
else
queue_string(d, " \b");
in -= 2;
if (p > d->raw_input->cmd)
p--;
if (p < d->raw_input_at)
(d->raw_input_at)--;
} else if (p < pend && isascii(*q) && isprint(*q)) {
*p++ = *q;
} else {
in--;
if (p >= pend)
lost++;
}

}
if (in < 0)
/* backspace and delete by themselves */
in = 0;
if (p > d->raw_input->cmd) {
d->raw_input_at = p;
} else {
free_lbuf(d->raw_input);
d->raw_input = NULL;
d->raw_input_at = NULL;
}
d->input_tot += got;
d->input_size += in;
d->input_lost += lost;
free_lbuf(buf);
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059

Saturday, June 16, 2012 11:52 PM

mudstate.debug_cmd = cmdsave;
return 1;

void close_sockets(emergency, message)


int emergency;
char *message;
{
DESC *d, *dnext;
DESC_SAFEITER_ALL(d, dnext) {
if (emergency) {
WRITE(d->descriptor, message, strlen(message));
if (shutdown(d->descriptor, 2) < 0)
log_perror("NET", "FAIL", NULL, "shutdown");
close(d->descriptor);
} else {
queue_string(d, message);
queue_write(d, "\r\n", 2);
shutdownsock(d, R_GOING_DOWN);
}

}
close(sock);

void NDECL(emergency_shutdown)
{
close_sockets(1, (char *)"Going down - Bye");
}
/* --------------------------------------------------------------------------* Print out stuff into error file.
*/
void NDECL(report)
{
STARTLOG(LOG_BUGS, "BUG", "INFO")
log_printf("Command: '%s'", mudstate.debug_cmd);
ENDLOG
if (Good_obj(mudstate.curr_player)) {
STARTLOG(LOG_BUGS, "BUG", "INFO")
log_printf("Player: ");
log_name_and_loc(mudstate.curr_player);
if ((mudstate.curr_enactor != mudstate.curr_player) &&
Good_obj(mudstate.curr_enactor)) {
log_printf(" Enactor: ");
log_name_and_loc(mudstate.curr_enactor);
}
ENDLOG
}
}

-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112

Saturday, June 16, 2012 11:52 PM

/* --------------------------------------------------------------------------* * Signal handling routines.


*/
#ifndef SIGCHLD
#define SIGCHLD SIGCLD
#endif
static RETSIGTYPE FDECL(sighandler, (int));
/* *INDENT-OFF* */
NAMETAB sigactions_nametab[] = {
{(char *)"exit",
3, 0, SA_EXIT},
{(char *)"default", 1, 0, SA_DFLT},
{ NULL,
0, 0, 0}};
/* *INDENT-ON* */
void NDECL(set_signals)
{
sigset_t sigs;
/* We have to reset our signal mask, because of the possibility
* that we triggered a restart on a SIGUSR1. If we did so, then
* the signal became blocked, and stays blocked, since control
* never returns to the caller; i.e., further attempts to send
* a SIGUSR1 would fail.
*/
sigfillset(&sigs);
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
signal(SIGALRM, sighandler);
signal(SIGCHLD, sighandler);
signal(SIGHUP, sighandler);
signal(SIGINT, sighandler);
signal(SIGQUIT, sighandler);
signal(SIGTERM, sighandler);
signal(SIGPIPE, SIG_IGN);
signal(SIGUSR1, sighandler);
signal(SIGUSR2, sighandler);
signal(SIGTRAP, sighandler);
#ifdef SIGXCPU
signal(SIGXCPU, sighandler);
#endif
signal(SIGFPE, SIG_IGN);
signal(SIGILL, sighandler);
signal(SIGSEGV, sighandler);
signal(SIGABRT, sighandler);
#ifdef SIGFSZ
signal(SIGXFSZ, sighandler);
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

Saturday, June 16, 2012 11:52 PM

#endif
#ifdef SIGEMT
signal(SIGEMT, sighandler);
#endif
#ifdef SIGBUS
signal(SIGBUS, sighandler);
#endif
#ifdef SIGSYS
signal(SIGSYS, sighandler);
#endif
}
static void unset_signals()
{
int i;

for (i = 0; i < NSIG; i++)


signal(i, SIG_DFL);

static void check_panicking(sig)


int sig;
{
int i;
/*
* If we are panicking, turn off signal catching and resignal
*/

if (mudstate.panicking) {
for (i = 0; i < NSIG; i++)
signal(i, SIG_DFL);
kill(getpid(), sig);
}
mudstate.panicking = 1;

void log_signal(signame)
const char *signame;
{
STARTLOG(LOG_PROBLEMS, "SIG", "CATCH")
log_printf("Caught signal %s", signame);
ENDLOG
}
static RETSIGTYPE sighandler(sig)
int sig;
{
#ifdef HAVE_SYS_SIGNAME
#define signames sys_signame
#else
#ifdef SYS_SIGLIST_DECLARED
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218

Saturday, June 16, 2012 11:52 PM

#define signames sys_siglist


#else
static const char *signames[] =
{
"SIGZERO", "SIGHUP", "SIGINT", "SIGQUIT",
"SIGILL", "SIGTRAP", "SIGABRT", "SIGEMT",
"SIGFPE", "SIGKILL", "SIGBUS", "SIGSEGV",
"SIGSYS", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGURG", "SIGSTOP", "SIGTSTP", "SIGCONT",
"SIGCHLD", "SIGTTIN", "SIGTTOU", "SIGIO",
"SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF",
"SIGWINCH", "SIGLOST", "SIGUSR1", "SIGUSR2"};
#endif
#endif

/* SYS_SIGLIST_DECLARED */
/* HAVE_SYS_SIGNAME */

int i;
pid_t child;
#if defined(HAVE_UNION_WAIT) && defined(NEED_WAIT3_DCL)
union wait stat;
#else
int stat;
#endif
switch (sig) {
case SIGUSR1:
/* Normal restart now */
log_signal(signames[sig]);
do_restart(GOD, GOD, 0);
break;
case SIGUSR2:
/* Dump a flatfile soon */
mudstate.flatfile_flag = 1;
break;
case SIGALRM:
/* Timer */
mudstate.alarm_triggered = 1;
break;
case SIGCHLD:
/* Change in child status */
#ifndef SIGNAL_SIGCHLD_BRAINDAMAGE
signal(SIGCHLD, sighandler);
#endif
while ((child = WAITOPT(&stat, WNOHANG)) > 0) {
if (mudconf.fork_dump && mudstate.dumping &&
child == mudstate.dumper &&
(WIFEXITED(stat) || WIFSIGNALED(stat))) {
mudstate.dumping = 0;
mudstate.dumper = 0;
} else if (child == slave_pid &&
(WIFEXITED(stat) || WIFSIGNALED(stat))) {
slave_pid = 0;
slave_socket = -1;
}
}
break;
case SIGHUP:
/* Dump database soon */
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

Saturday, June 16, 2012 11:52 PM

log_signal(signames[sig]);
mudstate.dump_counter = 0;
break;
case SIGINT:
/* Log + ignore */
log_signal(signames[sig]);
break;
case SIGQUIT:
/* Normal shutdown soon */
mudstate.shutdown_flag = 1;
break;
case SIGTERM:
/* Killed shutdown now */
#ifdef SIGXCPU
case SIGXCPU:
#endif
check_panicking(sig);
log_signal(signames[sig]);
raw_broadcast(0, "GAME: Caught signal %s, exiting." ,
signames[sig]);
dump_database_internal(DUMP_DB_KILLED);
exit(0);
break;
case SIGILL:
/* Panic save + restart now, or coredump now */
case SIGFPE:
case SIGSEGV:
case SIGTRAP:
#ifdef SIGXFSZ
case SIGXFSZ:
#endif
#ifdef SIGEMT
case SIGEMT:
#endif
#ifdef SIGBUS
case SIGBUS:
#endif
#ifdef SIGSYS
case SIGSYS:
#endif
check_panicking(sig);
log_signal(signames[sig]);
report();
if (mudconf.sig_action != SA_EXIT) {
raw_broadcast(0, "GAME: Fatal signal %s caught, restarting with previous
database.", signames[sig]);
/* Don't sync first. Using older db. */
dump_database_internal(DUMP_DB_CRASH);
CLOSE;
if (slave_socket != -1) {
shutdown(slave_socket, 2);
close(slave_socket);
slave_socket = -1;
}
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

Saturday, June 16, 2012 11:52 PM

if (slave_pid != 0) {
kill(slave_pid, SIGKILL);
}
/* Try our best to dump a usable core by generating
* a second signal with the SIG_DFL action.
*/
if (fork() > 0) {
unset_signals();
/* In the parent process (easier to follow
* with gdb), we're about to return from
* this signal handler and hope that a
* second signal is delivered. Meanwhile
* let's close all our files to avoid
* corrupting the child process.
*/
for (i = 0; i < maxd; i++)
close(i);
}

return;

alarm(0);
dump_restart_db();
execl(mudconf.exec_path, mudconf.exec_path,
(char *) "-c", mudconf.config_file,
(char *) "-l", mudconf.mudlogname,
(char *) "-p", mudconf.pid_file,
(char *) "-t", mudconf.txthome,
(char *) "-b", mudconf.binhome,
(char *) "-d", mudconf.dbhome,
(char *) "-g", mudconf.gdbm,
(char *) "-k", mudconf.crashdb,
NULL);
break;
} else {
unset_signals();
fprintf(mainlog_fp, "ABORT! bsd.c, SA_EXIT requested.\n" );
abort();
}
case SIGABRT:
/* Coredump now */
check_panicking(sig);
log_signal(signames[sig]);
report();
unset_signals();
fprintf(mainlog_fp, "ABORT! bsd.c, SIGABRT received.\n" );
abort();

}
signal(sig, sighandler);
mudstate.panicking = 0;

-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\bsd.c

1324
1325
1326

Saturday, June 16, 2012 11:52 PM

return;

-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:17 PM

/* cmdtabs.h - command and other supporting tables */


/* $Id: cmdtabs.h,v 1.46 2008/03/09 17:09:03 lwl Exp $ */
#include "copyright.h"
/* Make sure that all of your command and switch names are lowercase! */
/* *INDENT-OFF* */
/* --------------------------------------------------------------------------* Switch tables for the various commands.
*/
NAMETAB addcmd_sw[] = {
{(char *)"preserve",
1,
{ NULL,
0, 0,

CA_GOD,
0}};

ADDCMD_PRESERVE},

NAMETAB attrib_sw[]
{(char *)"access",
{(char *)"delete",
{(char *)"info",
{(char *)"rename",
{ NULL,
0,

= {
1,
1,
1,
1,
0,

CA_GOD,
CA_GOD,
CA_WIZARD,
CA_GOD,
0}};

ATTRIB_ACCESS},
ATTRIB_DELETE},
ATTRIB_INFO},
ATTRIB_RENAME},

NAMETAB boot_sw[] =
{(char *)"port",
{(char *)"quiet",
{ NULL,
0,

{
1,
1,
0,

CA_WIZARD,
CA_WIZARD,
0}};

BOOT_PORT|SW_MULTIPLE},
BOOT_QUIET|SW_MULTIPLE},

NAMETAB chown_sw[] = {
{(char *)"nostrip", 1,
{ NULL,
0, 0,

CA_WIZARD,
0}};

CHOWN_NOSTRIP},

NAMETAB chzone_sw[] = {
{(char *)"nostrip", 1, CA_WIZARD,
{ NULL,
0, 0,
0}};
NAMETAB clone_sw[] = {
{(char *)"cost",
1,
{(char *)"inherit", 3,
{(char *)"inventory",
{(char *)"location",
{(char *)"nostrip", 1,
{(char *)"parent", 2,
{(char *)"preserve",
{ NULL,
0, 0,

CHZONE_NOSTRIP},

CA_PUBLIC, CLONE_SET_COST|SW_MULTIPLE},
CA_PUBLIC, CLONE_INHERIT|SW_MULTIPLE},
3, CA_PUBLIC, CLONE_INVENTORY},
1, CA_PUBLIC, CLONE_LOCATION},
CA_WIZARD, CLONE_NOSTRIP|SW_MULTIPLE},
CA_PUBLIC, CLONE_FROM_PARENT|SW_MULTIPLE},
2, CA_PUBLIC, CLONE_PRESERVE|SW_MULTIPLE},
0}};

NAMETAB decomp_sw[] = {
{(char *)"pretty", 1, CA_PUBLIC,
{ NULL,
0, 0,
0}};
NAMETAB destroy_sw[] = {
{(char *)"instant", 4, CA_PUBLIC,

DECOMP_PRETTY},

DEST_INSTANT|SW_MULTIPLE},
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

{(char *)"override",
{ NULL,
0, 0,
NAMETAB dig_sw[] = {
{(char *)"teleport",
{ NULL,
0, 0,

Saturday, June 16, 2012 11:17 PM

8,

CA_PUBLIC,
0}};

DEST_OVERRIDE|SW_MULTIPLE},

1,

CA_PUBLIC,
0}};

DIG_TELEPORT},

NAMETAB doing_sw[] = {
{(char *)"header", 1,
{(char *)"message", 1,
{(char *)"poll",
1,
{(char *)"quiet",
1,
{ NULL,
0, 0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

NAMETAB dolist_sw[] = {
{(char *)"delimit",
{(char *)"space",
{(char *)"notify", 1,
{(char *)"now",
1,
{ NULL,

1,
CA_PUBLIC,
DOLIST_DELIMIT},
1,
CA_PUBLIC,
DOLIST_SPACE},
CA_PUBLIC, DOLIST_NOTIFY | SW_MULTIPLE },
CA_PUBLIC,
DOLIST_NOW|SW_MULTIPLE},
0,
0,
0,}};

NAMETAB drop_sw[] = {
{(char *)"quiet",
1,
{ NULL,
0, 0,

CA_PUBLIC,
0}};

NAMETAB dump_sw[] = {
{(char *)"structure",
{(char *)"text",
1,
{(char *)"flatfile",
{ NULL,
0, 0,

1, CA_WIZARD, DUMP_STRUCT|SW_MULTIPLE},
CA_WIZARD, DUMP_TEXT|SW_MULTIPLE},
1, CA_WIZARD, DUMP_FLATFILE|SW_MULTIPLE},
0}};

NAMETAB emit_sw[] = {
{(char *)"noeval", 1,
{(char *)"here",
1,
{(char *)"room",
1,
#ifdef PUEBLO_SUPPORT
{(char *)"html",
1,
#endif
{ NULL,
0, 0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,

DOING_HEADER|SW_MULTIPLE},
DOING_MESSAGE|SW_MULTIPLE},
DOING_POLL},
DOING_QUIET|SW_MULTIPLE},

DROP_QUIET},

SW_NOEVAL | SW_MULTIPLE},
SAY_HERE|SW_MULTIPLE},
SAY_ROOM|SW_MULTIPLE},

CA_PUBLIC,

SAY_HTML|SW_MULTIPLE},

0}};

NAMETAB end_sw[] = {
{(char *)"assert", 1,
{(char *)"break",
1,
{ NULL,
0, 0,

CA_PUBLIC,
CA_PUBLIC,
0}};

ENDCMD_ASSERT},
ENDCMD_BREAK},

NAMETAB enter_sw[] = {
{(char *)"quiet",
1,
{ NULL,
0, 0,

CA_PUBLIC,
0}};

MOVE_QUIET},

NAMETAB examine_sw[] = {
{(char *)"brief",
1, CA_PUBLIC,
{(char *)"debug",
1, CA_WIZARD,
{(char *)"full",
1, CA_PUBLIC,

EXAM_BRIEF},
EXAM_DEBUG},
EXAM_LONG},
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

{(char *)"owner",
{(char *)"pairs",
{(char *)"parent",
{(char *)"pretty",
{ NULL,
0,

Saturday, June 16, 2012 11:17 PM

1,
3,
1,
2,
0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

EXAM_OWNER},
EXAM_PAIRS},
EXAM_PARENT|SW_MULTIPLE},
EXAM_PRETTY},

NAMETAB femit_sw[] = {
{(char *)"noeval", 1,
{(char *)"here",
1,
{(char *)"room",
1,
{(char *)"spoof",
1,
{ NULL,
0, 0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

SW_NOEVAL | SW_MULTIPLE},
PEMIT_HERE|SW_MULTIPLE},
PEMIT_ROOM|SW_MULTIPLE},
PEMIT_SPOOF|SW_MULTIPLE},

NAMETAB fixdb_sw[] = {
/* {(char *)"add_pname",1, CA_GOD,
{(char *)"contents",
1, CA_GOD,
{(char *)"exits",
1, CA_GOD,
{(char *)"location",
1, CA_GOD,
{(char *)"next",
1, CA_GOD,
{(char *)"owner",
1, CA_GOD,
{(char *)"pennies", 1, CA_GOD,
{(char *)"rename", 1, CA_GOD,
/* {(char *)"rm_pname", 1, CA_GOD,
{ NULL,
0, 0,
0}};

FIXDB_ADD_PN}, */
FIXDB_CON},
FIXDB_EXITS},
FIXDB_LOC},
FIXDB_NEXT},
FIXDB_OWNER},
FIXDB_PENNIES},
FIXDB_NAME},
FIXDB_DEL_PN}, */

NAMETAB floaters_sw[] = {
{(char *)"all",
1, CA_PUBLIC,
{ NULL,
0, 0,
0}};

FLOATERS_ALL},

NAMETAB force_sw[] = {
{(char *)"now",
1,
{ NULL,
0, 0,

CA_PUBLIC,
0}};

FRC_NOW|SW_MULTIPLE},

NAMETAB fpose_sw[] = {
{(char *)"default", 1,
{(char *)"noeval", 3,
{(char *)"nospace", 1,
{(char *)"spoof",
1,
{ NULL,
0, 0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

0},
SW_NOEVAL | SW_MULTIPLE},
SAY_NOSPACE},
PEMIT_SPOOF | SW_MULTIPLE},

NAMETAB fsay_sw[] =
{(char *)"noeval",
{(char *)"spoof",
{ NULL,
0,

CA_PUBLIC,
CA_PUBLIC,
0}};

SW_NOEVAL | SW_MULTIPLE},
PEMIT_SPOOF | SW_MULTIPLE},

{
1,
1,
0,

NAMETAB function_sw[] =
{(char *)"list",
1,
{(char *)"noeval", 1,
{(char *)"privileged",
{(char *)"private", 5,
{(char *)"preserve",
{ NULL,
0, 0,

{
CA_WIZARD, FUNCT_LIST},
CA_WIZARD, FUNCT_NO_EVAL|SW_MULTIPLE},
3, CA_WIZARD, FUNCT_PRIV|SW_MULTIPLE},
CA_WIZARD, FUNCT_NOREGS|SW_MULTIPLE},
3, CA_WIZARD, FUNCT_PRES|SW_MULTIPLE},
0}};

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:17 PM

NAMETAB get_sw[] = {
{(char *)"quiet",
1,
{ NULL,
0, 0,

CA_PUBLIC,
0}};

GET_QUIET},

NAMETAB give_sw[] = {
{(char *)"quiet",
1,
{ NULL,
0, 0,

CA_WIZARD,
0}};

GIVE_QUIET},

NAMETAB goto_sw[] = {
{(char *)"quiet",
1,
{ NULL,
0, 0,

CA_PUBLIC,
0}};

MOVE_QUIET},

NAMETAB halt_sw[] = {
{(char *)"all",
1,
{ NULL,
0, 0,

CA_PUBLIC,
0}};

HALT_ALL},

NAMETAB help_sw[] = {
{(char *)"fine",
{ NULL,
0, 0,

1,

CA_PUBLIC,
0}};

HELP_FIND},

NAMETAB hook_sw[] = {
{(char *)"before", 1,
{(char *)"after",
1,
{(char *)"permit", 1,
{(char *)"preserve",
{(char *)"nopreserve",
{(char *)"private", 3,
{ NULL,
0, 0,

CA_GOD,
CA_GOD,
CA_GOD,
3, CA_GOD,
1, CA_GOD,
CA_GOD,
0}};

HOOK_BEFORE},
HOOK_AFTER},
HOOK_PERMIT},
HOOK_PRESERVE},
HOOK_NOPRESERVE},
HOOK_PRIVATE},

NAMETAB leave_sw[] = {
{(char *)"quiet",
1,
{ NULL,
0, 0,

CA_PUBLIC,
0}};

MOVE_QUIET},

NAMETAB listmotd_sw[] = {
{(char *)"brief",
1, CA_WIZARD,
{ NULL,
0, 0,
0}};
NAMETAB lock_sw[] = {
{(char *)"chownlock",
{(char *)"controllock",
{(char *)"defaultlock",
{(char *)"darklock",
{(char *)"droplock",
{(char *)"enterlock",
{(char *)"givelock",
{(char *)"heardlock",
{(char *)"hearslock",
{(char *)"knownlock",
{(char *)"knowslock",
{(char *)"leavelock",
{(char *)"linklock",
{(char *)"movedlock",
{(char *)"moveslock",

2,
2,
1,
2,
2,
1,
2,
5,
5,
5,
5,
2,
2,
5,
5,

MOTD_BRIEF},

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,

A_LCHOWN},
A_LCONTROL},
A_LOCK},
A_LDARK},
A_LDROP},
A_LENTER},
A_LGIVE},
A_LHEARD},
A_LHEARS},
A_LKNOWN},
A_LKNOWS},
A_LLEAVE},
A_LLINK},
A_LMOVED},
A_LMOVES},
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:17 PM

{(char *)"pagelock",
{(char *)"parentlock",
{(char *)"receivelock",
{(char *)"teloutlock",
{(char *)"tportlock",
{(char *)"uselock", 1,
{(char *)"userlock",
{(char *)"speechlock",
{ NULL,
0, 0,

3, CA_PUBLIC, A_LPAGE},
3, CA_PUBLIC, A_LPARENT},
1, CA_PUBLIC, A_LRECEIVE},
2, CA_PUBLIC, A_LTELOUT},
2, CA_PUBLIC, A_LTPORT},
CA_PUBLIC, A_LUSE},
4, CA_PUBLIC, A_LUSER},
1, CA_PUBLIC, A_LSPEECH},
0}};

NAMETAB look_sw[] = {
{(char *)"outside",
{ NULL,

1,
0,

NAMETAB mark_sw[] =
{(char *)"set",
{(char *)"clear",
{ NULL,
0,

CA_PUBLIC,
CA_PUBLIC,
0}};

{
1,
1,
0,

CA_PUBLIC,
0,

LOOK_OUTSIDE},
0}};

MARK_SET},
MARK_CLEAR},

NAMETAB markall_sw[] = {
{(char *)"set",
1, CA_PUBLIC,
{(char *)"clear",
1, CA_PUBLIC,
{ NULL,
0, 0,
0}};

MARK_SET},
MARK_CLEAR},

NAMETAB motd_sw[] =
{(char *)"brief",
{(char *)"connect",
{(char *)"down",
{(char *)"full",
{(char *)"list",
{(char *)"wizard",
{ NULL,
0,

{
1,
1,
1,
1,
1,
1,
0,

MOTD_BRIEF|SW_MULTIPLE},
MOTD_ALL},
MOTD_DOWN},
MOTD_FULL},
MOTD_LIST},
MOTD_WIZ},

NAMETAB notify_sw[]
{(char *)"all",
{(char *)"first",
{ NULL,
0,

= {
1, CA_PUBLIC,
1, CA_PUBLIC,
0,
0}};

NAMETAB oemit_sw[] = {
{(char *)"noeval", 1,
{(char *)"speech", 1,
{ NULL,
0, 0,
NAMETAB open_sw[] = {
{(char *)"inventory",
{(char *)"location",
{ NULL,
0, 0,
NAMETAB pemit_sw[] = {
{(char *)"contents",
{(char *)"object", 1,
{(char *)"silent", 2,
{(char *)"speech", 2,

CA_WIZARD,
CA_WIZARD,
CA_WIZARD,
CA_WIZARD,
CA_PUBLIC,
CA_WIZARD,
0}};

CA_PUBLIC,
CA_PUBLIC,
0}};
1,
1,

NFY_NFYALL},
NFY_NFY},

SW_NOEVAL | SW_MULTIPLE},
PEMIT_SPEECH|SW_MULTIPLE},

CA_PUBLIC,
CA_PUBLIC,
0}};

OPEN_INVENTORY},
OPEN_LOCATION},

1, CA_PUBLIC, PEMIT_CONTENTS|SW_MULTIPLE},
CA_PUBLIC, 0},
CA_PUBLIC, 0},
CA_PUBLIC, PEMIT_SPEECH|SW_MULTIPLE},
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

{(char *)"list",
{(char *)"noeval", 1,
#ifdef PUEBLO_SUPPORT
{(char *)"html",
1,
#endif
{ NULL,
0, 0,

Saturday, June 16, 2012 11:17 PM

1,
CA_PUBLIC,
PEMIT_LIST|SW_MULTIPLE},
CA_PUBLIC, SW_NOEVAL | SW_MULTIPLE},
CA_PUBLIC,

PEMIT_HTML|SW_MULTIPLE},

0}};

NAMETAB pose_sw[] =
{(char *)"default",
{(char *)"noeval",
{(char *)"nospace",
{ NULL,
0,

{
1,
3,
1,
0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

0},
SW_NOEVAL | SW_MULTIPLE},
SAY_NOSPACE},

NAMETAB ps_sw[] = {
{(char *)"all",
{(char *)"brief",
{(char *)"long",
{(char *)"summary",
{ NULL,
0,

1,
1,
1,
1,
0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

PS_ALL|SW_MULTIPLE},
PS_BRIEF},
PS_LONG},
PS_SUMM},

NAMETAB quota_sw[] = {
{(char *)"all",
1,
{(char *)"fix",
1,
{(char *)"remaining",
{(char *)"set",
1,
{(char *)"total",
1,
{(char *)"room",
1,
{(char *)"exit",
1,
{(char *)"thing",
1,
{(char *)"player", 1,
{ NULL,
0, 0,

CA_GOD,
QUOTA_ALL|SW_MULTIPLE},
CA_WIZARD, QUOTA_FIX},
1, CA_WIZARD, QUOTA_REM|SW_MULTIPLE},
CA_WIZARD, QUOTA_SET},
CA_WIZARD, QUOTA_TOT|SW_MULTIPLE},
CA_WIZARD, QUOTA_ROOM | SW_MULTIPLE},
CA_WIZARD, QUOTA_EXIT | SW_MULTIPLE},
CA_WIZARD, QUOTA_THING | SW_MULTIPLE},
CA_WIZARD, QUOTA_PLAYER | SW_MULTIPLE},
0}};

NAMETAB reference_sw[] = {
{(char *)"list",
1, CA_PUBLIC,
{ NULL,
0, 0,
0}};

NREF_LIST},

NAMETAB set_sw[] = {
{(char *)"quiet",
1,
{ NULL,
0, 0,

SET_QUIET},

CA_PUBLIC,
0}};

NAMETAB shutdown_sw[] = {
{(char *)"abort",
1, CA_WIZARD,
{ NULL,
0, 0,
0}};

SHUTDN_COREDUMP},

NAMETAB stats_sw[] = {
{(char *)"all",
1,
{(char *)"me",
1,
{(char *)"player", 1,
{ NULL,
0, 0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

STAT_ALL},
STAT_ME},
STAT_PLAYER},

NAMETAB sweep_sw[] = {
{(char *)"commands",
{(char *)"connected",

3,
3,

CA_PUBLIC,
CA_PUBLIC,

SWEEP_COMMANDS|SW_MULTIPLE},
SWEEP_CONNECT|SW_MULTIPLE},
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

{(char *)"exits",
1,
{(char *)"here",
1,
{(char *)"inventory",
{(char *)"listeners",
{(char *)"players", 1,
{ NULL,
0, 0,
NAMETAB switch_sw[]
{(char *)"all",
{(char *)"default",
{(char *)"first",
{(char *)"now",
{ NULL,
0,

= {
1,
1,
1,
1,
0,

Saturday, June 16, 2012 11:17 PM

CA_PUBLIC, SWEEP_EXITS|SW_MULTIPLE},
CA_PUBLIC, SWEEP_HERE|SW_MULTIPLE},
1, CA_PUBLIC, SWEEP_ME|SW_MULTIPLE},
1, CA_PUBLIC, SWEEP_LISTEN|SW_MULTIPLE},
CA_PUBLIC, SWEEP_PLAYER|SW_MULTIPLE},
0}};
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

NAMETAB teleport_sw[] = {
{(char *)"loud",
1, CA_PUBLIC,
{(char *)"quiet",
1, CA_PUBLIC,
{ NULL,
0, 0,
0}};

SWITCH_ANY},
SWITCH_DEFAULT},
SWITCH_ONE},
SWITCH_NOW|SW_MULTIPLE},

TELEPORT_DEFAULT},
TELEPORT_QUIET},

NAMETAB timecheck_sw[] = {
{(char *) "log",
1, CA_WIZARD, TIMECHK_LOG | SW_MULTIPLE},
{(char *) "reset", 1, CA_WIZARD, TIMECHK_RESET | SW_MULTIPLE},
{(char *) "screen", 1,
CA_WIZARD, TIMECHK_SCREEN | SW_MULTIPLE},
{ NULL,
0, 0,
0}};
NAMETAB toad_sw[] = {
{(char *)"no_chown",
{ NULL,
0, 0,

1,

CA_WIZARD,
0}};

TOAD_NO_CHOWN|SW_MULTIPLE},

NAMETAB trig_sw[] =
{(char *)"quiet",
{(char *)"now",
{ NULL,
0,

{
1,
1,
0,

CA_PUBLIC,
CA_PUBLIC,
0}};

TRIG_QUIET},
TRIG_NOW|SW_MULTIPLE},

NAMETAB verb_sw[] =
{(char *)"known",
{(char *)"move",
{(char *)"now",
{(char *)"no_name",
{(char *)"speech",
{ NULL,
0,

{
1,
1,
3,
3,
1,
0,

CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
CA_PUBLIC,
0}};

VERB_PRESENT|SW_MULTIPLE},
VERB_MOVE|SW_MULTIPLE},
VERB_NOW|SW_MULTIPLE},
VERB_NONAME|SW_MULTIPLE},
VERB_SPEECH|SW_MULTIPLE},

NAMETAB wall_sw[] = {
{(char *)"emit",
1,
{(char *)"no_prefix",
{(char *)"pose",
1,
{(char *)"wizard", 1,
{(char *)"admin",
1,
{ NULL,
0, 0,

CA_PUBLIC, SAY_WALLEMIT},
1, CA_PUBLIC, SAY_NOTAG|SW_MULTIPLE},
CA_PUBLIC, SAY_WALLPOSE},
CA_PUBLIC, SAY_WIZSHOUT|SW_MULTIPLE},
CA_ADMIN,
SAY_ADMINSHOUT},
0}};

NAMETAB warp_sw[] = {
{(char *)"check",
1,
{(char *)"dump",
1,

CA_WIZARD,
CA_WIZARD,

TWARP_CLEAN|SW_MULTIPLE},
TWARP_DUMP|SW_MULTIPLE},
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

{(char *)"idle",
{(char *)"queue",
{(char *)"events",
{ NULL,
0,

1,
1,
1,
0,

CA_WIZARD,
CA_WIZARD,
CA_WIZARD,
0}};

NAMETAB noeval_sw[] = {
{(char *)"noeval", 1, CA_PUBLIC,
{ NULL,
0, 0,
0}};

Saturday, June 16, 2012 11:17 PM

TWARP_IDLE|SW_MULTIPLE},
TWARP_QUEUE|SW_MULTIPLE},
TWARP_EVENTS|SW_MULTIPLE},

SW_NOEVAL},

/* --------------------------------------------------------------------------* Command table: Definitions for builtin commands, used to build the command
* hash table.
*
* Format: Name
Switches
Permissions Needed
* Key (if any)
Calling Seq
Handler
*/
CMDENT command_table[] = {
{(char *)"@@",
NULL,
CA_PUBLIC,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_comment}},
{(char *)"@addcommand",
addcmd_sw, CA_GOD,
0,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_addcommand}},
{(char *)"@admin",
NULL,
CA_WIZARD,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_admin}},
{(char *)"@alias",
NULL,
CA_NO_GUEST|CA_NO_SLAVE,
0,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_alias}},
{(char *)"@apply_marked",
NULL,
CA_WIZARD|CA_GBL_INTERP,
0,
CS_ONE_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND,
NULL,
NULL,
NULL,
{do_apply_marked}},
{(char *)"@attribute",
attrib_sw, CA_WIZARD,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_attribute}},
{(char *)"@boot",
boot_sw,
CA_NO_GUEST|CA_NO_SLAVE,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_boot}},
{(char *)"@chown",
chown_sw,
CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD,
CHOWN_ONE, CS_TWO_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_chown}},
{(char *)"@chownall",
chown_sw,
CA_WIZARD|CA_GBL_BUILD,
CHOWN_ALL, CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_chownall}},
{(char *)"@chzone",
chzone_sw,
CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_chzone}},
{(char *)"@clone",
clone_sw,
CA_NO_SLAVE|CA_GBL_BUILD|CA_CONTENTS|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_INTERP|CS_FUNCTION,
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:17 PM

NULL,
NULL,
NULL,
{do_clone}},
{(char *)"@colormap",
NULL,
CA_PUBLIC,
0,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_colormap}},
{(char *)"@cpattr",
NULL,
CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD,
0,
CS_TWO_ARG|CS_ARGV,
NULL,
NULL,
NULL,
{do_cpattr}},
{(char *)"@create",
NULL,
CA_NO_SLAVE|CA_GBL_BUILD|CA_CONTENTS|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_create}},
{(char *)"@cron",
NULL,
CA_NO_SLAVE|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_cron}},
{(char *)"@crondel",
NULL,
CA_NO_SLAVE|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_crondel}},
{(char *)"@crontab",
NULL,
CA_NO_SLAVE|CA_NO_GUEST,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_crontab}},
{(char *)"@cut",
NULL,
CA_WIZARD|CA_LOCATION,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_cut}},
{(char *)"@dbck",
NULL,
CA_WIZARD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_dbck}},
{(char *)"@decompile",
decomp_sw,
CA_PUBLIC,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_decomp}},
{(char *)"@delcommand",
NULL,
CA_GOD,
0,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_delcommand}},
{(char *)"@destroy",
destroy_sw,
CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD,
DEST_ONE,
CS_ONE_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_destroy}},
/*{(char *)"@destroyall",
NULL,
CA_WIZARD|CA_GBL_BUILD,
DEST_ALL,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_destroy}}, */
{(char *)"@dig",
dig_sw,
CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD,
0,
CS_TWO_ARG|CS_ARGV|CS_INTERP,
NULL,
NULL,
NULL,
{do_dig}},
{(char *)"@disable",
NULL,
CA_WIZARD,
GLOB_DISABLE,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_global}},
{(char *)"@doing",
doing_sw,
CA_PUBLIC,
0,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_doing}},
{(char *)"@dolist",
dolist_sw,
CA_GBL_INTERP,
0,
CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND,
NULL,
NULL,
NULL,
{do_dolist}},
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:17 PM

{(char *)"@drain",
NULL,
CA_GBL_INTERP|CA_NO_SLAVE|CA_NO_GUEST,
NFY_DRAIN, CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_notify}},
{(char *)"@dump",
dump_sw,
CA_WIZARD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_dump}},
{(char *)"@edit",
NULL,
CA_NO_SLAVE|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_ARGV|CS_STRIP_AROUND,
NULL,
NULL,
NULL,
{do_edit}},
{(char *)"@emit",
emit_sw,
CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE,
SAY_EMIT,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_say}},
{(char *)"@enable",
NULL,
CA_WIZARD,
GLOB_ENABLE,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_global}},
{(char *)"@end",
end_sw,
CA_GBL_INTERP,
0,
CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND,
NULL,
NULL,
NULL,
{do_end}},
{(char *)"@entrances",
NULL,
CA_NO_GUEST,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_entrances}},
{(char *)"@eval",
NULL,
CA_NO_SLAVE,
0,
CS_ONE_ARG | CS_INTERP,
NULL,
NULL,
NULL,
{do_eval}},
{(char *)"@femit",
femit_sw,
CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE,
PEMIT_FEMIT,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_pemit}},
{(char *)"@find",
NULL,
CA_PUBLIC,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_find}},
{(char *)"@fixdb",
fixdb_sw,
CA_GOD,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_fixdb}},
{(char *)"@floaters",
floaters_sw,
CA_PUBLIC,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_floaters}},
{(char *)"@force",
force_sw,
CA_NO_SLAVE|CA_GBL_INTERP|CA_NO_GUEST,
FRC_COMMAND,
CS_TWO_ARG|CS_INTERP|CS_CMDARG,
NULL,
NULL,
NULL,
{do_force}},
{(char *)"@fpose",
fpose_sw,
CA_LOCATION|CA_NO_SLAVE,
PEMIT_FPOSE,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_pemit}},
{(char *)"@fsay",
fsay_sw,
CA_LOCATION|CA_NO_SLAVE,
PEMIT_FSAY, CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_pemit}},
{(char *)"@freelist",
NULL,
CA_WIZARD,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_freelist}},
{(char *)"@function",
function_sw,
CA_GOD,
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:17 PM

0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_function}},
{(char *)"@halt",
halt_sw,
CA_NO_SLAVE,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_halt}},
{(char *)"@hashresize",
NULL,
CA_GOD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_hashresize}},
{(char *)"@hook",
hook_sw,
CA_GOD,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_hook}},
{(char *)"@kick",
NULL,
CA_WIZARD,
QUEUE_KICK, CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_queue}},
{(char *)"@last",
NULL,
CA_NO_GUEST,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_last}},
{(char *)"@link",
NULL,
CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_link}},
{(char *)"@list",
NULL,
CA_PUBLIC,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_list}},
{(char *)"@listcommands",
NULL,
CA_GOD,
0,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_listcommands}},
{(char *)"@list_file",
NULL,
CA_WIZARD,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_list_file}},
{(char *)"@listmotd",
listmotd_sw,
CA_PUBLIC,
MOTD_LIST, CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_motd}},
{(char *)"@lock",
lock_sw,
CA_NO_SLAVE,
0,
CS_TWO_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_lock}},
{(char *)"@log",
NULL,
CA_WIZARD,
0,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_logwrite}},
{(char *)"@logrotate",
NULL,
CA_GOD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_logrotate}},
{(char *)"@mark",
mark_sw,
CA_WIZARD,
SRCH_MARK, CS_ONE_ARG|CS_NOINTERP,
NULL,
NULL,
NULL,
{do_search}},
{(char *)"@mark_all",
markall_sw, CA_WIZARD,
MARK_SET,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_markall}},
{(char *)"@motd",
motd_sw,
CA_WIZARD,
0,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_motd}},
{(char *)"@mvattr",
NULL,
CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD,
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:17 PM

0,
CS_TWO_ARG|CS_ARGV,
NULL,
NULL,
NULL,
{do_mvattr}},
{(char *)"@name",
NULL,
CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_name}},
{(char *)"@newpassword",
NULL,
CA_WIZARD,
PASS_ANY,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_newpassword}},
{(char *)"@notify",
notify_sw,
CA_GBL_INTERP|CA_NO_SLAVE|CA_NO_GUEST,
0,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_notify}},
{(char *)"@oemit",
oemit_sw,
CA_LOCATION|CA_NO_GUEST|CA_NO_SLAVE,
PEMIT_OEMIT,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_pemit}},
{(char *)"@open",
open_sw,
CA_NO_SLAVE|CA_GBL_BUILD|CA_CONTENTS|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_ARGV|CS_INTERP,
NULL,
NULL,
NULL,
{do_open}},
{(char *)"@parent",
NULL,
CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_parent}},
{(char *)"@password",
NULL,
CA_NO_GUEST,
PASS_MINE, CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_password}},
{(char *)"@pcreate",
NULL,
CA_WIZARD|CA_GBL_BUILD,
PCRE_PLAYER,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_pcreate}},
{(char *)"@pemit",
pemit_sw,
CA_NO_GUEST|CA_NO_SLAVE,
PEMIT_PEMIT,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_pemit}},
{(char *)"@npemit",
pemit_sw,
CA_NO_GUEST|CA_NO_SLAVE,
PEMIT_PEMIT,
CS_TWO_ARG|CS_UNPARSE|CS_NOSQUISH,
NULL,
NULL,
NULL,
{do_pemit}},
{(char *)"@poor",
NULL,
CA_GOD,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_poor}},
{(char *)"@power",
NULL,
CA_PUBLIC,
0,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_power}},
{(char *)"@program",
NULL,
CA_PUBLIC,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_prog}},
{(char *)"@ps",
ps_sw,
CA_PUBLIC,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_ps}},
{(char *)"@quota",
quota_sw,
CA_PUBLIC,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_quota}},
{(char *)"@quitprogram",
NULL,
CA_PUBLIC,
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:17 PM

0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_quitprog}},
{(char *)"@readcache",
NULL,
CA_WIZARD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_readcache}},
{(char *)"@redirect",
NULL,
CA_PUBLIC,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_redirect}},
{(char *)"@reference",
reference_sw,
CA_PUBLIC,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_reference}},
{(char *)"@restart",
NULL,
CA_WIZARD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_restart}},
{(char *)"@robot",
NULL,
CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST|CA_PLAYER,
PCRE_ROBOT, CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_pcreate}},
{(char *)"@search",
NULL,
CA_PUBLIC,
SRCH_SEARCH,
CS_ONE_ARG|CS_NOINTERP,
NULL,
NULL,
NULL,
{do_search}},
{(char *)"@set",
set_sw,
CA_NO_SLAVE|CA_GBL_BUILD|CA_NO_GUEST,
0,
CS_TWO_ARG,
NULL,
NULL,
NULL,
{do_set}},
{(char *)"@shutdown",
shutdown_sw,
CA_WIZARD,
0,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_shutdown}},
{(char *)"@sql",
NULL,
CA_SQL_OK,
0,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_sql}},
{(char *)"@sqlconnect",
NULL,
CA_WIZARD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_sql_connect}},
{(char *)"@sqldisconnect", NULL,
CA_WIZARD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{sql_shutdown}},
{(char *)"@stats",
stats_sw,
CA_PUBLIC,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_stats}},
{(char *)"@startslave",
NULL,
CA_WIZARD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{boot_slave}},
{(char *)"@sweep",
sweep_sw,
CA_PUBLIC,
0,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_sweep}},
{(char *)"@switch",
switch_sw, CA_GBL_INTERP,
0,
CS_TWO_ARG|CS_ARGV|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND,
NULL,
NULL,
NULL,
{do_switch}},
{(char *)"@teleport",
teleport_sw,
CA_NO_GUEST,
TELEPORT_DEFAULT, CS_TWO_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_teleport}},
{(char *)"@timecheck",
timecheck_sw,
CA_WIZARD,
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:17 PM

0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_timecheck}},
{(char *)"@timewarp",
warp_sw,
CA_WIZARD,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_timewarp}},
{(char *)"@toad",
toad_sw,
CA_WIZARD,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_toad}},
{(char *)"@trigger",
trig_sw,
CA_GBL_INTERP,
0,
CS_TWO_ARG|CS_ARGV,
NULL,
NULL,
NULL,
{do_trigger}},
{(char *)"@unlink",
NULL,
CA_NO_SLAVE|CA_GBL_BUILD,
0,
CS_ONE_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_unlink}},
{(char *)"@unlock",
lock_sw,
CA_NO_SLAVE,
0,
CS_ONE_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_unlock}},
{(char *)"@verb",
verb_sw,
CA_GBL_INTERP|CA_NO_SLAVE,
0,
CS_TWO_ARG|CS_ARGV|CS_INTERP|CS_STRIP_AROUND,
NULL,
NULL,
NULL,
{do_verb}},
{(char *)"@wait",
NULL,
CA_GBL_INTERP,
0,
CS_TWO_ARG|CS_CMDARG|CS_NOINTERP|CS_STRIP_AROUND,
NULL,
NULL,
NULL,
{do_wait}},
{(char *)"@wall",
wall_sw,
CA_PUBLIC,
SAY_SHOUT, CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_say}},
{(char *)"@wipe",
NULL,
CA_NO_SLAVE|CA_NO_GUEST|CA_GBL_BUILD,
0,
CS_ONE_ARG|CS_INTERP|CS_FUNCTION,
NULL,
NULL,
NULL,
{do_wipe}},
{(char *)"drop",
drop_sw,
CA_NO_SLAVE|CA_CONTENTS|CA_LOCATION|CA_NO_GUEST,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_drop}},
{(char *)"enter",
enter_sw,
CA_LOCATION,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_enter}},
{(char *)"examine",
examine_sw, CA_PUBLIC,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_examine}},
{(char *)"get",
get_sw,
CA_LOCATION|CA_NO_GUEST,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_get}},
{(char *)"give",
give_sw,
CA_LOCATION|CA_NO_GUEST,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_give}},
{(char *)"goto",
goto_sw,
CA_LOCATION,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_move}},
{(char *)"internalgoto",
NULL,
CA_GOD,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_comment}},
{(char *)"inventory",
NULL,
CA_PUBLIC,
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:17 PM

LOOK_INVENTORY, CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_inventory}},
{(char *)"kill",
NULL,
CA_NO_GUEST|CA_NO_SLAVE,
KILL_KILL, CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_kill}},
{(char *)"leave",
leave_sw,
CA_LOCATION,
0,
CS_NO_ARGS|CS_INTERP,
NULL,
NULL,
NULL,
{do_leave}},
{(char *)"look",
look_sw,
CA_LOCATION,
LOOK_LOOK, CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_look}},
{(char *)"page",
noeval_sw, CA_NO_SLAVE,
0,
CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_page}},
{(char *)"pose",
pose_sw,
CA_LOCATION|CA_NO_SLAVE,
SAY_POSE,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_say}},
{(char *)"reply",
noeval_sw, CA_NO_SLAVE,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_reply_page}},
{(char *)"say",
noeval_sw, CA_LOCATION|CA_NO_SLAVE,
SAY_SAY,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_say}},
{(char *)"score",
NULL,
CA_PUBLIC,
LOOK_SCORE, CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_score}},
{(char *)"slay",
NULL,
CA_WIZARD,
KILL_SLAY, CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_kill}},
{(char *)"think",
NULL,
CA_NO_SLAVE,
0,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{do_think}},
{(char *)"use",
NULL,
CA_NO_SLAVE|CA_GBL_INTERP,
0,
CS_ONE_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_use}},
{(char *)"version",
NULL,
CA_PUBLIC,
0,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{do_version}},
{(char *)"whisper",
NULL,
CA_LOCATION|CA_NO_SLAVE,
PEMIT_WHISPER, CS_TWO_ARG|CS_INTERP,
NULL,
NULL,
NULL,
{do_pemit}},
{(char *)"doing",
NULL,
CA_PUBLIC,
CMD_DOING, CS_ONE_ARG,
NULL,
NULL,
NULL,
{logged_out}},
{(char *)"quit",
NULL,
CA_PUBLIC,
CMD_QUIT,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{logged_out}},
{(char *)"logout",
NULL,
CA_PUBLIC,
CMD_LOGOUT, CS_NO_ARGS,
NULL,
NULL,
NULL,
{logged_out}},
{(char *)"who",
NULL,
CA_PUBLIC,
CMD_WHO,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{logged_out}},
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:17 PM

{(char *)"session",
NULL,
CA_PUBLIC,
CMD_SESSION,
CS_ONE_ARG,
NULL,
NULL,
NULL,
{logged_out}},
{(char *)"info",
NULL,
CA_PUBLIC,
CMD_INFO,
CS_NO_ARGS,
NULL,
NULL,
NULL,
{logged_out}},
{(char *)"outputprefix",
NULL,
CA_PUBLIC,
CMD_PREFIX, CS_ONE_ARG,
NULL,
NULL,
NULL,
{logged_out}},
{(char *)"outputsuffix",
NULL,
CA_PUBLIC,
CMD_SUFFIX, CS_ONE_ARG,
NULL,
NULL,
NULL,
{logged_out}},
{(char *)"puebloclient",
NULL,
CA_PUBLIC,
CMD_PUEBLOCLIENT,CS_ONE_ARG,
NULL,
NULL,
NULL,
{logged_out}},
{(char *)"\\",
NULL,
CA_NO_GUEST|CA_LOCATION|CF_DARK|CA_NO_SLAVE,
SAY_PREFIX|SAY_EMIT,
CS_ONE_ARG|CS_INTERP|CS_LEADIN,
NULL,
NULL,
NULL,
{do_say}},
{(char *)"#",
NULL,
CA_NO_SLAVE|CA_GBL_INTERP|CF_DARK,
0,
CS_ONE_ARG|CS_INTERP|CS_CMDARG|CS_LEADIN,
NULL,
NULL,
NULL,
{do_force_prefixed}},
{(char *)":",
NULL,
CA_LOCATION|CF_DARK|CA_NO_SLAVE,
SAY_PREFIX|SAY_POSE,
CS_ONE_ARG|CS_INTERP|CS_LEADIN,
NULL,
NULL,
NULL,
{do_say}},
{(char *)";",
NULL,
CA_LOCATION|CF_DARK|CA_NO_SLAVE,
SAY_PREFIX|SAY_POSE_NOSPC, CS_ONE_ARG|CS_INTERP|CS_LEADIN,
NULL,
NULL,
NULL,
{do_say}},
{(char *)"\"",
NULL,
CA_LOCATION|CF_DARK|CA_NO_SLAVE,
SAY_PREFIX|SAY_SAY, CS_ONE_ARG|CS_INTERP|CS_LEADIN,
NULL,
NULL,
NULL,
{do_say}},
{(char *)"&",
NULL,
CA_NO_GUEST|CA_NO_SLAVE|CF_DARK,
0,
CS_TWO_ARG|CS_LEADIN,
NULL,
NULL,
NULL,
{do_setvattr}},
{(char *)NULL,
NULL,
0,
0,
0,
NULL,
NULL,
NULL,
{NULL}}};
/* --------------------------------------------------------------------------* Command, function, etc. access name table.
*/
NAMETAB access_nametab[] =
{
{(char *)"admin", 2, CA_WIZARD, CA_ADMIN},
{(char *)"builder", 6, CA_WIZARD, CA_BUILDER},
{(char *)"dark", 4, CA_GOD, CF_DARK},
{(char *)"disabled", 4, CA_GOD, CA_DISABLED},
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{NULL,

Saturday, June 16, 2012 11:17 PM

*)"global_build", 8, CA_PUBLIC, CA_GBL_BUILD},


*)"global_interp", 8, CA_PUBLIC, CA_GBL_INTERP},
*)"god", 2, CA_GOD, CA_GOD},
*)"head", 2, CA_WIZARD, CA_HEAD},
*)"immortal", 3, CA_WIZARD, CA_IMMORTAL},
*)"marker0", 7, CA_WIZARD, CA_MARKER0},
*)"marker1", 7, CA_WIZARD, CA_MARKER1},
*)"marker2", 7, CA_WIZARD, CA_MARKER2},
*)"marker3", 7, CA_WIZARD, CA_MARKER3},
*)"marker4", 7, CA_WIZARD, CA_MARKER4},
*)"marker5", 7, CA_WIZARD, CA_MARKER5},
*)"marker6", 7, CA_WIZARD, CA_MARKER6},
*)"marker7", 7, CA_WIZARD, CA_MARKER7},
*)"marker8", 7, CA_WIZARD, CA_MARKER8},
*)"marker9", 7, CA_WIZARD, CA_MARKER9},
*)"need_location", 6, CA_PUBLIC, CA_LOCATION},
*)"need_contents", 6, CA_PUBLIC, CA_CONTENTS},
*)"need_player", 6, CA_PUBLIC, CA_PLAYER},
*)"no_haven", 4, CA_PUBLIC, CA_NO_HAVEN},
*)"no_robot", 4, CA_WIZARD, CA_NO_ROBOT},
*)"no_slave", 5, CA_PUBLIC, CA_NO_SLAVE},
*)"no_suspect", 5, CA_WIZARD, CA_NO_SUSPECT},
*)"no_guest", 5, CA_WIZARD, CA_NO_GUEST},
*)"sql", 2, CA_GOD, CA_SQL_OK},
*)"staff", 3, CA_WIZARD, CA_STAFF},
*)"static", 3, CA_GOD, CA_STATIC},
*)"wizard", 3, CA_WIZARD, CA_WIZARD},
0, 0, 0}};

/* --------------------------------------------------------------------------* Attribute access name tables.


*/
NAMETAB attraccess_nametab[] = {
{(char *)"const",
2, CA_PUBLIC, AF_CONST},
{(char *)"dark",
2, CA_WIZARD, AF_DARK},
{(char *)"default",
3, CA_WIZARD, AF_DEFAULT},
{(char *)"deleted",
3, CA_WIZARD, AF_DELETED},
{(char *)"god",
1, CA_PUBLIC, AF_GOD},
{(char *)"hidden",
1, CA_WIZARD, AF_MDARK},
{(char *)"ignore",
2, CA_WIZARD, AF_NOCMD},
{(char *)"internal",
2, CA_WIZARD, AF_INTERNAL},
{(char *)"is_lock",
4, CA_PUBLIC, AF_IS_LOCK},
{(char *)"locked",
1, CA_PUBLIC, AF_LOCK},
{(char *)"no_clone",
5, CA_PUBLIC, AF_NOCLONE},
{(char *)"no_command",
5, CA_PUBLIC, AF_NOPROG},
{(char *)"no_inherit",
4, CA_PUBLIC, AF_PRIVATE},
{(char *)"visual",
1, CA_PUBLIC, AF_VISUAL},
{(char *)"wizard",
1, CA_PUBLIC, AF_WIZARD},
{ NULL,
0, 0,
0}};
NAMETAB indiv_attraccess_nametab[] = {
{(char *)"case",
1, CA_PUBLIC,

AF_CASE},
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cmdtabs.h

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918

{(char *)"hidden",
{(char *)"wizard",
{(char *)"no_command",
{(char *)"no_inherit",
{(char *)"no_name",
{(char *)"no_parse",
{(char *)"now",
{(char *)"regexp",
{(char *)"rmatch",
{(char *)"structure",
{(char *)"trace",
{(char *)"visual",
{(char *)"html",
{ NULL,
0,

1,
1,
4,
3,
2,
2,
1,
1,
2,
0,

Saturday, June 16, 2012 11:17 PM

CA_WIZARD, AF_MDARK},
CA_WIZARD, AF_WIZARD},
4, CA_PUBLIC, AF_NOPROG},
4, CA_PUBLIC, AF_PRIVATE},
CA_PUBLIC, AF_NONAME},
4, CA_PUBLIC, AF_NOPARSE},
CA_PUBLIC, AF_NOW},
CA_PUBLIC, AF_REGEXP},
CA_PUBLIC, AF_RMATCH},
1, CA_GOD,
AF_STRUCTURE},
CA_PUBLIC, AF_TRACE},
CA_PUBLIC, AF_VISUAL},
CA_PUBLIC, AF_HTML},
0}};

/* *INDENT-ON* */

-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:51 PM

/* command.c - command parser and support routines */


/* $Id: command.c,v 1.210 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include
#include
#include
#include
#include
#include

"help.h"
/*
"command.h"
"functions.h"
"match.h" /*
"attrs.h" /*
"powers.h" /*
"vattr.h" /*
"db_sql.h" /*
"pcre.h"
/*

required by code */
/* required by code */
/* required by code */
required by code */
required by code */
required by code */
required by code */
required by code */
required by code */

FDECL(list_cf_access, (dbref));
FDECL(list_cf_read_access, (dbref));
FDECL(list_siteinfo, (dbref));
FDECL(logged_out, (dbref, dbref, int, char *));
FDECL(list_functable, (dbref));
FDECL(list_funcaccess, (dbref));
FDECL(list_bufstats, (dbref));
FDECL(list_buftrace, (dbref));
FDECL(list_cached_objs, (dbref));
FDECL(list_cached_attrs, (dbref));
FDECL(list_rawmemory, (dbref));

extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

void
void
void
void
void
void
void
void
void
void
void

extern
extern
extern
extern
extern

int FDECL(atr_match, (dbref, dbref, char, char *, char *, int));


int FDECL(list_check, (dbref, dbref, char, char *, char *, int, int *));
void FDECL(do_enter_internal, (dbref, dbref, int));
int FDECL(regexp_match, (char *, char *, int, char **, int));
void FDECL(register_prefix_cmds, (const char *));

#define CACHING "attribute"


#define NOGO_MESSAGE "You can't go that way."
/* Take care of all the assorted problems associated with getrusage(). */
#ifdef hpux
#define HAVE_GETRUSAGE 1
#include <sys/syscall.h>
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

#define getrusage(x,p)
#endif

Saturday, June 16, 2012 11:51 PM

syscall(SYS_GETRUSAGE,x,p)

#ifdef _SEQUENT_
#define HAVE_GET_PROCESS_STATS 1
#include <sys/procstats.h>
#endif
/* This must be the LAST thing we include. */
#include "cmdtabs.h"

/* required by code */

/* --------------------------------------------------------------------------* Hook macros.


*
* We never want to call hooks in the case of @addcommand'd commands
* (both for efficiency reasons and the fact that we might NOT match an
* @addcommand even if we've been told there is one), but we leave this
* to the hook-adder to prevent.
*/
#define CALL_PRE_HOOK(x,a,na) \
if (((x)->pre_hook != NULL) && !((x)->callseq & CS_ADDED)) { \
process_hook((x)->pre_hook, (x)->callseq & CS_PRESERVE|CS_PRIVATE, \
player, cause, (a), (na)); \
}
#define CALL_POST_HOOK(x,a,na) \
if (((x)->post_hook != NULL) && !((x)->callseq & CS_ADDED)) { \
process_hook((x)->post_hook, (x)->callseq & CS_PRESERVE|CS_PRIVATE, \
player, cause, (a), (na)); \
}
CMDENT *prefix_cmds[256];
CMDENT *goto_cmdp, *enter_cmdp, *leave_cmdp, *internalgoto_cmdp;
/* --------------------------------------------------------------------------* Main body of code.
*/
void NDECL(init_cmdtab)
{
CMDENT *cp;
ATTR *ap;
char *p, *q;
char *cbuff;
int i;
hashinit(&mudstate.command_htab, 250 * HASH_FACTOR, HT_STR);
/* Load attribute-setting commands */

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

cbuff = alloc_sbuf("init_cmdtab");
for (ap = attr; ap->name; ap++) {
if ((ap->flags & AF_NOCMD) == 0) {
p = cbuff;
*p++ = '@';
for (q = (char *)ap->name; *q; p++, q++)
*p = tolower(*q);
*p = '\0';
cp = (CMDENT *) XMALLOC(sizeof(CMDENT), "init_cmdtab");
cp->cmdname = XSTRDUP(cbuff, "init_cmdtab.cmdname");
cp->perms = CA_NO_GUEST | CA_NO_SLAVE;
cp->switches = NULL;
if (ap->flags & (AF_WIZARD | AF_MDARK)) {
cp->perms |= CA_WIZARD;
}
cp->extra = ap->number;
cp->callseq = CS_TWO_ARG;
cp->pre_hook = NULL;
cp->post_hook = NULL;
cp->userperms = NULL;
cp->info.handler = do_setattr;
if (hashadd(cp->cmdname, (int *)cp, &mudstate.command_htab, 0)) {
XFREE(cp->cmdname, "init_cmdtab.2");
XFREE(cp, "init_cmdtab.3");
} else {
/* also add the __ alias form */
hashadd(tprintf("__%s", cp->cmdname), (int *)cp, &mudstate.command_htab,
HASH_ALIAS);
}
}
}
free_sbuf(cbuff);

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

Saturday, June 16, 2012 11:51 PM

/* Load the builtin commands, plus __ aliases */


for (cp = command_table; cp->cmdname; cp++) {
hashadd(cp->cmdname, (int *)cp, &mudstate.command_htab, 0);
hashadd(tprintf("__%s", cp->cmdname), (int *)cp, &mudstate.command_htab,
HASH_ALIAS);
}
/* Set the builtin prefix commands */
for (i = 0; i < 256; i++)
prefix_cmds[i] = NULL;
register_prefix_cmds("\":;\\#&");
/*

":;\#&

*/

goto_cmdp = (CMDENT *) hashfind("goto", &mudstate.command_htab);


enter_cmdp = (CMDENT *) hashfind("enter", &mudstate.command_htab);
leave_cmdp = (CMDENT *) hashfind("leave", &mudstate.command_htab);
internalgoto_cmdp = (CMDENT *) hashfind("internalgoto", &mudstate.command_htab);

void reset_prefix_cmds()
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

Saturday, June 16, 2012 11:51 PM

int i;
char cn[2] = "x";
for (i = 0; i < 256; i++) {
if (prefix_cmds[i]) {
cn[0] = i;
prefix_cmds[i] = (CMDENT *) hashfind(cn, &mudstate.command_htab);
}
}

/* --------------------------------------------------------------------------* check_access: Check if player has access to function.


*
Note that the calling function may also give permission
*
denied messages on failure.
*/
int check_access(player, mask)
dbref player;
int mask;
{
int mval, nval;
/* Check if we have permission to execute */
if (mask & (CA_DISABLED | CA_STATIC))
return 0;
if (God(player) || mudstate.initializing)
return 1;
/* Check for bits that we have to have. Since we know that
* we're not God at this point, if it is God-only, it fails.
* (God in combination with other stuff is implicitly checked,
* since we return false if we don't find the other bits.)
*/
if ((mval = mask & (CA_ISPRIV_MASK | CA_MARKER_MASK)) == CA_GOD)
return 0;
if (mval) {
mval = mask & CA_ISPRIV_MASK;
nval = mask & CA_MARKER_MASK;
if (mval && !nval) {
if (!(((mask & CA_WIZARD) && Wizard(player)) ||
((mask & CA_ADMIN) && WizRoy(player)) ||
((mask & CA_BUILDER) && Builder(player)) ||
((mask & CA_STAFF) && Staff(player)) ||
((mask & CA_HEAD) && Head(player)) ||
((mask & CA_IMMORTAL) && Immortal(player)) ||
((mask & CA_SQL_OK) && Can_Use_SQL(player))))
return 0;
} else if (!mval && nval) {
if (!(((mask & CA_MARKER0) && H_Marker0(player)) ||
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
return 0;
} else {
if (!(((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
((mask &
return 0;
}

CA_MARKER1)
CA_MARKER2)
CA_MARKER3)
CA_MARKER4)
CA_MARKER5)
CA_MARKER6)
CA_MARKER7)
CA_MARKER8)
CA_MARKER9)

&&
&&
&&
&&
&&
&&
&&
&&
&&

Saturday, June 16, 2012 11:51 PM

H_Marker1(player)) ||
H_Marker2(player)) ||
H_Marker3(player)) ||
H_Marker4(player)) ||
H_Marker5(player)) ||
H_Marker6(player)) ||
H_Marker7(player)) ||
H_Marker8(player)) ||
H_Marker9(player))))

CA_WIZARD) && Wizard(player)) ||


CA_ADMIN) && WizRoy(player)) ||
CA_BUILDER) && Builder(player)) ||
CA_STAFF) && Staff(player)) ||
CA_HEAD) && Head(player)) ||
CA_IMMORTAL) && Immortal(player)) ||
CA_SQL_OK) && Can_Use_SQL(player)) ||
CA_MARKER0) && H_Marker0(player)) ||
CA_MARKER1) && H_Marker1(player)) ||
CA_MARKER2) && H_Marker2(player)) ||
CA_MARKER3) && H_Marker3(player)) ||
CA_MARKER4) && H_Marker4(player)) ||
CA_MARKER5) && H_Marker5(player)) ||
CA_MARKER6) && H_Marker6(player)) ||
CA_MARKER7) && H_Marker7(player)) ||
CA_MARKER8) && H_Marker8(player)) ||
CA_MARKER9) && H_Marker9(player))))

/* Check the things that we can't be. */


if (((mask & CA_ISNOT_MASK) && !Wizard(player)) &&
(((mask & CA_NO_HAVEN) && Player_haven(player)) ||
((mask & CA_NO_ROBOT) && Robot(player)) ||
((mask & CA_NO_SLAVE) && Slave(player)) ||
((mask & CA_NO_SUSPECT) && Suspect(player)) ||
((mask & CA_NO_GUEST) && Guest(player)))) {
return 0;
}
}

return 1;

/* --------------------------------------------------------------------------* check_mod_access: Go through sequence of module call-outs, treating


* all of them like permission checks.
*/
int check_mod_access(player, xperms)
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

Saturday, June 16, 2012 11:51 PM

dbref player;
EXTFUNCS *xperms;
int i;
for (i = 0; i < xperms->num_funcs; i++) {
if (!xperms->ext_funcs[i])
continue;
if (!((xperms->ext_funcs[i]->handler)(player)))
return 0;
}
return 1;

/* --------------------------------------------------------------------------* check_userdef_access: Check if user has access to command with user-def'd


* permissions.
*/
int check_userdef_access(player, hookp, cargs, ncargs)
dbref player;
HOOKENT *hookp;
char *cargs[];
int ncargs;
{
char *buf;
char *bp, *tstr, *str;
dbref aowner;
int result, aflags, alen;
GDATA *preserve;
/* We have user-defined command permissions. Go evaluate the
* obj/attr pair that we've been given. If that result is
* nonexistent, we consider it a failure. We use boolean
* truth here.
*
* Note that unlike before and after hooks, we always preserve
* the registers. (When you get right down to it, this thing isn't
* really a hook. It's just convenient to re-use the same code
* that we use with hooks.)
*/
tstr = atr_get(hookp->thing, hookp->atr, &aowner, &aflags, &alen);
if (!tstr)
return 0;
if (!*tstr) {
free_lbuf(tstr);
return 0;
}
str = tstr;
preserve = save_global_regs("check_userdef_access");

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

Saturday, June 16, 2012 11:51 PM

bp = buf = alloc_lbuf("check_userdef_access");
exec(buf, &bp, hookp->thing, player, player,
EV_EVAL | EV_FCHECK | EV_TOP,
&str, cargs, ncargs);
restore_global_regs("check_userdef_access", preserve);
result = xlate(buf);
free_lbuf(buf);
free_lbuf(tstr);
}

return result;

/* --------------------------------------------------------------------------* process_hook: Evaluate a hook function.


*/
static void process_hook(hp, save_globs, player, cause, cargs, ncargs)
HOOKENT *hp;
int save_globs;
dbref player, cause;
char *cargs[];
int ncargs;
{
char *buf, *bp;
char *tstr, *str;
dbref aowner;
int aflags, alen;
GDATA *preserve;
/* We know we have a non-null hook. We want to evaluate the obj/attr
* pair of that hook. We consider the enactor to be the player who
* executed the command that caused this hook to be called.
*/
tstr = atr_get(hp->thing, hp->atr, &aowner, &aflags, &alen);
str = tstr;
if (save_globs & CS_PRESERVE) {
preserve = save_global_regs("process_hook");
} else if (save_globs & CS_PRIVATE) {
preserve = mudstate.rdata;
mudstate.rdata = NULL;
}
buf = bp = alloc_lbuf("process_hook");
exec(buf, &bp, hp->thing, player, player, EV_EVAL | EV_FCHECK | EV_TOP,
&str, cargs, ncargs);
free_lbuf(buf);
if (save_globs & CS_PRESERVE) {
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

Saturday, June 16, 2012 11:51 PM

restore_global_regs("process_hook", preserve);
} else if (save_globs & CS_PRIVATE) {
Free_RegData(mudstate.rdata);
mudstate.rdata = preserve;
}
}

free_lbuf(tstr);

void call_move_hook(player, cause, state)


dbref player, cause;
int state;
{
if (internalgoto_cmdp) {
if (!state) {
/* before move */
CALL_PRE_HOOK(internalgoto_cmdp, NULL, 0);
} else {
/* after move */
CALL_POST_HOOK(internalgoto_cmdp, NULL, 0);
}
}
}
/* --------------------------------------------------------------------------* process_cmdent: Perform indicated command with passed args.
*/
void process_cmdent(cmdp, switchp, player, cause, interactive, arg,
unp_command, cargs, ncargs)
CMDENT *cmdp;
char *switchp, *arg, *unp_command, *cargs[];
dbref player, cause;
int interactive, ncargs;
{
char *buf1, *buf2, tchar, *bp, *str, *buff, *s, *j, *new;
char *args[MAX_ARG], *aargs[NUM_ENV_VARS];
int nargs, i, interp, key, xkey, aflags, alen;
int hasswitch = 0;
int cmd_matches = 0;
dbref aowner;
ADDENT *add;
GDATA *preserve;
/* Perform object type checks. */
if (Invalid_Objtype(player)) {
notify(player, "Command incompatible with invoker type." );
return;
}
/* Check if we have permission to execute the command */
if (!Check_Cmd_Access(player, cmdp, cargs, ncargs)) {
notify(player, NOPERM_MESSAGE);
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

Saturday, June 16, 2012 11:51 PM

return;

/* Check global flags */


if ((!Builder(player)) && Protect(CA_GBL_BUILD) &&
!(mudconf.control_flags & CF_BUILD)) {
notify(player, "Sorry, building is not allowed now." );
return;
}
if (Protect(CA_GBL_INTERP) && !(mudconf.control_flags & CF_INTERP)) {
notify(player,
"Sorry, queueing and triggering are not allowed now." );
return;
}
key = cmdp->extra & ~SW_MULTIPLE;
if (key & SW_GOT_UNIQUE) {
i = 1;
key = key & ~SW_GOT_UNIQUE;
} else {
i = 0;
}
/* Check command switches. Note that there may be more than one,
* and that we OR all of them together along with the extra value
* from the command table to produce the key value in the handler call.
*/
if (switchp && cmdp->switches) {
do {
buf1 = strchr(switchp, '/');
if (buf1)
*buf1++ = '\0';
xkey = search_nametab(player, cmdp->switches,
switchp);
if (xkey == -1) {
notify(player,
tprintf("Unrecognized switch '%s' for command '%s'." ,
switchp, cmdp->cmdname));
return;
} else if (xkey == -2) {
notify(player, NOPERM_MESSAGE);
return;
} else if (!(xkey & SW_MULTIPLE)) {
if (i == 1) {
notify(player,
"Illegal combination of switches." );
return;
}
i = 1;
} else {
xkey &= ~SW_MULTIPLE;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

Saturday, June 16, 2012 11:51 PM

}
key |= xkey;
switchp = buf1;
hasswitch = 1;
} while (buf1);
} else if (switchp && !(cmdp->callseq & CS_ADDED)) {
notify(player,
tprintf("Command %s does not take switches." ,
cmdp->cmdname));
return;
}
/* At this point we're guaranteed we're going to execute something.
* Let's check to see if we have a pre-command hook.
*/
CALL_PRE_HOOK(cmdp, cargs, ncargs);
/* If the command normally has interpreted args, but the user
* specified, /noeval, just do EV_STRIP.
*
* If the command is interpreted, or we're interactive (and
* the command isn't specified CS_NOINTERP), eval the args.
*
* The others are obvious.
*/
if ((cmdp->callseq & CS_INTERP) && (key & SW_NOEVAL)) {
interp = EV_STRIP;
key &= ~SW_NOEVAL; /* Remove SW_NOEVAL from 'key' */
}
else if ((cmdp->callseq & CS_INTERP) ||
!(interactive || (cmdp->callseq & CS_NOINTERP)))
interp = EV_EVAL | EV_STRIP;
else if (cmdp->callseq & CS_STRIP)
interp = EV_STRIP;
else if (cmdp->callseq & CS_STRIP_AROUND)
interp = EV_STRIP_AROUND;
else
interp = 0;
switch (cmdp->callseq & CS_NARG_MASK) {
case CS_NO_ARGS:
/* <cmd>
(no args) */
(*(cmdp->info.handler)) (player, cause, key);
break;
case CS_ONE_ARG:
/* <cmd> <arg> */
/* If an unparsed command, just give it to the handler */
if (cmdp->callseq & CS_UNPARSE) {
(*(cmdp->info.handler)) (player, unp_command);
break;
}
/* Interpret if necessary, but not twice for CS_ADDED */
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

Saturday, June 16, 2012 11:51 PM

if ((interp & EV_EVAL) && !(cmdp->callseq & CS_ADDED)) {


buf1 = bp = alloc_lbuf("process_cmdent");
str = arg;
exec(buf1, &bp, player, cause, cause,
interp | EV_FCHECK | EV_TOP,
&str, cargs, ncargs);
} else
buf1 = parse_to(&arg, '\0', interp | EV_TOP);
/* Call the correct handler */
if (cmdp->callseq & CS_CMDARG) {
(*(cmdp->info.handler)) (player, cause, key, buf1,
cargs, ncargs);
} else {
if (cmdp->callseq & CS_ADDED) {
preserve = save_global_regs("process_cmdent_added");
/* Construct the matching buffer. */
/* In the case of a single-letter prefix, we want
* to just skip past that first letter. Otherwise
* we want to go past the first word.
*/
if (!(cmdp->callseq & CS_LEADIN)) {
for (j = unp_command; *j && (*j != ' '); j++) ;
} else {
j = unp_command; j++;
}
new = alloc_lbuf("process_cmdent.soft");
bp = new;
if (!*j) {
/* No args */
if (!(cmdp->callseq & CS_LEADIN)) {
safe_str(cmdp->cmdname, new, &bp);
} else {
safe_str(unp_command, new, &bp);
}
if (switchp) {
safe_chr('/', new, &bp);
safe_str(switchp, new, &bp);
}
*bp = '\0';
} else {
if (!(cmdp->callseq & CS_LEADIN))
j++;
safe_str(cmdp->cmdname, new, &bp);
if (switchp) {
safe_chr('/', new, &bp);
safe_str(switchp, new, &bp);
}
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

Saturday, June 16, 2012 11:51 PM

if (!(cmdp->callseq & CS_LEADIN))


safe_chr(' ', new, &bp);
safe_str(j, new, &bp);
*bp = '\0';

/* Now search against the attributes, unless we


* can't pass the uselock.
*/
for (add = (ADDENT *)cmdp->info.added;
add != NULL; add = add->next) {
buff = atr_get(add->thing, add->atr,
&aowner, &aflags, &alen);
/* Skip the '$' character, and the next */
for (s = buff + 2;
*s && ((*s != ':') || (*(s - 1) == '\\'));
s++)
;
if (!*s) {
free_lbuf(buff);
break;
}
*s++ = '\0';
if (((!(aflags & AF_REGEXP) &&
wild(buff + 1, new, aargs,
NUM_ENV_VARS)) ||
((aflags & AF_REGEXP) &&
regexp_match(buff + 1, new,
((aflags & AF_CASE) ?
0 : PCRE_CASELESS),
aargs, NUM_ENV_VARS))) &&
(!mudconf.addcmd_obey_uselocks ||
could_doit(player, add->thing, A_LUSE))) {
process_cmdline(((!(cmdp->callseq & CS_ACTOR)
|| God(player)) ?
add->thing :
player),
player, s, aargs,
NUM_ENV_VARS, NULL);
for (i = 0; i < NUM_ENV_VARS; i++) {
if (aargs[i])
free_lbuf(aargs[i]);
}
cmd_matches++;
}
free_lbuf(buff);
if (cmd_matches && mudconf.addcmd_obey_stop &&
Stop_Match(add->thing)) {
break;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687

Saturday, June 16, 2012 11:51 PM

if (!cmd_matches && !mudconf.addcmd_match_blindly) {


/* The command the player typed didn't match
* any of the wildcard patterns we have for
* that addcommand. We should raise an error.
* We DO NOT go back into trying to match
* other stuff -- this is a 'Huh?' situation.
*/
notify(player, mudconf.huh_msg);
STARTLOG(LOG_BADCOMMANDS, "CMD", "BAD")
log_name_and_loc(player);
log_printf(" entered: %s", new);
ENDLOG
}
free_lbuf(new);

restore_global_regs("process_cmdent", preserve);
} else
(*(cmdp->info.handler)) (player, cause, key, buf1);

/* Free the buffer if one was allocated */


if ((interp & EV_EVAL) && !(cmdp->callseq & CS_ADDED))
free_lbuf(buf1);
break;
case CS_TWO_ARG:

/* <cmd> <arg1> = <arg2> */

/* Interpret ARG1 */
buf2 = parse_to(&arg, '=', EV_STRIP_TS);
/* Handle when no '=' was specified */
if (!arg || (arg && !*arg)) {
arg = &tchar;
*arg = '\0';
}
buf1 = bp = alloc_lbuf("process_cmdent.2");
str = buf2;
exec(buf1, &bp, player, cause, cause,
EV_STRIP | EV_FCHECK | EV_EVAL | EV_TOP,
&str, cargs, ncargs);
if (cmdp->callseq & CS_ARGV) {
/* Arg2 is ARGV style.

Go get the args */

parse_arglist(player, cause, cause, arg, '\0',


-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

Saturday, June 16, 2012 11:51 PM

interp | EV_STRIP_LS | EV_STRIP_TS,


args, MAX_ARG, cargs, ncargs);
for (nargs = 0; (nargs < MAX_ARG) && args[nargs]; nargs++) ;
/* Call the correct command handler */
if (cmdp->callseq & CS_CMDARG) {
(*(cmdp->info.handler)) (player, cause, key,
buf1, args, nargs, cargs, ncargs);
} else {
(*(cmdp->info.handler)) (player, cause, key,
buf1, args, nargs);
}
/* Free the argument buffers */
for (i = 0; i <= nargs; i++)
if (args[i])
free_lbuf(args[i]);
} else {
/* Arg2 is normal style.

Interpret if needed */

if (interp & EV_EVAL) {


buf2 = bp = alloc_lbuf("process_cmdent.3");
str = arg;
exec(buf2, &bp, player, cause, cause,
interp | EV_FCHECK | EV_TOP,
&str, cargs, ncargs);
} else if (cmdp->callseq & CS_UNPARSE) {
buf2 = parse_to(&arg, '\0',
interp | EV_TOP | EV_NO_COMPRESS);
} else {
buf2 = parse_to(&arg, '\0',
interp | EV_STRIP_LS | EV_STRIP_TS | EV_TOP);
}
/* Call the correct command handler */
if (cmdp->callseq & CS_CMDARG) {
(*(cmdp->info.handler)) (player, cause, key,
buf1, buf2, cargs, ncargs);
} else {
(*(cmdp->info.handler)) (player, cause, key,
buf1, buf2);
}
/* Free the buffer, if needed */
if (interp & EV_EVAL)
free_lbuf(buf2);
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

Saturday, June 16, 2012 11:51 PM

}
/* Free the buffer obtained by evaluating Arg1 */

free_lbuf(buf1);
break;

/* And now we go do the posthook, if we have one. */


CALL_POST_HOOK(cmdp, cargs, ncargs);
}

return;

/* --------------------------------------------------------------------------* process_command: Execute a command.


*/
char *process_command(player, cause, interactive, command, args, nargs)
dbref player, cause;
int interactive, nargs;
char *command, *args[];
{
static char preserve_cmd[LBUF_SIZE];
char *p, *q, *arg, *lcbuf, *slashp, *cmdsave, *bp, *str, *evcmd;
char *gbuf, *gc;
int succ, aflags, alen, i, got_stop, pcount, retval = 0;
dbref exit, aowner, parent;
CMDENT *cmdp;
NUMBERTAB *np;
if (mudstate.cmd_invk_ctr == mudconf.cmd_invk_lim)
return command;
mudstate.cmd_invk_ctr++;
/* Robustify player */
cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< process_command >";
if (!command) {
fprintf(mainlog_fp, "ABORT! command.c, null command in process_command().\n" );
abort();
}
if (!Good_obj(player)) {
STARTLOG(LOG_BUGS, "CMD", "PLYR")
log_printf("Bad player in process_command: %d" ,
player);
ENDLOG
mudstate.debug_cmd = cmdsave;
return command;
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

Saturday, June 16, 2012 11:51 PM

}
/* Make sure player isn't going or halted */
if (Going(player) ||
(Halted(player) &&
!((Typeof(player) == TYPE_PLAYER) && interactive))) {
notify(Owner(player),
tprintf("Attempt to execute command by halted object #%d" ,
player));
mudstate.debug_cmd = cmdsave;
return command;
}
if (Suspect(player)) {
STARTLOG(LOG_SUSPECTCMDS,
log_name_and_loc(player);
log_printf(" entered:
ENDLOG
} else {
STARTLOG(LOG_ALLCOMMANDS,
log_name_and_loc(player);
log_printf(" entered:
ENDLOG
}

"CMD", "SUSP")
%s", command);
"CMD", "ALL")
%s", command);

s_Accessed(player);
/* Reset recursion limits. Baseline the CPU counter. */
mudstate.func_nest_lev = 0;
mudstate.func_invk_ctr = 0;
mudstate.ntfy_nest_lev = 0;
mudstate.lock_nest_lev = 0;
if (mudconf.func_cpu_lim > 0)
mudstate.cputime_base = clock();
if (Verbose(player)) {
if (H_Redirect(player)) {
np = (NUMBERTAB *) nhashfind(player, &mudstate.redir_htab);
if (np) {
notify(np->num,
tprintf("%s] %s", Name(player), command));
} else {
/* We have no pointer, we should have no flag. */
s_Flags3(player, Flags3(player) & ~HAS_REDIRECT);
}
} else {
notify(Owner(player), tprintf("%s] %s", Name(player),
command));
}
}
/*
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899

Saturday, June 16, 2012 11:51 PM

* NOTE THAT THIS WILL BREAK IF "GOD" IS NOT A DBREF.


*/
if (mudconf.control_flags & CF_GODMONITOR) {
raw_notify(GOD, tprintf("%s(#%d)%c %s", Name(player), player,
(interactive) ? '|' : ':', command));
}
/* Eat leading whitespace, and space-compress if configured */
while (*command && isspace(*command))
command++;
strcpy(preserve_cmd, command);
mudstate.debug_cmd = command;
mudstate.curr_cmd = preserve_cmd;
if (mudconf.space_compress) {
p = q = command;
while (*p) {
while (*p && !isspace(*p))
*q++ = *p++;
while (*p && isspace(*p))
p++;
if (*p)
*q++ = ' ';
}
*q = '\0';
}
/* Allow modules to intercept command strings. */
CALL_SOME_MODULES(retval, process_command,
(player, cause, interactive, command, args, nargs));
if (retval > 0) {
mudstate.debug_cmd = cmdsave;
return preserve_cmd;
}
/* Now comes the fun stuff. First check for single-letter leadins.
* We check these before checking HOME because
* they are among the most frequently executed commands,
* and they can never be the HOME command.
*/
i = command[0] & 0xff;
if ((prefix_cmds[i] != NULL) && command[0]) {
process_cmdent(prefix_cmds[i], NULL, player, cause,
interactive, command, command, args, nargs);
mudstate.debug_cmd = cmdsave;
return preserve_cmd;
}
/* Check for the HOME command. You cannot do hooks on this because
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

Saturday, June 16, 2012 11:51 PM

* home is not part of the traditional command table.


*/
if (Has_location(player) && string_compare(command, "home") == 0) {
if (((Fixed(player)) || (Fixed(Owner(player)))) &&
!(WizRoy(player))) {
notify(player, mudconf.fixed_home_msg);
mudstate.debug_cmd = cmdsave;
return preserve_cmd;
}
do_move(player, cause, 0, "home");
mudstate.debug_cmd = cmdsave;
return preserve_cmd;
}
/* Only check for exits if we may use the goto command */
if (Check_Cmd_Access(player, goto_cmdp, args, nargs)) {
/* Check for an exit name */
init_match_check_keys(player, command, TYPE_EXIT);
match_exit_with_parents();
exit = last_match_result();
if (exit != NOTHING) {
if (mudconf.exit_calls_move) {
/* Exits literally call the 'move' command. Note
* that, later, when we go to matching master-room
* and other global-ish exits, that we also need
* to have move_match_more set to 'yes', or
* we'll match here only to encounter dead silence
* when we try to find the exit inside the move
* routine. We also need to directly find what
* the pointer for the move (goto) command is,
* since we could have @addcommand'd it (and
* probably did, if this conf option is on).
* Finally, we've got to make this look like
* we really did type 'goto <exit>', or the
* @addcommand will just skip over the string.
*/
cmdp = (CMDENT *) hashfind("goto",
&mudstate.command_htab);
if (cmdp) { /* just in case */
gbuf = alloc_lbuf("process_command.goto");
gc = gbuf;
safe_str(cmdp->cmdname, gbuf, &gc);
safe_chr(' ', gbuf, &gc);
safe_str(command, gbuf, &gc);
*gc = '\0';
process_cmdent(cmdp, NULL, player, cause,
interactive, command, gbuf,
args, nargs);
free_lbuf(gbuf);
}
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

Saturday, June 16, 2012 11:51 PM

} else {
/* Execute the pre-hook for the goto command */
CALL_PRE_HOOK(goto_cmdp, args, nargs);
move_exit(player, exit, 0, NOGO_MESSAGE, 0);
/* Execute the post-hook for the goto command */
CALL_POST_HOOK(goto_cmdp, args, nargs);
}
mudstate.debug_cmd = cmdsave;
return preserve_cmd;

/* Check for an exit in the master room */


init_match_check_keys(player, command, TYPE_EXIT);
match_master_exit();
exit = last_match_result();
if (exit != NOTHING) {
if (mudconf.exit_calls_move) {
cmdp = (CMDENT *) hashfind("goto",
&mudstate.command_htab);
if (cmdp) {
gbuf = alloc_lbuf("process_command.goto");
gc = gbuf;
safe_str(cmdp->cmdname, gbuf, &gc);
safe_chr(' ', gbuf, &gc);
safe_str(command, gbuf, &gc);
*gc = '\0';
process_cmdent(cmdp, NULL, player, cause,
interactive, command, gbuf,
args, nargs);
free_lbuf(gbuf);
}
} else {
CALL_PRE_HOOK(goto_cmdp, args, nargs);
move_exit(player, exit, 1, NOGO_MESSAGE, 0);
CALL_POST_HOOK(goto_cmdp, args, nargs);
}
mudstate.debug_cmd = cmdsave;
return preserve_cmd;
}

}
/* Set up a lowercase command and an arg pointer for the hashed
* command check. Since some types of argument
* processing destroy the arguments, make a copy so that
* we keep the original command line intact. Store the
* edible copy in lcbuf after the lowercased command.
*/
/* Removed copy of the rest of the command, since it's ok to allow
* it to be trashed. -dcm
*/
lcbuf = alloc_lbuf("process_commands.lcbuf");
for (p = command, q = lcbuf; *p && !isspace(*p); p++, q++)
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:51 PM

*q = tolower(*p);
/* Make lowercase command */
*q++ = '\0';
/* Terminate command */
while (*p && isspace(*p))
p++;
/* Skip spaces before arg */
arg = p;
/* Remember where arg starts */
/* Strip off any command switches and save them */
slashp = strchr(lcbuf, '/');
if (slashp)
*slashp++ = '\0';
/* Check for a builtin command (or an alias of a builtin command) */
cmdp = (CMDENT *) hashfind(lcbuf, &mudstate.command_htab);
if (cmdp != NULL) {
if (mudconf.space_compress && (cmdp->callseq & CS_NOSQUISH)) {
/* We handle this specially -- there is no space compression
* involved, so we must go back to the preserved command.
*/
strcpy(command, preserve_cmd);
arg = command;
while (*arg && !isspace(*arg))
arg++;
if (*arg)
/* we stopped on the space, advance to next */
arg++;
}
process_cmdent(cmdp, slashp, player, cause, interactive, arg,
command, args, nargs);
free_lbuf(lcbuf);
mudstate.debug_cmd = cmdsave;
return preserve_cmd;
}
/* Check for enter and leave aliases, user-defined commands on the
* player, other objects where the player is, on objects in
* the player's inventory, and on the room that holds
* the player. We evaluate the command line here to allow
* chains of $-commands to work.
*/
str = evcmd = alloc_lbuf("process_command.evcmd");
StringCopy(evcmd, command);
bp = lcbuf;
exec(lcbuf, &bp, player, cause, cause,
EV_EVAL | EV_FCHECK | EV_STRIP | EV_TOP, &str, args, nargs);
free_lbuf(evcmd);
succ = 0;
/* Idea for enter/leave aliases from R'nice@TinyTIM */
if (Has_location(player) && Good_obj(Location(player))) {
/* Check for a leave alias, if we have permissions to
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

Saturday, June 16, 2012 11:51 PM

* use the 'leave' command.


*/
if (Check_Cmd_Access(player, leave_cmdp, args, nargs)) {
p = atr_pget(Location(player), A_LALIAS, &aowner, &aflags, &alen);
if (*p) {
if (matches_exit_from_list(lcbuf, p)) {
free_lbuf(lcbuf);
free_lbuf(p);
CALL_PRE_HOOK(leave_cmdp, args, nargs);
do_leave(player, player, 0);
CALL_POST_HOOK(leave_cmdp, args, nargs);
return preserve_cmd;
}
}
free_lbuf(p);
}
/* Check for enter aliases, if we have permissions to use the
* 'enter' command.
*/

if (Check_Cmd_Access(player, enter_cmdp, args, nargs)) {


DOLIST(exit, Contents(Location(player))) {
p = atr_pget(exit, A_EALIAS, &aowner, &aflags, &alen);
if (*p) {
if (matches_exit_from_list(lcbuf, p)) {
free_lbuf(lcbuf);
free_lbuf(p);
CALL_PRE_HOOK(enter_cmdp, args, nargs);
do_enter_internal(player, exit, 0);
CALL_POST_HOOK(enter_cmdp, args, nargs);
return preserve_cmd;
}
}
free_lbuf(p);
}
}

/* At each of the following stages, we check to make sure that we


* haven't hit a match on a STOP-set object.
*/
got_stop = 0;
/* Check for $-command matches on me */
if (mudconf.match_mine) {
if (((Typeof(player) != TYPE_PLAYER) ||
mudconf.match_mine_pl) &&
(atr_match(player, player, AMATCH_CMD, lcbuf, preserve_cmd, 1) > 0)) {
succ++;
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

Saturday, June 16, 2012 11:51 PM

got_stop = Stop_Match(player);

}
/* Check for $-command matches on nearby things and on my room */
if (!got_stop && Has_location(player)) {
succ += list_check(Contents(Location(player)), player,
AMATCH_CMD, lcbuf, preserve_cmd, 1, &got_stop);
if (!got_stop &&
atr_match(Location(player), player, AMATCH_CMD, lcbuf,
preserve_cmd, 1) > 0) {
succ++;
got_stop = Stop_Match(Location(player));
}

}
/* Check for $-command matches in my inventory */

if (!got_stop && Has_contents(player))


succ += list_check(Contents(player), player,
AMATCH_CMD, lcbuf, preserve_cmd, 1, &got_stop);
/* If we didn't find anything, and we're checking local masters,
* do those checks. Do it for the zone of the player's location first,
* and then, if nothing is found, on the player's personal zone.
* Walking back through the parent tree stops when a match is found.
* Also note that these matches are done in the style of the master room:
* parents of the contents of the rooms aren't checked for commands.
* We try to maintain 2.2/MUX compatibility here, putting both sets
* of checks together.
*/
if (Has_location(player) && Good_obj(Location(player))) {
/* 2.2 style location */
if (!succ && mudconf.local_masters) {
pcount = 0;
parent = Parent(Location(player));
while (!succ && !got_stop &&
Good_obj(parent) && ParentZone(parent) &&
(pcount < mudconf.parent_nest_lim)) {
if (Has_contents(parent)) {
succ += list_check(Contents(parent), player,
AMATCH_CMD, lcbuf, preserve_cmd,
mudconf.match_zone_parents,
&got_stop);
}
parent = Parent(parent);
pcount++;
}
}

-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

Saturday, June 16, 2012 11:51 PM

/* MUX style location */


if ((!succ) && mudconf.have_zones &&
(Zone(Location(player)) != NOTHING)) {
if (Typeof(Zone(Location(player))) == TYPE_ROOM) {
/* zone of player's location is a parent room */
if (Location(player) != Zone(player)) {
/* check parent room exits */
init_match_check_keys(player, command, TYPE_EXIT);
match_zone_exit();
exit = last_match_result();
if (exit != NOTHING) {
if (mudconf.exit_calls_move) {
cmdp = (CMDENT *) hashfind("goto",
&mudstate.command_htab);
if (cmdp) {
gbuf = alloc_lbuf("process_command.goto");
gc = gbuf;
safe_str(cmdp->cmdname, gbuf, &gc);
safe_chr(' ', gbuf, &gc);
safe_str(command, gbuf, &gc);
*gc = '\0';
process_cmdent(cmdp, NULL, player, cause,
interactive, command, gbuf,
args, nargs);
free_lbuf(gbuf);
}
} else {
CALL_PRE_HOOK(goto_cmdp, args, nargs);
move_exit(player, exit, 1, NOGO_MESSAGE, 0);
CALL_POST_HOOK(goto_cmdp, args, nargs);
}
mudstate.debug_cmd = cmdsave;
return preserve_cmd;
}
if (!got_stop) {
succ += list_check(Contents(Zone(Location(player))),
player, AMATCH_CMD, lcbuf,
preserve_cmd, 1, &got_stop);
}
}
/* end of parent room checks */
} else
/* try matching commands on area zone object */

if (!got_stop && !succ && mudconf.have_zones


&& (Zone(Location(player)) != NOTHING)) {
succ += atr_match(Zone(Location(player)), player,
AMATCH_CMD, lcbuf, preserve_cmd, 1);
}
/* end of matching on zone of player's location */

-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

Saturday, June 16, 2012 11:51 PM

/* 2.2 style player */


if (!succ && mudconf.local_masters) {
parent = Parent(player);
if (!Has_location(player) || !Good_obj(Location(player)) ||
((parent != Location(player)) &&
(parent != Parent(Location(player))))) {
pcount = 0;
while (!succ && !got_stop &&
Good_obj(parent) && ParentZone(parent) &&
(pcount < mudconf.parent_nest_lim)) {
if (Has_contents(parent)) {
succ += list_check(Contents(parent), player,
AMATCH_CMD, lcbuf, preserve_cmd, 0,
&got_stop);
}
parent = Parent(parent);
pcount++;
}
}
}
/* MUX style player */
/* if nothing matched with parent room/zone object, try matching
* zone commands on the player's personal zone
*/
if (!got_stop && !succ && mudconf.have_zones &&
(Zone(player) != NOTHING) &&
(!Has_location(player) || !Good_obj(Location(player)) ||
(Zone(Location(player)) != Zone(player)))) {
succ += atr_match(Zone(player), player, AMATCH_CMD, lcbuf,
preserve_cmd, 1);
}
/* If we didn't find anything, try in the master room */
if (!got_stop && !succ) {
if (Good_loc(mudconf.master_room)) {
succ += list_check(Contents(mudconf.master_room),
player, AMATCH_CMD, lcbuf,
preserve_cmd, 0, &got_stop);
if (!got_stop && atr_match(mudconf.master_room,
player, AMATCH_CMD, lcbuf, preserve_cmd, 0) > 0) {
succ++;
}
}
}
/* Allow modules to intercept, if still no match.
* This time we pass both the lower-cased evaluated buffer
* and the preserved command.
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

Saturday, June 16, 2012 11:51 PM

*/
if (!succ) {
CALL_SOME_MODULES(succ, process_no_match,
(player, cause, interactive, lcbuf, preserve_cmd,
args, nargs));
}
free_lbuf(lcbuf);
/* If we still didn't find anything, tell how to get help. */

if (!succ) {
notify(player, mudconf.huh_msg);
STARTLOG(LOG_BADCOMMANDS, "CMD", "BAD")
log_name_and_loc(player);
log_printf(" entered: %s", command);
ENDLOG
}
mudstate.debug_cmd = cmdsave;
return preserve_cmd;

/*
* --------------------------------------------------------------------------* * process_cmdline: Execute a semicolon/pipe-delimited series of commands.
*/
void process_cmdline(player, cause, cmdline, args, nargs, qent)
dbref player, cause;
char *cmdline, *args[];
int nargs;
BQUE *qent;
{
char *cp, *cmdsave, *save_poutnew, *save_poutbufc, *save_pout;
char *log_cmdbuf;
int save_inpipe, numpipes;
dbref save_poutobj, save_enactor, save_player;
#ifndef NO_LAG_CHECK
struct timeval begin_time, end_time;
int used_time;
#ifndef NO_TIMECHECKING
struct timeval obj_time;
#endif
#ifdef TRACK_USER_TIME
struct rusage usage;
struct timeval b_utime, e_utime;
#endif
#endif
if (mudstate.cmd_nest_lev == mudconf.cmd_nest_lim)
return;
mudstate.cmd_nest_lev++;
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376

Saturday, June 16, 2012 11:51 PM

cmdsave = mudstate.debug_cmd;
save_enactor = mudstate.curr_enactor;
save_player = mudstate.curr_player;
mudstate.curr_enactor = cause;
mudstate.curr_player = player;
save_inpipe = mudstate.inpipe;
save_poutobj = mudstate.poutobj;
save_poutnew = mudstate.poutnew;
save_poutbufc = mudstate.poutbufc;
save_pout = mudstate.pout;
mudstate.break_called = 0;
while (cmdline && (!qent || qent == mudstate.qfirst) &&
!mudstate.break_called) {
cp = parse_to(&cmdline, ';', 0);
if (cp && *cp) {
numpipes = 0;
while (cmdline && (*cmdline == '|') &&
(!qent || qent == mudstate.qfirst) &&
(numpipes < mudconf.ntfy_nest_lim)) {
cmdline++;
numpipes++;
mudstate.inpipe = 1;
mudstate.poutnew = alloc_lbuf("process_cmdline.pipe");
mudstate.poutbufc = mudstate.poutnew;
mudstate.poutobj = player;
mudstate.debug_cmd = cp;
/* No lag check on piped commands */
process_command(player, cause, 0, cp,
args, nargs);
if (mudstate.pout && mudstate.pout != save_pout) {
free_lbuf(mudstate.pout);
mudstate.pout = NULL;
}

*mudstate.poutbufc = '\0';
mudstate.pout = mudstate.poutnew;
cp = parse_to(&cmdline, ';', 0);

mudstate.inpipe = save_inpipe;
mudstate.poutnew = save_poutnew;
mudstate.poutbufc = save_poutbufc;
mudstate.poutobj = save_poutobj;
mudstate.debug_cmd = cp;
/* Is the queue still linked like we think it is? */
if (qent && qent != mudstate.qfirst) {
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

Saturday, June 16, 2012 11:51 PM

if (mudstate.pout && mudstate.pout != save_pout) {


free_lbuf(mudstate.pout);
mudstate.pout = NULL;
}
break;

#ifndef NO_LAG_CHECK
get_tod(&begin_time);
#ifdef TRACK_USER_TIME
getrusage(RUSAGE_SELF, &usage);
b_utime.tv_sec = usage.ru_utime.tv_sec;
b_utime.tv_usec = usage.ru_utime.tv_usec;
#endif
#endif /* ! NO_LAG_CHECK */
log_cmdbuf = process_command(player, cause,
0, cp, args, nargs);
if (mudstate.pout && mudstate.pout != save_pout) {
free_lbuf(mudstate.pout);
mudstate.pout = save_pout;
}
save_poutbufc = mudstate.poutbufc;
#ifndef NO_LAG_CHECK
get_tod(&end_time);
#ifdef TRACK_USER_TIME
getrusage(RUSAGE_SELF, &usage);
e_utime.tv_sec = usage.ru_utime.tv_sec;
e_utime.tv_usec = usage.ru_utime.tv_usec;
#endif
used_time = msec_diff(end_time, begin_time);
if ((used_time / 1000) >= mudconf.max_cmdsecs) {
STARTLOG(LOG_PROBLEMS, "CMD", "CPU")
log_name_and_loc(player);
log_printf(" queued command taking %.2f secs (enactor #%d): %s" ,
(double) (used_time / 1000),
mudstate.qfirst->cause,
log_cmdbuf);
ENDLOG
}
#ifndef NO_TIMECHECKING
/* Don't use msec_add(), this is more accurate */
obj_time = Time_Used(player);
#ifndef TRACK_USER_TIME
obj_time.tv_usec += end_time.tv_usec begin_time.tv_usec;
obj_time.tv_sec += end_time.tv_sec begin_time.tv_sec;
#else
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482

Saturday, June 16, 2012 11:51 PM

obj_time.tv_usec += e_utime.tv_usec b_utime.tv_usec;


obj_time.tv_sec += e_utime.tv_sec b_utime.tv_sec;
#endif /* ! TRACK_USER_TIME */
if (obj_time.tv_usec < 0) {
obj_time.tv_usec += 1000000;
obj_time.tv_sec--;
} else if (obj_time.tv_usec >= 1000000) {
obj_time.tv_sec += obj_time.tv_usec / 1000000;
obj_time.tv_usec = obj_time.tv_usec % 1000000;
}
s_Time_Used(player, obj_time);
#endif /* ! NO_TIMECHECKING */
#endif /* ! NO_LAG_CHECK */
}
}
mudstate.debug_cmd = cmdsave;
mudstate.curr_enactor = save_enactor;
mudstate.curr_player = save_player;
}

mudstate.cmd_nest_lev--;

/* --------------------------------------------------------------------------* list_cmdtable: List internal commands. Note that user-defined command


* permissions are ignored in this context.
*/
static void list_cmdtable(player)
dbref player;
{
CMDENT *cmdp, *modcmds;
char *buf, *bp;
MODULE *mp;
buf = alloc_lbuf("list_cmdtable");
bp = buf;
safe_str((char *) "Built-in commands:", buf, &bp);
for (cmdp = command_table; cmdp->cmdname; cmdp++) {
if (check_access(player, cmdp->perms)) {
if (!(cmdp->perms & CF_DARK)) {
safe_chr(' ', buf, &bp);
safe_str((char *) cmdp->cmdname, buf, &bp);
}
}
}
/* Players get the list of logged-out cmds too */
if (isPlayer(player))
display_nametab(player, logout_cmdtable, buf, 1);
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535

else

Saturday, June 16, 2012 11:51 PM

notify(player, buf);

WALK_ALL_MODULES(mp) {
if ((modcmds = DLSYM_VAR(mp->handle, mp->modname, "cmdtable",
CMDENT *)) != NULL) {
bp = buf;
safe_tprintf_str(buf, &bp, "Module %s commands:", mp->modname);
for (cmdp = modcmds; cmdp->cmdname; cmdp++) {
if (check_access(player, cmdp->perms)) {
if (!(cmdp->perms & CF_DARK)) {
safe_chr(' ', buf, &bp);
safe_str((char *) cmdp->cmdname, buf, &bp);
}
}
}
notify(player, buf);
}
}
}

free_lbuf(buf);

/* --------------------------------------------------------------------------* list_attrtable: List available attributes.


*/
static void list_attrtable(player)
dbref player;
{
ATTR *ap;
char *buf, *bp, *cp;

buf = alloc_lbuf("list_attrtable");
bp = buf;
for (cp = (char *)"Attributes:"; *cp; cp++)
*bp++ = *cp;
for (ap = attr; ap->name; ap++) {
if (See_attr(player, player, ap, player, 0)) {
*bp++ = ' ';
for (cp = (char *)(ap->name); *cp; cp++)
*bp++ = *cp;
}
}
*bp = '\0';
raw_notify(player, buf);
free_lbuf(buf);

/* --------------------------------------------------------------------------* list_cmdaccess: List access commands.


*/

-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

Saturday, June 16, 2012 11:51 PM

static void helper_list_cmdaccess(player, ctab, buff)


dbref player;
CMDENT *ctab;
char *buff;
{
CMDENT *cmdp;
ATTR *ap;

for (cmdp = ctab; cmdp->cmdname; cmdp++) {


if (check_access(player, cmdp->perms)) {
if (!(cmdp->perms & CF_DARK)) {
if (cmdp->userperms) {
ap = atr_num(cmdp->userperms->atr);
if (!ap) {
sprintf(buff, "%s: user(#%d/?BAD?)",
cmdp->cmdname,
cmdp->userperms->thing);
} else {
sprintf(buff, "%s: user(#%d/%s)",
cmdp->cmdname,
cmdp->userperms->thing,
ap->name);
}
} else {
sprintf(buff, "%s:", cmdp->cmdname);
}
listset_nametab(player, access_nametab,
cmdp->perms, buff, 1);
}
}
}

static void list_cmdaccess(player)


dbref player;
{
char *buff, *p, *q;
CMDENT *cmdp, *ctab;
ATTR *ap;
MODULE *mp;
buff = alloc_sbuf("list_cmdaccess");
helper_list_cmdaccess(player, command_table, buff);
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "cmdtable",
CMDENT *)) != NULL) {
helper_list_cmdaccess(player, ctab, buff);
}
}
for (ap = attr; ap->name; ap++) {
p = buff;
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641

Saturday, June 16, 2012 11:51 PM

*p++ = '@';
for (q = (char *)ap->name; *q; p++, q++)
*p = tolower(*q);
if (ap->flags & AF_NOCMD)
continue;
*p = '\0';
cmdp = (CMDENT *) hashfind(buff, &mudstate.command_htab);
if (cmdp == NULL)
continue;
if (!check_access(player, cmdp->perms))
continue;
if (!(cmdp->perms & CF_DARK)) {
sprintf(buff, "%s:", cmdp->cmdname);
listset_nametab(player, access_nametab,
cmdp->perms, buff, 1);
}

}
free_sbuf(buff);

/* --------------------------------------------------------------------------* list_cmdswitches: List switches for commands.


*/
static void list_cmdswitches(player)
dbref player;
{
char *buff;
CMDENT *cmdp, *ctab;
MODULE *mp;
buff = alloc_sbuf("list_cmdswitches");
for (cmdp = command_table; cmdp->cmdname; cmdp++) {
if (cmdp->switches) {
if (check_access(player, cmdp->perms)) {
if (!(cmdp->perms & CF_DARK)) {
sprintf(buff, "%s:", cmdp->cmdname);
display_nametab(player, cmdp->switches,
buff, 0);
}
}
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "cmdtable",
CMDENT *)) != NULL) {
for (cmdp = ctab; cmdp->cmdname; cmdp++) {
if (cmdp->switches) {
if (check_access(player, cmdp->perms)) {
if (!(cmdp->perms & CF_DARK)) {
sprintf(buff, "%s:", cmdp->cmdname);
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694

}
}

}
}

}
}

Saturday, June 16, 2012 11:51 PM

display_nametab(player, cmdp->switches,
buff, 0);

free_sbuf(buff);

/* --------------------------------------------------------------------------* list_attraccess: List access to attributes.


*/
static void list_attraccess(player)
dbref player;
{
char *buff;
ATTR *ap;

buff = alloc_sbuf("list_attraccess");
for (ap = attr; ap->name; ap++) {
if (Read_attr(player, player, ap, player, 0)) {
sprintf(buff, "%s:", ap->name);
listset_nametab(player, attraccess_nametab,
ap->flags, buff, 1);
}
}
free_sbuf(buff);

/* --------------------------------------------------------------------------* list_attrtypes: List attribute "types" (wildcards and permissions)


*/
static void list_attrtypes(player)
dbref player;
{
char *buff;
KEYLIST *kp;
if (!mudconf.vattr_flag_list) {
notify(player, "No attribute type patterns defined." );
return;
}
buff = alloc_sbuf("list_attrtypes");
for (kp = mudconf.vattr_flag_list; kp != NULL; kp = kp->next) {
sprintf(buff, "%s:", kp->name);
listset_nametab(player, attraccess_nametab, kp->data, buff, 1);
}
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747

Saturday, June 16, 2012 11:51 PM

free_sbuf(buff);

/* --------------------------------------------------------------------------* cf_access: Change command or switch permissions.


*/
CF_HAND(cf_access)
{
CMDENT *cmdp;
char *ap;
int set_switch;
for (ap = str; *ap && !isspace(*ap) && (*ap != '/'); ap++) ;
if (*ap == '/') {
set_switch = 1;
*ap++ = '\0';
} else {
set_switch = 0;
if (*ap)
*ap++ = '\0';
while (*ap && isspace(*ap))
ap++;
}

cmdp = (CMDENT *) hashfind(str, &mudstate.command_htab);


if (cmdp != NULL) {
if (set_switch)
return cf_ntab_access((int *)cmdp->switches, ap,
extra, player, cmd);
else
return cf_modify_bits(&(cmdp->perms), ap,
extra, player, cmd);
} else {
cf_log_notfound(player, cmd, "Command", str);
return -1;
}

/* --------------------------------------------------------------------------* cf_acmd_access: Change command permissions for all attr-setting cmds.


*/
CF_HAND(cf_acmd_access)
{
CMDENT *cmdp;
ATTR *ap;
char *buff, *p, *q;
int failure, save;
buff = alloc_sbuf("cf_acmd_access");
for (ap = attr; ap->name; ap++) {
p = buff;
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800

Saturday, June 16, 2012 11:51 PM

*p++ = '@';
for (q = (char *)ap->name; *q; p++, q++)
*p = tolower(*q);
*p = '\0';
cmdp = (CMDENT *) hashfind(buff, &mudstate.command_htab);
if (cmdp != NULL) {
save = cmdp->perms;
failure = cf_modify_bits(&(cmdp->perms), str,
extra, player, cmd);
if (failure != 0) {
cmdp->perms = save;
free_sbuf(buff);
return -1;
}
}

}
free_sbuf(buff);
return 0;

/* --------------------------------------------------------------------------* cf_attr_access: Change access on an attribute.


*/
CF_HAND(cf_attr_access)
{
ATTR *ap;
char *sp;
for (sp = str; *sp && !isspace(*sp); sp++) ;
if (*sp)
*sp++ = '\0';
while (*sp && isspace(*sp))
sp++;

ap = atr_str(str);
if (ap != NULL)
return cf_modify_bits(&(ap->flags), sp, extra, player, cmd);
else {
cf_log_notfound(player, cmd, "Attribute", str);
return -1;
}

/* --------------------------------------------------------------------------* cf_attr_type: Define attribute flags for new user-named attributes


*
whose names match a certain pattern.
*/
CF_HAND(cf_attr_type)
{
char *privs;
KEYLIST *kp;
-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853

Saturday, June 16, 2012 11:51 PM

int succ;
/* Split our string into the attribute pattern and privileges. Also
* uppercase it, while we're at it. Make sure it's not longer than
* an attribute name can be.
*/
for (privs = str; *privs && !isspace(*privs); privs++) {
*privs = toupper(*privs);
}
if (*privs)
*privs++ = '\0';
while (*privs && isspace(*privs))
privs++;
if (strlen(str) >= VNAME_SIZE)
str[VNAME_SIZE - 1] = '\0';
/* Create our new data blob. Make sure that we're setting the privs
* to something reasonable before trying to link it in. (If we're
* not, an error will have been logged; we don't need to do it.)
*/
kp = (KEYLIST *) XMALLOC(sizeof(KEYLIST), "cf_attr_type.kp");
kp->data = 0;
succ = cf_modify_bits(&(kp->data), privs, extra, player, cmd);
if (succ < 0) {
XFREE(kp, "cf_attr_type.kp");
return -1;
}
kp->name = XSTRDUP(str, "cf_attr_type.name");
kp->next = mudconf.vattr_flag_list;
mudconf.vattr_flag_list = kp;
}

return (succ);

/* --------------------------------------------------------------------------* cf_cmd_alias: Add a command alias.


*/
CF_HAND(cf_cmd_alias)
{
char *alias, *orig, *ap, *tokst;
CMDENT *cmdp, *cmd2;
NAMETAB *nt;
int *hp;
alias = strtok_r(str, " \t=,", &tokst);
orig = strtok_r(NULL, " \t=,", &tokst);
if (!orig) {

/* we only got one argument to @alias. Bad. */


-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906

Saturday, June 16, 2012 11:51 PM

cf_log_syntax(player, cmd, "Invalid original for alias %s" ,


alias);
return -1;

}
if (alias[0] == '_' && alias[1] == '_') {
cf_log_syntax(player, cmd, "Alias %s would cause @addcommand conflict" ,
alias);
return -1;
}
for (ap = orig; *ap && (*ap != '/'); ap++) ;
if (*ap == '/') {
/* Switch form of command aliasing: create an alias for a
* command + a switch
*/
*ap++ = '\0';
/* Look up the command */
cmdp = (CMDENT *) hashfind(orig, (HASHTAB *) vp);
if (cmdp == NULL) {
cf_log_notfound(player, cmd, "Command", orig);
return -1;
}
/* Look up the switch */
nt = find_nametab_ent(player, (NAMETAB *) cmdp->switches, ap);
if (!nt) {
cf_log_notfound(player, cmd, "Switch", ap);
return -1;
}
/*
* Got it, create the new command table entry
*/
cmd2 = (CMDENT *) XMALLOC(sizeof(CMDENT), "cf_cmd_alias");
cmd2->cmdname = XSTRDUP(alias, "cf_cmd_alias.cmdname");
cmd2->switches = cmdp->switches;
cmd2->perms = cmdp->perms | nt->perm;
cmd2->extra = (cmdp->extra | nt->flag) & ~SW_MULTIPLE;
if (!(nt->flag & SW_MULTIPLE))
cmd2->extra |= SW_GOT_UNIQUE;
cmd2->callseq = cmdp->callseq;
/*
*
*
*
*
*
*
*

KNOWN PROBLEM:
We are not inheriting the hook that the 'original' command
had -- we will have to add it manually (whereas an alias
of a non-switched command is just another hashtable entry
for the same command pointer and therefore gets the hook).
This is preferable to having to search the hashtable for
hooks when a hook is deleted, though.
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958

Saturday, June 16, 2012 11:51 PM

*/
cmd2->pre_hook = NULL;
cmd2->post_hook = NULL;
cmd2->userperms = NULL;
cmd2->info.handler = cmdp->info.handler;
if (hashadd(cmd2->cmdname, (int *)cmd2, (HASHTAB *) vp, 0)) {
XFREE(cmd2->cmdname, "cf_cmd_alias.cmdname");
XFREE(cmd2, "cf_cmd_alias");
}
} else {
/* A normal (non-switch) alias */
hp = hashfind(orig, (HASHTAB *) vp);
if (hp == NULL) {
cf_log_notfound(player, cmd, "Entry", orig);
return -1;
}

hashadd(alias, hp, (HASHTAB *) vp, HASH_ALIAS);


}
return 0;

/* --------------------------------------------------------------------------* list_df_flags: List default flags at create time.


*/
static void list_df_flags(player)
dbref player;
{
char *playerb, *roomb, *thingb, *exitb, *robotb, *stripb, *buff;
playerb = decode_flags(player, mudconf.player_flags);
roomb = decode_flags(player, mudconf.room_flags);
exitb = decode_flags(player, mudconf.exit_flags);
thingb = decode_flags(player, mudconf.thing_flags);
robotb = decode_flags(player, mudconf.robot_flags);
stripb = decode_flags(player, mudconf.stripped_flags);
buff = alloc_lbuf("list_df_flags");
sprintf(buff,
"Default flags: Players...P%s Rooms...R%s Exits...E%s
Robots...P%s Stripped...%s",
playerb, roomb, exitb, thingb, robotb, stripb);
raw_notify(player, buff);
free_lbuf(buff);
free_sbuf(playerb);
free_sbuf(roomb);
free_sbuf(exitb);
free_sbuf(thingb);
free_sbuf(robotb);
-37-

Things...%s

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011

Saturday, June 16, 2012 11:51 PM

free_sbuf(stripb);

/* --------------------------------------------------------------------------* list_costs: List the costs of things.


*/
#define coin_name(s)

(((s)==1) ? mudconf.one_coin : mudconf.many_coins)

static void list_costs(player)


dbref player;
{
char *buff;
buff = alloc_mbuf("list_costs");
*buff = '\0';
if (mudconf.quotas)
sprintf(buff, " and %d quota", mudconf.room_quota);
notify(player,
tprintf("Digging a room costs %d %s%s." ,
mudconf.digcost, coin_name(mudconf.digcost), buff));
if (mudconf.quotas)
sprintf(buff, " and %d quota", mudconf.exit_quota);
notify(player,
tprintf("Opening a new exit costs %d %s%s." ,
mudconf.opencost, coin_name(mudconf.opencost), buff));
notify(player,
tprintf("Linking an exit, home, or dropto costs %d %s." ,
mudconf.linkcost, coin_name(mudconf.linkcost)));
if (mudconf.quotas)
sprintf(buff, " and %d quota", mudconf.thing_quota);
if (mudconf.createmin == mudconf.createmax)
raw_notify(player,
tprintf("Creating a new thing costs %d %s%s." ,
mudconf.createmin,
coin_name(mudconf.createmin), buff));
else
raw_notify(player,
tprintf("Creating a new thing costs between %d and %d %s%s." ,
mudconf.createmin, mudconf.createmax,
mudconf.many_coins, buff));
if (mudconf.quotas)
sprintf(buff, " and %d quota", mudconf.player_quota);
notify(player,
tprintf("Creating a robot costs %d %s%s." ,
mudconf.robotcost, coin_name(mudconf.robotcost),
buff));
if (mudconf.killmin == mudconf.killmax) {
raw_notify(player,
tprintf("Killing costs %d %s, with a %d%% chance of success." ,
mudconf.killmin, coin_name(mudconf.digcost),
(mudconf.killmin * 100) /
mudconf.killguarantee));
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060

Saturday, June 16, 2012 11:51 PM

} else {
raw_notify(player,
tprintf("Killing costs between %d and %d %s." ,
mudconf.killmin, mudconf.killmax,
mudconf.many_coins));
raw_notify(player,
tprintf("You must spend %d %s to guarantee success." ,
mudconf.killguarantee,
coin_name(mudconf.killguarantee)));
}
raw_notify(player,
tprintf("Computationally expensive commands and functions (ie: @entrances,
@find, @search, @stats (with an argument or switch), search(), and stats())
cost %d %s.",
mudconf.searchcost, coin_name(mudconf.searchcost)));
if (mudconf.machinecost > 0)
raw_notify(player,
tprintf("Each command run from the queue costs 1/%d %s." ,
mudconf.machinecost, mudconf.one_coin));
if (mudconf.waitcost > 0) {
raw_notify(player,
tprintf("A %d %s deposit is charged for putting a command on the queue." ,
mudconf.waitcost, mudconf.one_coin));
raw_notify(player, "The deposit is refunded when the command is run or
canceled.");
}
if (mudconf.sacfactor == 0)
sprintf(buff, "%d", mudconf.sacadjust);
else if (mudconf.sacfactor == 1) {
if (mudconf.sacadjust < 0)
sprintf(buff, "<create cost> - %d", -mudconf.sacadjust);
else if (mudconf.sacadjust > 0)
sprintf(buff, "<create cost> + %d", mudconf.sacadjust);
else
sprintf(buff, "<create cost>");
} else {
if (mudconf.sacadjust < 0)
sprintf(buff, "(<create cost> / %d) - %d",
mudconf.sacfactor, -mudconf.sacadjust);
else if (mudconf.sacadjust > 0)
sprintf(buff, "(<create cost> / %d) + %d",
mudconf.sacfactor, mudconf.sacadjust);
else
sprintf(buff, "<create cost> / %d", mudconf.sacfactor);
}
raw_notify(player, tprintf("The value of an object is %s." , buff));
if (mudconf.clone_copy_cost)
raw_notify(player, "The default value of cloned objects is the value of the
original object.");
else
raw_notify(player,
tprintf("The default value of cloned objects is %d %s." ,
mudconf.createmin,
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113

Saturday, June 16, 2012 11:51 PM

coin_name(mudconf.createmin)));
}

free_mbuf(buff);

/* --------------------------------------------------------------------------* list_options: List boolean game options from mudconf.


* list_config: List non-boolean game options.
*/
extern void FDECL(list_options, (dbref));
static void list_params(player)
dbref player;
{
time_t now;
now = time(NULL);
raw_notify(player,
tprintf("Prototypes: Room...#%d Exit...#%d Thing...#%d
mudconf.room_proto, mudconf.exit_proto,
mudconf.thing_proto, mudconf.player_proto));

Player...#%d" ,

raw_notify(player,
tprintf("Attr Defaults: Room...#%d Exit...#%d Thing...#%d
mudconf.room_defobj, mudconf.exit_defobj,
mudconf.thing_defobj, mudconf.player_defobj));
raw_notify(player,
tprintf("Default Parents: Room...#%d Exit...#%d Thing...#%d
mudconf.room_parent, mudconf.exit_parent,
mudconf.thing_parent, mudconf.player_parent));

Player...#%d" ,

Player...#%d" ,

raw_notify(player, "Limits:");
raw_notify(player,
tprintf(" Function recursion...%d Function invocation...%d" ,
mudconf.func_nest_lim, mudconf.func_invk_lim));
raw_notify(player,
tprintf(" Command recursion...%d Command invocation...%d" ,
mudconf.cmd_nest_lim, mudconf.cmd_invk_lim));
raw_notify(player,
tprintf(" Output...%d Queue...%d CPU...%d Wild...%d Aliases...%d" ,
mudconf.output_limit, mudconf.queuemax,
mudconf.func_cpu_lim_secs,
mudconf.wild_times_lim, mudconf.max_player_aliases));
raw_notify(player,
tprintf(" Forwardlist...%d Propdirs... %d Registers...%d Stacks...%d" ,
mudconf.fwdlist_lim, mudconf.propdir_lim, mudconf.register_limit,
mudconf.stack_lim));
raw_notify(player,
tprintf(" Variables...%d Structures...%d Instances...%d" ,
mudconf.numvars_lim, mudconf.struct_lim, mudconf.instance_lim));
-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163

Saturday, June 16, 2012 11:51 PM

raw_notify(player,
tprintf(" Objects...%d Allowance...%d Trace levels...%d Connect
tries...%d",
mudconf.building_limit, mudconf.paylimit,
mudconf.trace_limit, mudconf.retry_limit));
if (mudconf.max_players >= 0)
raw_notify(player, tprintf(" Logins...%d", mudconf.max_players));
raw_notify(player,
tprintf("Nesting: Locks...%d Parents...%d Messages...%d
mudconf.lock_nest_lim, mudconf.parent_nest_lim,
mudconf.ntfy_nest_lim, mudconf.zone_nest_lim));
raw_notify(player,
tprintf("Timeouts: Idle...%d Connect...%d Tries...%d
mudconf.idle_timeout, mudconf.conn_timeout,
mudconf.retry_limit, mudconf.max_cmdsecs));

Zones...%d" ,

Lag...%d" ,

raw_notify(player,
tprintf("Money: Start...%d Daily...%d Singular: %s Plural: %s" ,
mudconf.paystart, mudconf.paycheck,
mudconf.one_coin, mudconf.many_coins));
if (mudconf.payfind > 0)
raw_notify(player, tprintf("Chance of finding money: 1 in %d" ,
mudconf.payfind));
raw_notify(player,
tprintf("Start Quotas: Total...%d Rooms...%d Exits...%d Things...%d
Players...%d",
mudconf.start_quota,
mudconf.start_room_quota, mudconf.start_exit_quota,
mudconf.start_thing_quota, mudconf.start_player_quota));
raw_notify(player, "Dbrefs:");
raw_notify(player,
tprintf(" MasterRoom...#%d StartRoom...#%d StartHome...#%d
DefaultHome...#%d",
mudconf.master_room, mudconf.start_room, mudconf.start_home,
mudconf.default_home));
if (Wizard(player)) {
raw_notify(player,
tprintf(" GuestChar...#%d GuestStart...#%d Freelist...#%d" ,
mudconf.guest_char, mudconf.guest_start_room,
mudstate.freelist));
raw_notify(player,
tprintf("Queue run sizes: No net activity... %d Activity... %d" ,
mudconf.queue_chunk, mudconf.active_q_chunk));
raw_notify(player,
tprintf("Intervals:

Dump...%d

Clean...%d
-41-

Idlecheck...%d

Optimize...%d" ,

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216

Saturday, June 16, 2012 11:51 PM

mudconf.dump_interval, mudconf.check_interval,
mudconf.idle_interval, mudconf.dbopt_interval));
raw_notify(player,
tprintf("Timers: Dump...%d Clean...%d Idlecheck...%d" ,
(int) (mudstate.dump_counter - now),
(int) (mudstate.check_counter - now),
(int) (mudstate.idle_counter - now)));
raw_notify(player,
tprintf("Scheduling: Timeslice...%d Max_Quota...%d
mudconf.timeslice, mudconf.cmd_quota_max,
mudconf.cmd_quota_incr));

Increment...%d" ,

raw_notify(player,
tprintf("Size of %s cache: Width...%d Size...%d" ,
CACHING, mudconf.cache_width, mudconf.cache_size));
}

/* --------------------------------------------------------------------------* list_vattrs: List user-defined attributes


*/
static void list_vattrs(player)
dbref player;
{
VATTR *va;
int na;
char *buff;
buff = alloc_lbuf("list_vattrs");
raw_notify(player, "--- User-Defined Attributes ---" );
for (va = vattr_first(), na = 0; va; va = vattr_next(va), na++) {
if (!(va->flags & AF_DELETED)) {
sprintf(buff, "%s(%d):", va->name, va->number);
listset_nametab(player, attraccess_nametab, va->flags,
buff, 1);
}
}

raw_notify(player, tprintf("%d attributes, next=%d",


na, mudstate.attr_next));
free_lbuf(buff);

/* --------------------------------------------------------------------------* list_hashstats: List information from hash tables


*/
static void list_hashstat(player, tab_name, htab)
dbref player;
HASHTAB *htab;
-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268

Saturday, June 16, 2012 11:51 PM

const char *tab_name;


{
char *buff;

buff = hashinfo(tab_name, htab);


raw_notify(player, buff);
free_mbuf(buff);

static void list_nhashstat(player, tab_name, htab)


dbref player;
NHSHTAB *htab;
const char *tab_name;
{
char *buff;

buff = nhashinfo(tab_name, htab);


raw_notify(player, buff);
free_mbuf(buff);

static void list_hashstats(player)


dbref player;
{
MODULE *mp;
MODHASHES *m_htab, *hp;
MODNHASHES *m_ntab, *np;
raw_notify(player, "Hash Stats
Size Entries Deleted
Empty Lookups
Checks Longest");
list_hashstat(player, "Commands", &mudstate.command_htab);
list_hashstat(player, "Logged-out Cmds", &mudstate.logout_cmd_htab);
list_hashstat(player, "Functions", &mudstate.func_htab);
list_hashstat(player, "User Functions", &mudstate.ufunc_htab);
list_hashstat(player, "Flags", &mudstate.flags_htab);
list_hashstat(player, "Powers", &mudstate.powers_htab);
list_hashstat(player, "Attr names", &mudstate.attr_name_htab);
list_hashstat(player, "Vattr names", &mudstate.vattr_name_htab);
list_hashstat(player, "Player Names", &mudstate.player_htab);
list_hashstat(player, "References", &mudstate.nref_htab);
list_nhashstat(player, "Net Descriptors", &mudstate.desc_htab);
list_nhashstat(player, "Forwardlists", &mudstate.fwdlist_htab);
list_nhashstat(player, "Propdirs", &mudstate.propdir_htab);
list_nhashstat(player, "Redirections", &mudstate.redir_htab);
list_nhashstat(player, "Overlaid $-cmds", &mudstate.parent_htab);
list_nhashstat(player, "Object Stacks", &mudstate.objstack_htab);
list_hashstat(player, "Variables", &mudstate.vars_htab);
list_hashstat(player, "Structure Defs", &mudstate.structs_htab);
list_hashstat(player, "Component Defs", &mudstate.cdefs_htab);
list_hashstat(player, "Instances", &mudstate.instance_htab);
list_hashstat(player, "Instance Data", &mudstate.instdata_htab);
list_hashstat(player, "Module APIs", &mudstate.api_func_htab);

-43-

Hits

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320

Saturday, June 16, 2012 11:51 PM

WALK_ALL_MODULES(mp) {
m_htab = DLSYM_VAR(mp->handle, mp->modname,
"hashtable", MODHASHES *);
if (m_htab) {
for (hp = m_htab; hp->htab != NULL; hp++) {
list_hashstat(player, hp->tabname, hp->htab);
}
}
m_ntab = DLSYM_VAR(mp->handle, mp->modname,
"nhashtable", MODNHASHES *);
if (m_ntab) {
for (np = m_ntab; np->tabname != NULL; np++) {
list_nhashstat(player, np->tabname, np->htab);
}
}
}

static void list_textfiles(player)


dbref player;
{
int i;
raw_notify(player, "Help File
Checks Longest");

Size Entries Deleted

Empty Lookups

for (i = 0; i < mudstate.helpfiles; i++)


list_hashstat(player, mudstate.hfiletab[i], &mudstate.hfile_hashes[i]);

/* These are from 'udb_cache.c'. */


extern time_t cs_ltime;
extern int cs_writes;
/* total writes */
extern int cs_reads;
/* total reads */
extern int cs_dbreads;
/* total read-throughs */
extern int cs_dbwrites;
/* total write-throughs */
extern int cs_dels;
/* total deletes */
extern int cs_checks;
/* total checks */
extern int cs_rhits;
/* total reads filled from cache */
extern int cs_ahits;
/* total reads filled active cache */
extern int cs_whits;
/* total writes to dirty cache */
extern int cs_fails;
/* attempts to grab nonexistent */
extern int cs_resets;
/* total cache resets */
extern int cs_syncs;
/* total cache syncs */
extern int cs_size;
/* total cache size */
/* --------------------------------------------------------------------------* list_db_stats: Get useful info from the DB layer about hash stats, etc.
*/
static void list_db_stats(player)
dbref player;
{
-44-

Hits

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373

Saturday, June 16, 2012 11:51 PM

raw_notify(player,
tprintf("DB Cache Stats
Writes
Reads (over %d seconds)" ,
(int) (time(NULL) - cs_ltime)));
raw_notify(player, tprintf("Calls
%12d%12d", cs_writes, cs_reads));
raw_notify(player, tprintf("Cache Hits %12d%12d",
cs_whits, cs_rhits));
raw_notify(player, tprintf("I/O
%12d%12d",
cs_dbwrites, cs_dbreads));
raw_notify(player, tprintf("Failed
%12d" ,
cs_fails));
raw_notify(player, tprintf("Hit ratio
%2.0f%%
%2.0f%%" ,
(cs_writes ? (float) cs_whits / cs_writes * 100 : 0.0),
(cs_reads ? (float) cs_rhits / cs_reads * 100 : 0.0)));
raw_notify(player, tprintf("\nDeletes
%12d", cs_dels));
raw_notify(player, tprintf("Checks
%12d", cs_checks));
raw_notify(player, tprintf("Syncs
%12d", cs_syncs));
raw_notify(player, tprintf("Cache Size %12d bytes", cs_size));

/* --------------------------------------------------------------------------* list_process: List local resource usage stats of the MUSH process.
* Adapted from code by Claudius@PythonMUCK,
*
posted to the net by Howard/Dark_Lord.
*/
static void list_process(player)
dbref player;
{
int pid, psize, maxfds;
#if defined(HAVE_GETRUSAGE) && defined(STRUCT_RUSAGE_COMPLETE)
struct rusage usage;
int ixrss, idrss, isrss, curr, last, dur;
getrusage(RUSAGE_SELF, &usage);
/*
* Calculate memory use from the aggregate totals
*/
curr = mudstate.mstat_curr;
last = 1 - curr;
dur = mudstate.mstat_secs[curr] - mudstate.mstat_secs[last];
if (dur > 0) {
ixrss = (mudstate.mstat_ixrss[curr] mudstate.mstat_ixrss[last]) / dur;
idrss = (mudstate.mstat_idrss[curr] mudstate.mstat_idrss[last]) / dur;
isrss = (mudstate.mstat_isrss[curr] mudstate.mstat_isrss[last]) / dur;
} else {
ixrss = 0;
idrss = 0;
isrss = 0;
-45-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426

Saturday, June 16, 2012 11:51 PM

}
#endif
#ifdef HAVE_GETDTABLESIZE
maxfds = getdtablesize();
#else
maxfds = sysconf(_SC_OPEN_MAX);
#endif
pid = getpid();
psize = getpagesize();
/*
* Go display everything
*/
raw_notify(player,
tprintf("Process ID: %10d
%10d bytes per page" ,
pid, psize));
#if defined(HAVE_GETRUSAGE) && defined(STRUCT_RUSAGE_COMPLETE)
raw_notify(player,
tprintf("Time used:
%10d user
%10d sys" ,
usage.ru_utime.tv_sec, usage.ru_stime.tv_sec));
/*
* raw_notify(player,
* * tprintf("Resident mem:%10d shared %10d private%10d stack",
* * ixrss, idrss, isrss));
*/
raw_notify(player,
tprintf("Integral mem:%10d shared %10d private%10d stack" ,
usage.ru_ixrss, usage.ru_idrss, usage.ru_isrss));
raw_notify(player,
tprintf("Max res mem: %10d pages %10d bytes" ,
usage.ru_maxrss, (usage.ru_maxrss * psize)));
raw_notify(player,
tprintf("Page faults: %10d hard
%10d soft
%10d swapouts" ,
usage.ru_majflt, usage.ru_minflt, usage.ru_nswap));
raw_notify(player,
tprintf("Disk I/O:
%10d reads %10d writes" ,
usage.ru_inblock, usage.ru_oublock));
raw_notify(player,
tprintf("Network I/O: %10d in
%10d out" ,
usage.ru_msgrcv, usage.ru_msgsnd));
raw_notify(player,
tprintf("Context swi: %10d vol
%10d forced %10d sigs" ,
usage.ru_nvcsw, usage.ru_nivcsw, usage.ru_nsignals));
raw_notify(player,
tprintf("Descs avail: %10d", maxfds));
#endif
}
/* ---------------------------------------------------------------------------46-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479

Saturday, June 16, 2012 11:51 PM

* list_memory: Breaks down memory usage of the process


*/
extern
extern
extern
extern

Chain *sys_c;
NAME *names, *purenames;
POOL pools[NUM_POOLS];
int anum_alc_top;

void list_memory(player)
{
double total = 0, each = 0, each2 = 0;
int i, j;
CMDENT *cmd;
ADDENT *add;
NAMETAB *name;
VATTR *vattr;
ATTR *attr;
FUN *func;
UFUN *ufunc;
Cache *cp;
Chain *sp;
HASHENT *htab;
struct help_entry *hlp;
FLAGENT *flag;
POWERENT *power;
OBJSTACK *stack;
VARENT *xvar;
STRUCTDEF *this_struct;
INSTANCE *inst_ptr;
STRUCTDATA *data_ptr;
/* Calculate size of object structures */
each = mudstate.db_top * sizeof(OBJ);
raw_notify(player,
tprintf("Object structures: %12.2fk", each / 1024));
total += each;
#ifdef MEMORY_BASED
each = 0;
/* Calculate size of stored attribute text */
DO_WHOLE_DB(i) {
each += obj_siz(&(db[i].attrtext));
each -= sizeof(Obj);
}
raw_notify(player,
tprintf("Stored attrtext
total += each;
#endif

: %12.2fk", each / 1024));

/* Calculate size of mudstate and mudconf structures */

-47-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532

Saturday, June 16, 2012 11:51 PM

each = sizeof(CONFDATA) + sizeof(STATEDATA);


raw_notify(player,
tprintf("mudconf/mudstate : %12.2fk", each / 1024));
total += each;
/* Calculate size of cache */
each = cs_size;
raw_notify(player,
tprintf("Cache data
total += each;

: %12.2fk", each / 1024));

each = sizeof(Chain) * mudconf.cache_width;


for (i = 0; i < mudconf.cache_width; i++) {
sp = &sys_c[i];
for(cp = sp->head; cp != NULL; cp = cp->nxt) {
each += sizeof(Cache);
each2 += cp->keylen;
}
}
raw_notify(player,
tprintf("Cache keys
: %12.2fk", each2 / 1024));
raw_notify(player,
tprintf("Cache overhead
: %12.2fk", each / 1024));
total += each + each2;
/* Calculate size of object pipelines */
each = 0;
for (i = 0; i < NUM_OBJPIPES; i++) {
if (mudstate.objpipes[i])
each += obj_siz(mudstate.objpipes[i]);
}
raw_notify(player,
tprintf("Object pipelines : %12.2fk", each / 1024));
total += each;
/* Calculate size of name caches */
each = sizeof(NAME *) * mudstate.db_top * 2;
for (i = 0; i < mudstate.db_top; i++) {
if (purenames[i])
each += strlen(purenames[i]) + 1;
if (names[i])
each += strlen(names[i]) + 1;
}
raw_notify(player,
tprintf("Name caches
: %12.2fk", each / 1024));
total += each;
/* Calculate size of buffers */

-48-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585

Saturday, June 16, 2012 11:51 PM

each = sizeof(POOL) * NUM_POOLS;


for (i = 0; i < NUM_POOLS; i++) {
each += pools[i].max_alloc * (pools[i].pool_size +
sizeof(POOLHDR) + sizeof(POOLFTR));
}
raw_notify(player,
tprintf("Buffers
: %12.2fk", each / 1024));
total += each;
/* Calculate size of command hashtable */
each = 0;
each += sizeof(HASHENT *) * mudstate.command_htab.hashsize;
for(i = 0; i < mudstate.command_htab.hashsize; i++) {
htab = mudstate.command_htab.entry[i];
while (htab != NULL) {
each += sizeof(HASHENT);
each += strlen(mudstate.command_htab.entry[i]->target.s) + 1;
/* Add up all the little bits in the CMDENT. */
if (!(htab->flags & HASH_ALIAS)) {
each += sizeof(CMDENT);
cmd = (CMDENT *)htab->data;
each += strlen(cmd->cmdname) + 1;
if ((name = cmd->switches) != NULL) {
for(j = 0; name[j].name != NULL; j++) {
each += sizeof(NAMETAB);
each += strlen(name[j].name) + 1;
}
}
if (cmd->callseq & CS_ADDED) {
add = cmd->info.added;
while (add != NULL) {
each += sizeof(ADDENT);
each += strlen(add->name) + 1;
add = add->next;
}
}
}
htab = htab->next;

}
}
raw_notify(player,
tprintf("Command table
total += each;

: %12.2fk", each / 1024));

/* Calculate size of logged-out commands hashtable */


each = 0;
each += sizeof(HASHENT *) * mudstate.logout_cmd_htab.hashsize;
for(i = 0; i < mudstate.logout_cmd_htab.hashsize; i++) {
htab = mudstate.logout_cmd_htab.entry[i];
-49-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638

Saturday, June 16, 2012 11:51 PM

while (htab != NULL) {


each += sizeof(HASHENT);
each += strlen(htab->target.s) + 1;
if (!(htab->flags & HASH_ALIAS)) {
name = (NAMETAB *)htab->data;
each += sizeof(NAMETAB);
each += strlen(name->name) + 1;
}
htab = htab->next;
}

}
raw_notify(player,
tprintf("Logout cmd htab
total += each;

: %12.2fk", each / 1024));

/* Calculate size of functions hashtable */


each = 0;
each += sizeof(HASHENT *) * mudstate.func_htab.hashsize;
for(i = 0; i < mudstate.func_htab.hashsize; i++) {
htab = mudstate.func_htab.entry[i];
while (htab != NULL) {
each += sizeof(HASHENT);
each += strlen(htab->target.s) + 1;
if (!(htab->flags & HASH_ALIAS)) {
func = (FUN *)htab->data;
each += sizeof(FUN);
}
/* We don't count func->name because we already got
* it with htab->target.s */
htab = htab->next;

}
}
raw_notify(player,
tprintf("Functions htab
total += each;

: %12.2fk", each / 1024));

/* Calculate size of user-defined functions hashtable */


each = 0;
each += sizeof(HASHENT *) * mudstate.ufunc_htab.hashsize;
for(i = 0; i < mudstate.ufunc_htab.hashsize; i++) {
htab = mudstate.ufunc_htab.entry[i];
while (htab != NULL) {
each += sizeof(HASHENT);
each += strlen(htab->target.s) + 1;
if (!(htab->flags & HASH_ALIAS)) {
ufunc = (UFUN *)htab->data;
while (ufunc != NULL) {
each += sizeof(UFUN);
each += strlen(ufunc->name) + 1;
ufunc = ufunc->next;
-50-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691

Saturday, June 16, 2012 11:51 PM

}
}
htab = htab->next;

}
}
raw_notify(player,
tprintf("U-functions htab : %12.2fk", each / 1024));
total += each;
/* Calculate size of flags hashtable */
each = 0;
each += sizeof(HASHENT *) * mudstate.flags_htab.hashsize;
for(i = 0; i < mudstate.flags_htab.hashsize; i++) {
htab = mudstate.flags_htab.entry[i];
while (htab != NULL) {
each += sizeof(HASHENT);
each += strlen(htab->target.s) + 1;
if (!(htab->flags & HASH_ALIAS)) {
flag = (FLAGENT *)htab->data;
each += sizeof(FLAGENT);
}

/* We don't count flag->flagname because we already got


* it with htab->target.s */
htab = htab->next;

}
raw_notify(player,
tprintf("Flags htab
total += each;

: %12.2fk", each / 1024));

/* Calculate size of powers hashtable */


each = 0;
each += sizeof(HASHENT *) * mudstate.powers_htab.hashsize;
for(i = 0; i < mudstate.powers_htab.hashsize; i++) {
htab = mudstate.powers_htab.entry[i];
while (htab != NULL) {
each += sizeof(HASHENT);
each += strlen(htab->target.s) + 1;
if (!(htab->flags & HASH_ALIAS)) {
power = (POWERENT *)htab->data;
each += sizeof(POWERENT);
}

/* We don't count power->powername because we already got


* it with htab->target.s */
htab = htab->next;

}
raw_notify(player,
tprintf("Powers htab

: %12.2fk", each / 1024));


-51-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744

Saturday, June 16, 2012 11:51 PM

total += each;
/* Calculate size of helpfile hashtables */
each = 0;
for(j = 0; j < mudstate.helpfiles; j++) {
each += sizeof(HASHENT *) * mudstate.hfile_hashes[j].hashsize;
for(i = 0; i < mudstate.hfile_hashes[j].hashsize; i++) {
htab = mudstate.hfile_hashes[j].entry[i];
while (htab != NULL) {
each += sizeof(HASHENT);
each += strlen(htab->target.s) + 1;
if (!(htab->flags & HASH_ALIAS)) {
each += sizeof(struct help_entry);
hlp = (struct help_entry *)htab->data;
}
htab = htab->next;
}
}
}
raw_notify(player,
tprintf("Helpfiles htabs : %12.2fk", each / 1024));
total += each;
/* Calculate size of vattr name hashtable */
each = 0;
each += sizeof(HASHENT *) * mudstate.vattr_name_htab.hashsize;
for(i = 0; i < mudstate.vattr_name_htab.hashsize; i++) {
htab = mudstate.vattr_name_htab.entry[i];
while (htab != NULL) {
each += sizeof(HASHENT);
each += strlen(htab->target.s) + 1;
each += sizeof(VATTR);
htab = htab->next;
}
}
raw_notify(player,
tprintf("Vattr name htab : %12.2fk", each / 1024));
total += each;
/* Calculate size of attr name hashtable */
each = 0;
each += sizeof(HASHENT *) * mudstate.attr_name_htab.hashsize;
for(i = 0; i < mudstate.attr_name_htab.hashsize; i++) {
htab = mudstate.attr_name_htab.entry[i];
while (htab != NULL) {
each += sizeof(HASHENT);
each += strlen(htab->target.s) + 1;
if (!(htab->flags & HASH_ALIAS)) {
attr = (ATTR *)htab->data;
-52-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797

Saturday, June 16, 2012 11:51 PM

each += sizeof(ATTR);
each += strlen(attr->name) + 1;

}
htab = htab->next;

}
raw_notify(player,
tprintf("Attr name htab
total += each;

: %12.2fk", each / 1024));

/* Calculate the size of anum_table */


each = sizeof(ATTR *) * anum_alc_top;
raw_notify(player,
tprintf("Attr num table
: %12.2fk", each / 1024));
total += each;
/* --- After this point, we only report if it's non-zero. */
/* Calculate size of object stacks */
each = 0;
for (stack = (OBJSTACK *)hash_firstentry((HASHTAB *)&mudstate.objstack_htab);
stack != NULL;
stack = (OBJSTACK *)hash_nextentry((HASHTAB *)&mudstate.objstack_htab)) {
each += sizeof(OBJSTACK);
each += strlen(stack->data) + 1;
}
if (each) {
raw_notify(player,
tprintf("Object stacks
: %12.2fk", each / 1024));
}
total += each;
/* Calculate the size of xvars. */
each = 0;
for (xvar = (VARENT *) hash_firstentry(&mudstate.vars_htab);
xvar != NULL;
xvar = (VARENT *) hash_nextentry(&mudstate.vars_htab)) {
each += sizeof(VARENT);
each += strlen(xvar->text) + 1;
}
if (each) {
raw_notify(player,
tprintf("X-Variables
: %12.2fk", each / 1024));
}
total += each;
/* Calculate the size of overhead associated with structures. */
each = 0;
for (this_struct = (STRUCTDEF *) hash_firstentry(&mudstate.structs_htab);
-53-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850

Saturday, June 16, 2012 11:51 PM

this_struct != NULL;
this_struct = (STRUCTDEF *) hash_nextentry(&mudstate.structs_htab)) {
each += sizeof(STRUCTDEF);
each += strlen(this_struct->s_name) + 1;
for (i = 0; i < this_struct->c_count; i++) {
each += strlen(this_struct->c_names[i]) + 1;
each += sizeof(COMPONENT);
each += strlen(this_struct->c_array[i]->def_val) + 1;
}

}
for (inst_ptr = (INSTANCE *) hash_firstentry(&mudstate.instance_htab);
inst_ptr != NULL;
inst_ptr = (INSTANCE *) hash_nextentry(&mudstate.instance_htab)) {
each += sizeof(INSTANCE);
}
if (each) {
raw_notify(player,
tprintf("Struct var defs : %12.2fk", each / 1024));
}
total += each;
/* Calculate the size of data associated with structures. */

each = 0;
for (data_ptr = (STRUCTDATA *) hash_firstentry(&mudstate.instdata_htab);
data_ptr != NULL;
data_ptr = (STRUCTDATA *) hash_nextentry(&mudstate.instdata_htab)) {
each += sizeof(STRUCTDATA);
if (data_ptr->text) {
each += strlen(data_ptr->text) + 1;
}
}
if (each) {
raw_notify(player,
tprintf("Struct var data : %12.2fk", each / 1024));
}
total += each;
/* Report end total. */

raw_notify(player,
tprintf("\r\nTotal

: %12.2fk" , total / 1024));

/* --------------------------------------------------------------------------* do_list: List information stored in internal structures.


*/
#define
#define
#define
#define
#define

LIST_ATTRIBUTES 1
LIST_COMMANDS
2
LIST_COSTS 3
LIST_FLAGS 4
LIST_FUNCTIONS 5
-54-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903

#define LIST_GLOBALS
#define LIST_ALLOCATOR
#define LIST_LOGGING
#define LIST_DF_FLAGS
#define LIST_PERMS 10
#define LIST_ATTRPERMS
#define LIST_OPTIONS
#define LIST_HASHSTATS
#define LIST_BUFTRACE
#define LIST_CONF_PERMS
#define LIST_SITEINFO
#define LIST_POWERS 17
#define LIST_SWITCHES
#define LIST_VATTRS 19
#define LIST_DB_STATS
#define LIST_PROCESS
#define LIST_BADNAMES
#define LIST_CACHEOBJS
#define LIST_TEXTFILES
#define LIST_PARAMS 25
#define LIST_CF_RPERMS
#define LIST_ATTRTYPES
#define LIST_FUNCPERMS
#define LIST_MEMORY 29
#define LIST_CACHEATTRS
#define LIST_RAWMEM 31
/* *INDENT-OFF* */

Saturday, June 16, 2012 11:51 PM

6
7
8
9
11
12
13
14
15
16
18
20
21
22
23
24

/* GAC 4/6/92 */

26
27
28
30

NAMETAB list_names[] = {
{(char *)"allocations",
2, CA_WIZARD, LIST_ALLOCATOR},
{(char *)"attr_permissions",
6, CA_WIZARD, LIST_ATTRPERMS},
{(char *)"attr_types",
6, CA_PUBLIC, LIST_ATTRTYPES},
{(char *)"attributes",
2, CA_PUBLIC, LIST_ATTRIBUTES},
{(char *)"bad_names",
2, CA_WIZARD, LIST_BADNAMES},
{(char *)"buffers",
2, CA_WIZARD, LIST_BUFTRACE},
{(char *)"cache",
2, CA_WIZARD, LIST_CACHEOBJS},
{(char *)"cache_attrs",
6, CA_WIZARD, LIST_CACHEATTRS},
{(char *)"commands",
3, CA_PUBLIC, LIST_COMMANDS},
{(char *)"config_permissions", 8, CA_GOD,
LIST_CONF_PERMS},
{(char *)"config_read_perms",
4, CA_PUBLIC, LIST_CF_RPERMS},
{(char *)"costs",
3, CA_PUBLIC, LIST_COSTS},
{(char *)"db_stats",
2, CA_WIZARD, LIST_DB_STATS},
{(char *)"default_flags",
1, CA_PUBLIC, LIST_DF_FLAGS},
{(char *)"flags",
2, CA_PUBLIC, LIST_FLAGS},
{(char *)"func_permissions",
5, CA_WIZARD, LIST_FUNCPERMS},
{(char *)"functions",
2, CA_PUBLIC, LIST_FUNCTIONS},
{(char *)"globals",
1, CA_WIZARD, LIST_GLOBALS},
{(char *)"hashstats",
1, CA_WIZARD, LIST_HASHSTATS},
{(char *)"logging",
1, CA_GOD,
LIST_LOGGING},
{(char *)"memory",
1, CA_WIZARD, LIST_MEMORY},
{(char *)"options",
1, CA_PUBLIC, LIST_OPTIONS},
{(char *)"params",
2, CA_PUBLIC, LIST_PARAMS},
{(char *)"permissions",
2, CA_WIZARD, LIST_PERMS},
-55-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956

Saturday, June 16, 2012 11:51 PM

{(char *)"powers",
2, CA_WIZARD, LIST_POWERS},
{(char *)"process",
2, CA_WIZARD, LIST_PROCESS},
{(char *)"raw_memory",
1, CA_WIZARD, LIST_RAWMEM},
{(char *)"site_information",
2, CA_WIZARD, LIST_SITEINFO},
{(char *)"switches",
2, CA_PUBLIC, LIST_SWITCHES},
{(char *)"textfiles",
1, CA_WIZARD, LIST_TEXTFILES},
{(char *)"user_attributes", 1, CA_WIZARD, LIST_VATTRS},
{ NULL,
0, 0,
0}};
/* *INDENT-ON* */
extern NAMETAB enable_names[];
extern NAMETAB logoptions_nametab[];
extern NAMETAB logdata_nametab[];
void do_list(player, cause, extra, arg)
dbref player, cause;
int extra;
char *arg;
{
int flagvalue;
flagvalue = search_nametab(player, list_names, arg);
switch (flagvalue) {
case LIST_ALLOCATOR:
list_bufstats(player);
break;
case LIST_BUFTRACE:
list_buftrace(player);
break;
case LIST_ATTRIBUTES:
list_attrtable(player);
break;
case LIST_COMMANDS:
list_cmdtable(player);
break;
case LIST_SWITCHES:
list_cmdswitches(player);
break;
case LIST_COSTS:
list_costs(player);
break;
case LIST_OPTIONS:
list_options(player);
break;
case LIST_HASHSTATS:
list_hashstats(player);
break;
case LIST_SITEINFO:
list_siteinfo(player);
break;
case LIST_FLAGS:
display_flagtab(player);
-56-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009

Saturday, June 16, 2012 11:51 PM

break;
case LIST_FUNCPERMS:
list_funcaccess(player);
break;
case LIST_FUNCTIONS:
list_functable(player);
break;
case LIST_GLOBALS:
interp_nametab(player, enable_names, mudconf.control_flags,
(char *)"Global parameters:", (char *)"enabled",
(char *)"disabled");
break;
case LIST_DF_FLAGS:
list_df_flags(player);
break;
case LIST_PERMS:
list_cmdaccess(player);
break;
case LIST_CONF_PERMS:
list_cf_access(player);
break;
case LIST_CF_RPERMS:
list_cf_read_access(player);
break;
case LIST_POWERS:
display_powertab(player);
break;
case LIST_ATTRPERMS:
list_attraccess(player);
break;
case LIST_VATTRS:
list_vattrs(player);
break;
case LIST_LOGGING:
interp_nametab(player, logoptions_nametab, mudconf.log_options,
(char *)"Events Logged:", (char *)"enabled",
(char *)"disabled");
interp_nametab(player, logdata_nametab, mudconf.log_info,
(char *)"Information Logged:", (char *)"yes",
(char *)"no");
break;
case LIST_DB_STATS:
list_db_stats(player);
break;
case LIST_PROCESS:
list_process(player);
break;
case LIST_BADNAMES:
badname_list(player, "Disallowed names:");
break;
case LIST_CACHEOBJS:
list_cached_objs(player);
break;
-57-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.c

3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034

Saturday, June 16, 2012 11:51 PM

case LIST_TEXTFILES:
list_textfiles(player);
break;
case LIST_PARAMS:
list_params(player);
break;
case LIST_ATTRTYPES:
list_attrtypes(player);
break;
case LIST_MEMORY:
list_memory(player);
break;
case LIST_CACHEATTRS:
list_cached_attrs(player);
break;
case LIST_RAWMEM:
list_rawmemory(player);
break;
default:
display_nametab(player, list_names,
(char *)"Unknown option. Use one of:" , 1);
}

-58-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:15 PM

/* command.h - declarations used by the command processor */


/* $Id: command.h,v 1.45 2008/03/09 17:09:03 lwl Exp $ */
#include "copyright.h"
#ifndef __COMMAND_H
#define __COMMAND_H
#define CMD_NO_ARG(name) \
extern void FDECL(name, (dbref, dbref,
#define CMD_ONE_ARG(name) \
extern void FDECL(name, (dbref, dbref,
#define CMD_ONE_ARG_CMDARG(name) \
extern void FDECL(name, (dbref, dbref,
#define CMD_TWO_ARG(name) \
extern void FDECL(name, (dbref, dbref,
#define CMD_TWO_ARG_CMDARG(name) \
extern void FDECL(name, (dbref, dbref,
#define CMD_TWO_ARG_ARGV(name) \
extern void FDECL(name, (dbref, dbref,
#define CMD_TWO_ARG_ARGV_CMDARG(name) \
extern void FDECL(name, (dbref, dbref,

int))
int, char *))
int, char *, char *[], int))
int, char *, char *))
int, char *, char *, char*[], int))
int, char *, char *[], int))
int, char *, char *[], int, char*[], int))

/* Command function handlers */


CMD_ONE_ARG_CMDARG(do_apply_marked);
/* Apply command to marked objects */
CMD_TWO_ARG(do_admin);
/* Change config parameters */
CMD_TWO_ARG(do_alias);
/* Change the alias of something */
CMD_TWO_ARG(do_attribute);
/* Manage user-named attributes */
CMD_ONE_ARG(do_boot);
/* Force-disconnect a player */
CMD_TWO_ARG(do_chown);
/* Change object or attribute owner */
CMD_TWO_ARG(do_chownall);
/* Give away all of someone's objs */
CMD_TWO_ARG(do_chzone);
/* Change an object's zone. */
CMD_TWO_ARG(do_clone);
/* Create a copy of an object */
CMD_TWO_ARG(do_colormap);
/* Remap ANSI colors in output */
CMD_NO_ARG(do_comment);
/* Ignore argument and do nothing */
CMD_TWO_ARG_ARGV(do_cpattr);
/* Copy attributes */
CMD_TWO_ARG(do_create);
/* Create a new object */
CMD_TWO_ARG(do_cron);
/* Add a new cron entry */
CMD_ONE_ARG(do_crondel);
/* Delete cron entries */
CMD_ONE_ARG(do_crontab);
/* List out cron entries */
CMD_ONE_ARG(do_cut);
/* Truncate contents or exits list */
CMD_NO_ARG(do_dbck);
/* Consistency check */
CMD_TWO_ARG(do_decomp);
/* Show commands to recreate obj */
CMD_ONE_ARG(do_destroy);
/* Destroy an object */
CMD_TWO_ARG_ARGV(do_dig);
/* Dig a new room */
CMD_ONE_ARG(do_doing);
/* Set doing string in WHO report */
CMD_TWO_ARG_CMDARG(do_dolist);
/* Iterate command on list members */
CMD_ONE_ARG(do_drop);
/* Drop an object */
CMD_NO_ARG(do_dump);
/* Dump the database */
CMD_TWO_ARG_ARGV(do_edit);
/* Edit one or more attributes */
CMD_TWO_ARG_CMDARG(do_end);
/* End action list on a conditional */
CMD_ONE_ARG(do_enter);
/* Enter an object */
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:15 PM

CMD_ONE_ARG(do_entrances);
/* List exits and links to loc */
CMD_ONE_ARG(do_eval);
/* Like @@ comment, but takes an arg */
CMD_ONE_ARG(do_examine);
/* Examine an object */
CMD_ONE_ARG(do_find);
/* Search for name in database */
CMD_TWO_ARG(do_fixdb);
/* Database repair functions */
CMD_ONE_ARG(do_floaters);
/* Display floating rooms */
CMD_TWO_ARG_CMDARG(do_force);
/* Force someone to do something */
CMD_ONE_ARG_CMDARG(do_force_prefixed); /* #<num> <cmd> variant of FORCE */
CMD_ONE_ARG(do_freelist);
/* Move obj to head of freelist */
CMD_TWO_ARG(do_function);
/* Make user-def global function */
CMD_ONE_ARG(do_get);
/* Get an object */
CMD_TWO_ARG(do_give);
/* Give something away */
CMD_ONE_ARG(do_global);
/* Enable/disable global flags */
CMD_ONE_ARG(do_halt);
/* Remove commands from the queue */
CMD_NO_ARG(do_hashresize);
/* Resize the hash tables */
CMD_TWO_ARG(do_hook);
/* Command hooks */
CMD_ONE_ARG(do_help);
/* Print info from help files */
CMD_NO_ARG(do_inventory);
/* Print what I am carrying */
CMD_TWO_ARG(do_prog);
/* Interactive input */
CMD_ONE_ARG(do_quitprog);
/* Quits @prog */
CMD_TWO_ARG(do_kill);
/* Kill something */
CMD_ONE_ARG(do_last);
/* Get recent login info */
CMD_NO_ARG(do_leave);
/* Leave the current object */
CMD_TWO_ARG(do_link);
/* Set home, dropto, or dest */
CMD_ONE_ARG(do_list);
/* List contents of internal tables */
CMD_ONE_ARG(do_list_file);
/* List contents of message files */
CMD_TWO_ARG(do_lock);
/* Set a lock on an object */
CMD_ONE_ARG(do_look);
/* Look here or at something */
CMD_NO_ARG(do_markall);
/* Mark or unmark all objects */
CMD_ONE_ARG(do_motd);
/* Set/list MOTD messages */
CMD_ONE_ARG(do_move);
/* Move about using exits */
CMD_TWO_ARG_ARGV(do_mvattr);
/* Move attributes on object */
CMD_TWO_ARG(do_name);
/* Change the name of something */
CMD_TWO_ARG(do_newpassword);
/* Change passwords */
CMD_TWO_ARG(do_notify);
/* Notify or drain semaphore */
CMD_TWO_ARG_ARGV(do_open);
/* Open an exit */
CMD_TWO_ARG(do_page);
/* Send message to faraway player */
CMD_TWO_ARG(do_parent);
/* Set parent field */
CMD_TWO_ARG(do_password);
/* Change my password */
CMD_TWO_ARG(do_pcreate);
/* Create new characters */
CMD_TWO_ARG(do_pemit);
/* Messages to specific player */
CMD_ONE_ARG(do_poor);
/* Reduce wealth of all players */
CMD_TWO_ARG(do_power);
/* Sets powers */
CMD_ONE_ARG(do_ps);
/* List contents of queue */
CMD_ONE_ARG(do_queue);
/* Force queue processing */
CMD_TWO_ARG(do_quota);
/* Set or display quotas */
CMD_NO_ARG(do_readcache);
/* Reread text file cache */
CMD_TWO_ARG(do_redirect);
/* Redirect output */
CMD_TWO_ARG(do_reference);
/* Manipulate nrefs */
CMD_ONE_ARG(do_reply_page);
/* Reply to a page */
CMD_NO_ARG(do_restart);
/* Restart the game. */
CMD_ONE_ARG(do_say);
/* Messages to all */
CMD_NO_ARG(do_score);
/* Display my wealth */
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:15 PM

CMD_ONE_ARG(do_search);
/* Search for objs matching criteria */
CMD_TWO_ARG(do_set);
/* Set flags or attributes */
CMD_TWO_ARG(do_setattr);
/* Set object attribute */
CMD_TWO_ARG(do_setvattr);
/* Set variable attribute */
CMD_ONE_ARG(do_shutdown);
/* Stop the game */
CMD_ONE_ARG(do_stats);
/* Display object type breakdown */
CMD_ONE_ARG(do_sweep);
/* Check for listeners */
CMD_TWO_ARG_ARGV_CMDARG(do_switch); /* Execute cmd based on match */
CMD_TWO_ARG(do_teleport);
/* Teleport elsewhere */
CMD_ONE_ARG(do_think);
/* Think command */
CMD_NO_ARG(do_timecheck);
/* Check time used by objects */
CMD_ONE_ARG(do_timewarp);
/* Warp various timers */
CMD_TWO_ARG(do_toad);
/* Turn a tinyjerk into a tinytoad */
CMD_TWO_ARG_ARGV(do_trigger);
/* Trigger an attribute */
CMD_ONE_ARG(do_unlock);
/* Remove a lock from an object */
CMD_ONE_ARG(do_unlink);
/* Unlink exit or remove dropto */
CMD_ONE_ARG(do_use);
/* Use object */
CMD_NO_ARG(do_version);
/* List MUSH version number */
CMD_TWO_ARG_ARGV(do_verb);
/* Execute a user-created verb */
CMD_TWO_ARG_CMDARG(do_wait);
/* Perform command after a wait */
CMD_ONE_ARG(do_wipe);
/* Mass-remove attrs from obj */
CMD_TWO_ARG(do_addcommand);
/* Add or replace a global command */
CMD_TWO_ARG(do_delcommand);
/* Delete an added global command */
CMD_ONE_ARG(do_listcommands);
/* List added global commands */
CMD_TWO_ARG(do_logwrite);
/* Write to the logfile */
CMD_NO_ARG(do_logrotate);
/* Rotate the logfile */
CMD_NO_ARG(do_sql_connect);
/* Create a SQL db connection */
CMD_ONE_ARG(do_sql);
/* Execute a SQL command */
typedef struct addedentry ADDENT;
struct addedentry {
dbref
thing;
int atr;
char
*name;
struct addedentry *next;
};
typedef struct cmdentry CMDENT;
struct cmdentry {
char
*cmdname;
NAMETAB *switches;
int perms;
int extra;
int callseq;
/* int (*modperms)(); */
HOOKENT *userperms;
HOOKENT *pre_hook;
HOOKENT *post_hook;
union {
void
(*handler)();
ADDENT *added;
} info;
};
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

Saturday, June 16, 2012 11:15 PM

/* Command handler call conventions */


#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

CS_NO_ARGS 0x00000 /* No arguments */


CS_ONE_ARG 0x00001 /* One argument */
CS_TWO_ARG 0x00002 /* Two arguments */
CS_NARG_MASK
0x00003 /* Argument count mask */
CS_ARGV
0x00004 /* ARG2 is in ARGV form */
CS_INTERP
0x00010 /* Interpret ARG2 if 2 args, ARG1 if 1 */
CS_NOINTERP 0x00020 /* Never interp ARG2 if 2 or ARG1 if 1 */
CS_CAUSE
0x00040 /* Pass cause to old command handler */
CS_UNPARSE 0x00080 /* Pass unparsed cmd to old-style handler */
CS_CMDARG
0x00100 /* Pass in given command args */
CS_STRIP
0x00200 /* Strip braces even when not interpreting */
CS_STRIP_AROUND 0x00400 /* Strip braces around entire string only */
CS_ADDED
0x00800 /* Command has been added by @addcommand */
CS_LEADIN
0x01000 /* Command is a single-letter lead-in */
CS_PRESERVE 0x02000 /* For hooks, preserve global registers */
CS_NOSQUISH 0x04000 /* Do not space-compress */
CS_FUNCTION 0x08000 /* Can call with command() */
CS_ACTOR
0x10000 /* @addcommand executed by player, not obj */
CS_PRIVATE 0x20000 /* For hooks, use private global registers */

/* Command permission flags */


#define
#define
#define
#define
#define
#define
#define
#define
#define

CA_PUBLIC
CA_GOD
CA_WIZARD
CA_BUILDER
CA_IMMORTAL
CA_STAFF
CA_HEAD
CA_SQL_OK
CA_ADMIN

0x00000000
0x00000001
0x00000002
0x00000004
0x00000008
0x00000010
0x00000020
0x00000040
0x00000080

/*
/*
/*
/*
/*
/*
/*
/*
/*

No access restrictions */
GOD only... */
Wizards only */
Builders only */
Immortals only */
Must have STAFF flag */
Must have HEAD flag */
Must have SQL_OK power */
Wizard or royal */

#define CA_ISPRIV_MASK
(CA_GOD|CA_WIZARD|CA_BUILDER|CA_IMMORTAL|CA_STAFF|CA_HEAD|CA_ADMIN|CA_SQL_OK)
#define
#define
#define
#define
#define

CA_NO_HAVEN 0x00000100 /*
CA_NO_ROBOT 0x00000200 /*
CA_NO_SLAVE 0x00000400 /*
CA_NO_SUSPECT
0x00000800
CA_NO_GUEST 0x00001000 /*

#define CA_ISNOT_MASK
#define
#define
#define
#define
#define
#define
#define

CA_MARKER0
CA_MARKER1
CA_MARKER2
CA_MARKER3
CA_MARKER4
CA_MARKER5
CA_MARKER6

Not
Not
Not
/*
Not

by HAVEN players */
by ROBOT players */
by SLAVE players */
Not by SUSPECT players */
by GUEST players */

(CA_NO_HAVEN|CA_NO_ROBOT|CA_NO_SLAVE|CA_NO_SUSPECT|CA_NO_GUEST)

0x00002000
0x00004000
0x00008000
0x00010000
0x00020000
0x00040000
0x00080000
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\command.h

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

#define CA_MARKER7
#define CA_MARKER8
#define CA_MARKER9

Saturday, June 16, 2012 11:15 PM

0x00100000
0x00200000
0x00400000

#define CA_MARKER_MASK
(CA_MARKER0|CA_MARKER1|CA_MARKER2|CA_MARKER3|CA_MARKER4|CA_MARKER5|CA_MARKER6|CA_MARKER7|
CA_MARKER8|CA_MARKER9)
#define
#define
#define
#define
#define

CA_GBL_BUILD
0x00800000 /* Requires the global BUILDING flag */
CA_GBL_INTERP
0x01000000 /* Requires the global INTERP flag */
CA_DISABLED 0x02000000 /* Command completely disabled */
CA_STATIC
0x04000000 /* Cannot be changed at runtime */
CA_NO_DECOMP
0x08000000 /* Don't include in @decompile */

#define
#define
#define
#define

CA_LOCATION
CA_CONTENTS
CA_PLAYER
CF_DARK

0x10000000
0x20000000
0x40000000
0x80000000

/*
/*
/*
/*

Invoker
Invoker
Invoker
Command

must have location */


must have contents */
must be a player */
doesn't show up in list */

#define SW_MULTIPLE 0x80000000 /* This sw may be spec'd w/others */


#define SW_GOT_UNIQUE
0x40000000 /* Already have a unique option */
#define SW_NOEVAL
0x20000000
/* Don't parse args before calling
* handler
*/
/* (typically via a switch alias) */
/*
#define Check_Cmd_Access(p,c,a,n) \
(check_access(p,(c)->perms) && \
(!((c)->xperms) || check_mod_access(p,(c)->xperms)) && \
(!((c)->userperms) || check_userdef_access(p,(c)->userperms,a,n) || God(p)))
*/
#define Check_Cmd_Access(p,c,a,n) \
(check_access(p,(c)->perms) && \
(!((c)->userperms) || check_userdef_access(p,(c)->userperms,a,n) || God(p)))
extern int FDECL(check_userdef_access, (dbref, HOOKENT *, char *[], int));
extern char *
FDECL(process_command, (dbref, dbref, int, char *, char *[], int));
#endif /* __COMMAND_H */

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\compat.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:51 PM

/* compat.c - functions that we need to provide because they are missing */


/* $Id: compat.c,v 1.5 2000/05/29 22:20:10 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#ifdef NEED_TIMELOCAL
#define altzone

((time_t)(timezone + 3600))

/*
* CAUTION: side effects
*/
#define is_leap(x) (((!((x)%4)&&(x)%100)||!(((x)+1900)%400))?1:0)
static int yday_size[2][12] =
{
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
};
static int mon_size[2][12] =
{
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
/* e.g: normalize(&tm_secs, &tm_hour, 60); */
static void normalize(x, y, f)
int *x, *y, f;
{
if (*x >= f) {
*y += *x / f;
*x %= f;
}
/* can't rely on modulus for negative numbers */

while (*x < 0) {


*x += f;
(*y)--;
}

time_t timelocal(tp)
struct tm *tp;
{
long unsigned k;
struct tm tm;
time_t t, t1;
tzset();

/* set up time zone */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\compat.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:51 PM

/* normalize the time */


normalize(&tp->tm_sec, &tp->tm_min, 60);
normalize(&tp->tm_min, &tp->tm_hour, 60);
normalize(&tp->tm_hour, &tp->tm_mday, 24);
/* normalize the month first */
normalize(&tp->tm_mon, &tp->tm_year, 12);
/* days to months a little tricky */
while (tp->tm_mday < 1) {
if (--tp->tm_mon < 0) {
tp->tm_year--;
tp->tm_mon += 12;
}
tp->tm_mday += mon_size[is_leap(tp->tm_year)][tp->tm_mon];
}
while (tp->tm_mday > (k = mon_size[is_leap(tp->tm_year)][tp->tm_mon])) {
tp->tm_mday -= k;

if (++tp->tm_mon > 12) {


tp->tm_year++;
tp->tm_mon -= 12;
}

k = tp->tm_year / 4;
/* number of 4 year groups */
t = (k * 1461) - 1; /* number of days */
k = tp->tm_year % 4;
/* number of years beyond group */
t += (k * 365);
/* add number of days */
if (k)
/* if not group break year */
t++;
/* add one day */
/*
* Since the epoch starts at Jan 1/70, we have to subtract the of
* days from Jan 1/00. This is actually 25567 days.
* See below for the explanation of the discrepancy
*/
t -= 25568;
/* t = # days to 00:00:00 Jan 1/70 */
t += yday_size[is_leap(tp->tm_year)][tp->tm_mon];
/* Add the number of days in month. Note that we should really
* subtract 1 from the day first but we effectively did this above
* when we subtracted an extra day (25568 instead of * * 25567)
*/
t += tp->tm_mday;

/* # days to given day at 00:00:00 */

/* now add in the number of seconds in the day */


t = (t * 24) + tp->tm_hour;
t = (t * 60) + tp->tm_min;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\compat.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

t = (t * 60) + tp->tm_sec;

Saturday, June 16, 2012 11:51 PM

/* total number of seconds */

/* if caller thinks he/she knows what time zone then believe them */
if (tp->tm_isdst == 0)
t += timezone;
else if (tp->tm_isdst > 0)
t += altzone;
else {
/* we have to figure it out, guess dst first */
t1 = t + altzone;
tm = *localtime(&t1);
/* see if the guess matches the reality */
if (tm.tm_hour == tp->tm_hour && tm.tm_min == tp->tm_min)
t = t1;
else {
#ifdef CHECK_INVALID
/* if CHECK_INVALID is defined then we attempt to
* check for the invalid time case e.g. a time of
* 0230h on the first sunday in April will return -1
* personally I don't think this is polite behaviour
*/
t1 = t + timezone;
tm = *localtime(&t1);
if ((tm.tm_hour == tp->tm_hour) &&
(tm.tm_min == tp->tm_min))
t = t1;
else
return (-1);

#else
#endif
}

t += timezone;
}

*tp = *localtime(&t);
return (t);

/* set other fields in structure */

#endif /* NEED_TIMELOCAL */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:50 PM

/* conf.c - configuration functions and defaults */


/* $Id: conf.c,v 1.197 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include

"command.h"
/* required by code */
"attrs.h" /* required by code */
"match.h" /* required by code */
"ansi.h"
/* required by code */

/* Some systems are lame, and inet_addr() claims to return -1 on failure,


* despite the fact that it returns an unsigned long. (It's not really a -1,
* obviously.) Better-behaved systems use INADDR_NONE.
*/
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
/*
* --------------------------------------------------------------------------* * External symbols.
*/
CONFDATA mudconf;
STATEDATA mudstate;
extern
extern
extern
extern
extern
extern
extern
extern

NAMETAB logdata_nametab[];
NAMETAB logoptions_nametab[];
NAMETAB access_nametab[];
NAMETAB attraccess_nametab[];
NAMETAB list_names[];
NAMETAB sigactions_nametab[];
CONF conftable[];
LOGFILETAB logfds_table[];

/* --------------------------------------------------------------------------* cf_init: Initialize mudconf to default values.


*/
void NDECL(cf_init)
{
char *s;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:50 PM

s = XMALLOC(MBUF_SIZE, "cf_init");
mudconf.status_file = XSTRDUP("shutdown.status", "cf_string");
mudstate.modules_list = NULL;
mudstate.modloaded[0] = '\0';
mudconf.port = 6250;
mudconf.conc_port = 6251;
mudconf.init_size = 1000;
mudconf.use_global_aconn = 1;
mudconf.global_aconn_uselocks = 0;
mudconf.guest_char = NOTHING;
mudconf.guest_nuker = GOD;
mudconf.number_guests = 30;
mudconf.guest_basename = XSTRDUP("Guest", "cf_string");
mudconf.guest_password = XSTRDUP("guest", "cf_string");
mudconf.guest_prefixes = XSTRDUP("", "cf_string");
mudconf.guest_suffixes = XSTRDUP("", "cf_string");
sprintf(s, "%s/guest.txt", mudconf.txthome);
mudconf.guest_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/connect.txt", mudconf.txthome);
mudconf.conn_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/register.txt", mudconf.txthome);
mudconf.creg_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/create_reg.txt", mudconf.txthome);
mudconf.regf_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/motd.txt", mudconf.txthome);
mudconf.motd_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/wizmotd.txt", mudconf.txthome);
mudconf.wizmotd_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/quit.txt", mudconf.txthome);
mudconf.quit_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/down.txt", mudconf.txthome);
mudconf.down_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/full.txt", mudconf.txthome);
mudconf.full_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/badsite.txt", mudconf.txthome);
mudconf.site_file = XSTRDUP(s, "cf_string");
sprintf(s, "%s/newuser.txt", mudconf.txthome);
mudconf.crea_file = XSTRDUP(s, "cf_string");
#ifdef PUEBLO_SUPPORT
sprintf(s, "%s/htmlconn.txt", mudconf.txthome);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:50 PM

mudconf.htmlconn_file = XSTRDUP(s, "cf_string");


#endif
mudconf.motd_msg = XSTRDUP("", "cf_string");
mudconf.wizmotd_msg = XSTRDUP("", "cf_string");
mudconf.downmotd_msg = XSTRDUP("", "cf_string");
mudconf.fullmotd_msg = XSTRDUP("", "cf_string");
mudconf.dump_msg = XSTRDUP("", "cf_string");
mudconf.postdump_msg = XSTRDUP("", "cf_string");
mudconf.fixed_home_msg = XSTRDUP("", "cf_string");
mudconf.fixed_tel_msg = XSTRDUP("", "cf_string");
mudconf.huh_msg = XSTRDUP("Huh? (Type \"help\" for help.)" , "cf_string");
#ifdef PUEBLO_SUPPORT
mudconf.pueblo_msg = XSTRDUP("</xch_mudtext><img xch_mode=html><tt>" , "cf_string");
#endif
mudconf.sql_host = XSTRDUP("127.0.0.1", "cf_string");
mudconf.sql_db = XSTRDUP("", "cf_string");
mudconf.sql_username = XSTRDUP("", "cf_string");
mudconf.sql_password = XSTRDUP("", "cf_string");
mudconf.sql_reconnect = 0;
mudconf.indent_desc = 0;
mudconf.name_spaces = 1;
mudconf.fork_dump = 0;
mudconf.fork_vfork = 0;
mudconf.dbopt_interval = 0;
#ifdef PUEBLO_SUPPORT
mudconf.have_pueblo = 1;
#else
mudconf.have_pueblo = 0;
#endif
mudconf.have_zones = 1;
mudconf.paranoid_alloc = 0;
mudconf.sig_action = SA_DFLT;
mudconf.max_players = -1;
mudconf.dump_interval = 3600;
mudconf.check_interval = 600;
mudconf.events_daily_hour = 7;
mudconf.dump_offset = 0;
mudconf.check_offset = 300;
mudconf.idle_timeout = 3600;
mudconf.conn_timeout = 120;
mudconf.idle_interval = 60;
mudconf.retry_limit = 3;
mudconf.output_limit = 16384;
mudconf.paycheck = 0;
mudconf.paystart = 0;
mudconf.paylimit = 10000;
mudconf.start_quota = mudconf.start_room_quota =
mudconf.start_exit_quota = mudconf.start_thing_quota =
mudconf.start_player_quota = 20;
mudconf.site_chars = 25;
mudconf.payfind = 0;
mudconf.digcost = 10;
mudconf.linkcost = 1;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:50 PM

mudconf.opencost = 1;
mudconf.createmin = 10;
mudconf.createmax = 505;
mudconf.killmin = 10;
mudconf.killmax = 100;
mudconf.killguarantee = 100;
mudconf.robotcost = 1000;
mudconf.pagecost = 10;
mudconf.searchcost = 100;
mudconf.waitcost = 10;
mudconf.machinecost = 64;
mudconf.building_limit = 50000;
mudconf.exit_quota = 1;
mudconf.player_quota = 1;
mudconf.room_quota = 1;
mudconf.thing_quota = 1;
mudconf.queuemax = 100;
mudconf.queue_chunk = 10;
mudconf.active_q_chunk = 10;
mudconf.sacfactor = 5;
mudconf.sacadjust = -1;
mudconf.use_hostname = 1;
mudconf.quotas = 0;
mudconf.typed_quotas = 0;
mudconf.ex_flags = 1;
mudconf.robot_speak = 1;
mudconf.clone_copy_cost = 0;
mudconf.pub_flags = 1;
mudconf.quiet_look = 1;
mudconf.exam_public = 1;
mudconf.read_rem_desc = 0;
mudconf.read_rem_name = 0;
mudconf.sweep_dark = 0;
mudconf.player_listen = 0;
mudconf.quiet_whisper = 1;
mudconf.dark_sleepers = 1;
mudconf.see_own_dark = 1;
mudconf.idle_wiz_dark = 0;
mudconf.visible_wizzes = 0;
mudconf.pemit_players = 0;
mudconf.pemit_any = 0;
mudconf.addcmd_match_blindly = 1;
mudconf.addcmd_obey_stop = 0;
mudconf.addcmd_obey_uselocks = 0;
mudconf.lattr_oldstyle = 0;
mudconf.bools_oldstyle = 0;
mudconf.match_mine = 0;
mudconf.match_mine_pl = 0;
mudconf.switch_df_all = 1;
mudconf.fascist_objeval = 0;
mudconf.fascist_tport = 0;
mudconf.terse_look = 1;
mudconf.terse_contents = 1;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:50 PM

mudconf.terse_exits = 1;
mudconf.terse_movemsg = 1;
mudconf.trace_topdown = 1;
mudconf.trace_limit = 200;
mudconf.safe_unowned = 0;
mudconf.wiz_obey_linklock = 0;
mudconf.local_masters = 1;
mudconf.match_zone_parents = 1;
mudconf.req_cmds_flag = 1;
mudconf.ansi_colors = 1;
mudconf.safer_passwords = 0;
mudconf.instant_recycle = 1;
mudconf.dark_actions = 0;
mudconf.no_ambiguous_match = 0;
mudconf.exit_calls_move = 0;
mudconf.move_match_more = 0;
mudconf.autozone = 1;
mudconf.page_req_equals = 0;
mudconf.comma_say = 0;
mudconf.you_say = 1;
mudconf.c_cmd_subst = 1;
mudconf.register_limit = 50;
/* -- ??? Running SC on a non-SC DB may cause problems */
mudconf.space_compress = 1;
mudconf.start_room = 0;
mudconf.guest_start_room = NOTHING; /* default, use start_room */
mudconf.start_home = NOTHING;
mudconf.default_home = NOTHING;
mudconf.master_room = NOTHING;
mudconf.player_proto = NOTHING;
mudconf.room_proto = NOTHING;
mudconf.exit_proto = NOTHING;
mudconf.thing_proto = NOTHING;
mudconf.player_defobj = NOTHING;
mudconf.room_defobj = NOTHING;
mudconf.thing_defobj = NOTHING;
mudconf.exit_defobj = NOTHING;
mudconf.player_parent = NOTHING;
mudconf.room_parent = NOTHING;
mudconf.exit_parent = NOTHING;
mudconf.thing_parent = NOTHING;
mudconf.player_flags.word1 = 0;
mudconf.player_flags.word2 = 0;
mudconf.player_flags.word3 = 0;
mudconf.room_flags.word1 = 0;
mudconf.room_flags.word2 = 0;
mudconf.room_flags.word3 = 0;
mudconf.exit_flags.word1 = 0;
mudconf.exit_flags.word2 = 0;
mudconf.exit_flags.word3 = 0;
mudconf.thing_flags.word1 = 0;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:50 PM

mudconf.thing_flags.word2 = 0;
mudconf.thing_flags.word3 = 0;
mudconf.robot_flags.word1 = ROBOT;
mudconf.robot_flags.word2 = 0;
mudconf.robot_flags.word3 = 0;
mudconf.stripped_flags.word1 = IMMORTAL | INHERIT | ROYALTY | WIZARD;
mudconf.stripped_flags.word2 = BLIND | CONNECTED | GAGGED |
HEAD_FLAG | SLAVE | STAFF | STOP_MATCH | SUSPECT | UNINSPECTED;
mudconf.stripped_flags.word3 = 0;
mudconf.vattr_flags = 0;
mudconf.vattr_flag_list = NULL;
mudconf.mud_name = XSTRDUP("TinyMUSH", "cf_string");
mudconf.mud_shortname = XSTRDUP("", "cf_string");
mudconf.one_coin = XSTRDUP("penny", "cf_string");
mudconf.many_coins = XSTRDUP("pennies", "cf_string");
mudconf.struct_dstr = XSTRDUP("\r\n", "cf_string");
mudconf.timeslice = 1000;
mudconf.cmd_quota_max = 100;
mudconf.cmd_quota_incr = 1;
#ifdef NO_LAG_CHECK
mudconf.lag_check = 0;
#else
mudconf.lag_check = 1;
#endif
mudconf.max_cmdsecs = 120;
mudconf.control_flags = 0xffffffff; /* Everything for now... */
mudconf.control_flags &= ~CF_GODMONITOR; /* Except for monitoring... */
mudconf.log_options = LOG_ALWAYS | LOG_BUGS | LOG_SECURITY |
LOG_NET | LOG_LOGIN | LOG_DBSAVES | LOG_CONFIGMODS |
LOG_SHOUTS | LOG_STARTUP | LOG_WIZARD |
LOG_PROBLEMS | LOG_PCREATES | LOG_TIMEUSE | LOG_LOCAL;
mudconf.log_info = LOGOPT_TIMESTAMP | LOGOPT_LOC;
mudconf.log_diversion = 0;
mudconf.markdata[0] = 0x01;
mudconf.markdata[1] = 0x02;
mudconf.markdata[2] = 0x04;
mudconf.markdata[3] = 0x08;
mudconf.markdata[4] = 0x10;
mudconf.markdata[5] = 0x20;
mudconf.markdata[6] = 0x40;
mudconf.markdata[7] = 0x80;
mudconf.wild_times_lim = 25000;
mudconf.cmd_nest_lim = 50;
mudconf.cmd_invk_lim = 2500;
mudconf.func_nest_lim = 50;
mudconf.func_invk_lim = 2500;
mudconf.func_cpu_lim_secs = 60;
mudconf.func_cpu_lim = 60 * CLOCKS_PER_SEC;
mudconf.ntfy_nest_lim = 20;
mudconf.fwdlist_lim = 100;
mudconf.propdir_lim = 10;
mudconf.lock_nest_lim = 20;
mudconf.parent_nest_lim = 10;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:50 PM

mudconf.zone_nest_lim = 20;
mudconf.numvars_lim = 50;
mudconf.stack_lim = 50;
mudconf.struct_lim = 100;
mudconf.instance_lim = 100;
mudconf.max_player_aliases = 10;
mudconf.cache_width = CACHE_WIDTH;
mudconf.cache_size = CACHE_SIZE;
mudstate.initializing = 0;
mudstate.loading_db = 0;
mudstate.panicking = 0;
mudstate.standalone = 0;
mudstate.dumping = 0;
mudstate.dumper = 0;
mudstate.logging = 0;
mudstate.epoch = 0;
mudstate.generation = 0;
mudstate.reboot_nums = 0;
mudstate.mudlognum = 0;
mudstate.helpfiles = 0;
mudstate.hfiletab = NULL;
mudstate.hfiletab_size = 0;
mudstate.hfile_hashes = NULL;
mudstate.curr_player = NOTHING;
mudstate.curr_enactor = NOTHING;
mudstate.curr_cmd = (char *) "< none >";
mudstate.shutdown_flag = 0;
mudstate.flatfile_flag = 0;
mudstate.attr_next = A_USER_START;
mudstate.debug_cmd = (char *)"< init >";
StringCopy(mudstate.doing_hdr, "Doing");
mudstate.access_list = NULL;
mudstate.suspect_list = NULL;
mudstate.qfirst = NULL;
mudstate.qlast = NULL;
mudstate.qlfirst = NULL;
mudstate.qllast = NULL;
mudstate.qwait = NULL;
mudstate.qsemfirst = NULL;
mudstate.qsemlast = NULL;
mudstate.badname_head = NULL;
mudstate.mstat_ixrss[0] = 0;
mudstate.mstat_ixrss[1] = 0;
mudstate.mstat_idrss[0] = 0;
mudstate.mstat_idrss[1] = 0;
mudstate.mstat_isrss[0] = 0;
mudstate.mstat_isrss[1] = 0;
mudstate.mstat_secs[0] = 0;
mudstate.mstat_secs[1] = 0;
mudstate.mstat_curr = 0;
mudstate.iter_alist.data = NULL;
mudstate.iter_alist.len = 0;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:50 PM

mudstate.iter_alist.next = NULL;
mudstate.mod_alist = NULL;
mudstate.mod_size = 0;
mudstate.mod_al_id = NOTHING;
mudstate.olist = NULL;
mudstate.min_size = 0;
mudstate.db_top = 0;
mudstate.db_size = 0;
mudstate.moduletype_top = DBTYPE_RESERVED;
mudstate.freelist = NOTHING;
mudstate.markbits = NULL;
mudstate.sql_socket = -1;
mudstate.cmd_nest_lev = 0;
mudstate.cmd_invk_ctr = 0;
mudstate.func_nest_lev = 0;
mudstate.func_invk_ctr = 0;
mudstate.wild_times_lev = 0;
mudstate.cputime_base = clock();
mudstate.ntfy_nest_lev = 0;
mudstate.lock_nest_lev = 0;
mudstate.zone_nest_num = 0;
mudstate.in_loop = 0;
mudstate.loop_token[0] = NULL;
mudstate.loop_token2[0] = NULL;
mudstate.loop_number[0] = 0;
mudstate.in_switch = 0;
mudstate.switch_token = NULL;
mudstate.break_called = 0;
mudstate.inpipe = 0;
mudstate.pout = NULL;
mudstate.poutnew = NULL;
mudstate.poutbufc = NULL;
mudstate.poutobj = -1;
mudstate.dbm_fd = -1;
mudstate.rdata = NULL;
}

XFREE(s, "cf_init");

/* --------------------------------------------------------------------------* cf_log_notfound: Log a 'parameter not found' error.


*/
void cf_log_notfound(player, cmd, thingname, thing)
dbref player;
char *cmd, *thing;
const char *thingname;
{
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NFND")
log_printf("%s: %s %s not found", cmd, thingname, thing);
ENDLOG
} else {
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:50 PM

notify(player, tprintf("%s %s not found", thingname, thing));

/* --------------------------------------------------------------------------* cf_log_syntax: Log a syntax error.


*/
#if defined(__STDC__) && defined(STDC_HEADERS)
void cf_log_syntax(dbref player, char *cmd, const char *template,...)
#else
void cf_log_syntax(va_alist)
va_dcl
#endif
{
va_list ap;
#if defined(__STDC__) && defined(STDC_HEADERS)
va_start(ap, template);
#else
dbref player;
char *cmd, *template;
player = va_arg(ap, dbref);
cmd = va_arg(ap, char *);
template = va_arg(ap, char *);
#endif
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "SYNTX")
log_printf("%s: ", cmd);
log_vprintf(template, ap);
ENDLOG
} else {
notify(player, tvprintf(template, ap));
}
}

va_end(ap);

/* --------------------------------------------------------------------------* cf_status_from_succfail: Return command status from succ and fail info
*/
int cf_status_from_succfail(player, cmd, success, failure)
dbref player;
char *cmd;
int success, failure;
{
/*
* If any successes, return SUCCESS(0) if no failures or
* PARTIAL_SUCCESS(1) if any failures.
*/
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:50 PM

if (success > 0)
return ((failure == 0) ? 0 : 1);
/*
* No successes.
* FAILURE(-1)
*/

If no failures indicate nothing done. Always return

if (failure == 0) {
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NDATA")
log_printf("%s: Nothing to set", cmd);
ENDLOG
} else {
notify(player, "Nothing to set");
}
}
return -1;

/* --------------------------------------------------------------------------* cf_const: Read-only integer or boolean parameter.


*/
CF_HAND(cf_const)
{
/* Fail on any attempt to change the value */
}

return -1;

/* --------------------------------------------------------------------------* cf_int: Set integer parameter.


*/
CF_HAND(cf_int)
{
/* Copy the numeric value to the parameter */

if ((extra > 0) && (atoi(str) > extra)) {


cf_log_syntax(player, cmd, "Value exceeds limit of %d", extra);
return -1;
}
sscanf(str, "%d", vp);
return 0;

/* --------------------------------------------------------------------------* cf_int_factor: Set integer parameter that will be used as a factor


*
(ie. cannot be set to 0)
*/

-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:50 PM

CF_HAND(cf_int_factor)
{
int num;
/* Copy the numeric value to the parameter */
num = atoi(str);

if ((extra > 0) && (num > extra)) {


cf_log_syntax(player, cmd, "Value exceeds limit of %d", extra);
return -1;
}
if (num == 0) {
cf_log_syntax(player, cmd, "Value cannot be 0. You may want a value of 1." );
return -1;
}
sscanf(str, "%d", vp);
return 0;

/* --------------------------------------------------------------------------* cf_dbref: Set dbref parameter.


*/
CF_HAND(cf_dbref)
{
int num;
/* No consistency check on initialization. */
if (mudstate.initializing) {
if (*str == '#') {
sscanf(str, "#%d", vp);
} else {
sscanf(str, "%d", vp);
}
return 0;
}
/* Otherwise we have to validate this. If 'extra' is non-zero, the
* dbref is allowed to be NOTHING.
*/
if (*str == '#')
num = atoi(str + 1);
else
num = atoi(str);
if (((extra == NOTHING) && (num == NOTHING)) ||
(Good_obj(num) && !Going(num))) {
if (*str == '#') {
sscanf(str, "#%d", vp);
} else {
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:50 PM

sscanf(str, "%d", vp);


}
return 0;
}

if (extra == NOTHING) {
cf_log_syntax(player, cmd, "A valid dbref, or -1, is required." );
} else {
cf_log_syntax(player, cmd, "A valid dbref is required.");
}
return -1;

/* --------------------------------------------------------------------------* cf_module: Open a loadable module. Modules are initialized later in the
* startup.
*/
CF_HAND(cf_module)
{
lt_dlhandle handle;
void (*initptr)(void);
MODULE *mp;
handle = lt_dlopen(tprintf("%s.la", str));
if (!handle) {
STARTLOG(LOG_STARTUP, "CNF", "MOD")
log_printf("Loading of %s module failed: %s" ,
str, lt_dlerror());
ENDLOG
return -1;
}
mp = (MODULE *) XMALLOC(sizeof(MODULE), "cf_module.mp");
mp->modname = XSTRDUP(str, "cf_module.name");
mp->handle = handle;
mp->next = mudstate.modules_list;
mudstate.modules_list = mp;
/* Look up our symbols now, and cache the pointers. They're
* not going to change from here on out.
*/
mp->process_command = DLSYM_INT(handle, str, "process_command",
(dbref, dbref, int, char *,
char *[], int));
mp->process_no_match = DLSYM_INT(handle, str, "process_no_match",
(dbref, dbref, int, char *, char *,
char *[], int));
mp->did_it = DLSYM_INT(handle, str, "did_it",
(dbref, dbref, dbref,
int, const char *, int, const char *, int,
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

int, char *[], int, int));


mp->create_obj = DLSYM(handle, str, "create_obj", (dbref, dbref));
mp->destroy_obj = DLSYM(handle, str, "destroy_obj", (dbref, dbref));
mp->create_player = DLSYM(handle, str, "create_player",
(dbref, dbref, int, int));
mp->destroy_player = DLSYM(handle, str, "destroy_player",
(dbref, dbref));
mp->announce_connect = DLSYM(handle, str, "announce_connect",
(dbref, const char *, int));
mp->announce_disconnect = DLSYM(handle, str, "announce_disconnect",
(dbref, const char *, int));
mp->examine = DLSYM(handle, str, "examine",
(dbref, dbref, dbref, int, int));
mp->dump_database = DLSYM(handle, str, "dump_database", (FILE *));
mp->db_grow = DLSYM(handle, str, "db_grow", (int, int));
mp->db_write = DLSYM(handle, str, "db_write", (void));
mp->db_write_flatfile = DLSYM(handle, str, "db_write_flatfile", (FILE *));
mp->do_second = DLSYM(handle, str, "do_second", (void));
mp->cache_put_notify = DLSYM(handle, str, "cache_put_notify", (DBData, unsigned int
));
mp->cache_del_notify = DLSYM(handle, str, "cache_del_notify", (DBData, unsigned int
));

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687

Saturday, June 16, 2012 11:50 PM

if (!mudstate.standalone) {
if ((initptr = DLSYM(handle, str, "init", (void))) != NULL)
(*initptr)();
}
STARTLOG(LOG_STARTUP, "CNF", "MOD")
log_printf("Loaded module: %s", str);
ENDLOG
}

return 0;

/* *INDENT-OFF* */
/* --------------------------------------------------------------------------* cf_bool: Set boolean parameter.
*/
NAMETAB bool_names[] = {
{(char *)"true",
1, 0, 1},
{(char *)"false",
1, 0, 0},
{(char *)"yes",
1, 0, 1},
{(char *)"no",
1, 0, 0},
{(char *)"1",
1, 0, 1},
{(char *)"0",
1, 0, 0},
{NULL,
0, 0, 0}};
/* *INDENT-ON* */

-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

Saturday, June 16, 2012 11:50 PM

CF_HAND(cf_bool)
{
*vp = (int) search_nametab(GOD, bool_names, str);
if (*vp < 0)
*vp = (long) 0;
return 0;
}
/* --------------------------------------------------------------------------* cf_option: Select one option from many choices.
*/
CF_HAND(cf_option)
{
int i;

i = search_nametab(GOD, (NAMETAB *) extra, str);


if (i < 0) {
cf_log_notfound(player, cmd, "Value", str);
return -1;
}
*vp = i;
return 0;

/* --------------------------------------------------------------------------* cf_string: Set string parameter.


*/
CF_HAND(cf_string)
{
int retval;
/*
* Make a copy of the string if it is not too big
*/

retval = 0;
if (strlen(str) >= (unsigned int)extra) {
str[extra - 1] = '\0';
if (mudstate.initializing) {
STARTLOG(LOG_STARTUP, "CNF", "NFND")
log_printf("%s: String truncated", cmd);
ENDLOG
} else {
notify(player, "String truncated");
}
retval = 1;
}
XFREE(*(char **)vp, "cf_string");
*(char **)vp = XSTRDUP(str, "cf_string");
return retval;

-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

Saturday, June 16, 2012 11:50 PM

/* --------------------------------------------------------------------------* cf_alias: define a generic hash table alias.


*/
CF_HAND(cf_alias)
{
char *alias, *orig, *p, *tokst;
int *cp, upcase;

alias = strtok_r(str, " \t=,", &tokst);


orig = strtok_r(NULL, " \t=,", &tokst);
if (orig) {
upcase = 0;
for (p = orig; *p; p++)
*p = tolower(*p);
cp = hashfind(orig, (HASHTAB *) vp);
if (cp == NULL) {
upcase++;
for (p = orig; *p; p++)
*p = toupper(*p);
cp = hashfind(orig, (HASHTAB *) vp);
if (cp == NULL) {
cf_log_notfound(player, cmd,
(char *) extra, orig);
return -1;
}
}
if (upcase) {
for (p = alias; *p; p++)
*p = toupper(*p);
} else {
for (p = alias; *p; p++)
*p = tolower(*p);
}
if (((HASHTAB *)vp)->flags & HT_KEYREF) {
/* hashadd won't copy it, so we do that here */
p = alias;
alias = XSTRDUP(p, "cf_alias");
}
return hashadd(alias, cp, (HASHTAB *) vp, HASH_ALIAS);
} else {
cf_log_syntax(player, cmd, "Invalid original for alias %s" ,
alias);
return -1;
}

/* --------------------------------------------------------------------------* cf_divert_log: Redirect a log type.


*/
CF_HAND(cf_divert_log)
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

Saturday, June 16, 2012 11:50 PM

char *type_str, *file_str, *tokst;


int f, fd;
FILE *fptr;
LOGFILETAB *tp, *lp;
/* Two args, two args only */
type_str = strtok_r(str, " \t", &tokst);
file_str = strtok_r(NULL, " \t", &tokst);
if (!type_str || !file_str) {
cf_log_syntax(player, cmd, "Missing pathname to log to." , (char *) "");
return -1;
}
/* Find the log. */
f = search_nametab(GOD, (NAMETAB *) extra, type_str);
if (f <= 0) {
cf_log_notfound(player, cmd, "Log diversion", type_str);
return -1;
}
for (tp = logfds_table; tp->log_flag; tp++) {
if (tp->log_flag == f)
break;
}
if (tp == NULL) {
/* This should never happen! */
cf_log_notfound(player, cmd, "Logfile table corruption", type_str);
return -1;
}
/* We shouldn't have a file open already. */
if (tp->filename != NULL) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_printf("Log type %s already diverted: %s" ,
type_str, tp->filename);
ENDLOG
return -1;
}
/* Check to make sure that we don't have this filename open already. */
fptr = NULL;
for (lp = logfds_table; lp->log_flag; lp++) {
if (lp->filename && !strcmp(file_str, lp->filename)) {
fptr = lp->fileptr;
break;
}
}
/* We don't have this filename yet. Open the logfile. */
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899

Saturday, June 16, 2012 11:50 PM

if (!fptr) {
fptr = fopen(file_str, "w");
if (!fptr) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_printf("Cannot open logfile: %s", file_str);
ENDLOG
return -1;
}
if ((fd = fileno(fptr)) == -1) {
return -1;
}
#ifdef FNDELAY
if (fcntl(fd, F_SETFL, FNDELAY) == -1) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_printf("Cannot make nonblocking: %s" , file_str);
ENDLOG
return -1;
}
#else
if (fcntl(fd, F_SETFL, O_NDELAY) == -1) {
STARTLOG(LOG_STARTUP, "CNF", "DIVT")
log_printf("Cannot make nonblocking: %s" , file_str);
ENDLOG
return -1;
}
#endif
}
/* Indicate that this is being diverted. */
tp->fileptr = fptr;
tp->filename = XSTRDUP(file_str, "cf_divert_log");
*vp |= f;
}

return 0;

/* --------------------------------------------------------------------------* cf_modify_bits: set or clear bits in a flag word from a namelist.


*/
CF_HAND(cf_modify_bits)
{
char *sp, *tokst;
int f, negate, success, failure;
/*
* Walk through the tokens
*/

-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

Saturday, June 16, 2012 11:50 PM

success = failure = 0;
sp = strtok_r(str, " \t", &tokst);
while (sp != NULL) {
/* Check for negation */
negate = 0;
if (*sp == '!') {
negate = 1;
sp++;
}
/* Set or clear the appropriate bit */
f = search_nametab(GOD, (NAMETAB *) extra, sp);
if (f > 0) {
if (negate)
*vp &= ~f;
else
*vp |= f;
success++;
} else {
cf_log_notfound(player, cmd, "Entry", sp);
failure++;
}
/* Get the next token */
sp = strtok_r(NULL, " \t", &tokst);

}
return cf_status_from_succfail(player, cmd, success, failure);

/* --------------------------------------------------------------------------* modify_xfuncs: Helper function to change xfuncs.


*/
static NAMEDFUNC **all_named_funcs = NULL;
static int num_named_funcs = 0;
static int modify_xfuncs(fn_name, fn_ptr, xfuncs, negate)
char *fn_name;
int (*fn_ptr)(dbref);
EXTFUNCS **xfuncs;
int negate;
/* 0 - normal, 1 - remove */
{
EXTFUNCS *xfp;
NAMEDFUNC *np, **tp;
int i;
xfp = *xfuncs;
/* If we're negating, just remove it from the list of functions. */
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

Saturday, June 16, 2012 11:50 PM

if (negate) {
if (!xfp)
return 0;
for (i = 0; i < xfp->num_funcs; i++) {
if (!strcmp(xfp->ext_funcs[i]->fn_name, fn_name)) {
xfp->ext_funcs[i] = NULL;
return 1;
}
}
return 0;
}
/* Have we encountered this function before? */
np = NULL;
for (i = 0; i < num_named_funcs; i++) {
if (!strcmp(all_named_funcs[i]->fn_name, fn_name)) {
np = all_named_funcs[i];
break;
}
}
/* If not, we need to allocate it. */
if (!np) {
np = (NAMEDFUNC *) XMALLOC(sizeof(NAMEDFUNC), "nfunc");
np->fn_name = (char *) strdup(fn_name);
np->handler = fn_ptr;
}
/* Add it to the ones we know about. */
if (num_named_funcs == 0) {
all_named_funcs = (NAMEDFUNC **) XMALLOC(sizeof(NAMEDFUNC *),
"all_named_funcs");
num_named_funcs = 1;
all_named_funcs[0] = np;
} else {
tp = (NAMEDFUNC **) XREALLOC(all_named_funcs,
(num_named_funcs + 1) * sizeof(NAMEDFUNC *),
"all_named_funcs");
tp[num_named_funcs] = np;
all_named_funcs = tp;
num_named_funcs++;
}
/* Do we have an existing list of functions? If not, this is easy. */
if (!xfp) {
xfp = (EXTFUNCS *) XMALLOC(sizeof(EXTFUNCS), "xfunc");
xfp->num_funcs = 1;
xfp->ext_funcs = (NAMEDFUNC **) XMALLOC(sizeof(NAMEDFUNC *), "nfuncs");
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:50 PM

xfp->ext_funcs[0] = np;
*xfuncs = xfp;
return 1;
}
/* See if we have an empty slot to insert into. */
for (i = 0; i < xfp->num_funcs; i++) {
if (!xfp->ext_funcs[i]) {
xfp->ext_funcs[i] = np;
return 1;
}
}
/* Guess not. Tack it onto the end. */

tp = (NAMEDFUNC **) XREALLOC(xfp->ext_funcs,


(xfp->num_funcs + 1) * sizeof(NAMEDFUNC *),
"nfuncs");
tp[xfp->num_funcs] = np;
xfp->ext_funcs = tp;
xfp->num_funcs++;
return 1;

/* --------------------------------------------------------------------------* parse_ext_access: Parse an extended access list with module callouts.


*/
int parse_ext_access(perms, xperms, str, ntab, player, cmd)
int *perms;
EXTFUNCS **xperms;
char *str;
NAMETAB *ntab;
dbref player;
char *cmd;
{
char *sp, *tokst, *cp, *ostr;
int f, negate, success, failure, got_one;
MODULE *mp;
int (*hp)(dbref);
/* Walk through the tokens */
success = failure = 0;
sp = strtok_r(str, " \t", &tokst);
while (sp != NULL) {
/* Check for negation

*/

negate = 0;
if (*sp == '!') {
negate = 1;
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

Saturday, June 16, 2012 11:50 PM

sp++;

/* Set or clear the appropriate bit */


f = search_nametab(GOD, ntab, sp);
if (f > 0) {
if (negate)
*perms &= ~f;
else
*perms |= f;
success++;
} else {
/* Is this a module callout? */
got_one = 0;
if (!strncmp(sp, "mod_", 4)) {
/* Split it apart, see if we have anything. */
ostr = (char *) strdup(sp);
if (*(sp + 4) != '\0') {
cp = strchr(sp + 4, '_');
if (cp) {
*cp++ = '\0';
WALK_ALL_MODULES(mp) {
got_one = 1;
if (!strcmp(sp + 4, mp->modname)) {
hp = DLSYM_INT(mp->handle, mp->modname, cp,
(dbref));
if (!hp) {
cf_log_notfound(player, cmd,
"Module function", ostr);
failure++;
} else {
if (modify_xfuncs(ostr, hp, xperms,
negate))
success++;
else
failure++;
}
break;
}
}
if (!got_one) {
cf_log_notfound(player, cmd, "Loaded module",
sp + 4);
got_one = 1;
}
}
}
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

Saturday, June 16, 2012 11:50 PM

free(ostr);
}

if (!got_one) {
cf_log_notfound(player, cmd, "Entry", sp);
failure++;
}

/* Get the next token */


sp = strtok_r(NULL, " \t", &tokst);
}
}

return cf_status_from_succfail(player, cmd, success, failure);

/* --------------------------------------------------------------------------* cf_set_flags: Clear flag word and then set from a flags htab.
*/
CF_HAND(cf_set_flags)
{
char *sp, *tokst;
FLAGENT *fp;
FLAGSET *fset;
int success, failure;
for (sp = str; *sp; sp++)
*sp = toupper(*sp);
/*
* Walk through the tokens
*/
success = failure = 0;
sp = strtok_r(str, " \t", &tokst);
fset = (FLAGSET *) vp;
while (sp != NULL) {
/*
* Set the appropriate bit
*/
fp = (FLAGENT *) hashfind(sp, &mudstate.flags_htab);
if (fp != NULL) {
if (success == 0) {
(*fset).word1 = 0;
(*fset).word2 = 0;
(*fset).word3 = 0;
}
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

Saturday, June 16, 2012 11:50 PM

if (fp->flagflag & FLAG_WORD3)


(*fset).word3 |= fp->flagvalue;
else if (fp->flagflag & FLAG_WORD2)
(*fset).word2 |= fp->flagvalue;
else
(*fset).word1 |= fp->flagvalue;
success++;
} else {
cf_log_notfound(player, cmd, "Entry", sp);
failure++;
}
/*
* Get the next token
*/
sp = strtok_r(NULL, " \t", &tokst);

}
if ((success == 0) && (failure == 0)) {
(*fset).word1 = 0;
(*fset).word2 = 0;
(*fset).word3 = 0;
return 0;
}
if (success > 0)
return ((failure == 0) ? 0 : 1);
return -1;

/* --------------------------------------------------------------------------* cf_badname: Disallow use of player name/alias.


*/
CF_HAND(cf_badname)
{
if (extra)
badname_remove(str);
else
badname_add(str);
return 0;
}
/* --------------------------------------------------------------------------* sane_inet_addr: inet_addr() does not necessarily do reasonable checking
* for sane syntax. On certain operating systems, if passed less than four
* octets, it will cause a segmentation violation. This is unfriendly.
* We take steps here to deal with it.
*/
static unsigned long sane_inet_addr(str)
char *str;
{
int i;
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

Saturday, June 16, 2012 11:50 PM

char *p;

p = str;
for (i = 1; (p = strchr(p, '.')) != NULL; i++, p++)
;
if (i < 4)
return INADDR_NONE;
else
return inet_addr(str);

/* --------------------------------------------------------------------------* cf_site: Update site information


*/
CF_AHAND(cf_site)
{
SITE *site, *last, *head;
char *addr_txt, *mask_txt, *tokst;
struct in_addr addr_num, mask_num;
int mask_bits;
if ((mask_txt = strchr(str, '/')) == NULL) {
/* Standard IP range and netmask notation. */
addr_txt = strtok_r(str, " \t=,", &tokst);
if (addr_txt)
mask_txt = strtok_r(NULL, " \t=,", &tokst);
if (!addr_txt || !*addr_txt || !mask_txt || !*mask_txt) {
cf_log_syntax(player, cmd, "Missing host address or mask." ,
(char *)"");
return -1;
}
if ((addr_num.s_addr = sane_inet_addr(addr_txt)) == INADDR_NONE) {
cf_log_syntax(player, cmd, "Malformed host address: %s", addr_txt);
return -1;
}
if (((mask_num.s_addr = sane_inet_addr(mask_txt)) == INADDR_NONE) &&
strcmp(mask_txt, "255.255.255.255")) {
cf_log_syntax(player, cmd, "Malformed mask address: %s", mask_txt);
return -1;
}
} else {
/* RFC 1517, 1518, 1519, 1520: CIDR IP prefix notation */
addr_txt = str;
*mask_txt++ = '\0';
mask_bits = atoi(mask_txt);
if ((mask_bits > 32) || (mask_bits < 0)) {
cf_log_syntax(player, cmd,
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

Saturday, June 16, 2012 11:50 PM

"Mask bits (%d) in CIDR IP prefix out of range." ,


mask_bits);
return -1;
} else if (mask_bits == 0) {
mask_num.s_addr = htonl(0); /* can't shift by 32 */
} else {
mask_num.s_addr = htonl(0xFFFFFFFFU << (32 - mask_bits));
}
if ((addr_num.s_addr = sane_inet_addr(addr_txt)) == INADDR_NONE) {
cf_log_syntax(player, cmd, "Malformed host address: %s", addr_txt);
return -1;
}
}
head = (SITE *) * vp;
/*
* Parse the access entry and allocate space for it
*/
if (!(site = (SITE *) XMALLOC(sizeof(SITE), "cf_site")))
return -1;
/*
* Initialize the site entry
*/
site->address.s_addr = addr_num.s_addr;
site->mask.s_addr = mask_num.s_addr;
site->flag = (long) extra;
site->next = NULL;
/*
* Link in the entry. Link it at the start if not initializing, at
* the end if initializing. This is so that entries in the config
* file are processed as you would think they would be, while
* entries made while running are processed first.
*/

if (mudstate.initializing) {
if (head == NULL) {
*vp = (long *) site;
} else {
for (last = head; last->next; last = last->next)
;
last->next = site;
}
} else {
site->next = head;
*vp = (long *) site;
}
return 0;

-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376

Saturday, June 16, 2012 11:50 PM

/* --------------------------------------------------------------------------* cf_cf_access: Set write or read access on config directives


* kludge: this cf handler uses vp as an extra extra field since the
* first extra field is taken up with the access nametab.
*/
static int helper_cf_cf_access(tp, player, vp, ap, cmd, extra)
CONF *tp;
dbref player;
int *vp;
char *ap, *cmd;
long extra;
{
/* Cannot modify parameters set STATIC */

if (tp->flags & CA_STATIC) {


notify(player, NOPERM_MESSAGE);
STARTLOG(LOG_CONFIGMODS, "CFG", "PERM")
if (db)
log_name(player);
else
log_printf("System");
log_printf(" tried to change %s access to static param: %s" ,
(((long)vp) ? "read" : "write"),
tp->pname);
ENDLOG
return -1;
}
if ((long)vp) {
return (cf_modify_bits(&tp->rperms, ap, extra,
player, cmd));
} else {
return (cf_modify_bits(&tp->flags, ap, extra,
player, cmd));
}

CF_HAND(cf_cf_access)
{
CONF *tp, *ctab;
char *ap;
MODULE *mp;
for (ap = str; *ap && !isspace(*ap); ap++) ;
if (*ap)
*ap++ = '\0';
for (tp = conftable; tp->pname; tp++) {
if (!strcmp(tp->pname, str)) {
return (helper_cf_cf_access(tp, player, vp, ap, cmd, extra));
}
}
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

Saturday, June 16, 2012 11:50 PM

WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (!strcmp(tp->pname, str)) {
return (helper_cf_cf_access(tp, player, vp, ap,
cmd, extra));
}
}
}
}

cf_log_notfound(player, cmd, "Config directive", str);


return -1;

/* --------------------------------------------------------------------------* cf_helpfile: Add a help/news-style file. Only valid during startup.


*/
int add_helpfile(player, confcmd, str, is_raw)
dbref player;
char *confcmd, *str;
int is_raw;
{
char *fcmd, *fpath, *newstr, *tokst;
CMDENT *cmdp;
char **ftab;
/* pointer to an array of filepaths */
HASHTAB *hashes;
/* Make a new string so we won't SEGV if given a constant string */
newstr = alloc_mbuf("add_helpfile");
StringCopy(newstr, str);
fcmd = strtok_r(newstr, " \t=,", &tokst);
fpath = strtok_r(NULL, " \t=,", &tokst);
if (fpath == NULL) {
cf_log_syntax(player, confcmd, "Missing path for helpfile %s" , fcmd);
free_mbuf(newstr);
return -1;
}
if (fcmd[0] == '_' && fcmd[1] == '_') {
cf_log_syntax(player, confcmd, "Helpfile %s would cause @addcommand conflict" , fcmd);
free_mbuf(newstr);
return -1;
}
if (strlen(fpath) > SBUF_SIZE) {
cf_log_syntax(player, confcmd, "Helpfile %s filename too long" , fcmd);
free_mbuf(newstr);
return -1;
}
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481

Saturday, June 16, 2012 11:50 PM

cmdp = (CMDENT *) XMALLOC(sizeof(CMDENT), "add_helpfile.cmdp");


cmdp->cmdname = XSTRDUP(fcmd, "add_helpfile.cmd");
cmdp->switches = NULL;
cmdp->perms = 0;
cmdp->pre_hook = NULL;
cmdp->post_hook = NULL;
cmdp->userperms = NULL;
cmdp->callseq = CS_ONE_ARG;
cmdp->info.handler = do_help;
cmdp->extra = mudstate.helpfiles;
if (is_raw)
cmdp->extra |= HELP_RAWHELP;
hashdelete(cmdp->cmdname, &mudstate.command_htab);
hashadd(cmdp->cmdname, (int *) cmdp, &mudstate.command_htab, 0);
hashdelete(tprintf("__%s", cmdp->cmdname), &mudstate.command_htab);
hashadd(tprintf("__%s", cmdp->cmdname), (int *) cmdp, &mudstate.command_htab,
HASH_ALIAS);
/* We may need to grow the helpfiles table, or create it. */
if (!mudstate.hfiletab) {
mudstate.hfiletab = (char **) XCALLOC(4, sizeof(char *), "helpfile.htab");
mudstate.hfile_hashes = (HASHTAB *) XCALLOC(4, sizeof(HASHTAB), "helpfile.hashes");
mudstate.hfiletab_size = 4;
} else if (mudstate.helpfiles >= mudstate.hfiletab_size) {
ftab = (char **) XREALLOC(mudstate.hfiletab,
(mudstate.hfiletab_size + 4) * sizeof(char *),
"helpfile.htab");
hashes = (HASHTAB *) XREALLOC(mudstate.hfile_hashes,
(mudstate.hfiletab_size + 4) *
sizeof(HASHTAB), "helpfile.hashes");
ftab[mudstate.hfiletab_size] = NULL;
ftab[mudstate.hfiletab_size + 1] = NULL;
ftab[mudstate.hfiletab_size + 2] = NULL;
ftab[mudstate.hfiletab_size + 3] = NULL;
mudstate.hfiletab_size += 4;
mudstate.hfiletab = ftab;
mudstate.hfile_hashes = hashes;
}
/* Add or replace the path to the file. */
if (mudstate.hfiletab[mudstate.helpfiles] != NULL)
XFREE(mudstate.hfiletab[mudstate.helpfiles], "add_helpfile.fpath");
mudstate.hfiletab[mudstate.helpfiles] = XSTRDUP(fpath, "add_helpfile.fpath");

-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534

Saturday, June 16, 2012 11:50 PM

/* Initialize the associated hashtable. */


hashinit(&mudstate.hfile_hashes[mudstate.helpfiles], 30 * HASH_FACTOR,
HT_STR);
mudstate.helpfiles++;
free_mbuf(newstr);
}

return 0;

CF_HAND(cf_helpfile)
{
return add_helpfile(player, cmd, str, 0);
}
CF_HAND(cf_raw_helpfile)
{
return add_helpfile(player, cmd, str, 1);
}
/* --------------------------------------------------------------------------* cf_include: Read another config file. Only valid during startup.
*/
CF_HAND(cf_include)
{
FILE *fp;
char *cp, *ap, *zp, *buf;
extern int FDECL(cf_set, (char *, char *, dbref));
if (!mudstate.initializing)
return -1;
fp = fopen(str, "r");
if (fp == NULL) {
cf_log_notfound(player, cmd, "Config file", str);
return -1;
}
buf = alloc_lbuf("cf_include");
fgets(buf, LBUF_SIZE, fp);
while (!feof(fp)) {
cp = buf;
if (*cp == '#') {
fgets(buf, LBUF_SIZE, fp);
continue;
}
/*
* Not a comment line. Strip off the NL and any characters
* following it. Then, split the line into the command and
* argument portions (separated by a space). Also, trim off
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587

Saturday, June 16, 2012 11:50 PM

* the trailing comment, if any (delimited by #)


*/
for (cp = buf; *cp && *cp != '\n'; cp++) ;
*cp = '\0'; /*
* strip \n
*/
for (cp = buf; *cp && isspace(*cp); cp++) ; /*
* strip
* spaces
*/
for (ap = cp; *ap && !isspace(*ap); ap++) ; /*
* skip over
* command
*/
if (*ap)
*ap++ = '\0';
/*
* trim command
*/
for (; *ap && isspace(*ap); ap++) ; /*
* skip spaces
*/
for (zp = ap; *zp && (*zp != '#'); zp++) ; /*
* find
* comment
*/
if (*zp && !(isdigit(*(zp + 1)) && isspace(*(zp -1))))
*zp = '\0'; /*
* zap comment, but only if it's
* not sitting between whitespace
* and a digit, which traps a case
* like 'master_room #2'
*/
for (zp = zp - 1; zp >= ap && isspace(*zp); zp--)
*zp = '\0'; /*
* zap trailing spaces
*/
cf_set(cp, ap, player);
fgets(buf, LBUF_SIZE, fp);

}
free_lbuf(buf);
fclose(fp);
return 0;

extern
extern
extern
extern
extern
extern
extern

CF_HDCL(cf_access);
CF_HDCL(cf_cmd_alias);
CF_HDCL(cf_acmd_access);
CF_HDCL(cf_attr_access);
CF_HDCL(cf_attr_type);
CF_HDCL(cf_func_access);
CF_HDCL(cf_flag_access);
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618

Saturday, June 16, 2012 11:50 PM

extern CF_HDCL(cf_flag_name);
extern CF_HDCL(cf_power_access);
/* *INDENT-OFF* */
/* --------------------------------------------------------------------------* conftable: Table for parsing the configuration file.
*/
CONF conftable[] = {
{(char *)"access",
cf_access, CA_GOD,
CA_DISABLED,
NULL,
(long)access_nametab},
{(char *)"addcommands_match_blindly",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
addcmd_match_blindly, (long)"@addcommands don't error if no match is found" },
{(char *)"addcommands_obey_stop",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
addcmd_obey_stop, (long)"@addcommands obey STOP"},
{(char *)"addcommands_obey_uselocks",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
addcmd_obey_uselocks, (long)"@addcommands obey UseLocks"},
{(char *)"alias",
cf_cmd_alias,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.command_htab, 0},
{(char *)"ansi_colors",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.ansi_colors
,
(long)"ANSI color codes enabled"},
{(char *)"attr_access",
cf_attr_access, CA_GOD,
CA_DISABLED,
NULL,
(long)attraccess_nametab},
{(char *)"attr_alias",
cf_alias,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.attr_name_htab,(long)"Attribute"},
{(char *)"attr_cmd_access",
cf_acmd_access, CA_GOD,
CA_DISABLED,
NULL,
(long)access_nametab},
{(char *)"attr_type",
cf_attr_type,
CA_GOD,
CA_DISABLED,
NULL,
(long)attraccess_nametab},
{(char *)"autozone",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.autozone,
(long)"New objects are @chzoned to their creator's zone" },
{(char *)"bad_name",
cf_badname, CA_GOD,
CA_DISABLED,
NULL,
0},
{(char *)"badsite_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
site_file, MBUF_SIZE},
{(char *)"binary_home",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
binhome,
MBUF_SIZE},
{(char *)"booleans_oldstyle",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
bools_oldstyle,
(long)"Dbrefs #0 and #-1 are boolean false, all
other\n\t\t\t\tdbrefs are boolean true" },
{(char *)"building_limit",
cf_int,
CA_GOD,
CA_PUBLIC, (int *)&mudconf.
building_limit, 0},
{(char *)"c_is_command",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.c_cmd_subst
,
(long)"%c substitution is last command rather than ANSI" },
{(char *)"cache_size",
cf_int,
CA_GOD,
CA_GOD,
&mudconf.cache_size
,
0},
{(char *)"cache_width",
cf_int,
CA_STATIC, CA_GOD,
&mudconf.cache_width
,
0},
{(char *)"check_interval",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.
check_interval,
0},
{(char *)"check_offset",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.
check_offset,
0},
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645

Saturday, June 16, 2012 11:50 PM

{(char *)"clone_copies_cost",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
clone_copy_cost,
(long)"@clone copies object cost"},
{(char *)"command_invocation_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
cmd_invk_lim,
0},
{(char *)"command_quota_increment", cf_int,
CA_GOD,
CA_WIZARD, &mudconf.
cmd_quota_incr,
0},
{(char *)"command_quota_max",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.
cmd_quota_max,
0},
{(char *)"command_recursion_limit", cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
cmd_nest_lim,
0},
{(char *)"concentrator_port",
cf_int,
CA_STATIC, CA_WIZARD, &mudconf.
conc_port,
0},
{(char *)"config_access",
cf_cf_access,
CA_GOD,
CA_DISABLED,
NULL,
(long)access_nametab},
{(char *)"config_read_access",
cf_cf_access,
CA_GOD,
CA_DISABLED,
(int *)1
,
(long)access_nametab},
{(char *)"conn_timeout",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.
conn_timeout,
0},
{(char *)"connect_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
conn_file, MBUF_SIZE},
{(char *)"connect_reg_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
creg_file, MBUF_SIZE},
{(char *)"crash_database",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
crashdb,
MBUF_SIZE},
{(char *)"create_max_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.createmax,
0},
{(char *)"create_min_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.createmin,
0},
{(char *)"dark_actions",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
dark_actions,
(long)"Dark objects still trigger @a-actions when moving" },
{(char *)"dark_sleepers",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
dark_sleepers,
(long)"Disconnected players not shown in room contents" },
{(char *)"database_home",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
dbhome,
MBUF_SIZE},
{(char *)"default_home",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
default_home,
NOTHING},
{(char *)"dig_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.digcost,
0},
{(char *)"divert_log",
cf_divert_log, CA_STATIC, CA_DISABLED,
&mudconf.
log_diversion,
(long) logoptions_nametab},
{(char *)"down_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
down_file, MBUF_SIZE},
{(char *)"down_motd_message",
cf_string, CA_GOD,
CA_WIZARD, (int *)&mudconf.
downmotd_msg,
GBUF_SIZE},
{(char *)"dump_interval",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.
dump_interval,
0},
{(char *)"dump_message",
cf_string, CA_GOD,
CA_WIZARD, (int *)&mudconf.
dump_msg,
MBUF_SIZE},
{(char *)"postdump_message",
cf_string, CA_GOD,
CA_WIZARD, (int *)&mudconf.
postdump_msg,
MBUF_SIZE},
{(char *)"dump_offset",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.dump_offset
,
0},
{(char *)"earn_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.paylimit,
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671

Saturday, June 16, 2012 11:50 PM

0},
{(char *)"examine_flags",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.ex_flags,
(long)"examine shows names of flags" },
{(char *)"examine_public_attrs",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
exam_public,
(long)"examine shows public attributes" },
{(char *)"exit_flags",
cf_set_flags,
CA_GOD,
CA_DISABLED,
(int *)&
mudconf.exit_flags, 0},
{(char *)"exit_calls_move",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
exit_calls_move,
(long)"Using an exit calls the move command" },
{(char *)"exit_parent",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.exit_parent
,
NOTHING},
{(char *)"exit_proto",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.exit_proto
,
NOTHING},
{(char *)"exit_attr_defaults",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
exit_defobj,
NOTHING},
{(char *)"exit_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.exit_quota
,
0},
{(char *)"events_daily_hour",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
events_daily_hour, 0},
{(char *)"fascist_teleport",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
fascist_tport,
(long)"@teleport source restricted to control or JUMP_OK" },
{(char *)"fixed_home_message",
cf_string, CA_STATIC, CA_PUBLIC, (int *)&mudconf.
fixed_home_msg, MBUF_SIZE},
{(char *)"fixed_tel_message",
cf_string, CA_STATIC, CA_PUBLIC, (int *)&mudconf.
fixed_tel_msg, MBUF_SIZE},
{(char *)"find_money_chance",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.payfind
,
0},
{(char *)"flag_alias",
cf_alias,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.flags_htab,
(long)"Flag"},
{(char *)"flag_access",
cf_flag_access, CA_GOD,
CA_DISABLED,
NULL,
0},
{(char *)"flag_name",
cf_flag_name,
CA_GOD,
CA_DISABLED,
NULL,
0},
{(char *)"forbid_site",
cf_site,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.access_list,
H_FORBIDDEN},
{(char *)"fork_dump",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.fork_dump,
(long)"Dumps are performed using a forked process" },
{(char *)"fork_vfork",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.fork_vfork
,
(long)"Forks are done using vfork()" },
{(char *)"forwardlist_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
fwdlist_lim,
0},
{(char *)"full_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
full_file, MBUF_SIZE},
{(char *)"full_motd_message",
cf_string, CA_GOD,
CA_WIZARD, (int *)&mudconf.
fullmotd_msg,
GBUF_SIZE},
{(char *)"function_access",
cf_func_access, CA_GOD,
CA_DISABLED,
NULL,
(long)access_nametab},
{(char *)"function_alias",
cf_alias,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.func_htab, (long)"Function"},
{(char *)"function_invocation_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
func_invk_lim,
0},
{(char *)"function_recursion_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
func_nest_lim,
0},
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700

Saturday, June 16, 2012 11:50 PM

{(char *)"function_cpu_limit",
cf_int,
CA_STATIC, CA_PUBLIC, &mudconf.
func_cpu_lim_secs, 0},
{(char *)"gdbm_database",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.gdbm
,
MBUF_SIZE},
{(char *)"global_aconn_uselocks",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
global_aconn_uselocks, (long)"Obey UseLocks on global @Aconnect and @Adisconnect" },
{(char *)"good_name",
cf_badname, CA_GOD,
CA_DISABLED,
NULL,
1},
{(char *)"guest_basename",
cf_string, CA_STATIC, CA_PUBLIC, (int *)&mudconf.
guest_basename, PLAYER_NAME_LIMIT},
{(char *)"guest_char_num",
cf_dbref,
CA_GOD,
CA_WIZARD, &mudconf.guest_char
,
NOTHING},
{(char *)"guest_nuker",
cf_dbref,
CA_GOD,
CA_WIZARD, &mudconf.guest_nuker
,
GOD},
{(char *)"guest_password",
cf_string, CA_GOD,
CA_GOD,
(int *)&mudconf.
guest_password, SBUF_SIZE},
{(char *)"guest_prefixes",
cf_string, CA_GOD,
CA_WIZARD, (int *)&mudconf.
guest_prefixes, LBUF_SIZE},
{(char *)"guest_suffixes",
cf_string, CA_GOD,
CA_WIZARD, (int *)&mudconf.
guest_suffixes, LBUF_SIZE},
{(char *)"number_guests",
cf_int,
CA_STATIC, CA_WIZARD, &mudconf.
number_guests,
0},
{(char *)"guest_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
guest_file, MBUF_SIZE},
{(char *)"guest_site",
cf_site,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.access_list,
H_GUEST},
{(char *)"guest_starting_room",
cf_dbref,
CA_GOD,
CA_WIZARD, &mudconf.
guest_start_room, NOTHING},
{(char *)"have_pueblo",
cf_const,
CA_STATIC, CA_PUBLIC, &mudconf.have_pueblo
,
(long)"Pueblo client extensions are supported" },
{(char *)"have_zones",
cf_bool,
CA_STATIC, CA_PUBLIC, &mudconf.have_zones
,
(long)"Multiple control via ControlLocks is permitted" },
{(char *)"helpfile",
cf_helpfile,
CA_STATIC, CA_DISABLED,
NULL,
0},
{(char *)"hostnames",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
use_hostname,
(long)"DNS lookups are done on hostnames" },
#ifdef PUEBLO_SUPPORT
{(char *)"html_connect_file",
htmlconn_file, MBUF_SIZE},
{(char *)"pueblo_message",
pueblo_msg, GBUF_SIZE},
#endif

cf_string,

CA_STATIC,

CA_GOD,

(int *)&mudconf.

CA_WIZARD,

(int *)&mudconf.

{(char *)"huh_message",
cf_string, CA_GOD,
CA_PUBLIC,
huh_msg,
MBUF_SIZE},
{(char *)"idle_wiz_dark",
cf_bool,
CA_GOD,
CA_WIZARD,
idle_wiz_dark,
(long)"Wizards who idle are set DARK" },
{(char *)"idle_interval",
cf_int,
CA_GOD,
CA_WIZARD,
idle_interval,
0},
{(char *)"idle_timeout",
cf_int,
CA_GOD,
CA_PUBLIC,
idle_timeout,
0},

(int *)&mudconf.

cf_string,

-34-

CA_GOD,

&mudconf.
&mudconf.
&mudconf.

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727

Saturday, June 16, 2012 11:50 PM

{(char *)"include",
cf_include, CA_STATIC, CA_DISABLED,
NULL,
0},
{(char *)"indent_desc",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.indent_desc
,
(long)"Descriptions are indented"},
{(char *)"initial_size",
cf_int,
CA_STATIC, CA_WIZARD, &mudconf.init_size,
0},
{(char *)"instance_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
instance_lim,
0},
{(char *)"instant_recycle",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
instant_recycle,
(long)"@destroy instantly recycles objects set DESTROY_OK" },
{(char *)"kill_guarantee_cost",
cf_int_factor,
CA_GOD,
CA_PUBLIC, &mudconf
.killguarantee,
0},
{(char *)"kill_max_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.killmax,
0},
{(char *)"kill_min_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.killmin,
0},
{(char *)"lag_check",
cf_const,
CA_STATIC, CA_PUBLIC, &mudconf.lag_check,
(long)"CPU usage warnings are enabled" },
{(char *)"lag_maximum",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.max_cmdsecs
,
0},
{(char *)"lattr_default_oldstyle", cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
lattr_oldstyle,
(long)"Empty lattr() returns blank, not #-1 NO MATCH" },
{(char *)"link_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.linkcost,
0},
{(char *)"list_access",
cf_ntab_access, CA_GOD,
CA_DISABLED,
(int *)
list_names,
(long)access_nametab},
{(char *)"local_master_rooms",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
local_masters,
(long)"Objects set ZONE act as local master rooms" },
{(char *)"local_master_parents",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
match_zone_parents,
(long)"Objects in local master rooms inherit\n\t\t\t\tcommands
from their parent"},
{(char *)"lock_recursion_limit",
cf_int,
CA_WIZARD, CA_PUBLIC, &mudconf.
lock_nest_lim,
0},
{(char *)"log",
cf_modify_bits, CA_GOD,
CA_DISABLED,
&mudconf.
log_options,
(long)logoptions_nametab},
{(char *)"log_options",
cf_modify_bits, CA_GOD,
CA_DISABLED,
&mudconf.
log_info,
(long)logdata_nametab},
{(char *)"logout_cmd_access",
cf_ntab_access, CA_GOD,
CA_DISABLED,
(int *)
logout_cmdtable,
(long)access_nametab},
{(char *)"logout_cmd_alias",
cf_alias,
CA_GOD,
CA_DISABLED,
(int *)&
mudstate.logout_cmd_htab,(long)"Logged-out command"},
{(char *)"look_obey_terse",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.terse_look
,
(long)"look obeys the TERSE flag"},
{(char *)"machine_command_cost",
cf_int_factor,
CA_GOD,
CA_PUBLIC, &mudconf
.machinecost,
0},
{(char *)"master_room",
cf_dbref,
CA_GOD,
CA_WIZARD, &mudconf.master_room
,
NOTHING},
{(char *)"match_own_commands",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
match_mine,
(long)"Non-players can match $-commands on themselves" },
{(char *)"max_players",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.max_players
,
0},
{(char *)"module",
cf_module, CA_STATIC, CA_WIZARD, NULL,
0},
{(char *)"money_name_plural",
cf_string, CA_GOD,
CA_PUBLIC, (int *)&mudconf.
-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753

Saturday, June 16, 2012 11:50 PM

many_coins, SBUF_SIZE},
{(char *)"money_name_singular",
cf_string, CA_GOD,
CA_PUBLIC, (int *)&mudconf.
one_coin,
SBUF_SIZE},
{(char *)"motd_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
motd_file, MBUF_SIZE},
{(char *)"motd_message",
cf_string, CA_GOD,
CA_WIZARD, (int *)&mudconf.
motd_msg,
GBUF_SIZE},
{(char *)"move_match_more",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
move_match_more,
(long)"Move command checks for global and zone
exits,\n\t\t\t\tresolves ambiguity" },
{(char *)"mud_name",
cf_string, CA_GOD,
CA_PUBLIC, (int *)&mudconf.
mud_name,
SBUF_SIZE},
{(char *)"mud_shortname",
cf_string, CA_GOD,
CA_PUBLIC, (int *)&mudconf.
mud_shortname, SBUF_SIZE},
{(char *)"newuser_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
crea_file, MBUF_SIZE},
{(char *)"no_ambiguous_match",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
no_ambiguous_match,
(long)"Ambiguous matches resolve to the last match" },
{(char *)"notify_recursion_limit", cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
ntfy_nest_lim,
0},
{(char *)"objeval_requires_control",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
fascist_objeval,
(long)"Control of victim required by objeval()" },
{(char *)"open_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.opencost,
0},
{(char *)"opt_frequency",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.
dbopt_interval,
0},
{(char *)"output_limit",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.
output_limit,
0},
{(char *)"page_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.pagecost,
0},
{(char *)"page_requires_equals",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
page_req_equals,
(long)"page command always requires an equals sign" },
{(char *)"paranoid_allocate",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
paranoid_alloc,
(long)"Buffer pools sanity-checked on alloc/free" },
{(char *)"parent_recursion_limit", cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
parent_nest_lim,
0},
{(char *)"paycheck",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.paycheck,
0},
{(char *)"pemit_far_players",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
pemit_players,
(long)"@pemit targets can be players in other locations" },
{(char *)"pemit_any_object",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
pemit_any,
(long)"@pemit targets can be objects in other locations" },
{(char *)"permit_site",
cf_site,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.access_list,
0},
{(char *)"player_aliases_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
max_player_aliases,
0},
{(char *)"player_flags",
cf_set_flags,
CA_GOD,
CA_DISABLED,
(int *)&
mudconf.player_flags,
0},
{(char *)"player_listen",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
player_listen,
(long)"@listen and ^-monitors are checked on players" },
{(char *)"player_match_own_commands",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
match_mine_pl,
(long)"Players can match $-commands on themselves" },
{(char *)"player_name_spaces",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779

Saturday, June 16, 2012 11:50 PM

name_spaces,
(long)"Player names can contain spaces" },
{(char *)"player_parent",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
player_parent,
NOTHING},
{(char *)"player_proto",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
player_proto,
NOTHING},
{(char *)"player_attr_defaults",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
player_defobj,
NOTHING},
{(char *)"player_queue_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
queuemax,
0},
{(char *)"player_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
player_quota,
0},
{(char *)"player_starting_home",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
start_home,
NOTHING},
{(char *)"player_starting_room",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
start_room,
0},
{(char *)"port",
cf_int,
CA_STATIC, CA_PUBLIC, &mudconf.port,
0},
{(char *)"power_access",
cf_power_access,CA_GOD,
CA_DISABLED,
NULL,
0},
{(char *)"power_alias",
cf_alias,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.powers_htab,
(long)"Power"},
{(char *)"propdir_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.propdir_lim
,
0},
{(char *)"public_flags",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.pub_flags,
(long)"Flag information is public"},
{(char *)"queue_active_chunk",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
active_q_chunk,
0},
{(char *)"queue_idle_chunk",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
queue_chunk,
0},
{(char *)"quiet_look",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.quiet_look
,
(long)"look shows public attributes in addition to @Desc" },
{(char *)"quiet_whisper",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
quiet_whisper,
(long)"whisper is quiet"},
{(char *)"quit_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
quit_file, MBUF_SIZE},
{(char *)"quotas",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.quotas,
(long)"Quotas are enforced"},
{(char *)"raw_helpfile",
cf_raw_helpfile,CA_STATIC, CA_DISABLED,
NULL,
0},
{(char *)"read_remote_desc",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
read_rem_desc,
(long)"@Desc is public, even to players not nearby" },
{(char *)"read_remote_name",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
read_rem_name,
(long)"Names are public, even to players not nearby" },
{(char *)"register_create_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
regf_file, MBUF_SIZE},
{(char *)"register_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
register_limit,
0},
{(char *)"register_site",
cf_site,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.access_list,
H_REGISTRATION},
{(char *)"require_cmds_flag",
cf_bool,
CA_GOD,
CA_PUBLIC, (int *)&mudconf.
req_cmds_flag, (long)"Only objects with COMMANDS flag are searched\n\t\t\t\tfor
$-commands"},
{(char *)"retry_limit",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.retry_limit
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805

Saturday, June 16, 2012 11:50 PM

,
0},
{(char *)"robot_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.robotcost,
0},
{(char *)"robot_flags",
cf_set_flags,
CA_GOD,
CA_DISABLED,
(int *)&
mudconf.robot_flags,
0},
{(char *)"robot_speech",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.robot_speak
,
(long)"Robots can speak in locations their owners do not\n\t\t\t\tcontrol" },
{(char *)"room_flags",
cf_set_flags,
CA_GOD,
CA_DISABLED,
(int *)&
mudconf.room_flags, 0},
{(char *)"room_parent",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.room_parent
,
NOTHING},
{(char *)"room_proto",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.room_proto
,
NOTHING},
{(char *)"room_attr_defaults",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
room_defobj,
NOTHING},
{(char *)"room_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.room_quota
,
0},
{(char *)"sacrifice_adjust",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
sacadjust,
0},
{(char *)"sacrifice_factor",
cf_int_factor,
CA_GOD,
CA_PUBLIC, &mudconf
.sacfactor,
0},
{(char *)"safer_passwords",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
safer_passwords,
(long)"Passwords must satisfy minimum security standards" },
{(char *)"say_uses_comma",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.comma_say,
(long)"Say uses a grammatically-correct comma" },
{(char *)"say_uses_you",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.you_say,
(long)"Say uses You rather than the player name" },
{(char *)"search_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.searchcost
,
0},
{(char *)"see_owned_dark",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
see_own_dark,
(long)"look shows DARK objects owned by you" },
{(char *)"signal_action",
cf_option, CA_STATIC, CA_GOD,
&mudconf.sig_action
,
(long)sigactions_nametab},
{(char *)"site_chars",
cf_int,
CA_GOD,
CA_WIZARD, &mudconf.site_chars
,
MBUF_SIZE - 2},
{(char *)"space_compress",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
space_compress,
(long)"Multiple spaces are compressed to a single space" },
{(char *)"sql_database",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
sql_db,
MBUF_SIZE},
{(char *)"sql_host",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
sql_host,
MBUF_SIZE},
{(char *)"sql_username",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
sql_username,
MBUF_SIZE},
{(char *)"sql_password",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
sql_password,
MBUF_SIZE},
{(char *)"sql_reconnect",
cf_bool,
CA_GOD,
CA_WIZARD, &mudconf.
sql_reconnect,
(long)"SQL queries re-initiate dropped connections" },
{(char *)"stack_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.stack_lim,
0},
{(char *)"starting_money",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.paystart,
0},
{(char *)"starting_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.start_quota
,
0},
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832

Saturday, June 16, 2012 11:50 PM

{(char *)"starting_exit_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
start_exit_quota, 0},
{(char *)"starting_player_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
start_player_quota,
0},
{(char *)"starting_room_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
start_room_quota, 0},
{(char *)"starting_thing_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
start_thing_quota, 0},
{(char *)"status_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
status_file,
MBUF_SIZE},
{(char *)"stripped_flags",
cf_set_flags,
CA_GOD,
CA_DISABLED,
(int *)&
mudconf.stripped_flags, 0},
{(char *)"structure_delimiter_string", cf_string, CA_GOD,
CA_PUBLIC, (int *)&
mudconf.struct_dstr,
0},
{(char *)"structure_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.struct_lim
,
0},
{(char *)"suspect_site",
cf_site,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.suspect_list, H_SUSPECT},
{(char *)"sweep_dark",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.sweep_dark
,
(long)"@sweep works on Dark locations" },
{(char *)"switch_default_all",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
switch_df_all,
(long)"@switch default is /all, not /first" },
{(char *)"terse_shows_contents",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
terse_contents,
(long)"TERSE suppresses the contents list of a location" },
{(char *)"terse_shows_exits",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
terse_exits,
(long)"TERSE suppresses the exit list of a location" },
{(char *)"terse_shows_move_messages",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
terse_movemsg,
(long)"TERSE suppresses movement messages" },
{(char *)"text_home",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
txthome,
MBUF_SIZE},
{(char *)"thing_flags",
cf_set_flags,
CA_GOD,
CA_DISABLED,
(int *)&
mudconf.thing_flags,
0},
{(char *)"thing_parent",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
thing_parent,
NOTHING},
{(char *)"thing_proto",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.thing_proto
,
NOTHING},
{(char *)"thing_attr_defaults",
cf_dbref,
CA_GOD,
CA_PUBLIC, &mudconf.
thing_defobj,
NOTHING},
{(char *)"thing_quota",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.thing_quota
,
0},
{(char *)"timeslice",
cf_int_factor,
CA_GOD,
CA_PUBLIC, &mudconf.
timeslice,
0},
{(char *)"trace_output_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
trace_limit,
0},
{(char *)"trace_topdown",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
trace_topdown,
(long)"Trace output is top-down"},
{(char *)"trust_site",
cf_site,
CA_GOD,
CA_DISABLED,
(int *)&mudstate
.suspect_list, 0},
{(char *)"typed_quotas",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
typed_quotas,
(long)"Quotas are enforced per object type" },
{(char *)"unowned_safe",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
safe_unowned,
(long)"Objects not owned by you are considered SAFE" },
{(char *)"user_attr_access",
cf_modify_bits, CA_GOD,
CA_DISABLED,
&mudconf
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873

Saturday, June 16, 2012 11:50 PM

.vattr_flags,
(long)attraccess_nametab},
{(char *)"use_global_aconn",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
use_global_aconn, (long)"Global @Aconnects and @Adisconnects are used" },
{(char *)"variables_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.numvars_lim
,
0},
{(char *)"visible_wizards",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
visible_wizzes,
(long)"DARK Wizards are hidden from WHO but not invisible" },
{(char *)"wait_cost",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.waitcost,
0},
{(char *)"wildcard_match_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
wild_times_lim,
0},
{(char *)"wizard_obeys_linklock",
cf_bool,
CA_GOD,
CA_PUBLIC, &mudconf.
wiz_obey_linklock, (long)"Check LinkLock even if player can link to anything" },
{(char *)"wizard_motd_file",
cf_string, CA_STATIC, CA_GOD,
(int *)&mudconf.
wizmotd_file,
MBUF_SIZE},
{(char *)"wizard_motd_message",
cf_string, CA_GOD,
CA_WIZARD, (int *)&mudconf.
wizmotd_msg,
GBUF_SIZE},
{(char *)"zone_recursion_limit",
cf_int,
CA_GOD,
CA_PUBLIC, &mudconf.
zone_nest_lim,
0},
{ NULL,
NULL,
0,
0,
NULL,
0}};
/* *INDENT-ON* */
/* --------------------------------------------------------------------------* cf_set: Set config parameter.
*/
static int helper_cf_set(cp, ap, player, tp)
char *cp, *ap;
dbref player;
CONF *tp;
{
int i;
char *buff;
if (!mudstate.standalone && !mudstate.initializing && !check_access(player, tp->
flags)) {
notify(player, NOPERM_MESSAGE);
return (-1);
}
if (!mudstate.initializing) {
buff = alloc_lbuf("cf_set");
StringCopy(buff, ap);
}
i = tp->interpreter(tp->loc, ap, tp->extra, player, cp);
if (!mudstate.initializing) {
STARTLOG(LOG_CONFIGMODS, "CFG", "UPDAT")
log_name(player);
log_printf(" entered config directive: %s with args '%s'. Status: " , cp,
strip_ansi(buff));
switch (i) {
case 0:
-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

Saturday, June 16, 2012 11:50 PM

log_printf("Success.");
break;
case 1:
log_printf("Partial success.");
break;
case -1:
log_printf("Failure.");
break;
default:
log_printf("Strange.");
}
ENDLOG
free_lbuf(buff);
}
return i;

int cf_set(cp, ap, player)


char *cp, *ap;
dbref player;
{
CONF *tp, *ctab;
MODULE *mp;
/*
* Search the config parameter table for the command. If we find it,
* call the handler to parse the argument.
*/
/* Make sure that if we're standalone, the paramaters we need to
* load module flatfiles are loaded */
if (mudstate.standalone && strcmp(cp, "module") &&
strcmp(cp, "database_home")) {
return 0;
}
for (tp = conftable; tp->pname; tp++) {
if (!strcmp(tp->pname, cp)) {
return (helper_cf_set(cp, ap, player, tp));
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (!strcmp(tp->pname, cp))
return (helper_cf_set(cp, ap, player, tp));
}
}
}

-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979

/* Config directive not found.

Saturday, June 16, 2012 11:50 PM

Complain about it. */

if (!mudstate.standalone)
cf_log_notfound(player, (char *)"Set", "Config directive", cp);
}

return (-1);

/* --------------------------------------------------------------------------* do_admin: Command handler to set config params at runtime


*/
void do_admin(player, cause, extra, kw, value)
dbref player, cause;
int extra;
char *kw, *value;
{
int i;

i = cf_set(kw, value, player);


if ((i >= 0) && !Quiet(player))
notify(player, "Set.");
return;

/* --------------------------------------------------------------------------* cf_read: Read in config parameters from named file


*/
int cf_read(fn)
char *fn;
{
int retval;
char tmpfile[256], *c;
mudconf.config_file = XSTRDUP(fn, "cf_read.config_file");
mudstate.initializing = 1;
retval = cf_include(NULL, fn, 0, 0, (char *)"init");
mudstate.initializing = 0;
/* Fill in missing DB file names */
strcpy(tmpfile, mudconf.gdbm);
if ((c = strchr(tmpfile, '.')) != NULL)
*c = '\0';

if (!*mudconf.crashdb) {
XFREE(mudconf.crashdb, "cf_read_crashdb");
mudconf.crashdb = XSTRDUP(tprintf("%s.CRASH", tmpfile),
"cf_read_crashdb");
}
return retval;

-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

Saturday, June 16, 2012 11:50 PM

/* --------------------------------------------------------------------------* list_cf_access, list_cf_read_access: List write or read access to


* config directives.
*/
void list_cf_access(player)
dbref player;
{
CONF *tp, *ctab;
char *buff;
MODULE *mp;
buff = alloc_mbuf("list_cf_access");
for (tp = conftable; tp->pname; tp++) {
if (God(player) || check_access(player, tp->flags)) {
sprintf(buff, "%s:", tp->pname);
listset_nametab(player, access_nametab, tp->flags,
buff, 1);
}
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (God(player) || check_access(player, tp->flags)) {
sprintf(buff, "%s:", tp->pname);
listset_nametab(player, access_nametab, tp->flags,
buff, 1);
}
}
}
}
}

free_mbuf(buff);

void list_cf_read_access(player)
dbref player;
{
CONF *tp, *ctab;
char *buff;
MODULE *mp;
buff = alloc_mbuf("list_cf_read_access");
for (tp = conftable; tp->pname; tp++) {
if (God(player) || check_access(player, tp->rperms)) {
sprintf(buff, "%s:", tp->pname);
listset_nametab(player, access_nametab, tp->rperms,
buff, 1);
-43-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085

Saturday, June 16, 2012 11:50 PM

WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (God(player) || check_access(player, tp->rperms)) {
sprintf(buff, "%s:", tp->pname);
listset_nametab(player, access_nametab, tp->rperms,
buff, 1);
}
}
}
}
}

free_mbuf(buff);

/* --------------------------------------------------------------------------* cf_verify: Walk all configuration tables and validate any dbref values.
*/
#define Check_Conf_Dbref(x) \
if ((x)->interpreter == cf_dbref) { \
if (!((((x)->extra == NOTHING) && (*((x)->loc) == NOTHING)) || \
(Good_obj(*((x)->loc)) && !Going(*((x)->loc))))) { \
STARTLOG(LOG_ALWAYS, "CNF", "VRFY") \
log_printf("%s #%d is invalid. Reset to #%d.", \
(x)->pname, *((x)->loc), (x)->extra); \
ENDLOG \
*((x)->loc) = (dbref) (x)->extra; \
} \
}
void cf_verify()
{
CONF *tp, *ctab;
MODULE *mp;
for (tp = conftable; tp->pname; tp++) {
Check_Conf_Dbref(tp);
}

WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
Check_Conf_Dbref(tp);
}
}
}

-44-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138

Saturday, June 16, 2012 11:50 PM

/* --------------------------------------------------------------------------* cf_display: Given a config parameter by name, return its value in some
* sane fashion.
*/
static void helper_cf_display(player, buff, bufc, tp)
dbref player;
char *buff, **bufc;
CONF *tp;
{
NAMETAB *opt;

if (!check_access(player, tp->rperms)) {
safe_noperm(buff, bufc);
return;
}
if ((tp->interpreter == cf_bool) ||
(tp->interpreter == cf_int) ||
(tp->interpreter == cf_int_factor) ||
(tp->interpreter == cf_const)) {
safe_ltos(buff, bufc, *(tp->loc));
return;
}
if ((tp->interpreter == cf_string)) {
safe_str(*((char **)tp->loc), buff, bufc);
return;
}
if ((tp->interpreter == cf_dbref)) {
safe_dbref(buff, bufc, *(tp->loc));
return;
}
if ((tp->interpreter == cf_option)) {
opt = find_nametab_ent_flag(GOD, (NAMETAB *)tp->extra, *(tp->loc));
safe_str((opt ? opt->name : "*UNKNOWN*"), buff, bufc);
return;
}
safe_noperm(buff, bufc);
return;

void cf_display(player, param_name, buff, bufc)


dbref player;
char *param_name;
char *buff;
char **bufc;
{
CONF *tp, *ctab;
MODULE *mp;
for (tp = conftable; tp->pname; tp++) {
if (!strcasecmp(tp->pname, param_name)) {
helper_cf_display(player, buff, bufc, tp);
-45-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191

}
}

Saturday, June 16, 2012 11:50 PM

return;

WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (!strcasecmp(tp->pname, param_name)) {
helper_cf_display(player, buff, bufc, tp);
return;
}
}
}
}
}

safe_nomatch(buff, bufc);

void list_options(player)
dbref player;
{
CONF *tp, *ctab;
MODULE *mp;
for (tp = conftable; tp->pname; tp++) {
if (((tp->interpreter == cf_const) ||
(tp->interpreter == cf_bool)) &&
(check_access(player, tp->rperms))) {

}
}

raw_notify(player, tprintf("%-25s %c %s?",


tp->pname,
(*(tp->loc) ? 'Y' : 'N'),
(tp->extra ? (char *)tp->extra : "")));

WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (((tp->interpreter == cf_const) ||
(tp->interpreter == cf_bool)) &&
(check_access(player, tp->rperms))) {

}
}

}
}

raw_notify(player, tprintf("%-25s %c %s?",


tp->pname,
(*(tp->loc) ? 'Y' : 'N'),
(tp->extra ? (char *)tp->extra : "")));

-46-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\conf.c

2192
2193

Saturday, June 16, 2012 11:50 PM

-47-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\config.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

Saturday, June 16, 2012 11:15 PM

/* config.h - Configuration of compile-time options, limits, db format, etc. */


/* $Id: config.h,v 1.45 2004/10/04 20:31:27 tyrspace Exp $ */
#include "copyright.h"
#ifndef __CONFIG_H
#define __CONFIG_H
/* Do not change anything unless you are certain you know what it does.
* General user-definable compile-time options can be found in the
* Makefile.
*/
#define
#define
#define
#define
#define
#define
#define
#define

CONF_FILE
LOG_FILE
PID_FILE
BIN_DIR
TXT_DIR
DATA_DIR
DB_FILE
CRASH_FILE

"netmush.conf"
/* Default config file */
"netmush.log"
/* Default log file */
"netmush.pid"
/* Default pid file */
"./bin"
/* Default binary directory */
"./text"
/* Default text directory */
"./data"
/* Default data directory */
"netmush.gdbm"
/* Default database name */
"netmush.db.CRASH"
/* Default crash database name */

#define
#define
#define
#define

PLAYER_NAME_LIMIT
NUM_ENV_VARS
MAX_ARG
100
MAX_ITER_NESTING

22 /* Max length for player names */


10 /* Number of env vars (%0 et al) */
/* max # args from command processor */
1024
/* max # of iter levels */

#ifndef MAX_GLOBAL_REGS
#define MAX_GLOBAL_REGS
#endif

36

#ifndef MAX_DELIM_LEN
#define MAX_DELIM_LEN
#endif

128 /* Maximum length of a delimiter. */

#define MARK_FLAG_SEP

'_' /* sep. of dbref from marker flags */

#define HASH_FACTOR

/* r() registers: must be 10 or 36 */

/* How much hashing you want. */

#define OUTPUT_BLOCK_SIZE

16384

#define DOING_LEN

/* length of the DOING field in WHO */

41

#define PUEBLO_SUPPORT_MSG "This world is Pueblo 1.0 enhanced\r\n\r\n"


/* --------------------------------------------------------------------------* Database R/W flags.
*/
#define MANDFLAGS
(V_LINK|V_PARENT|V_XFLAGS|V_ZONE|V_POWERS|V_3FLAGS|V_QUOTED|V_TQUOTAS|V_TIMESTAMPS|V_VISU
ALATTRS)

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\config.h

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

Saturday, June 16, 2012 11:15 PM

#define OFLAGS1

(V_GDBM|V_ATRKEY)

#define OFLAGS2

(V_ATRNAME|V_ATRMONEY)

#define OUTPUT_VERSION
#define OUTPUT_FLAGS

/* GDBM has these */

1
/* Version 1 */
(MANDFLAGS|OFLAGS1|OFLAGS2)
/* format for dumps */

#define UNLOAD_VERSION 1
/* version for export */
#define UNLOAD_OUTFLAGS (MANDFLAGS)
/* format for export */
/* magic lock cookies */
#define NOT_TOKEN
'!'
#define AND_TOKEN
'&'
#define OR_TOKEN
'|'
#define LOOKUP_TOKEN
'*'
#define NUMBER_TOKEN
'#'
#define INDIR_TOKEN '@'
/* One of these two should go. */
#define CARRY_TOKEN '+'
/* One of these two should go. */
#define IS_TOKEN
'='
#define OWNER_TOKEN '$'
/* matching attribute tokens */
#define AMATCH_CMD '$'
#define AMATCH_LISTEN
'^'
/* delimiters for various things */
#define EXIT_DELIMITER ';'
#define ARG_DELIMITER
'='
/* These chars get replaced by the current item from a list in commands and
* functions that do iterative replacement, such as @apply_marked, dolist,
* the eval= operator for @search, and iter().
*/
#define BOUND_VAR
"##"
#define LISTPLACE_VAR
"#@"
/* This token is similar, marking the first argument in a switch. */
#define SWITCH_VAR

"#$"

/* This token is used to denote a null output delimiter. */


#define NULL_DELIM_VAR

"@@"

/* This is used to indent output from pretty-printing. */


#define INDENT_STR

"

"

/* This is used as the 'null' delimiter for structures stored via write(). */
#define GENERIC_STRUCT_DELIM

'\f'
-2-

/* form feed char */

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\config.h

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

#define GENERIC_STRUCT_STRDELIM

Saturday, June 16, 2012 11:15 PM

"\f"

/* amount of object endowment, based on cost */


#define OBJECT_ENDOWMENT(cost) (((cost)/mudconf.sacfactor) +mudconf.sacadjust)
/* !!! added for recycling, return value of object */
#define OBJECT_DEPOSIT(pennies) \
(((pennies)-mudconf.sacadjust)*mudconf.sacfactor)
#define StringCopy strcpy
#define StringCopyTrunc strncpy
#define DEV_NULL "/dev/null"
#define READ read
#define WRITE write
#endif /* __CONFIG_H */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\copyright.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:14 PM

/* copyright.h */
/* $Id: copyright.h,v 1.13 2009/01/12 01:31:26 lwl Exp $ */
/* -*-C-*- */
#ifndef __COPYRIGHT_H
#define __COPYRIGHT_H
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*

TinyMUSH 3 Source Code


Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009 by Lydia Leong,
David Passmore, Robby Griffin, Scott Dorr, and Eddy Beaupre.
Copyright (c) 2001, 2002, 2003, by Lydia Leong, David Passmore,
Robby Griffin, and Scott Dorr.
Copyright (c) 2000 by Lydia Leong, David Passmore, and Robby Griffin.
Copyright (c) 1999 by Lydia Leong and David Passmore.
All rights reserved.
See http://tinymush.sourceforge.net/ for more information.
TinyMUX Source Code
Copyright (c) 1995, 1996, 1997, 1998, 1999, David Passmore.
TinyMUSH 2.2 Source Code
Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, Lydia Leong,
Jean Marie Diaz, and Deborah Wilson-Hooker.
TinyMUSH 2.0 Source code
Copyright (c) 1991, Joseph Traub and Glenn Crocker. All rights reserved.
Based on TinyMUD code
Copyright (c) 1995, David Applegate, James Aspnes, Timothy Freeman,
and Bennet Yee. All rights reserved.
(Modified by these authors from the original 1989, 1990 TinyMUD copyright.)
--TinyMUSH 3 is a derivation of TinyMUSH 2.2 and TinyMUX, both of which
are derivations of TinyMUSH 2.0, which in turn is based upon TinyMUD.
There are also portions of source code derived from PennMUSH 1.50.
The TinyMUD copyright follows below. PennMUSH, TinyMUSH 2.0, TinyMUSH 2.2,
and TinyMUSH 3 follow the OSI-standard Artistic License.
--Revised TinyMUD copyright:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that: (1) source code distributions
retain the above copyright notice and this paragraph in its entirety,
and (2) distributions including binary code include the above copyright
notice and this paragraph in its entirety in the documentation or other
materials provided with the distribution. The names of the copyright
holders may not be used to endorse or promote products derived from
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\copyright.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*

Saturday, June 16, 2012 11:14 PM

this software without specific prior written permission.


THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
--TinyMUSH 3 Copyright: The Artistic License
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to
make reasonable modifications.
Definitions:
- "Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
- "Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes of
the Copyright Holder.
- "Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
- "You" is you, if you're thinking about copying or distributing
this Package.
- "Reasonable copying fee" is whatever you can justify on the basis
of media cost, duplication charges, time of people involved, and
so on. (You will not be required to justify it to the Copyright
Holder, but only to the computing community at large as a market
that must bear the fee.)
- "Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item. It
also means that recipients of the item may redistribute it under
the same conditions they received it.
1. You may make and give away verbatim copies of the source form of
the Standard Version of this Package without restriction, provided
that you duplicate all of the original copyright notices and
associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way,
provided that you insert a prominent notice in each changed file
stating how and when you changed that file, and provided that you do
at least ONE of the following:
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\copyright.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*

Saturday, June 16, 2012 11:14 PM

a) place your modifications in the Public Domain or otherwise make


them Freely Available, such as by posting said modifications to
Usenet or an equivalent medium, or placing the modifications on a
major archive site such as ftp.uu.net, or by allowing the Copyright
Holder to include your modifications in the Standard Version of the
Package.
b) use the modified Package only within your corporation or
organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that
clearly documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library
files, together with instructions (in the manual page or
equivalent) on where to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) accompany any non-standard executables with their corresponding
Standard Version executables, giving the non-standard executables
non-standard names, and clearly documenting the differences in
manual pages (or equivalent), together with instructions on where
to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of
this Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial)
software distribution provided that you do not advertise this Package
as a product of your own.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whomever generated
them, and may be sold commercially, and may be aggregated with this
Package.
7. C or perl subroutines supplied by you and linked into this Package
shall not be considered part of this Package.
8. The name of the Copyright Holder may not be used to endorse or
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\copyright.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:14 PM

* promote products derived from this software without specific prior


* written permission.
*
* 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* The authors may be reached via email at tinymush-dev@godlike.com.
*
* --*
* TinyMUSH 2.0 Credits:
*
Lawrence Foard:
*
Wrote the original TinyMUSH 1.0 code from which this later derived.
*
Jin (and MicroMUSH):
*
Made many, many changes to the code that improved it immensely.
*
Robert Hood (virus):
*
Modified the interface.c code to support alots of users.
*
Lachesis:
*
Introduced the idea of property lists to TinyMUCK
*
Many others:
*
Many features borrowed from other muds.
*
* --*
* TinyMUSH 2.2 Credits:
*
* TinyMUSH 2.2 is the result of the efforts of many, many people. A few
* deserve special mention here: Andrew Molitor, Russ Smith, Mark Vasoll,
* and Dave McCracken for much in the way of code and advice; Alan Schwartz
* and T. Alexander "Talek" Popiel (PennMUSH) and David Passmore (TinyMUX)
* for ideas and code; and John Batzel (and the rest of the PernMUSH
* wizcrew) for beta-testing, many ideas, and a lot of patience.
*
* --*
* TinyMUSH 3 Credits:
*
* Many people contributed to the end result which is TinyMUSH 3. They
* include:
*
* - Fred "Iago" Hicks, for the logo
* - Deborah Wilson-Hooker, T. Alexander Popiel, JT Traub, and
*
Andrew Molitor, as always
* - The players of From the Ashes, Babylon 5: The Last Best Hope,
*
and Blood of Amber, for alpha testing
* - The TinyMUX and Hogs lists, and the players of the Godlike Edge,
*
for everything
*
* ... and everyone who participated in the religious wars between TinyMUSH
*
and TinyMUX, which ultimately spurred our decision to merge them. :)
*/

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\copyright.h

213
214

Saturday, June 16, 2012 11:14 PM

#endif /* __COPYRIGHT_H */

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:49 PM

/* cque.c - commands and functions for manipulating the command queue */


/* $Id: cque.c,v 1.39 2003/06/03 16:18:38 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include <signal.h>
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include

"match.h" /* required by code */


"attrs.h" /* required by code */
"powers.h" /* required by code */
"command.h"
/* required by code */

extern int FDECL(a_Queue, (dbref, int));


extern void FDECL(s_Queue, (dbref, int));
extern int FDECL(QueueMax, (dbref));
/* --------------------------------------------------------------------------* add_to: Adjust an object's queue or semaphore count.
*/
static int add_to(doer, player, am, attrnum)
dbref doer, player;
int am, attrnum;
{
int num, aflags, alen;
dbref aowner;
char buff[20];
char *atr_gotten;

num = atoi(atr_gotten = atr_get(player, attrnum, &aowner,


&aflags, &alen));
free_lbuf(atr_gotten);
num += am;
if (num)
ltos(buff, num);
else
*buff = '\0';
atr_add(player, attrnum, buff, Owner(doer), aflags);
return (num);

/* ---------------------------------------------------------------------------1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:49 PM

* give_que: Thread a queue block onto the high or low priority queue
*/
static void give_que(tmp)
BQUE *tmp;
{
tmp->next = NULL;
tmp->waittime = 0;
/* Thread the command into the correct queue */

if (Typeof(tmp->cause) == TYPE_PLAYER) {
if (mudstate.qlast != NULL) {
mudstate.qlast->next = tmp;
mudstate.qlast = tmp;
} else
mudstate.qlast = mudstate.qfirst = tmp;
} else {
if (mudstate.qllast) {
mudstate.qllast->next = tmp;
mudstate.qllast = tmp;
} else
mudstate.qllast = mudstate.qlfirst = tmp;
}

/* --------------------------------------------------------------------------* que_want: Do we want this queue entry?


*/
static int que_want(entry, ptarg, otarg)
BQUE *entry;
dbref ptarg, otarg;
{
if (!Good_obj(entry->player))
return 0;
if ((ptarg != NOTHING) && (ptarg != Owner(entry->player)))
return 0;
if ((otarg != NOTHING) && (otarg != entry->player))
return 0;
return 1;
}
/* --------------------------------------------------------------------------* halt_que: Remove all queued commands from a certain player
*/
int halt_que(player, object)
dbref player, object;
{
BQUE *trail, *point, *next;
int numhalted, halt_all, i;
int *dbrefs_array;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:49 PM

numhalted = 0;
halt_all = ((player == NOTHING) && (object == NOTHING)) ? 1 : 0;
if (halt_all)
dbrefs_array = (int *) XCALLOC(mudstate.db_top, sizeof(int),
"halt_que.dbrefs");
/* Player queue */
for (point = mudstate.qfirst; point; point = point->next)
if (que_want(point, player, object)) {
numhalted++;
if (halt_all && Good_obj(point->player))
dbrefs_array[Owner(point->player)] += 1;
point->player = NOTHING;
}
/* Object queue */
for (point = mudstate.qlfirst; point; point = point->next)
if (que_want(point, player, object)) {
numhalted++;
if (halt_all && Good_obj(point->player))
dbrefs_array[Owner(point->player)] += 1;
point->player = NOTHING;
}
/* Wait queue */
for (point = mudstate.qwait, trail = NULL; point; point = next)
if (que_want(point, player, object)) {
numhalted++;
if (halt_all && Good_obj(point->player))
dbrefs_array[Owner(point->player)] += 1;
if (trail)
trail->next = next = point->next;
else
mudstate.qwait = next = point->next;
Free_QData(point);
free_qentry(point);
} else
next = (trail = point)->next;
/* Semaphore queue */
for (point = mudstate.qsemfirst, trail = NULL; point; point = next)
if (que_want(point, player, object)) {
numhalted++;
if (halt_all && Good_obj(point->player))
dbrefs_array[Owner(point->player)] += 1;
if (trail)
trail->next = next = point->next;
else
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:49 PM

mudstate.qsemfirst = next = point->next;


if (point == mudstate.qsemlast)
mudstate.qsemlast = trail;
add_to(player, point->sem, -1, point->attr);
Free_QData(point);
free_qentry(point);
} else
next = (trail = point)->next;
if (halt_all) {
for (i = 0; i < mudstate.db_top; i++) {
if (dbrefs_array[i]) {
giveto(i, (mudconf.waitcost * dbrefs_array[i]));
s_Queue(i, 0);
}
}
XFREE(dbrefs_array, "halt_que.dbrefs");
return numhalted;
}

if (player == NOTHING)
player = Owner(object);
giveto(player, (mudconf.waitcost * numhalted));
if (object == NOTHING)
s_Queue(player, 0);
else
a_Queue(player, -numhalted);
return numhalted;

/* --------------------------------------------------------------------------* do_halt: Command interface to halt_que.


*/
void do_halt(player, cause, key, target)
dbref player, cause;
int key;
char *target;
{
dbref player_targ, obj_targ;
int numhalted;
if ((key & HALT_ALL) && !(Can_Halt(player))) {
notify(player, NOPERM_MESSAGE);
return;
}
/* Figure out what to halt */
if (!target || !*target) {
obj_targ = NOTHING;
if (key & HALT_ALL) {
player_targ = NOTHING;
} else {
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:49 PM

player_targ = Owner(player);
if (Typeof(player) != TYPE_PLAYER)
obj_targ = player;

}
} else {
if (Can_Halt(player))
obj_targ = match_thing(player, target);
else
obj_targ = match_controlled(player, target);

if (!Good_obj(obj_targ))
return;
if (key & HALT_ALL) {
notify(player, "Can't specify a target and /all" );
return;
}
if (Typeof(obj_targ) == TYPE_PLAYER) {
player_targ = obj_targ;
obj_targ = NOTHING;
} else {
player_targ = NOTHING;
}

numhalted = halt_que(player_targ, obj_targ);


if (Quiet(player))
return;
if (numhalted == 1)
notify(Owner(player), "1 queue entries removed.");
else
notify(Owner(player),
tprintf("%d queue entries removed.", numhalted));

/* --------------------------------------------------------------------------* nfy_que: Notify commands from the queue and perform or discard them.
*/
int nfy_que(player, sem, attr, key, count)
dbref player, sem;
int attr, key, count;
{
BQUE *point, *trail, *next;
int num, aflags, alen;
dbref aowner;
char *str;
if (attr) {
str = atr_get(sem, attr, &aowner, &aflags, &alen);
num = atoi(str);
free_lbuf(str);
} else {
num = 1;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:49 PM

}
if (num > 0) {
num = 0;
for (point = mudstate.qsemfirst, trail = NULL; point; point = next) {
if ((point->sem == sem) &&
((point->attr == attr) || !attr)) {
num++;
if (trail)
trail->next = next = point->next;
else
mudstate.qsemfirst = next = point->next;
if (point == mudstate.qsemlast)
mudstate.qsemlast = trail;
/* Either run or discard the command */
if (key != NFY_DRAIN) {
give_que(point);
} else {
giveto(point->player,
mudconf.waitcost);
a_Queue(Owner(point->player), -1);
Free_QData(point);
free_qentry(point);
}
} else {
next = (trail = point)->next;
}
/* If we've notified enough, exit */
if ((key == NFY_NFY) && (num >= count))
next = NULL;

}
} else {
num = 0;
}

/* Update the sem waiters count */


if (key == NFY_NFY)
add_to(player, sem, -count, (attr ? attr : A_SEMAPHORE));
else
atr_clr(sem, (attr ? attr: A_SEMAPHORE));
}

return num;

/* --------------------------------------------------------------------------* do_notify: Command interface to nfy_que


*/

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:49 PM

void do_notify(player, cause, key, what, count)


dbref player, cause;
int key;
char *what, *count;
{
dbref thing, aowner;
int loccount, attr, aflags;
ATTR *ap;
char *obj;
obj = parse_to(&what, '/', 0);
init_match(player, obj, NOTYPE);
match_everything(0);
if ((thing = noisy_match_result()) < 0) {
notify(player, "No match.");
} else if (!controls(player, thing) && !Link_ok(thing)) {
notify(player, NOPERM_MESSAGE);
} else {
if (!what || !*what) {
ap = NULL;
} else {
ap = atr_str(what);
}
if (!ap) {
attr = A_SEMAPHORE;
} else {
/* Do they have permission to set this attribute? */
atr_pget_info(thing, ap->number, &aowner, &aflags);
if (Set_attr(player, thing, ap, aflags)) {
attr = ap->number;
} else {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
}

if (count && *count)


loccount = atoi(count);
else
loccount = 1;
if (loccount > 0) {
nfy_que(player, thing, attr, key, loccount);
if (!(Quiet(player) || Quiet(thing))) {
if (key == NFY_DRAIN)
notify_quiet(player, "Drained.");
else
notify_quiet(player, "Notified.");
}
}

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:49 PM

/* --------------------------------------------------------------------------* setup_que: Set up a queue entry.


*/
static BQUE *setup_que(player, cause, command, args, nargs, gargs)
dbref player, cause;
char *command, *args[];
int nargs;
GDATA *gargs;
{
int a, tlen;
BQUE *tmp;
char *tptr;
/* Can we run commands at all? */
if (Halted(player))
return NULL;
/* make sure player can afford to do it */
a = mudconf.waitcost;
if (a && mudconf.machinecost && (Randomize(mudconf.machinecost) == 0))
a++;
if (!payfor(player, a)) {
notify(Owner(player), "Not enough money to queue command." );
return NULL;
}
/* Wizards and their objs may queue up to db_top+1 cmds. Players are
* limited to QUEUE_QUOTA. -mnp
*/
a = QueueMax(Owner(player));
if (a_Queue(Owner(player), 1) > a) {
notify(Owner(player),
"Run away objects: too many commands queued.
halt_que(Owner(player), NOTHING);
/* halt also means no command execution allowed */
s_Halted(player);
return NULL;

}
/* We passed all the tests */

/* Calculate the length of the save string */


tlen = 0;
if (command)
tlen = strlen(command) + 1;
if (nargs > NUM_ENV_VARS)
nargs = NUM_ENV_VARS;
for (a = 0; a < nargs; a++) {
-8-

Halted." );

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:49 PM

if (args[a])
tlen += (strlen(args[a]) + 1);

}
if (gargs) {
for (a = 0; a < gargs->q_alloc; a++) {
if (gargs->q_regs[a])
tlen += gargs->q_lens[a] + 1;
}
for (a = 0; a < gargs->xr_alloc; a++) {
if (gargs->x_names[a] && gargs->x_regs[a]) {
tlen += strlen(gargs->x_names[a]) +
gargs->x_lens[a] + 2;
}
}
}
/* Create the queue entry and load the save string */
tmp = alloc_qentry("setup_que.qblock");
if (!(tptr = tmp->text = (char *) XMALLOC(tlen, "setup_que"))) {
free_qentry(tmp);
return (BQUE *) NULL;
}
tmp->comm = NULL;
for (a = 0; a < NUM_ENV_VARS; a++) {
tmp->env[a] = NULL;
}
Alloc_RegData("setup_que", gargs, tmp->gdata);
if (command) {
strcpy(tptr, command);
tmp->comm = tptr;
tptr += (strlen(command) + 1);
}
for (a = 0; a < nargs; a++) {
if (args[a]) {
strcpy(tptr, args[a]);
tmp->env[a] = tptr;
tptr += (strlen(args[a]) + 1);
}
}
if (gargs && gargs->q_alloc) {
for (a = 0; a < gargs->q_alloc; a++) {
if (gargs->q_regs[a]) {
tmp->gdata->q_lens[a] = gargs->q_lens[a];
memcpy(tptr, gargs->q_regs[a], gargs->q_lens[a] + 1);
tmp->gdata->q_regs[a] = tptr;
tptr += gargs->q_lens[a] + 1;
}
}
}
if (gargs && gargs->xr_alloc) {
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:49 PM

for (a = 0; a < gargs->xr_alloc; a++) {


if (gargs->x_names[a] && gargs->x_regs[a]) {
strcpy(tptr, gargs->x_names[a]);
tmp->gdata->x_names[a] = tptr;
tptr += strlen(gargs->x_names[a]) + 1;
tmp->gdata->x_lens[a] = gargs->x_lens[a];
memcpy(tptr, gargs->x_regs[a], gargs->x_lens[a] + 1);
tmp->gdata->x_regs[a] = tptr;
tptr += gargs->x_lens[a] + 1;
}
}

/* Load the rest of the queue block */

tmp->player = player;
tmp->waittime = 0;
tmp->next = NULL;
tmp->sem = NOTHING;
tmp->attr = 0;
tmp->cause = cause;
tmp->nargs = nargs;
return tmp;

/* --------------------------------------------------------------------------* wait_que: Add commands to the wait or semaphore queues.


*/
void wait_que(player, cause, wait, sem, attr, command, args, nargs, gargs)
dbref player, cause, sem;
int wait, nargs, attr;
char *command, *args[];
GDATA *gargs;
{
BQUE *tmp, *point, *trail;
if (mudconf.control_flags & CF_INTERP)
tmp = setup_que(player, cause, command, args, nargs, gargs);
else
tmp = NULL;
if (tmp == NULL) {
return;
}
if (wait != 0)
tmp->waittime = time(NULL) + wait;
tmp->sem = sem;
tmp->attr = attr;
if (sem == NOTHING) {
/* No semaphore, put on wait queue if wait value specified.
* Otherwise put on the normal queue.
*/
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:49 PM

if (wait <= 0) {
give_que(tmp);
} else {
for (point = mudstate.qwait, trail = NULL;
point && point->waittime <= tmp->waittime;
point = point->next) {
trail = point;
}
tmp->next = point;
if (trail != NULL)
trail->next = tmp;
else
mudstate.qwait = tmp;
}
} else {
tmp->next = NULL;
if (mudstate.qsemlast != NULL)
mudstate.qsemlast->next = tmp;
else
mudstate.qsemfirst = tmp;
mudstate.qsemlast = tmp;
}

/* --------------------------------------------------------------------------* do_wait: Command interface to wait_que


*/
void do_wait(player, cause, key, event, cmd, cargs, ncargs)
dbref player, cause;
int key, ncargs;
char *event, *cmd, *cargs[];
{
dbref thing, aowner;
int howlong, num, attr, aflags;
char *what;
ATTR *ap;
/* If arg1 is all numeric, do simple (non-sem) timed wait. */
if (is_number(event)) {
howlong = atoi(event);
wait_que(player, cause, howlong, NOTHING, 0, cmd,
cargs, ncargs, mudstate.rdata);
return;
}
/* Semaphore wait with optional timeout */
what = parse_to(&event, '/', 0);
init_match(player, what, NOTYPE);
match_everything(0);
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:49 PM

thing = noisy_match_result();
if (!Good_obj(thing)) {
notify(player, "No match.");
} else if (!controls(player, thing) && !Link_ok(thing)) {
notify(player, NOPERM_MESSAGE);
} else {
/* Get timeout, default 0 */
if (event && *event && is_number(event)) {
attr = A_SEMAPHORE;
howlong = atoi(event);
} else {
attr = A_SEMAPHORE;
howlong = 0;
}
if (event && *event && !is_number(event)) {
ap = atr_str(event);
if (!ap) {
attr = mkattr(event);
if (attr <= 0) {
notify_quiet(player, "Invalid attribute.");
return;
}
ap = atr_num(attr);
}
atr_pget_info(thing, ap->number, &aowner, &aflags);
if (attr && Set_attr(player, thing, ap, aflags)) {
attr = ap->number;
howlong = 0;
} else {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
}
num = add_to(player, thing, 1, attr);
if (num <= 0) {
/* thing over-notified, run the command immediately */
thing = NOTHING;
howlong = 0;

}
wait_que(player, cause, howlong, thing, attr, cmd,
cargs, ncargs, mudstate.rdata);

/* --------------------------------------------------------------------------* que_next: Return the time in seconds until the next command should be
* run from the queue.
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:49 PM

*/
int NDECL(que_next)
{
int min, this;
BQUE *point;
/* If there are commands in the player queue, we want to run them
* immediately.
*/
if (test_top())
return 0;
/* If there are commands in the object queue, we want to run them
* after a one-second pause.
*/
if (mudstate.qlfirst != NULL)
return 1;
/* Walk the wait and semaphore queues, looking for the smallest
* wait value. Return the smallest value - 1, because
* the command gets moved to the player queue when it has
* 1 second to go.
*/
min = 1000;
for (point = mudstate.qwait; point; point = point->next) {
this = point->waittime - mudstate.now;
if (this <= 2)
return 1;
if (this < min)
min = this;
}

for (point = mudstate.qsemfirst; point; point = point->next) {


if (point->waittime == 0)
/* Skip if no timeout */
continue;
this = point->waittime - mudstate.now;
if (this <= 2)
return 1;
if (this < min)
min = this;
}
return min - 1;

/* --------------------------------------------------------------------------* do_second: Check the wait and semaphore queues for commands to remove.
*/
void NDECL(do_second)
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:49 PM

BQUE *trail, *point, *next;


char *cmdsave;
/* move contents of low priority queue onto end of normal one this
* helps to keep objects from getting out of control since
* its affects on other objects happen only after one
* second this should allow @halt to be type before
* getting blown away by scrolling text
*/
if ((mudconf.control_flags & CF_DEQUEUE) == 0)
return;
cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< do_second >";
if (mudstate.qlfirst) {
if (mudstate.qlast)
mudstate.qlast->next = mudstate.qlfirst;
else
mudstate.qfirst = mudstate.qlfirst;
mudstate.qlast = mudstate.qllast;
mudstate.qllast = mudstate.qlfirst = NULL;
}
/* Note: the point->waittime test would be 0 except the command is
* being put in the low priority queue to be done in one
* second anyway
*/
/* Do the wait queue */
for (point = mudstate.qwait; point && point->waittime <= mudstate.now;
point = point->next) {
mudstate.qwait = point->next;
give_que(point);
}
/* Check the semaphore queue for expired timed-waits */
for (point = mudstate.qsemfirst, trail = NULL; point; point = next) {
if (point->waittime == 0) {
next = (trail = point)->next;
continue;
/* Skip if not timed-wait */
}
if (point->waittime <= mudstate.now) {
if (trail != NULL)
trail->next = next = point->next;
else
mudstate.qsemfirst = next = point->next;
if (point == mudstate.qsemlast)
mudstate.qsemlast = trail;
add_to(point->player, point->sem, -1,
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:49 PM

(point->attr ? point->attr : A_SEMAPHORE));


point->sem = NOTHING;
give_que(point);
} else
next = (trail = point)->next;

}
mudstate.debug_cmd = cmdsave;
return;

/* --------------------------------------------------------------------------* do_top: Execute the command at the top of the queue


*/
int do_top(ncmds)
int ncmds;
{
BQUE *tmp;
dbref player;
int count;
char *cmdsave;
if ((mudconf.control_flags & CF_DEQUEUE) == 0)
return 0;
cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< do_top >";
for (count = 0; count < ncmds; count++) {
if (!test_top()) {
mudstate.debug_cmd = cmdsave;
Free_RegData(mudstate.rdata);
mudstate.rdata = NULL;
return count;
}
player = mudstate.qfirst->player;
if ((player >= 0) && !Going(player)) {
giveto(player, mudconf.waitcost);
mudstate.curr_enactor = mudstate.qfirst->cause;
mudstate.curr_player = player;
a_Queue(Owner(player), -1);
mudstate.qfirst->player = NOTHING;
if (!Halted(player)) {
/* Load scratch args */
if (mudstate.qfirst->gdata) {
Free_RegData(mudstate.rdata);
Alloc_RegData("do_top", mudstate.qfirst->gdata,
mudstate.rdata);
Copy_RegData("do_top", mudstate.qfirst->gdata,
mudstate.rdata);
} else {
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:49 PM

Free_RegData(mudstate.rdata);
mudstate.rdata = NULL;

mudstate.cmd_invk_ctr = 0;
process_cmdline(player, mudstate.qfirst->cause,
mudstate.qfirst->comm,
mudstate.qfirst->env,
mudstate.qfirst->nargs, mudstate.qfirst);
}

if (mudstate.qfirst) {
tmp = mudstate.qfirst;
mudstate.qfirst = mudstate.qfirst->next;
Free_QData(tmp);
free_qentry(tmp);
}
if (!mudstate.qfirst)
/* gotta check this, as the value's changed */
mudstate.qlast = NULL;
}
Free_RegData(mudstate.rdata);
mudstate.rdata = NULL;

mudstate.debug_cmd = cmdsave;
return count;

/* --------------------------------------------------------------------------* do_ps: tell player what commands they have pending in the queue
*/
static void show_que(player, key, queue, qtot, qent, qdel,
player_targ, obj_targ, header)
dbref player, player_targ, obj_targ;
int key, *qtot, *qent, *qdel;
BQUE *queue;
const char *header;
{
BQUE *tmp;
char *bp, *bufp;
int i;
ATTR *ap;
*qtot = 0;
*qent = 0;
*qdel = 0;
for (tmp = queue; tmp; tmp = tmp->next) {
(*qtot)++;
if (que_want(tmp, player_targ, obj_targ)) {
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:49 PM

(*qent)++;
if (key == PS_SUMM)
continue;
if (*qent == 1)
notify(player,
tprintf("----- %s Queue -----",
header));
bufp = unparse_object(player, tmp->player, 0);
if ((tmp->waittime > 0) && (Good_obj(tmp->sem))) {
/* A minor shortcut. We can never timeout-wait
* on a non-Semaphore attribute.
*/
notify(player,
tprintf("[#%d/%d] %s:%s",
tmp->sem,
tmp->waittime - mudstate.now,
bufp, tmp->comm));
} else if (tmp->waittime > 0) {
notify(player,
tprintf("[%d] %s:%s",
tmp->waittime - mudstate.now,
bufp, tmp->comm));
} else if (Good_obj(tmp->sem)) {
if (tmp->attr == A_SEMAPHORE) {
notify(player,
tprintf("[#%d] %s:%s", tmp->sem,
bufp, tmp->comm));
} else {
ap = atr_num(tmp->attr);
if (ap && ap->name) {
notify(player,
tprintf("[#%d/%s] %s:%s", tmp->sem,
ap->name,
bufp, tmp->comm));
} else {
notify(player,
tprintf("[#%d] %s:%s", tmp->sem,
bufp, tmp->comm));
}
}
} else {
notify(player,
tprintf("%s:%s", bufp, tmp->comm));
}
bp = bufp;
if (key == PS_LONG) {
for (i = 0; i < (tmp->nargs); i++) {
if (tmp->env[i] != NULL) {
safe_str((char *)"; Arg",
bufp, &bp);
safe_chr(i + '0', bufp, &bp);
safe_str((char *)"='",
bufp, &bp);
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:49 PM

safe_str(tmp->env[i],
bufp, &bp);
safe_chr('\'', bufp, &bp);

}
}
*bp = '\0';
bp = unparse_object(player, tmp->cause, 0);
notify(player,
tprintf("
Enactor: %s%s",
bp, bufp));
free_lbuf(bp);

}
free_lbuf(bufp);
} else if (tmp->player == NOTHING) {
(*qdel)++;
}

}
return;

void do_ps(player, cause, key, target)


dbref player, cause;
int key;
char *target;
{
char *bufp;
dbref player_targ, obj_targ;
int pqent, pqtot, pqdel, oqent, oqtot, oqdel, wqent, wqtot, sqent,
sqtot, i;
/* Figure out what to list the queue for */
if ((key & PS_ALL) && !(See_Queue(player))) {
notify(player, NOPERM_MESSAGE);
return;
}
if (!target || !*target) {
obj_targ = NOTHING;
if (key & PS_ALL) {
player_targ = NOTHING;
} else {
player_targ = Owner(player);
if (Typeof(player) != TYPE_PLAYER)
obj_targ = player;
}
} else {
player_targ = Owner(player);
if (See_Queue(player))
obj_targ = match_thing(player, target);
else
obj_targ = match_controlled(player, target);
if (!Good_obj(obj_targ))
return;
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

if (key & PS_ALL) {


notify(player, "Can't specify a target and /all" );
return;
}
if (Typeof(obj_targ) == TYPE_PLAYER) {
player_targ = obj_targ;
obj_targ = NOTHING;
}

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991

}
key = key & ~PS_ALL;

switch (key) {
case PS_BRIEF:
case PS_SUMM:
case PS_LONG:
break;
default:
notify(player, "Illegal combination of switches." );
return;
}
/* Go do it */
show_que(player, key, mudstate.qfirst, &pqtot, &pqent, &pqdel,
player_targ, obj_targ, "Player");
show_que(player, key, mudstate.qlfirst, &oqtot, &oqent, &oqdel,
player_targ, obj_targ, "Object");
show_que(player, key, mudstate.qwait, &wqtot, &wqent, &i,
player_targ, obj_targ, "Wait");
show_que(player, key, mudstate.qsemfirst, &sqtot, &sqent, &i,
player_targ, obj_targ, "Semaphore");
/* Display stats */

992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

Saturday, June 16, 2012 11:49 PM

bufp = alloc_mbuf("do_ps");
if (See_Queue(player))
sprintf(bufp, "Totals: Player...%d/%d[%ddel] Object...%d/%d[%ddel]
Wait...%d/%d Semaphore...%d/%d" ,
pqent, pqtot, pqdel, oqent, oqtot, oqdel,
wqent, wqtot, sqent, sqtot);
else
sprintf(bufp, "Totals: Player...%d/%d Object...%d/%d Wait...%d/%d
Semaphore...%d/%d",
pqent, pqtot, oqent, oqtot, wqent, wqtot, sqent, sqtot);
notify(player, bufp);
free_mbuf(bufp);

/* --------------------------------------------------------------------------* do_queue: Queue management


*/
void do_queue(player, cause, key, arg)
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:49 PM

dbref player, cause;


int key;
char *arg;
{
BQUE *point;
int i, ncmds, was_disabled;
was_disabled = 0;
if (key == QUEUE_KICK) {
i = atoi(arg);
if ((mudconf.control_flags & CF_DEQUEUE) == 0) {
was_disabled = 1;
mudconf.control_flags |= CF_DEQUEUE;
notify(player, "Warning: automatic dequeueing is disabled." );
}
ncmds = do_top(i);
if (was_disabled)
mudconf.control_flags &= ~CF_DEQUEUE;
if (!Quiet(player))
notify(player,
tprintf("%d commands processed.", ncmds));
} else if (key == QUEUE_WARP) {
i = atoi(arg);
if ((mudconf.control_flags & CF_DEQUEUE) == 0) {
was_disabled = 1;
mudconf.control_flags |= CF_DEQUEUE;
notify(player, "Warning: automatic dequeueing is disabled." );
}
/* Handle the wait queue */
for (point = mudstate.qwait; point; point = point->next) {
point->waittime = -i;
}
/* Handle the semaphore queue */
for (point = mudstate.qsemfirst; point; point = point->next) {
if (point->waittime > 0) {
point->waittime -= i;
if (point->waittime <= 0)
point->waittime = -1;
}
}
do_second();
if (was_disabled)
mudconf.control_flags &= ~CF_DEQUEUE;
if (Quiet(player))
return;
if (i > 0)
notify(player,
tprintf("WaitQ timer advanced %d seconds." , i));
else if (i < 0)
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\cque.c

1059
1060
1061
1062
1063
1064
1065
1066
1067

else

Saturday, June 16, 2012 11:49 PM

notify(player,
tprintf("WaitQ timer set back %d seconds." , i));
notify(player,
"Object queue appended to player queue." );

-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:49 PM

/* create.c - Commands that create new objects */


/* $Id: create.c,v 1.49 2005/10/21 16:13:15 alierak Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include
#include
extern
extern
extern
extern
extern

"match.h" /*
"command.h"
"attrs.h" /*
"powers.h" /*
"ansi.h"
/*

required by code */
/* required by code */
required by code */
required by code */
required by code */

dbref FDECL(match_controlled_quiet, (dbref, const char *));


dbref FDECL(clone_home, (dbref, dbref));
int FDECL(can_set_home, (dbref, dbref, dbref));
CONF conftable[];
CF_HDCL(cf_dbref);

/* --------------------------------------------------------------------------* parse_linkable_room: Get a location to link to.


*/
static dbref parse_linkable_room(player, room_name)
dbref player;
char *room_name;
{
dbref room;
init_match(player, room_name, NOTYPE);
match_everything(MAT_NO_EXITS | MAT_NUMERIC | MAT_HOME);
room = match_result();
/* HOME is always linkable */
if (room == HOME)
return HOME;
/* Make sure we can link to it */
if (!Good_obj(room)) {
notify_quiet(player, "That's not a valid object.");
return NOTHING;
} else if (!Linkable(player, room)) {
notify_quiet(player, "You can't link to that.");
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:49 PM

return NOTHING;
} else {
return room;
}

/* --------------------------------------------------------------------------* open_exit, do_open: Open a new exit and optionally link it somewhere.
*/
static void open_exit(player, loc, direction, linkto)
dbref player, loc;
char *direction, *linkto;
{
dbref exit;
if (!Good_obj(loc))
return;
if (!direction || !*direction) {
notify_quiet(player, "Open where?");
return;
} else if (!(controls(player, loc) ||
(Open_Anywhere(player) && !God(loc)))) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
exit = create_obj(player, TYPE_EXIT, direction, 0);
if (exit == NOTHING)
return;
/* Initialize everything and link it in. */
s_Exits(exit, loc);
s_Next(exit, Exits(loc));
s_Exits(loc, exit);
/* and we're done */
notify_quiet(player, "Opened.");
/* See if we should do a link */
if (!linkto || !*linkto)
return;
loc = parse_linkable_room(player, linkto);
if (loc != NOTHING) {
/* Make sure the player passes the link lock */
if (loc != HOME && (!Good_obj(loc) ||
!Passes_Linklock(player, loc))) {
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:49 PM

notify_quiet(player, "You can't link to there.");


return;

}
/* Link it if the player can pay for it */

if (!payfor(player, mudconf.linkcost)) {
notify_quiet(player,
tprintf("You don't have enough %s to link." ,
mudconf.many_coins));
} else {
s_Location(exit, loc);
notify_quiet(player, "Linked.");
}

void do_open(player, cause, key, direction, links, nlinks)


dbref player, cause;
int key, nlinks;
char *direction, *links[];
{
dbref loc, destnum;
char *dest;
/* Create the exit and link to the destination, if there is one */
if (nlinks >= 1)
dest = links[0];
else
dest = NULL;
if (key == OPEN_INVENTORY)
loc = player;
else
loc = Location(player);
open_exit(player, loc, direction, dest);
/* Open the back link if we can */

if (nlinks >= 2) {
destnum = parse_linkable_room(player, dest);
if (destnum != NOTHING) {
open_exit(player, destnum, links[1],
tprintf("%d", loc));
}
}

/* --------------------------------------------------------------------------* link_exit, do_link: Set destination(exits), dropto(rooms) or


* home(player,thing)
*/
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:49 PM

void link_exit(player, exit, dest)


dbref player, exit, dest;
{
int cost, quot;
/* Make sure we can link there:
* Our destination is HOME
* Our destination is AMBIGUOUS and we can link to variable exits
* Normal destination check:
*
- We must control the destination or it must be LINK_OK or
*
we must have LinkToAny and the destination's not God.
*
- We must be able to pass the linklock, or we must be able to
*
LinkToAny (power, or be a wizard) and be config'd so wizards
*
ignore linklocks
*/
if (!((dest == HOME) ||
((dest == AMBIGUOUS) && LinkVariable(player)) ||
(Linkable(player, dest) && Passes_Linklock(player, dest)))) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
/* Exit must be unlinked or controlled by you */
if ((Location(exit) != NOTHING) && !controls(player, exit)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
/* handle costs */
cost = mudconf.linkcost;
quot = 0;
if (Owner(exit) != Owner(player)) {
cost += mudconf.opencost;
quot += mudconf.exit_quota;
}
if (!canpayfees(player, player, cost, quot, TYPE_EXIT))
return;
else
payfees(player, cost, quot, TYPE_EXIT);
/* Pay the owner for his loss */
if (Owner(exit) != Owner(player)) {
payfees(Owner(exit), -mudconf.opencost, -quot, TYPE_EXIT);
s_Owner(exit, Owner(player));
s_Flags(exit, (Flags(exit) & ~(INHERIT | WIZARD)) | HALT);
}
/* link has been validated and paid for, do it and tell the player */

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:49 PM

s_Location(exit, dest);
if (!Quiet(player))
notify_quiet(player, "Linked.");
s_Modified(exit);

void do_link(player, cause, key, what, where)


dbref player, cause;
int key;
char *what, *where;
{
dbref thing, room;
/* Find the thing to link */
init_match(player, what, TYPE_EXIT);
match_everything(0);
thing = noisy_match_result();
if (thing == NOTHING)
return;
/* Allow unlink if where is not specified */
if (!where || !*where) {
do_unlink(player, cause, key, what);
return;
}
switch (Typeof(thing)) {
case TYPE_EXIT:
/* Set destination */
if (!strcasecmp(where, "variable")) {
room = AMBIGUOUS;
} else {
room = parse_linkable_room(player, where);
}
if (room != NOTHING)
link_exit(player, thing, room);
break;
case TYPE_PLAYER:
case TYPE_THING:
/* Set home */
if (!Controls(player, thing)) {
notify_quiet(player, NOPERM_MESSAGE);
break;
}
init_match(player, where, NOTYPE);
match_everything(MAT_NO_EXITS);
room = noisy_match_result();
if (!Good_obj(room))
break;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:49 PM

if (!Has_contents(room)) {
notify_quiet(player, "Can't link to an exit.");
break;
}
if (!can_set_home(player, thing, room) ||
!Passes_Linklock(player, room)) {
notify_quiet(player, NOPERM_MESSAGE);
} else if (room == HOME) {
notify_quiet(player, "Can't set home to home.");
} else {
s_Home(thing, room);
if (!Quiet(player))
notify_quiet(player, "Home set.");
s_Modified(thing);
}
break;
case TYPE_ROOM:
/* Set dropto */
if (!Controls(player, thing)) {
notify_quiet(player, NOPERM_MESSAGE);
break;
}
room = parse_linkable_room(player, where);
if (room == HOME) {
s_Dropto(thing, room);
if (!Quiet(player))
notify_quiet(player, "Dropto set.");
s_Modified(thing);
} else if (!(Good_obj(room))) {
break;
} else if (!isRoom(room)) {
notify_quiet(player, "That is not a room!");
} else if (!(Linkable(player, room) &&
Passes_Linklock(player, room))) {
notify_quiet(player, NOPERM_MESSAGE);
} else {
s_Dropto(thing, room);
if (!Quiet(player))
notify_quiet(player, "Dropto set.");
s_Modified(thing);
}
break;
case TYPE_GARBAGE:
notify_quiet(player, NOPERM_MESSAGE);
break;
default:
STARTLOG(LOG_BUGS, "BUG", "OTYPE")
log_printf("Strange object type: object #%d = %d" ,
thing, Typeof(thing));
ENDLOG
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:49 PM

/* --------------------------------------------------------------------------* do_parent: Set an object's parent field.


*/
void do_parent(player, cause, key, tname, pname)
dbref player, cause;
int key;
char *tname, *pname;
{
dbref thing, parent, curr;
int lev;
/* get victim

*/

init_match(player, tname, NOTYPE);


match_everything(0);
thing = noisy_match_result();
if (thing == NOTHING)
return;
/* Make sure we can do it */
if (!Controls(player, thing)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
/* Find out what the new parent is */
if (*pname) {
init_match(player, pname, Typeof(thing));
match_everything(0);
parent = noisy_match_result();
if (parent == NOTHING)
return;
/* Make sure we have rights to set parent */
if (!Parentable(player, parent)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
/* Verify no recursive reference */
ITER_PARENTS(parent, curr, lev) {
if (curr == thing) {
notify_quiet(player,
"You can't have yourself as a parent!" );
return;
}
}
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:49 PM

} else {
parent = NOTHING;
}

s_Parent(thing, parent);
s_Modified(thing);
if (!Quiet(thing) && !Quiet(player)) {
if (parent == NOTHING)
notify_quiet(player, "Parent cleared.");
else
notify_quiet(player, "Parent set.");
}

/* --------------------------------------------------------------------------* do_dig: Create a new room.


*/
void do_dig(player, cause, key, name, args, nargs)
dbref player, cause;
int key, nargs;
char *name, *args[];
{
dbref room;
char *buff;
/* we don't need to know player's location!

hooray! */

if (!name || !*name) {
notify_quiet(player, "Dig what?");
return;
}
room = create_obj(player, TYPE_ROOM, name, 0);
if (room == NOTHING)
return;
notify(player,
tprintf("%s created with room number %d." , name, room));

buff = alloc_sbuf("do_dig");
if ((nargs >= 1) && args[0] && *args[0]) {
sprintf(buff, "%d", room);
open_exit(player, Location(player), args[0], buff);
}
if ((nargs >= 2) && args[1] && *args[1]) {
sprintf(buff, "%d", Location(player));
open_exit(player, room, args[1], buff);
}
free_sbuf(buff);
if (key == DIG_TELEPORT)
(void)move_via_teleport(player, room, cause, 0);

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:49 PM

/* --------------------------------------------------------------------------* do_create: Make a new object.


*/
void do_create(player, cause, key, name, coststr)
dbref player, cause;
int key;
char *name, *coststr;
{
dbref thing;
int cost;
cost = atoi(coststr);
if (!name || !*name || (strip_ansi_len(name) == 0)) {
notify_quiet(player, "Create what?");
return;
} else if (cost < 0) {
notify_quiet(player,
"You can't create an object for less than nothing!" );
return;
}
thing = create_obj(player, TYPE_THING, name, cost);
if (thing == NOTHING)
return;

move_via_generic(thing, player, NOTHING, 0);


s_Home(thing, new_home(player));
if (!Quiet(player)) {
notify(player,
tprintf("%s created as object #%d",
Name(thing), thing));
}

/* --------------------------------------------------------------------------* do_clone: Create a copy of an object.


*/
void do_clone(player, cause, key, name, arg2)
dbref player, cause;
int key;
char *name, *arg2;
{
dbref clone, thing, new_owner, loc;
FLAG rmv_flags;
int cost;
const char *clone_name;
if ((key & CLONE_INVENTORY) || !Has_location(player))
loc = player;
else
loc = Location(player);
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:49 PM

if (!Good_obj(loc))
return;
init_match(player, name, NOTYPE);
match_everything(0);
thing = noisy_match_result();
if ((thing == NOTHING) || (thing == AMBIGUOUS))
return;
/* Let players clone things set VISUAL.
* all that data
*/

It's easier than retyping in

if (!Examinable(player, thing)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
if (isPlayer(thing)) {
notify_quiet(player, "You cannot clone players!");
return;
}
/* You can only make a parent link to what you control */
if (!Controls(player, thing) && !Parent_ok(thing) &&
(key & CLONE_FROM_PARENT)) {
notify_quiet(player,
tprintf("You don't control %s, ignoring /parent." ,
Name(thing)));
key &= ~CLONE_FROM_PARENT;
}
/* You can only preserve the owner on the clone of an object owned
* by another player, if you control that player.
*/
new_owner = (key & CLONE_PRESERVE) ? Owner(thing) : Owner(player);
if ((new_owner != Owner(player)) && !Controls(player, new_owner)) {
notify_quiet(player,
tprintf("You don't control the owner of %s, ignoring /preserve." ,
Name(thing)));
new_owner = Owner(player);
}
/* Determine the cost of cloning.
* We have to do limits enforcement here, because we're going
* to wipe out the attribute for money set by create_obj()
* and need to set this ourselves. Note that you can't change
* the cost of objects other than things.
*/
if (key & CLONE_SET_COST) {
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:49 PM

cost = atoi(arg2);
arg2 = NULL;
} else {
cost = 0;
}
switch (Typeof(thing)) {
case TYPE_THING:
if (key & CLONE_SET_COST) {
if (cost < mudconf.createmin)
cost = mudconf.createmin;
if (cost > mudconf.createmax)
cost = mudconf.createmax;
} else {
cost = OBJECT_DEPOSIT((mudconf.clone_copy_cost) ?
Pennies(thing) : 1);
}
break;
case TYPE_ROOM:
cost = mudconf.digcost;
break;
case TYPE_EXIT:
if (!Controls(player, loc)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
cost = mudconf.opencost;
break;
}
/* Go make the clone object */
if ((arg2 && *arg2) && ok_name(arg2))
clone = create_obj(new_owner, Typeof(thing), arg2, cost);
else
clone = create_obj(new_owner, Typeof(thing), Name(thing), cost);
if (clone == NOTHING)
return;
/* Wipe out any old attributes and copy in the new data */
atr_free(clone);
if (key & CLONE_FROM_PARENT) {
s_Parent(clone, thing);
} else {
atr_cpy(player, clone, thing);
}
/* Reset the name, since we cleared the attributes. */
if ((arg2 && *arg2) && ok_name(arg2))
clone_name = arg2;
else
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:49 PM

clone_name = Name(thing);
s_Name(clone, (char *)clone_name);
/* Reset the cost, since this also got wiped when we cleared
* attributes. Note that only things have a value, though you
* pay a cost for creating everything.
*/
if (isThing(clone))
s_Pennies(clone, OBJECT_ENDOWMENT(cost));
/* Clear out problem flags from the original. Don't strip
* the INHERIT bit if we got the Inherit switch. Don't
* strip other flags if we got the NoStrip switch EXCEPT
* for the Wizard flag, unless we're God. (Powers are not
* cloned, ever.)
*/
if (key & CLONE_NOSTRIP) {
if (God(player)) {
s_Flags(clone, Flags(thing));
} else {
s_Flags(clone, Flags(thing) & ~WIZARD);
}
s_Flags2(clone, Flags2(thing));
s_Flags3(clone, Flags3(thing));
} else {
rmv_flags = mudconf.stripped_flags.word1;
if ((key & CLONE_INHERIT) && Inherits(player))
rmv_flags &= ~INHERIT;
s_Flags(clone, Flags(thing) & ~rmv_flags);
s_Flags2(clone, Flags2(thing) & ~mudconf.stripped_flags.word2);
s_Flags3(clone, Flags3(thing) & ~mudconf.stripped_flags.word3);
}
/* Tell creator about it */
if (!Quiet(player)) {
if (arg2 && *arg2)
notify(player,
tprintf("%s cloned as %s, new copy is object #%d." ,
Name(thing), clone_name, clone));
else
notify(player,
tprintf("%s cloned, new copy is object #%d." ,
Name(thing), clone));
}
/* Put the new thing in its new home. Break any dropto or link, then
* try to re-establish it.
*/
switch (Typeof(thing)) {
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:49 PM

case TYPE_THING:
s_Home(clone, clone_home(player, thing));
move_via_generic(clone, loc, player, 0);
break;
case TYPE_ROOM:
s_Dropto(clone, NOTHING);
if (Dropto(thing) != NOTHING)
link_exit(player, clone, Dropto(thing));
break;
case TYPE_EXIT:
s_Exits(loc, insert_first(Exits(loc), clone));
s_Exits(clone, loc);
s_Location(clone, NOTHING);
if (Location(thing) != NOTHING)
link_exit(player, clone, Location(thing));
break;
}
/* If same owner run Aclone, else halt it.
* can
*/

Also copy parent if we

if (new_owner == Owner(thing)) {
if (!(key & CLONE_FROM_PARENT))
s_Parent(clone, Parent(thing));
did_it(player, clone, A_NULL, NULL, A_NULL, NULL, A_ACLONE, 0,
(char **)NULL, 0, MSG_MOVE);
} else {
if (!(key & CLONE_FROM_PARENT) &&
(Controls(player, thing) || Parent_ok(thing)))
s_Parent(clone, Parent(thing));
s_Halted(clone);
}

/* --------------------------------------------------------------------------* do_pcreate: Create new players and robots.


*/
void do_pcreate(player, cause, key, name, pass)
dbref player, cause;
int key;
char *name, *pass;
{
int isrobot;
dbref newplayer;
char *newname;
isrobot = (key == PCRE_ROBOT) ? 1 : 0;
newplayer = create_player(name, pass, player, isrobot, 0);
newname = munge_space(name);
if (newplayer == NOTHING) {
notify_quiet(player, tprintf("Failure creating '%s'",
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:49 PM

newname));
free_lbuf(newname);
return;

}
if (isrobot) {
move_object(newplayer, Location(player));
notify_quiet(player,
tprintf("New robot '%s' (#%d) created with password '%s'" ,
newname, newplayer, pass));
notify_quiet(player, "Your robot has arrived.");
STARTLOG(LOG_PCREATES, "CRE", "ROBOT")
log_name(newplayer);
log_printf(" created by ");
log_name(player);
ENDLOG
} else {
move_object(newplayer, (Good_loc(mudconf.start_room) ?
mudconf.start_room : 0));
notify_quiet(player,
tprintf("New player '%s' (#%d) created with password '%s'" ,
newname, newplayer, pass));
STARTLOG(LOG_PCREATES | LOG_WIZARD, "WIZ", "PCREA")
log_name(newplayer);
log_printf(" created by ");
log_name(player);
ENDLOG
}
free_lbuf(newname);

/* --------------------------------------------------------------------------* can_destroy_exit, can_destroy_player, do_destroy:


* Destroy things.
*/
static int can_destroy_exit(player, exit)
dbref player, exit;
{
dbref loc;

loc = Exits(exit);
if (!((Has_location(player) && (loc == Location(player))) ||
(player == loc) || (player == exit) || Wizard(player))) {
notify_quiet(player,
"You cannot destroy exits in another room." );
return 0;
}
return 1;

/*
* --------------------------------------------------------------------------* * destroyable: Indicates if target of a @destroy is a 'special' object in
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:49 PM

* * the database.
*/
int destroyable(victim)
dbref victim;
{
CONF *tp, *ctab;
MODULE *mp;
if ((victim == (dbref) 0) ||
(God(victim)))
return 0;
for (tp = conftable; tp->pname; tp++) {
if (tp->interpreter == cf_dbref &&
victim == *((dbref *)(tp->loc)))
return 0;
}
WALK_ALL_MODULES(mp) {
if ((ctab = DLSYM_VAR(mp->handle, mp->modname, "conftable",
CONF *)) != NULL) {
for (tp = ctab; tp->pname; tp++) {
if (tp->interpreter == cf_dbref &&
victim == *((dbref *)(tp->loc)))
return 0;
}
}
}
}

return 1;

static int can_destroy_player(player, victim)


dbref player, victim;
{
if (!Wizard(player)) {
notify_quiet(player, "Sorry, no suicide allowed.");
return 0;
}
if (Wizard(victim)) {
notify_quiet(player, "Even you can't do that!");
return 0;
}
return 1;
}
void do_destroy(player, cause, key, what)
dbref player, cause;
int key;
char *what;
{
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:49 PM

dbref thing;
int can_doit;
const char *typename;
char *t, *tbuf;
/* You can destroy anything you control. */
thing = match_controlled_quiet(player, what);
/* If you own a location, you can destroy its exits. */
if ((thing == NOTHING) && controls(player, Location(player))) {
init_match(player, what, TYPE_EXIT);
match_exit();
thing = last_match_result();
}
/* You can destroy DESTROY_OK things in your inventory. */
if (thing == NOTHING) {
init_match(player, what, TYPE_THING);
match_possession();
thing = last_match_result();
if ((thing != NOTHING) && !(isThing(thing) && Destroy_ok(thing))) {
thing = NOPERM;
}
}
/* Return an error if we didn't find anything to destroy. */
if (match_status(player, thing) == NOTHING) {
return;
}
/* Check SAFE and DESTROY_OK flags */
if (Safe(thing, player) && !(key & DEST_OVERRIDE) &&
!(isThing(thing) && Destroy_ok(thing))) {
notify_quiet(player,
"Sorry, that object is protected. Use @destroy/override to destroy it." );
return;
}
/* Make sure we're not trying to destroy a special object */
if (!destroyable(thing)) {
notify_quiet(player, "You can't destroy that!");
return;
}
/* Make sure we can do it, on a type-specific basis */
switch (Typeof(thing)) {
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:49 PM

case TYPE_EXIT:
typename = "exit";
can_doit = can_destroy_exit(player, thing);
break;
case TYPE_PLAYER:
typename = "player";
can_doit = can_destroy_player(player, thing);
break;
case TYPE_ROOM:
typename = "room";
can_doit = 1;
break;
case TYPE_THING:
typename = "thing";
can_doit = 1;
break;
case TYPE_GARBAGE:
typename = "garbage";
can_doit = 1;
break;
default:
typename = "weird object";
can_doit = 1;
break;
}
if (!can_doit)
return;
/* We can use @destroy/instant to immediately blow up an object
* that was already queued for destruction -- that object is
* unmodified except for being Going.
*/
if (Going(thing) &&
!((key & DEST_INSTANT) && (Typeof(thing) != TYPE_GARBAGE))) {
notify_quiet(player,
tprintf("That %s has already been destroyed." ,
typename));
return;
}
/* If we specified the instant switch, or we're configured to
* immediately make Destroy_Ok things (or things owned by
* Destroy_Ok owners) go away, we do instant destruction.
*/
if ((key & DEST_INSTANT) ||
(mudconf.instant_recycle &&
(Destroy_ok(thing) || Destroy_ok(Owner(thing))))) {
switch (Typeof(thing)) {
case TYPE_EXIT:
destroy_exit(thing);
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\create.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949

Saturday, June 16, 2012 11:49 PM

break;
case TYPE_PLAYER:
atr_add_raw(thing, A_DESTROYER, tprintf("%d", player));
destroy_player(thing);
break;
case TYPE_ROOM:
empty_obj(thing);
destroy_obj(NOTHING, thing);
break;
case TYPE_THING:
destroy_thing(thing);
break;
default:
notify(player, "Weird object type cannot be destroyed." );
break;

}
return;
}

/* Otherwise we queue things up for destruction. */


if (!isRoom(thing)) {
notify(player,
tprintf("The %s shakes and begins to crumble." , typename));
} else {
notify_all(thing, player, "The room shakes and begins to crumble." );
}
if (!Quiet(thing) && !Quiet(Owner(thing))) {
notify_quiet(Owner(thing),
tprintf("You will be rewarded shortly for %s(#%d)." ,
Name(thing), thing));
}
if ((Owner(thing) != player) && !Quiet(player)) {
t = tbuf = alloc_sbuf("do_destroy.owner");
safe_sb_str(Name(Owner(thing)), tbuf, &t);
notify_quiet(player, tprintf("Destroyed. %s's %s(#%d)",
tbuf, Name(thing), thing));
free_sbuf(tbuf);
}
if (isPlayer(thing))
atr_add_raw(thing, A_DESTROYER, tprintf("%d", player));
}

s_Going(thing);

-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:47 PM

/* db.c - attribute interface, some flatfile and object routines */


/* $Id: db.c,v 1.143 2009/01/11 19:04:34 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include <sys/stat.h>
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include
#include
#include

"attrs.h"
"vattr.h"
"match.h"
"powers.h"
"udb.h"
"ansi.h"

#ifndef O_ACCMODE
#define O_ACCMODE
#endif

/*
/*
/*
/*
/*
/*

required
required
required
required
required
required

by
by
by
by
by
by

code
code
code
code
code
code

*/
*/
*/
*/
*/
*/

(O_RDONLY|O_WRONLY|O_RDWR)

/*
* Restart definitions
*/
#define RS_CONCENTRATE
#define RS_RECORD_PLAYERS
#define RS_NEW_STRINGS
#define RS_COUNT_REBOOTS

0x00000002
0x00000004
0x00000008
0x00000010

OBJ *db = NULL;


NAME *names = NULL;
NAME *purenames = NULL;
extern
extern
extern
extern

int
int
int
int

sock;
ndescriptors;
maxd;
slave_socket;

extern pid_t slave_pid;


extern void FDECL(desc_addhash, (DESC *));
#ifdef TEST_MALLOC
int malloc_count = 0;
int malloc_bytes = 0;
char *malloc_ptr;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:47 PM

char *malloc_str;
#endif /* TEST_MALLOC */
extern VATTR *FDECL(vattr_rename, (char *, char *));
/* --------------------------------------------------------------------------* Temp file management, used to get around static limits in some versions
* of libc.
*/
FILE *t_fd;
int t_is_pipe;
#ifdef TLI
int t_is_tli;
#endif
static void tf_xclose(fd)
FILE *fd;
{
if (fd) {
if (t_is_pipe)
pclose(fd);
#ifdef TLI
else if (t_is_tli)
t_close(fd);
#endif
else
fclose(fd);
} else {
close(0);
}
t_fd = NULL;
t_is_pipe = 0;
}
static int tf_fiddle(tfd)
int tfd;
{
if (tfd < 0) {
tfd = open(DEV_NULL, O_RDONLY, 0);
return -1;
}
if (tfd != 0) {
dup2(tfd, 0);
close(tfd);
}
return 0;
}
static int tf_xopen(fname, mode)
char *fname;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:47 PM

int mode;
{
int fd;

fd = open(fname, mode, 0600);


fd = tf_fiddle(fd);
return fd;

/* #define t_xopen(f,m) t_fiddle(open(f, m, 0600)) */


static const char *mode_txt(mode)
int mode;
{
switch (mode & O_ACCMODE) {
case O_RDONLY:
return "r";
case O_WRONLY:
return "w";
}
return "r+";
}
void NDECL(tf_init)
{
fclose(stdin);
tf_xopen(DEV_NULL, O_RDONLY);
t_fd = NULL;
t_is_pipe = 0;
}
int tf_open(fname, mode)
char *fname;
int mode;
{
tf_xclose(t_fd);
return tf_xopen(fname, mode);
}
#ifdef TLI
int tf_topen(fam, mode)
int fam, mode;
{
tf_xclose(t_fd);
return tf_fiddle(t_open(fam, mode, NULL));
}
#endif
void tf_close(fdes)
int fdes;
{
tf_xclose(t_fd);
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:47 PM

tf_xopen(DEV_NULL, O_RDONLY);

FILE *tf_fopen(fname, mode)


char *fname;
int mode;
{
tf_xclose(t_fd);
if (tf_xopen(fname, mode) >= 0) {
t_fd = fdopen(0, mode_txt(mode));
return t_fd;
}
return NULL;
}
void tf_fclose(fd)
FILE *fd;
{
tf_xclose(t_fd);
tf_xopen(DEV_NULL, O_RDONLY);
}
FILE *tf_popen(fname, mode)
char *fname;
int mode;
{
tf_xclose(t_fd);
t_fd = popen(fname, mode_txt(mode));
if (t_fd != NULL) {
t_is_pipe = 1;
}
return t_fd;
}
/* #define GNU_MALLOC_TEST 1 */
#ifdef GNU_MALLOC_TEST
extern unsigned int malloc_sbrk_used;

/* amount of data space used now */

#endif
/*
* Check routine forward declaration.
*/
static int FDECL(fwdlist_ck, (int, dbref, dbref, int, char *));
static int FDECL(propdir_ck, (int, dbref, dbref, int, char *));
extern void FDECL(pcache_reload, (dbref));
extern void FDECL(desc_reload, (dbref));
/* *INDENT-OFF* */
/* List of built-in attributes */
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:47 PM

ATTR attr[] =
{
{"Aahear", A_AAHEAR,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Aclone", A_ACLONE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Aconnect",
A_ACONNECT, AF_DEFAULT|AF_NOPROG,
NULL},
{"Adesc",
A_ADESC,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Adfail", A_ADFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Adisconnect", A_ADISCONNECT, AF_DEFAULT|AF_NOPROG,
NULL},
{"Adrop",
A_ADROP,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Aefail", A_AEFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Aenter", A_AENTER,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Afail",
A_AFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Agfail", A_AGFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Ahear",
A_AHEAR,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Akill",
A_AKILL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Aleave", A_ALEAVE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Alfail", A_ALFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Alias",
A_ALIAS,
AF_NOPROG|AF_NOCMD|AF_NOCLONE|AF_PRIVATE|AF_CONST,
NULL},
{"Allowance",
A_ALLOWANCE,
AF_MDARK|AF_NOPROG|AF_WIZARD,
NULL},
{"Amail",
A_AMAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Amhear", A_AMHEAR,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Amove",
A_AMOVE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Apay",
A_APAY,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Arfail", A_ARFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Asucc",
A_ASUCC,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Atfail", A_ATFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Atport", A_ATPORT,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Atofail", A_ATOFAIL, AF_DEFAULT|AF_NOPROG,
NULL},
{"Aufail", A_AUFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Ause",
A_AUSE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Away",
A_AWAY,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Charges", A_CHARGES, AF_NOPROG,
NULL},
{"ChownLock",
A_LCHOWN,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Comment", A_COMMENT, AF_NOPROG|AF_MDARK|AF_WIZARD,
NULL},
{"Conformat",
A_LCON_FMT, AF_DEFAULT|AF_NOPROG,
NULL},
{"ControlLock", A_LCONTROL, AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Cost",
A_COST,
AF_NOPROG,
NULL},
{"Daily",
A_DAILY,
AF_NOPROG,
NULL},
{"DarkLock",
A_LDARK,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Desc",
A_DESC,
AF_DEFAULT|AF_VISUAL|AF_NOPROG,
NULL},
{"DefaultLock", A_LOCK,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Destroyer",
A_DESTROYER,
AF_MDARK|AF_WIZARD|AF_NOPROG,
NULL},
{"Dfail",
A_DFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Drop",
A_DROP,
AF_DEFAULT|AF_NOPROG,
NULL},
{"DropLock",
A_LDROP,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Ealias", A_EALIAS,
AF_NOPROG,
NULL},
{"Efail",
A_EFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Enter",
A_ENTER,
AF_DEFAULT|AF_NOPROG,
NULL},
{"EnterLock",
A_LENTER,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Exitformat", A_LEXITS_FMT,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Exitto", A_EXITVARDEST, AF_NOPROG,
NULL},
{"Fail",
A_FAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:47 PM

{"Filter", A_FILTER,
AF_NOPROG,
NULL},
{"Forwardlist", A_FORWARDLIST, AF_NOPROG,
fwdlist_ck},
{"Gfail",
A_GFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"GiveLock",
A_LGIVE,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"HeardLock",
A_LHEARD,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"HearsLock",
A_LHEARS,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Idesc",
A_IDESC,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Idle",
A_IDLE,
AF_NOPROG,
NULL},
{"Infilter",
A_INFILTER, AF_NOPROG,
NULL},
{"Inprefix",
A_INPREFIX, AF_NOPROG,
NULL},
{"Kill",
A_KILL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"KnownLock",
A_LKNOWN,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"KnowsLock",
A_LKNOWS,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Lalias", A_LALIAS,
AF_NOPROG,
NULL},
{"Last",
A_LAST, AF_VISUAL|AF_WIZARD|AF_NOCMD|AF_NOPROG|AF_NOCLONE,
NULL},
{"Lastip", A_LASTIP,
AF_NOPROG|AF_NOCMD|AF_NOCLONE|AF_GOD,
NULL},
{"Lastpage",
A_LASTPAGE, AF_INTERNAL|AF_NOCMD|AF_NOPROG|AF_GOD|AF_PRIVATE,
NULL},
{"Lastsite",
A_LASTSITE, AF_NOPROG|AF_NOCMD|AF_NOCLONE|AF_GOD,
NULL},
{"Leave",
A_LEAVE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"LeaveLock",
A_LLEAVE,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Lfail",
A_LFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"LinkLock",
A_LLINK,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Listen", A_LISTEN,
AF_NOPROG,
NULL},
{"Logindata",
A_LOGINDATA,
AF_MDARK|AF_NOPROG|AF_NOCMD|AF_CONST,
NULL},
{"Mailcurf",
A_MAILCURF, AF_MDARK|AF_WIZARD|AF_NOPROG|AF_NOCLONE,
NULL},
{"Mailflags",
A_MAILFLAGS,
AF_MDARK|AF_WIZARD|AF_NOPROG|AF_NOCLONE,
NULL},
{"Mailfolders", A_MAILFOLDERS, AF_MDARK|AF_WIZARD|AF_NOPROG|AF_NOCLONE,
NULL},
{"Mailmsg", A_MAILMSG, AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL,
NULL},
{"Mailsub", A_MAILSUB, AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL,
NULL},
{"Mailsucc",
A_MAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Mailto", A_MAILTO,
AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL,
NULL},
{"MovedLock",
A_LMOVED,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"MovesLock",
A_LMOVES,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Move",
A_MOVE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Name",
A_NAME,
AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL,
NULL},
{"Nameformat", A_NAME_FMT, AF_DEFAULT|AF_NOPROG,
NULL},
{"Newobjs", A_NEWOBJS, AF_MDARK|AF_NOPROG|AF_GOD|AF_NOCMD|AF_NOCLONE,
NULL},
{"Odesc",
A_ODESC,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Odfail", A_ODFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Odrop",
A_ODROP,
AF_DEFAULT|AF_NOPROG,
NULL},
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:47 PM

{"Oefail", A_OEFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Oenter", A_OENTER,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Ofail",
A_OFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Ogfail", A_OGFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Okill",
A_OKILL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Oleave", A_OLEAVE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Olfail", A_OLFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Omove",
A_OMOVE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Opay",
A_OPAY,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Orfail", A_ORFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Osucc",
A_OSUCC,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Otfail", A_OTFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Otport", A_OTPORT,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Otofail", A_OTOFAIL, AF_DEFAULT|AF_NOPROG,
NULL},
{"Oufail", A_OUFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Ouse",
A_OUSE,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Oxenter", A_OXENTER, AF_DEFAULT|AF_NOPROG,
NULL},
{"Oxleave", A_OXLEAVE, AF_DEFAULT|AF_NOPROG,
NULL},
{"Oxtport", A_OXTPORT, AF_DEFAULT|AF_NOPROG,
NULL},
{"Pagegroup",
A_PAGEGROUP,
AF_INTERNAL|AF_NOCMD|AF_NOPROG|AF_GOD|AF_PRIVATE,
NULL},
{"PageLock",
A_LPAGE,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"ParentLock", A_LPARENT, AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Pay",
A_PAY,
AF_NOPROG,
NULL},
{"Prefix", A_PREFIX,
AF_NOPROG,
NULL},
{"Progcmd", A_PROGCMD, AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL,
NULL},
{"Propdir", A_PROPDIR, AF_NOPROG,
propdir_ck},
{"Queuemax",
A_QUEUEMAX, AF_MDARK|AF_WIZARD|AF_NOPROG,
NULL},
{"Quota",
A_QUOTA,
AF_MDARK|AF_NOPROG|AF_GOD|AF_NOCMD|AF_NOCLONE,
NULL},
{"ReceiveLock", A_LRECEIVE, AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Reject", A_REJECT,
AF_NOPROG,
NULL},
{"Rfail",
A_RFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Rquota", A_RQUOTA,
AF_MDARK|AF_NOPROG|AF_GOD|AF_NOCMD|AF_NOCLONE,
NULL},
{"Runout", A_RUNOUT,
AF_NOPROG,
NULL},
{"Semaphore",
A_SEMAPHORE,
AF_NOPROG|AF_WIZARD|AF_NOCMD|AF_NOCLONE,
NULL},
{"Sex",
A_SEX, AF_VISUAL|AF_NOPROG,
NULL},
{"Signature",
A_SIGNATURE,
AF_NOPROG,
NULL},
{"Speechformat",A_SPEECHFMT,
AF_DEFAULT|AF_NOPROG,
NULL},
{"SpeechLock", A_LSPEECH, AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Startup", A_STARTUP, AF_NOPROG,
NULL},
{"Succ",
A_SUCC,
AF_DEFAULT|AF_NOPROG,
NULL},
{"TeloutLock", A_LTELOUT, AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Tfail",
A_TFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Timeout", A_TIMEOUT, AF_MDARK|AF_NOPROG|AF_WIZARD,
NULL},
{"Tport",
A_TPORT,
AF_DEFAULT|AF_NOPROG,
NULL},
{"TportLock",
A_LTPORT,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Tofail", A_TOFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Ufail",
A_UFAIL,
AF_DEFAULT|AF_NOPROG,
NULL},
{"Use",
A_USE,
AF_DEFAULT|AF_NOPROG,
NULL},
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:47 PM

{"UseLock", A_LUSE,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"UserLock",
A_LUSER,
AF_NOPROG|AF_NOCMD|AF_IS_LOCK, NULL},
{"Va",
A_VA,
0,
NULL},
{"Vb",
A_VA+1,
0,
NULL},
{"Vc",
A_VA+2,
0,
NULL},
{"Vd",
A_VA+3,
0,
NULL},
{"Ve",
A_VA+4,
0,
NULL},
{"Vf",
A_VA+5,
0,
NULL},
{"Vg",
A_VA+6,
0,
NULL},
{"Vh",
A_VA+7,
0,
NULL},
{"Vi",
A_VA+8,
0,
NULL},
{"Vj",
A_VA+9,
0,
NULL},
{"Vk",
A_VA+10,
0,
NULL},
{"Vl",
A_VA+11,
0,
NULL},
{"Vm",
A_VA+12,
0,
NULL},
{"Vn",
A_VA+13,
0,
NULL},
{"Vo",
A_VA+14,
0,
NULL},
{"Vp",
A_VA+15,
0,
NULL},
{"Vq",
A_VA+16,
0,
NULL},
{"Vr",
A_VA+17,
0,
NULL},
{"Vs",
A_VA+18,
0,
NULL},
{"Vt",
A_VA+19,
0,
NULL},
{"Vu",
A_VA+20,
0,
NULL},
{"Vv",
A_VA+21,
0,
NULL},
{"Vw",
A_VA+22,
0,
NULL},
{"Vx",
A_VA+23,
0,
NULL},
{"Vy",
A_VA+24,
0,
NULL},
{"Vz",
A_VA+25,
0,
NULL},
{"Vrml_url",
A_VRML_URL, AF_NOPROG,
NULL},
{"Htdesc", A_HTDESC,
AF_DEFAULT|AF_VISUAL|AF_NOPROG,
NULL},
{"*Atrlist",
A_LIST, AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL, NULL},
{"*Password",
A_PASS, AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL, NULL},
{"*Money", A_MONEY,
AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL,
NULL},
{"*Invalid",
A_TEMP,
AF_DARK|AF_NOPROG|AF_NOCMD|AF_INTERNAL,
NULL},
{NULL,
0,
0,
NULL}};
/* *INDENT-ON* */
/* --------------------------------------------------------------------------* fwdlist_set, fwdlist_clr: Manage cached forwarding lists
*/
void fwdlist_set(thing, ifp)
dbref thing;
FWDLIST *ifp;
{
FWDLIST *fp, *xfp;
int i, stat = 0;
/* If fwdlist is null, clear */

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:47 PM

if (!ifp || (ifp->count <= 0)) {


fwdlist_clr(thing);
return;
}
/* Copy input forwardlist to a correctly-sized buffer */
fp = (FWDLIST *) XMALLOC(sizeof(FWDLIST), "fwdlist_set");
fp->data = (int *) XCALLOC(ifp->count, sizeof(int),
"fwdlist_set.data");
for (i = 0; i < ifp->count; i++) {
fp->data[i] = ifp->data[i];
}
fp->count = ifp->count;
/*
* Replace an existing forwardlist, or add a new one
*/

xfp = fwdlist_get(thing);
if (xfp) {
if (xfp->data)
XFREE(xfp->data, "fwdlist_set.xfp_data");
XFREE(xfp, "fwdlist_set.xfp");
stat = nhashrepl(thing, (int *)fp, &mudstate.fwdlist_htab);
} else {
stat = nhashadd(thing, (int *)fp, &mudstate.fwdlist_htab);
}
if (stat < 0) {
/* the add or replace failed */
if (fp->data)
XFREE(fp->data, "fwdlist_set.fp_data");
XFREE(fp, "fwdlist_set.fp");
}

void fwdlist_clr(thing)
dbref thing;
{
FWDLIST *xfp;
/* If a forwardlist exists, delete it */

xfp = fwdlist_get(thing);
if (xfp) {
if (xfp->data)
XFREE(xfp->data, "fwdlist_clr.data");
XFREE(xfp, "fwdlist_clr");
nhashdelete(thing, &mudstate.fwdlist_htab);
}

/* --------------------------------------------------------------------------* fwdlist_load: Load text into a forwardlist.


*/
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:47 PM

int fwdlist_load(fp, player, atext)


FWDLIST *fp;
dbref player;
char *atext;
{
dbref target;
char *tp, *bp, *dp;
int i, count, errors, fail;
int *tmp_array;
tmp_array = (int *)XCALLOC((LBUF_SIZE / 2), sizeof(int),
"fwdlist_load.tmp");
count = 0;
errors = 0;
bp = tp = alloc_lbuf("fwdlist_load.str");
strcpy(tp, atext);
do {
for (; *bp && isspace(*bp); bp++) ; /* skip spaces */
for (dp = bp; *bp && !isspace(*bp); bp++) ; /* remember string */
if (*bp)
*bp++ = '\0';
/* terminate string */
if ((*dp++ == '#') && isdigit(*dp)) {
target = atoi(dp);
if (!mudstate.standalone) {
fail = (!Good_obj(target) ||
(!God(player) &&
!controls(player, target) &&
(!Link_ok(target) ||
!could_doit(player, target, A_LLINK))));
} else {
fail = !Good_obj(target);
}
if (fail) {
if (!mudstate.standalone)
notify(player,
tprintf("Cannot forward to #%d: Permission denied." ,
target));
errors++;
} else if (count < mudconf.fwdlist_lim) {
if (fp->data)
fp->data[count++] = target;
else
tmp_array[count++] = target;
} else {
if (!mudstate.standalone)
notify(player,
tprintf("Cannot forward to #%d: Forwardlist limit exceeded." ,
target));
errors++;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:47 PM

}
}
} while (*bp);
free_lbuf(tp);
if ((fp->data == NULL) && (count > 0)) {
fp->data = (int *) XCALLOC(count, sizeof(int), "fwdlist_load.data");
for (i = 0; i < count; i++)
fp->data[i] = tmp_array[i];
}

fp->count = count;
XFREE(tmp_array, "fwdlist_load.tmp");
return errors;

/*
* --------------------------------------------------------------------------* fwdlist_rewrite: Generate a text string from a FWDLIST buffer.
*/
int fwdlist_rewrite(fp, atext)
FWDLIST *fp;
char *atext;
{
char *tp, *bp;
int i, count;

if (fp && fp->count) {


count = fp->count;
tp = alloc_sbuf("fwdlist_rewrite.errors");
bp = atext;
for (i = 0; i < fp->count; i++) {
if (Good_obj(fp->data[i])) {
sprintf(tp, "#%d ", fp->data[i]);
safe_str(tp, atext, &bp);
} else {
count--;
}
}
*bp = '\0';
free_sbuf(tp);
} else {
count = 0;
*atext = '\0';
}
return count;

/* --------------------------------------------------------------------------* fwdlist_ck: Check a list of dbref numbers to forward to for AUDIBLE


*/
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:47 PM

static int fwdlist_ck(key, player, thing, anum, atext)


int key, anum;
dbref player, thing;
char *atext;
{
FWDLIST *fp;
int count;
if (mudstate.standalone)
return 1;
count = 0;
if (atext && *atext) {
fp = (FWDLIST *) XMALLOC(sizeof(FWDLIST), "fwdlist_ck.fp");
fp->data = NULL;
fwdlist_load(fp, player, atext);
} else {
fp = NULL;
}
/* Set the cached forwardlist */

fwdlist_set(thing, fp);
count = fwdlist_rewrite(fp, atext);
if (fp) {
if (fp->data)
XFREE(fp->data, "fwdlist_ck.fp_data");
XFREE(fp, "fwdlist_ck.fp");
}
return ((count > 0) || !atext || !*atext);

FWDLIST *fwdlist_get(thing)
dbref thing;
{
dbref aowner;
int aflags, alen, errors;
char *tp;
static FWDLIST *fp = NULL;
if (!mudstate.standalone)
return (FWDLIST *)nhashfind((thing), &mudstate.fwdlist_htab);
if (!fp) {
fp = (FWDLIST *) XMALLOC(sizeof(FWDLIST), "fwdlist_get");
fp->data = NULL;
}
tp = atr_get(thing, A_FORWARDLIST, &aowner, &aflags, &alen);
errors = fwdlist_load(fp, GOD, tp);
free_lbuf(tp);
return fp;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:47 PM

}
/* --------------------------------------------------------------------------* propdir functions
*/
void propdir_set(thing, ifp)
dbref thing;
PROPDIR *ifp;
{
PROPDIR *fp, *xfp;
int i, stat = 0;
/* If propdir list is null, clear */
if (!ifp || (ifp->count <= 0)) {
propdir_clr(thing);
return;
}
/* Copy input propdir to a correctly-sized buffer */
fp = (PROPDIR *) XMALLOC(sizeof(PROPDIR), "propdir_set");
fp->data = (int *) XCALLOC(ifp->count, sizeof(int),
"propdir_set.data");
for (i = 0; i < ifp->count; i++) {
fp->data[i] = ifp->data[i];
}
fp->count = ifp->count;
/*
* Replace an existing propdir, or add a new one
*/

xfp = propdir_get(thing);
if (xfp) {
if (xfp->data)
XFREE(xfp->data, "propdir_set.xfp_data");
XFREE(xfp, "propdir_set.xfp");
stat = nhashrepl(thing, (int *)fp, &mudstate.propdir_htab);
} else {
stat = nhashadd(thing, (int *)fp, &mudstate.propdir_htab);
}
if (stat < 0) {
/* the add or replace failed */
if (fp->data)
XFREE(fp->data, "propdir_set.fp_data");
XFREE(fp, "propdir_set.fp");
}

void propdir_clr(thing)
dbref thing;
{
PROPDIR *xfp;
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:47 PM

/* If a propdir exists, delete it */

xfp = propdir_get(thing);
if (xfp) {
if (xfp->data)
XFREE(xfp->data, "propdir_clr.data");
XFREE(xfp, "propdir_clr");
nhashdelete(thing, &mudstate.propdir_htab);
}

int propdir_load(fp, player, atext)


PROPDIR *fp;
dbref player;
char *atext;
{
dbref target;
char *tp, *bp, *dp;
int i, count, errors, fail;
int *tmp_array;
tmp_array = (int *)XCALLOC((LBUF_SIZE / 2), sizeof(int),
"propdir_load.tmp");
count = 0;
errors = 0;
bp = tp = alloc_lbuf("propdir_load.str");
strcpy(tp, atext);
do {
for (; *bp && isspace(*bp); bp++) ; /* skip spaces */
for (dp = bp; *bp && !isspace(*bp); bp++) ; /* remember string */
if (*bp)
*bp++ = '\0';
/* terminate string */
if ((*dp++ == '#') && isdigit(*dp)) {
target = atoi(dp);
if (!mudstate.standalone) {
fail = (!Good_obj(target) || !Parentable(player, target));
} else {
fail = !Good_obj(target);
}
if (fail) {
if (!mudstate.standalone) {
notify(player,
tprintf("Cannot parent to #%d: Permission denied." ,
target));
}
errors++;
} else if (count < mudconf.propdir_lim) {
if (fp->data)
fp->data[count++] = target;
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:47 PM

else

tmp_array[count++] = target;
} else {
if (!mudstate.standalone) {
notify(player,
tprintf("Cannot parent to #%d: Propdir limit exceeded." ,
target));
}
errors++;
}

}
} while (*bp);
free_lbuf(tp);

if ((fp->data == NULL) && (count > 0)) {


fp->data = (int *) XCALLOC(count, sizeof(int), "propdir_load.data");
for (i = 0; i < count; i++)
fp->data[i] = tmp_array[i];
}

fp->count = count;
XFREE(tmp_array, "propdir_load.tmp");
return errors;

int propdir_rewrite(fp, atext)


PROPDIR *fp;
char *atext;
{
char *tp, *bp;
int i, count;

if (fp && fp->count) {


count = fp->count;
tp = alloc_sbuf("propdir_rewrite.errors");
bp = atext;
for (i = 0; i < fp->count; i++) {
if (Good_obj(fp->data[i])) {
sprintf(tp, "#%d ", fp->data[i]);
safe_str(tp, atext, &bp);
} else {
count--;
}
}
*bp = '\0';
free_sbuf(tp);
} else {
count = 0;
*atext = '\0';
}
return count;

-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:47 PM

static int propdir_ck(key, player, thing, anum, atext)


int key, anum;
dbref player, thing;
char *atext;
{
PROPDIR *fp;
int count;
if (mudstate.standalone)
return 1;
count = 0;
if (atext && *atext) {
fp = (PROPDIR *) XMALLOC(sizeof(PROPDIR), "propdir_ck.fp");
fp->data = NULL;
propdir_load(fp, player, atext);
} else {
fp = NULL;
}
/* Set the cached propdir */

propdir_set(thing, fp);
count = propdir_rewrite(fp, atext);
if (fp) {
if (fp->data)
XFREE(fp->data, "propdir_ck.fp_data");
XFREE(fp, "propdir_ck.fp");
}
return ((count > 0) || !atext || !*atext);

PROPDIR *propdir_get(thing)
dbref thing;
{
dbref aowner;
int aflags, alen, errors;
char *tp;
static PROPDIR *fp = NULL;
if (!mudstate.standalone)
return (PROPDIR *)nhashfind((thing), &mudstate.propdir_htab);
if (!fp) {
fp = (PROPDIR *) XMALLOC(sizeof(PROPDIR), "propdir_get");
fp->data = NULL;
}
tp = atr_get(thing, A_PROPDIR, &aowner, &aflags, &alen);
errors = propdir_load(fp, GOD, tp);
free_lbuf(tp);
return fp;
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:47 PM

}
/* --------------------------------------------------------------------------*/
static char *set_string(ptr, new)
char **ptr, *new;
{
/* if pointer not null, free it */
if (*ptr)
XFREE(*ptr, "set_string");
/* if new string is not null allocate space for it and copy it */

if (!new)
/* || !*new */
return (*ptr = NULL);
/* Check with GAC about this */
*ptr = XSTRDUP(new, "set_string");
return (*ptr);

/* --------------------------------------------------------------------------* Name, s_Name: Get or set an object's name.


*/
INLINE void safe_name(thing, outbuf, bufc)
dbref thing;
char *outbuf, **bufc;
{
dbref aowner;
int aflags, alen;
time_t save_access_time;
char *buff;
/* Retrieving a name never counts against an object's access time. */
save_access_time = AccessTime(thing);
if (!purenames[thing]) {
buff = atr_get(thing, A_NAME, &aowner, &aflags, &alen);
set_string(&purenames[thing], strip_ansi(buff));
free_lbuf(buff);
}
if (!names[thing]) {
buff = atr_get(thing, A_NAME, &aowner, &aflags, &alen);
set_string(&names[thing], buff);
s_NameLen(thing, alen);
free_lbuf(buff);
}
safe_known_str(names[thing], NameLen(thing), outbuf, bufc);
}

s_AccessTime(thing, save_access_time);

-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:47 PM

INLINE char *Name(thing)


dbref thing;
{
dbref aowner;
int aflags, alen;
time_t save_access_time;
char *buff;
save_access_time = AccessTime(thing);
if (!purenames[thing]) {
buff = atr_get(thing, A_NAME, &aowner, &aflags, &alen);
set_string(&purenames[thing], strip_ansi(buff));
free_lbuf(buff);
}

if (!names[thing]) {
buff = atr_get(thing, A_NAME, &aowner, &aflags, &alen);
set_string(&names[thing], buff);
s_NameLen(thing, alen);
free_lbuf(buff);
}
s_AccessTime(thing, save_access_time);
return names[thing];

INLINE char *PureName(thing)


dbref thing;
{
dbref aowner;
int aflags, alen;
time_t save_access_time;
char *buff;
save_access_time = AccessTime(thing);
if (!names[thing]) {
buff = atr_get(thing, A_NAME, &aowner, &aflags, &alen);
set_string(&names[thing], buff);
s_NameLen(thing, alen);
free_lbuf(buff);
}

if (!purenames[thing]) {
buff = atr_get(thing, A_NAME, &aowner, &aflags, &alen);
set_string(&purenames[thing], strip_ansi(buff));
free_lbuf(buff);
}
s_AccessTime(thing, save_access_time);
return purenames[thing];

-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:47 PM

INLINE void s_Name(thing, s)


dbref thing;
char *s;
{
int len;
/* Truncate the name if we have to */
if (s) {
len = strlen(s);
if (len > MBUF_SIZE) {
len = MBUF_SIZE - 1;
s[len] = '\0';
}
} else {
len = 0;
}

atr_add_raw(thing, A_NAME, (char *)s);


s_NameLen(thing, len);
set_string(&names[thing], (char *)s);
set_string(&purenames[thing], strip_ansi((char *)s));

void safe_exit_name(it, buff, bufc)


dbref it;
char *buff, **bufc;
{
char *s = *bufc;
int ansi_state = ANST_NORMAL;
safe_name(it, buff, bufc);
while (*s && (*s != EXIT_DELIMITER)) {
if (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
} else {
++s;
}
}

*bufc = s;
safe_str(ansi_transition_esccode(ansi_state, ANST_NORMAL), buff, bufc);

void s_Pass(thing, s)
dbref thing;
const char *s;
{
atr_add_raw(thing, A_PASS, (char *)s);
}
/* ---------------------------------------------------------------------------19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:47 PM

* do_attribute: Manage user-named attributes.


*/
extern NAMETAB attraccess_nametab[];
void do_attribute(player, cause, key, aname, value)
dbref player, cause;
int key;
char *aname, *value;
{
int success, negate, f;
char *buff, *sp, *p, *q, *tbuf, *tokst;
VATTR *va;
ATTR *va2;
/* Look up the user-named attribute we want to play with.
* Note vattr names have a limited size.
*/
buff = alloc_sbuf("do_attribute");
for (p = buff, q = aname;
*q && ((p - buff) < (VNAME_SIZE - 1));
p++, q++)
*p = toupper(*q);
*p = '\0';
if (!(ok_attr_name(buff) && (va = vattr_find(buff)))) {
notify(player, "No such user-named attribute." );
free_sbuf(buff);
return;
}
switch (key) {
case ATTRIB_ACCESS:
/* Modify access to user-named attribute */
for (sp = value; *sp; sp++)
*sp = toupper(*sp);
sp = strtok_r(value, " ", &tokst);
success = 0;
while (sp != NULL) {
/* Check for negation */
negate = 0;
if (*sp == '!') {
negate = 1;
sp++;
}
/* Set or clear the appropriate bit */
f = search_nametab(player, attraccess_nametab, sp);
if (f > 0) {
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:47 PM

success = 1;
if (negate)
va->flags &= ~f;
else
va->flags |= f;
/* Set the dirty bit */
va->flags |= AF_DIRTY;
} else {
notify(player,
tprintf("Unknown permission: %s.", sp));
}
/* Get the next token */
sp = strtok_r(NULL, " ", &tokst);
}
if (success && !Quiet(player))
notify(player, "Attribute access changed.");
break;
case ATTRIB_RENAME:
/* Make sure the new name doesn't already exist */
va2 = atr_str(value);
if (va2) {
notify(player,
"An attribute with that name already exists." );
free_sbuf(buff);
return;
}
if (vattr_rename(va->name, value) == NULL)
notify(player, "Attribute rename failed.");
else
notify(player, "Attribute renamed.");
break;
case ATTRIB_DELETE:
/* Remove the attribute */
vattr_delete(buff);
notify(player, "Attribute deleted.");
break;
case ATTRIB_INFO:
/* Print info, like @list user_attr does */
if (!(va->flags & AF_DELETED)) {
tbuf = alloc_lbuf("attribute_info");
sprintf(tbuf, "%s(%d):", va->name, va->number);
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

Saturday, June 16, 2012 11:47 PM

listset_nametab(player, attraccess_nametab, va->flags,


tbuf, 1);
free_lbuf(tbuf);
} else {
notify(player, "That attribute has been deleted." );
}
break;

}
free_sbuf(buff);
return;

/* --------------------------------------------------------------------------* do_fixdb: Directly edit database fields


*/
void do_fixdb(player, cause, key, arg1, arg2)
dbref player, cause;
int key;
char *arg1, *arg2;
{
dbref thing, res;
init_match(player, arg1, NOTYPE);
match_everything(0);
thing = noisy_match_result();
if (thing == NOTHING)
return;
res = NOTHING;
switch (key) {
case FIXDB_OWNER:
case FIXDB_LOC:
case FIXDB_CON:
case FIXDB_EXITS:
case FIXDB_NEXT:
init_match(player, arg2, NOTYPE);
match_everything(0);
res = noisy_match_result();
break;
case FIXDB_PENNIES:
res = atoi(arg2);
break;
}
switch (key) {
case FIXDB_OWNER:
s_Owner(thing, res);
if (!Quiet(player))
notify(player, tprintf("Owner set to #%d", res));
break;
case FIXDB_LOC:
s_Location(thing, res);
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

Saturday, June 16, 2012 11:47 PM

if (!Quiet(player))
notify(player, tprintf("Location set to #%d", res));
break;
case FIXDB_CON:
s_Contents(thing, res);
if (!Quiet(player))
notify(player, tprintf("Contents set to #%d", res));
break;
case FIXDB_EXITS:
s_Exits(thing, res);
if (!Quiet(player))
notify(player, tprintf("Exits set to #%d", res));
break;
case FIXDB_NEXT:
s_Next(thing, res);
if (!Quiet(player))
notify(player, tprintf("Next set to #%d", res));
break;
case FIXDB_PENNIES:
s_Pennies(thing, res);
if (!Quiet(player))
notify(player, tprintf("Pennies set to %d", res));
break;
case FIXDB_NAME:
if (Typeof(thing) == TYPE_PLAYER) {
if (!ok_player_name(arg2)) {
notify(player,
"That's not a good name for a player." );
return;
}
if (lookup_player(NOTHING, arg2, 0) != NOTHING) {
notify(player,
"That name is already in use." );
return;
}
STARTLOG(LOG_SECURITY, "SEC", "CNAME")
log_name(thing),
log_printf(" renamed to %s", strip_ansi(arg2));
ENDLOG
if (Suspect(player)) {
raw_broadcast(WIZARD,
"[Suspect] %s renamed to %s",
Name(thing), arg2);
}
delete_player_name(thing, Name(thing));
s_Name(thing, arg2);
add_player_name(thing, arg2);
} else {
if (!ok_name(arg2)) {
notify(player,
"Warning: That is not a reasonable name." );
}
s_Name(thing, arg2);
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

Saturday, June 16, 2012 11:47 PM

}
if (!Quiet(player))
notify(player, tprintf("Name set to %s", arg2));
break;

/* --------------------------------------------------------------------------* init_attrtab: Initialize the attribute hash tables.


*/
void NDECL(init_attrtab)
{
ATTR *a;
char *buff, *p, *q;

hashinit(&mudstate.attr_name_htab, 100 * HASH_FACTOR, HT_STR);


buff = alloc_sbuf("init_attrtab");
for (a = attr; a->number; a++) {
anum_extend(a->number);
anum_set(a->number, a);
for (p = buff, q = (char *)a->name; *q; p++, q++)
*p = toupper(*q);
*p = '\0';
hashadd(buff, (int *)a, &mudstate.attr_name_htab, 0);
}
free_sbuf(buff);

/* --------------------------------------------------------------------------* atr_str: Look up an attribute by name.


*/
ATTR *atr_str(s)
char *s;
{
char *buff, *p, *q;
ATTR *a;
VATTR *va;
static ATTR tattr;
/* Convert the buffer name to uppercase. Limit length of name.

*/

buff = alloc_sbuf("atr_str");
for (p = buff, q = s; *q && ((p - buff) < (VNAME_SIZE - 1)); p++, q++)
*p = toupper(*q);
*p = '\0';
if (!ok_attr_name(buff)) {
free_sbuf(buff);
return NULL;
}

-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325

Saturday, June 16, 2012 11:47 PM

/* Look for a predefined attribute */


if (!mudstate.standalone) {
a = (ATTR *) hashfind(buff, &mudstate.attr_name_htab);
if (a != NULL) {
free_sbuf(buff);
return a;
}
} else {
for (a = attr; a->name; a++) {
if (!string_compare(a->name, s)) {
free_sbuf(buff);
return a;
}
}
}
/* Nope, look for a user attribute */
va = vattr_find(buff);
free_sbuf(buff);
/* If we got one, load tattr and return a pointer to it. */
if (va != NULL) {
tattr.name = va->name;
tattr.number = va->number;
tattr.flags = va->flags;
tattr.check = NULL;
return &tattr;
}
if (mudstate.standalone) {
/*
* No exact match, try for a prefix match on predefined attribs.
* Check for both longer versions and shorter versions.
*/

for (a = attr; a->name; a++) {


if (string_prefix(s, a->name))
return a;
if (string_prefix(a->name, s))
return a;
}

/* All failed, return NULL */


}

return NULL;

/* --------------------------------------------------------------------------* anum_extend: Grow the attr num lookup table.


-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

Saturday, June 16, 2012 11:47 PM

*/
ATTR **anum_table = NULL;
int anum_alc_top = 0;
void anum_extend(newtop)
int newtop;
{
ATTR **anum_table2;
int delta, i;
if (!mudstate.standalone)
delta = mudconf.init_size;
else
delta = 1000;

if (newtop <= anum_alc_top)


return;
if (newtop < anum_alc_top + delta)
newtop = anum_alc_top + delta;
if (anum_table == NULL) {
anum_table = (ATTR **) XCALLOC(newtop + 1, sizeof(ATTR *),
"anum_extend");
} else {
anum_table2 = (ATTR **) XCALLOC(newtop + 1, sizeof(ATTR *),
"anum_extend");
for (i = 0; i <= anum_alc_top; i++)
anum_table2[i] = anum_table[i];
XFREE(anum_table, "anum_extend");
anum_table = anum_table2;
}
anum_alc_top = newtop;

/* --------------------------------------------------------------------------* atr_num: Look up an attribute by number.


*/
ATTR *atr_num(anum)
int anum;
{
VATTR *va;
static ATTR tattr;
/* Look for a predefined attribute */
if (anum < A_USER_START)
return anum_get(anum);
if (anum > anum_alc_top)
return NULL;
/* It's a user-defined attribute, we need to copy data */
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431

Saturday, June 16, 2012 11:47 PM

va = (VATTR *) anum_get(anum);
if (va != NULL) {
tattr.name = va->name;
tattr.number = va->number;
tattr.flags = va->flags;
tattr.check = NULL;
return &tattr;
}
/* All failed, return NULL */
}

return NULL;

/* --------------------------------------------------------------------------* mkattr: Lookup attribute by name, creating if needed.


*/
int mkattr(buff)
char *buff;
{
ATTR *ap;
VATTR *va;
int vflags;
KEYLIST *kp;
if (!(ap = atr_str(buff))) {
/* Unknown attr, create a new one.
* Check if it matches any attribute type pattern that
* we have defined; if it does, give it those flags.
* Otherwise, use the default vattr flags.
*/
if (!mudstate.standalone) {
vflags = mudconf.vattr_flags;
for (kp = mudconf.vattr_flag_list; kp != NULL; kp = kp->next) {
if (quick_wild(kp->name, buff)) {
vflags = kp->data;
break;
}
}
va = vattr_alloc(buff, vflags);
} else {
va = vattr_alloc(buff, mudconf.vattr_flags);
}
if (!va || !(va->number))
return -1;
return va->number;

}
if (!(ap->number))
return -1;

-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

Saturday, June 16, 2012 11:47 PM

return ap->number;

/* --------------------------------------------------------------------------* al_decode: Fetch an attribute number from an alist.


*/
static int al_decode(app)
char **app;
{
int atrnum = 0, anum, atrshft = 0;
char *ap;
ap = *app;

for (;;) {
anum = ((*ap) & 0x7f);
if (atrshft > 0)
atrnum += (anum << atrshft);
else
atrnum = anum;
if (!(*ap++ & 0x80)) {
*app = ap;
return atrnum;
}
atrshft += 7;
}
/* NOTREACHED */

/* --------------------------------------------------------------------------* al_code: Store an attribute number in an alist.


*/
static void al_code(app, atrnum)
char **app;
int atrnum;
{
char *ap;
ap = *app;

for (;;) {
*ap = atrnum & 0x7f;
atrnum = atrnum >> 7;
if (!atrnum) {
*app = ++ap;
return;
}
*ap++ |= 0x80;
}

-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537

Saturday, June 16, 2012 11:47 PM

/* --------------------------------------------------------------------------* Commer: check if an object has any $-commands in its attributes.


*/
int Commer(thing)
dbref thing;
{
char *s, *as;
int attr, aflags, alen;
dbref aowner;
ATTR *ap;
if ((!Has_Commands(thing) && mudconf.req_cmds_flag) || Halted(thing))
return 0;
s = alloc_lbuf("Commer");
atr_push();
for (attr = atr_head(thing, &as); attr; attr = atr_next(&as)) {
ap = atr_num(attr);
if (!ap || (ap->flags & AF_NOPROG))
continue;
s = atr_get_str(s, thing, attr, &aowner, &aflags, &alen);
if ((*s == '$') && !(aflags & AF_NOPROG)) {
atr_pop();
free_lbuf(s);
return 1;
}

}
atr_pop();
free_lbuf(s);
return 0;

/* routines to handle object attribute lists */


/* --------------------------------------------------------------------------* al_size, al_fetch, al_store, al_add, al_delete: Manipulate attribute lists
*/
/* al_extend: Get more space for attributes, if needed */
void al_extend(buffer, bufsiz, len, copy)
char **buffer;
int *bufsiz, len, copy;
{
char *tbuff;
int newsize;
if (len > *bufsiz) {
newsize = len + ATR_BUF_CHUNK;
tbuff = (char *) XMALLOC(newsize, "al_extend");
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590

Saturday, June 16, 2012 11:47 PM

if (*buffer) {
if (copy)
memcpy(tbuff, *buffer, *bufsiz);
XFREE(*buffer, "al_extend");
}
*buffer = tbuff;
*bufsiz = newsize;

/* al_size: Return length of attribute list in chars */


int al_size(astr)
char *astr;
{
if (!astr)
return 0;
return (strlen(astr) + 1);
}
/* al_store: Write modified attribute list */
void NDECL(al_store)
{
if (mudstate.mod_al_id != NOTHING) {
if (mudstate.mod_alist && *mudstate.mod_alist) {
atr_add_raw(mudstate.mod_al_id, A_LIST,
mudstate.mod_alist);
} else {
atr_clr(mudstate.mod_al_id, A_LIST);
}
}
mudstate.mod_al_id = NOTHING;
}
/* al_fetch: Load attribute list */
char *al_fetch(thing)
dbref thing;
{
char *astr;
int len;
/* We only need fetch if we change things */
if (mudstate.mod_al_id == thing)
return mudstate.mod_alist;
/* Fetch and set up the attribute list */
al_store();
astr = atr_get_raw(thing, A_LIST);
if (astr) {
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

Saturday, June 16, 2012 11:47 PM

len = al_size(astr);
al_extend(&mudstate.mod_alist, &mudstate.mod_size, len, 0);
memcpy(mudstate.mod_alist, astr, len);
} else {
al_extend(&mudstate.mod_alist, &mudstate.mod_size, 1, 0);
*mudstate.mod_alist = '\0';
}
mudstate.mod_al_id = thing;
return mudstate.mod_alist;

/* al_add: Add an attribute to an attribute list */


void al_add(thing, attrnum)
dbref thing;
int attrnum;
{
char *abuf, *cp;
int anum;
/* If trying to modify List attrib, return.
* attribute list.
*/

Otherwise, get the

if (attrnum == A_LIST)
return;
abuf = al_fetch(thing);
/* See if attr is in the list.

If so, exit (need not do anything) */

cp = abuf;
while (*cp) {
anum = al_decode(&cp);
if (anum == attrnum)
return;
}
/* Nope, extend it */
al_extend(&mudstate.mod_alist, &mudstate.mod_size,
(cp - abuf + ATR_BUF_INCR), 1);
if (mudstate.mod_alist != abuf) {
/* extend returned different buffer, re-find the end */
abuf = mudstate.mod_alist;
for (cp = abuf; *cp; anum = al_decode(&cp)) ;

}
/* Add the new attribute on to the end */
al_code(&cp, attrnum);
*cp = '\0';

-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696

Saturday, June 16, 2012 11:47 PM

return;

/* al_delete: Remove an attribute from an attribute list */


void al_delete(thing, attrnum)
dbref thing;
int attrnum;
{
int anum;
char *abuf, *cp, *dp;
/* If trying to modify List attrib, return.
* attribute list.
*/

Otherwise, get the

if (attrnum == A_LIST)
return;
abuf = al_fetch(thing);
if (!abuf)
return;

cp = abuf;
while (*cp) {
dp = cp;
anum = al_decode(&cp);
if (anum == attrnum) {
while (*cp) {
anum = al_decode(&cp);
al_code(&dp, anum);
}
*dp = '\0';
return;
}
}
return;

INLINE static void makekey(thing, atr, abuff)


dbref thing;
int atr;
Aname *abuff;
{
abuff->object = thing;
abuff->attrnum = atr;
return;
}
/* --------------------------------------------------------------------------* al_destroy: wipe out an object's attribute list.
*/
void al_destroy(thing)
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

Saturday, June 16, 2012 11:47 PM

dbref thing;
{
if (mudstate.mod_al_id == thing)
al_store(); /* remove from cache */
atr_clr(thing, A_LIST);
}
/* --------------------------------------------------------------------------* atr_encode: Encode an attribute string.
*/
static char *atr_encode(iattr, thing, owner, flags, atr)
char *iattr;
dbref thing, owner;
int flags, atr;
{
/* If using the default owner and flags (almost all attributes will),
* just store the string.
*/
if (((owner == Owner(thing)) || (owner == NOTHING)) && !flags)
return iattr;
/* Encode owner and flags into the attribute text */

if (owner == NOTHING)
owner = Owner(thing);
return tprintf("%c%d:%d:%s", ATR_INFO_CHAR, owner, flags, iattr);

/* --------------------------------------------------------------------------* atr_decode: Decode an attribute string.


*/
static void atr_decode(iattr, oattr, thing, owner, flags, atr, alen)
char *iattr, *oattr;
dbref thing, *owner;
int *flags, atr, *alen;
{
char *cp;
int neg;
/* See if the first char of the attribute is the special character */
if (*iattr == ATR_INFO_CHAR) {
/* It is, crack the attr apart */
cp = &iattr[1];
/* Get the attribute owner */

-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

Saturday, June 16, 2012 11:47 PM

*owner = 0;
neg = 0;
if (*cp == '-') {
neg = 1;
cp++;
}
while (isdigit(*cp)) {
*owner = (*owner * 10) + (*cp++ - '0');
}
if (neg)
*owner = 0 - *owner;
/* If delimiter is not ':', just return attribute */
if (*cp++ != ':') {
*owner = Owner(thing);
*flags = 0;
if (oattr) {
StrCopyLen(oattr, iattr, alen);
}
return;
}
/* Get the attribute flags */
*flags = 0;
while (isdigit(*cp)) {
*flags = (*flags * 10) + (*cp++ - '0');
}
/* If delimiter is not ':', just return attribute */
if (*cp++ != ':') {
*owner = Owner(thing);
*flags = 0;
if (oattr) {
StrCopyLen(oattr, iattr, alen);
}
}
/* Get the attribute text */
if (oattr) {
StrCopyLen(oattr, cp, alen);
}
if (*owner == NOTHING)
*owner = Owner(thing);
} else {
/* Not the special character, return normal info */
*owner = Owner(thing);
*flags = 0;
if (oattr) {
StrCopyLen(oattr, iattr, alen);
-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

Saturday, June 16, 2012 11:47 PM

/* --------------------------------------------------------------------------* atr_clr: clear an attribute in the list.


*/
void atr_clr(thing, atr)
dbref thing;
int atr;
{
Aname okey;
DBData key;
makekey(thing, atr, &okey);
/* Delete the entry from cache */
key.dptr = &okey;
key.dsize = sizeof(Aname);
cache_del(key, DBTYPE_ATTRIBUTE);
al_delete(thing, atr);
if (!mudstate.standalone && !mudstate.loading_db)
s_Modified(thing);
switch (atr) {
case A_STARTUP:
s_Flags(thing, Flags(thing) & ~HAS_STARTUP);
break;
case A_DAILY:
s_Flags2(thing, Flags2(thing) & ~HAS_DAILY);
if (!mudstate.standalone)
(void) cron_clr(thing, A_DAILY);
break;
case A_FORWARDLIST:
s_Flags2(thing, Flags2(thing) & ~HAS_FWDLIST);
break;
case A_LISTEN:
s_Flags2(thing, Flags2(thing) & ~HAS_LISTEN);
break;
case A_SPEECHFMT:
s_Flags3(thing, Flags3(thing) & ~HAS_SPEECHMOD);
break;
case A_PROPDIR:
s_Flags3(thing, Flags3(thing) & ~HAS_PROPDIR);
break;
case A_TIMEOUT:
if (!mudstate.standalone)
desc_reload(thing);
break;
-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

Saturday, June 16, 2012 11:47 PM

case A_QUEUEMAX:
if (!mudstate.standalone)
pcache_reload(thing);
break;
}

/* --------------------------------------------------------------------------* atr_add_raw, atr_add: add attribute of type atr to list


*/
void atr_add_raw(thing, atr, buff)
dbref thing;
int atr;
char *buff;
{
Attr *a;
Aname okey;
DBData key, data;
makekey(thing, atr, &okey);
if (!buff || !*buff) {
/* Delete the entry from cache */
key.dptr = &okey;
key.dsize = sizeof(Aname);
cache_del(key, DBTYPE_ATTRIBUTE);

al_delete(thing, atr);
return;

if ((a = (Attr *) XMALLOC(strlen(buff) + 1, "atr_add_raw.2")) == (char *)0) {


return;
}
strcpy(a, buff);
/* Store the value in cache */
key.dptr = &okey;
key.dsize = sizeof(Aname);
data.dptr = a;
data.dsize = strlen(a) + 1;
cache_put(key, data, DBTYPE_ATTRIBUTE);
al_add(thing, atr);
if (!mudstate.standalone && !mudstate.loading_db)
s_Modified(thing);
switch (atr) {
case A_STARTUP:
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961

Saturday, June 16, 2012 11:47 PM

s_Flags(thing, Flags(thing) | HAS_STARTUP);


break;
case A_DAILY:
s_Flags2(thing, Flags2(thing) | HAS_DAILY);
if (!mudstate.standalone && !mudstate.loading_db) {
char tbuf[SBUF_SIZE];
(void) cron_clr(thing, A_DAILY);
sprintf(tbuf, "0 %d * * *", mudconf.events_daily_hour);
call_cron(thing, thing, A_DAILY, tbuf);
}
break;
case A_FORWARDLIST:
s_Flags2(thing, Flags2(thing) | HAS_FWDLIST);
break;
case A_LISTEN:
s_Flags2(thing, Flags2(thing) | HAS_LISTEN);
break;
case A_SPEECHFMT:
s_Flags3(thing, Flags3(thing) | HAS_SPEECHMOD);
break;
case A_PROPDIR:
s_Flags3(thing, Flags3(thing) | HAS_PROPDIR);
break;
case A_TIMEOUT:
if (!mudstate.standalone)
desc_reload(thing);
break;
case A_QUEUEMAX:
if (!mudstate.standalone)
pcache_reload(thing);
break;
}

void atr_add(thing, atr, buff, owner, flags)


dbref thing, owner;
int atr, flags;
char *buff;
{
char *tbuff;

if (!buff || !*buff) {
atr_clr(thing, atr);
} else {
tbuff = atr_encode(buff, thing, owner, flags, atr);
atr_add_raw(thing, atr, tbuff);
}

void atr_set_owner(thing, atr, owner)


dbref thing, owner;
int atr;
{
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014

Saturday, June 16, 2012 11:47 PM

dbref aowner;
int aflags, alen;
char *buff;

buff = atr_get(thing, atr, &aowner, &aflags, &alen);


atr_add(thing, atr, buff, owner, aflags);
free_lbuf(buff);

void atr_set_flags(thing, atr, flags)


dbref thing, flags;
int atr;
{
dbref aowner;
int aflags, alen;
char *buff;

buff = atr_get(thing, atr, &aowner, &aflags, &alen);


atr_add(thing, atr, buff, aowner, flags);
free_lbuf(buff);

/* --------------------------------------------------------------------------* atr_get_raw, atr_get_str, atr_get: Get an attribute from the database.


*/
char *atr_get_raw(thing, atr)
dbref thing;
int atr;
{
DBData key, data;
Aname okey;
if (Typeof(thing) == TYPE_GARBAGE)
return NULL;
if (!mudstate.standalone && !mudstate.loading_db)
s_Accessed(thing);
makekey(thing, atr, &okey);
/* Fetch the entry from cache and return it */

key.dptr = &okey;
key.dsize = sizeof(Aname);
data = cache_get(key, DBTYPE_ATTRIBUTE);
return data.dptr;

char *atr_get_str(s, thing, atr, owner, flags, alen)


char *s;
dbref thing, *owner;
int atr, *flags, *alen;
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067

Saturday, June 16, 2012 11:47 PM

char *buff;
buff = atr_get_raw(thing, atr);
if (!buff) {
*owner = Owner(thing);
*flags = 0;
*alen = 0;
*s = '\0';
} else {
atr_decode(buff, s, thing, owner, flags, atr, alen);
}
return s;

char *atr_get(thing, atr, owner, flags, alen)


dbref thing, *owner;
int atr, *flags, *alen;
{
char *buff;

buff = alloc_lbuf("atr_get");
return atr_get_str(buff, thing, atr, owner, flags, alen);

int atr_get_info(thing, atr, owner, flags)


dbref thing, *owner;
int atr, *flags;
{
int alen;
char *buff;

buff = atr_get_raw(thing, atr);


if (!buff) {
*owner = Owner(thing);
*flags = 0;
return 0;
}
atr_decode(buff, NULL, thing, owner, flags, atr, &alen);
return 1;

char *atr_pget_str(s, thing, atr, owner, flags, alen)


char *s;
dbref thing, *owner;
int atr, *flags, *alen;
{
char *buff;
dbref parent;
int lev;
ATTR *ap;
PROPDIR *pp;

-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120

Saturday, June 16, 2012 11:47 PM

ITER_PARENTS(thing, parent, lev) {


buff = atr_get_raw(parent, atr);
if (buff && *buff) {
atr_decode(buff, s, thing, owner, flags, atr, alen);
if ((lev == 0) || !(*flags & AF_PRIVATE))
return s;
}
if ((lev == 0) && Good_obj(Parent(parent))) {
ap = atr_num(atr);
if (!ap || ap->flags & AF_PRIVATE)
break;
}
}
if (H_Propdir(thing) && ((pp = propdir_get(thing)) != NULL)) {
for (lev = 0;
(lev < pp->count) && (lev < mudconf.propdir_lim);
lev++) {
parent = pp->data[lev];
if (Good_obj(parent) && (parent != thing)) {
buff = atr_get_raw(parent, atr);
if (buff && *buff) {
atr_decode(buff, s, thing, owner, flags, atr, alen);
if (!(*flags & AF_PRIVATE))
return s;
}
}
}
}

*owner = Owner(thing);
*flags = 0;
*alen = 0;
*s = '\0';
return s;

char *atr_pget(thing, atr, owner, flags, alen)


dbref thing, *owner;
int atr, *flags, *alen;
{
char *buff;

buff = alloc_lbuf("atr_pget");
return atr_pget_str(buff, thing, atr, owner, flags, alen);

int atr_pget_info(thing, atr, owner, flags)


dbref thing, *owner;
int atr, *flags;
{
char *buff;
dbref parent;
-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173

Saturday, June 16, 2012 11:47 PM

int lev, alen;


ATTR *ap;
PROPDIR *pp;
ITER_PARENTS(thing, parent, lev) {
buff = atr_get_raw(parent, atr);
if (buff && *buff) {
atr_decode(buff, NULL, thing, owner, flags, atr, &alen);
if ((lev == 0) || !(*flags & AF_PRIVATE))
return 1;
}
if ((lev == 0) && Good_obj(Parent(parent))) {
ap = atr_num(atr);
if (!ap || ap->flags & AF_PRIVATE)
break;
}
}

if (H_Propdir(thing) && ((pp = propdir_get(thing)) != NULL)) {


for (lev = 0;
(lev < pp->count) && (lev < mudconf.propdir_lim);
lev++) {
parent = pp->data[lev];
if (Good_obj(parent) && (parent != thing)) {
buff = atr_get_raw(parent, atr);
if (buff && *buff) {
atr_decode(buff, NULL, thing, owner, flags, atr &alen);
if (!(*flags & AF_PRIVATE))
return 1;
}
}
}

*owner = Owner(thing);
*flags = 0;
return 0;

/* --------------------------------------------------------------------------* atr_free: Return all attributes of an object.


*/
void atr_free(thing)
dbref thing;
{
int attr;
char *as;
atr_push();
for (attr = atr_head(thing, &as); attr; attr = atr_next(&as)) {
atr_clr(thing, attr);
}
-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226

atr_pop();
al_destroy(thing);

Saturday, June 16, 2012 11:47 PM

/* Just to be on the safe side */

/* --------------------------------------------------------------------------* atr_cpy: Copy all attributes from one object to another. Takes the
* player argument to ensure that only attributes that COULD be set by
* the player are copied.
*/
void atr_cpy(player, dest, source)
dbref player, dest, source;
{
int attr, aflags, alen;
dbref owner, aowner;
char *as, *buf;
ATTR *at;

owner = Owner(dest);
buf = alloc_lbuf("atr_cpy");
atr_push();
for (attr = atr_head(source, &as); attr; attr = atr_next(&as)) {
buf = atr_get_str(buf, source, attr, &aowner, &aflags, &alen);
if (!(aflags & AF_LOCK))
aowner = owner;
/* change owner */
at = atr_num(attr);
if (attr && at) {
if (Write_attr(owner, dest, at, aflags))
/* Only set attrs that owner has perm to set */
atr_add(dest, attr, buf, aowner, aflags);
}
}
atr_pop();
free_lbuf(buf);

/* --------------------------------------------------------------------------* atr_chown: Change the ownership of the attributes of an object to the


* current owner if they are not locked.
*/
void atr_chown(obj)
dbref obj;
{
int attr, aflags, alen;
dbref owner, aowner;
char *as, *buf;
owner = Owner(obj);
buf = alloc_lbuf("atr_chown");
atr_push();
for (attr = atr_head(obj, &as); attr; attr = atr_next(&as)) {
buf = atr_get_str(buf, obj, attr, &aowner, &aflags, &alen);
-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279

Saturday, June 16, 2012 11:47 PM

if ((aowner != owner) && !(aflags & AF_LOCK))


atr_add(obj, attr, buf, owner, aflags);

}
atr_pop();
free_lbuf(buf);

/* --------------------------------------------------------------------------* atr_next: Return next attribute in attribute list.


*/
int atr_next(attrp)
char **attrp;
{
if (!*attrp || !**attrp) {
return 0;
} else {
return al_decode(attrp);
}
}
/* --------------------------------------------------------------------------* atr_push, atr_pop: Push and pop attr lists.
*/
void NDECL(atr_push)
{
ALIST *new_alist;
new_alist = (ALIST *) alloc_sbuf("atr_push");
new_alist->data = mudstate.iter_alist.data;
new_alist->len = mudstate.iter_alist.len;
new_alist->next = mudstate.iter_alist.next;

mudstate.iter_alist.data = NULL;
mudstate.iter_alist.len = 0;
mudstate.iter_alist.next = new_alist;
return;

void NDECL(atr_pop)
{
ALIST *old_alist;
char *cp;
old_alist = mudstate.iter_alist.next;
if (mudstate.iter_alist.data) {
XFREE(mudstate.iter_alist.data, "al_extend");
}
if (old_alist) {
mudstate.iter_alist.data = old_alist->data;
mudstate.iter_alist.len = old_alist->len;
-43-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332

Saturday, June 16, 2012 11:47 PM

mudstate.iter_alist.next = old_alist->next;
cp = (char *)old_alist;
free_sbuf(cp);
} else {
mudstate.iter_alist.data = NULL;
mudstate.iter_alist.len = 0;
mudstate.iter_alist.next = NULL;
}
return;

/* --------------------------------------------------------------------------* atr_head: Returns the head of the attr list for object 'thing'
*/
int atr_head(thing, attrp)
dbref thing;
char **attrp;
{
char *astr;
int alen;
/* Get attribute list.

Save a read if it is in the modify atr list */

if (thing == mudstate.mod_al_id) {
astr = mudstate.mod_alist;
} else {
astr = atr_get_raw(thing, A_LIST);
}
alen = al_size(astr);
/* If no list, return nothing */
if (!alen)
return 0;
/* Set up the list and return the first entry */

al_extend(&mudstate.iter_alist.data, &mudstate.iter_alist.len,
alen, 0);
memcpy(mudstate.iter_alist.data, astr, alen);
*attrp = mudstate.iter_alist.data;
return atr_next(attrp);

/* --------------------------------------------------------------------------* db_grow: Extend the struct database.


*/
#define SIZE_HACK

/* So mistaken refs to #-1 won't die. */

void initialize_objects(first, last)


-44-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

Saturday, June 16, 2012 11:47 PM

dbref first, last;


{
dbref thing;
for (thing = first; thing < last; thing++) {
s_Owner(thing, GOD);
s_Flags(thing, (TYPE_GARBAGE | GOING));
s_Powers(thing, 0);
s_Powers2(thing, 0);
s_Location(thing, NOTHING);
s_Contents(thing, NOTHING);
s_Exits(thing, NOTHING);
s_Link(thing, NOTHING);
s_Next(thing, NOTHING);
s_Zone(thing, NOTHING);
s_Parent(thing, NOTHING);
#ifdef MEMORY_BASED
db[thing].attrtext.atrs = NULL;
db[thing].attrtext.at_count = 0;
#endif
}
}
void db_grow(newtop)
dbref newtop;
{
int newsize, marksize, delta, i;
MARKBUF *newmarkbuf;
OBJ *newdb;
NAME *newnames, *newpurenames;
char *cp;
if (!mudstate.standalone)
delta = mudconf.init_size;
else
delta = 1000;
/* Determine what to do based on requested size, current top and
* size. Make sure we grow in reasonable-size chunks to prevent
* frequent reallocations of the db array.
*/
/* If requested size is smaller than the current db size, ignore it */
if (newtop <= mudstate.db_top) {
return;
}
/* If requested size is greater than the current db size but smaller
* than the amount of space we have allocated, raise the db size
* and initialize the new area.
*/
if (newtop <= mudstate.db_size) {
-45-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437

Saturday, June 16, 2012 11:47 PM

for (i = mudstate.db_top; i < newtop; i++) {


names[i] = NULL;
purenames[i] = NULL;
}
initialize_objects(mudstate.db_top, newtop);
mudstate.db_top = newtop;
return;

}
/* Grow by a minimum of delta objects */

if (newtop <= mudstate.db_size + delta) {


newsize = mudstate.db_size + delta;
} else {
newsize = newtop;
}
/* Enforce minimum database size */
if (newsize < mudstate.min_size)
newsize = mudstate.min_size + delta;
/* Grow the name tables */
newnames = (NAME *) XCALLOC(newsize + SIZE_HACK, sizeof(NAME),
"db_grow.names");
if (!newnames) {
fprintf(mainlog_fp,
"ABORT! db.c, could not allocate space for %d item name cache in
db_grow().\n",
newsize);
abort();
}
if (names) {
/* An old name cache exists.

Copy it. */

names -= SIZE_HACK;
memcpy((char *)newnames, (char *)names,
(newtop + SIZE_HACK) * sizeof(NAME));
cp = (char *)names;
XFREE(cp, "db_grow.name");
} else {
/* Creating a brand new struct database. Fill in the
* 'reserved' area in case it gets referenced.
*/
names = newnames;
for (i = 0; i < SIZE_HACK; i++) {
names[i] = NULL;
}

}
names = newnames + SIZE_HACK;

-46-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489

Saturday, June 16, 2012 11:47 PM

newnames = NULL;
newpurenames = (NAME *) XCALLOC(newsize + SIZE_HACK,
sizeof(NAME),
"db_grow.purenames");
if (!newpurenames) {
fprintf(mainlog_fp,
"ABORT! db.c, could not allocate space for %d item name cache in
db_grow().\n", newsize);
abort();
}
memset((char *)newpurenames, 0, (newsize + SIZE_HACK) * sizeof(NAME));
if (purenames) {
/* An old name cache exists.

Copy it. */

purenames -= SIZE_HACK;
memcpy((char *)newpurenames, (char *)purenames,
(newtop + SIZE_HACK) * sizeof(NAME));
cp = (char *)purenames;
XFREE(cp, "db_grow.purename");
} else {
/* Creating a brand new struct database. Fill in the
* 'reserved' area in case it gets referenced.
*/
purenames = newpurenames;
for (i = 0; i < SIZE_HACK; i++) {
purenames[i] = NULL;
}

}
purenames = newpurenames + SIZE_HACK;
newpurenames = NULL;
/* Grow the db array */
newdb = (OBJ *) XCALLOC(newsize + SIZE_HACK, sizeof(OBJ),
"db_grow.db");
if (!newdb) {
STARTLOG(LOG_ALWAYS, "ALC", "DB")
log_printf("Could not allocate space for %d item struct database." , newsize);
ENDLOG
abort();
}
if (db) {
/* An old struct database exists.
db -= SIZE_HACK;
memcpy((char *)newdb, (char *)db,
-47-

Copy it to the new buffer */

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542

Saturday, June 16, 2012 11:47 PM

(mudstate.db_top + SIZE_HACK) * sizeof(OBJ));


cp = (char *)db;
XFREE(cp, "db_grow.db");
} else {
/* Creating a brand new struct database. Fill in the
* 'reserved' area in case it gets referenced.
*/
db = newdb;
for (i = 0; i < SIZE_HACK; i++) {
s_Owner(i, GOD);
s_Flags(i, (TYPE_GARBAGE | GOING));
s_Flags2(i, 0);
s_Flags3(i, 0);
s_Powers(i, 0);
s_Powers2(i, 0);
s_Location(i, NOTHING);
s_Contents(i, NOTHING);
s_Exits(i, NOTHING);
s_Link(i, NOTHING);
s_Next(i, NOTHING);
s_Zone(i, NOTHING);
s_Parent(i, NOTHING);
}

}
db = newdb + SIZE_HACK;
newdb = NULL;

/* Go do the rest of the things */


CALL_ALL_MODULES(db_grow, (newsize, newtop));
for (i = mudstate.db_top; i < newtop; i++) {
names[i] = NULL;
purenames[i] = NULL;
}
initialize_objects(mudstate.db_top, newtop);
mudstate.db_top = newtop;
mudstate.db_size = newsize;
/* Grow the db mark buffer */
marksize = (newsize + 7) >> 3;
newmarkbuf = (MARKBUF *) XMALLOC(marksize, "db_grow");
memset((char *)newmarkbuf, 0, marksize);
if (mudstate.markbits) {
marksize = (newtop + 7) >> 3;
memcpy((char *)newmarkbuf, (char *)mudstate.markbits, marksize);
cp = (char *)mudstate.markbits;
XFREE(cp, "db_grow");
}
mudstate.markbits = newmarkbuf;
-48-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595

Saturday, June 16, 2012 11:47 PM

}
void NDECL(db_free)
{
char *cp;

if (db != NULL) {
db -= SIZE_HACK;
cp = (char *)db;
XFREE(cp, "db_grow");
db = NULL;
}
mudstate.db_top = 0;
mudstate.db_size = 0;
mudstate.freelist = NOTHING;

void NDECL(db_make_minimal)
{
dbref obj;
db_free();
db_grow(1);
s_Name(0, "Limbo");
s_Flags(0, TYPE_ROOM);
s_Flags2(0, 0);
s_Flags3(0, 0);
s_Powers(0, 0);
s_Powers2(0, 0);
s_Location(0, NOTHING);
s_Exits(0, NOTHING);
s_Link(0, NOTHING);
s_Parent(0, NOTHING);
s_Zone(0, NOTHING);
s_Pennies(0, 1);
s_Owner(0, 1);
/* should be #1 */
load_player_names();
obj = create_player((char *)"Wizard", (char *)"potrzebie", NOTHING, 0, 1);
s_Flags(obj, Flags(obj) | WIZARD);
s_Flags2(obj, 0);
s_Flags3(obj, 0);
s_Powers(obj, 0);
s_Powers2(obj, 0);
s_Pennies(obj, 1000);
/* Manually link to Limbo, just in case */
s_Location(obj, 0);
s_Next(obj, NOTHING);
s_Contents(0, obj);
-49-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648

Saturday, June 16, 2012 11:47 PM

s_Link(obj, 0);

dbref parse_dbref(s)
const char *s;
{
const char *p;
int x;
/* Enforce completely numeric dbrefs */
for (p = s; *p; p++) {
if (!isdigit(*p))
return NOTHING;
}

x = atoi(s);
return ((x >= 0) ? x : NOTHING);

void putstring(f, s)
FILE *f;
const char *s;
{
putc('"', f);
while (s && *s) {
switch (*s) {
case '\n':
putc('\\', f);
putc('n', f);
break;
case '\r':
putc('\\', f);
putc('r', f);
break;
case '\t':
putc('\\', f);
putc('t', f);
break;
case ESC_CHAR:
putc('\\', f);
putc('e', f);
break;
case '\\':
case '"':
putc('\\', f);
default:
putc(*s, f);
}
s++;
}
putc('"', f);
-50-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701

Saturday, June 16, 2012 11:47 PM

putc('\n', f);

const char *getstring_noalloc(f, new_strings)


FILE *f;
int new_strings;
{
static char buf[LBUF_SIZE];
char *p;
int c, lastc;
p = buf;
c = fgetc(f);
if (!new_strings || (c != '"')) {
ungetc(c, f);
c = '\0';
for (;;) {
lastc = c;
c = fgetc(f);
/* If EOF or null, return */
if (!c || (c == EOF)) {
*p = '\0';
return buf;
}
/* If a newline, return if prior char is not a cr.
* Otherwise keep on truckin'
*/
if ((c == '\n') && (lastc != '\r')) {
*p = '\0';
return buf;
}
safe_chr(c, buf, &p);

}
} else {
for (;;) {
c = fgetc(f);
if (c == '"') {
if ((c = fgetc(f)) != '\n')
ungetc(c, f);
*p = '\0';
return buf;
} else if (c == '\\') {
c = fgetc(f);
switch (c) {
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
-51-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754

Saturday, June 16, 2012 11:47 PM

case 't':
c = '\t';
break;
case 'e':
c = ESC_CHAR;
break;
}

}
if ((c == '\0') || (c == EOF)) {
*p = '\0';
return buf;
}
safe_chr(c, buf, &p);

INLINE dbref getref(f)


FILE *f;
{
static char buf[SBUF_SIZE];
fgets(buf, sizeof(buf), f);
return (atoi(buf));
}
INLINE long getlong(f)
FILE *f;
{
static char buf[SBUF_SIZE];
fgets(buf, sizeof(buf), f);
return (atol(buf));
}
void free_boolexp(b)
BOOLEXP *b;
{
if (b == TRUE_BOOLEXP)
return;
switch (b->type) {
case BOOLEXP_AND:
case BOOLEXP_OR:
free_boolexp(b->sub1);
free_boolexp(b->sub2);
free_bool(b);
break;
case BOOLEXP_NOT:
case BOOLEXP_CARRY:
case BOOLEXP_IS:
case BOOLEXP_OWNER:
case BOOLEXP_INDIR:
free_boolexp(b->sub1);
free_bool(b);
-52-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807

Saturday, June 16, 2012 11:47 PM

break;
case BOOLEXP_CONST:
free_bool(b);
break;
case BOOLEXP_ATR:
case BOOLEXP_EVAL:
XFREE(b->sub1, "test_atr.sub1");
free_bool(b);
break;
}

BOOLEXP *dup_bool(b)
BOOLEXP *b;
{
BOOLEXP *r;
if (b == TRUE_BOOLEXP)
return (TRUE_BOOLEXP);

r = alloc_bool("dup_bool");
switch (r->type = b->type) {
case BOOLEXP_AND:
case BOOLEXP_OR:
r->sub2 = dup_bool(b->sub2);
case BOOLEXP_NOT:
case BOOLEXP_CARRY:
case BOOLEXP_IS:
case BOOLEXP_OWNER:
case BOOLEXP_INDIR:
r->sub1 = dup_bool(b->sub1);
case BOOLEXP_CONST:
r->thing = b->thing;
break;
case BOOLEXP_EVAL:
case BOOLEXP_ATR:
r->thing = b->thing;
r->sub1 = (BOOLEXP *) XSTRDUP((char *)b->sub1, "dup_bool.sub1");
break;
default:
fprintf(mainlog_fp, "bad bool type!!\n");
return (TRUE_BOOLEXP);
}
return (r);

int init_gdbm_db(gdbmfile)
char *gdbmfile;
{
/* Calculate proper database block size */
for (mudstate.db_block_size = 1; mudstate.db_block_size < (LBUF_SIZE * 4);
mudstate.db_block_size = mudstate.db_block_size << 1) ;
-53-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860

Saturday, June 16, 2012 11:47 PM

cache_init(mudconf.cache_width);
dddb_setfile(gdbmfile);
dddb_init();
STARTLOG(LOG_ALWAYS, "INI", "LOAD")
log_printf("Using gdbm file: %s", gdbmfile);
ENDLOG
db_free();
return (0);

/* check_zone - checks back through a zone tree for control */


int check_zone(player, thing)
dbref player, thing;
{
if (mudstate.standalone)
return 0;
if (!mudconf.have_zones || (Zone(thing) == NOTHING) ||
isPlayer(thing) ||
(mudstate.zone_nest_num + 1 == mudconf.zone_nest_lim)) {
mudstate.zone_nest_num = 0;
return 0;
}
/* We check Control_OK on the thing itself, not on its ZMO -* that allows us to have things default into a zone without
* needing to be controlled by that ZMO.
*/
if (!Control_ok(thing)) {
return 0;
}
mudstate.zone_nest_num++;
/* If the zone doesn't have a ControlLock, DON'T allow control. */
if (atr_get_raw(Zone(thing), A_LCONTROL) &&
could_doit(player, Zone(thing), A_LCONTROL)) {
mudstate.zone_nest_num = 0;
return 1;
} else {
return check_zone(player, Zone(thing));
}
}
int check_zone_for_player(player, thing)
dbref player, thing;
{
if (!Control_ok(Zone(thing))) {
return 0;
-54-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912

Saturday, June 16, 2012 11:47 PM

mudstate.zone_nest_num++;
if (!mudconf.have_zones || (Zone(thing) == NOTHING) ||
(mudstate.zone_nest_num == mudconf.zone_nest_lim) || !(isPlayer(thing))) {
mudstate.zone_nest_num = 0;
return 0;
}
if (atr_get_raw(Zone(thing), A_LCONTROL) && could_doit(player, Zone(thing),
A_LCONTROL)) {
mudstate.zone_nest_num = 0;
return 1;
} else {
return check_zone(player, Zone(thing));
}
}
/* --------------------------------------------------------------------------* dump_restart_db: Writes out socket information.
*/
void dump_restart_db()
{
FILE *f;
DESC *d;
int version = 0;
/* We maintain a version number for the restart database,
* so we can restart even if the format of the restart db
* has been changed in the new executable.
*/
version |= RS_RECORD_PLAYERS;
version |= RS_NEW_STRINGS;
version |= RS_COUNT_REBOOTS;
f = fopen("restart.db", "w");
fprintf(f, "+V%d\n", version);
putref(f, sock);
putlong(f, mudstate.start_time);
putref(f, mudstate.reboot_nums);
putstring(f, mudstate.doing_hdr);
putref(f, mudstate.record_players);
DESC_ITER_ALL(d) {
putref(f, d->descriptor);
putref(f, d->flags);
putlong(f, d->connected_at);
putref(f, d->command_count);
putref(f, d->timeout);
putref(f, d->host_info);
-55-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965

Saturday, June 16, 2012 11:47 PM

putref(f, d->player);
putlong(f, d->last_time);
putstring(f, d->output_prefix);
putstring(f, d->output_suffix);
putstring(f, d->addr);
putstring(f, d->doing);
putstring(f, d->username);

}
putref(f, 0);
}

fclose(f);

void load_restart_db()
{
FILE *f;
DESC *d;
DESC *p;
int val, version, new_strings = 0;
char *temp, buf[8];
struct stat fstatbuf;
f = fopen("restart.db", "r");
if (!f) {
mudstate.restarting = 0;
return;
}
mudstate.restarting = 1;
fgets(buf, 3, f);
if (strncmp(buf, "+V", 2)) {
abort();
}
version = getref(f);
sock = getref(f);
if (version & RS_NEW_STRINGS)
new_strings = 1;
maxd = sock + 1;
mudstate.start_time = (time_t) getlong(f);
if (version & RS_COUNT_REBOOTS)
mudstate.reboot_nums = getref(f) + 1;
strcpy(mudstate.doing_hdr, getstring_noalloc(f, new_strings));
if (version & RS_CONCENTRATE) {
(void)getref(f);
}
if (version & RS_RECORD_PLAYERS) {
-56-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018

Saturday, June 16, 2012 11:47 PM

mudstate.record_players = getref(f);

while ((val = getref(f)) != 0) {


ndescriptors++;
d = alloc_desc("restart");
d->descriptor = val;
d->flags = getref(f);
d->connected_at = (time_t) getlong(f);
d->retries_left = mudconf.retry_limit;
d->command_count = getref(f);
d->timeout = getref(f);
d->host_info = getref(f);
d->player = getref(f);
d->last_time = (time_t) getlong(f);
temp = (char *)getstring_noalloc(f, new_strings);
if (*temp) {
d->output_prefix = alloc_lbuf("set_userstring");
strcpy(d->output_prefix, temp);
} else {
d->output_prefix = NULL;
}
temp = (char *)getstring_noalloc(f, new_strings);
if (*temp) {
d->output_suffix = alloc_lbuf("set_userstring");
strcpy(d->output_suffix, temp);
} else {
d->output_suffix = NULL;
}
strcpy(d->addr, getstring_noalloc(f, new_strings));
strcpy(d->doing, getstring_noalloc(f, new_strings));
strcpy(d->username, getstring_noalloc(f, new_strings));
d->colormap = NULL;
if (version & RS_CONCENTRATE) {
(void)getref(f);
(void)getref(f);
}
d->output_size = 0;
d->output_tot = 0;
d->output_lost = 0;
d->output_head = NULL;
d->output_tail = NULL;
d->input_head = NULL;
d->input_tail = NULL;
d->input_size = 0;
d->input_tot = 0;
d->input_lost = 0;
d->raw_input = NULL;
d->raw_input_at = NULL;
d->quota = mudconf.cmd_quota_max;
d->program_data = NULL;
-57-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.c

3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063

Saturday, June 16, 2012 11:47 PM

d->hashnext = NULL;
/* Note that d->address is NOT INITIALIZED, and it DOES
* get used later, particularly when checking logout.
*/
if (descriptor_list) {
for (p = descriptor_list; p->next; p = p->next) ;
d->prev = &p->next;
p->next = d;
d->next = NULL;
} else {
d->next = descriptor_list;
d->prev = &descriptor_list;
descriptor_list = d;
}

if (d->descriptor >= maxd)


maxd = d->descriptor + 1;
desc_addhash(d);
if (isPlayer(d->player))
s_Flags2(d->player, Flags2(d->player) | CONNECTED);

/* In case we've had anything bizarre happen... */


DESC_ITER_ALL(d) {
if (fstat(d->descriptor, &fstatbuf) < 0) {
STARTLOG(LOG_PROBLEMS, "ERR", "RESTART")
log_printf("Bad descriptor %d", d->descriptor);
ENDLOG
shutdownsock(d, R_SOCKDIED);
}
}
DESC_ITER_CONN(d) {
if (!isPlayer(d->player)) {
shutdownsock(d, R_QUIT);
}
}

fclose(f);
remove("restart.db");

-58-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:12 PM

/* db.h */
/* $Id: db.h,v 1.51 2003/11/19 00:27:30 dpassmor Exp $ */
#include "copyright.h"
#ifndef __DB_H
#define __DB_H
#define
#define
#define
#define

SYNC
CLOSE
DBCLOSE
OPTIMIZE

cache_sync()
{ cache_sync(); dddb_close(); }
dddb_close()
(void) dddb_optimize()

/* Macros to help deal with batch writes of attribute numbers and objects */
#define ATRNUM_BLOCK_SIZE
(int) ((mudstate.db_block_size - 32) / \
(2 * sizeof (int) + VNAME_SIZE))
#define ATRNUM_BLOCK_BYTES (int) ((ATRNUM_BLOCK_SIZE) * \
(2 * sizeof (int) + VNAME_SIZE))
#define OBJECT_BLOCK_SIZE
(int) ((mudstate.db_block_size - 32) / \
(sizeof(int) + sizeof(DUMPOBJ)))
#define OBJECT_BLOCK_BYTES (int) ((OBJECT_BLOCK_SIZE) * \
(sizeof(int) + sizeof(DUMPOBJ)))
#define ENTRY_NUM_BLOCKS(total, blksize)
(int) (total / blksize)
#define ENTRY_BLOCK_STARTS(blk, blksize)
(int) (blk * blksize)
#define ENTRY_BLOCK_ENDS(blk, blksize) (int) (blk * blksize) + (blksize - 1)
#include "udb.h"
#include "udb_defs.h"
#define ITER_PARENTS(t,p,l) for ((l)=0, (p)=(t); \
(Good_obj(p) && \
((l) < mudconf.parent_nest_lim)); \
(p)=Parent(p), (l)++)
#define Hasprivs(x)

(Royalty(x) || Wizard(x))

typedef struct attr ATTR;


struct attr {
const char *name;
/* This has to be first. braindeath. */
int number;
/* attr number */
int flags;
int FDECL((*check),(int, dbref, dbref, int, char *));
};
extern ATTR *
extern ATTR *

FDECL(atr_num, (int anum));


FDECL(atr_str, (char *s));

extern ATTR attr[];


extern ATTR **anum_table;
#define anum_get(x) (anum_table[(x)])
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:12 PM

#define anum_set(x,v)
anum_table[(x)] = v
extern void FDECL(anum_extend,(int));
#define ATR_INFO_CHAR

'\1'

/* Leadin char for attr control data */

/* Boolean expressions,
#define BOOLEXP_AND 0
#define BOOLEXP_OR 1
#define BOOLEXP_NOT 2
#define BOOLEXP_CONST
#define BOOLEXP_ATR 4
#define BOOLEXP_INDIR
#define BOOLEXP_CARRY
#define BOOLEXP_IS 7
#define BOOLEXP_OWNER
#define BOOLEXP_EVAL

for locks */

3
5
6
8
9

typedef struct boolexp BOOLEXP;


struct boolexp {
boolexp_type type;
struct boolexp *sub1;
struct boolexp *sub2;
dbref thing;
/* thing refers to an object */
};
#define TRUE_BOOLEXP ((BOOLEXP *) 0)
/* Database format information */
#define
#define
#define
#define
#define
#define
#define

F_UNKNOWN
F_MUSH
F_MUSE
F_MUD
F_MUCK
F_MUX
F_TINYMUSH

0
1
2
3
4
5
6

/*
/*
/*
/*
/*
/*
/*

Unknown database format */


MUSH format (many variants) */
MUSE format */
Old TinyMUD format */
TinyMUCK format */
TinyMUX format */
TinyMUSH 3.0 format */

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

V_MASK
0x000000ff /*
V_ZONE
0x00000100 /*
V_LINK
0x00000200 /*
V_GDBM
0x00000400 /*
V_ATRNAME
0x00000800 /*
V_ATRKEY
0x00001000 /*
V_PERNKEY
0x00001000 /*
V_PARENT
0x00002000 /*
V_COMM
0x00004000 /*
V_ATRMONEY 0x00008000 /*
V_XFLAGS
0x00010000 /*
V_POWERS
0x00020000
V_3FLAGS
0x00040000 /*
V_QUOTED
0x00080000 /*
V_TQUOTAS
0x00100000
V_TIMESTAMPS
0x00200000

Database version */
ZONE/DOMAIN field */
LINK field (exits from objs) */
attrs are in a gdbm db, not here */
NAME is an attr, not in the hdr */
KEY is an attr, not in the hdr */
PERN: Extra locks in object hdr */
db has the PARENT field */
PERN: Comm status in header */
Money is kept in an attribute */
An extra word of flags */
/* Powers? */
Adding a 3rd flag word */
Quoted strings, ala PennMUSH */
/* Typed quotas */
/* Timestamps */
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:12 PM

#define V_VISUALATTRS
0x00400000 /* ODark-to-Visual attr flags */
#define V_DBCLEAN
0x80000000 /* Option to clean attr table */
/* special dbref's */
#define NOTHING
(-1)
#define AMBIGUOUS
(-2)
#define HOME
(-3)
#define NOPERM
(-4)

/*
/*
/*
/*

null dbref */
multiple possibilities, for matchers */
virtual room, represents mover's home */
Error status, no permission */

typedef struct object OBJ;


struct object {
dbref
location;
/* PLAYER, THING: where it is */
/* ROOM: dropto: */
/* EXIT: where it goes to */
dbref
contents;
/* PLAYER, THING, ROOM: head of contentslist */
/* EXIT: unused */
dbref
exits;
/* PLAYER, THING, ROOM: head of exitslist */
/* EXIT: where it is */
dbref
next;
/* PLAYER, THING: next in contentslist */
/* EXIT: next in exitslist */
/* ROOM: unused */
dbref
link;
/* PLAYER, THING: home location */
/* ROOM, EXIT: unused */
dbref
parent;
/* ALL: defaults for attrs, exits, $cmds, */
dbref
owner;
/* PLAYER: domain number + class + moreflags */
/* THING, ROOM, EXIT: owning player number */
dbref

zone;

/* Whatever the object is zoned to.*/

FLAG
FLAG
FLAG

flags;
flags2;
flags3;

/* ALL: Flags set on the object */


/* ALL: even more flags */
/* ALL: yet _more_ flags */

POWER
POWER

powers;
powers2;

/* ALL: Powers on object */


/* ALL: even more powers */

time_t
time_t

last_access;
/* ALL: Time last accessed */
last_mod;
/* ALL: Time last modified */

/* Make sure everything you want to write to the DBM database


* is in the first part of the structure and included in DUMPOBJ */
int name_length;
int
int
int
int

/* ALL: Length of name string */

stack_count;
/* ALL: number of things on the stack */
vars_count; /* ALL: number of variables */
struct_count;
/* ALL: number of structures */
instance_count; /* ALL: number of struct instances */

#ifndef NO_TIMECHECKING
struct timeval cpu_time_used;
#endif

/* ALL: CPU time eaten */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

#ifdef MEMORY_BASED
Obj attrtext;
#endif
};

Saturday, June 16, 2012 11:12 PM

/* Array of attribute text */

/* The DUMPOBJ structure exists for use during database writes. It is


* a duplicate of the OBJ structure except for items we don't need to write */
typedef struct dump_object DUMPOBJ;
struct dump_object {
dbref
location;
/* PLAYER, THING: where it is */
/* ROOM: dropto: */
/* EXIT: where it goes to */
dbref
contents;
/* PLAYER, THING, ROOM: head of contentslist */
/* EXIT: unused */
dbref
exits;
/* PLAYER, THING, ROOM: head of exitslist */
/* EXIT: where it is */
dbref
next;
/* PLAYER, THING: next in contentslist */
/* EXIT: next in exitslist */
/* ROOM: unused */
dbref
link;
/* PLAYER, THING: home location */
/* ROOM, EXIT: unused */
dbref
parent;
/* ALL: defaults for attrs, exits, $cmds, */
dbref
owner;
/* PLAYER: domain number + class + moreflags */
/* THING, ROOM, EXIT: owning player number */

};

dbref

zone;

/* Whatever the object is zoned to.*/

FLAG
FLAG
FLAG

flags;
flags2;
flags3;

/* ALL: Flags set on the object */


/* ALL: even more flags */
/* ALL: yet _more_ flags */

POWER
POWER

powers;
powers2;

/* ALL: Powers on object */


/* ALL: even more powers */

time_t
time_t

last_access;
/* ALL: Time last accessed */
last_mod;
/* ALL: Time last modified */

typedef char *NAME;


extern OBJ *db;
extern NAME *names;
#define Location(t)

db[t].location

#define Zone(t)

db[t].zone

#define
#define
#define
#define
#define

db[t].contents
db[t].exits
db[t].next
db[t].link
db[t].owner

Contents(t)
Exits(t)
Next(t)
Link(t)
Owner(t)

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

#define
#define
#define
#define
#define
#define
#define
#define
#define

Parent(t)
Flags(t)
Flags2(t)
Flags3(t)
Powers(t)
Powers2(t)
NameLen(t)
Home(t)
Dropto(t)

#define AccessTime(t)
#define ModTime(t)
#define
#define
#define
#define

VarsCount(t)
StackCount(t)
StructCount(t)
InstanceCount(t)

Saturday, June 16, 2012 11:12 PM

db[t].parent
db[t].flags
db[t].flags2
db[t].flags3
db[t].powers
db[t].powers2
db[t].name_length
Link(t)
Location(t)
db[t].last_access
db[t].last_mod
db[t].vars_count
db[t].stack_count
db[t].struct_count
db[t].instance_count

#ifndef NO_TIMECHECKING
#define Time_Used(t)
db[t].cpu_time_used
#define s_Time_Used(t,n)
db[t].cpu_time_used.tv_sec = n.tv_sec; \
db[t].cpu_time_used.tv_usec = n.tv_usec
#endif
/* If we modify something on the db object that needs to be written
* at dump time, set the object DIRTY */
#define s_Location(t,n)
db[t].location = (n); \
db[t].flags3 |= DIRTY
#define s_Zone(t,n)
db[t].zone = (n); \
db[t].flags3 |= DIRTY
#define s_Contents(t,n)
db[t].contents = (n); \
db[t].flags3 |= DIRTY
#define s_Exits(t,n)
db[t].exits = (n); \
db[t].flags3 |= DIRTY
#define s_Next(t,n)
db[t].next = (n); \
db[t].flags3 |= DIRTY
#define s_Link(t,n)
db[t].link = (n); \
db[t].flags3 |= DIRTY
#define s_Owner(t,n)
db[t].owner = (n); \
db[t].flags3 |= DIRTY
#define s_Parent(t,n)
db[t].parent = (n); \
db[t].flags3 |= DIRTY
#define s_Flags(t,n)
db[t].flags = (n); \
db[t].flags3 |= DIRTY
#define s_Flags2(t,n)
db[t].flags2 = (n); \
db[t].flags3 |= DIRTY
#define s_Flags3(t,n)
db[t].flags3 = (n); \
db[t].flags3 |= DIRTY
#define s_Powers(t,n)
db[t].powers = (n); \
db[t].flags3 |= DIRTY
#define s_Powers2(t,n)
db[t].powers2 = (n); \
db[t].flags3 |= DIRTY
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.h

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:12 PM

#define s_AccessTime(t,n)
db[t].last_access = (n); \
db[t].flags3 |= DIRTY
#define s_ModTime(t,n)
db[t].last_mod = (n); \
db[t].flags3 |= DIRTY
#define s_Accessed(t)
db[t].last_access = mudstate.now; \
db[t].flags3 |= DIRTY
#define s_Modified(t)
db[t].last_mod = mudstate.now; \
db[t].flags3 |= DIRTY
#define s_Clean(t)
db[t].flags3 = db[t].flags3 & ~DIRTY
#define s_NameLen(t,n)
db[t].name_length = (n)
#define s_Home(t,n)
s_Link(t,n)
#define s_Dropto(t,n)
s_Location(t,n)
#define s_VarsCount(t,n)
db[t].vars_count = n;
#define s_StackCount(t,n)
db[t].stack_count = n;
#define s_StructCount(t,n) db[t].struct_count = n;
#define s_InstanceCount(t,n)
db[t].instance_count = n;
extern int FDECL(Pennies, (dbref));
extern void FDECL(s_Pennies, (dbref, int));
extern void NDECL(tf_init);
extern int FDECL(tf_open, (char *, int));
extern void FDECL(tf_close, (int));
extern FILE *
FDECL(tf_fopen, (char *, int));
extern void FDECL(tf_fclose, (FILE *));
extern FILE *
FDECL(tf_popen, (char *, int));
#define tf_pclose(f)
tf_fclose(f)
#define putref(pr__f,pr__ref)
#define putlong(pr__f,pr__i)
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

fprintf(pr__f, "%d\n", (int)pr__ref)


fprintf(pr__f, "%ld\n", (long)pr__i)

INLINE dbref FDECL(getref, (FILE *));


INLINE long FDECL(getlong, (FILE *));
BOOLEXP *FDECL(dup_bool, (BOOLEXP *));
void FDECL(free_boolexp, (BOOLEXP *));
dbref
FDECL(parse_dbref, (const char *));
int FDECL(mkattr, (char *));
void FDECL(al_add, (dbref, int));
void FDECL(al_delete, (dbref, int));
void FDECL(al_destroy, (dbref));
void NDECL(al_store);
void FDECL(db_grow, (dbref));
void NDECL(db_free);
void NDECL(db_make_minimal);
dbref
FDECL(db_convert, (FILE *, int *, int *, int *));
dbref
NDECL(db_read);
dbref
FDECL(db_write_flatfile, (FILE *, int, int));
dbref
NDECL(db_write);
FILE
*FDECL(db_module_flatfile, (char *, int));
void FDECL(destroy_thing, (dbref));
void FDECL(destroy_exit, (dbref));

#define DOLIST(thing,list) \
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db.h

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

Saturday, June 16, 2012 11:12 PM

for ((thing)=(list); \
((thing)!=NOTHING) && (Next(thing)!=(thing)); \
(thing)=Next(thing))
#define SAFE_DOLIST(thing,next,list) \
for ((thing)=(list),(next)=((thing)==NOTHING ? NOTHING: Next(thing)); \
(thing)!=NOTHING && (Next(thing)!=(thing)); \
(thing)=(next), (next)=Next(next))
#define DO_WHOLE_DB(thing) \
for ((thing)=0; (thing)<mudstate.db_top; (thing)++)
#define DO_WHOLE_DB_BACKWARDS(thing) \
for ((thing)=mudstate.db_top-1; (thing)>=0; (thing)--)
#define Dropper(thing)

(Connected(Owner(thing)) && Hearer(thing))

/* Clear a player's aliases, given x (player dbref) and b (alias buffer). */


#define Clear_Player_Aliases(x,b) \
{ \
char *cpa__p, *cpa__tokp; \
for (cpa__p = strtok_r((b), ";", &cpa__tokp); cpa__p; \
cpa__p = strtok_r(NULL, ";", &cpa__tokp)) { \
delete_player_name((x), cpa__p); \
} \
}
typedef struct logfiletable LOGFILETAB;
struct logfiletable {
int log_flag;
FILE *fileptr;
char *filename;
};
typedef struct numbertable NUMBERTAB;
struct numbertable {
int num;
};
#endif /* __DB_H */

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_empty.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

Saturday, June 16, 2012 11:47 PM

/* db_empty.c - Placeholder code if not using an external SQL database. */


/* $Id: db_empty.c,v 1.7 2003/02/24 18:05:22 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "functions.h" /* required by code */
/* See db_sql.h for details of what each of these functions do. */
int sql_init()
{
return -1;
}
int sql_query(player, q_string, buff, bufc, row_delim, field_delim)
dbref player;
char *q_string;
char *buff;
char **bufc;
const Delim *row_delim, *field_delim;
{
notify(player, "No external SQL database connectivity is configured." );
if (buff)
safe_str("#-1", buff, bufc);
return -1;
}
void sql_shutdown()
{
mudstate.sql_socket = -1;
}

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_msql.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:47 PM

/* db_msql.c - Implements accessing an mSQL 2.x database. */


/* $Id: db_msql.c,v 1.15 2003/02/24 18:05:22 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "functions.h" /* required by code */
#include "msql.h"

/* required by code */

/* See db_sql.h for details of what each of these functions do. */


/* Because we cannot trap error codes in mSQL, just error messages, we have
* to compare against error messages to find out what really happened with
* something. This particular error message is SERVER_GONE_ERROR in
* mSQL's errmsg.h -- this needs to change if that API definition changes.
*/
#define MSQL_SERVER_GONE_ERROR "MSQL server has gone away"
/* Number of times to retry a connection if we fail in the middle of
* a query.
*/
#define MSQL_RETRY_TIMES 3
/* -----------------------------------------------------------------------* Do the work here.
*/
void sql_shutdown()
{
if (mudstate.sql_socket == -1)
return;
msqlClose(mudstate.sql_socket);
mudstate.sql_socket = -1;
}
int sql_init()
{
int result;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_msql.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:47 PM

/* Make sure we have valid config options. */


if (!mudconf.sql_host || !*mudconf.sql_host)
return -1;
if (!mudconf.sql_db || !*mudconf.sql_db)
return -1;
/* If we are already connected, drop and retry the connection, in
* case for some reason the server went away.
*/
sql_shutdown();
/* Try to connect to the database host. If we have specified
* localhost, use the Unix domain socket instead.
*/
if (!strcmp(mudconf.sql_host, (char *) "localhost"))
result = msqlConnect(NULL);
else
result = msqlConnect(mudconf.sql_host);
if (result == -1) {
STARTLOG(LOG_ALWAYS, "SQL", "CONN")
log_printf("Failed connection to SQL server %s: %s" ,
mudconf.sql_host, msqlErrMsg);
ENDLOG
return -1;
}
STARTLOG(LOG_ALWAYS, "SQL", "CONN")
log_printf("Connected to SQL server %s, socket fd %d" ,
mudconf.sql_host, result);
ENDLOG
mudstate.sql_socket = result;
/* Select the database we want. If we can't get it, disconnect. */
if (msqlSelectDB(mudstate.sql_socket, mudconf.sql_db) == -1) {
STARTLOG(LOG_ALWAYS, "SQL", "CONN")
log_printf("Failed db select: %s", msqlErrMsg);
ENDLOG
msqlClose(mudstate.sql_socket);
mudstate.sql_socket = -1;
return -1;
}

STARTLOG(LOG_ALWAYS, "SQL", "CONN")


log_printf("SQL database selected: %s", mudconf.sql_db);
ENDLOG
return (mudstate.sql_socket);

int sql_query(player, q_string, buff, bufc, row_delim, field_delim)


-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_msql.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:47 PM

dbref player;
char *q_string;
char *buff;
char **bufc;
const Delim *row_delim, *field_delim;
m_result *qres;
m_row row_p;
int got_rows, got_fields;
int i, j;
int retries;
/* If we have no connection, and we don't have auto-reconnect on
* (or we try to auto-reconnect and we fail), this is an error
* generating a #-1. Notify the player, too, and set the return code.
*/
if ((mudstate.sql_socket == -1) && (mudconf.sql_reconnect != 0)) {
/* Try to reconnect. */
retries = 0;
while ((retries < MSQL_RETRY_TIMES) &&
(mudstate.sql_socket == -1)) {
sleep(1);
sql_init();
retries++;
}
}
if (mudstate.sql_socket == -1) {
notify(player, "No SQL database connection." );
if (buff)
safe_str("#-1", buff, bufc);
return -1;
}
if (!q_string || !*q_string)
return 0;
/* Send the query. */
got_rows = msqlQuery(mudstate.sql_socket, q_string);
if ((got_rows == -1) && !strcmp(msqlErrMsg, MSQL_SERVER_GONE_ERROR)) {
/* We got this error because the server died unexpectedly
* and it shouldn't have. Try repeatedly to reconnect before
* giving up and failing. This induces a few seconds of lag,
* depending on number of retries; we put in the sleep() here
* to see if waiting a little bit helps.
*/
STARTLOG(LOG_PROBLEMS, "SQL", "GONE")
log_printf("Connection died to SQL server on fd %d" ,
mudstate.sql_socket);
ENDLOG

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_msql.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:47 PM

retries = 0;
mudstate.sql_socket = -1;
while ((retries < MSQL_RETRY_TIMES) &&
(mudstate.sql_socket == -1)) {
sleep(1);
sql_init();
retries++;
}
if (mudstate.sql_socket != -1)
got_rows = msqlQuery(mudstate.sql_socket, q_string);
}
if (got_rows == -1) {
notify(player, msqlErrMsg);
if (buff)
safe_str("#-1", buff, bufc);
return -1;
}
/* A null store means that this wasn't a SELECT */
qres = msqlStoreResult();
if (!qres) {
notify(player, tprintf("SQL query touched %d %s.",
got_rows, (got_rows == 1) ? "row" : "rows"));
return 0;
}
/* Check to make sure we got rows back. */
got_rows = msqlNumRows(qres);
if (got_rows == 0) {
return 0;
}
/* Construct properly-delimited data. */
if (buff) {
for (i = 0; i < got_rows; i++) {
if (i > 0) {
print_sep(row_delim, buff, bufc);
}
row_p = msqlFetchRow(qres);
if (row_p) {
got_fields = msqlNumFields(qres);
for (j = 0; j < got_fields; j++) {
if (j > 0) {
print_sep(field_delim, buff, bufc);
}
if (row_p[j] && *row_p[j])
safe_str(row_p[j], buff, bufc);
}
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_msql.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

Saturday, June 16, 2012 11:47 PM

}
}
} else {
for (i = 0; i < got_rows; i++) {
row_p = msqlFetchRow(qres);
if (row_p) {
got_fields = msqlNumFields(qres);
for (j = 0; j < got_fields; j++) {
if (row_p[j] && *row_p[j]) {
notify(player, tprintf("Row %d, Field %d: %s",
i+1, j+1, row_p[j]));
} else {
notify(player,
tprintf("Row %d, Field %d: NULL", i+1, j+1));
}
}
} else {
notify(player, tprintf("Row %d: NULL", i+1));
}
}
}

msqlFreeResult(qres);
return 0;

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_mysql.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:46 PM

/* db_mysql.c - Implements accessing a mySQL 3.22+ database. */


/* $Id: db_mysql.c,v 1.11 2004/09/13 14:12:54 tyrspace Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "functions.h" /* required by code */
#include "mysql.h"
#include "errmsg.h"
/* See db_sql.h for details of what each of these functions do. */
/* Number of times to retry a connection if we fail in the middle of
* a query.
*/
#define MYSQL_RETRY_TIMES 3
static MYSQL *mysql_struct = NULL;
void sql_shutdown()
{
MYSQL *mysql;

if (!mysql_struct)
return;
mysql = mysql_struct;
STARTLOG(LOG_ALWAYS, "SQL", "DISC")
log_printf("Disconnected from SQL server %s, SQL database selected: %s" ,
mysql->host, mysql->db);
ENDLOG
mysql_close(mysql);
XFREE(mysql, "mysql");
mysql_struct = NULL;
mudstate.sql_socket = -1;

int sql_init()
{
MYSQL *mysql, *result;
/* Make sure we have valid config options. */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_mysql.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:46 PM

if (!mudconf.sql_host || !*mudconf.sql_host)
return -1;
if (!mudconf.sql_db || !*mudconf.sql_db)
return -1;
/* If we are already connected, drop and retry the connection, in
* case for some reason the server went away.
*/
if (mysql_struct)
sql_shutdown();
/* Try to connect to the database host. If we have specified
* localhost, use the Unix domain socket instead.
*/
mysql = (MYSQL *) XMALLOC(sizeof(MYSQL), "mysql");
mysql_init(mysql);
result =

mysql_real_connect(mysql, mudconf.sql_host,
mudconf.sql_username, mudconf.sql_password,
mudconf.sql_db, 0, NULL, 0);
if (!result) {
STARTLOG(LOG_ALWAYS, "SQL", "CONN")
log_printf("Failed connection to SQL server %s: %s" ,
mudconf.sql_host, mysql_error(mysql));
ENDLOG
XFREE(mysql, "mysql");
return -1;
}
STARTLOG(LOG_ALWAYS, "SQL", "CONN")
log_printf("Connected to SQL server %s, SQL database selected: %s" ,
mysql->host, mysql->db);
ENDLOG

mysql_struct = mysql;
mudstate.sql_socket = mysql->net.fd;
return 1;

int sql_query(player, q_string, buff, bufc, row_delim, field_delim)


dbref player;
char *q_string;
char *buff;
char **bufc;
const Delim *row_delim, *field_delim;
{
MYSQL_RES *qres;
MYSQL_ROW row_p;
MYSQL *mysql;
int num_rows, got_rows, got_fields;
int i, j;
int retries;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_mysql.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:46 PM

/* If we have no connection, and we don't have auto-reconnect on


* (or we try to auto-reconnect and we fail), this is an error
* generating a #-1. Notify the player, too, and set the return code.
*/
mysql = mysql_struct;
if ((!mysql) & (mudconf.sql_reconnect != 0)) {
/* Try to reconnect. */
retries = 0;
while ((retries < MYSQL_RETRY_TIMES) && !mysql) {
sleep(1);
sql_init();
mysql = mysql_struct;
retries++;
}
}
if (!mysql) {
notify(player, "No SQL database connection." );
if (buff)
safe_str("#-1", buff, bufc);
return -1;
}
if (!q_string || !*q_string)
return 0;
/* Send the query. */
got_rows = mysql_real_query(mysql, q_string, strlen(q_string));
if ((got_rows) && (mysql_errno(mysql) == CR_SERVER_GONE_ERROR)) {
/* We got this error because the server died unexpectedly
* and it shouldn't have. Try repeatedly to reconnect before
* giving up and failing. This induces a few seconds of lag,
* depending on number of retries; we put in the sleep() here
* to see if waiting a little bit helps.
*/
STARTLOG(LOG_PROBLEMS, "SQL", "GONE")
log_printf("Connection died to SQL server" );
ENDLOG
retries = 0;
sql_shutdown();
while ((retries < MYSQL_RETRY_TIMES) &&
(!mysql)) {
sleep(1);
sql_init();
mysql = mysql_struct;
retries++;
}

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_mysql.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:46 PM

if (mysql)
got_rows = mysql_real_query(mysql, q_string, strlen(q_string));
}
if (got_rows) {
notify(player, mysql_error(mysql));
if (buff)
safe_str("#-1", buff, bufc);
return -1;
}
/* A number of affected rows greater than 0 means it wasn't a SELECT */
num_rows = mysql_affected_rows(mysql);
if (num_rows > 0) {
notify(player, tprintf("SQL query touched %d %s.",
num_rows, (num_rows == 1) ? "row" : "rows"));
return 0;
} else if (num_rows == 0) {
return 0;
}
/* Check to make sure we got rows back. */
qres = mysql_store_result(mysql);
got_rows = mysql_num_rows(qres);
if (got_rows == 0) {
mysql_free_result(qres);
return 0;
}
/* Construct properly-delimited data. */
if (buff) {
for (i = 0; i < got_rows; i++) {
if (i > 0) {
print_sep(row_delim, buff, bufc);
}
row_p = mysql_fetch_row(qres);
if (row_p) {
got_fields = mysql_num_fields(qres);
for (j = 0; j < got_fields; j++) {
if (j > 0) {
print_sep(field_delim, buff, bufc);
}
if (row_p[j] && *row_p[j])
safe_str(row_p[j], buff, bufc);
}
}
}
} else {
for (i = 0; i < got_rows; i++) {
row_p = mysql_fetch_row(qres);
if (row_p) {
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_mysql.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

}
}

Saturday, June 16, 2012 11:46 PM

got_fields = mysql_num_fields(qres);
for (j = 0; j < got_fields; j++) {
if (row_p[j] && *row_p[j]) {
notify(player, tprintf("Row %d, Field %d: %s",
i+1, j+1, row_p[j]));
} else {
notify(player,
tprintf("Row %d, Field %d: NULL", i+1, j+1));
}
}
} else {
notify(player, tprintf("Row %d: NULL", i+1));
}

mysql_free_result(qres);
return 0;

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Saturday, June 16, 2012 11:46 PM

/* db_rw.c - flatfile implementation */


/* $Id: db_rw.c,v 1.96 2002/09/22 05:48:34 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include
#include
#include

"alloc.h" /*
"flags.h" /*
"htab.h"
/*
"mudconf.h"
"udb.h"
/*
"db.h"
/*

required by mudconf */
required by mudconf */
required by mudconf */
/* required by code */
required by code */
required by externs */

#include "externs.h"
#include "vattr.h"
#include "attrs.h"

/* required by code */
/* required by code */
/* required by code */

#include "powers.h" /* required by code */


extern void FDECL(db_grow, (dbref));
extern struct object *db;
static int g_version;
static int g_format;
static int g_flags;
extern int anum_alc_top;
static int *used_attrs_table;
/* --------------------------------------------------------------------------* getboolexp1: Get boolean subexpression from file.
*/
BOOLEXP *getboolexp1(f)
FILE *f;
{
BOOLEXP *b;
char *buff, *s;
int c, d, anum;
c = getc(f);
switch (c) {
case '\n':
ungetc(c, f);
return TRUE_BOOLEXP;
/* break; */
case EOF:
fprintf(mainlog_fp, "ABORT! db_rw.c, unexpected EOF in boolexp in
getboolexp1().\n");
abort();
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

Saturday, June 16, 2012 11:46 PM

break;
case '(':
b = alloc_bool("getboolexp1.openparen");
switch (c = getc(f)) {
case NOT_TOKEN:
b->type = BOOLEXP_NOT;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
case INDIR_TOKEN:
b->type = BOOLEXP_INDIR;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
case IS_TOKEN:
b->type = BOOLEXP_IS;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
case CARRY_TOKEN:
b->type = BOOLEXP_CARRY;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
case OWNER_TOKEN:
b->type = BOOLEXP_OWNER;
b->sub1 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;
default:
ungetc(c, f);
b->sub1 = getboolexp1(f);
if ((c = getc(f)) == '\n')
c = getc(f);
switch (c) {
case AND_TOKEN:
b->type = BOOLEXP_AND;
break;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

Saturday, June 16, 2012 11:46 PM

case OR_TOKEN:
b->type = BOOLEXP_OR;
break;
default:
goto error;
}
b->sub2 = getboolexp1(f);
if ((d = getc(f)) == '\n')
d = getc(f);
if (d != ')')
goto error;
return b;

}
case '-':
/* obsolete NOTHING key, eat it */
while ((c = getc(f)) != '\n') {
if (c == EOF) {
fprintf(mainlog_fp, "ABORT! db_rw.c, unexpected EOF in getboolexp1().\n" );
abort();
}
}
ungetc(c, f);
return TRUE_BOOLEXP;
case '"':
ungetc(c, f);
buff = alloc_lbuf("getboolexp.quoted");
StringCopy(buff, getstring_noalloc(f, 1));
c = fgetc(f);
if (c == EOF) {
free_lbuf(buff);
return TRUE_BOOLEXP;
}
b = alloc_bool("getboolexp1.quoted");
anum = mkattr(buff);
if (anum <= 0) {
free_bool(b);
free_lbuf(buff);
goto error;
}
free_lbuf(buff);
b->thing = anum;
/* if last character is : then this is an attribute lock. A
* last character of / means an eval lock
*/
if ((c == ':') || (c == '/')) {
if (c == '/')
b->type = BOOLEXP_EVAL;
else
b->type = BOOLEXP_ATR;
b->sub1 = (BOOLEXP *) XSTRDUP(getstring_noalloc(f, 1),
"getboolexp1.attr_lock");
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

Saturday, June 16, 2012 11:46 PM

}
return b;
default:
/* dbref or attribute */
ungetc(c, f);
b = alloc_bool("getboolexp1.default");
b->type = BOOLEXP_CONST;
b->thing = 0;
/* This is either an attribute, eval, or constant lock.
* Constant locks are of the form <num>, while attribute and
* eval locks are of the form <anam-or-anum>:<string> or
* <aname-or-anum>/<string> respectively. The
* characters <nl>, |, and & terminate the string.
*/
if (isdigit(c)) {
while (isdigit(c = getc(f))) {
b->thing = b->thing * 10 + c - '0';
}
} else if (isalpha(c)) {
buff = alloc_lbuf("getboolexp1.atr_name");
for (s = buff;
((c = getc(f)) != EOF) && (c != '\n') &&
(c != ':') && (c != '/');
*s++ = c) ;
if (c == EOF) {
free_lbuf(buff);
free_bool(b);
goto error;
}
*s = '\0';
/* Look the name up as an attribute.
* create a new attribute.
*/

If not found,

anum = mkattr(buff);
if (anum <= 0) {
free_bool(b);
free_lbuf(buff);
goto error;
}
free_lbuf(buff);
b->thing = anum;
} else {
free_bool(b);
goto error;
}
/* if last character is : then this is an attribute lock. A
* last character of / means an eval lock
*/

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

Saturday, June 16, 2012 11:46 PM

if ((c == ':') || (c == '/')) {


if (c == '/')
b->type = BOOLEXP_EVAL;
else
b->type = BOOLEXP_ATR;
buff = alloc_lbuf("getboolexp1.attr_lock");
for (s = buff;
((c = getc(f)) != EOF) && (c != '\n') && (c != ')') &&
(c != OR_TOKEN) && (c != AND_TOKEN);
*s++ = c) ;
if (c == EOF)
goto error;
*s++ = 0;
b->sub1 = (BOOLEXP *) XSTRDUP(buff, "getboolexp1.attr_lock");
free_lbuf(buff);
}
ungetc(c, f);
return b;

error:
fprintf(mainlog_fp,
"ABORT! db_rw.c, reached error case in getboolexp1().\n" );
abort();
/* bomb out */
return TRUE_BOOLEXP;
/* NOTREACHED */

/* --------------------------------------------------------------------------* getboolexp: Read a boolean expression from the flat file.


*/
static BOOLEXP *getboolexp(f)
FILE *f;
{
BOOLEXP *b;
char c;
b = getboolexp1(f);
if (getc(f) != '\n') {
fprintf(mainlog_fp, "ABORT! db_rw.c, parse error in getboolexp().\n" );
abort();
/* parse error, we lose */
}
if ((c = getc(f)) != '\n')
ungetc(c, f);
}

return b;

/* --------------------------------------------------------------------------* unscramble_attrnum: Fix up attribute numbers from foreign muds


*/

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

Saturday, June 16, 2012 11:46 PM

static int unscramble_attrnum(attrnum)


int attrnum;
{
switch (g_format) {
case F_MUSH:
/* TinyMUSH 2.2: Deal with different attribute numbers. */

switch (attrnum) {
case 208:
return A_NEWOBJS;
break;
case 209:
return A_LCON_FMT;
break;
case 210:
return A_LEXITS_FMT;
break;
case 211:
return A_PROGCMD;
break;
default:
return attrnum;
}
default:
return attrnum;
}

/* --------------------------------------------------------------------------* get_list: Read attribute list from flat file.


*/
static int get_list(f, i, new_strings)
FILE *f;
dbref i;
int new_strings;
{
dbref atr;
int c;
char *buff;
buff = alloc_lbuf("get_list");
while (1) {
switch (c = getc(f)) {
case '>':
/* read # then string */
if (mudstate.standalone)
atr = unscramble_attrnum(getref(f));
else
atr = getref(f);
if (atr > 0) {
/* Store the attr */
atr_add_raw(i, atr,
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

Saturday, June 16, 2012 11:46 PM

(char *)getstring_noalloc(f, new_strings));


} else {
/* Silently discard */
getstring_noalloc(f, new_strings);

}
break;
case '\n': /* ignore newlines. They're due to v(r). */
break;
case '<':
/* end of list */
free_lbuf(buff);
c = getc(f);
if (c != '\n') {
ungetc(c, f);
fprintf(mainlog_fp,
"No line feed on object %d\n" , i);
return 1;
}
return 1;
default:
fprintf(mainlog_fp,
"Bad character '%c' when getting attributes on object %d\n" ,
c, i);
/* We've found a bad spot. I hope things aren't
* too bad.
*/
}

(void)getstring_noalloc(f, new_strings);

}
return 1;

/* NOTREACHED */

/* --------------------------------------------------------------------------* putbool_subexp: Write a boolean sub-expression to the flat file.


*/
static void putbool_subexp(f, b)
FILE *f;
BOOLEXP *b;
{
ATTR *va;
switch (b->type) {
case BOOLEXP_IS:
putc('(', f);
putc(IS_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_CARRY:
putc('(', f);
putc(CARRY_TOKEN, f);
putbool_subexp(f, b->sub1);
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

Saturday, June 16, 2012 11:46 PM

putc(')', f);
break;
case BOOLEXP_INDIR:
putc('(', f);
putc(INDIR_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_OWNER:
putc('(', f);
putc(OWNER_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_AND:
putc('(', f);
putbool_subexp(f, b->sub1);
putc(AND_TOKEN, f);
putbool_subexp(f, b->sub2);
putc(')', f);
break;
case BOOLEXP_OR:
putc('(', f);
putbool_subexp(f, b->sub1);
putc(OR_TOKEN, f);
putbool_subexp(f, b->sub2);
putc(')', f);
break;
case BOOLEXP_NOT:
putc('(', f);
putc(NOT_TOKEN, f);
putbool_subexp(f, b->sub1);
putc(')', f);
break;
case BOOLEXP_CONST:
fprintf(f, "%d", b->thing);
break;
case BOOLEXP_ATR:
va = atr_num(b->thing);
if (va) {
fprintf(f, "%s:%s", va->name, (char *)b->sub1);
} else {
fprintf(f, "%d:%s\n", b->thing, (char *)b->sub1);
}
break;
case BOOLEXP_EVAL:
va = atr_num(b->thing);
if (va) {
fprintf(f, "%s/%s\n", va->name, (char *)b->sub1);
} else {
fprintf(f, "%d/%s\n", b->thing, (char *)b->sub1);
}
break;
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

Saturday, June 16, 2012 11:46 PM

default:
fprintf(mainlog_fp, "Unknown boolean type in putbool_subexp: %d\n" ,
b->type);
}

/* --------------------------------------------------------------------------* putboolexp: Write boolean expression to the flat file.


*/
void putboolexp(f, b)
FILE *f;
BOOLEXP *b;
{
if (b != TRUE_BOOLEXP) {
putbool_subexp(f, b);
}
putc('\n', f);
}
/* --------------------------------------------------------------------------* upgrade_flags: Convert foreign flags to MUSH format.
*/
static void upgrade_flags(flags1, flags2, flags3, thing, db_format, db_version)
FLAG *flags1, *flags2, *flags3;
dbref thing;
int db_format, db_version;
{
FLAG f1, f2, f3, newf1, newf2, newf3;
f1 = *flags1;
f2 = *flags2;
f3 = *flags3;
newf1 = 0;
newf2 = 0;
newf3 = 0;
if ((db_format == F_MUSH) && (db_version >= 3)) {
newf1 = f1;
newf2 = f2;
newf3 = 0;
/* Then we have to do the 2.2 to 3.0 flag conversion */
if (newf1
newf1
newf2
}
if (newf2
newf2
newf2
}
if (newf2

& ROYALTY) {
&= ~ROYALTY;
|= CONTROL_OK;
& HAS_COMMANDS) {
&= ~HAS_COMMANDS;
|= NOBLEED;
& AUDITORIUM) {
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

Saturday, June 16, 2012 11:46 PM

newf2 &= ~AUDITORIUM;


newf2 |= ZONE_PARENT;

}
if (newf2 & ANSI) {
newf2 &= ~ANSI;
newf2 |= STOP_MATCH;
}
if (newf2 & HEAD_FLAG) {
newf2 &= ~HEAD_FLAG;
newf2 |= HAS_COMMANDS;
}
if (newf2 & FIXED) {
newf2 &= ~FIXED;
newf2 |= BOUNCE;
}
if (newf2 & STAFF) {
newf2 &= STAFF;
newf2 |= HTML;
}
if (newf2 & HAS_DAILY) {
newf2 &= ~HAS_DAILY;
/* This is the unimplemented TICKLER flag. */
}
if (newf2 & GAGGED) {
newf2 &= ~GAGGED;
newf2 |= ANSI;
}
if (newf2 & WATCHER) {
newf2 &= ~WATCHER;
s_Powers(thing, Powers(thing) | POW_BUILDER);
}
} else if (db_format == F_MUX) {
/* TinyMUX to 3.0 flag conversion */
newf1 = f1;
newf2 = f2;
newf3 = f3;
if (newf2 & ZONE_PARENT) {
/* This used to be an object set NO_COMMAND. We unset the
* flag.
*/
newf2 &= ~ZONE_PARENT;
} else {
/* And if it wasn't NO_COMMAND, then it should be COMMANDS. */
newf2 |= HAS_COMMANDS;
}
if (newf2 & WATCHER) {
/* This used to be the COMPRESS flag, which didn't do
* anything.
*/
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

Saturday, June 16, 2012 11:46 PM

newf2 &= ~WATCHER;


}
if ((newf1 & MONITOR) && ((newf1 & TYPE_MASK) == TYPE_PLAYER)) {
/* Players set MONITOR should be set WATCHER as well. */
newf2 |= WATCHER;
}
} else if (db_format == F_TINYMUSH) {
/* Native TinyMUSH 3.0 database.
* The only thing we have to do is clear the redirection
* flag, as nothing is ever redirected at startup.
*/
newf1 = f1;
newf2 = f2;
newf3 = f3 & ~HAS_REDIRECT;
}
newf2 = newf2 & ~FLOATING; /* this flag is now obsolete */

*flags1 = newf1;
*flags2 = newf2;
*flags3 = newf3;
return;

/* --------------------------------------------------------------------------* efo_convert: Fix things up for Exits-From-Objects


*/
void NDECL(efo_convert)
{
int i;
dbref link;
DO_WHOLE_DB(i) {
switch (Typeof(i)) {
case TYPE_PLAYER:
case TYPE_THING:
/* swap Exits and Link */

link = Link(i);
s_Link(i, Exits(i));
s_Exits(i, link);
break;

/* --------------------------------------------------------------------------* fix_mux_zones: Convert MUX-style zones to 3.0-style zones.


*/
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

Saturday, June 16, 2012 11:46 PM

static void fix_mux_zones()


{
/* For all objects in the database where Zone(thing) != NOTHING,
* set the CONTROL_OK flag on them.
*
* For all objects in the database that are ZMOs (that have other
* objects zoned to them), copy the EnterLock of those objects to
* the ControlLock.
*/
int i;
int *zmarks;
char *astr;
zmarks = (int *) XCALLOC(mudstate.db_top, sizeof(int), "fix_mux_zones");
DO_WHOLE_DB(i) {
if (Zone(i) != NOTHING) {
s_Flags2(i, Flags2(i) | CONTROL_OK);
zmarks[Zone(i)] = 1;
}
}
DO_WHOLE_DB(i) {
if (zmarks[i]) {
astr = atr_get_raw(i, A_LENTER);
if (astr) {
atr_add_raw(i, A_LCONTROL, astr);
}
}
}
}

XFREE(zmarks, "fix_mux_zones");

/* --------------------------------------------------------------------------* fix_typed_quotas: Explode standard quotas into typed quotas


*/
static void fix_typed_quotas()
{
/* If we have a pre-2.2 or MUX database, only the QUOTA and RQUOTA
* attributes exist. For simplicity's sake, we assume that players
* will have the same quotas for all types, equal to the current
* value. This is going to produce incorrect values for RQUOTA;
* this is easily fixed by a @quota/fix done from within-game.
*
* If we have a early beta 2.2 release, we have quotas which are
* spread out over ten attributes. We're going to have to grab
* those, make the new quotas, and then delete the old attributes.
*/

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687

Saturday, June 16, 2012 11:46 PM

int i;
char *qbuf, *rqbuf;

DO_WHOLE_DB(i) {
if (isPlayer(i)) {
qbuf = atr_get_raw(i, A_QUOTA);
rqbuf = atr_get_raw(i, A_RQUOTA);
if (!qbuf || !*qbuf)
qbuf = (char *)"1";
if (!rqbuf || !*rqbuf)
rqbuf = (char *)"0";
atr_add_raw(i, A_QUOTA,
tprintf("%s %s %s %s %s",
qbuf, qbuf, qbuf, qbuf, qbuf));
atr_add_raw(i, A_RQUOTA,
tprintf("%s %s %s %s %s",
rqbuf, rqbuf, rqbuf, rqbuf, rqbuf));
}
}

dbref db_read_flatfile(f, db_format, db_version, db_flags)


FILE *f;
int *db_format, *db_version, *db_flags;
{
dbref i, anum;
char ch;
const char *tstr;
int header_gotten, size_gotten, nextattr_gotten;
int read_attribs, read_name, read_zone, read_link, read_key, read_parent;
int read_extflags, read_3flags, read_money, read_timestamps, read_new_strings;
int read_powers, read_powers_player, read_powers_any;
int has_typed_quotas, has_visual_attrs;
int deduce_version, deduce_name, deduce_zone, deduce_timestamps;
int aflags, f1, f2, f3;
BOOLEXP *tempbool;
time_t tmptime;
#ifndef NO_TIMECHECKING
struct timeval obj_time;
#endif
header_gotten = 0;
size_gotten = 0;
nextattr_gotten = 0;
g_format = F_UNKNOWN;
g_version = 0;
g_flags = 0;
read_attribs = 1;
read_name = 1;
read_zone = 0;
read_link = 0;
read_key = 1;
read_parent = 0;
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

Saturday, June 16, 2012 11:46 PM

read_money = 1;
read_extflags = 0;
read_3flags = 0;
has_typed_quotas = 0;
has_visual_attrs = 0;
read_timestamps = 0;
read_new_strings = 0;
read_powers = 0;
read_powers_player = 0;
read_powers_any = 0;
deduce_version = 1;
deduce_zone = 1;
deduce_name = 1;
deduce_timestamps = 1;
fprintf(mainlog_fp, "Reading ");
db_free();
for (i = 0;; i++) {
if (!(i % 100)) {
fputc('.', mainlog_fp);
}
switch (ch = getc(f)) {
case '-':
/* Misc tag */
switch (ch = getc(f)) {
case 'R':
/* Record number of players */
mudstate.record_players = getref(f);
break;
default:
(void)getstring_noalloc(f, 0);
}
break;
case '+':
/* MUX and MUSH header */
ch = getc(f); /* 2nd char selects type */
if ((ch == 'V') || (ch == 'X') || (ch == 'T')) {
/* The following things are common across 2.x, MUX,
* and 3.0.
*/
if (header_gotten) {
fprintf(mainlog_fp,
"\nDuplicate MUSH version header entry at object %d, ignored.\n" ,
i);
tstr = getstring_noalloc(f, 0);
break;
}
header_gotten = 1;
deduce_version = 0;
g_version = getref(f);

-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

Saturday, June 16, 2012 11:46 PM

/* Otherwise extract feature flags */


if (g_version & V_GDBM) {
read_attribs = 0;
read_name = !(g_version & V_ATRNAME);
}
read_zone = (g_version & V_ZONE);
read_link = (g_version & V_LINK);
read_key = !(g_version & V_ATRKEY);
read_parent = (g_version & V_PARENT);
read_money = !(g_version & V_ATRMONEY);
read_extflags = (g_version & V_XFLAGS);
has_typed_quotas = (g_version & V_TQUOTAS);
read_timestamps = (g_version & V_TIMESTAMPS);
has_visual_attrs = (g_version & V_VISUALATTRS);
g_flags = g_version & ~V_MASK;

deduce_name = 0;
deduce_version = 0;
deduce_zone = 0;

/* More generic switch. */


switch (ch) {
case 'T':
/* 3.0 VERSION */
g_format = F_TINYMUSH;
read_3flags = (g_version & V_3FLAGS);
read_powers = (g_version & V_POWERS);
read_new_strings = (g_version & V_QUOTED);
g_version &= V_MASK;
break;
case 'V':
/* 2.0 VERSION */
g_format = F_MUSH;
g_version &= V_MASK;
break;
case 'X':
/* MUX VERSION */
g_format = F_MUX;
read_3flags = (g_version & V_3FLAGS);
read_powers = (g_version & V_POWERS);
read_new_strings = (g_version & V_QUOTED);
g_version &= V_MASK;
break;
case 'S':
/* SIZE */
if (size_gotten) {
fprintf(mainlog_fp,
"\nDuplicate size entry at object %d, ignored.\n" ,
i);
tstr = getstring_noalloc(f, 0);
} else {
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

Saturday, June 16, 2012 11:46 PM

mudstate.min_size = getref(f);
}
size_gotten = 1;
break;
case 'A':
/* USER-NAMED ATTRIBUTE */
anum = getref(f);
tstr = getstring_noalloc(f, read_new_strings);
if (isdigit(*tstr)) {
aflags = 0;
while (isdigit(*tstr))
aflags = (aflags * 10) +
(*tstr++ - '0');
tstr++;
/* skip ':' */
if (!has_visual_attrs) {
/* If not AF_ODARK, is AF_VISUAL.
* Strip AF_ODARK.
*/
if (aflags & AF_ODARK)
aflags &= ~AF_ODARK;
else
aflags |= AF_VISUAL;
}
} else {
aflags = mudconf.vattr_flags;
}
vattr_define((char *)tstr, anum, aflags);
break;
case 'F':
/* OPEN USER ATTRIBUTE SLOT */
anum = getref(f);
break;
case 'N':
/* NEXT ATTR TO ALLOC WHEN NO
* FREELIST
*/
if (nextattr_gotten) {
fprintf(mainlog_fp,
"\nDuplicate next free vattr entry at object %d, ignored.\n" ,
i);
tstr = getstring_noalloc(f, 0);
} else {
mudstate.attr_next = getref(f);
nextattr_gotten = 1;
}
break;
default:
fprintf(mainlog_fp,
"\nUnexpected character '%c' in MUSH header near object #%d,
ignored.\n",
ch, i);
tstr = getstring_noalloc(f, 0);
}
break;
case '!':
/* MUX entry/MUSH entry */
if (deduce_version) {
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898

Saturday, June 16, 2012 11:46 PM

g_format = F_TINYMUSH;
g_version = 1;
deduce_name = 0;
deduce_zone = 0;
deduce_version = 0;
} else if (deduce_zone) {
deduce_zone = 0;
read_zone = 0;
}
i = getref(f);
db_grow(i + 1);
#ifndef NO_TIMECHECKING
obj_time.tv_sec = obj_time.tv_usec = 0;
s_Time_Used(i, obj_time);
#endif
s_StackCount(i, 0);
s_VarsCount(i, 0);
s_StructCount(i, 0);
s_InstanceCount(i, 0);
if (read_name) {
tstr = getstring_noalloc(f, read_new_strings);
if (deduce_name) {
if (isdigit(*tstr)) {
read_name = 0;
s_Location(i, atoi(tstr));
} else {
s_Name(i, (char *)tstr);
s_Location(i, getref(f));
}
deduce_name = 0;
} else {
s_Name(i, (char *)tstr);
s_Location(i, getref(f));
}
} else {
s_Location(i, getref(f));
}
if (read_zone)
s_Zone(i, getref(f));
/* else s_Zone(i, NOTHING); */
/* CONTENTS and EXITS */
s_Contents(i, getref(f));
s_Exits(i, getref(f));
/* LINK */
if (read_link) {
s_Link(i, getref(f));
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951

Saturday, June 16, 2012 11:46 PM

} else {
s_Link(i, NOTHING);
}
/* NEXT */
s_Next(i, getref(f));
/* LOCK */
if (read_key) {
tempbool = getboolexp(f);
atr_add_raw(i, A_LOCK,
unparse_boolexp_quiet(1, tempbool));
free_boolexp(tempbool);
}
/* OWNER */
s_Owner(i, getref(f));
/* PARENT */
if (read_parent) {
s_Parent(i, getref(f));
} else {
s_Parent(i, NOTHING);
}
/* PENNIES */
if (read_money)
s_Pennies(i, getref(f));
/* FLAGS */
f1 = getref(f);
if (read_extflags)
f2 = getref(f);
else
f2 = 0;
if (read_3flags)
f3 = getref(f);
else
f3 = 0;
upgrade_flags(&f1, &f2, &f3, i, g_format, g_version);
s_Flags(i, f1);
s_Flags2(i, f2);
s_Flags3(i, f3);
if (read_powers) {
f1 = getref(f);
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004

Saturday, June 16, 2012 11:46 PM

f2 = getref(f);
s_Powers(i, f1);
s_Powers2(i, f2);

if (read_timestamps) {
tmptime = (time_t) getlong(f);
s_AccessTime(i, tmptime);
tmptime = (time_t) getlong(f);
s_ModTime(i, tmptime);
} else {
AccessTime(i) = ModTime(i) = time(NULL);
}
/* ATTRIBUTES */
if (read_attribs) {
if (!get_list(f, i, read_new_strings)) {
fprintf(mainlog_fp,
"\nError reading attrs for object #%d\n" ,
i);
return -1;
}
}
/* check to see if it's a player */
if (Typeof(i) == TYPE_PLAYER) {
c_Connected(i);
}
break;
case '*':
/* EOF marker */
tstr = getstring_noalloc(f, 0);
if (strcmp(tstr, "**END OF DUMP***")) {
fprintf(mainlog_fp,
"\nBad EOF marker at object #%d\n" ,
i);
return -1;
} else {
fprintf(mainlog_fp, "\n");
*db_version = g_version;
*db_format = g_format;
*db_flags = g_flags;
if (!has_typed_quotas)
fix_typed_quotas();
if (g_format == F_MUX)
fix_mux_zones();
return mudstate.db_top;
}
default:
fprintf(mainlog_fp, "\nIllegal character '%c' near object #%d\n" ,
ch, i);
return -1;
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

Saturday, June 16, 2012 11:46 PM

int db_read()
{
DBData key, data;
int *c, vattr_flags, i, j, blksize, num;
char *s;
#ifndef NO_TIMECHECKING
struct timeval obj_time;
#endif
/* Fetch the database info */
key.dptr = "TM3";
key.dsize = strlen("TM3") + 1;
data = db_get(key, DBTYPE_DBINFO);
if (!data.dptr) {
fprintf(mainlog_fp, "\nCould not open main record" );
return -1;
}
/* Unroll the data returned */
c = data.dptr;
memcpy((void *)&mudstate.min_size, (void *)c, sizeof(int));
c++;
memcpy((void *)&mudstate.attr_next, (void *)c, sizeof(int));
c++;
memcpy((void *)&mudstate.record_players, (void *)c, sizeof(int));
c++;
memcpy((void *)&mudstate.moduletype_top, (void *)c, sizeof(int));
RAW_FREE(data.dptr, "db_get");
/* Load the attribute numbers */
blksize = ATRNUM_BLOCK_SIZE;
for (i = 0; i <= ENTRY_NUM_BLOCKS(mudstate.attr_next, blksize); i++) {
key.dptr = &i;
key.dsize = sizeof(int);
data = db_get(key, DBTYPE_ATRNUM);
if (data.dptr) {
/* Unroll the data into flags and name */
s = data.dptr;

-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110

Saturday, June 16, 2012 11:46 PM

while ((s - (char *)data.dptr) < data.dsize) {


memcpy((void *)&j, (void *)s, sizeof(int));
s += sizeof(int);
memcpy((void *)&vattr_flags, (void *)s, sizeof(int));
s += sizeof(int);
vattr_define(s, j, vattr_flags);
s = strchr((const char *)s, '\0');
if (!s) {
/* Houston, we have a problem */
fprintf(mainlog_fp,
"\nError reading attribute number %d\n" ,
j + ENTRY_BLOCK_STARTS(i, blksize));
}

s++;
}
RAW_FREE(data.dptr, "db_get");

}
/* Load the object structures */
if (mudstate.standalone)
fprintf(mainlog_fp, "Reading ");
blksize = OBJECT_BLOCK_SIZE;
for (i = 0; i <= ENTRY_NUM_BLOCKS(mudstate.min_size, blksize); i++) {
key.dptr = &i;
key.dsize = sizeof(int);
data = db_get(key, DBTYPE_OBJECT);
if (data.dptr) {
/* Unroll the data into objnum and object */
s = data.dptr;
while ((s - (char *)data.dptr) < data.dsize) {
memcpy((void *)&num, (void *)s, sizeof(int));
s += sizeof(int);
db_grow(num + 1);
if (mudstate.standalone && !(num % 100)) {
fputc('.', mainlog_fp);
}
/* We read the entire object structure in
* and copy it into place */
memcpy((void *)&(db[num]), (void *)s, sizeof(DUMPOBJ));
s += sizeof(DUMPOBJ);
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

Saturday, June 16, 2012 11:46 PM

#ifndef NO_TIMECHECKING
obj_time.tv_sec = obj_time.tv_usec = 0;
s_Time_Used(num, obj_time);
#endif
s_StackCount(num, 0);
s_VarsCount(num, 0);
s_StructCount(num, 0);
s_InstanceCount(num, 0);
#ifdef MEMORY_BASED
db[num].attrtext.at_count = 0;
db[num].attrtext.atrs = NULL;
#endif
/* Check to see if it's a player */
if (Typeof(num) == TYPE_PLAYER) {
c_Connected(num);
}
}

s_Clean(num);

RAW_FREE(data.dptr, "db_get");

if (!mudstate.standalone)
load_player_names();
if (mudstate.standalone)
fprintf(mainlog_fp, "\n");
}

return (0);

static int db_write_object_out(f, i, db_format, flags, n_atrt)


FILE *f;
dbref i;
int db_format, flags;
int *n_atrt;
{
ATTR *a;
char *got, *as;
dbref aowner;
int ca, aflags, alen, save, j, changed;
BOOLEXP *tempbool;
if (Going(i)) {
return (0);
}
fprintf(f, "!%d\n", i);
if (!(flags & V_ATRNAME))
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

Saturday, June 16, 2012 11:46 PM

putstring(f, Name(i));
putref(f, Location(i));
if (flags & V_ZONE)
putref(f, Zone(i));
putref(f, Contents(i));
putref(f, Exits(i));
if (flags & V_LINK)
putref(f, Link(i));
putref(f, Next(i));
if (!(flags & V_ATRKEY)) {
got = atr_get(i, A_LOCK, &aowner, &aflags, &alen);
tempbool = parse_boolexp(GOD, got, 1);
free_lbuf(got);
putboolexp(f, tempbool);
if (tempbool)
free_boolexp(tempbool);
}
putref(f, Owner(i));
if (flags & V_PARENT)
putref(f, Parent(i));
if (!(flags & V_ATRMONEY))
putref(f, Pennies(i));
putref(f, Flags(i));
if (flags & V_XFLAGS)
putref(f, Flags2(i));
if (flags & V_3FLAGS)
putref(f, Flags3(i));
if (flags & V_POWERS) {
putref(f, Powers(i));
putref(f, Powers2(i));
}
if (flags & V_TIMESTAMPS) {
putlong(f, AccessTime(i));
putlong(f, ModTime(i));
}
/* write the attribute list */
changed = 0;
for (ca = atr_head(i, &as); ca; ca = atr_next(&as)) {
save = 0;
if (!mudstate.standalone) {
a = atr_num(ca);
if (a)
j = a->number;
else
j = -1;
} else {
j = ca;
}
if (j > 0) {
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269

Saturday, June 16, 2012 11:46 PM

switch (j) {
case A_NAME:
if (flags & V_ATRNAME)
save = 1;
break;
case A_LOCK:
if (flags & V_ATRKEY)
save = 1;
break;
case A_LIST:
case A_MONEY:
break;
default:
save = 1;
}

}
if (save) {
got = atr_get_raw(i, j);
if (used_attrs_table != NULL) {
fprintf(f, ">%d\n", used_attrs_table[j]);
if (used_attrs_table[j] != j) {
changed = 1;
*n_atrt += 1;
}
} else {
fprintf(f, ">%d\n", j);
}
putstring(f, got);
}

}
fprintf(f, "<\n");
return (changed);

dbref db_write_flatfile(f, format, version)


FILE *f;
int format, version;
{
dbref i;
int flags;
VATTR *vp;
int n, end, ca, n_oldtotal, n_oldtop, n_deleted, n_renumbered;
int n_objt, n_atrt, anxt, dbclean;
int *old_attrs_table;
char *as;
al_store();
dbclean = (version & V_DBCLEAN) ? 1 : 0;
version &= ~V_DBCLEAN;
switch (format) {
case F_TINYMUSH:
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322

Saturday, June 16, 2012 11:46 PM

flags = version;
break;
default:
fprintf(mainlog_fp, "Can only write TinyMUSH 3 format.\n" );
return -1;
}
if (mudstate.standalone)
fprintf(mainlog_fp, "Writing ");
/* Attribute cleaning, if standalone. */
if (mudstate.standalone && dbclean) {
used_attrs_table = (int *) XCALLOC(mudstate.attr_next,
sizeof(int),
"flatfile.used_attrs_table");
old_attrs_table = (int *) XCALLOC(mudstate.attr_next,
sizeof(int),
"flatfile.old_attrs_table");
n_oldtotal = mudstate.attr_next;
n_oldtop = anum_alc_top;
n_deleted = n_renumbered = n_objt = n_atrt = 0;
/* Non-user defined attributes are always considered used. */
for (n = 0; n < A_USER_START; n++)
used_attrs_table[n] = n;
/* Walk the database. Mark all the attribute numbers in use. */
atr_push();
DO_WHOLE_DB(i) {
for (ca = atr_head(i, &as); ca; ca = atr_next(&as))
used_attrs_table[ca] = old_attrs_table[ca] = ca;
}
atr_pop();
/* Count up how many attributes we're deleting. */
vp = vattr_first();
while (vp) {
if (used_attrs_table[vp->number] == 0)
n_deleted++;
vp = vattr_next(vp);
}
/* Walk the table we've created of used statuses. When we
* find free slots, walk backwards to the first used slot
* at the end of the table. Write the number of the free
* slot into that used slot.
* Keep a mapping of what things used to be.
*/

-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375

Saturday, June 16, 2012 11:46 PM

for (n = A_USER_START, end = mudstate.attr_next - 1;


(n < mudstate.attr_next) && (n < end); n++) {
if (used_attrs_table[n] == 0) {
while ((end > n) && (used_attrs_table[end] == 0))
end--;
if (end > n) {
old_attrs_table[n] = end;
used_attrs_table[end] = used_attrs_table[n] = n;
end--;
}
}
}
/* Count up our renumbers. */
for (n = A_USER_START; n < mudstate.attr_next; n++) {
if ((used_attrs_table[n] != n) && (used_attrs_table[n] != 0)) {
vp = (VATTR *) anum_get(n);
if (vp)
n_renumbered++;
}
}
/* The new end of the attribute table is the first thing
* we've renumbered.
*/
for (anxt = A_USER_START;
((anxt == used_attrs_table[anxt]) &&
(anxt < mudstate.attr_next));
anxt++)
;
} else {
used_attrs_table = NULL;
anxt = mudstate.attr_next;
}
/* Write database information.
* TinyMUSH 2 wrote '+V', MUX wrote '+X', 3.0 writes '+T'.
*/
fprintf(f, "+T%d\n+S%d\n+N%d\n", flags, mudstate.db_top, anxt);
fprintf(f, "-R%d\n", mudstate.record_players);
/* Dump user-named attribute info */
if (mudstate.standalone && dbclean) {
for (i = A_USER_START; i < anxt; i++) {
if (used_attrs_table[i] == 0)
continue;
vp = (VATTR *) anum_get(old_attrs_table[i]);
if (vp) {
if (!(vp->flags & AF_DELETED)) {
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412

fprintf(f, "+A%d\n\"%d:%s\"\n",
i, vp->flags, vp->name);
}

}
}
} else {
vp = vattr_first();
while (vp != NULL) {
if (!(vp->flags & AF_DELETED)) {
fprintf(f, "+A%d\n\"%d:%s\"\n",
vp->number, vp->flags, vp->name);
}
vp = vattr_next(vp);
}
}
/* Dump object and attribute info */
n_objt = n_atrt = 0;
DO_WHOLE_DB(i) {
if (mudstate.standalone && !(i % 100)) {
fputc('.', mainlog_fp);
}
}

n_objt += db_write_object_out(f, i, format, flags, &n_atrt);

fputs("***END OF DUMP***\n", f);


fflush(f);
if (mudstate.standalone) {
fprintf(mainlog_fp, "\n");
if (dbclean) {
if (n_objt) {
fprintf(mainlog_fp, "Cleaned %d attributes (now %d): %d deleted, %d
renumbered (%d objects and %d individual attrs touched).\n" ,
n_oldtotal, anxt, n_deleted, n_renumbered,
n_objt, n_atrt);
} else if (n_deleted || n_renumbered) {
fprintf(mainlog_fp, "Cleaned %d attributes (now %d): %d deleted, %d
renumbered (no objects touched).\n" ,
n_oldtotal, anxt, n_deleted, n_renumbered);
}
XFREE(used_attrs_table, "flatfile.used_attrs_table");
XFREE(old_attrs_table, "flatfile.old_attrs_table");
}
}

1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426

Saturday, June 16, 2012 11:46 PM

return (mudstate.db_top);

-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479

Saturday, June 16, 2012 11:46 PM

dbref db_write()
{
VATTR *vp;
DBData key, data;
int *c, blksize, num, i, j, k, dirty, len;
char *s;
al_store();
if (mudstate.standalone)
fprintf(mainlog_fp, "Writing ");
/* Lock the database */
db_lock();
/* Write database information */
i = mudstate.attr_next;
/* Roll up various paramaters needed for startup into one record.
* This should be the only data record of its type */
c = data.dptr = (int *)XMALLOC(4 * sizeof(int), "db_write");
memcpy((void *)c, (void *)&mudstate.db_top, sizeof(int));
c++;
memcpy((void *)c, (void *)&i, sizeof(int));
c++;
memcpy((void *)c, (void *)&mudstate.record_players, sizeof(int));
c++;
memcpy((void *)c, (void *)&mudstate.moduletype_top, sizeof(int));
/* "TM3" is our unique key */
key.dptr = "TM3";
key.dsize = strlen("TM3") + 1;
data.dsize = 4 * sizeof(int);
db_put(key, data, DBTYPE_DBINFO);
XFREE(data.dptr, "db_write");
/* Dump user-named attribute info */
/*
*
*
*

First, calculate the number of attribute entries we can fit in


a block, allowing for some minor DBM key overhead. This should
not change unless the size of VNAME_SIZE or LBUF_SIZE changes,
in which case you'd have to reload anyway */

blksize = ATRNUM_BLOCK_SIZE;
/* Step through the attribute number array, writing stuff in 'num'
* sized chunks */
data.dptr = (char *)XMALLOC(ATRNUM_BLOCK_BYTES, "db_write.cdata");
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532

Saturday, June 16, 2012 11:46 PM

for (i = 0; i <= ENTRY_NUM_BLOCKS(mudstate.attr_next, blksize); i++) {


dirty = 0;
num = 0;
s = data.dptr;
for (j = ENTRY_BLOCK_STARTS(i, blksize);
(j <= ENTRY_BLOCK_ENDS(i, blksize)) &&
(j < mudstate.attr_next);
j++) {
if (j < A_USER_START) {
continue;
}
vp = (VATTR *)anum_table[j];
if (vp && !(vp->flags & AF_DELETED)) {
if (!mudstate.standalone) {
if (vp->flags & AF_DIRTY) {
/* Only write the dirty
* attribute numbers and
* clear the flag */
vp->flags &= ~AF_DIRTY;
dirty = 1;

}
} else {
dirty = 1;
}

num++;

if (!num) {
/* No valid attributes in this block, delete it */
key.dptr = &i;
key.dsize = sizeof(int);
db_del(key, DBTYPE_ATRNUM);
}
if (dirty) {
/* Something is dirty in this block, write all of
* the attribute numbers in this block */
for (j = 0; (j < blksize) &&
((ENTRY_BLOCK_STARTS(i, blksize) + j) < mudstate.attr_next);
j++) {
/* j is an offset of attribute
* numbers into the current block */
if ((ENTRY_BLOCK_STARTS(i, blksize) + j) < A_USER_START) {
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585

Saturday, June 16, 2012 11:46 PM

continue;

vp = (VATTR *)anum_table[ENTRY_BLOCK_STARTS(i, blksize) + j];

if (vp && !(vp->flags & AF_DELETED)) {


len = strlen(vp->name) + 1;
memcpy((void *)s, (void *)&vp->number, sizeof(int));
s += sizeof(int);
memcpy((void *)s, (void *)&vp->flags, sizeof(int));
s += sizeof(int);
memcpy((void *)s, (void *)vp->name, len);
s += len;
}

/* Write the block: Block number is our key */


key.dptr = &i;
key.dsize = sizeof(int);
data.dsize = s - (char *)data.dptr;
db_put(key, data, DBTYPE_ATRNUM);

}
}
XFREE(data.dptr, "db_write.cdata");

/* Dump object structures using the same block-based method we use


* to dump attribute numbers */
blksize = OBJECT_BLOCK_SIZE;
/* Step through the object structure array, writing stuff in 'num'
* sized chunks */
data.dptr = (char *)XMALLOC(OBJECT_BLOCK_BYTES, "db_write.cdata");
for (i = 0; i <= ENTRY_NUM_BLOCKS(mudstate.db_top, blksize); i++) {
dirty = 0;
num = 0;
s = data.dptr;
for (j = ENTRY_BLOCK_STARTS(i, blksize);
(j <= ENTRY_BLOCK_ENDS(i, blksize)) &&
(j < mudstate.db_top);
j++) {
if (mudstate.standalone && !(j % 100)) {
fputc('.', mainlog_fp);
}
/* We assume you always do a dbck before dump, and
* Going objects are really destroyed! */

-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638

Saturday, June 16, 2012 11:46 PM

if (!Going(j)) {
if (!mudstate.standalone) {
if (Flags3(j) & DIRTY) {
/* Only write the dirty
* objects and clear the
* flag */
s_Clean(j);
dirty = 1;

}
} else {
dirty = 1;
}
num++;

if (!num) {
/* No valid objects in this block, delete it */

key.dptr = &i;
key.dsize = sizeof(int);
db_del(key, DBTYPE_OBJECT);

if (dirty) {
/* Something is dirty in this block, write all of the
* objects in this block */
for (j = 0; (j < blksize) &&
((ENTRY_BLOCK_STARTS(i, blksize) + j) < mudstate.db_top);
j++) {
/* j is an offset of object numbers into the
* current block */
k = ENTRY_BLOCK_STARTS(i, blksize) + j;

if (!Going(k)) {
memcpy((void *)s, (void *)&k, sizeof(int));
s += sizeof(int);
memcpy((void *)s, (void *)&(db[k]), sizeof(DUMPOBJ));
s += sizeof(DUMPOBJ);
}

/* Write the block: Block number is our key */

key.dptr = &i;
key.dsize = sizeof(int);
data.dsize = s - (char *)data.dptr;
db_put(key, data, DBTYPE_OBJECT);

-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_rw.c

1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681

Saturday, June 16, 2012 11:46 PM

XFREE(data.dptr, "db_write.cdata");
/* Unlock the database */
db_unlock();

if (mudstate.standalone)
fprintf(mainlog_fp, "\n");
return (mudstate.db_top);

/* Open a file pointer for a module to use when writing a flatfile */


FILE *db_module_flatfile(modname, wrflag)
char *modname;
int wrflag;
{
char filename[256];
FILE *f = NULL;
sprintf(filename, "%s/mod_%s.db", mudconf.dbhome, modname);
if (wrflag) {
f = tf_fopen(filename, O_WRONLY | O_CREAT | O_TRUNC);
STARTLOG(LOG_ALWAYS, "DMP", "DUMP")
log_printf("Writing db: %s", filename);
ENDLOG
} else {
f = tf_fopen(filename, O_RDONLY);
STARTLOG(LOG_ALWAYS, "INI", "LOAD")
log_printf("Loading db: %s", filename);
ENDLOG
}

if (f != NULL) {
return f;
} else {
log_perror("DMP", "FAIL", "Opening flatfile", filename);
return NULL;
}

-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\db_sql.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

Saturday, June 16, 2012 11:10 PM

/* db_sql.h */
/* $Id: db_sql.h,v 1.7 2003/02/24 18:05:22 rmg Exp $ */
#include "copyright.h"
#ifndef __DB_SQL_H
#define __DB_SQL_H
/*
* If we are already connected to the database, do nothing.
* Otherwise, attempt to connect: return a socket fd if successful,
* return -1 if failed, stamp a message to the logfile.
* Select a database. On failure, write to the logfile, close the socket,
* and return -1.
* Save the database socket fd as mudstate.sql_socket (which is initialized
* to -1 at start time).
*
*/
int NDECL(sql_init);
/*
* Send a query string to the database and obtain a result string (we
* pass an lbuf and a pointer to the appropriate place in it),
* with the rows separated by a delimiter and the fields separated
* by another delimiter. If we encounter an error, set the result
* string to #-1.
* If buff is NULL, we are in interactive mode and we simply notify
* the player of results, rather than writing into the result string.
* On success, return 0. On failure, return -1.
*/
int FDECL(sql_query, (dbref, char *, char *, char **,
const Delim *, const Delim *));
/*
* Shut down the database connection.
*/
void NDECL(sql_shutdown);
#endif /* __DB_SQL_H */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:45 PM

/* eval.c - command evaluation and cracking */


/* $Id: eval.c,v 1.80 2008/04/27 14:52:45 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"powers.h" /* required by code */


"attrs.h" /* required by code */
"functions.h" /* required by code */
"ansi.h"
/* required by code */

extern char qidx_chartab[256];

/* from funvars.c */

/* --------------------------------------------------------------------------* parse_to: Split a line at a character, obeying nesting. The line is


* destructively modified (a null is inserted where the delimiter was found)
* dstr is modified to point to the char after the delimiter, and the function
* return value points to the found string (space compressed if specified).
* If we ran off the end of the string without finding the delimiter, dstr is
* returned as NULL.
*/
static char *parse_to_cleanup(eval, first, cstr, rstr, zstr)
int eval, first;
char *cstr, *rstr, *zstr;
{
if ((mudconf.space_compress || (eval & EV_STRIP_TS)) &&
!(eval & EV_NO_COMPRESS) && !first && (cstr[-1] == ' '))
zstr--;
if ((eval & EV_STRIP_AROUND) && (*rstr == '{') && (zstr[-1] == '}')) {
rstr++;
if ((mudconf.space_compress && !(eval & EV_NO_COMPRESS)) ||
(eval & EV_STRIP_LS))
while (*rstr && isspace(*rstr))
rstr++;
rstr[-1] = '\0';
zstr--;
if ((mudconf.space_compress && !(eval & EV_NO_COMPRESS)) ||
(eval & EV_STRIP_TS))
while (zstr[-1] && isspace(zstr[-1]))
zstr--;
*zstr = '\0';
}
*zstr = '\0';
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:45 PM

return rstr;

/* We can't change this to just '*zstr++ = *cstr++', because of the inherent


problems with copying a memory location to itself. */
#define NEXTCHAR \
if (cstr == zstr) { \
cstr++; \
zstr++; \
} else \
*zstr++ = *cstr++
char *parse_to(dstr, delim, eval)
char **dstr, delim;
int eval;
{
#define stacklim 32
char stack[stacklim];
char *rstr, *cstr, *zstr;
int sp, tp, first, bracketlev;
if ((dstr == NULL) || (*dstr == NULL))
return NULL;
if (**dstr == '\0') {
rstr = *dstr;
*dstr = NULL;
return rstr;
}
sp = 0;
first = 1;
rstr = *dstr;
if ((mudconf.space_compress || (eval & EV_STRIP_LS)) &&
!(eval & EV_NO_COMPRESS)) {
while (*rstr && isspace(*rstr))
rstr++;
*dstr = rstr;
}
zstr = cstr = rstr;
while (*cstr) {
switch (*cstr) {
case '\\': /* general escape */
case '%':
/* also escapes chars */
if ((*cstr == '\\') && (eval & EV_STRIP_ESC)) {
cstr++;
} else {
NEXTCHAR;
}
if (*cstr) {
NEXTCHAR;
}
first = 0;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:45 PM

break;
case ']':
case ')':
for (tp = sp - 1; (tp >= 0) && (stack[tp] != *cstr); tp--) ;
/* If we hit something on the stack, unwind to it
* Otherwise (it's not on stack), if it's our
* delim we are done, and we convert the
* delim to a null and return a ptr to the
* char after the null. If it's not our
* delimiter, skip over it normally
*/
if (tp >= 0)
sp = tp;
else if (*cstr == delim) {
rstr = parse_to_cleanup(eval, first,
cstr, rstr, zstr);
*dstr = ++cstr;
return rstr;
}
first = 0;
NEXTCHAR;
break;
case '{':
bracketlev = 1;
if (eval & EV_STRIP) {
cstr++;
} else {
NEXTCHAR;
}
while (*cstr && (bracketlev > 0)) {
switch (*cstr) {
case '\\':
case '%':
if (cstr[1]) {
if ((*cstr == '\\') &&
(eval & EV_STRIP_ESC))
cstr++;
else
NEXTCHAR;
}
break;
case '{':
bracketlev++;
break;
case '}':
bracketlev--;
break;
}
if (bracketlev > 0) {
NEXTCHAR;
}
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:45 PM

}
if ((eval & EV_STRIP) && (bracketlev == 0)) {
cstr++;
} else if (bracketlev == 0) {
NEXTCHAR;
}
first = 0;
break;
default:
if ((*cstr == delim) && (sp == 0)) {
rstr = parse_to_cleanup(eval, first,
cstr, rstr, zstr);
*dstr = ++cstr;
return rstr;
}
switch (*cstr) {
case ' ':
/* space */
if (mudconf.space_compress &&
!(eval & EV_NO_COMPRESS)) {
if (first)
rstr++;
else if (cstr[-1] == ' ')
zstr--;
}
NEXTCHAR;
break;
case '[':
if (sp < stacklim)
stack[sp++] = ']';
NEXTCHAR;
first = 0;
break;
case '(':
if (sp < stacklim)
stack[sp++] = ')';
NEXTCHAR;
first = 0;
break;
case ESC_CHAR:
NEXTCHAR;
if (*cstr == ANSI_CSI) {
do {
NEXTCHAR;
} while ((*cstr & 0xf0) == 0x30);
}
while ((*cstr & 0xf0) == 0x20) {
NEXTCHAR;
}
if (*cstr) {
NEXTCHAR;
}
first = 0;
break;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:45 PM

default:
first = 0;
NEXTCHAR;
break;
}

}
}
rstr = parse_to_cleanup(eval, first, cstr, rstr, zstr);
*dstr = NULL;
return rstr;

/* --------------------------------------------------------------------------* parse_arglist: Parse a line into an argument list contained in lbufs.


* A pointer is returned to whatever follows the final delimiter.
* If the arglist is unterminated, a NULL is returned. The original arglist
* is destructively modified.
*/
char *parse_arglist(player, caller, cause, dstr, delim, eval,
fargs, nfargs, cargs, ncargs)
dbref player, caller, cause, eval, nfargs, ncargs;
char *dstr, delim, *fargs[], *cargs[];
{
char *rstr, *tstr, *bp, *str;
int arg, peval;
for (arg = 0; arg < nfargs; arg++)
fargs[arg] = NULL;
if (dstr == NULL)
return NULL;
rstr = parse_to(&dstr, delim, 0);
arg = 0;
peval = (eval & ~EV_EVAL);
while ((arg < nfargs) && rstr) {
if (arg < (nfargs - 1))
tstr = parse_to(&rstr, ',', peval);
else
tstr = parse_to(&rstr, '\0', peval);
if (eval & EV_EVAL) {
bp = fargs[arg] = alloc_lbuf("parse_arglist");
str = tstr;
exec(fargs[arg], &bp, player, caller, cause,
eval | EV_FCHECK, &str, cargs, ncargs);
} else {
fargs[arg] = alloc_lbuf("parse_arglist");
strcpy(fargs[arg], tstr);
}
arg++;
}
return dstr;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:45 PM

}
/* --------------------------------------------------------------------------* exec: Process a command line, evaluating function calls and %-substitutions.
*/
int get_gender(player)
dbref player;
{
char first, *atr_gotten;
dbref aowner;
int aflags, alen;

atr_gotten = atr_pget(player, A_SEX, &aowner, &aflags, &alen);


first = *atr_gotten;
free_lbuf(atr_gotten);
switch (first) {
case 'P':
case 'p':
return 4;
case 'M':
case 'm':
return 3;
case 'F':
case 'f':
case 'W':
case 'w':
return 2;
default:
return 1;
}

/* --------------------------------------------------------------------------* Trace cache routines.


*/
typedef struct tcache_ent TCENT;
struct tcache_ent {
char *orig;
char *result;
struct tcache_ent *next;
} *tcache_head;
int tcache_top, tcache_count;
void NDECL(tcache_init)
{
tcache_head = NULL;
tcache_top = 1;
tcache_count = 0;
}
int NDECL(tcache_empty)
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:45 PM

if (tcache_top) {
tcache_top = 0;
tcache_count = 0;
return 1;
}
return 0;

static void tcache_add(orig, result)


char *orig, *result;
{
char *tp;
TCENT *xp;

if (strcmp(orig, result)) {
tcache_count++;
if (tcache_count <= mudconf.trace_limit) {
xp = (TCENT *) alloc_sbuf("tcache_add.sbuf");
tp = alloc_lbuf("tcache_add.lbuf");
strcpy(tp, result);
xp->orig = orig;
xp->result = tp;
xp->next = tcache_head;
tcache_head = xp;
} else {
free_lbuf(orig);
}
} else {
free_lbuf(orig);
}

static void tcache_finish(player)


dbref player;
{
TCENT *xp;
NUMBERTAB *np;
dbref target;
if (H_Redirect(player)) {
np = (NUMBERTAB *) nhashfind(player, &mudstate.redir_htab);
if (np) {
target = np->num;
} else {
/* Ick. If we have no pointer, we should have no flag. */
s_Flags3(player, Flags3(player) & ~HAS_REDIRECT);
target = Owner(player);
}
} else {
target = Owner(player);
}

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:45 PM

while (tcache_head != NULL) {


xp = tcache_head;
tcache_head = xp->next;
notify(target,
tprintf("%s(#%d)} '%s' -> '%s'", Name(player), player,
xp->orig, xp->result));
free_lbuf(xp->orig);
free_lbuf(xp->result);
free_sbuf(xp);
}
tcache_top = 1;
tcache_count = 0;

/* Character table for fast lookups.


* 0 - 31 (00 - 1F): NULL plus other specials
* 32 - 63 (20 - 3F): space through ? (symbol characters)
* 64 - 95 (40 - 5F): @ through _ (includes upper-case letters)
* 96 - 127 (60 - 7F): ` through delete (includes lower-case letters)
*
* We want '', ESC, ' ', '\', '[', '{', '(', '%', and '#'.
*/
char special_chartab[256] =
{
1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
1,0,0,1,0,1,0,0, 1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
};
char token_chartab[256] =
{
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,1,0,1,1,0,0,0, 0,0,0,1,0,0,0,0,
1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
};

0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,

0,0,0,1,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,1,1,0,0,0,
0,0,0,1,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0

0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0

char *ansi_chartab[256] =
{
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,
0,
ANSI_BBLUE, ANSI_BCYAN,
0,
0,
0,
ANSI_BGREEN,
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

};

Saturday, June 16, 2012 11:45 PM

0,
0,
0,
0,
0,
ANSI_BMAGENTA, 0,
0,
0,
0,
ANSI_BRED,
0,
0,
0,
0,
ANSI_BWHITE,
ANSI_BBLACK, ANSI_BYELLOW, 0,
0,
0,
0,
0,
0,
0,
0,
ANSI_BLUE,
ANSI_CYAN,
0,
0,
ANSI_BLINK, ANSI_GREEN,
ANSI_HILITE, ANSI_INVERSE, 0,
0,
0,
ANSI_MAGENTA, ANSI_NORMAL, 0,
0,
0,
ANSI_RED,
0,
0,
ANSI_UNDER,
0,
ANSI_WHITE,
ANSI_BLACK, ANSI_YELLOW,
0,
0,
0,
0,
0,
0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0

void exec(buff, bufc, player, caller, cause, eval, dstr, cargs, ncargs)
char *buff, **bufc;
dbref player, caller, cause;
int eval, ncargs;
char **dstr;
char *cargs[];
{
char *real_fargs[MAX_NFARGS + 1];
char **fargs = real_fargs + 1;
char *tstr, *tbuf, *savepos, *atr_gotten, *start, *oldp;
char savec, ch, *savestr, *str, *xptr, *mundane, *p;
char *realbuff = NULL, *realbp = NULL;
char xtbuf[SBUF_SIZE], *xtp;
dbref aowner;
int at_space, nfargs, gender, i, j, alldone, aflags, alen, feval;
int is_trace, is_top, save_count;
int ansi, nchar, navail;
FUN *fp;
UFUN *ufp;
VARENT *xvar;
ATTR *ap;
GDATA *preserve;
static const char *subj[5] =
{"", "it", "she", "he", "they"};
static const char *poss[5] =
{"", "its", "her", "his", "their"};
static const char *obj[5] =
{"", "it", "her", "him", "them"};
static const char *absp[5] =
{"", "its", "hers", "his", "theirs"};

-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:45 PM

if (*dstr == NULL) {
**bufc = '\0';
return;
}
at_space = 1;
gender = -1;
alldone = 0;
ansi = 0;
is_trace = Trace(player) && !(eval & EV_NOTRACE);
is_top = 0;
/* Extend the buffer if we need to. */
if (((*bufc) - buff) > (LBUF_SIZE - SBUF_SIZE)) {
realbuff = buff;
realbp = *bufc;
buff = (char *)XMALLOC(LBUF_SIZE, "exec.buff_extend");
*bufc = buff;
}
oldp = start = *bufc;
/* If we are tracing, save a copy of the starting buffer */
savestr = NULL;
if (is_trace) {
is_top = tcache_empty();
savestr = alloc_lbuf("exec.save");
strcpy(savestr, *dstr);
}
while (**dstr && !alldone) {
/* We adjust the special table every time we go around this
* loop, in order to avoid always treating '#' like a special
* character, as it gets used a whole heck of a lot.
*/
special_chartab[(unsigned char) '#'] =
(mudstate.in_loop || mudstate.in_switch) ? 1 : 0;
if (!special_chartab[(unsigned char) **dstr]) {
/* Mundane characters are the most common. There are usually
* a bunch in a row. We should just copy them.
*/
mundane = *dstr;
nchar = 0;
do {
nchar++;
} while (!special_chartab[(unsigned char) *(++mundane)]);
p = *bufc;
navail = LBUF_SIZE - 1 - (p - buff);
nchar = (nchar > navail) ? navail : nchar;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:45 PM

memcpy(p, *dstr, nchar);


*bufc = p + nchar;
*dstr = mundane;
at_space = 0;
}
/* We must have a special character at this point. */
if (**dstr == '\0')
break;
switch (**dstr) {
case ' ':
/* A space. Add a space if not compressing or if
* previous char was not a space
*/
if (!(mudconf.space_compress && at_space) ||
(eval & EV_NO_COMPRESS)) {
safe_chr(' ', buff, bufc);
at_space = 1;
}
break;
case '\\':
/* General escape. Add the following char without
* special processing
*/
at_space = 0;
(*dstr)++;
if (**dstr) {
safe_chr(**dstr, buff, bufc);
} else
(*dstr)--;
break;
case '[':
/* Function start. Evaluate the contents of the
* square brackets as a function. If no closing
* bracket, insert the [ and continue.
*/
at_space = 0;
tstr = (*dstr)++;
if (eval & EV_NOFCHECK) {
safe_chr('[', buff, bufc);
*dstr = tstr;
break;
}
tbuf = parse_to(dstr, ']', 0);
if (*dstr == NULL) {
safe_chr('[', buff, bufc);
*dstr = tstr;
} else {
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:45 PM

str = tbuf;
exec(buff, bufc, player, caller, cause,
(eval | EV_FCHECK | EV_FMAND),
&str, cargs, ncargs);
(*dstr)--;

}
break;
case '{':
/* Literal start. Insert everything up to the
* terminating } without parsing. If no closing
* brace, insert the { and continue.
*/
at_space = 0;
tstr = (*dstr)++;
tbuf = parse_to(dstr, '}', 0);
if (*dstr == NULL) {
safe_chr('{', buff, bufc);
*dstr = tstr;
} else {
if (!(eval & EV_STRIP)) {
safe_chr('{', buff, bufc);
}
/* Preserve leading spaces (Felan) */
if (*tbuf == ' ') {
safe_chr(' ', buff, bufc);
tbuf++;
}
str = tbuf;
exec(buff, bufc, player, caller, cause,
(eval & ~(EV_STRIP | EV_FCHECK)),
&str, cargs, ncargs);
if (!(eval & EV_STRIP)) {
safe_chr('}', buff, bufc);
}
(*dstr)--;

}
break;
case '%':
/* Percent-replace start. Evaluate the chars
* following and perform the appropriate
* substitution.
*/
at_space = 0;
(*dstr)++;
savec = **dstr;
savepos = *bufc;
switch (savec) {
case '\0': /* Null - all done */
(*dstr)--;
break;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:45 PM

case
case
case
case
case
case
case
case
case
case

'0':
/* Command argument number N */
'1':
'2':
'3':
'4':
'5':
'6':
'7':
'8':
'9':
i = (**dstr - '0');
if ((i < ncargs) && (cargs[i] != NULL))
safe_str(cargs[i], buff, bufc);
break;
case 'r':
/* Carriage return */
case 'R':
safe_crlf(buff, bufc);
break;
case 't':
/* Tab */
case 'T':
safe_chr('\t', buff, bufc);
break;
case 'B':
/* Blank */
case 'b':
safe_chr(' ', buff, bufc);
break;
case 'C':
case 'c':
if (mudconf.c_cmd_subst) {
safe_str(mudstate.curr_cmd, buff, bufc);
break;
}
/* FALLTHRU */
case 'x':
/* ANSI color */
case 'X':
(*dstr)++;
if (!**dstr) {
/*
* Note: There is an interesting
* bug/misfeature in the implementation
* of %v? and %q? -- if the second
* character is garbage or non-existent,
* it and the leading v or q gets eaten.
* In the interests of not changing the
* old behavior, this is not getting
* "fixed", but in this case, where
* moving the pointer back without
* exiting on an error condition ends up
* turning things black, the behavior
* must by necessity be different. So we
* do break out of the switch.
*/
(*dstr)--;
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:45 PM

break;
}
if (!mudconf.ansi_colors) {
/* just skip over the characters */
break;
}
if (!ansi_chartab[(unsigned char) **dstr]) {
safe_chr(**dstr, buff, bufc);
} else {
safe_str(ansi_chartab[(unsigned char) **dstr], buff, bufc);
ansi = (**dstr == 'n') ? 0 : 1;
}
break;
case '=': /* equivalent of generic v() attr get */
(*dstr)++;
if (**dstr != '<') {
(*dstr)--;
break;
}
xptr = *dstr;
(*dstr)++;
if (!**dstr) {
*dstr = xptr;
break;
}
xtp = xtbuf;
while (**dstr && (**dstr != '>')) {
safe_sb_chr(**dstr, xtbuf, &xtp);
(*dstr)++;
}
if (**dstr != '>') {
/* Ran off the end. Back up. */
*dstr = xptr;
break;
}
*xtp = '\0';
ap = atr_str(xtbuf);
if (!ap)
break;
atr_pget_info(player, ap->number,
&aowner, &aflags);
if (See_attr(player, player, ap,
aowner, aflags)) {
atr_gotten = atr_pget(player, ap->number,
&aowner, &aflags,
&alen);
safe_known_str(atr_gotten, alen,
buff, bufc);
free_lbuf(atr_gotten);
}
break;
case '_':
/* x-variable */
(*dstr)++;
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:45 PM

/* Check for %_<varname> */


if (**dstr != '<') {
ch = tolower(**dstr);
if (!**dstr)
(*dstr)--;
if (!isalnum(ch))
break;
xtp = xtbuf;
safe_ltos(xtbuf, &xtp, player);
safe_chr('.', xtbuf, &xtp);
safe_chr(ch, xtbuf, &xtp);
} else {
xptr = *dstr;
(*dstr)++;
if (!**dstr) {
*dstr = xptr;
break;
}
xtp = xtbuf;
safe_ltos(xtbuf, &xtp, player);
safe_chr('.', xtbuf, &xtp);
while (**dstr && (**dstr != '>')) {
/* Copy. No interpretation. */
ch = tolower(**dstr);
safe_sb_chr(ch, xtbuf, &xtp);
(*dstr)++;
}
if (**dstr != '>') {
/* We ran off the end of the string
* without finding a termination
* condition. Go back.
*/
*dstr = xptr;
break;
}
}
*xtp = '\0';
if ((xvar = (VARENT *) hashfind(xtbuf,
&mudstate.vars_htab))) {
safe_str(xvar->text, buff, bufc);
}
break;
case 'V':
/* Variable attribute */
case 'v':
(*dstr)++;
ch = toupper(**dstr);
if (!**dstr)
(*dstr)--;
if ((ch < 'A') || (ch > 'Z'))
break;
i = A_VA + ch - 'A';
atr_gotten = atr_pget(player, i, &aowner,
&aflags, &alen);
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:45 PM

safe_known_str(atr_gotten, alen, buff, bufc);


free_lbuf(atr_gotten);
break;
case 'Q':
/* Local registers */
case 'q':
(*dstr)++;
if (!**dstr) {
(*dstr)--;
break;
}
if (**dstr != '<') {
i = qidx_chartab[(unsigned char) **dstr];
if ((i < 0) || (i >= MAX_GLOBAL_REGS))
break;
if (mudstate.rdata &&
mudstate.rdata->q_alloc > i) {
safe_known_str(mudstate.rdata->q_regs[i],
mudstate.rdata->q_lens[i],
buff, bufc);
}
if (!**dstr)
(*dstr)--;
break;
}
xptr = *dstr;
(*dstr)++;
if (!**dstr) {
*dstr = xptr;
break;
}
if (!mudstate.rdata ||
!mudstate.rdata->xr_alloc) {
/* We know there's no result, so we
* just advance past.
*/
while (**dstr && (**dstr != '>'))
(*dstr)++;
if (**dstr != '>') {
/* Whoops, no end. Go back. */
*dstr = xptr;
break;
}
break;
}
xtp = xtbuf;
while (**dstr && (**dstr != '>')) {
safe_sb_chr(tolower(**dstr), xtbuf, &xtp);
(*dstr)++;
}
if (**dstr != '>') {
/* Ran off the end. Back up. */
*dstr = xptr;
break;
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:45 PM

}
*xtp = '\0';
for (i=0; i < mudstate.rdata->xr_alloc; i++) {
if (mudstate.rdata->x_names[i] &&
!strcmp(xtbuf,
mudstate.rdata->x_names[i])) {
safe_known_str(mudstate.rdata->x_regs[i],
mudstate.rdata->x_lens[i],
buff, bufc);
break;
}
}
break;
case 'O':
/* Objective pronoun */
case 'o':
if (gender < 0)
gender = get_gender(cause);
if (!gender)
safe_name(cause, buff, bufc);
else
safe_str((char *)obj[gender],
buff, bufc);
break;
case 'P':
/* Personal pronoun */
case 'p':
if (gender < 0)
gender = get_gender(cause);
if (!gender) {
safe_name(cause, buff, bufc);
safe_chr('s', buff, bufc);
} else {
safe_str((char *)poss[gender],
buff, bufc);
}
break;
case 'S':
/* Subjective pronoun */
case 's':
if (gender < 0)
gender = get_gender(cause);
if (!gender)
safe_name(cause, buff, bufc);
else
safe_str((char *)subj[gender],
buff, bufc);
break;
case 'A':
/* Absolute possessive */
case 'a':
/* idea from Empedocles */
if (gender < 0)
gender = get_gender(cause);
if (!gender) {
safe_name(cause, buff, bufc);
safe_chr('s', buff, bufc);
} else {
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:45 PM

safe_str((char *)absp[gender],
buff, bufc);

}
break;
case '#':
/* Invoker DB number */
safe_dbref(buff, bufc, cause);
break;
case '!':
/* Executor DB number */
safe_dbref(buff, bufc, player);
break;
case 'N':
/* Invoker name */
case 'n':
safe_name(cause, buff, bufc);
break;
case 'L':
/* Invoker location db# */
case 'l':
if (!(eval & EV_NO_LOCATION)) {
safe_dbref(buff, bufc, where_is(cause));
}
break;
case '@':
/* Caller dbref */
safe_dbref(buff, bufc, caller);
break;
case 'M':
case 'm':
safe_str(mudstate.curr_cmd, buff, bufc);
break;
case 'I':
/* itext() equivalent */
case 'i':
case 'J':
/* itext2() equivalent */
case 'j':
xtp = *dstr;
(*dstr)++;
if (!**dstr)
(*dstr)--;
if (**dstr == '-') {
/* use number as delta back from current */
(*dstr)++;
if (!**dstr)
(*dstr)--;
if (!isdigit(**dstr))
break;
i = (**dstr - '0');
} else {
if (!mudstate.in_loop || !isdigit(**dstr))
break;
i = mudstate.in_loop - 1 - (**dstr - '0');
if (i < 0)
break;
}
if (i > mudstate.in_loop - 1)
break;
if ((*xtp == 'i') || (*xtp == 'I')) {
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:45 PM

safe_str(mudstate.loop_token[i],
buff, bufc);
} else {
safe_str(mudstate.loop_token2[i],
buff, bufc);
}
break;
case '+':
/* arguments to function */
safe_ltos(buff, bufc, ncargs);
break;
case '|':
/* piped command output */
safe_str(mudstate.pout, buff, bufc);
break;
case '%':
/* Percent - a literal % */
safe_chr('%', buff, bufc);
break;
default:
/* Just copy */
safe_chr(**dstr, buff, bufc);
}
if (isupper(savec))
*savepos = toupper(*savepos);
break;
case '(':
/* Arglist start. See if what precedes is a
* function. If so, execute it if we should.
*/
at_space = 0;
if (!(eval & EV_FCHECK)) {
safe_chr('(', buff, bufc);
break;
}
/* Load an sbuf with an uppercase version of the func
* name, and see if the func exists. Trim
* trailing spaces from the name if configured.
*/
**bufc = '\0';
xtp = xtbuf;
safe_sb_str(oldp, xtbuf, &xtp);
*xtp = '\0';
if (mudconf.space_compress && (eval & EV_FMAND)) {
while ((--xtp >= xtbuf) && isspace(*xtp)) ;
xtp++;
*xtp = '\0';
}
for (xtp = xtbuf; *xtp; xtp++)
*xtp = toupper(*xtp);
fp = (FUN *) hashfind(xtbuf, &mudstate.func_htab);
/* If not a builtin func, check for global func */
ufp = NULL;
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:45 PM

if (fp == NULL) {
ufp = (UFUN *) hashfind(xtbuf,
&mudstate.ufunc_htab);
}
/* Do the right thing if it doesn't exist */
if (!fp && !ufp) {
if (eval & EV_FMAND) {
*bufc = oldp;
safe_tprintf_str(buff, bufc, "#-1 FUNCTION (%s) NOT FOUND" , xtbuf);
alldone = 1;
} else {
safe_chr('(', buff, bufc);
}
eval &= ~EV_FCHECK;
break;
}
/* Get the arglist and count the number of args
* Negative # of args means join subsequent args
*/
if (ufp)
nfargs = MAX_NFARGS;
else if (fp->nargs < 0)
nfargs = -fp->nargs;
else
nfargs = MAX_NFARGS;
tstr = *dstr;
if ((fp && (fp->flags & FN_NO_EVAL)) ||
(ufp && (ufp->flags & FN_NO_EVAL)))
feval = (eval & ~EV_EVAL) | EV_STRIP_ESC;
else
feval = eval;
*dstr = parse_arglist(player, caller, cause, *dstr + 1,
')', feval, fargs, nfargs,
cargs, ncargs);
/* If no closing delim, just insert the '(' and
* continue normally
*/
if (!*dstr) {
*dstr = tstr;
safe_chr(**dstr, buff, bufc);
for (i = 0; i < nfargs; i++)
if (fargs[i] != NULL)
free_lbuf(fargs[i]);
eval &= ~EV_FCHECK;
break;
}
/* Count number of args returned */

-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:45 PM

(*dstr)--;
j = 0;
for (i = 0; i < nfargs; i++)
if (fargs[i] != NULL)
j = i + 1;
nfargs = j;
/* We've got function(args) now, so back up over
* function name in output buffer
*/
*bufc = oldp;
/* If it's a user-defined function, perform it now. */
if (ufp) {
mudstate.func_nest_lev++;
mudstate.func_invk_ctr++;
if (mudstate.func_nest_lev >=
mudconf.func_nest_lim) {
safe_str("#-1 FUNCTION RECURSION LIMIT EXCEEDED" , buff, bufc);
} else if (mudstate.func_invk_ctr >=
mudconf.func_invk_lim) {
safe_str("#-1 FUNCTION INVOCATION LIMIT EXCEEDED" , buff, bufc);
} else if (Too_Much_CPU()) {
safe_str("#-1 FUNCTION CPU LIMIT EXCEEDED" , buff, bufc);
} else if (Going(player)) {
safe_str("#-1 BAD INVOKER", buff, bufc);
} else if (!check_access(player, ufp->perms)) {
safe_noperm(buff, bufc);
} else {
tstr = atr_get(ufp->obj, ufp->atr,
&aowner, &aflags,
&alen);
if (ufp->flags & FN_PRIV)
i = ufp->obj;
else
i = player;
str = tstr;
if (ufp->flags & FN_NOREGS) {
preserve = mudstate.rdata;
mudstate.rdata = NULL;
} else if (ufp->flags & FN_PRES) {
preserve = save_global_regs("eval.save");
}
exec(buff, bufc, i, player, cause,
((ufp->flags & FN_NO_EVAL) ?
(EV_FCHECK | EV_EVAL) : feval),
&str, fargs, nfargs);
if (ufp->flags & FN_NOREGS) {
Free_RegData(mudstate.rdata);
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

Saturday, June 16, 2012 11:45 PM

mudstate.rdata = preserve;
} else if (ufp->flags & FN_PRES) {
restore_global_regs("eval.restore",
preserve);
}
}

free_lbuf(tstr);

/* Return the space allocated for the args */


mudstate.func_nest_lev--;
for (i = 0; i < nfargs; i++)
if (fargs[i] != NULL)
free_lbuf(fargs[i]);
eval &= ~EV_FCHECK;
break;

}
/* If the number of args is right, perform the func.
* Otherwise return an error message. Note
* that parse_arglist returns zero args as one
* null arg, so we have to handle that case
* specially.
*/
if ((fp->nargs == 0) && (nfargs == 1)) {
if (!*fargs[0]) {
free_lbuf(fargs[0]);
fargs[0] = NULL;
nfargs = 0;
}
}
if ((nfargs == fp->nargs) ||
(nfargs == -fp->nargs) ||
(fp->flags & FN_VARARGS)) {
/* Check recursion limit */
mudstate.func_nest_lev++;
mudstate.func_invk_ctr++;
if (mudstate.func_nest_lev >=
mudconf.func_nest_lim) {
safe_str("#-1 FUNCTION RECURSION LIMIT EXCEEDED" , buff, bufc);
} else if (mudstate.func_invk_ctr >=
mudconf.func_invk_lim) {
safe_str("#-1 FUNCTION INVOCATION LIMIT EXCEEDED" , buff, bufc);
} else if (Too_Much_CPU()) {
safe_str("#-1 FUNCTION CPU LIMIT EXCEEDED" , buff, bufc);
} else if (Going(player)) {
/* Deal with the peculiar case of the
* calling object being destroyed
* mid-function sequence, such as
* with a command()/@destroy combo...
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

Saturday, June 16, 2012 11:45 PM

*/
safe_str("#-1 BAD INVOKER", buff, bufc);
} else if (!Check_Func_Access(player, fp)) {
safe_noperm(buff, bufc);
} else {
fargs[-1] = (char *)fp;
fp->fun( FUNCTION_ARGLIST );
}
mudstate.func_nest_lev--;
} else {
safe_tprintf_str(buff, bufc,
"#-1 FUNCTION (%s) EXPECTS %d ARGUMENTS BUT GOT %d" ,
fp->name, fp->nargs, nfargs);
}
/* Return the space allocated for the arguments */
for (i = 0; i < nfargs; i++)
if (fargs[i] != NULL)
free_lbuf(fargs[i]);
eval &= ~EV_FCHECK;
break;
case '#':
/* We should never reach this point unless we're
* in a loop or switch, thanks to the table lookup.
*/
at_space = 0;
(*dstr)++;
if (!token_chartab[(unsigned char) **dstr]) {
(*dstr)--;
safe_chr(**dstr, buff, bufc);
} else {
if ((**dstr == '#') && mudstate.in_loop) {
safe_str(mudstate.loop_token[mudstate.in_loop-1],
buff, bufc);
} else if ((**dstr == '@') && mudstate.in_loop) {
safe_ltos(buff, bufc,
mudstate.loop_number[mudstate.in_loop-1]);
} else if ((**dstr == '+') && mudstate.in_loop) {
safe_str(mudstate.loop_token2[mudstate.in_loop-1],
buff, bufc);
} else if ((**dstr == '$') && mudstate.in_switch) {
safe_str(mudstate.switch_token, buff, bufc);
} else if (**dstr == '!') {
/* Nesting level of loop takes precedence
* over switch nesting level.
*/
safe_ltos(buff, bufc,
((mudstate.in_loop) ?
(mudstate.in_loop - 1):
mudstate.in_switch));
} else {
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

Saturday, June 16, 2012 11:45 PM

(*dstr)--;
safe_chr(**dstr, buff, bufc);
}

}
break;
case ESC_CHAR:
safe_copy_esccode(*dstr, buff, bufc);
(*dstr)--;
break;
}
(*dstr)++;

/* If we're eating spaces, and the last thing was a space, eat it
* up. Complicated by the fact that at_space is initially
* true. So check to see if we actually put something in the
* buffer, too.
*/
if (mudconf.space_compress && at_space && !(eval & EV_NO_COMPRESS)
&& (start != *bufc))
(*bufc)--;
/* The ansi() function knows how to take care of itself. However,
* if the player used a %x sub in the string, and hasn't yet
* terminated the color with a %xn yet, we'll have to do it for
* them.
*/
if (ansi)
safe_ansi_normal(buff, bufc);
**bufc = '\0';
/* Report trace information */
if (is_trace) {
tcache_add(savestr, start);
save_count = tcache_count - mudconf.trace_limit;;
if (is_top || !mudconf.trace_topdown)
tcache_finish(player);
if (is_top && (save_count > 0)) {
tbuf = alloc_mbuf("exec.trace_diag");
sprintf(tbuf,
"%d lines of trace output discarded." ,
save_count);
notify(player, tbuf);
free_mbuf(tbuf);
}
}
if (realbuff) {
*bufc = realbp;
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325

Saturday, June 16, 2012 11:45 PM

safe_str(buff, realbuff, bufc);


**bufc = '\0';
XFREE(buff, "exec.buff_extend");
buff = realbuff;

/* --------------------------------------------------------------------------* save_global_regs, restore_global_regs: Save and restore the global


* registers to protect them from various sorts of munging.
*/
GDATA *save_global_regs(funcname)
const char *funcname;
{
GDATA *preserve;

if (mudstate.rdata) {
Alloc_RegData(funcname, mudstate.rdata, preserve);
Copy_RegData(funcname, mudstate.rdata, preserve);
} else {
preserve = NULL;
}
return preserve;

void restore_global_regs(funcname, preserve)


const char *funcname;
GDATA *preserve;
{
if (!mudstate.rdata && !preserve)
return;
if (mudstate.rdata && preserve &&
(mudstate.rdata->dirty == preserve->dirty)) {
/* No change in the values. Move along. */
Free_RegData(preserve);
return;
}
/* Rather than doing a big free-and-copy thing, we could just handle
* changes in the data structure size. Place for future optimization.
*/
if (!preserve) {
Free_RegData(mudstate.rdata);
mudstate.rdata = NULL;
} else {
if (mudstate.rdata) {
Free_RegData(mudstate.rdata);
}
Alloc_RegData(funcname, preserve, mudstate.rdata);
Copy_RegData(funcname, preserve, mudstate.rdata);
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\eval.c

1326
1327
1328
1329

Saturday, June 16, 2012 11:45 PM

Free_RegData(preserve);
}

-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:10 PM

/* externs.h - Prototypes for externs not defined elsewhere */


/* $Id: externs.h,v 1.136 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#ifndef __EXTERNS_H
#define __EXTERNS_H
/* -------------------------------------------------------------------------* External function declarations.
*/
/* From external sources */
extern char *
FDECL(crypt, (const char *, const char *));
#ifdef NEED_VSPRINTF_DCL
extern char *
FDECL(vsprintf, (char *, char *, va_list));
#endif
/* From boolexp.c */
extern int FDECL(eval_boolexp, (dbref, dbref, dbref, BOOLEXP *));
extern int FDECL(eval_boolexp_atr, (dbref, dbref, dbref, char *));
extern BOOLEXP *FDECL(parse_boolexp, (dbref,const char *, int));
/* From bsd.c */
extern void NDECL(boot_slave);
/* From command.c */
extern int FDECL(check_access, (dbref, int));
extern int FDECL(check_mod_access, (dbref, EXTFUNCS *));
extern void NDECL(reset_prefix_cmds);
extern void FDECL(process_cmdline, (dbref, dbref, char *, char *[], int,
BQUE *));
extern void FDECL(call_move_hook, (dbref, dbref, int));
/* From conf.c */
extern void VDECL(cf_log_syntax, (dbref, char *, const char *, ...));
extern void FDECL(cf_log_notfound, (dbref, char *, const char *, char *));
extern int FDECL(cf_modify_bits, (int *, char *, long, dbref, char *));
/* From cque.c */
extern int FDECL(nfy_que, (dbref, dbref, int, int, int));
extern int FDECL(halt_que, (dbref, dbref));
extern void FDECL(wait_que, (dbref, dbref, int, dbref, int, char *,
char *[], int, GDATA *));
extern int NDECL(que_next);
extern int FDECL(do_top, (int ncmds));
extern void NDECL(do_second);
/* From create.c */
extern int FDECL(destroyable, (dbref));
/* From db.c */
extern const char *FDECL(getstring_noalloc, (FILE *, int));
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

Saturday, June 16, 2012 11:10 PM

void FDECL(putstring, (FILE *, const char *));


void NDECL(dump_restart_db);
int FDECL(Commer, (dbref));
void FDECL(s_Pass, (dbref, const char *));
INLINE void FDECL(s_Name, (dbref, char *));
INLINE char *
FDECL(Name, (dbref));
INLINE char *
FDECL(PureName, (dbref));
INLINE void FDECL(safe_name, (dbref, char *, char **));
void FDECL(safe_exit_name, (dbref, char *, char **));
int FDECL(fwdlist_load, (FWDLIST *, dbref, char *));
void FDECL(fwdlist_set, (dbref, FWDLIST *));
void FDECL(fwdlist_clr, (dbref));
int FDECL(fwdlist_rewrite, (FWDLIST *, char *));
FWDLIST *FDECL(fwdlist_get, (dbref));
int FDECL(propdir_load, (PROPDIR *, dbref, char *));
void FDECL(propdir_set, (dbref, PROPDIR *));
void FDECL(propdir_clr, (dbref));
int FDECL(propdir_rewrite, (PROPDIR *, char *));
PROPDIR *FDECL(propdir_get, (dbref));
void NDECL(atr_push);
void NDECL(atr_pop);
int FDECL(atr_head, (dbref, char **));
int FDECL(atr_next, (char **));
int FDECL(init_gdbm_db, (char *));
void FDECL(atr_cpy, (dbref, dbref, dbref));
void FDECL(atr_chown, (dbref));
void FDECL(atr_clr, (dbref, int));
void FDECL(atr_add_raw, (dbref, int, char *));
void FDECL(atr_add, (dbref, int, char *, dbref, int));
void FDECL(atr_set_owner, (dbref, int, dbref));
void FDECL(atr_set_flags, (dbref, int, int));
char *
FDECL(atr_get_raw, (dbref, int));
char *
FDECL(atr_get, (dbref, int, dbref *, int *, int *));
char *
FDECL(atr_pget, (dbref, int, dbref *, int *, int *));
char *
FDECL(atr_get_str, (char *, dbref, int, dbref *, int *,
int *));
char *
FDECL(atr_pget_str, (char *, dbref, int, dbref *, int *,
int *));
int FDECL(atr_get_info, (dbref, int, dbref *, int *));
int FDECL(atr_pget_info, (dbref, int, dbref *, int *));
void FDECL(atr_free, (dbref));
int FDECL(check_zone, (dbref, dbref));
int FDECL(check_zone_for_player, (dbref, dbref));
void FDECL(toast_player, (dbref));

/* From eval.c */
extern char *
FDECL(parse_to, (char **, char, int));
extern char *
FDECL(parse_arglist, (dbref, dbref, dbref, char *, char, int,
char *[], int, char*[], int));
extern void FDECL(exec, (char *, char **, dbref, dbref, dbref,
int, char **, char *[], int));
extern GDATA * FDECL(save_global_regs, (const char *));
extern void FDECL(restore_global_regs, (const char *, GDATA *));
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:10 PM

/* From fnhelper.c */
extern dbref
FDECL(match_thing, (dbref, char *));
extern int FDECL(xlate, (char *));
extern long FDECL(random_range, (long, long));
/* From game.c */
extern void FDECL(notify_except, (dbref, dbref, dbref,
const char *, int));
extern void FDECL(notify_except2, (dbref, dbref, dbref, dbref,
const char *, int));
extern void FDECL(notify_check, (dbref, dbref, const char *, int));
extern int FDECL(Hearer, (dbref));
extern void FDECL(html_escape, (const char *, char *, char **));
extern void FDECL(dump_database_internal, (int));
extern void FDECL(fork_and_dump, (int));
/* From htab.c */
extern
CF_HDCL(cf_ntab_access);
/* From log.c */
extern FILE *
mainlog_fp;
extern int FDECL(start_log, (const char *, const char *, int));
extern void NDECL(end_log);
extern void FDECL(log_perror, (const char *, const char *,const char *,
const char *));
extern void VDECL(log_printf, (const char *, ...));
extern void FDECL(log_vprintf, (const char *, va_list));
extern void FDECL(log_name, (dbref));
extern void FDECL(log_name_and_loc, (dbref));
extern void FDECL(log_type_and_name, (dbref));
/* From look.c */
extern void FDECL(look_in, (dbref,dbref, int));
extern void FDECL(show_vrml_url, (dbref, dbref));
/* From object.c */
extern dbref
FDECL(new_home, (dbref));
extern void FDECL(divest_object, (dbref));
extern dbref
FDECL(create_obj, (dbref, int, char *, int));
extern void FDECL(destroy_obj, (dbref, dbref));
extern void FDECL(empty_obj, (dbref));
/* From netcommon.c */
extern void VDECL(raw_broadcast, (int, char *, ...));
/* From move.c */
extern void FDECL(move_object, (dbref, dbref));
extern void FDECL(move_via_generic, (dbref, dbref, dbref, int));
extern void FDECL(move_via_exit, (dbref, dbref, dbref, dbref, int));
extern int FDECL(move_via_teleport, (dbref, dbref, dbref, int));
extern void FDECL(move_exit, (dbref, dbref, int, const char *, int));

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:10 PM

/* From object.c */
extern void FDECL(destroy_player, (dbref));
/* From player.c */
extern dbref
FDECL(create_player, (char *, char *, dbref, int, int));
extern int FDECL(add_player_name, (dbref, char *));
extern int FDECL(delete_player_name, (dbref, char *));
extern dbref
FDECL(lookup_player, (dbref, char *, int));
extern void NDECL(load_player_names);
extern void FDECL(badname_add, (char *));
extern void FDECL(badname_remove, (char *));
extern int FDECL(badname_check, (char *));
extern void FDECL(badname_list, (dbref, const char *));
/* From predicates.c */
extern char *
VDECL(tprintf, (const char *, ...));
extern char *
FDECL(tvprintf, (const char *, va_list));
extern void VDECL(safe_tprintf_str, (char *, char **, const char *, ...));
extern dbref
FDECL(insert_first, (dbref, dbref));
extern dbref
FDECL(remove_first, (dbref, dbref));
extern dbref
FDECL(reverse_list, (dbref));
extern int FDECL(member, (dbref, dbref));
extern int FDECL(is_integer, (char *));
extern int FDECL(is_number, (char *));
extern int FDECL(could_doit, (dbref, dbref, int));
extern void FDECL(add_quota, (dbref, int, int));
extern int FDECL(canpayfees, (dbref, dbref, int, int, int));
extern int FDECL(payfees, (dbref, int, int, int));
extern void FDECL(giveto, (dbref,int));
extern int FDECL(payfor, (dbref,int));
extern int FDECL(ok_name, (const char *));
extern int FDECL(ok_player_name, (const char *));
extern int FDECL(ok_attr_name, (const char *));
extern int FDECL(ok_password, (const char *, dbref));
extern void FDECL(handle_ears, (dbref, int, int));
extern dbref
FDECL(match_possessed, (dbref, dbref, char *, dbref, int));
extern void FDECL(parse_range, (char **, dbref *, dbref *));
extern int FDECL(parse_thing_slash, (dbref, char *, char **, dbref *));
extern int FDECL(get_obj_and_lock, (dbref, char *, dbref *, ATTR **,
char *, char **));
extern dbref
FDECL(where_is, (dbref));
extern dbref
FDECL(where_room, (dbref));
extern int FDECL(locatable, (dbref, dbref, dbref));
extern int FDECL(nearby, (dbref, dbref));
extern char *
FDECL(master_attr, (dbref, dbref, int, char **, int, int *));
extern void FDECL(did_it, (dbref, dbref, int, const char *, int,
const char *, int, int, char *[], int, int));
/* From set.c */
extern int FDECL(parse_attrib, (dbref, char *, dbref *, int *, int));
extern int FDECL(parse_attrib_wild, (dbref, char *, dbref *, int,
int, int, int));
extern void FDECL(edit_string, (char *, char **, char *, char *));
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

extern dbref
extern dbref

Saturday, June 16, 2012 11:10 PM

FDECL(match_controlled, (dbref, const char *));


FDECL(match_affected, (dbref, const char *));

/* From stringutil.c */
extern char *
FDECL(upcasestr, (char *));
extern char *
FDECL(munge_space, (char *));
extern char *
FDECL(trim_spaces, (char *));
extern char *
FDECL(grabto, (char **, char));
extern int FDECL(string_compare, (const char *, const char *));
extern int FDECL(string_prefix, (const char *, const char *));
extern const char * FDECL(string_match, (const char * ,const char *));
extern char *
FDECL(replace_string, (const char *, const char *,
const char *));
extern void FDECL(edit_string, (char *, char **, char *, char *));
extern char *
FDECL(skip_space, (const char *));
extern int FDECL(minmatch, (char *, char *, int));
extern INLINE void FDECL(safe_copy_str, (char *, char *, char **, int));
extern INLINE int FDECL(safe_copy_str_fn, (const char *, char *, char **, int));
extern int FDECL(safe_copy_long_str, (char *, char *, char **, int));
extern INLINE void FDECL(safe_known_str, (const char *, int, char *, char **));
extern int FDECL(matches_exit_from_list, (char *, char *));
extern char *
FDECL(translate_string, (char *, int));
extern int FDECL(ltos, (char *, long));
extern INLINE void FDECL(safe_ltos, (char *, char **, long));
/* From timer.c */
extern int FDECL(call_cron, (dbref, dbref, int, char *));
extern int FDECL(cron_clr, (dbref, int));
/* From udb_achunk.c */
extern int NDECL(dddb_close);
extern int FDECL(dddb_setfile, (char *));
extern int NDECL(dddb_init);
/* From unparse.c */
extern char *
FDECL(unparse_boolexp, (dbref, BOOLEXP *));
extern char *
FDECL(unparse_boolexp_quiet, (dbref, BOOLEXP *));
extern char *
FDECL(unparse_boolexp_decompile, (dbref, BOOLEXP *));
extern char *
FDECL(unparse_boolexp_function, (dbref, BOOLEXP *));
/* From walkdb.c */
extern int FDECL(chown_all, (dbref, dbref, dbref, int));
extern void NDECL(olist_push);
extern void NDECL(olist_pop);
extern void FDECL(olist_add, (dbref));
extern dbref
NDECL(olist_first);
extern dbref
NDECL(olist_next);
/* From wild.c */
extern int FDECL(wild, (char *, char *, char *[], int));
extern int FDECL(wild_match, (char *, char *));
extern int FDECL(quick_wild, (char *, char *));
extern int FDECL(register_match, (char *, char *, char *[], int));
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:10 PM

/* -------------------------------------------------------------------------* Constants.
*/
/* Command handler keys */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

ADDCMD_PRESERVE 1
/* Use player rather than addcommand thing */
ATTRIB_ACCESS
1
/* Change access to attribute */
ATTRIB_RENAME
2
/* Rename attribute */
ATTRIB_DELETE
4
/* Delete attribute */
ATTRIB_INFO 8
/* Info (number, flags) about attribute */
BOOT_QUIET 1
/* Inhibit boot message to victim */
BOOT_PORT
2
/* Boot by port number */
CHOWN_ONE
1
/* item = new_owner */
CHOWN_ALL
2
/* old_owner = new_owner */
CHOWN_NOSTRIP
4
/* Don't strip (most) flags from object */
CHZONE_NOSTRIP 1
/* Don't strip (most) flags from object */
CLONE_LOCATION 0
/* Create cloned object in my location */
CLONE_INHERIT
1
/* Keep INHERIT bit if set */
CLONE_PRESERVE 2
/* Preserve the owner of the object */
CLONE_INVENTORY 4
/* Create cloned object in my inventory */
CLONE_SET_COST 8
/* ARG2 is cost of cloned object */
CLONE_FROM_PARENT 16
/* Set parent instead of cloning attrs */
CLONE_NOSTRIP
32 /* Don't strip (most) flags from clone */
DBCK_FULL
1
/* Do all tests */
DECOMP_PRETTY
1
/* pretty-format output */
DEST_ONE
1
/* object */
DEST_ALL
2
/* owner */
DEST_OVERRIDE
4
/* override Safe() */
DEST_INSTANT
8
/* instantly destroy */
DIG_TELEPORT
1
/* teleport to room after @digging */
DOLIST_SPACE
0
/* expect spaces as delimiter */
DOLIST_DELIMIT 1
/* expect custom delimiter */
DOLIST_NOTIFY
2
/* queue a '@notify me' at the end */
DOLIST_NOW 4
/* Run commands immediately, no queueing */
DOING_MESSAGE
0
/* Set my DOING message */
DOING_HEADER
1
/* Set the DOING header */
DOING_POLL 2
/* List DOING header */
DOING_QUIET 4
/* Inhibit 'Set.' message */
DROP_QUIET 1
/* Don't do Odrop/Adrop if control */
DUMP_STRUCT 1
/* Dump flat structure file */
DUMP_TEXT
2
/* Dump text (gdbm) file */
DUMP_FLATFILE
8
/* Dump to flatfile */
ENDCMD_BREAK
0
/* @break - end action list on true */
ENDCMD_ASSERT
1
/* @assert - end action list on false */
EXAM_DEFAULT
0
/* Default */
EXAM_BRIEF 1
/* Don't show attributes */
EXAM_LONG
2
/* Nonowner sees public attrs too */
EXAM_DEBUG 4
/* Display more info for finding db problems */
EXAM_PARENT 8
/* Get attr from parent when exam obj/attr */
EXAM_PRETTY 16 /* Pretty-format output */
EXAM_PAIRS 32 /* Print paren matches in color */
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

EXAM_OWNER 64
FIXDB_OWNER 1
FIXDB_LOC
2
FIXDB_CON
4
FIXDB_EXITS 8
FIXDB_NEXT 16
FIXDB_PENNIES
FIXDB_NAME 64
FLOATERS_ALL
FUNCT_LIST 1
FUNCT_NO_EVAL
FUNCT_PRIV 4
FUNCT_PRES 8
FUNCT_NOREGS
FRC_COMMAND 1
FRC_NOW
2
GET_QUIET
1
GIVE_QUIET 1
GLOB_ENABLE 1
GLOB_DISABLE
HALT_ALL
1
HELP_FIND
1
HELP_RAWHELP
HOOK_BEFORE 1
HOOK_AFTER 2
HOOK_PRESERVE
HOOK_NOPRESERVE
HOOK_PERMIT 16
HOOK_PRIVATE
KILL_KILL
1
KILL_SLAY
2
LOOK_LOOK
1
LOOK_INVENTORY
LOOK_SCORE 4
LOOK_OUTSIDE
MARK_SET
0
MARK_CLEAR 1
MOTD_ALL
0
MOTD_WIZ
1
MOTD_DOWN
2
MOTD_FULL
4
MOTD_LIST
8
MOTD_BRIEF 16
MOVE_QUIET 1
NFY_NFY
0
NFY_NFYALL 1
NFY_DRAIN
2
NREF_LIST
1
OPEN_LOCATION
OPEN_INVENTORY
PASS_ANY
1
PASS_MINE
2
PCRE_PLAYER 1

Saturday, June 16, 2012 11:10 PM

/* Nonowner sees just owner */


/* Fix OWNER field */
/* Fix LOCATION field */
/* Fix CONTENTS field */
/* Fix EXITS field */
/* Fix NEXT field */
32 /* Fix PENNIES field */
/* Set NAME attribute */
1
/* Display all floating rooms in db */
/* List the user-defined functions */
2
/* Don't evaluate args to function */
/* Perform ufun as holding obj */
/* Preserve r-regs before ufun */
16 /* Private r-regs for ufun */
/* what=command */
/* run command immediately, no queueing */
/* Don't do osucc/asucc if control */
/* Inhibit give messages */
/* key to enable */
2
/* key to disable */
/* halt everything */
/* do a wildcard search through help subjects */
0x08000000 /* A high bit. Don't eval text. */
/* pre-command hook */
/* post-command hook */
4
/* preserve global regs */
8
/* don't preserve global regs */
/* user-defined permissions */
32 /* private global regs */
/* gives victim insurance */
/* no insurance */
/* list desc (and succ/fail if room) */
2
/* list inventory of object */
/* list score (# coins) */
8
/* look for object in container of player */
/* Set mark bits */
/* Clear mark bits */
/* login message for all */
/* login message for wizards */
/* login message when logins disabled */
/* login message when too many players on */
/* Display current login messages */
/* Suppress motd file display for wizards */
/* Dont do Osucc/Ofail/Asucc/Afail if ctrl */
/* Notify first waiting command */
/* Notify all waiting commands */
/* Delete waiting commands */
/* List rather than set nrefs */
0
/* Open exit in my location */
1
/* Open exit in me */
/* name=newpass */
/* oldpass=newpass */
/* create new player */
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

Saturday, June 16, 2012 11:10 PM

PCRE_ROBOT 2
/* create robot player */
PEMIT_PEMIT 1
/* emit to named player */
PEMIT_OEMIT 2
/* emit to all in current room except named */
PEMIT_WHISPER
3
/* whisper to player in current room */
PEMIT_FSAY 4
/* force controlled obj to say */
PEMIT_FEMIT 5
/* force controlled obj to emit */
PEMIT_FPOSE 6
/* force controlled obj to pose */
PEMIT_FPOSE_NS 7
/* force controlled obj to pose w/o space */
PEMIT_CONTENTS 8
/* Send to contents (additive) */
PEMIT_HERE 16 /* Send to location (@femit, additive) */
PEMIT_ROOM 32 /* Send to containing rm (@femit, additive) */
PEMIT_LIST
64
/* Send to a list */
PEMIT_SPEECH
128 /* Explicitly tag this as speech */
PEMIT_HTML 256
/* HTML escape, and no newline */
PEMIT_MOVE 512 /* Explicitly tag this as a movement message */
PEMIT_SPOOF 1024
/* change enactor to target object */
PS_BRIEF
0
/* Short PS report */
PS_LONG
1
/* Long PS report */
PS_SUMM
2
/* Queue counts only */
PS_ALL
4
/* List entire queue */
QUEUE_KICK 1
/* Process commands from queue */
QUEUE_WARP 2
/* Advance or set back wait queue clock */
QUOTA_SET
1
/* Set a quota */
QUOTA_FIX
2
/* Repair a quota */
QUOTA_TOT
4
/* Operate on total quota */
QUOTA_REM
8
/* Operate on remaining quota */
QUOTA_ALL
16 /* Operate on all players */
QUOTA_ROOM
32
/* Room quota set */
QUOTA_EXIT
64
/* Exit quota set */
QUOTA_THING
128
/* Thing quota set */
QUOTA_PLAYER
256
/* Player quota set */
SAY_SAY
1
/* say in current room */
SAY_NOSPACE 1
/* OR with xx_EMIT to get nospace form */
SAY_POSE
2
/* pose in current room */
SAY_POSE_NOSPC 3
/* pose w/o space in current room */
SAY_EMIT
5
/* emit in current room */
SAY_SHOUT
8
/* shout to all logged-in players */
SAY_WALLPOSE
9
/* Pose to all logged-in players */
SAY_WALLEMIT
10 /* Emit to all logged-in players */
SAY_WIZSHOUT
12 /* shout to all logged-in wizards */
SAY_WIZPOSE 13 /* Pose to all logged-in wizards */
SAY_WIZEMIT 14 /* Emit to all logged-in wizards */
SAY_ADMINSHOUT 15 /* Emit to all wizards or royalty */
SAY_NOTAG
32 /* Don't put Broadcast: in front (additive) */
SAY_HERE
64 /* Output to current location */
SAY_ROOM
128 /* Output to containing room */
SAY_HTML
256
/* Don't output a newline */
SAY_PREFIX 512 /* first char indicates formatting */
SET_QUIET
1
/* Don't display 'Set.' message. */
SHUTDN_COREDUMP 1
/* Produce a coredump */
SRCH_SEARCH 1
/* Do a normal search */
SRCH_MARK
2
/* Set mark bit for matches */
SRCH_UNMARK 3
/* Clear mark bit for matches */
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:10 PM

#define STAT_PLAYER 0
/* Display stats for one player or tot objs */
#define STAT_ALL
1
/* Display global stats */
#define STAT_ME
2
/* Display stats for me */
#define SWITCH_DEFAULT 0
/* Use the configured default for switch */
#define SWITCH_ANY 1
/* Execute all cases that match */
#define SWITCH_ONE 2
/* Execute only first case that matches */
#define SWITCH_NOW 4
/* Execute case(s) immediately, no queueing */
#define SWEEP_ME
1
/* Check my inventory */
#define SWEEP_HERE 2
/* Check my location */
#define SWEEP_COMMANDS 4
/* Check for $-commands */
#define SWEEP_LISTEN
8
/* Check for @listen-ers */
#define SWEEP_PLAYER
16 /* Check for players and puppets */
#define SWEEP_CONNECT
32 /* Search for connected players/puppets */
#define SWEEP_EXITS 64 /* Search the exits for audible flags */
#define SWEEP_VERBOSE
256 /* Display what pattern matches */
#define TELEPORT_DEFAULT 1 /* Emit all messages */
#define TELEPORT_QUIET
2 /* Teleport in quietly */
#define TIMECHK_RESET
1
/* Reset all counters to zero */
#define TIMECHK_SCREEN 2
/* Write info to screen */
#define TIMECHK_LOG 4
/* Write info to log */
#define TOAD_NO_CHOWN
1
/* Don't change ownership */
#define TRIG_QUIET 1
/* Don't display 'Triggered.' message. */
#define TRIG_NOW
2
/* Run immediately, no queueing */
#define TWARP_QUEUE 1
/* Warp the wait and sem queues */
#define TWARP_DUMP 2
/* Warp the dump interval */
#define TWARP_CLEAN 4
/* Warp the cleaning interval */
#define TWARP_IDLE 8
/* Warp the idle check interval */
/* twarp empty
16 */
#define TWARP_EVENTS
32 /* Warp the events checking interval */
#define VERB_NOW
1
/* Run @afoo immediately, no queueing */
#define VERB_MOVE
2
/* Treat like movement message */
#define VERB_SPEECH 4
/* Treat like speech message */
#define VERB_PRESENT
8
/* Treat like presence message */
#define VERB_NONAME 16 /* Do not prepend name to odefault */
/* Hush codes for movement messages */
#define HUSH_ENTER
#define HUSH_LEAVE
#define HUSH_EXIT

1
2
4

/* xENTER/xEFAIL */
/* xLEAVE/xLFAIL */
/* xSUCC/xDROP/xFAIL from exits */

/* Evaluation directives */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

EV_FIGNORE 0x00000000 /*
EV_FMAND
0x00000100 /*
EV_FCHECK
0x00000200 /*
EV_STRIP
0x00000400 /*
EV_EVAL
0x00000800 /*
EV_STRIP_TS 0x00001000 /*
EV_STRIP_LS 0x00002000 /*
EV_STRIP_ESC
0x00004000
EV_STRIP_AROUND 0x00008000
EV_TOP
0x00010000 /*

Don't look for func if () found */


Text before () must be func name */
Check text before () for function */
Strip one level of brackets */
Evaluate results before returning */
Strip trailing spaces */
Strip leading spaces */
/* Strip one level of \ characters */
/* Strip {} only at ends of string */
This is a toplevel call to eval() */
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

#define
#define
#define
#define

Saturday, June 16, 2012 11:10 PM

EV_NOTRACE 0x00020000 /* Don't trace this call to eval */


EV_NO_COMPRESS 0x00040000
/* Don't compress spaces. */
EV_NO_LOCATION 0x00080000 /* Suppresses %l */
EV_NOFCHECK 0x00100000 /* Do not evaluate functions! */

/* Function flags */
#define FN_VARARGS 0x80000000 /* allows variable # of args */
#define FN_NO_EVAL 0x40000000 /* Don't evaluate args to function */
#define FN_PRIV
0x20000000 /* Perform ufun as holding obj */
#define FN_PRES
0x10000000 /* Preserve r-regs before ufun */
#define FN_NOREGS
0x08000000 /* Private r-regs for ufun */
/* Lower flag values are used for function-specific switches */
/* Message forwarding directives */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

MSG_PUP_ALWAYS 0x00001 /* Always forward msg to puppet own */


MSG_INV
0x00002 /* Forward msg to contents */
MSG_INV_L
0x00004 /* ... only if msg passes my @listen */
MSG_INV_EXITS
0x00008 /* Forward through my audible exits */
MSG_NBR
0x00010 /* Forward msg to neighbors */
MSG_NBR_A
0x00020 /* ... only if I am audible */
MSG_NBR_EXITS
0x00040 /* Also forward to neighbor exits */
MSG_NBR_EXITS_A 0x00080 /* ... only if I am audible */
MSG_LOC
0x00100 /* Send to my location */
MSG_LOC_A
0x00200 /* ... only if I am audible */
MSG_FWDLIST 0x00400 /* Forward to my fwdlist members if audible */
MSG_ME
0x00800 /* Send to me */
MSG_S_INSIDE
0x01000 /* Originator is inside target */
MSG_S_OUTSIDE
0x02000 /* Originator is outside target */
MSG_HTML
0x04000 /* Don't send \r\n */
MSG_SPEECH 0x08000 /* This message is speech. */
MSG_MOVE
0x10000 /* This message is movement. */
MSG_PRESENCE
0x20000 /* This message is related to presence. */
MSG_ME_ALL (MSG_ME|MSG_INV_EXITS|MSG_FWDLIST)
MSG_F_CONTENTS (MSG_INV)
MSG_F_UP
(MSG_NBR_A|MSG_LOC_A)
MSG_F_DOWN (MSG_INV_L)

/* Look primitive directives */


#define
#define
#define
#define
#define

LK_IDESC
0x0001
LK_OBEYTERSE
0x0002
LK_SHOWATTR 0x0004
LK_SHOWEXIT 0x0008
LK_SHOWVRML 0x0010

/* Quota types */
#define QTYPE_ALL 0
#define QTYPE_ROOM 1
#define QTYPE_EXIT 2
#define QTYPE_THING 3
#define QTYPE_PLAYER 4
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

Saturday, June 16, 2012 11:10 PM

/* Signal handling directives */


#define SA_EXIT
#define SA_DFLT

1
2

/* Exit, and dump core */


/* Try to restart on a fatal error */

/* Database dumping directives for dump_database_internal() */


#define
#define
#define
#define
#define

DUMP_DB_NORMAL
DUMP_DB_CRASH
DUMP_DB_RESTART
DUMP_DB_FLATFILE
DUMP_DB_KILLED

0
1
2
3
4

/* -------------------------------------------------------------------------* A zillion ways to notify things.


*/
#define notify(p,m)

notify_check(p,p,m, \
MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN)
#define notify_html(p,m)
notify_check(p,p,m, \
MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN|MSG_HT
ML)
#define notify_quiet(p,m)
notify_check(p,p,m, \
MSG_PUP_ALWAYS|MSG_ME)
#define notify_with_cause(p,c,m)
notify_check(p,c,m, \
MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN)
#define notify_with_cause_html(p,c,m)
notify_check(p,c,m, \

#define
#define
#define
#define
#define
#define
#define

MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN|MSG_HT
ML)
notify_with_cause_extra(p,c,m,f) notify_check(p,c,m, \
MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN|(f))
notify_quiet_with_cause(p,c,m) notify_check(p,c,m, \
MSG_PUP_ALWAYS|MSG_ME)
notify_puppet(p,c,m)
notify_check(p,c,m, \
MSG_ME_ALL|MSG_F_DOWN)
notify_quiet_puppet(p,c,m) notify_check(p,c,m, \
MSG_ME)
notify_all(p,c,m)
notify_check(p,c,m, \
MSG_ME_ALL|MSG_NBR_EXITS|MSG_F_UP|MSG_F_CONTENTS)
notify_all_from_inside(p,c,m)
notify_check(p,c,m, \
MSG_ME_ALL|MSG_NBR_EXITS_A|MSG_F_UP|MSG_F_CONTENTS|MSG_S_INSIDE)
notify_all_from_inside_speech(p,c,m)
notify_check(p,c,m, \

MSG_ME_ALL|MSG_NBR_EXITS_A|MSG_F_UP|MSG_F_CONTENTS|MSG_S_INSIDE|M
SG_SPEECH)
#define notify_all_from_inside_move(p,c,m) notify_check(p,c,m, \
MSG_ME_ALL|MSG_NBR_EXITS_A|MSG_F_UP|MSG_F_CONTENTS|MSG_S_INSIDE|M
SG_MOVE)
#define notify_all_from_inside_html(p,c,m)
notify_check(p,c,m, \
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

Saturday, June 16, 2012 11:10 PM

MSG_ME_ALL|MSG_NBR_EXITS_A|MSG_F_UP|MSG_F_C
ONTENTS|MSG_S_INSIDE|MSG_HTML)
#define notify_all_from_inside_html_speech(p,c,m)
notify_check(p,c,m, \
MSG_ME_ALL|MSG_NBR_EXITS_A|MSG_F_UP|MSG_F_C
ONTENTS|MSG_S_INSIDE|MSG_HTML|MSG_SPEECH)
#define notify_all_from_outside(p,c,m) notify_check(p,c,m, \
MSG_ME_ALL|MSG_NBR_EXITS|MSG_F_UP|MSG_F_CONTENTS|MSG_S_OUTSIDE)
#define CANNOT_HEAR_MSG
#define NOT_PRESENT_MSG

"That target cannot hear you."


"That target is not present."

/* -------------------------------------------------------------------------* General macros.


*/
#define Randomize(n)

(random_range(0, (n) - 1))

#define Protect(f) (cmdp->perms & f)


#define Invalid_Objtype(x) \
((Protect(CA_LOCATION) && !Has_location(x)) || \
(Protect(CA_CONTENTS) && !Has_contents(x)) || \
(Protect(CA_PLAYER) && (Typeof(x) != TYPE_PLAYER)))
#define safe_atoi(s)

((s == NULL) ? 0 : atoi(s))

#define STARTLOG(key,p,s) \
if ((((key) & mudconf.log_options) != 0) && start_log(p, s, key)) {
#define ENDLOG \
end_log(); }
#define LOG_SIMPLE(key,p,s,m) \
STARTLOG(key,p,s) \
log_printf("%s", m); \
ENDLOG
#define test_top()
#define controls(p,x)

((mudstate.qfirst != NULL) ? 1 : 0)
Controls(p,x)

/* -------------------------------------------------------------------------* Global data things.


*/
#define Free_RegDataStruct(d) \
if (d) { \
if ((d)->q_regs) { \
XFREE((d)->q_regs, "q_regs"); \
} \
if ((d)->q_lens) { \
XFREE((d)->q_lens, "q_lens"); \
} \
if ((d)->x_names) { \
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677

Saturday, June 16, 2012 11:10 PM

XFREE((d)->x_names, "x_names"); \
} \
if ((d)->x_regs) { \
XFREE((d)->x_regs, "x_regs"); \
} \
if ((d)->x_lens) { \
XFREE((d)->x_lens, "x_lens"); \
} \
XFREE(d, "gdata"); \
}
#define Free_RegData(d) \
{ \
int z; \
if (d) { \
for (z = 0; z < (d)->q_alloc; z++) { \
if ((d)->q_regs[z]) \
free_lbuf((d)->q_regs[z]); \
} \
for (z = 0; z < (d)->xr_alloc; z++) { \
if ((d)->x_names[z]) \
free_sbuf((d)->x_names[z]); \
if ((d)->x_regs[z]) \
free_lbuf((d)->x_regs[z]); \
} \
Free_RegDataStruct(d); \
} \
}
#define Free_QData(q) \
XFREE((q)->text, "queue.text"); \
Free_RegDataStruct((q)->gdata);
#define Init_RegData(f, t) \
(t) = (GDATA *) XMALLOC(sizeof(GDATA), (f)); \
(t)->q_alloc = (t)->xr_alloc = 0; \
(t)->q_regs = (t)->x_names = (t)->x_regs = NULL; \
(t)->q_lens = (t)->x_lens = NULL; \
(t)->dirty = 0;
#define Alloc_RegData(f, g, t) \
if ((g) && ((g)->q_alloc || (g)->xr_alloc)) { \
(t) = (GDATA *) XMALLOC(sizeof(GDATA), (f)); \
(t)->q_alloc = (g)->q_alloc; \
if ((g)->q_alloc) { \
(t)->q_regs = XCALLOC((g)->q_alloc, sizeof(char *), "q_regs"); \
(t)->q_lens = XCALLOC((g)->q_alloc, sizeof(int), "q_lens"); \
} else { \
(t)->q_regs = NULL; \
(t)->q_lens = NULL; \
} \
(t)->xr_alloc = (g)->xr_alloc; \
if ((g)->xr_alloc) { \
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730

Saturday, June 16, 2012 11:10 PM

(t)->x_names = XCALLOC((g)->xr_alloc, sizeof(char *), "x_names"); \


(t)->x_regs = XCALLOC((g)->xr_alloc, sizeof(char *), "x_regs"); \
(t)->x_lens = XCALLOC((g)->xr_alloc, sizeof(int), "x_lens"); \
} else { \
(t)->x_names = NULL; \
(t)->x_regs = NULL; \
(t)->x_lens = NULL; \
} \
(t)->dirty = 0; \
} else { \
(t) = NULL; \
}
/* Copy global data from g to t */
#define Copy_RegData(f, g, t) \
{ \
int z; \
if ((g) && (g)->q_alloc) { \
for (z = 0; z < (g)->q_alloc; z++) { \
if ((g)->q_regs[z] && *((g)->q_regs[z])) { \
(t)->q_regs[z] = alloc_lbuf(f); \
memcpy((t)->q_regs[z], (g)->q_regs[z], (g)->q_lens[z] + 1); \
(t)->q_lens[z] = (g)->q_lens[z]; \
} \
} \
} \
if ((g) && (g)->xr_alloc) { \
for (z = 0; z < (g)->xr_alloc; z++) { \
if ((g)->x_names[z] && *((g)->x_names[z]) && \
(g)->x_regs[z] && *((g)->x_regs[z])) { \
(t)->x_names[z] = alloc_sbuf("glob.x_name"); \
strcpy((t)->x_names[z], (g)->x_names[z]); \
(t)->x_regs[z] = alloc_lbuf("glob.x_reg"); \
memcpy((t)->x_regs[z], (g)->x_regs[z], (g)->x_lens[z] + 1); \
(t)->x_lens[z] = (g)->x_lens[z]; \
} \
} \
} \
if (g) \
(t)->dirty = (g)->dirty; \
else \
(t)->dirty = 0; \
}
/* -------------------------------------------------------------------------* Module things.
*/
#define WALK_ALL_MODULES(mp) \
for (mp = mudstate.modules_list; mp != NULL; mp = mp->next)
/* Syntax: DLSYM(<handler>, <module name>, <function name>, <prototype>) */
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783

Saturday, June 16, 2012 11:10 PM

#define DLSYM(h,m,x,p) \
(void (*)p)lt_dlsym((h), tprintf("mod_%s_%s", (m), (x)))
#define DLSYM_INT(h,m,x,p) \
(int (*)p)lt_dlsym((h), tprintf("mod_%s_%s", (m), (x)))
#define DLSYM_VAR(h,m,x,p) \
(p)lt_dlsym((h), tprintf("mod_%s_%s", (m), (x)))
/* Syntax: CALL_ALL_MODULES(<name of function>, (<args>))
* Call all modules defined for this symbol.
*/
#define CALL_ALL_MODULES(xfn,args) \
{ \
MODULE *cam__mp; \
WALK_ALL_MODULES(cam__mp) { \
if (cam__mp->xfn) { \
(*(cam__mp->xfn))args; \
} \
} \
}
#define CALL_ALL_MODULES_NOCACHE(xfn,proto,args) \
{ \
MODULE *cam__mp; \
void (*cam__ip)proto; \
WALK_ALL_MODULES(cam__mp) { \
if ((cam__ip = DLSYM(cam__mp->handle, cam__mp->modname, xfn, proto)) != NULL) \
(*cam__ip)args; \
} \
}
/* Syntax: CALL_SOME_MODULES(<return value variable>,
*
<name of function>, (<args>))
* Call modules in sequence until we get back a non-zero value.
*/
#define CALL_SOME_MODULES(rv,xfn,args) \
{ \
MODULE *csm__mp; \
for (csm__mp = mudstate.modules_list, rv = 0; \
(csm__mp != NULL) && !rv; \
csm__mp = csm__mp->next) { \
if (csm__mp->xfn) { \
rv = (*(csm__mp->xfn))args; \
} \
} \
}
/* -------------------------------------------------------------------------* String things.
*/

-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\externs.h

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

Saturday, June 16, 2012 11:10 PM

/* Copies a string, and sets its length, not including the terminating null
* character, in another variable. Note that it is assumed that the source
* string is null-terminated.
* Takes: string to copy to, string to copy from, length (pointer to int)
*/
#define StrCopyLen(scl__dest,scl__src,scl__len) \
*(scl__len) = strlen(scl__src); \
memcpy(scl__dest,scl__src,(int) *(scl__len) + 1);
/* Copies a string of known length, and null-terminates it.
* Takes: pointer to copy to, pointer to copy from, length
*/
#define StrCopyKnown(scl__dest,scl__src,scl__len) \
memcpy(scl__dest,scl__src,scl__len); \
scl__dest[scl__len] = '\0';
/* Various macros for writing common string sequences. */
#define
#define
#define
#define
#define
#define

safe_crlf(b,p)
safe_known_str("\r\n",2,(b),(p))
safe_ansi_normal(b,p)
safe_known_str(ANSI_NORMAL,4,(b),(p))
safe_nothing(b,p)
safe_known_str("#-1",3,(b),(p))
safe_noperm(b,p)
safe_known_str("#-1 PERMISSION DENIED",21,(b),(p))
safe_nomatch(b,p)
safe_known_str("#-1 NO MATCH",12,(b),(p))
safe_bool(b,p,n)
safe_chr(((n) ? '1' : '0'),(b),(p))

#define safe_dbref(b,p,n) \
safe_chr('#',(b),(p)); \
safe_ltos((b),(p),(n));
#endif /* __EXTERNS_H */

-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\file_c.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:45 PM

/* file_c.c - File cache management */


/* $Id: file_c.c,v 1.10 2000/11/30 08:21:16 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include "command.h"
/* required by code */
#include "file_c.h" /* required by code */
typedef struct filecache_hdr FCACHE;
typedef struct filecache_block_hdr FBLKHDR;
typedef struct filecache_block FBLOCK;
struct filecache_hdr {
char **filename;
FBLOCK *fileblock;
const char *desc;
};
struct filecache_block {
struct filecache_block_hdr {
struct filecache_block *nxt;
int nchars;
} hdr;
char data[MBUF_SIZE - sizeof(FBLKHDR)];
};
#define FBLOCK_SIZE (MBUF_SIZE - sizeof(FBLKHDR))
/* *INDENT-OFF* */
FCACHE fcache[] = {
{ &mudconf.conn_file,
{ &mudconf.site_file,
{ &mudconf.down_file,
{ &mudconf.full_file,
{ &mudconf.guest_file,
{ &mudconf.creg_file,
{ &mudconf.crea_file,
{ &mudconf.regf_file,
{ &mudconf.motd_file,
{ &mudconf.wizmotd_file,
{ &mudconf.quit_file,
#ifdef PUEBLO_SUPPORT

NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,

"Conn" },
"Conn/Badsite" },
"Conn/Down" },
"Conn/Full" },
"Conn/Guest" },
"Conn/Reg" },
"Crea/Newuser" },
"Crea/RegFail" },
"Motd" },
"Wizmotd" },
"Quit" },

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\file_c.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:45 PM

{ &mudconf.htmlconn_file,
NULL,
"Conn/Html"},
#endif
{ NULL,
NULL,
NULL }};
NAMETAB list_files[] = {
{(char *)"badsite_connect", 1, CA_WIZARD, FC_CONN_SITE},
{(char *)"connect",
2, CA_WIZARD, FC_CONN},
{(char *)"create_register", 2, CA_WIZARD, FC_CREA_REG},
{(char *)"down",
1, CA_WIZARD, FC_CONN_DOWN},
{(char *)"full",
1, CA_WIZARD, FC_CONN_FULL},
{(char *)"guest_motd",
1, CA_WIZARD, FC_CONN_GUEST},
#ifdef PUEBLO_SUPPORT
{(char *)"html_connect",
1, CA_WIZARD, FC_CONN_HTML},
#endif
{(char *)"motd",
1, CA_WIZARD, FC_MOTD},
{(char *)"newuser",
1, CA_WIZARD, FC_CREA_NEW},
{(char *)"quit",
1, CA_WIZARD, FC_QUIT},
{(char *)"register_connect",
1, CA_WIZARD, FC_CONN_REG},
{(char *)"wizard_motd",
1, CA_WIZARD, FC_WIZMOTD},
{ NULL,
0, 0,
0}};
/* *INDENT-ON* */
void do_list_file(player, cause, extra, arg)
dbref player, cause;
int extra;
char *arg;
{
int flagvalue;

flagvalue = search_nametab(player, list_files, arg);


if (flagvalue < 0) {
display_nametab(player, list_files,
(char *)"Unknown file. Use one of:", 1);
return;
}
fcache_send(player, flagvalue);

static FBLOCK *fcache_fill(fp, ch)


FBLOCK *fp;
char ch;
{
FBLOCK *tfp;
if (fp->hdr.nchars >= (MBUF_SIZE - sizeof(FBLKHDR))) {
/* We filled the current buffer.

Go get a new one. */

tfp = fp;
fp = (FBLOCK *) alloc_mbuf("fcache_fill");
fp->hdr.nxt = NULL;
fp->hdr.nchars = 0;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\file_c.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:45 PM

tfp->hdr.nxt = fp;
}
fp->data[fp->hdr.nchars++] = ch;
return fp;

static int fcache_read(cp, filename)


FBLOCK **cp;
char *filename;
{
int n, nmax, tchars, fd;
char *buff;
FBLOCK *fp, *tfp;
/* Free a prior buffer chain */
fp = *cp;
while (fp != NULL) {
tfp = fp->hdr.nxt;
free_mbuf(fp);
fp = tfp;
}
*cp = NULL;
/* Read the text file into a new chain */
if ((fd = tf_open(filename, O_RDONLY)) == -1) {
/* Failure: log the event */
STARTLOG(LOG_PROBLEMS, "FIL", "OPEN")
log_printf("Couldn't open file '%s'.", filename);
ENDLOG
tf_close(fd);
return -1;

}
buff = alloc_lbuf("fcache_read.temp");

/* Set up the initial cache buffer to make things easier */


fp = (FBLOCK *) alloc_mbuf("fcache_read.first");
fp->hdr.nxt = NULL;
fp->hdr.nchars = 0;
*cp = fp;
tchars = 0;
/* Process the file, one lbuf at a time */
nmax = read(fd, buff, LBUF_SIZE);
while (nmax > 0) {
for (n = 0; n < nmax; n++) {
switch (buff[n]) {
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\file_c.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:45 PM

case '\n':
fp = fcache_fill(fp, '\r');
fp = fcache_fill(fp, '\n');
tchars += 2;
case '\0':
case '\r':
break;
default:
fp = fcache_fill(fp, buff[n]);
tchars++;
}

}
nmax = read(fd, buff, LBUF_SIZE);

}
free_lbuf(buff);
tf_close(fd);

/* If we didn't read anything in, toss the initial buffer */

if (fp->hdr.nchars == 0) {
*cp = NULL;
free_mbuf(fp);
}
return tchars;

void fcache_rawdump(fd, num)


int fd, num;
{
int cnt, remaining;
char *start;
FBLOCK *fp;
if ((num < 0) || (num > FC_LAST))
return;
fp = fcache[num].fileblock;
while (fp != NULL) {
start = fp->data;
remaining = fp->hdr.nchars;
while (remaining > 0) {
cnt = WRITE(fd, start, remaining);
if (cnt < 0)
return;
remaining -= cnt;
start += cnt;

}
fp = fp->hdr.nxt;

}
return;

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\file_c.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:45 PM

void fcache_dump(d, num)


DESC *d;
int num;
{
FBLOCK *fp;
if ((num < 0) || (num > FC_LAST))
return;
fp = fcache[num].fileblock;

while (fp != NULL) {


queue_write(d, fp->data, fp->hdr.nchars);
fp = fp->hdr.nxt;
}

void fcache_send(player, num)


dbref player;
int num;
{
DESC *d;

DESC_ITER_PLAYER(player, d) {
fcache_dump(d, num);
}

void fcache_load(player)
dbref player;
{
FCACHE *fp;
char *buff, *bufc, *sbuf;
int i;
buff = bufc = alloc_lbuf("fcache_load.lbuf");
sbuf = alloc_sbuf("fcache_load.sbuf");
for (fp = fcache; fp->filename; fp++) {
i = fcache_read(&fp->fileblock, *(fp->filename));
if ((player != NOTHING) && !Quiet(player)) {
sprintf(sbuf, "%d", i);
if (fp == fcache)
safe_str((char *)"File sizes: ", buff, &bufc);
else
safe_str((char *)" ", buff, &bufc);
safe_str((char *)fp->desc, buff, &bufc);
safe_str((char *)"...", buff, &bufc);
safe_str(sbuf, buff, &bufc);
}
}
*bufc = '\0';
if ((player != NOTHING) && !Quiet(player)) {
notify(player, buff);
}
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\file_c.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279

Saturday, June 16, 2012 11:45 PM

free_lbuf(buff);
free_sbuf(sbuf);

void NDECL(fcache_init)
{
FCACHE *fp;

for (fp = fcache; fp->filename; fp++) {


fp->fileblock = NULL;
}
fcache_load(NOTHING);

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\file_c.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

Saturday, June 16, 2012 11:10 PM

/* file_c.h -- File cache header file */


/* $Id: file_c.h,v 1.5 2000/05/29 22:20:23 rmg Exp $ */
#include "copyright.h"
#ifndef __FILE_C_H
#define __FILE_C_H
/* File caches.

These _must_ track the fcache array in file_c.c */

#define FC_CONN
0
#define FC_CONN_SITE
1
#define FC_CONN_DOWN
2
#define FC_CONN_FULL
3
#define FC_CONN_GUEST
4
#define FC_CONN_REG 5
#define FC_CREA_NEW 6
#define FC_CREA_REG 7
#define FC_MOTD
8
#define FC_WIZMOTD 9
#define FC_QUIT
10
#ifdef PUEBLO_SUPPORT
#define FC_CONN_HTML
11
#define FC_LAST
11
#else
#define FC_LAST
10
#endif /* PUEBLO_SUPPORT */
/* File cache routines */
extern
extern
extern
extern
extern

void
void
void
void
void

FDECL(fcache_rawdump, (int fd, int num));


FDECL(fcache_dump, (DESC *d, int num));
FDECL(fcache_send, (dbref, int));
FDECL(fcache_load, (dbref));
NDECL(fcache_init);

#endif /* __FILE_C_H */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:44 PM

/* flags.c - flag manipulation routines */


/* $Id: flags.c,v 1.65 2009/01/11 19:04:34 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"command.h"
/* required by code */
"powers.h" /* required by code */
"match.h" /* required by code */
"ansi.h"
/* required by code */

/* --------------------------------------------------------------------------* fh_any: set or clear indicated bit, no security checking


*/
int fh_any(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
/* Never let God drop his own wizbit. */

if (God(target) && reset && (flag == WIZARD) &&


!(fflags & FLAG_WORD2) && !(fflags & FLAG_WORD3)) {
notify(player, "You cannot make God mortal." );
return 0;

/* Otherwise we can go do it. */


if (fflags & FLAG_WORD3) {
if (reset) {
s_Flags3(target, Flags3(target)
} else {
s_Flags3(target, Flags3(target)
}
} else if (fflags & FLAG_WORD2) {
if (reset) {
s_Flags2(target, Flags2(target)
} else {
s_Flags2(target, Flags2(target)
}
} else {
if (reset) {
-1-

& ~flag);
| flag);

& ~flag);
| flag);

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:44 PM

s_Flags(target, Flags(target) & ~flag);


} else {
s_Flags(target, Flags(target) | flag);
}

}
return 1;

/* --------------------------------------------------------------------------* fh_god: only GOD may set or clear the bit


*/
int fh_god(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
if (!God(player))
return 0;
return (fh_any(target, player, flag, fflags, reset));
}
/* --------------------------------------------------------------------------* fh_wiz: only WIZARDS (or GOD) may set or clear the bit
*/
int fh_wiz(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
if (!Wizard(player) && !God(player))
return 0;
return (fh_any(target, player, flag, fflags, reset));
}
/* --------------------------------------------------------------------------* fh_wizroy: only WIZARDS, ROYALTY, (or GOD) may set or clear the bit
*/
int fh_wizroy(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
if (!WizRoy(player) && !God(player))
return 0;
return (fh_any(target, player, flag, fflags, reset));
}
/* --------------------------------------------------------------------------* fh_restrict_player: Only Wizards can set this on players, but
* ordinary players can set it on other types of objects.
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:44 PM

*/
int fh_restrict_player(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
if (isPlayer(target) && !Wizard(player) && !God(player))
return 0;
return (fh_any(target, player, flag, fflags, reset));
}
/* --------------------------------------------------------------------------* fh_privileged: You can set this flag on a non-player object, if you
* yourself have this flag and are a player who owns themselves (i.e.,
* no robots). Only God can set this on a player.
*/
int fh_privileged(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
int has_it;
if (!God(player)) {
if (!isPlayer(player) || (player != Owner(player)))
return 0;
if (isPlayer(target))
return 0;
if (fflags & FLAG_WORD3)
has_it = (Flags3(player) & flag) ? 1 : 0;
else if (fflags & FLAG_WORD2)
has_it = (Flags2(player) & flag) ? 1 : 0;
else
has_it = (Flags(player) & flag) ? 1 : 0;
if (!has_it)
return 0;
}
}

return (fh_any(target, player, flag, fflags, reset));

/* --------------------------------------------------------------------------* fh_inherit: only players may set or clear this bit.


*/
int fh_inherit(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:44 PM

int fflags, reset;


{
if (!Inherits(player))
return 0;
return (fh_any(target, player, flag, fflags, reset));
}
/* --------------------------------------------------------------------------* fh_dark_bit: manipulate the dark bit. Nonwizards may not set on players.
*/
int fh_dark_bit(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
if (!reset && isPlayer(target) && !((target == player) &&
Can_Hide(player)) &&
(!Wizard(player) && !God(player)))
return 0;
return (fh_any(target, player, flag, fflags, reset));
}
/* --------------------------------------------------------------------------* fh_going_bit: Manipulate the going bit. Can only be cleared on
* objects slated for destruction, by non-god. May only be set by god.
* Even god can't destroy nondestroyable objects.
*/
int fh_going_bit(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
if (Going(target) && reset && (Typeof(target) != TYPE_GARBAGE)) {
notify(player, "Your object has been spared from destruction." );
return (fh_any(target, player, flag, fflags, reset));
}
if (!God(player) || !destroyable(target))
return 0;
return (fh_any(target, player, flag, fflags, reset));
}
/* --------------------------------------------------------------------------* fh_hear_bit: set or clear bits that affect hearing.
*/
int fh_hear_bit(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
int could_hear;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:44 PM

int result;

could_hear = Hearer(target);
result = fh_any(target, player, flag, fflags, reset);
handle_ears(target, could_hear, Hearer(target));
return result;

/* --------------------------------------------------------------------------* fh_player_bit: Can set and reset this on everything but players.
*/
int fh_player_bit(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
if (isPlayer(target))
return 0;
return (fh_any(target, player, flag, fflags, reset));
}
/* --------------------------------------------------------------------------* fh_power_bit: Check power bit to set/reset.
*/
int fh_power_bit(target, player, flag, fflags, reset)
dbref target, player;
FLAG flag;
int fflags, reset;
{
if (flag & WATCHER) {
/* Wizards can set this on anything.
* Players with the Watch power can set this on themselves.
*/
if (Wizard(player) ||
((Owner(player) == Owner(target)) && Can_Watch(player)))
return (fh_any(target, player, flag, fflags, reset));
else
return 0;
}
}

return 0;

/* *INDENT-OFF* */
/* All flags names MUST be in uppercase! */
FLAGENT gen_flags[] = {
{"ABODE",
ABODE,
FLAG_WORD2, 0,

'A',
fh_any},
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:44 PM

{"BLIND",
BLIND,
'B',
FLAG_WORD2, 0,
fh_wiz},
{"CHOWN_OK",
CHOWN_OK,
'C',
0,
0,
fh_any},
{"DARK",
DARK,
'D',
0,
0,
fh_dark_bit},
{"FREE",
NODEFAULT, 'F',
FLAG_WORD3, 0,
fh_wiz},
{"GOING",
GOING,
'G',
0,
CA_NO_DECOMP,
fh_going_bit},
{"HAVEN",
HAVEN,
'H',
0,
0,
fh_any},
{"INHERIT",
INHERIT,
'I',
0,
0,
fh_inherit},
{"JUMP_OK",
JUMP_OK,
'J',
0,
0,
fh_any},
{"KEY",
KEY,
'K',
FLAG_WORD2, 0,
fh_any},
{"LINK_OK",
LINK_OK,
'L',
0,
0,
fh_any},
{"MONITOR",
MONITOR,
'M',
0,
0,
fh_hear_bit},
{"NOSPOOF",
NOSPOOF,
'N',
0,
CA_WIZARD,
fh_any},
{"OPAQUE",
OPAQUE,
'O',
0,
0,
fh_any},
{"QUIET",
QUIET,
'Q',
0,
0,
fh_any},
{"STICKY",
STICKY,
'S',
0,
0,
fh_any},
{"TRACE",
TRACE,
'T',
0,
0,
fh_any},
{"UNFINDABLE",
UNFINDABLE, 'U',
FLAG_WORD2, 0,
fh_any},
{"VISUAL",
VISUAL,
'V',
0,
0,
fh_any},
{"WIZARD",
WIZARD,
'W',
0,
0,
fh_god},
{"ANSI",
ANSI,
'X',
FLAG_WORD2,
0,
fh_any},
{"PARENT_OK",
PARENT_OK, 'Y',
FLAG_WORD2, 0,
fh_any},
{"ROYALTY",
ROYALTY,
'Z',
0,
0,
fh_wiz},
{"AUDIBLE",
HEARTHRU,
'a',
0,
0,
fh_hear_bit},
{"BOUNCE",
BOUNCE,
'b',
FLAG_WORD2,
0,
fh_any},
{"CONNECTED",
CONNECTED, 'c',
FLAG_WORD2, CA_NO_DECOMP,
fh_god},
{"DESTROY_OK",
DESTROY_OK, 'd',
0,
0,
fh_any},
{"ENTER_OK",
ENTER_OK,
'e',
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:44 PM

0,
0,
fh_any},
{"FIXED",
FIXED,
'f',
FLAG_WORD2,
0,
fh_restrict_player},
{"UNINSPECTED",
UNINSPECTED,
'g',
FLAG_WORD2,
0,
fh_wizroy},
{"HALTED",
HALT,
'h',
0,
0,
fh_any},
{"IMMORTAL",
IMMORTAL,
'i',
0,
0,
fh_wiz},
{"GAGGED",
GAGGED,
'j',
FLAG_WORD2, 0,
fh_wiz},
{"CONSTANT",
CONSTANT_ATTRS, 'k',
FLAG_WORD2, 0,
fh_wiz},
{"LIGHT",
LIGHT,
'l',
FLAG_WORD2, 0,
fh_any},
{"MYOPIC",
MYOPIC,
'm',
0,
0,
fh_any},
{"AUDITORIUM",
AUDITORIUM, 'n',
FLAG_WORD2, 0,
fh_any},
{"ZONE",
ZONE_PARENT,
'o',
FLAG_WORD2, 0,
fh_any},
{"PUPPET",
PUPPET,
'p',
0,
0,
fh_hear_bit},
{"TERSE",
TERSE,
'q',
0,
0,
fh_any},
{"ROBOT",
ROBOT,
'r',
0,
0,
fh_player_bit},
{"SAFE",
SAFE,
's',
0,
0,
fh_any},
{"TRANSPARENT",
SEETHRU,
't',
0,
0,
fh_any},
{"SUSPECT",
SUSPECT,
'u',
FLAG_WORD2, CA_WIZARD,
fh_wiz},
{"VERBOSE",
VERBOSE,
'v',
0,
0,
fh_any},
{"STAFF",
STAFF,
'w',
FLAG_WORD2, 0,
fh_wiz},
{"SLAVE",
SLAVE,
'x',
FLAG_WORD2,
CA_WIZARD,
fh_wiz},
{"ORPHAN",
ORPHAN,
'y',
FLAG_WORD3, 0,
fh_any},
{"CONTROL_OK",
CONTROL_OK, 'z',
FLAG_WORD2, 0,
fh_any},
{"STOP",
STOP_MATCH, '!',
FLAG_WORD2, 0,
fh_wiz},
{"COMMANDS",
HAS_COMMANDS,
'$',
FLAG_WORD2, 0,
fh_any},
{"PRESENCE",
PRESENCE,
'^',
FLAG_WORD3, 0,
fh_wiz},
{"NOBLEED",
NOBLEED,
'-',
FLAG_WORD2,
0,
fh_any},
{"VACATION",
VACATION,
'|',
FLAG_WORD2, 0,
fh_restrict_player},
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:44 PM

{"HEAD",

HEAD_FLAG,
'?',
FLAG_WORD2,
0,
fh_wiz},
{"WATCHER",
WATCHER,
'+',
FLAG_WORD2, 0,
fh_power_bit},
{"HAS_DAILY",
HAS_DAILY, '*',
FLAG_WORD2, CA_GOD|CA_NO_DECOMP,
fh_god},
{"HAS_STARTUP",
HAS_STARTUP,
'=',
0,
CA_GOD|CA_NO_DECOMP,
fh_god},
{"HAS_FORWARDLIST", HAS_FWDLIST,
'&',
FLAG_WORD2, CA_GOD|CA_NO_DECOMP,
fh_god},
{"HAS_LISTEN",
HAS_LISTEN, '@',
FLAG_WORD2, CA_GOD|CA_NO_DECOMP,
fh_god},
{"HAS_PROPDIR",
HAS_PROPDIR,
',',
FLAG_WORD3, CA_GOD|CA_NO_DECOMP,
fh_god},
{"PLAYER_MAILS",
PLAYER_MAILS,
'`',
FLAG_WORD2,
CA_GOD|CA_NO_DECOMP,
fh_god},
#ifdef PUEBLO_SUPPORT
{"HTML",
HTML,
'~',
FLAG_WORD2,
0,
fh_any},
#endif
{"REDIR_OK",
REDIR_OK,
'>',
FLAG_WORD3, 0,
fh_any},
{"HAS_REDIRECT",
HAS_REDIRECT,
'<',
FLAG_WORD3, CA_GOD|CA_NO_DECOMP,
fh_god},
{"HAS_DARKLOCK",
HAS_DARKLOCK,
'.',
FLAG_WORD3, CA_GOD|CA_NO_DECOMP,
fh_god},
{"SPEECHMOD",
HAS_SPEECHMOD, '"',
FLAG_WORD3, 0,
fh_any},
{"MARKER0",
MARK_0,
'0',
FLAG_WORD3, 0,
fh_god},
{"MARKER1",
MARK_1,
'1',
FLAG_WORD3, 0,
fh_god},
{"MARKER2",
MARK_2,
'2',
FLAG_WORD3, 0,
fh_god},
{"MARKER3",
MARK_3,
'3',
FLAG_WORD3, 0,
fh_god},
{"MARKER4",
MARK_4,
'4',
FLAG_WORD3, 0,
fh_god},
{"MARKER5",
MARK_5,
'5',
FLAG_WORD3, 0,
fh_god},
{"MARKER6",
MARK_6,
'6',
FLAG_WORD3, 0,
fh_god},
{"MARKER7",
MARK_7,
'7',
FLAG_WORD3, 0,
fh_god},
{"MARKER8",
MARK_8,
'8',
FLAG_WORD3, 0,
fh_god},
{"MARKER9",
MARK_9,
'9',
FLAG_WORD3, 0,
fh_god},
{ NULL,
0,
' ',
0,
0,
NULL}};
OBJENT object_types[8] = {
{"ROOM",
'R', CA_PUBLIC, OF_CONTENTS|OF_EXITS|OF_DROPTO|OF_HOME},
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:44 PM

{"THING",
' ', CA_PUBLIC,
OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_SIBLINGS},
{"EXIT",
'E', CA_PUBLIC, OF_SIBLINGS},
{"PLAYER", 'P', CA_PUBLIC,
OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_OWNER|OF_SIBLINGS},
{"TYPE5",
'+', CA_GOD,
0},
{"GARBAGE", '_', CA_PUBLIC,
OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_SIBLINGS},
{"GARBAGE", '#', CA_GOD,
0}};
/* *INDENT-ON* */

/* --------------------------------------------------------------------------* init_flagtab: initialize flag hash tables.


*/
void NDECL(init_flagtab)
{
FLAGENT *fp;
hashinit(&mudstate.flags_htab, 100 * HASH_FACTOR, HT_STR|HT_KEYREF);

for (fp = gen_flags; fp->flagname; fp++) {


hashadd((char *)fp->flagname, (int *)fp, &mudstate.flags_htab, 0);
}

/* --------------------------------------------------------------------------* display_flags: display available flags.


*/
void display_flagtab(player)
dbref player;
{
char *buf, *bp;
FLAGENT *fp;
bp = buf = alloc_lbuf("display_flagtab");
safe_str((char *)"Flags:", buf, &bp);
for (fp = gen_flags; fp->flagname; fp++) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
continue;
if ((fp->listperm & CA_GOD) && !God(player))
continue;
safe_chr(' ', buf, &bp);
safe_str((char *)fp->flagname, buf, &bp);
safe_chr('(', buf, &bp);
safe_chr(fp->flaglett, buf, &bp);
safe_chr(')', buf, &bp);
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:44 PM

}
*bp = '\0';
notify(player, buf);
free_lbuf(buf);

FLAGENT *find_flag(thing, flagname)


dbref thing;
char *flagname;
{
char *cp;
/* Make sure the flag name is valid */

for (cp = flagname; *cp; cp++)


*cp = toupper(*cp);
return (FLAGENT *) hashfind(flagname, &mudstate.flags_htab);

/* --------------------------------------------------------------------------* flag_set: Set or clear a specified flag on an object.


*/
void flag_set(target, player, flag, key)
dbref target, player;
char *flag;
int key;
{
FLAGENT *fp;
int negate, result;
/* Trim spaces, and handle the negation character */
negate = 0;
while (*flag
flag++;
if (*flag ==
negate =
flag++;
}
while (*flag
flag++;

&& isspace(*flag))
'!') {
1;
&& isspace(*flag))

/* Make sure a flag name was specified */


if (*flag == '\0') {
if (negate)
notify(player, "You must specify a flag to clear." );
else
notify(player, "You must specify a flag to set." );
return;
}
fp = find_flag(target, flag);
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:44 PM

if (fp == NULL) {
notify(player, "I don't understand that flag." );
return;
}
/* Invoke the flag handler, and print feedback */

result = fp->handler(target, player, fp->flagvalue,


fp->flagflag, negate);
if (!result)
notify(player, NOPERM_MESSAGE);
else if (!(key & SET_QUIET) && !Quiet(player)) {
notify(player, (negate ? "Cleared." : "Set."));
s_Modified(target);
}
return;

/* --------------------------------------------------------------------------* decode_flags: converts a flag set into corresponding letters.


*/
char *decode_flags(player, flagset)
dbref player;
FLAGSET flagset;
{
char *buf, *bp, *s;
FLAGENT *fp;
int flagtype;
FLAG fv;
buf = bp = s = alloc_sbuf("decode_flags");
*bp = '\0';
flagtype = (flagset.word1 & TYPE_MASK);
if (object_types[flagtype].lett != ' ')
safe_sb_chr(object_types[flagtype].lett, buf, &bp);
for (fp = gen_flags; fp->flagname; fp++) {
if (fp->flagflag & FLAG_WORD3)
fv = flagset.word3;
else if (fp->flagflag & FLAG_WORD2)
fv = flagset.word2;
else
fv = flagset.word1;
if (fv & fp->flagvalue) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
continue;
if ((fp->listperm & CA_GOD) && !God(player))
continue;

safe_sb_chr(fp->flaglett, buf, &bp);

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:44 PM

*bp = '\0';
return buf;

/* --------------------------------------------------------------------------* unparse_flags: converts a thing's flags into corresponding letters.


*/
char *unparse_flags(player, thing)
dbref player, thing;
{
char *buf, *bp, *s;
FLAGENT *fp;
int flagtype;
FLAG fv, flagword, flag2word, flag3word;
buf = bp = s = alloc_sbuf("unparse_flags");
*bp = '\0';
if (!Good_obj(player) || !Good_obj(thing)) {
strcpy(buf, "#-2 ERROR");
return buf;
}
flagword = Flags(thing);
flag2word = Flags2(thing);
flag3word = Flags3(thing);
flagtype = (flagword & TYPE_MASK);
if (object_types[flagtype].lett != ' ')
safe_sb_chr(object_types[flagtype].lett, buf, &bp);
for (fp = gen_flags; fp->flagname; fp++) {
if (fp->flagflag & FLAG_WORD3)
fv = flag3word;
else if (fp->flagflag & FLAG_WORD2)
fv = flag2word;
else
fv = flagword;
if (fv & fp->flagvalue) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
continue;
if ((fp->listperm & CA_GOD) && !God(player))
continue;
/* don't show CONNECT on dark wizards to mortals */
if ((flagtype == TYPE_PLAYER) && isConnFlag(fp) &&
Can_Hide(thing) && Hidden(thing) &&
!See_Hidden(player))
continue;
/* Check if this is a marker flag and we're at
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:44 PM

* the beginning of a buffer. If so, we need


* to insert a separator character first so
* we don't end up running the dbref number
* into the flags.
*/
if ((s == bp) && isMarkerFlag(fp))
safe_sb_chr(MARK_FLAG_SEP, buf, &bp);

safe_sb_chr(fp->flaglett, buf, &bp);

*bp = '\0';
return buf;

/* --------------------------------------------------------------------------* has_flag: does object have flag visible to player?


*/
int has_flag(player, it, flagname)
dbref player, it;
char *flagname;
{
FLAGENT *fp;
FLAG fv;
fp = find_flag(it, flagname);
if (fp == NULL) {
/* find_flag() uppercases the string */
if (!strcmp(flagname, "PLAYER"))
return isPlayer(it);
if (!strcmp(flagname, "THING"))
return isThing(it);
if (!strcmp(flagname, "ROOM"))
return isRoom(it);
if (!strcmp(flagname, "EXIT"))
return isExit(it);
return 0;
}
if (fp->flagflag & FLAG_WORD3)
fv = Flags3(it);
else if (fp->flagflag & FLAG_WORD2)
fv = Flags2(it);
else
fv = Flags(it);
if (fv & fp->flagvalue) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
return 0;
if ((fp->listperm & CA_GOD) && !God(player))
return 0;
/* don't show CONNECT on dark wizards to mortals */
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:44 PM

if (isPlayer(it) && isConnFlag(fp) &&


Can_Hide(it) && Hidden(it) &&
!See_Hidden(player))
return 0;
return 1;

}
return 0;

/* --------------------------------------------------------------------------* flag_description: Return an mbuf containing the type and flags on thing.
*/
char *flag_description(player, target)
dbref player, target;
{
char *buff, *bp;
FLAGENT *fp;
int otype;
FLAG fv;
/* Allocate the return buffer */
otype = Typeof(target);
bp = buff = alloc_mbuf("flag_description");
/* Store the header strings and object type */
safe_mb_str((char *)"Type: ", buff, &bp);
safe_mb_str((char *)object_types[otype].name, buff, &bp);
safe_mb_str((char *)" Flags:", buff, &bp);
if (object_types[otype].perm != CA_PUBLIC) {
return buff;
}
/* Store the type-invariant flags */
for (fp = gen_flags; fp->flagname; fp++) {
if (fp->flagflag & FLAG_WORD3)
fv = Flags3(target);
else if (fp->flagflag & FLAG_WORD2)
fv = Flags2(target);
else
fv = Flags(target);
if (fv & fp->flagvalue) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
continue;
if ((fp->listperm & CA_GOD) && !God(player))
continue;
/* don't show CONNECT on dark wizards to mortals */
if (isPlayer(target) && isConnFlag(fp) &&
Can_Hide(target) && Hidden(target) &&
!See_Hidden(player))
continue;
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

}
}

Saturday, June 16, 2012 11:44 PM

safe_mb_chr(' ', buff, &bp);


safe_mb_str((char *)fp->flagname, buff, &bp);

return buff;

/*
* --------------------------------------------------------------------------* * Return an lbuf containing the name and number of an object
*/
char *unparse_object_numonly(target)
dbref target;
{
char *buf, *bp;

buf = alloc_lbuf("unparse_object_numonly");
if (target == NOTHING) {
strcpy(buf, "*NOTHING*");
} else if (target == HOME) {
strcpy(buf, "*HOME*");
} else if (target == AMBIGUOUS) {
strcpy(buf, "*VARIABLE*");
} else if (!Good_obj(target)) {
sprintf(buf, "*ILLEGAL*(#%d)", target);
} else {
bp = buf;
safe_tprintf_str(buf, &bp, "%s(#%d)", Name(target), target);
}
return buf;

/* --------------------------------------------------------------------------* Return an lbuf pointing to the object name and possibly the db# and flags
*/
char *unparse_object(player, target, obey_myopic)
dbref player, target;
int obey_myopic;
{
char *buf, *fp, *bp;
int exam;
buf = alloc_lbuf("unparse_object");
if (target == NOTHING) {
strcpy(buf, "*NOTHING*");
} else if (target == HOME) {
strcpy(buf, "*HOME*");
} else if (target == AMBIGUOUS) {
strcpy(buf, "*VARIABLE*");
} else if (isGarbage(target)) {
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:44 PM

fp = unparse_flags(player, target);
bp = buf;
safe_tprintf_str(buf, &bp, "*GARBAGE*(#%d%s)", target, fp);
free_sbuf(fp);
} else if (!Good_obj(target)) {
sprintf(buf, "*ILLEGAL*(#%d)", target);
} else {
if (obey_myopic)
exam = MyopicExam(player, target);
else
exam = Examinable(player, target);
if (exam ||
(Flags(target) & (CHOWN_OK | JUMP_OK | LINK_OK | DESTROY_OK)) ||
(Flags2(target) & ABODE)) {
/* show everything */
fp = unparse_flags(player, target);
bp = buf;
safe_tprintf_str(buf, &bp, "%s(#%d%s)",
Name(target), target, fp);
free_sbuf(fp);
} else {
/* show only the name. */
strcpy(buf, Name(target));
}

}
return buf;

/* --------------------------------------------------------------------------* letter_to_flag: Given a one-character flag abbrev, return the flag pointer.
*/
FLAGENT *letter_to_flag(this_letter)
char this_letter;
{
FLAGENT *fp;

for (fp = gen_flags; fp->flagname; fp++) {


if (fp->flaglett == this_letter)
return fp;
}
return NULL;

/* --------------------------------------------------------------------------* cf_flag_access: Modify who can set a flag.


*/
CF_HAND(cf_flag_access)
{
char *fstr, *permstr, *tokst;
FLAGENT *fp;
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:44 PM

fstr = strtok_r(str, " \t=,", &tokst);


permstr = strtok_r(NULL, " \t=,", &tokst);
if (!fstr || !*fstr || !permstr || !*permstr) {
return -1;
}
if ((fp = find_flag(GOD, fstr)) == NULL) {
cf_log_notfound(player, cmd, "No such flag", fstr);
return -1;
}
/* Don't change the handlers on special things. */
if ((fp->handler != fh_any) &&
(fp->handler != fh_wizroy) &&
(fp->handler != fh_wiz) &&
(fp->handler != fh_god) &&
(fp->handler != fh_restrict_player) &&
(fp->handler != fh_privileged)) {
STARTLOG(LOG_CONFIGMODS, "CFG", "PERM")
log_printf("Cannot change access for flag: %s" , fp->flagname);
ENDLOG
return -1;
}

if (!strcmp(permstr, (char *) "any")) {


fp->handler = fh_any;
} else if (!strcmp(permstr, (char *) "royalty")) {
fp->handler = fh_wizroy;
} else if (!strcmp(permstr, (char *) "wizard")) {
fp->handler = fh_wiz;
} else if (!strcmp(permstr, (char *) "god")) {
fp->handler = fh_god;
} else if (!strcmp(permstr, (char *) "restrict_player")) {
fp->handler = fh_restrict_player;
} else if (!strcmp(permstr, (char *) "privileged")) {
fp->handler = fh_privileged;
} else {
cf_log_notfound(player, cmd, "Flag access", permstr);
return -1;
}
return 0;

/* --------------------------------------------------------------------------* cf_flag_name: Modify the name of a user-defined flag.


*/
CF_HAND(cf_flag_name)
{
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:44 PM

char *numstr, *namestr, *tokst;


FLAGENT *fp;
int flagnum = -1;
char *flagstr, *cp;
numstr = strtok_r(str, " \t=,", &tokst);
namestr = strtok_r(NULL, " \t=,", &tokst);
if (numstr && (strlen(numstr) == 1)) {
flagnum = atoi(numstr);
}
if ((flagnum < 0) || (flagnum > 9)) {
cf_log_notfound(player, cmd, "Not a marker flag", numstr);
return -1;
}
if ((fp = letter_to_flag(*numstr)) == NULL) {
cf_log_notfound(player, cmd, "Marker flag", numstr);
return -1;
}
/* Our conditions: The flag name MUST start with an underscore.
* It must not conflict with the name of any existing flag.
* There is a KNOWN MEMORY LEAK here -- if you name the flag and
* rename it later, the old bit of memory for the name won't get
* freed. This should pretty much never happen, since you're not
* going to run around arbitrarily giving your flags new names all
* the time.
*/
flagstr = XSTRDUP(tprintf("_%s", namestr), "cf_flag_name");
if (strlen(flagstr) > 31) {
cf_log_syntax(player, cmd, "Marker flag name too long: %s" , namestr);
XFREE(flagstr, "cf_flag_name");
}
for (cp = flagstr; cp && *cp; cp++) {
if (!isalnum(*cp) && (*cp != '_')) {
cf_log_syntax(player, cmd, "Illegal marker flag name: %s" ,
namestr);
XFREE(flagstr, "cf_flag_name");
return -1;
}
*cp = tolower(*cp);
}
if (hashfind(flagstr, &mudstate.flags_htab)) {
XFREE(flagstr, "cf_flag_name");
cf_log_syntax(player, cmd, "Marker flag name in use: %s" , namestr);
return -1;
}
for (cp = flagstr; cp && *cp; cp++)
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:44 PM

*cp = toupper(*cp);
fp->flagname = (const char *) flagstr;
hashadd((char *)fp->flagname, (int *) fp, &mudstate.flags_htab, 0);
}

return 0;

/* --------------------------------------------------------------------------* convert_flags: convert a list of flag letters into its bit pattern.
* Also set the type qualifier if specified and not already set.
*/
int convert_flags(player, flaglist, fset, p_type)
dbref player;
char *flaglist;
FLAGSET *fset;
FLAG *p_type;
{
int i, handled;
char *s;
FLAG flag1mask, flag2mask, flag3mask, type;
FLAGENT *fp;
flag1mask = flag2mask = flag3mask = 0;
type = NOTYPE;
for (s = flaglist; *s; s++) {
handled = 0;
/* Check for object type */
for (i = 0; (i <= 7) && !handled; i++) {
if ((object_types[i].lett == *s) &&
!(((object_types[i].perm & CA_WIZARD) &&
!Wizard(player)) ||
((object_types[i].perm & CA_GOD) &&
!God(player)))) {
if ((type != NOTYPE) && (type != i)) {
notify(player,
tprintf("%c: Conflicting type specifications." ,
*s));
return 0;
}
type = i;
handled = 1;
}
}
/* Check generic flags */
if (handled)
continue;
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:44 PM

for (fp = gen_flags; (fp->flagname) && !handled; fp++) {


if ((fp->flaglett == *s) &&
!(((fp->listperm & CA_WIZARD) &&
!Wizard(player)) ||
((fp->listperm & CA_GOD) &&
!God(player)))) {
if (fp->flagflag & FLAG_WORD3)
flag3mask |= fp->flagvalue;
else if (fp->flagflag & FLAG_WORD2)
flag2mask |= fp->flagvalue;
else
flag1mask |= fp->flagvalue;
handled = 1;
}
}

if (!handled) {
notify(player,
tprintf("%c: Flag unknown or not valid for specified object type" ,
*s));
return 0;
}

/* return flags to search for and type */

(*fset).word1 = flag1mask;
(*fset).word2 = flag2mask;
(*fset).word3 = flag3mask;
*p_type = type;
return 1;

/* --------------------------------------------------------------------------* decompile_flags: Produce commands to set flags on target.


*/
void decompile_flags(player, thing, thingname)
dbref player, thing;
char *thingname;
{
FLAG f1, f2, f3;
FLAGENT *fp;
/* Report generic flags */
f1 = Flags(thing);
f2 = Flags2(thing);
f3 = Flags3(thing);
for (fp = gen_flags; fp->flagname; fp++) {
/* Skip if we shouldn't decompile this flag */
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089

Saturday, June 16, 2012 11:44 PM

if (fp->listperm & CA_NO_DECOMP)


continue;
/* Skip if this flag is not set */
if (fp->flagflag & FLAG_WORD3) {
if (!(f3 & fp->flagvalue))
continue;
} else if (fp->flagflag & FLAG_WORD2) {
if (!(f2 & fp->flagvalue))
continue;
} else {
if (!(f1 & fp->flagvalue))
continue;
}
/* Skip if we can't see this flag */
if (!check_access(player, fp->listperm))
continue;
/* We made it this far, report this flag */

notify(player, tprintf("@set %s=%s", strip_ansi(thingname), fp->flagname));

-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:09 PM

/* flags.h - object flags */


/* $Id: flags.h,v 1.57 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#ifndef __FLAGS_H
#define __FLAGS_H
#define FLAG_WORD2
#define FLAG_WORD3

0x1 /* 2nd word of flags. */


0x2 /* 3rd word of flags. */

/* Object types */
#define TYPE_ROOM
0x0
#define TYPE_THING 0x1
#define TYPE_EXIT
0x2
#define TYPE_PLAYER
#define TYPE_ZONE
#define TYPE_GARBAGE
#define GOODTYPE
0x5
#define NOTYPE
0x7
#define TYPE_MASK
0x7

0x3
0x4
0x5
/* Values less than this pass Good_obj check */

/* First word of flags */


#define SEETHRU
0x00000008
#define WIZARD
0x00000010
#define LINK_OK
0x00000020
#define DARK
0x00000040
#define JUMP_OK
0x00000080
#define STICKY
0x00000100
#define DESTROY_OK 0x00000200
#define HAVEN
0x00000400
#define QUIET
0x00000800
#define HALT
0x00001000
#define TRACE
0x00002000
#define GOING
0x00004000
#define MONITOR
0x00008000
#define MYOPIC
0x00010000
#define PUPPET
0x00020000
#define CHOWN_OK
0x00040000
#define ENTER_OK
0x00080000
#define VISUAL
0x00100000
#define IMMORTAL
0x00200000
#define HAS_STARTUP 0x00400000
#define OPAQUE
0x00800000
#define VERBOSE
0x01000000
#define INHERIT
0x02000000
#define NOSPOOF
0x04000000
#define ROBOT
0x08000000
#define SAFE
0x10000000
#define ROYALTY
0x20000000
#define HEARTHRU
0x40000000
#define TERSE
0x80000000

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

Can see through to the other side */


gets automatic control */
anybody can link to this room */
Don't show contents or presence */
Others may @tel here */
Object goes home when dropped */
Others may @destroy */
No killing here, or no pages */
Prevent 'feelgood' messages */
object cannot perform actions */
Generate evaluation trace output */
object is available for recycling */
Process ^x:action listens on obj? */
See things as nonowner/nonwizard */
Relays ALL messages to owner */
Object may be @chowned freely */
Object may be ENTERed */
Everyone can see properties */
Object can't be killed */
Load some attrs at startup */
Can't see inside */
Tells owner everything it does. */
Gets owner's privs. (i.e. Wiz) */
Report originator of all actions. */
Player is a ROBOT */
Need /override to @destroy */
Sees like a wiz, but ca't modify */
Can hear out of this obj or exit */
Only show room name on look */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:09 PM

/* Second word of flags */


#define KEY
0x00000001 /* No puppets */
#define ABODE
0x00000002 /* May @set home here */
#define FLOATING
0x00000004 /* -- Legacy -- */
#define UNFINDABLE 0x00000008 /* Can't loc() from afar */
#define PARENT_OK
0x00000010 /* Others may @parent to me */
#define LIGHT
0x00000020 /* Visible in dark places */
#define HAS_LISTEN 0x00000040 /* Internal: LISTEN attr set */
#define HAS_FWDLIST 0x00000080 /* Internal: FORWARDLIST attr set */
#define AUDITORIUM 0x00000100 /* Should we check the SpeechLock? */
#define ANSI
0x00000200
#define HEAD_FLAG
0x00000400
#define FIXED
0x00000800
#define UNINSPECTED
0x00001000
#define ZONE_PARENT 0x00002000 /* Check as local master room */
#define DYNAMIC
0x00004000
#define NOBLEED
0x00008000
#define STAFF
0x00010000
#define HAS_DAILY
0x00020000
#define GAGGED
0x00040000
#define HAS_COMMANDS
0x00080000 /* Check it for $commands */
#define STOP_MATCH 0x00100000 /* Stop matching commands if found */
#define BOUNCE
0x00200000 /* Forward messages to contents */
#define CONTROL_OK 0x00400000 /* ControlLk specifies who ctrls me */
#define CONSTANT_ATTRS 0x00800000 /* Can't set attrs on this object */
#define VACATION
0x01000000
#define PLAYER_MAILS
0x02000000 /* Mail message in progress */
#define HTML
0x04000000
/* Player supports HTML */
#define BLIND
0x08000000 /* Suppress has arrived / left msgs */
#define SUSPECT
0x10000000 /* Report some activities to wizards */
#define WATCHER
0x20000000 /* Watch logins */
#define CONNECTED
0x40000000 /* Player is connected */
#define SLAVE
0x80000000 /* Disallow most commands */
/* Third word of flags */
#define REDIR_OK
0x00000001 /*
#define HAS_REDIRECT
0x00000002
#define ORPHAN
0x00000004 /*
#define HAS_DARKLOCK
0x00000008
#define DIRTY
0x00000010 /*
#define NODEFAULT
0x00000020 /*
#define PRESENCE
0x00000040 /*
#define HAS_SPEECHMOD
0x00000080
#define HAS_PROPDIR 0X00000100 /*
/* FREE FREE FREE */
#define MARK_0
0x00400000 /*
#define MARK_1
0x00800000
#define MARK_2
0x01000000
#define MARK_3
0x02000000
#define MARK_4
0x04000000
#define MARK_5
0x08000000
#define MARK_6
0x10000000
#define MARK_7
0x20000000

Can be victim of @redirect */


/* Victim of @redirect */
Don't check parent chain for $cmd */
/* Has a DarkLock */
Temporary flag: object is dirty */
Not subject to attr defaults */
Check presence-related locks */
/* Check @speechmod attr */
Internal: has Propdir attr */
User-defined flags */

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

#define MARK_8
#define MARK_9
#define MARK_FLAGS

0x40000000
0x80000000
0xffc00000

Saturday, June 16, 2012 11:09 PM

/* Bitwise-or of all marker flags */

/* --------------------------------------------------------------------------* FLAGENT: Information about object flags.


*/
typedef struct flag_entry {
const char *flagname;
/* Name of the flag */
int flagvalue; /* Which bit in the object is the flag */
char
flaglett;
/* Flag letter for listing */
int flagflag;
/* Ctrl flags for this flag (recursive? :-) */
int listperm;
/* Who sees this flag when set */
int (*handler)();
/* Handler for setting/clearing this flag */
} FLAGENT;
/* --------------------------------------------------------------------------* OBJENT: Fundamental object types
*/
typedef struct object_entry {
const char *name;
char
lett;
int perm;
int flags;
} OBJENT;
extern OBJENT object_types[8];
#define
#define
#define
#define
#define
#define
#define

OF_CONTENTS
OF_LOCATION
OF_EXITS
OF_HOME
OF_DROPTO
OF_OWNER
OF_SIBLINGS

0x0001
0x0002
0x0004
0x0008
0x0010
0x0020
0x0040

/*
/*
/*
/*
/*
/*
/*

Object
Object
Object
Object
Object
Object
Object

has
has
has
has
has
can
has

contents: Contents() */
a location: Location() */
exits: Exits() */
a home: Home() */
a dropto: Dropto() */
own other objects */
siblings: Next() */

typedef struct flagset {


FLAG
word1;
FLAG
word2;
FLAG
word3;
} FLAGSET;
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

void NDECL(init_flagtab);
void FDECL(display_flagtab, (dbref));
void FDECL(flag_set, (dbref, dbref, char *, int));
char *
FDECL(flag_description, (dbref, dbref));
FLAGENT *FDECL(find_flag, (dbref, char *));
char *
FDECL(decode_flags, (dbref, FLAGSET));
char *
FDECL(unparse_flags, (dbref, dbref));
int FDECL(has_flag, (dbref, dbref, char *));
char *
FDECL(unparse_object, (dbref, dbref, int));
char *
FDECL(unparse_object_numonly, (dbref));
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:09 PM

extern int FDECL(convert_flags, (dbref, char *, FLAGSET *, FLAG *));


extern void FDECL(decompile_flags, (dbref, dbref, char *));
#define GOD ((dbref) 1)
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

---------------------- Object Permission/Attribute Macros */


IS(X,T,F)
- Is X of type T and have flag F set? */
Typeof(X)
- What object type is X */
God(X)
- Is X player #1 */
Robot(X)
- Is X a robot player */
Wizard(X)
- Does X have wizard privs */
Immortal(X)
- Is X unkillable */
Alive(X)
- Is X a player or a puppet */
Dark(X)
- Is X dark */
Quiet(X)
- Should 'Set.' messages et al from X be disabled */
Verbose(X)
- Should owner receive all commands executed? */
Trace(X)
- Should owner receive eval trace output? */
Player_haven(X) - Is the owner of X no-page */
Haven(X)
- Is X no-kill(rooms) or no-page(players) */
Halted(X)
- Is X halted (not allowed to run commands)? */
Suspect(X)
- Is X someone the wizzes should keep an eye on */
Slave(X)
- Should X be prevented from db-changing commands */
Safe(X,P)
- Does P need the /OVERRIDE switch to @destroy X? */
Monitor(X)
- Should we check for ^xxx:xxx listens on player? */
Terse(X)
- Should we only show the room name on a look? */
Myopic(X)
- Should things as if we were nonowner/nonwiz */
Audible(X)
- Should X forward messages? */
Findroom(X)
- Can players in room X be found via @whereis? */
Unfindroom(X)
- Is @whereis blocked for players in room X? */
Findable(X)
- Can @whereis find X */
Unfindable(X)
- Is @whereis blocked for X */
No_robots(X)
- Does X disallow robot players from using */
Has_location(X) - Is X something with a location (ie plyr or obj) */
Has_home(X)
- Is X something with a home (ie plyr or obj) */
Has_contents(X) - Is X something with contents (ie plyr/obj/room) */
Good_dbref(X)
- Is X inside the DB? */
Good_obj(X)
- Is X inside the DB and have a valid type? */
Good_owner(X)
- Is X a good owner value? */
Good_home(X)
- Is X a good home value? */
Good_loc(X)
- Is X a good location value? */
Going(X)
- Is X marked GOING? */
Inherits(X)
- Does X inherit the privs of its owner */
Examinable(P,X) - Can P look at attribs of X */
MyopicExam(P,X) - Can P look at attribs of X (obeys MYOPIC) */
Controls(P,X)
- Can P force X to do something */
Darkened(P,X)
- Is X dark, and does P pass its DarkLock? */
Can_See(P,X,L)
- Can P see thing X, depending on location dark (L)? */
Can_See_Exit(P,X,L) - Can P see exit X, depending on loc dark (L)? */
Abode(X)
- Is X an ABODE room */
Link_exit(P,X)
- Can P link from exit X */
Linkable(P,X)
- Can P link to X */
Mark(x)
- Set marked flag on X */
Unmark(x)
- Clear marked flag on X */
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

/*
/*
/*
/*
/*
/*

Saturday, June 16, 2012 11:09 PM

Marked(x)
- Check marked flag on X */
See_attr(P,X,A,O,F) - Can P see text attr A on X if attr has owner O */
Set_attr(P,X,A,F)
- Can P set/change text attr A (with flags F) on X */
Read_attr(P,X,A,O,F) - Can P see attr A on X if attr has owner O */
Write_attr(P,X,A,F) - Can P set/change attr A (with flags F) on X */
Lock_attr(P,X,A,O)
- Can P lock/unlock attr A (with owner O) on X */

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

IS(thing,type,flag) ((Typeof(thing)==(type)) && (Flags(thing) & (flag)))


Typeof(x)
(Flags(x) & TYPE_MASK)
God(x)
((x) == GOD)
Robot(x)
(isPlayer(x) && ((Flags(x) & ROBOT) != 0))
Alive(x)
(isPlayer(x) || (Puppet(x) && Has_contents(x)))
OwnsOthers(x)
((object_types[Typeof(x)].flags & OF_OWNER) != 0)
Has_location(x) ((object_types[Typeof(x)].flags & OF_LOCATION) != 0)
Has_contents(x) ((object_types[Typeof(x)].flags & OF_CONTENTS) != 0)
Has_exits(x)
((object_types[Typeof(x)].flags & OF_EXITS) != 0)
Has_siblings(x) ((object_types[Typeof(x)].flags & OF_SIBLINGS) != 0)
Has_home(x) ((object_types[Typeof(x)].flags & OF_HOME) != 0)
Has_dropto(x)
((object_types[Typeof(x)].flags & OF_DROPTO) != 0)
Home_ok(x) ((object_types[Typeof(x)].flags & OF_HOME) != 0)
isPlayer(x) (Typeof(x) == TYPE_PLAYER)
isRoom(x)
(Typeof(x) == TYPE_ROOM)
isExit(x)
(Typeof(x) == TYPE_EXIT)
isThing(x) (Typeof(x) == TYPE_THING)
isGarbage(x)
(Typeof(x) == TYPE_GARBAGE)

#define
#define
#define
#define
#define

Good_dbref(x)
(((x) >= 0) && ((x) < mudstate.db_top))
Good_obj(x) (Good_dbref(x) && (Typeof(x) < GOODTYPE))
Good_owner(x)
(Good_obj(x) && OwnsOthers(x))
Good_home(x)
(Good_obj(x) && Home_ok(x))
Good_loc(x) (Good_obj(x) && Has_contents(x))

#define
#define
#define
#define
#define
#define
#define
#define

Royalty(x)
((Flags(x) & ROYALTY) != 0)
WizRoy(x)
(Royalty(x) || Wizard(x))
Staff(x)
((Flags2(x) & STAFF) != 0)
Head(x)
((Flags2(x) & HEAD_FLAG) != 0)
Fixed(x)
((Flags2(x) & FIXED) != 0)
Uninspected(x) ((Flags2(x) & UNINSPECTED) != 0)
Ansi(x)
((Flags2(x) & ANSI) != 0)
NoBleed(x)
((Flags2(x) & NOBLEED) != 0)

#define Transparent(x) ((Flags(x) & SEETHRU) != 0)


#define Link_ok(x) (((Flags(x) & LINK_OK) != 0) && Has_contents(x))
#define Wizard(x)
((Flags(x) & WIZARD) || \
((Flags(Owner(x)) & WIZARD) && Inherits(x)))
#define Dark(x)
(((Flags(x) & DARK) != 0) && \
(!Alive(x) || \
(Wizard(x) && !mudconf.visible_wizzes) || \
Can_Cloak(x)))
#define DarkMover(x)
((Wizard(x) || Can_Cloak(x)) && Dark(x))
#define Jump_ok(x) (((Flags(x) & JUMP_OK) != 0) && Has_contents(x))
#define Sticky(x)
((Flags(x) & STICKY) != 0)
#define Destroy_ok(x)
((Flags(x) & DESTROY_OK) != 0)
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

Saturday, June 16, 2012 11:09 PM

Haven(x)
((Flags(x) & HAVEN) != 0)
Player_haven(x) ((Flags(Owner(x)) & HAVEN) != 0)
Quiet(x)
((Flags(x) & QUIET) != 0)
Halted(x)
((Flags(x) & HALT) != 0)
Trace(x)
((Flags(x) & TRACE) != 0)
Going(x)
((Flags(x) & GOING) != 0)
Monitor(x) ((Flags(x) & MONITOR) != 0)
Myopic(x)
((Flags(x) & MYOPIC) != 0)
Puppet(x)
((Flags(x) & PUPPET) != 0)
Chown_ok(x) ((Flags(x) & CHOWN_OK) != 0)
Enter_ok(x) (((Flags(x) & ENTER_OK) != 0) && \
Has_location(x) && Has_contents(x))
Visual(x)
((Flags(x) & VISUAL) != 0)
Immortal(x) ((Flags(x) & IMMORTAL) || \
((Flags(Owner(x)) & IMMORTAL) && Inherits(x)))
Opaque(x)
((Flags(x) & OPAQUE) != 0)
Verbose(x) ((Flags(x) & VERBOSE) != 0)
Inherits(x) (((Flags(x) & INHERIT) != 0) || \
((Flags(Owner(x)) & INHERIT) != 0) || \
((x) == Owner(x)))
Nospoof(x) ((Flags(x) & NOSPOOF) != 0)
Safe(x,p)
(OwnsOthers(x) || \
(Flags(x) & SAFE) || \
(mudconf.safe_unowned && (Owner(x) != Owner(p))))
Control_ok(x)
((Flags2(x) & CONTROL_OK) != 0)
Constant_Attrs(x) ((Flags2(x) & CONSTANT_ATTRS) != 0)
Audible(x) ((Flags(x) & HEARTHRU) != 0)
Terse(x)
((Flags(x) & TERSE) != 0)
Gagged(x)
((Flags2(x) & GAGGED) != 0)
Vacation(x) ((Flags2(x) & VACATION) != 0)
Sending_Mail(x) ((Flags2(x) & PLAYER_MAILS) != 0)
Key(x)
((Flags2(x) & KEY) != 0)
Abode(x)
(((Flags2(x) & ABODE) != 0) && Home_ok(x))
Auditorium(x)
((Flags2(x) & AUDITORIUM) != 0)
Findable(x) ((Flags2(x) & UNFINDABLE) == 0)
Hideout(x) ((Flags2(x) & UNFINDABLE) != 0)
Parent_ok(x)
((Flags2(x) & PARENT_OK) != 0)
Light(x)
((Flags2(x) & LIGHT) != 0)
Suspect(x) ((Flags2(Owner(x)) & SUSPECT) != 0)
Watcher(x) ((Flags2(x) & WATCHER) != 0)
Connected(x)
(((Flags2(x) & CONNECTED) != 0) && \
(Typeof(x) == TYPE_PLAYER))
Slave(x)
((Flags2(Owner(x)) & SLAVE) != 0)
ParentZone(x)
((Flags2(x) & ZONE_PARENT) != 0)
Stop_Match(x)
((Flags2(x) & STOP_MATCH) != 0)
Has_Commands(x) ((Flags2(x) & HAS_COMMANDS) != 0)
Bouncer(x)
((Flags2(x) & BOUNCE) != 0)
Hidden(x)
((Flags(x) & DARK) != 0)
Blind(x)
((Flags2(x) & BLIND) != 0)
Redir_ok(x) ((Flags3(x) & REDIR_OK) != 0)
Orphan(x)
((Flags3(x) & ORPHAN) != 0)
NoDefault(x)
((Flags3(x) & NODEFAULT) != 0)
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

#define Unreal(x)

Saturday, June 16, 2012 11:09 PM

((Flags3(x) & PRESENCE) != 0)

#define
#define
#define
#define
#define
#define
#define

H_Startup(x)
((Flags(x) & HAS_STARTUP) != 0)
H_Fwdlist(x)
((Flags2(x) & HAS_FWDLIST) != 0)
H_Listen(x) ((Flags2(x) & HAS_LISTEN) != 0)
H_Redirect(x)
((Flags3(x) & HAS_REDIRECT) != 0)
H_Darklock(x)
((Flags3(x) & HAS_DARKLOCK) != 0)
H_Speechmod(x) ((Flags3(x) & HAS_SPEECHMOD) != 0)
H_Propdir(x)
((Flags3(x) & HAS_PROPDIR) != 0)

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

H_Marker0(x)
((Flags3(x) & MARK_0) != 0)
H_Marker1(x)
((Flags3(x) & MARK_1) != 0)
H_Marker2(x)
((Flags3(x) & MARK_2) != 0)
H_Marker3(x)
((Flags3(x) & MARK_3) != 0)
H_Marker4(x)
((Flags3(x) & MARK_4) != 0)
H_Marker5(x)
((Flags3(x) & MARK_5) != 0)
H_Marker6(x)
((Flags3(x) & MARK_6) != 0)
H_Marker7(x)
((Flags3(x) & MARK_7) != 0)
H_Marker8(x)
((Flags3(x) & MARK_8) != 0)
H_Marker9(x)
((Flags3(x) & MARK_9) != 0)
isMarkerFlag(fp)
(((fp)->flagflag & FLAG_WORD3) && \
((fp)->flagvalue & MARK_FLAGS))

#define
#define
#define
#define
#define

s_Halted(x) s_Flags((x), Flags(x) | HALT)


s_Going(x) s_Flags((x), Flags(x) | GOING)
s_Connected(x) s_Flags2((x), Flags2(x) | CONNECTED)
c_Connected(x) s_Flags2((x), Flags2(x) & ~CONNECTED)
isConnFlag(fp) (((fp)->flagflag & FLAG_WORD2) && \
((fp)->flagvalue & CONNECTED))
s_Has_Darklock(x)
s_Flags3((x), Flags3(x) | HAS_DARKLOCK)
c_Has_Darklock(x)
s_Flags3((x), Flags3(x) & ~HAS_DARKLOCK)
s_Trace(x) s_Flags((x), Flags(x) | TRACE)
c_Trace(x) s_Flags((x), Flags(x) & ~TRACE)

#define
#define
#define
#define

#define Html(x) ((Flags2(x) & HTML) != 0)


#define s_Html(x) s_Flags2((x), Flags2(x) | HTML)
#define c_Html(x) s_Flags2((x), Flags2(x) & ~HTML)
/* --------------------------------------------------------------------------* Base control-oriented predicates.
*/
#define Parentable(p,x) (Controls(p,x) || \
(Parent_ok(x) && could_doit(p,x,A_LPARENT)))
#define OnControlLock(p,x) (check_zone(p,x))
#define Controls(p,x)
(Good_obj(x) && \
(!(God(x) && !God(p))) && \
(Control_All(p) || \
((Owner(p) == Owner(x)) && \
(Inherits(p) || !Inherits(x))) || \
OnControlLock(p,x)))
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:09 PM

#define Cannot_Objeval(p,x) ((x == NOTHING) || God(x) || \


(mudconf.fascist_objeval ? \
!Controls(p, x) : \
((Owner(x) != Owner(p)) && !Wizard(p))))
#define Has_power(p,x)

(check_access((p),powers_nametab[x].flag))

#define Mark(x)
(mudstate.markbits->chunk[(x)>>3] |= \
mudconf.markdata[(x)&7])
#define Unmark(x)
(mudstate.markbits->chunk[(x)>>3] &= \
~mudconf.markdata[(x)&7])
#define Marked(x)
(mudstate.markbits->chunk[(x)>>3] & \
mudconf.markdata[(x)&7])
#define Mark_all(i) for ((i)=0; (i)<((mudstate.db_top+7)>>3); (i)++) \
mudstate.markbits->chunk[i]=(char)0xff
#define Unmark_all(i)
for ((i)=0; (i)<((mudstate.db_top+7)>>3); (i)++) \
mudstate.markbits->chunk[i]=(char)0x0
/* --------------------------------------------------------------------------* Visibility constraints.
*/
#define Examinable(p,x) (((Flags(x) & VISUAL) != 0) || \
(See_All(p)) || \
(Owner(p) == Owner(x)) || \
OnControlLock(p,x))
#define MyopicExam(p,x) (((Flags(x) & VISUAL) != 0) || \
(!Myopic(p) && (See_All(p) || \
(Owner(p) == Owner(x)) || \
OnControlLock(p,x))))
/* An object is considered Darkened if:
*
It is set Dark.
*
It does not have a DarkLock set (no HAS_DARKLOCK flag on the object;
*
an empty lock means the player would pass the DarkLock), OR
*
the player passes the DarkLock.
* DarkLocks only apply when we are checking if we can see something on
* a 'look'. They are not checked when matching, when looking at lexits(),
* when determining whether a move is seen, on @sweep, etc.
*/
#define Darkened(p,x)
(Dark(x) && \
(!H_Darklock(x) || could_doit(p,x,A_LDARK)))
/* For an object in a room, don't show if all of the following apply:
* Sleeping players should not be seen.
* The thing is a disconnected player.
* The player is not a puppet.
*
You don't see yourself or exits.
*
If a location is not dark, you see it if it's not dark or you control it.
*
If the location is dark, you see it if you control it. Seeing your own
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

*
*
*/

Saturday, June 16, 2012 11:09 PM

dark objects is controlled by mudconf.see_own_dark.


In dark locations, you also see things that are LIGHT and !DARK.

#define Sees(p,x) \
(!Darkened(p,x) || (mudconf.see_own_dark && MyopicExam(p,x)))
#define Sees_Always(p,x) \
(!Darkened(p,x) || (mudconf.see_own_dark && Examinable(p,x)))
#define Sees_In_Dark(p,x)
((Light(x) && !Darkened(p,x)) || \
(mudconf.see_own_dark && MyopicExam(p,x)))
#define Can_See(p,x,l) (!(((p) == (x)) || isExit(x) || \
(mudconf.dark_sleepers && isPlayer(x) && \
!Connected(x) && !Puppet(x))) && \
((l) ? Sees(p,x) : Sees_In_Dark(p,x)) && \
((!Unreal(x) || Check_Known(p,x)) && \
(!Unreal(p) || Check_Knows(x,p))))
#define Can_See_Exit(p,x,l) (!Darkened(p,x) && (!(l) || Light(x)) && \
((!Unreal(x) || Check_Known(p,x)) && \
(!Unreal(p) || Check_Knows(x,p))))
/* For exits visible (for lexits(), etc.), this is true if we can examine
* the exit's location, examine the exit, or the exit is LIGHT. It is also
* true if neither the location or base or exit is dark.
*/
#define VE_LOC_XAM 0x01
/* Location is examinable */
#define VE_LOC_DARK 0x02
/* Location is dark */
#define VE_BASE_DARK
0x04
/* Base location (pre-parent) is dark */
#define Exit_Visible(x,p,k) \
(((k) & VE_LOC_XAM) || Examinable(p,x) || Light(x) || \
(!((k) & (VE_LOC_DARK | VE_BASE_DARK)) && !Dark(x)))
/* --------------------------------------------------------------------------* Linking.
*/
/* Can I link this exit to something else? */
#define Link_exit(p,x) ((Typeof(x) == TYPE_EXIT) && \
((Location(x) == NOTHING) || Controls(p,x)))
/* Is this something I can link to?
*
- It must be a valid object, and be able to have contents.
*
- I must control it, or have it be Link_ok, or I must the
*
link_to_any power and not have the destination be God.
*/
#define Linkable(p,x)
(Good_obj(x) && Has_contents(x) && \
(Controls(p,x) || Link_ok(x) ||
\
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:09 PM

(LinkToAny(p) && !God(x))))


/* Can I pass the linklock check on this?
*
- I must have link_to_any (or be a wizard) and wizards must
*
ignore linklocks,
* OR
*
- I must be able to pass the linklock.
*/
#define Passes_Linklock(p,x) \
((LinkToAny(p) && !mudconf.wiz_obey_linklock) || \
could_doit(p,x,A_LLINK))
/* --------------------------------------------------------------------------* Attribute visibility and write permissions.
*/
#define AttrFlags(a,f)

((f) | (a)->flags)

#define Visible_desc(p,x,a) \
(((a)->number != A_DESC) || mudconf.read_rem_desc || nearby(p,x))
#define Invisible_attr(p,x,a,o,f) \
((!Examinable(p,x) && (Owner(p) != o)) || \
((AttrFlags(a,f) & AF_MDARK) && !Sees_Hidden_Attrs(p)) || \
((AttrFlags(a,f) & AF_DARK) && !God(p)))
#define Visible_attr(p,x,a,o,f) \
(((AttrFlags(a,f) & AF_VISUAL) && Visible_desc(p,x,a)) || \
!Invisible_attr(p,x,a,o,f))
#define See_attr(p,x,a,o,f) \
(!((a)->flags & (AF_INTERNAL|AF_IS_LOCK)) && !(f & AF_STRUCTURE) && \
Visible_attr(p,x,a,o,f))
#define Read_attr(p,x,a,o,f) \
(!((a)->flags & AF_INTERNAL) && !(f & AF_STRUCTURE) && \
Visible_attr(p,x,a,o,f))
#define See_attr_all(p,x,a,o,f,y) \
(!((a)->flags & (AF_INTERNAL|AF_IS_LOCK)) && \
((y) || !(f &AF_STRUCTURE)) && \
Visible_attr(p,x,a,o,f))
#define Read_attr_all(p,x,a,o,f,y) \
(!((a)->flags & AF_INTERNAL) && \
((y) || !(f &AF_STRUCTURE)) && \
Visible_attr(p,x,a,o,f))
/*
*
*
*
*

We can set it if:


The (master) attribute is not internal or a lock AND
we're God OR we meet the following criteria:
- The object is not God.
- The attribute on the object is not locked.
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

* * *
*
*
*
*/

Saturday, June 16, 2012 11:09 PM

The object is not set Constant.


We control the object, and the attribute and master attribute do
not have the Wizard or God flags,
OR
We are a Wizard and the attribute and master attribute do not have
the God flags.

#define Set_attr(p,x,a,f) \
(!((a)->flags & (AF_INTERNAL|AF_IS_LOCK|AF_CONST)) && \
(God(p) || \
(!God(x) && !((f) & AF_LOCK) && !Constant_Attrs(x) && \
((Controls(p,x) && \
!((a)->flags & (AF_WIZARD|AF_GOD)) && \
!((f) & (AF_WIZARD|AF_GOD))) || \
(Sets_Wiz_Attrs(p) && !((a)->flags & AF_GOD) && !((f) & AF_GOD))))))
/* Write_attr() is only used by atr_cpy(), and thus is not subject
* to the effects of the Constant flag.
*/
#define Write_attr(p,x,a,f) \
(!((a)->flags & (AF_INTERNAL|AF_NOCLONE)) && \
(God(p) || \
(!God(x) && !(f & AF_LOCK) && \
((Controls(p,x) && \
!((a)->flags & (AF_WIZARD|AF_GOD)) && \
!((f) & (AF_WIZARD|AF_GOD))) || \
(Sets_Wiz_Attrs(p) && \
!((a)->flags & AF_GOD))))))
/* We can lock/unlock it if:
* we're God OR we meet the following criteria:
* - The (master) attribute is not internal or a lock AND
* - The object is not God.
* - The object is not set Constant.
* - The master attribute does not have the Wizard or God flags,
*
OR
*
We are a Wizard and the master attribute does not have the God flag.
* - We are a Wizard OR we own the attribute.
*/
#define Lock_attr(p,x,a,o) \
(God(p) || \
(!God(x) && \
!((a)->flags & (AF_INTERNAL|AF_IS_LOCK|AF_CONST)) && \
!Constant_Attrs(x) && \
(!((a)->flags & (AF_WIZARD|AF_GOD)) || \
(Sets_Wiz_Attrs(p) && !((a)->flags & AF_GOD))) && \
(Wizard(p) || (o) == Owner(p))))
/* Visibility abstractions */

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\flags.h

584
585
586
587
588
589
590
591
592
593

#define
#define
#define
#define
#define
#define
#define

Are_Real(p,t)
Check_Heard(t,p)
Check_Noticed(t,p)
Check_Known(t,p)
Check_Hears(p,t)
Check_Notices(p,t)
Check_Knows(p,t)

Saturday, June 16, 2012 11:09 PM

(!(Unreal(p) || Unreal(t)))
(could_doit((t),(p),A_LHEARD))
(could_doit((t),(p),A_LMOVED))
(could_doit((t),(p),A_LKNOWN))
(could_doit((p),(t),A_LHEARS))
(could_doit((p),(t),A_LMOVES))
(could_doit((p),(t),A_LKNOWS))

#endif /* __FLAGS_H */

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:44 PM

/* fnhelper.c - helper functions for MUSH functions */


/* $Id: fnhelper.c,v 1.24 2004/02/23 04:35:14 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include
#include

"functions.h"
"match.h" /*
"attrs.h" /*
"powers.h" /*
"ansi.h"
/*

/* required by code */
required by code */
required by code */
required by code */
required by code */

static long NDECL(genrand_int31);


/* --------------------------------------------------------------------------* Trim off leading and trailing spaces if the separator char is a space
*/
char *trim_space_sep(str, sep)
char *str;
const Delim *sep;
{
char *p;

if ((sep->len > 1) || (sep->str[0] != ' ') || !*str)


return str;
while (*str == ' ')
str++;
for (p = str; *p; p++) ;
for (p--; *p == ' ' && p > str; p--) ;
p++;
*p = '\0';
return str;

/* --------------------------------------------------------------------------* Tokenizer functions.


* next_token: Point at start of next token in string.
* split_token: Get next token from string as null-term string. String is
*
destructively modified.
* next_token_ansi: Point at start of next token, and tell what color it is.
*/
char *next_token(str, sep)
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:44 PM

char *str;
const Delim *sep;
{
char *p;

if (sep->len == 1) {
while (*str == ESC_CHAR) {
skip_esccode(str);
}
while (*str && (*str != sep->str[0])) {
++str;
while (*str == ESC_CHAR) {
skip_esccode(str);
}
}
if (!*str)
return NULL;
++str;
if (sep->str[0] == ' ') {
while (*str == ' ')
++str;
}
} else {
if ((p = strstr(str, sep->str)) == NULL)
return NULL;
str = p + sep->len;
}
return str;

char *split_token(sp, sep)


char **sp;
const Delim *sep;
{
char *str, *save, *p;
save = str = *sp;
if (!str) {
*sp = NULL;
return NULL;
}
if (sep->len == 1) {
while (*str == ESC_CHAR) {
skip_esccode(str);
}
while (*str && (*str != sep->str[0])) {
++str;
while (*str == ESC_CHAR) {
skip_esccode(str);
}
}
if (*str) {
*str++ = '\0';
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:44 PM

if (sep->str[0] == ' ') {


while (*str == ' ')
++str;
}
} else {
str = NULL;
}
} else {
if ((p = strstr(str, sep->str)) != NULL) {
*p = '\0';
str = p + sep->len;
} else {
str = NULL;
}
}
*sp = str;
return save;

char *next_token_ansi(str, sep, ansi_state_ptr)


char *str;
const Delim *sep;
int *ansi_state_ptr;
{
int ansi_state = *ansi_state_ptr;
char *p;
if (sep->len == 1) {
while (*str == ESC_CHAR) {
track_esccode(str, ansi_state);
}
while (*str && (*str != sep->str[0])) {
++str;
while (*str == ESC_CHAR) {
track_esccode(str, ansi_state);
}
}
if (!*str) {
*ansi_state_ptr = ansi_state;
return NULL;
}
++str;
if (sep->str[0] == ' ') {
while (*str == ' ')
++str;
}
} else {
/* ansi tracking not supported yet in multichar delims */
if ((p = strstr(str, sep->str)) == NULL)
return NULL;
str = p + sep->len;
}
*ansi_state_ptr = ansi_state;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:44 PM

return str;

/* --------------------------------------------------------------------------* Count the words in a delimiter-separated list.


*/
int countwords(str, sep)
char *str;
const Delim *sep;
{
int n;

str = trim_space_sep(str, sep);


if (!*str)
return 0;
for (n = 0; str; str = next_token(str, sep), n++) ;
return n;

/* --------------------------------------------------------------------------* list2arr, arr2list: Convert lists to arrays and vice versa.


*/
int list2arr(arr, maxtok, list, sep)
char ***arr, *list;
const Delim *sep;
int maxtok;
{
static unsigned char tok_starts[(LBUF_SIZE >> 3) + 1];
static int initted = 0;
char *tok, *liststart;
int ntok, tokpos, i, bits;
/* Mark token starting points in a static 1k bitstring,
* then go back and collect them into an array of just
* the right number of pointers.
*/
if (!initted) {
memset(tok_starts, 0, sizeof(tok_starts));
initted = 1;
}
liststart = list = trim_space_sep(list, sep);
tok = split_token(&list, sep);
for (ntok = 0, tokpos = 0; tok && ntok < maxtok;
++ntok, tok = split_token(&list, sep)) {
tokpos = tok - liststart;
tok_starts[tokpos >> 3] |= (1 << (tokpos & 0x7));
}
if (ntok == 0) {
/* So we don't try to malloc(0). */
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:44 PM

++ntok;

/* Caller must free this array of pointers later. Validity of


* the pointers is dependent upon the original list string
* having not been freed yet.
*/
*arr = (char **)XCALLOC(ntok, sizeof(char *), "list2arr");
tokpos
ntok =
for (i
if

>>= 3;
0;
= 0; i <= tokpos; ++i) {
(tok_starts[i]) {
/* There's at least one token starting in this byte
* of the bitstring, so we scan the bits.
*/
bits = tok_starts[i];
tok_starts[i] = 0;
tok = liststart + (i << 3);
do {
if (bits & 0x1) {
(*arr)[ntok] = tok;
++ntok;
}
bits >>= 1;
++tok;
} while (bits);

}
}
return ntok;

void arr2list(arr, alen, list, bufc, sep)


char **arr, **bufc, *list;
const Delim *sep;
int alen;
{
int i;

if (alen) {
safe_str(arr[0], list, bufc);
}
for (i = 1; i < alen; i++) {
print_sep(sep, list, bufc);
safe_str(arr[i], list, bufc);
}

/* --------------------------------------------------------------------------* Find the ANSI states at the beginning and end of each word of a list.
* NOTE! Needs one more array slot than list2arr (think fenceposts) but
* still takes the same maxlen and returns the same number of words.
*/
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

Saturday, June 16, 2012 11:44 PM

int list2ansi(arr, prior_state, maxlen, list, sep)


int *arr, *prior_state, maxlen;
char *list;
const Delim *sep;
{
int i, ansi_state;
if (maxlen <= 0)
return 0;
ansi_state = arr[0] = *prior_state;
list = trim_space_sep(list, sep);

for (i = 1; list && i < maxlen;


list = next_token_ansi(list, sep, &ansi_state), ++i) {
arr[i - 1] = ansi_state;
}
arr[i] = ANST_NONE;
return i - 1;

/* --------------------------------------------------------------------------* Quick-matching for function purposes.


*/
dbref match_thing(player, name)
dbref player;
char *name;
{
init_match(player, name, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
return (noisy_match_result());
}
/* --------------------------------------------------------------------------* fn_range_check: Check # of args to a function with an optional argument
* for validity.
*/
int fn_range_check(fname, nfargs, minargs, maxargs, result, bufc)
const char *fname;
char *result, **bufc;
int nfargs, minargs, maxargs;
{
if ((nfargs >= minargs) && (nfargs <= maxargs))
return 1;
if (maxargs == (minargs + 1))
safe_tprintf_str(result, bufc, "#-1 FUNCTION (%s) EXPECTS %d OR %d ARGUMENTS
BUT GOT %d",
fname, minargs, maxargs, nfargs);
else
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

Saturday, June 16, 2012 11:44 PM

safe_tprintf_str(result, bufc, "#-1 FUNCTION (%s) EXPECTS BETWEEN %d AND %d


ARGUMENTS BUT GOT %d",
fname, minargs, maxargs, nfargs);
return 0;

/* --------------------------------------------------------------------------* delim_check: obtain delimiter


*/
int delim_check( FUNCTION_ARGLIST, sep_arg, sep, dflags)
char *fargs[], *cargs[], *buff, **bufc;
Delim *sep;
int nfargs, ncargs, sep_arg, dflags;
dbref player, caller, cause;
{
char *tstr, *bp, *str;
int tlen;
if (nfargs < sep_arg) {
sep->str[0] = ' ';
sep->len = 1;
return 1;
}
tlen = strlen(fargs[sep_arg - 1]);
if (tlen <= 1)
dflags &= ~DELIM_EVAL;
if (dflags & DELIM_EVAL) {
tstr = bp = alloc_lbuf("delim_check");
str = fargs[sep_arg - 1];
exec(tstr, &bp, player, caller, cause,
EV_EVAL | EV_FCHECK, &str, cargs, ncargs);
tlen = strlen(tstr);
} else {
tstr = fargs[sep_arg - 1];
}
sep->len = 1;
if (tlen == 0) {
sep->str[0] = ' ';
} else if (tlen == 1) {
sep->str[0] = *tstr;
} else {
if ((dflags & DELIM_NULL) &&
!strcmp(tstr, (char *) NULL_DELIM_VAR)) {
sep->str[0] = '\0';
} else if ((dflags & DELIM_CRLF) &&
!strcmp(tstr, (char *) "\r\n")) {
sep->str[0] = '\r';
} else if (dflags & DELIM_STRING) {
if (tlen > MAX_DELIM_LEN) {
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

Saturday, June 16, 2012 11:44 PM

safe_str("#-1 SEPARATOR TOO LONG", buff, bufc);


sep->len = 0;
} else {
strcpy(sep->str, tstr);
sep->len = tlen;
}
} else {
safe_str("#-1 SEPARATOR MUST BE ONE CHARACTER" ,
buff, bufc);
sep->len = 0;
}
}
if (dflags & DELIM_EVAL)
free_lbuf(tstr);
}

return (sep->len);

/* --------------------------------------------------------------------------* Boolean true/false check.


*/
int xlate(arg)
char *arg;
{
char *temp2;
if (arg[0] == '#') {
arg++;
if (is_integer(arg)) {
if (mudconf.bools_oldstyle) {
switch (atoi(arg)) {
case -1:
return 0;
case 0:
return 0;
default:
return 1;
}
} else {
return (atoi(arg) >= 0);
}
}
if (mudconf.bools_oldstyle) {
return 0;
} else {
/* Case of '#-1 <string>' */
return !((arg[0] == '-') && (arg[1] == '1') &&
(arg[2] == ' '));
}
}
temp2 = Eat_Spaces(arg);
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

Saturday, June 16, 2012 11:44 PM

if (!*temp2)
return 0;
if (is_integer(temp2))
return atoi(temp2);
return 1;

/* --------------------------------------------------------------------------* used by fun_reverse and fun_revwords to reverse things


*/
INLINE void do_reverse(from, to)
char *from, *to;
{
char *tp;

tp = to + strlen(from);
*tp-- = '\0';
while (*from) {
*tp-- = *from++;
}

/* --------------------------------------------------------------------------* Random number generator, from PennMUSH's get_random_long(), which


* is turn based on MUX2's RandomINT32().
*/
long random_range(low, high)
long low, high;
{
unsigned long x, n, n_limit;
/* Validate parameters. */
if (high < low)
return 0;
else if (high == low)
return low;
x = high - low;
if (INT_MAX < x)
return -1;
x++;
/* Look for a random number on the interval [0,x-1].
* MUX2's implementation states:
*
In order to be perfectly conservative about not introducing any
*
further sources of statistical bias, we're going to call getrand()
*
until we get a number less than the greatest representable
*
multiple of x. We'll then return n mod x.
*
N.B. This loop happens in randomized constant time, and pretty
*
damn fast randomized constant time too, since
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

*
*
*
*/

Saturday, June 16, 2012 11:44 PM

P(UINT32_MAX_VALUE - n < UINT32_MAX_VALUE % x) < 0.5, for any x.


So even for the least desirable x, the average number of times
we will call getrand() is less than 2.

n_limit = INT_MAX - (INT_MAX % x);


do {
n = genrand_int31();
} while (n >= n_limit);
}

return low + (n % x);

/* --------------------------------------------------------------------------* ALL OTHER CODE FOR TINYMUSH SHOULD GO ABOVE THIS LINE.
* --------------------------------------------------------------------------*/
/*

A C-program for MT19937, with initialization improved 2002/2/10.


Coded by Takuji Nishimura and Makoto Matsumoto.
This is a faster version by taking Shawn Cokus's optimization,
Matthe Bellew's simplification, Isaku Wada's real version.
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

Saturday, June 16, 2012 11:44 PM

LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING


NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

Any feedback is very welcome.


http://www.math.keio.ac.jp/matumoto/emt.html
email: matumoto@math.keio.ac.jp

/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL
/* constant vector a */
#define UMASK 0x80000000UL /* most significant w-r bits */
#define LMASK 0x7fffffffUL /* least significant r bits */
#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
static
static
static
static

unsigned long state[N]; /* the array for the state vector


int left = 1;
int initf = 0;
unsigned long *next;

*/

/* initializes state[N] with a seed */


void init_genrand(s)
unsigned long s;
{
int j;
state[0]= s & 0xffffffffUL;
for (j=1; j<N; j++) {
state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect
*/
/* only MSBs of the array state[].
*/
/* 2002/01/09 modified by Makoto Matsumoto
*/
state[j] &= 0xffffffffUL; /* for >32 bit machines */
}
left = 1; initf = 1;
}
static void next_state()
{
unsigned long *p=state;
int j;
/* if init_genrand() has not been called, */
/* a default initial seed is used
*/
if (initf==0) init_genrand(5489UL);
left = N;
next = state;

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnhelper.c

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607

Saturday, June 16, 2012 11:44 PM

for (j=N-M+1; --j; p++)


*p = p[M] ^ TWIST(p[0], p[1]);
for (j=M; --j; p++)
*p = p[M-N] ^ TWIST(p[0], p[1]);
}

*p = p[M-N] ^ TWIST(p[0], state[0]);

/* generates a random number on [0,0x7fffffff]-interval */


static long NDECL(genrand_int31)
{
unsigned long y;
if (--left == 0) next_state();
y = *next++;
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
}

return (long)(y>>1);

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:09 PM

/* fnproto.h - function prototypes from funmath.c, etc. */


/* $Id: fnproto.h,v 1.84 2009/01/11 18:49:08 lwl Exp $ */
#include "copyright.h"
#ifndef __FNPROTO_H
#define __FNPROTO_H
#define XFUNCTION(x)
\
extern void FDECL(x, (char *, char **, dbref, dbref, dbref, \
char *[], int, char *[], int))
#ifdef PUEBLO_SUPPORT
XFUNCTION(fun_html_escape);
XFUNCTION(fun_html_unescape);
XFUNCTION(fun_url_escape);
XFUNCTION(fun_url_unescape);
#endif /* PUEBLO SUPPORT */
XFUNCTION(fun_config);
XFUNCTION(fun_lwho);
XFUNCTION(fun_ports);
XFUNCTION(fun_doing);
XFUNCTION(handle_conninfo);
XFUNCTION(fun_conn);
XFUNCTION(fun_session);
XFUNCTION(fun_programmer);
XFUNCTION(fun_helptext);
XFUNCTION(fun_sql);
/* From funiter.c */
XFUNCTION(perform_loop);
XFUNCTION(perform_iter);
XFUNCTION(fun_ilev);
XFUNCTION(fun_itext);
XFUNCTION(fun_inum);
XFUNCTION(fun_fold);
XFUNCTION(handle_filter);
XFUNCTION(fun_map);
XFUNCTION(fun_mix);
XFUNCTION(fun_step);
XFUNCTION(fun_foreach);
XFUNCTION(fun_munge);
XFUNCTION(fun_while);
/* From funlist.c */
XFUNCTION(fun_words);
XFUNCTION(fun_first);
XFUNCTION(fun_rest);
XFUNCTION(fun_last);
XFUNCTION(fun_match);
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:09 PM

XFUNCTION(fun_matchall);
XFUNCTION(fun_extract);
XFUNCTION(fun_index);
XFUNCTION(fun_ldelete);
XFUNCTION(fun_replace);
XFUNCTION(fun_lreplace);
XFUNCTION(fun_insert);
XFUNCTION(fun_remove);
XFUNCTION(fun_member);
XFUNCTION(fun_revwords);
XFUNCTION(fun_splice);
XFUNCTION(handle_sort);
XFUNCTION(fun_sortby);
XFUNCTION(handle_sets);
XFUNCTION(fun_columns);
XFUNCTION(process_tables);
XFUNCTION(fun_table);
XFUNCTION(fun_elements);
XFUNCTION(fun_grab);
XFUNCTION(fun_graball);
XFUNCTION(fun_shuffle);
XFUNCTION(fun_ledit);
XFUNCTION(fun_itemize);
XFUNCTION(fun_choose);
XFUNCTION(fun_group);
/* From funmath.c */
XFUNCTION(fun_pi);
XFUNCTION(fun_e);
XFUNCTION(fun_sign);
XFUNCTION(fun_abs);
XFUNCTION(fun_floor);
XFUNCTION(fun_ceil);
XFUNCTION(fun_round);
XFUNCTION(fun_trunc);
XFUNCTION(fun_inc);
XFUNCTION(fun_dec);
XFUNCTION(fun_sqrt);
XFUNCTION(fun_exp);
XFUNCTION(fun_ln);
XFUNCTION(handle_trig);
XFUNCTION(fun_gt);
XFUNCTION(fun_gte);
XFUNCTION(fun_lt);
XFUNCTION(fun_lte);
XFUNCTION(fun_eq);
XFUNCTION(fun_neq);
XFUNCTION(fun_ncomp);
XFUNCTION(fun_sub);
XFUNCTION(fun_div);
XFUNCTION(fun_floordiv);
XFUNCTION(fun_fdiv);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:09 PM

XFUNCTION(fun_modulo);
XFUNCTION(fun_remainder);
XFUNCTION(fun_power);
XFUNCTION(fun_log);
XFUNCTION(fun_shl);
XFUNCTION(fun_shr);
XFUNCTION(fun_band);
XFUNCTION(fun_bor);
XFUNCTION(fun_bnand);
XFUNCTION(fun_add);
XFUNCTION(fun_mul);
XFUNCTION(fun_max);
XFUNCTION(fun_min);
XFUNCTION(fun_dist2d);
XFUNCTION(fun_dist3d);
XFUNCTION(fun_ladd);
XFUNCTION(fun_lmax);
XFUNCTION(fun_lmin);
XFUNCTION(handle_vector);
XFUNCTION(handle_vectors);
XFUNCTION(fun_not);
XFUNCTION(fun_notbool);
XFUNCTION(fun_t);
XFUNCTION(handle_logic);
/* From funmisc.c */
XFUNCTION(fun_switchall);
XFUNCTION(fun_switch);
XFUNCTION(fun_case);
XFUNCTION(handle_ifelse);
XFUNCTION(fun_rand);
XFUNCTION(fun_die);
XFUNCTION(fun_lrand);
XFUNCTION(fun_lnum);
XFUNCTION(fun_time);
XFUNCTION(fun_secs);
XFUNCTION(fun_convsecs);
XFUNCTION(fun_convtime);
XFUNCTION(fun_timefmt);
XFUNCTION(fun_starttime);
XFUNCTION(fun_restarts);
XFUNCTION(fun_restarttime);
XFUNCTION(fun_version);
XFUNCTION(fun_mudname);
XFUNCTION(fun_hasmodule);
XFUNCTION(fun_connrecord);
XFUNCTION(fun_fcount);
XFUNCTION(fun_fdepth);
XFUNCTION(fun_ccount);
XFUNCTION(fun_cdepth);
XFUNCTION(fun_s);
XFUNCTION(fun_subeval);
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:09 PM

XFUNCTION(fun_link);
XFUNCTION(fun_tel);
XFUNCTION(fun_wipe);
XFUNCTION(fun_pemit);
XFUNCTION(fun_remit);
XFUNCTION(fun_oemit);
XFUNCTION(fun_force);
XFUNCTION(fun_trigger);
XFUNCTION(fun_wait);
XFUNCTION(fun_command);
XFUNCTION(fun_create);
XFUNCTION(fun_set);
/* From funobj.c */
XFUNCTION(fun_con);
XFUNCTION(fun_exit);
XFUNCTION(fun_next);
XFUNCTION(handle_loc);
XFUNCTION(fun_rloc);
XFUNCTION(fun_room);
XFUNCTION(fun_owner);
XFUNCTION(fun_controls);
XFUNCTION(fun_sees);
XFUNCTION(fun_nearby);
XFUNCTION(handle_name);
XFUNCTION(handle_pronoun);
XFUNCTION(fun_lock);
XFUNCTION(fun_elock);
XFUNCTION(fun_elockstr);
XFUNCTION(fun_xcon);
XFUNCTION(fun_lcon);
XFUNCTION(fun_lexits);
XFUNCTION(fun_entrances);
XFUNCTION(fun_home);
XFUNCTION(fun_money);
XFUNCTION(fun_findable);
XFUNCTION(fun_visible);
XFUNCTION(fun_writable);
XFUNCTION(fun_flags);
XFUNCTION(handle_flaglists);
XFUNCTION(fun_hasflag);
XFUNCTION(fun_haspower);
XFUNCTION(fun_hasflags);
XFUNCTION(handle_timestamp);
XFUNCTION(fun_parent);
XFUNCTION(fun_lparent);
XFUNCTION(fun_children);
XFUNCTION(fun_zone);
XFUNCTION(scan_zone);
XFUNCTION(fun_zfun);
XFUNCTION(fun_hasattr);
XFUNCTION(fun_v);
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:09 PM

XFUNCTION(perform_get);
XFUNCTION(fun_eval);
XFUNCTION(do_ufun);
XFUNCTION(fun_objcall);
XFUNCTION(fun_localize);
XFUNCTION(fun_private);
XFUNCTION(fun_default);
XFUNCTION(fun_edefault);
XFUNCTION(fun_udefault);
XFUNCTION(fun_objeval);
XFUNCTION(fun_num);
XFUNCTION(fun_pmatch);
XFUNCTION(fun_pfind);
XFUNCTION(fun_locate);
XFUNCTION(handle_lattr);
XFUNCTION(fun_search);
XFUNCTION(fun_stats);
XFUNCTION(fun_objmem);
XFUNCTION(fun_playmem);
XFUNCTION(fun_type);
XFUNCTION(fun_hastype);
XFUNCTION(fun_lastcreate);
XFUNCTION(fun_speak);
XFUNCTION(handle_okpres);
/* From funstring.c */
XFUNCTION(fun_isword);
XFUNCTION(fun_isnum);
XFUNCTION(fun_isdbref);
XFUNCTION(fun_null);
XFUNCTION(fun_squish);
XFUNCTION(fun_trim);
XFUNCTION(fun_after);
XFUNCTION(fun_before);
XFUNCTION(fun_lcstr);
XFUNCTION(fun_ucstr);
XFUNCTION(fun_capstr);
XFUNCTION(fun_space);
XFUNCTION(fun_ljust);
XFUNCTION(fun_rjust);
XFUNCTION(fun_center);
XFUNCTION(fun_left);
XFUNCTION(fun_right);
XFUNCTION(fun_chomp);
XFUNCTION(fun_comp);
XFUNCTION(fun_streq);
XFUNCTION(fun_strmatch);
XFUNCTION(fun_edit);
XFUNCTION(fun_merge);
XFUNCTION(fun_secure);
XFUNCTION(fun_escape);
XFUNCTION(fun_ansi);
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:09 PM

XFUNCTION(fun_stripansi);
XFUNCTION(fun_encrypt);
XFUNCTION(fun_decrypt);
XFUNCTION(fun_scramble);
XFUNCTION(fun_reverse);
XFUNCTION(fun_mid);
XFUNCTION(fun_translate);
XFUNCTION(fun_pos);
XFUNCTION(fun_lpos);
XFUNCTION(fun_wordpos);
XFUNCTION(fun_ansipos);
XFUNCTION(fun_repeat);
XFUNCTION(perform_border);
XFUNCTION(fun_cat);
XFUNCTION(fun_strcat);
XFUNCTION(fun_strlen);
XFUNCTION(fun_delete);
XFUNCTION(fun_lit);
XFUNCTION(fun_art);
XFUNCTION(fun_alphamax);
XFUNCTION(fun_alphamin);
XFUNCTION(fun_valid);
XFUNCTION(fun_beep);
/* From funvars.c */
XFUNCTION(fun_setq);
XFUNCTION(fun_setr);
XFUNCTION(fun_r);
XFUNCTION(fun_wildmatch);
XFUNCTION(fun_qvars);
XFUNCTION(fun_lregs);
XFUNCTION(fun_x);
XFUNCTION(fun_setx);
XFUNCTION(fun_store);
XFUNCTION(fun_xvars);
XFUNCTION(fun_let);
XFUNCTION(fun_lvars);
XFUNCTION(fun_clearvars);
XFUNCTION(fun_structure);
XFUNCTION(fun_construct);
XFUNCTION(fun_load);
XFUNCTION(fun_read);
XFUNCTION(fun_delimit);
XFUNCTION(fun_z);
XFUNCTION(fun_modify);
XFUNCTION(fun_unload);
XFUNCTION(fun_write);
XFUNCTION(fun_destruct);
XFUNCTION(fun_unstructure);
XFUNCTION(fun_lstructures);
XFUNCTION(fun_linstances);
XFUNCTION(fun_empty);
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:09 PM

XFUNCTION(fun_items);
XFUNCTION(fun_push);
XFUNCTION(fun_dup);
XFUNCTION(fun_swap);
XFUNCTION(handle_pop);
XFUNCTION(fun_popn);
XFUNCTION(fun_lstack);
XFUNCTION(perform_regedit);
XFUNCTION(fun_wildparse);
XFUNCTION(perform_regparse);
XFUNCTION(perform_regrab);
XFUNCTION(perform_regmatch);
XFUNCTION(fun_until);
XFUNCTION(perform_grep);
/* *INDENT-OFF* */
/* --------------------------------------------------------------------------* flist: List of existing functions in alphabetical order.
*/
FUN flist[] = {
{"@@",
fun_null,

1, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"ABS",
fun_abs,
1, 0,
CA_PUBLIC, NULL},
{"ACOS",
handle_trig,
1, TRIG_ARC|TRIG_CO,
CA_PUBLIC, NULL},
{"ACOSD",
handle_trig,
1, TRIG_ARC|TRIG_CO|TRIG_DEG,
CA_PUBLIC, NULL},
{"ADD",
fun_add,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"AFTER",
fun_after, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"ALPHAMAX",
fun_alphamax,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"ALPHAMIN",
fun_alphamin,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"AND",
handle_logic,
0, FN_VARARGS|LOGIC_AND,
CA_PUBLIC, NULL},
{"ANDBOOL", handle_logic,
0, FN_VARARGS|LOGIC_AND|LOGIC_BOOL,
CA_PUBLIC, NULL},
{"ANDFLAGS",
handle_flaglists, 2, 0,
CA_PUBLIC, NULL},
{"ANSI",
fun_ansi,
2, 0,
CA_PUBLIC, NULL},
{"ANSIPOS",
fun_ansipos,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"APOSS",
handle_pronoun, 1, PRONOUN_APOSS, CA_PUBLIC,
NULL},
{"ART",
fun_art,
1, 0,
CA_PUBLIC, NULL},
{"ASIN",
handle_trig,
1, TRIG_ARC,
CA_PUBLIC, NULL},
{"ASIND",
handle_trig,
1, TRIG_ARC|TRIG_DEG,
CA_PUBLIC, NULL},
{"ATAN",
handle_trig,
1, TRIG_ARC|TRIG_TAN,
CA_PUBLIC, NULL},
{"ATAND",
handle_trig,
1, TRIG_ARC|TRIG_TAN|TRIG_DEG,
CA_PUBLIC, NULL},
{"BAND",
fun_band,
2, 0,
CA_PUBLIC, NULL},
{"BEEP",
fun_beep,
0, 0,
CA_WIZARD, NULL},
{"BEFORE", fun_before, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"BNAND",
fun_bnand, 2, 0,
CA_PUBLIC, NULL},
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:09 PM

{"BOR",
{"BORDER",

fun_bor,
2, 0,
CA_PUBLIC, NULL},
perform_border, 0, FN_VARARGS|JUST_LEFT,
CA_PUBLIC, NULL},
{"CANDBOOL",
handle_logic,
0, FN_VARARGS|FN_NO_EVAL|LOGIC_AND|LOGIC_BOOL,
CA_PUBLIC, NULL},
{"CAND",
handle_logic,
0, FN_VARARGS|FN_NO_EVAL|LOGIC_AND,
CA_PUBLIC, NULL},
{"CAPSTR", fun_capstr, -1, 0,
CA_PUBLIC, NULL},
{"CASE",
fun_case,
0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"CAT",
fun_cat,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"CBORDER", perform_border, 0, FN_VARARGS|JUST_CENTER,
CA_PUBLIC, NULL},
{"CCOUNT", fun_ccount, 0, 0,
CA_PUBLIC, NULL},
{"CDEPTH", fun_cdepth, 0, 0,
CA_PUBLIC, NULL},
{"CEIL",
fun_ceil,
1, 0,
CA_PUBLIC, NULL},
{"CENTER", fun_center, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"CHILDREN",
fun_children,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"CHOMP",
fun_chomp, 1, 0,
CA_PUBLIC, NULL},
{"CHOOSE", fun_choose, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"CLEARVARS",
fun_clearvars, 0, 0,
CA_PUBLIC, NULL},
{"COLUMNS", fun_columns,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"COMMAND", fun_command,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"COMP",
fun_comp,
2, 0,
CA_PUBLIC, NULL},
{"CON",
fun_con,
1, 0,
CA_PUBLIC, NULL},
{"CONFIG", fun_config, 1, 0,
CA_PUBLIC, NULL},
{"CONN",
handle_conninfo, 1, 0,
CA_PUBLIC, NULL},
{"CONNRECORD", fun_connrecord, 0, 0,
CA_PUBLIC, NULL},
{"CONSTRUCT",
fun_construct, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"CONTROLS",
fun_controls,
2, 0,
CA_PUBLIC, NULL},
{"CONVSECS",
fun_convsecs,
1, 0,
CA_PUBLIC, NULL},
{"CONVTIME",
fun_convtime,
1, 0,
CA_PUBLIC, NULL},
{"COR",
handle_logic,
0, FN_VARARGS|FN_NO_EVAL|LOGIC_OR,
CA_PUBLIC, NULL},
{"CORBOOL", handle_logic,
0, FN_VARARGS|FN_NO_EVAL|LOGIC_OR|LOGIC_BOOL,
CA_PUBLIC, NULL},
{"COS",
handle_trig,
1, TRIG_CO,
CA_PUBLIC, NULL},
{"COSD",
handle_trig,
1, TRIG_CO|TRIG_DEG,
CA_PUBLIC, NULL},
{"CREATE",
fun_create,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"CTABLES", process_tables, 0, FN_VARARGS|JUST_CENTER,
CA_PUBLIC, NULL},
{"DEC",
fun_dec,
1, 0,
CA_PUBLIC, NULL},
{"DECRYPT", fun_decrypt,
2, 0,
CA_PUBLIC, NULL},
{"DEFAULT", fun_default,
2, FN_NO_EVAL, CA_PUBLIC, NULL},
{"DELETE", fun_delete, 3, 0,
CA_PUBLIC, NULL},
{"DELIMIT", fun_delimit,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"DESTRUCT",
fun_destruct,
1, 0,
CA_PUBLIC, NULL},
{"DIE",
fun_die,
2, 0,
CA_PUBLIC, NULL},
{"DIST2D", fun_dist2d, 4, 0,
CA_PUBLIC, NULL},
{"DIST3D", fun_dist3d, 6, 0,
CA_PUBLIC, NULL},
{"DIV",
fun_div,
2, 0,
CA_PUBLIC, NULL},
{"DOING",
fun_doing, 1, 0,
CA_PUBLIC, NULL},
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:09 PM

{"DUP",
fun_dup,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"E",
fun_e,
0, 0,
CA_PUBLIC, NULL},
{"EDEFAULT",
fun_edefault,
2, FN_NO_EVAL, CA_PUBLIC, NULL},
{"EDIT",
fun_edit,
3, 0,
CA_PUBLIC, NULL},
{"ELEMENTS",
fun_elements,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"ELOCK",
fun_elock, 2, 0,
CA_PUBLIC, NULL},
{"ELOCKSTR",
fun_elockstr,
3, 0,
CA_PUBLIC, NULL},
{"EMPTY",
fun_empty, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"ENCRYPT", fun_encrypt,
2, 0,
CA_PUBLIC, NULL},
{"ENTRANCES",
fun_entrances, 0, FN_VARARGS, CA_NO_GUEST,
NULL},
{"EQ",
fun_eq,
2, 0,
CA_PUBLIC, NULL},
{"ESCAPE", fun_escape, -1, 0,
CA_PUBLIC, NULL},
{"EXIT",
fun_exit,
1, 0,
CA_PUBLIC, NULL},
{"EXP",
fun_exp,
1, 0,
CA_PUBLIC, NULL},
{"EXTRACT", fun_extract,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"EVAL",
fun_eval,
0, FN_VARARGS|GET_EVAL|GET_XARGS,
CA_PUBLIC, NULL},
{"SUBEVAL",
fun_subeval,
1, 0,
CA_PUBLIC, NULL},
{"FCOUNT", fun_fcount, 0, 0,
CA_PUBLIC, NULL},
{"FDEPTH", fun_fdepth, 0, 0,
CA_PUBLIC, NULL},
{"FDIV",
fun_fdiv,
2, 0,
CA_PUBLIC, NULL},
{"FILTER", handle_filter, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"FILTERBOOL", handle_filter, 0, FN_VARARGS|LOGIC_BOOL,
CA_PUBLIC, NULL},
{"FINDABLE",
fun_findable,
2, 0,
CA_PUBLIC, NULL},
{"FIRST",
fun_first, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"FLAGS",
fun_flags, 1, 0,
CA_PUBLIC, NULL},
{"FLOOR",
fun_floor, 1, 0,
CA_PUBLIC, NULL},
{"FLOORDIV",
fun_floordiv,
2, 0,
CA_PUBLIC, NULL},
{"FOLD",
fun_fold,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"FORCE",
fun_force, 2, 0,
CA_PUBLIC, NULL},
{"FOREACH", fun_foreach,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"FULLNAME",
handle_name,
1, NAMEFN_FULLNAME, CA_PUBLIC, NULL},
{"GET",
perform_get,
1, 0,
CA_PUBLIC, NULL},
{"GET_EVAL",
perform_get,
1, GET_EVAL,
CA_PUBLIC, NULL},
{"GRAB",
fun_grab,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"GRABALL", fun_graball,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"GREP",
perform_grep,
0, FN_VARARGS|GREP_EXACT, CA_PUBLIC, NULL},
{"GREPI",
perform_grep,
0, FN_VARARGS|GREP_EXACT|REG_CASELESS,
CA_PUBLIC, NULL},
{"GROUP",
fun_group, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"GT",
fun_gt,
2, 0,
CA_PUBLIC, NULL},
{"GTE",
fun_gte,
2, 0,
CA_PUBLIC, NULL},
{"HASATTR", fun_hasattr,
2, 0,
CA_PUBLIC, NULL},
{"HASATTRP",
fun_hasattr,
2, CHECK_PARENTS,
CA_PUBLIC, NULL},
{"HASFLAG", fun_hasflag,
2, 0,
CA_PUBLIC, NULL},
{"HASFLAGS",
fun_hasflags,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"HASMODULE",
fun_hasmodule, 1, 0,
CA_PUBLIC, NULL},
{"HASPOWER",
fun_haspower,
2, 0,
CA_PUBLIC, NULL},
{"HASTYPE", fun_hastype,
2, 0,
CA_PUBLIC, NULL},
{"HEARS",
handle_okpres, 2, PRESFN_HEARS,
CA_PUBLIC, NULL},
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

Saturday, June 16, 2012 11:09 PM

{"HELPTEXT",
fun_helptext,
2, 0,
CA_PUBLIC, NULL},
{"HOME",
fun_home,
1, 0,
CA_PUBLIC, NULL},
#ifdef PUEBLO_SUPPORT
{"HTML_ESCAPE", fun_html_escape,-1, 0,
CA_PUBLIC, NULL},
{"HTML_UNESCAPE",fun_html_unescape,-1,0,
CA_PUBLIC, NULL},
#endif /* PUEBLO_SUPPORT */
{"IDLE",
handle_conninfo, 1, CONNINFO_IDLE, CA_PUBLIC,
NULL},
{"IFELSE",
handle_ifelse,
0, IFELSE_BOOL|FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"IFTRUE",
handle_ifelse,
0, IFELSE_TOKEN|IFELSE_BOOL|FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"IFFALSE",
handle_ifelse,
0, IFELSE_FALSE|IFELSE_TOKEN|IFELSE_BOOL|FN_VARARGS|
FN_NO_EVAL,
CA_PUBLIC, NULL},
{"IFZERO",
handle_ifelse,
0, IFELSE_FALSE|FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"ILEV",
fun_ilev,
0, 0,
CA_PUBLIC, NULL},
{"INC",
fun_inc,
1, 0,
CA_PUBLIC, NULL},
{"INDEX",
fun_index, 4, 0,
CA_PUBLIC, NULL},
{"INSERT", fun_insert, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"INUM",
fun_inum,
1, 0,
CA_PUBLIC, NULL},
{"INZONE", scan_zone, 1, TYPE_ROOM, CA_PUBLIC, NULL},
{"ISDBREF", fun_isdbref,
1, 0,
CA_PUBLIC, NULL},
{"ISNUM",
fun_isnum, 1, 0,
CA_PUBLIC, NULL},
{"ISWORD", fun_isword, 1, 0,
CA_PUBLIC, NULL},
{"ISORT",
handle_sort,
0, FN_VARARGS|SORT_POS,
CA_PUBLIC, NULL},
{"ITEMIZE", fun_itemize,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"ITEMS",
fun_items, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"ITER",
perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_NONE|FILT_COND_NONE,
CA_PUBLIC, NULL},
{"ITER2",
perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_NONE|FILT_COND_NONE|
LOOP_TWOLISTS,
CA_PUBLIC, NULL},
{"ISFALSE", perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_NONE|FILT_COND_FALSE,
CA_PUBLIC, NULL},
{"ISTRUE", perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_NONE|FILT_COND_TRUE,
CA_PUBLIC, NULL},
{"ITEXT",
fun_itext, 1, 0,
CA_PUBLIC, NULL},
{"KNOWS",
handle_okpres, 2, PRESFN_KNOWS,
CA_PUBLIC, NULL},
{"LADD",
fun_ladd,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LAND",
handle_logic,
0, FN_VARARGS|LOGIC_LIST|LOGIC_AND,
CA_PUBLIC, NULL},
{"LANDBOOL",
handle_logic,
0, FN_VARARGS|LOGIC_LIST|LOGIC_AND|LOGIC_BOOL,
CA_PUBLIC, NULL},
{"LAST",
fun_last,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LASTACCESS", handle_timestamp, 1, 0,
CA_PUBLIC, NULL},
{"LASTCREATE", fun_lastcreate, 2, 0,
CA_PUBLIC, NULL},
{"LASTMOD", handle_timestamp, 1, TIMESTAMP_MOD, CA_PUBLIC, NULL},
{"LATTR",
handle_lattr,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LCON",
fun_lcon,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LCSTR",
fun_lcstr, -1, 0,
CA_PUBLIC, NULL},
{"LDELETE", fun_ldelete,
0, FN_VARARGS, CA_PUBLIC, NULL},
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

Saturday, June 16, 2012 11:09 PM

529
530
531
532
533
534
535
536

{"LDIFF",

537
538

CA_PUBLIC},
{"LIST2",
perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_NONE|FILT_COND_NONE|
LOOP_NOTIFY|LOOP_TWOLISTS,
CA_PUBLIC},
{"LIT",
fun_lit,
-1, FN_NO_EVAL, CA_PUBLIC, NULL},
{"LINK",
fun_link,
2, 0,
CA_PUBLIC, NULL},
{"LINSTANCES", fun_linstances, 0, 0,
CA_PUBLIC, NULL},
{"LINTER", handle_sets,
0, FN_VARARGS|SET_TYPE|SET_INTERSECT,
CA_PUBLIC, NULL},
{"LJUST",
fun_ljust, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"LMAX",
fun_lmax,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LMIN",
fun_lmin,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LN",
fun_ln,
1, 0,
CA_PUBLIC, NULL},
{"LNUM",
fun_lnum,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LOAD",
fun_load,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LOC",
handle_loc, 1, 0,
CA_PUBLIC, NULL},
{"LOCATE", fun_locate, 3, 0,
CA_PUBLIC, NULL},
{"LOCALIZE",
fun_localize,
1, FN_NO_EVAL, CA_PUBLIC, NULL},
{"LOCK",
fun_lock,
1, 0,
CA_PUBLIC, NULL},
{"LOG",
fun_log,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LPARENT", fun_lparent,
0, FN_VARARGS, CA_PUBLIC},
{"LOOP",
perform_loop,
0, FN_VARARGS|FN_NO_EVAL|LOOP_NOTIFY,
CA_PUBLIC, NULL},
{"LOR",
handle_logic,
0, FN_VARARGS|LOGIC_LIST|LOGIC_OR,
CA_PUBLIC, NULL},
{"LORBOOL", handle_logic,
0, FN_VARARGS|LOGIC_LIST|LOGIC_OR|LOGIC_BOOL,
CA_PUBLIC, NULL},
{"LPOS",
fun_lpos,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LRAND",
fun_lrand, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"LREGS",
fun_lregs, 0, 0,
CA_PUBLIC, NULL},
{"LREPLACE",
fun_lreplace,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"LSTACK", fun_lstack, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"LSTRUCTURES", fun_lstructures, 0, 0,
CA_PUBLIC, NULL},
{"LT",
fun_lt,
2, 0,
CA_PUBLIC, NULL},
{"LTE",
fun_lte,
2, 0,
CA_PUBLIC, NULL},
{"LUNION", handle_sets,
0, FN_VARARGS|SET_TYPE|SET_UNION,
CA_PUBLIC, NULL},
{"LVARS",
fun_lvars, 0, 0,
CA_PUBLIC, NULL},
{"LWHO",
fun_lwho,
0, 0,
CA_PUBLIC, NULL},
{"MAP",
fun_map,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"MATCH",
fun_match, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"MATCHALL",
fun_matchall,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"MAX",
fun_max,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"MEMBER", fun_member, 0, FN_VARARGS, CA_PUBLIC, NULL},

539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

{"LEDIT",
{"LEFT",
{"LET",
{"LEXITS",
{"LIST",
LOOP_NOTIFY,

handle_sets,

0, FN_VARARGS|SET_TYPE|SET_DIFF,
CA_PUBLIC, NULL},
fun_ledit, 0, FN_VARARGS, CA_PUBLIC, NULL},
fun_left,
2, 0,
CA_PUBLIC, NULL},
fun_let,
0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
fun_lexits, 0, FN_VARARGS, CA_PUBLIC, NULL},
perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_NONE|FILT_COND_NONE|

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632

{"MERGE",
{"MID",
{"MIN",
{"MIX",
{"MODULO",
{"MODIFY",
{"MONEY",
{"MOVES",
{"MUDNAME",
{"MUL",
{"MUNGE",
{"NAME",
{"NATTR",
{"NCOMP",
{"NEARBY",
{"NEQ",
{"NESCAPE",
{"NEXT",
{"NONZERO",
{"NOT",
{"NOTBOOL",
{"NSECURE",
{"NULL",
{"NUM",
{"OBJ",
{"OBJCALL",
{"OBJEVAL",
{"OBJMEM",
{"OEMIT",
{"OR",
{"ORBOOL",
{"ORFLAGS",
{"OWNER",
{"PARENT",
{"PARSE",
{"PEEK",
{"PEMIT",
{"PFIND",
{"PI",
{"PLAYMEM",
{"PMATCH",
{"POP",
{"POPN",
{"PORTS",
{"POS",
{"POSS",

Saturday, June 16, 2012 11:09 PM

fun_merge, 3, 0,
CA_PUBLIC, NULL},
fun_mid,
3, 0,
CA_PUBLIC, NULL},
fun_min,
0, FN_VARARGS, CA_PUBLIC, NULL},
fun_mix,
0, FN_VARARGS, CA_PUBLIC, NULL},
fun_modulo, 2, 0,
CA_PUBLIC, NULL},
fun_modify, 0, FN_VARARGS, CA_PUBLIC, NULL},
fun_money, 1, 0,
CA_PUBLIC, NULL},
handle_okpres, 2, PRESFN_MOVES,
CA_PUBLIC, NULL},
fun_mudname,
0, 0,
CA_PUBLIC, NULL},
fun_mul,
0, FN_VARARGS, CA_PUBLIC, NULL},
fun_munge, 0, FN_VARARGS, CA_PUBLIC, NULL},
handle_name,
1, 0,
CA_PUBLIC, NULL},
handle_lattr,
1, LATTR_COUNT,
CA_PUBLIC, NULL},
fun_ncomp, 2, 0,
CA_PUBLIC, NULL},
fun_nearby, 2, 0,
CA_PUBLIC, NULL},
fun_neq,
2, 0,
CA_PUBLIC, NULL},
fun_escape, -1, FN_NO_EVAL, CA_PUBLIC, NULL},
fun_next,
1, 0,
CA_PUBLIC, NULL},
handle_ifelse, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
fun_not,
1, 0,
CA_PUBLIC, NULL},
fun_notbool,
1, 0,
CA_PUBLIC, NULL},
fun_secure, -1, FN_NO_EVAL, CA_PUBLIC, NULL},
fun_null,
1, 0,
CA_PUBLIC, NULL},
fun_num,
1, 0,
CA_PUBLIC, NULL},
handle_pronoun, 1, PRONOUN_OBJ, CA_PUBLIC, NULL},
fun_objcall,
0, FN_VARARGS, CA_PUBLIC, NULL},
fun_objeval,
2, FN_NO_EVAL, CA_PUBLIC, NULL},
fun_objmem, 1, 0,
CA_PUBLIC, NULL},
fun_oemit, 2, 0,
CA_PUBLIC, NULL},
handle_logic,
0, FN_VARARGS|LOGIC_OR,
CA_PUBLIC, NULL},
handle_logic,
0, FN_VARARGS|LOGIC_OR|LOGIC_BOOL,
CA_PUBLIC, NULL},
handle_flaglists, 2, LOGIC_OR, CA_PUBLIC, NULL},
fun_owner, 1, 0,
CA_PUBLIC, NULL},
fun_parent, 1, 0,
CA_PUBLIC, NULL},
perform_loop,
0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
handle_pop, 0, FN_VARARGS|POP_PEEK,
CA_PUBLIC, NULL},
fun_pemit, 2, 0,
CA_PUBLIC, NULL},
fun_pfind, 1, 0,
CA_PUBLIC, NULL},
fun_pi,
0, 0,
CA_PUBLIC, NULL},
fun_playmem,
1, 0,
CA_PUBLIC, NULL},
fun_pmatch, 1, 0,
CA_PUBLIC, NULL},
handle_pop, 0, FN_VARARGS, CA_PUBLIC, NULL},
fun_popn,
0, FN_VARARGS, CA_PUBLIC, NULL},
fun_ports, 0, FN_VARARGS, CA_WIZARD, NULL},
fun_pos,
2, 0,
CA_PUBLIC, NULL},
handle_pronoun, 1, PRONOUN_POSS, CA_PUBLIC,
NULL},
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685

Saturday, June 16, 2012 11:09 PM

{"POWER",
fun_power, 2, 0,
CA_PUBLIC, NULL},
{"PRIVATE",
fun_private,
1, FN_NO_EVAL, CA_PUBLIC, NULL},
{"PROGRAMMER", fun_programmer, 1, 0,
CA_PUBLIC, NULL},
{"PUSH",
fun_push,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"QVARS",
fun_qvars, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"R",
fun_r,
1, 0,
CA_PUBLIC, NULL},
{"RAND",
fun_rand,
1, 0,
CA_PUBLIC, NULL},
{"RBORDER", perform_border, 0, FN_VARARGS|JUST_RIGHT,
CA_PUBLIC, NULL},
{"READ",
fun_read,
3, 0,
CA_PUBLIC, NULL},
{"REGEDIT", perform_regedit, 3, 0,
CA_PUBLIC, NULL},
{"REGEDITALL", perform_regedit, 3, REG_MATCH_ALL,
CA_PUBLIC, NULL},
{"REGEDITALLI", perform_regedit, 3, REG_MATCH_ALL|REG_CASELESS,
CA_PUBLIC, NULL},
{"REGEDITI",
perform_regedit, 3, REG_CASELESS,
CA_PUBLIC, NULL},
{"REGRAB", perform_regrab, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"REGRABALL",
perform_regrab, 0, FN_VARARGS|REG_MATCH_ALL,
CA_PUBLIC, NULL},
{"REGRABALLI", perform_regrab, 0, FN_VARARGS|REG_MATCH_ALL|REG_CASELESS,
CA_PUBLIC, NULL},
{"REGRABI", perform_regrab, 0, FN_VARARGS|REG_CASELESS,
CA_PUBLIC, NULL},
{"REGREP", perform_grep,
0, FN_VARARGS|GREP_REGEXP,
CA_PUBLIC, NULL},
{"REGREPI", perform_grep,
0, FN_VARARGS|GREP_REGEXP|REG_CASELESS,
CA_PUBLIC, NULL},
{"REGMATCH",
perform_regmatch, 0, FN_VARARGS,
CA_PUBLIC, NULL},
{"REGMATCHI",
perform_regmatch, 0, FN_VARARGS|REG_CASELESS,
CA_PUBLIC, NULL},
{"REGPARSE",
perform_regparse, 3, 0,
CA_PUBLIC, NULL},
{"REGPARSEI",
perform_regparse, 3, REG_CASELESS,
CA_PUBLIC, NULL},
{"REMAINDER",
fun_remainder, 2, 0,
CA_PUBLIC, NULL},
{"REMIT",
fun_remit, 2, 0,
CA_PUBLIC, NULL},
{"REMOVE", fun_remove, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"REPEAT", fun_repeat, 2, 0,
CA_PUBLIC, NULL},
{"REPLACE", fun_replace,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"REST",
fun_rest,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"RESTARTS",
fun_restarts,
0, 0,
CA_PUBLIC, NULL},
{"RESTARTTIME", fun_restarttime, 0, 0,
CA_PUBLIC, NULL},
{"REVERSE", fun_reverse,
-1, 0,
CA_PUBLIC, NULL},
{"REVWORDS",
fun_revwords,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"RIGHT",
fun_right, 2, 0,
CA_PUBLIC, NULL},
{"RJUST",
fun_rjust, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"RLOC",
fun_rloc,
2, 0,
CA_PUBLIC, NULL},
{"ROOM",
fun_room,
1, 0,
CA_PUBLIC, NULL},
{"ROUND",
fun_round, 2, 0,
CA_PUBLIC, NULL},
{"RTABLES", process_tables, 0, FN_VARARGS|JUST_RIGHT,
CA_PUBLIC, NULL},
{"S",
fun_s,
-1, 0,
CA_PUBLIC, NULL},
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738

Saturday, June 16, 2012 11:09 PM

{"SCRAMBLE",
fun_scramble,
1, 0,
CA_PUBLIC, NULL},
{"SEARCH", fun_search, -1, 0,
CA_PUBLIC, NULL},
{"SECS",
fun_secs,
0, 0,
CA_PUBLIC, NULL},
{"SECURE", fun_secure, -1, 0,
CA_PUBLIC, NULL},
{"SEES",
fun_sees,
2, 0,
CA_PUBLIC, NULL},
{"SESSION", fun_session,
1, 0,
CA_PUBLIC, NULL},
{"SET",
fun_set,
2, 0,
CA_PUBLIC, NULL},
{"SETDIFF", handle_sets,
0, FN_VARARGS|SET_DIFF,
CA_PUBLIC, NULL},
{"SETINTER",
handle_sets,
0, FN_VARARGS|SET_INTERSECT,
CA_PUBLIC, NULL},
{"SETQ",
fun_setq,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"SETR",
fun_setr,
2, 0,
CA_PUBLIC, NULL},
{"SETX",
fun_setx,
2, 0,
CA_PUBLIC, NULL},
{"SETUNION",
handle_sets,
0, FN_VARARGS|SET_UNION,
CA_PUBLIC, NULL},
{"SHL",
fun_shl,
2, 0,
CA_PUBLIC, NULL},
{"SHR",
fun_shr,
2, 0,
CA_PUBLIC, NULL},
{"SHUFFLE", fun_shuffle,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"SIGN",
fun_sign,
1, 0,
CA_PUBLIC, NULL},
{"SIN",
handle_trig,
1, 0,
CA_PUBLIC, NULL},
{"SIND",
handle_trig,
1, TRIG_DEG,
CA_PUBLIC, NULL},
{"SORT",
handle_sort,
0, FN_VARARGS|SORT_ITEMS, CA_PUBLIC,
{"SORTBY", fun_sortby, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"SPACE",
fun_space, 1, 0,
CA_PUBLIC, NULL},
{"SPEAK",
fun_speak, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"SPLICE", fun_splice, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"SQL",
fun_sql,
0, FN_VARARGS, CA_SQL_OK, NULL},
{"SQRT",
fun_sqrt,
1, 0,
CA_PUBLIC, NULL},
{"SQUISH", fun_squish, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"STARTTIME",
fun_starttime, 0, 0,
CA_PUBLIC, NULL},
{"STATS",
fun_stats, 1, 0,
CA_PUBLIC, NULL},
{"STEP",
fun_step,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"STORE",
fun_store, 2, 0,
CA_PUBLIC, NULL},
{"STRCAT", fun_strcat, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"STREQ",
fun_streq, 2, 0,
CA_PUBLIC, NULL},
{"STRIPANSI",
fun_stripansi, 1, 0,
CA_PUBLIC, NULL},
{"STRLEN", fun_strlen, -1, 0,
CA_PUBLIC, NULL},
{"STRMATCH",
fun_strmatch,
2, 0,
CA_PUBLIC, NULL},
{"STRTRUNC",
fun_left,
2, 0,
CA_PUBLIC, NULL},
{"STRUCTURE",
fun_structure, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"SUB",
fun_sub,
2, 0,
CA_PUBLIC, NULL},
{"SUBJ",
handle_pronoun, 1, PRONOUN_SUBJ, CA_PUBLIC,
NULL},
{"SWAP",
fun_swap,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"SWITCH", fun_switch, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"SWITCHALL",
fun_switchall, 0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"T",
fun_t,
1, 0,
CA_PUBLIC, NULL},
{"TABLE",
fun_table, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"TABLES", process_tables, 0, FN_VARARGS|JUST_LEFT,
CA_PUBLIC, NULL},
{"TAN",
handle_trig,
1, TRIG_TAN,
CA_PUBLIC, NULL},
-14-

NULL},

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790

{"TAND",

Saturday, June 16, 2012 11:09 PM

handle_trig,

1, TRIG_TAN|TRIG_DEG,
CA_PUBLIC, NULL},
{"TEL",
fun_tel,
2, 0,
CA_PUBLIC, NULL},
{"TIME",
fun_time,
0, 0,
CA_PUBLIC, NULL},
{"TIMEFMT", fun_timefmt,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"TOSS",
handle_pop, 0, FN_VARARGS|POP_TOSS,
CA_PUBLIC, NULL},
{"TRANSLATE",
fun_translate, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"TRIGGER", fun_trigger,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"TRIM",
fun_trim,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"TRUNC",
fun_trunc, 1, 0,
CA_PUBLIC, NULL},
{"TYPE",
fun_type,
1, 0,
CA_PUBLIC, NULL},
{"U",
do_ufun,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"UCSTR",
fun_ucstr, -1, 0,
CA_PUBLIC, NULL},
{"UDEFAULT",
fun_udefault,
0, FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"ULOCAL", do_ufun,
0, FN_VARARGS|U_LOCAL,
CA_PUBLIC, NULL},
{"UNLOAD", fun_unload, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"UNSTRUCTURE", fun_unstructure,1, 0,
CA_PUBLIC, NULL},
{"UNTIL",
fun_until, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"UPRIVATE",
do_ufun,
0, FN_VARARGS|U_PRIVATE,
CA_PUBLIC, NULL},
#ifdef PUEBLO_SUPPORT
{"URL_ESCAPE", fun_url_escape, -1, 0,
CA_PUBLIC, NULL},
{"URL_UNESCAPE",fun_url_unescape,-1,0,
CA_PUBLIC, NULL},
#endif /* PUEBLO_SUPPORT */
{"USETRUE",
handle_ifelse, 0, IFELSE_DEFAULT|IFELSE_BOOL|FN_VARARGS|FN_NO_EVAL,
CA_PUBLIC, NULL},
{"USEFALSE",
handle_ifelse, 0, IFELSE_FALSE|IFELSE_DEFAULT|IFELSE_BOOL|FN_VARARGS|
FN_NO_EVAL,
CA_PUBLIC, NULL},
{"V",
fun_v,
1, 0,
CA_PUBLIC, NULL},
{"VADD",
handle_vectors, 0, FN_VARARGS|VEC_ADD,
CA_PUBLIC, NULL},
{"VALID",
fun_valid, 2, FN_VARARGS, CA_PUBLIC, NULL},
{"VDIM",
fun_words, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"VDOT",
handle_vectors, 0, FN_VARARGS|VEC_DOT,
CA_PUBLIC, NULL},
{"VERSION", fun_version,
0, 0,
CA_PUBLIC, NULL},
{"VISIBLE", fun_visible,
2, 0,
CA_PUBLIC, NULL},
{"VMAG",
handle_vector, 0, FN_VARARGS|VEC_MAG,
CA_PUBLIC, NULL},
{"VMUL",
handle_vectors, 0, FN_VARARGS|VEC_MUL,
CA_PUBLIC, NULL},
{"VSUB",
handle_vectors, 0, FN_VARARGS|VEC_SUB,
CA_PUBLIC, NULL},
{"VUNIT",
handle_vector, 0, FN_VARARGS|VEC_UNIT,
CA_PUBLIC, NULL},
{"WAIT",
fun_wait,
2, 0,
CA_PUBLIC, NULL},
{"WHENFALSE",
perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_FALSE|FILT_COND_NONE,
CA_PUBLIC, NULL},
{"WHENTRUE",
perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_TRUE|FILT_COND_NONE,
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\fnproto.h

791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824

Saturday, June 16, 2012 11:09 PM

CA_PUBLIC, NULL},
{"WHENFALSE2", perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_FALSE|FILT_COND_NONE
|LOOP_TWOLISTS,
CA_PUBLIC, NULL},
{"WHENTRUE2",
perform_iter,
0, FN_VARARGS|FN_NO_EVAL|BOOL_COND_TRUE|FILT_COND_NONE|
LOOP_TWOLISTS,
CA_PUBLIC, NULL},
{"WHERE",
handle_loc, 1, LOCFN_WHERE, CA_PUBLIC, NULL},
{"WHILE",
fun_while, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"WILDGREP",
perform_grep,
0, FN_VARARGS|GREP_WILD,
CA_PUBLIC, NULL},
{"WILDMATCH",
fun_wildmatch, 3, 0,
CA_PUBLIC, NULL},
{"WILDPARSE",
fun_wildparse, 3, 0,
CA_PUBLIC, NULL},
{"WIPE",
fun_wipe,
1, 0,
CA_PUBLIC, NULL},
{"WORDPOS",
fun_wordpos,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"WORDS",
fun_words, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"WRITABLE",
fun_writable,
2, 0,
CA_PUBLIC, NULL},
{"WRITE",
fun_write, 2, 0,
CA_PUBLIC, NULL},
{"X",
fun_x,
1, 0,
CA_PUBLIC, NULL},
{"XCON",
fun_xcon,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"XGET",
perform_get,
2, GET_XARGS, CA_PUBLIC, NULL},
{"XOR",
handle_logic,
0, FN_VARARGS|LOGIC_XOR,
CA_PUBLIC, NULL},
{"XORBOOL", handle_logic,
0, FN_VARARGS|LOGIC_XOR|LOGIC_BOOL,
CA_PUBLIC, NULL},
{"XVARS",
fun_xvars, 0, FN_VARARGS, CA_PUBLIC, NULL},
{"Z",
fun_z,
2, 0,
CA_PUBLIC, NULL},
{"ZFUN",
fun_zfun,
0, FN_VARARGS, CA_PUBLIC, NULL},
{"ZONE",
fun_zone,
1, 0,
CA_PUBLIC, NULL},
{"ZWHO",
scan_zone, 1, TYPE_PLAYER,
CA_PUBLIC, NULL},
{NULL,
NULL,
0, 0,
0,
NULL}};
/* *INDENT-ON* */
#endif /* __FNPROTO_H */

-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Saturday, June 16, 2012 11:43 PM

/* functions.c - MUSH function handlers */


/* $Id: functions.c,v 1.175 2008/02/21 15:21:15 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include
#include
#include
#include
#include
#include

"command.h"
/* required by code */
"match.h" /* required by code */
"attrs.h" /* required by code */
"powers.h" /* required by code */
"functions.h" /* required by code */
"fnproto.h"
/* required by code */

extern int FDECL(parse_ext_access, (int *, EXTFUNCS **, char *, NAMETAB *, dbref, char
*));
extern NAMETAB access_nametab[];
UFUN *ufun_head;
const Delim SPACE_DELIM = { 1, " " };
void NDECL(init_functab)
{
FUN *fp;
hashinit(&mudstate.func_htab, 250 * HASH_FACTOR, HT_STR|HT_KEYREF);

for (fp = flist; fp->name; fp++) {


hashadd((char *)fp->name, (int *)fp, &mudstate.func_htab, 0);
}
ufun_head = NULL;
hashinit(&mudstate.ufunc_htab, 15 * HASH_FACTOR, HT_STR);

void do_function(player, cause, key, fname, target)


dbref player, cause;
int key;
char *fname, *target;
{
UFUN *ufp, *ufp2;
ATTR *ap;
char *np, *bp;
int atr, aflags;
dbref obj, aowner;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.c

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

Saturday, June 16, 2012 11:43 PM

/* Check for list first */


if (key & FUNCT_LIST) {
if (fname && *fname) {
/* Make it case-insensitive, and look it up. */
for (bp = fname; *bp; bp++) {
*bp = tolower(*bp);
}
ufp = (UFUN *) hashfind(fname, &mudstate.ufunc_htab);
if (ufp) {
notify(player,
tprintf("%s: #%d/%s",
ufp->name, ufp->obj,
((ATTR *) atr_num(ufp->atr))->name));
} else {
notify(player,
tprintf("%s not found in user function table." ,
fname));
}
return;
}
/* No name given, list them all. */

for (ufp = (UFUN *) hash_firstentry(&mudstate.ufunc_htab);


ufp != NULL;
ufp = (UFUN *) hash_nextentry(&mudstate.ufunc_htab)) {
notify(player,
tprintf("%s: #%d/%s",
ufp->name, ufp->obj,
((ATTR *) atr_num(ufp->atr))->name));
}
return;

/* Make a local uppercase copy of the function name */


bp = np = alloc_sbuf("add_user_func");
safe_sb_str(fname, np, &bp);
*bp = '\0';
for (bp = np; *bp; bp++)
*bp = toupper(*bp);
/* Verify that the function doesn't exist in the builtin table */
if (hashfind(np, &mudstate.func_htab) != NULL) {
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.c

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

Saturday, June 16, 2012 11:43 PM

notify_quiet(player,
"Function already defined in builtin function table." );
free_sbuf(np);
return;

}
/* Make sure the target object exists */

if (!parse_attrib(player, target, &obj, &atr, 0)) {


notify_quiet(player, NOMATCH_MESSAGE);
free_sbuf(np);
return;
}
/* Make sure the attribute exists */
if (atr == NOTHING) {
notify_quiet(player, "No such attribute.");
free_sbuf(np);
return;
}
/* Make sure attribute is readably by me */
ap = atr_num(atr);
if (!ap) {
notify_quiet(player, "No such attribute.");
free_sbuf(np);
return;
}
atr_get_info(obj, atr, &aowner, &aflags);
if (!See_attr(player, obj, ap, aowner, aflags)) {
notify_quiet(player, NOPERM_MESSAGE);
free_sbuf(np);
return;
}
/* Privileged functions require you control the obj.

*/

if ((key & FUNCT_PRIV) && !Controls(player, obj)) {


notify_quiet(player, NOPERM_MESSAGE);
free_sbuf(np);
return;
}
/* See if function already exists. If so, redefine it */
ufp = (UFUN *) hashfind(np, &mudstate.ufunc_htab);
if (!ufp) {
ufp = (UFUN *) XMALLOC(sizeof(UFUN), "do_function");
ufp->name = XSTRDUP(np, "do_function.name");
for (bp = (char *)ufp->name; *bp; bp++)
*bp = toupper(*bp);
ufp->obj = obj;
ufp->atr = atr;
ufp->perms = CA_PUBLIC;
ufp->next = NULL;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.c

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

Saturday, June 16, 2012 11:43 PM

if (!ufun_head) {
ufun_head = ufp;
} else {
for (ufp2 = ufun_head; ufp2->next; ufp2 = ufp2->next) ;
ufp2->next = ufp;
}
if (hashadd(np, (int *) ufp, &mudstate.ufunc_htab, 0)) {
notify_quiet(player, tprintf("Function %s not defined.", fname));
XFREE(ufp->name, "do_function");
XFREE(ufp, "do_function.2");
free_sbuf(np);
return;
}
}
ufp->obj = obj;
ufp->atr = atr;
ufp->flags = 0;
if (key & FUNCT_NO_EVAL)
ufp->flags |= FN_NO_EVAL;
if (key & FUNCT_PRIV)
ufp->flags |= FN_PRIV;
if (key & FUNCT_NOREGS)
ufp->flags |= FN_NOREGS;
else if (key & FUNCT_PRES)
ufp->flags |= FN_PRES;

free_sbuf(np);
if (!Quiet(player))
notify_quiet(player, tprintf("Function %s defined.", fname));

/* --------------------------------------------------------------------------* list_functable: List available functions.


*/
void list_functable(player)
dbref player;
{
FUN *fp, *modfns;
UFUN *ufp;
char *buf, *bp;
MODULE *mp;
buf = alloc_lbuf("list_functable");
bp = buf;
safe_str((char *)"Built-in functions:", buf, &bp);
for (fp = flist; fp->name; fp++) {
if (Check_Func_Access(player, fp)) {
safe_chr(' ', buf, &bp);
safe_str((char *) fp->name, buf, &bp);
}
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.c

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

Saturday, June 16, 2012 11:43 PM

}
notify(player, buf);
WALK_ALL_MODULES(mp) {
if ((modfns = DLSYM_VAR(mp->handle, mp->modname, "functable",
FUN *)) != NULL) {
bp = buf;
safe_tprintf_str(buf, &bp, "Module %s functions:",
mp->modname);
for (fp = modfns; fp->name; fp++) {
if (Check_Func_Access(player, fp)) {
safe_chr(' ', buf, &bp);
safe_str((char *) fp->name, buf, &bp);
}
}
notify(player, buf);
}
}
bp = buf;
safe_str((char *)"User-defined functions:", buf, &bp);
for (ufp = ufun_head; ufp; ufp = ufp->next) {
if (check_access(player, ufp->perms)) {
safe_chr(' ', buf, &bp);
safe_str(ufp->name, buf, &bp);
}
}
notify(player, buf);
}

free_lbuf(buf);

/* --------------------------------------------------------------------------* list_funcaccess: List access on functions.


*/
static void helper_list_funcaccess(player, fp, buff)
dbref player;
FUN *fp;
char *buff;
{
char *bp;
int i;
while (fp->name) {
if (Check_Func_Access(player, fp)) {
if (!fp->xperms) {
sprintf(buff, "%s:", fp->name);
} else {
bp = buff;
safe_str((char *) fp->name, buff, &bp);
safe_chr(':', buff, &bp);
for (i = 0; i < fp->xperms->num_funcs; i++) {
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.c

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

Saturday, June 16, 2012 11:43 PM

if (fp->xperms->ext_funcs[i]) {
safe_chr(' ', buff, &bp);
safe_str(fp->xperms->ext_funcs[i]->fn_name,
buff, &bp);
}

}
}
listset_nametab(player, access_nametab,
fp->perms, buff, 1);

}
fp++;

void list_funcaccess(player)
dbref player;
{
char *buff;
FUN *ftab;
UFUN *ufp;
MODULE *mp;
buff = alloc_sbuf("list_funcaccess");
helper_list_funcaccess(player, flist, buff);
WALK_ALL_MODULES(mp) {
if ((ftab = DLSYM_VAR(mp->handle, mp->modname, "functable",
FUN *)) != NULL) {
helper_list_funcaccess(player, ftab, buff);
}
}
for (ufp = ufun_head; ufp; ufp = ufp->next) {
if (check_access(player, ufp->perms)) {
sprintf(buff, "%s:", ufp->name);
listset_nametab(player, access_nametab,
ufp->perms, buff, 1);
}
}
}

free_sbuf(buff);

/* --------------------------------------------------------------------------* cf_func_access: set access on functions


*/
CF_HAND(cf_func_access)
{
FUN *fp;
UFUN *ufp;
char *ap;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.c

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

Saturday, June 16, 2012 11:43 PM

for (ap = str; *ap && !isspace(*ap); ap++) ;


if (*ap)
*ap++ = '\0';

for (fp = flist; fp->name; fp++) {


if (!string_compare(fp->name, str)) {
return (parse_ext_access(&fp->perms, &fp->xperms,
ap, (NAMETAB *) extra,
player, cmd));
}
}
for (ufp = ufun_head; ufp; ufp = ufp->next) {
if (!string_compare(ufp->name, str)) {
return (cf_modify_bits(&ufp->perms, ap, extra,
player, cmd));
}
}
cf_log_notfound(player, cmd, "Function", str);
return -1;

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:08 PM

/* functions.h - declarations for functions & function processing */


/* $Id: functions.h,v 1.73 2009/01/11 18:49:08 lwl Exp $ */
#include "copyright.h"
#ifndef __FUNCTIONS_H
#define __FUNCTIONS_H
/* --------------------------------------------------------------------------* Type definitions.
*/
#define MAX_NFARGS 30
typedef struct fun {
const char *name;
/* Function name */
void
(*fun)();
/* Handler */
int
nargs;
/* Number of args needed or expected */
unsigned int
flags;
/* Function flags */
int
perms;
/* Access to function */
EXTFUNCS
*xperms;
/* Extended access to function */
} FUN;
typedef struct ufun {
char
*name;
/* Function name */
dbref
obj;
/* Object ID */
int
atr;
/* Attribute ID */
unsigned int
flags;
/* Function flags */
int
perms;
/* Access to function */
struct ufun *next;
/* Next ufun in chain */
} UFUN;
typedef struct delim {
size_t
len;
char
str[MAX_DELIM_LEN];
} Delim;
typedef struct var_entry VARENT;
struct var_entry {
char *text;
/* variable text */
};
typedef struct component_def COMPONENT;
struct component_def {
int (*typer_func)();
/* type-checking handler */
char *def_val;
/* default value */
};
typedef struct structure_def STRUCTDEF;
struct structure_def {
char *s_name;
/* name of the structure */
char **c_names;
/* array of component names */
COMPONENT **c_array;
/* array of pointers to components */
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

};

Saturday, June 16, 2012 11:08 PM

int c_count;
/* number of components */
char delim;
/* output delimiter when unloading */
int need_typecheck;
/* any components without types of any? */
int n_instances;
/* number of instances out there */
char *names_base;
/* pointer for later freeing */
char *defs_base;
/* pointer for later freeing */

typedef struct instance_def INSTANCE;


struct instance_def {
STRUCTDEF *datatype;
/* pointer to structure data type def */
};
typedef struct data_def STRUCTDATA;
struct data_def {
char *text;
};
typedef struct object_stack OBJSTACK;
struct object_stack {
char *data;
OBJSTACK *next;
};
#ifdef FLOATING_POINTS
#ifndef linux
double atof();
#endif
#define aton atof
typedef double NVAL;
#else
#define aton atoi
typedef int NVAL;
#endif

/* linux defines atof as a macro */


/* ! linux */

/* FLOATING_POINTS */

/* --------------------------------------------------------------------------* Constants used in delimiter macros.


*/
#define
#define
#define
#define

DELIM_EVAL 0x001
/* Must eval delimiter. */
DELIM_NULL 0x002
/* Null delimiter okay. */
DELIM_CRLF 0x004
/* '%r' delimiter okay. */
DELIM_STRING
0x008
/* Multi-character delimiter okay. */

/* --------------------------------------------------------------------------* Function declarations.


*/
extern const Delim SPACE_DELIM;
extern char *FDECL(trim_space_sep, (char *, const Delim *));
extern char *FDECL(next_token, (char *, const Delim *));
extern char *FDECL(split_token, (char **, const Delim *));
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

Saturday, June 16, 2012 11:08 PM

extern char *FDECL(next_token_ansi, (char *, const Delim *, int *));


extern int FDECL(countwords, (char *, const Delim *));
extern int FDECL(list2arr, (char ***, int, char *, const Delim *));
extern void FDECL(arr2list, (char **, int, char *, char **, const Delim *));
extern int FDECL(list2ansi, (int *, int *, int, char *, const Delim *));
extern INLINE void FDECL(do_reverse, (char *, char *));
extern int FDECL(fn_range_check, (const char *, int, int, int, char *, char **));
extern int FDECL(delim_check, ( char *, char **, dbref, dbref, dbref, char **, int, char
**, int, int, Delim *, int ));
/* --------------------------------------------------------------------------* Function prototype macro.
*/
#define FUNCTION_ARGLIST buff, bufc, player, caller, cause, fargs, nfargs, cargs, ncargs
#define FUNCTION(x) \
void x( FUNCTION_ARGLIST ) \
char *buff, **bufc; \
dbref player, caller, cause; \
char *fargs[], *cargs[]; \
int nfargs, ncargs;
/* --------------------------------------------------------------------------* Delimiter macros for functions that take an optional delimiter character.
*/
/* Minimum work needed to copy a delimiter. Assumes that the "str" member
* of the Delim struct is last.
*/
#define Delim_Copy(sep_dest, sep_src) \
memcpy((sep_dest), (sep_src), \
sizeof(Delim) - MAX_DELIM_LEN + 1 + (sep_src)->len)
/* Separator checking "helper" macros.
*
VaChk_Sep(sep_ptr, sep_len, arg_n, flags): Use arg_n as separator.
*
VaChk_InSep(arg_number, flags): Use arg_number as input sep.
*
VaChk_DefaultOut(arg_number): If nfargs less than arg_number,
*
use the input separator. DO NOT PUT A SEMI-COLON AFTER THIS MACRO.
*
VaChk_OutSep(arg_number, flags): Use arg_number as output sep.
*/
#define VaChk_Sep(xsep, xargnum, xflags) \
if (!delim_check( FUNCTION_ARGLIST, xargnum, xsep, xflags)) \
return
#define VaChk_InSep(xargnum, xflags) \
VaChk_Sep(&isep, xargnum, (xflags)|DELIM_STRING)
#define VaChk_DefaultOut(xargnum) \
if (nfargs < xargnum) { \
Delim_Copy(&osep, &isep); \
} else
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

Saturday, June 16, 2012 11:08 PM

#define VaChk_OutSep(xargnum, xflags) \


VaChk_Sep(&osep, xargnum, (xflags)|DELIM_STRING|DELIM_NULL|DELIM_CRLF)
/*
* VaChk_Range(min_args, max_args): Functions which take
*
between min_args and max_args. Don't check for delimiters.
*
* VaChk_Only_InPure(max_args): Functions which take max_args - 1
*
args or, with a delimiter, max_args args. No special stuff.
*
* VaChk_Only_In(max_args): Functions which take max_args - 1 args
*
or, with a delimiter, max_args args.
*
* VaChk_Only_Out(max_args): Functions which take max_args - 1 args
*
or, with a delimiter, max_args args. The one delimiter is an output delim.
*
* VaChk_InPure(max_args): Functions which take max_args - 1
*
args or, with a delimiter, max_args args. No special stuff.
*
* VaChk_In(min_args, max_args): Functions which take
*
between min_args and max_args, with max_args as a delimiter.
*
* VaChk_Out(min_args, max_args): Functions which take
*
between min_args and max_args, with max_args as an output delimiter.
*
* VaChk_Only_In_Out(max_args): Functions which take at least
*
max_args - 2, with max_args - 1 as an input delimiter, and max_args as
*
an output delimiter.
*
* VaChk_In_Out(min_args, max_args): Functions which take at
*
least min_args, with max_args - 1 as an input delimiter, and max_args
*
as an output delimiter.
*
* VaChk_InEval_OutEval(min_args, max_args): Functions which
*
take at least min_args, with max_args - 1 as an input delimiter that
*
must be evaluated, and max_args as an output delimiter which must
*
be evaluated.
*/
#define VaChk_Range(xminargs,xnargs) \
if (!fn_range_check(((FUN *)fargs[-1])->name, nfargs, xminargs, xnargs, \
buff, bufc)) \
return
#define VaChk_Only_InPure(xnargs) \
VaChk_Range(xnargs-1, xnargs); \
if (!delim_check( FUNCTION_ARGLIST, xnargs, &isep, 0)) \
return
#define VaChk_Only_In(xnargs) \
VaChk_Range(xnargs-1, xnargs); \
VaChk_InSep(xnargs, 0)
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

Saturday, June 16, 2012 11:08 PM

#define VaChk_Only_Out(xnargs) \
VaChk_Range(xnargs-1, xnargs); \
VaChk_OutSep(xnargs, 0)
#define VaChk_InPure(xminargs, xnargs) \
VaChk_Range(xminargs, xnargs); \
if (!delim_check( FUNCTION_ARGLIST, xnargs, &isep, 0)) \
return
#define VaChk_In(xminargs, xnargs) \
VaChk_Range(xminargs, xnargs); \
VaChk_InSep(xnargs, 0)
#define VaChk_Out(xminargs, xnargs) \
VaChk_Range(xminargs, xnargs); \
VaChk_OutSep(xnargs, 0)
#define VaChk_Only_In_Out(xnargs) \
VaChk_Range(xnargs-2, xnargs); \
VaChk_InSep(xnargs-1, 0); \
VaChk_DefaultOut(xnargs) { \
VaChk_OutSep(xnargs, 0); \
}
#define VaChk_In_Out(xminargs, xnargs) \
VaChk_Range(xminargs, xnargs); \
VaChk_InSep(xnargs-1, 0); \
VaChk_DefaultOut(xnargs) { \
VaChk_OutSep(xnargs, 0); \
}
#define VaChk_InEval_OutEval(xminargs, xnargs) \
VaChk_Range(xminargs, xnargs); \
VaChk_InSep(xnargs-1, DELIM_EVAL); \
VaChk_OutSep(xnargs, DELIM_EVAL)
#define VaChk_Only_InEval(xnargs) \
VaChk_Range(xnargs-1, xnargs); \
VaChk_InSep(xnargs, DELIM_EVAL)
/* --------------------------------------------------------------------------* Miscellaneous macros.
*/
/* Get function flags. Note that Is_Func() and Func_Mask() are identical;
* they are given specific names for code clarity.
*/
#define Func_Flags(x)
#define Is_Func(x)
#define Func_Mask(x)

(((FUN *)(x)[-1])->flags)
(((FUN *)fargs[-1])->flags & (x))
(((FUN *)fargs[-1])->flags & (x))

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

Saturday, June 16, 2012 11:08 PM

/* Check access to built-in function. */


#define Check_Func_Access(p,f) \
(check_access(p,(f)->perms) && \
(!((f)->xperms) || check_mod_access(p,(f)->xperms)))
/* Trim spaces. */
#define Eat_Spaces(x)

trim_space_sep((x), &SPACE_DELIM)

/* Special handling of separators. */


#define print_sep(s,b,p) \
if ((s)->len == 1) { \
if ((s)->str[0] == '\r') { \
safe_crlf((b),(p)); \
} else if ((s)->str[0] != '\0') { \
safe_chr((s)->str[0],(b),(p)); \
} \
} else { \
safe_known_str((s)->str, (s)->len, (b), (p)); \
}
/* Macro for finding an <attr> or <obj>/<attr>
* Parse_Uattr(player, string to parse, thing, attribute number, attr pointer)
*/
#define Parse_Uattr(p,s,t,n,a)
\
if (parse_attrib((p), (s), &(t), &(n), 0)) {
if (((n) == NOTHING) || !(Good_obj(t)))
\
(a) = NULL;
\
else
\
(a) = atr_num(n);
\
} else {
\
(t) = (p);
\
(a) = atr_str(s);
\
}

/* Macro for obtaining an attrib


* Get_Uattr(player, thing, attr pointer, text buffer, owner, flags, length)
*/
#define Get_Uattr(p,t,a,b,o,f,l)
\
if (!(a)) {
\
return;
\
}
\
(b) = atr_pget((t), (a)->number, &(o), &(f), &(l));
if (!*(b) || !(See_attr((p), (t), (a), (o), (f)))) {
free_lbuf(b);
\
return;
\
}

\
\

/* Macro for getting an <attr>, <obj>/<attr> or #lambda/<code>


-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

Saturday, June 16, 2012 11:08 PM

* Get_Ulambda(player, thing, string, anum, ap, atext, aowner, aflags, alen)


*/
#define Get_Ulambda(p,t,s,n,a,b,o,f,l)
if (string_prefix((s), "#lambda/")) {
(t) = (p);
\
(n) = NOTHING;
\
(a) = NULL;
\
(b) = alloc_lbuf("lambda.atext");
(l) = strlen((s) + 8);
\
StrCopyKnown((b), (s) + 8, (l));
(o) = (p);
\
(f) = 0;
\
} else {
\
Parse_Uattr((p),(s),(t),(n),(a));
Get_Uattr((p),(t),(a),(b),(o),(f),(l));
}

\
\

\
\

/* Macro for writing a certain amount of padding into a buffer.


* l is the number of characters left to write.
* m is a throwaway integer for holding the maximum.
* c is the separator character to use.
*/
#define print_padding(l,m,c) \
if ((l) > 0) { \
(m) = LBUF_SIZE - 1 - (*bufc - buff); \
(l) = ((l) > (m)) ? (m) : (l); \
memset(*bufc, (c), (l)); \
*bufc += (l); \
**bufc = '\0'; \
}
/* Handling CPU time checking. */
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*

CPU time "clock()" compatibility notes:


Linux clock() doesn't necessarily start at 0.
BSD clock() does appear to always start at 0.
Linux sets CLOCKS_PER_SEC to 1000000, citing POSIX, so its clock()
will wrap around from (32-bit) INT_MAX to INT_MIN every 72 cpu-minutes
or so. The actual clock resolution is low enough that, for example,
it probably never returns odd numbers.
BSD sets CLOCKS_PER_SEC to 100, so theoretically I could hose a cpu
for 250 days and see what it does when it hits INT_MAX. Any bets? Any
possible reason to care?
NetBSD clock() can occasionally decrease as the scheduler's estimate of
how much cpu the mush will use during the current timeslice is revised,
so we can't use subtraction.

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

Saturday, June 16, 2012 11:08 PM

* BSD clock() returns -1 if there is an error.


*/
/*
* CPU time logic notes:
*
* B = mudstate.cputime_base
* L = mudstate.cputime_base + mudconf.func_cpu_lim
* N = mudstate.cputime_now
*
* Assuming B != -1 and N != -1 to catch errors on BSD, the possible
* combinations of these values are as follows (note >> means "much
* greater than", not right shift):
*
* 1. B < L normal
-- limit should be checked, and is not wrapped yet
* 2. B == L disabled -- limit should not be checked
* 3. B > L strange -- probably misconfigured
* 4. B >> L wrapped -- limit should be checked, and note L wrapped
*
* 1. normal:
* 1a. N << B
-- too much, N wrapped
* 1b. N < B
-- fine, NetBSD counted backwards
* 1c. N >= B, N <= L -- fine
* 1d. N > L
-- too much
*
* 2. disabled:
* 2a. always
-- fine, not checking
*
* 3. strange:
* 3a. always
-- fine, I guess we shouldn't check
*
* 4. wrapped:
* 4a. N <= L
-- fine, N wrapped but not over limit yet
* 4b. N > L, N << B -- too much, N wrapped
* 4c. N < B
-- fine, NetBSD counted backwards
* 4d. N >= B
-- fine
*
* Note that 1a, 1d, and 4b are the cases where we can be certain that
* too much cpu has been used. The code below only checks for 1d. The
* other two are corner cases that require some distinction between
* "x > y" and "x >> y".
*/
#define Too_Much_CPU() \
((mudstate.cputime_now = clock()), \
((mudstate.cputime_now > mudstate.cputime_base + mudconf.func_cpu_lim) && \
(mudstate.cputime_base + mudconf.func_cpu_lim > mudstate.cputime_base) && \
(mudstate.cputime_base != -1) && \
(mudstate.cputime_now != -1)))
/* --------------------------------------------------------------------------* Function-specific flags used in the function table.
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

Saturday, June 16, 2012 11:08 PM

*/
/* from
#define
#define
#define

handle_sort
SORT_OPER
SORT_ITEMS
SORT_POS

(sort, isort): */
0x0f
/* mask to select sort operation bits */
0
1

/* from
#define
#define
#define
#define
#define

handle_sets (setunion, setdiff, setinter, lunion, ldiff, linter): */


SET_OPER
0x0f
/* mask to select set operation bits */
SET_UNION
0
SET_INTERSECT
1
SET_DIFF
2
SET_TYPE
0x10
/* set type is given, don't autodetect */

/* from
/* from
#define
#define
#define
#define

process_tables (tables, rtables, ctables): */


perform_border (border, rborder, cborder): */
JUST_TYPE
0x0f
/* mask to select justification bits */
JUST_LEFT
0
JUST_RIGHT 1
JUST_CENTER 2

/* from handle_logic (and, or, andbool, orbool, land, lor, landbool, lorbool,
*
cand, cor, candbool, corbool, xor, xorbool): */
/* from handle_flaglists (andflags, orflags): */
/* from handle_filter (filter, filterbool): */
#define LOGIC_OPER 0x0f
/* mask to select boolean operation bits */
#define LOGIC_AND
0
#define LOGIC_OR
1
#define LOGIC_XOR
2
#define LOGIC_BOOL 0x10
/* interpret operands as boolean, not int */
#define LOGIC_LIST 0x40
/* operands come in a list, not separately */
/* from handle_vectors (vadd, vsub, vmul, vdot): */
#define VEC_OPER
0x0f
/* mask to select vector operation bits */
#define VEC_ADD
0
#define VEC_SUB
1
#define VEC_MUL
2
#define VEC_DOT
3
/* #define VEC_CROSS
4 -- not implemented */
/* from handle_vector (vmag, vunit): */
#define VEC_MAG
5
#define VEC_UNIT
6
/* from
/* from
#define
#define
#define
#define
#define
#define
#define

perform_loop (loop, parse): */


perform_iter (list, iter, whentrue, whenfalse, istrue, isfalse): */
BOOL_COND_TYPE 0x0f
/* mask to select exit-condition bits */
BOOL_COND_NONE 1
/* loop until end of list */
BOOL_COND_FALSE 2
/* loop until true */
BOOL_COND_TRUE 3
/* loop until false */
FILT_COND_TYPE 0x0f0
/* mask to select filter bits */
FILT_COND_NONE 0x010
/* show all results */
FILT_COND_FALSE 0x020
/* show only false results */
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

Saturday, June 16, 2012 11:08 PM

#define FILT_COND_TRUE 0x030


/* show only true results */
#define LOOP_NOTIFY 0x100
/* send loop results directly to enactor */
#define LOOP_TWOLISTS
0x200
/* process two lists */
/* from
#define
#define
#define
#define

handle_okpres (hears, moves, knows): */


PRESFN_OPER 0x0f
/* Mask to select bits */
PRESFN_HEARS
0x01
/* Detect hearing */
PRESFN_MOVES
0x02
/* Detect movement */
PRESFN_KNOWS
0x04
/* Detect knows */

/* from perform_get (get, get_eval, xget, eval(a,b)): */


#define GET_EVAL
0x01
/* evaluate the attribute */
#define GET_XARGS
0x02
/* obj and attr are two separate args */
/* from handle_pop (pop, peek, toss): */
#define POP_PEEK
0x01
/* don't remove item from stack */
#define POP_TOSS
0x02
/* don't display item from stack */
/* from
/* from
/* from
/* from
/* from
#define
#define
#define
#define
#define
#define

perform_regedit (regedit, regediti, regeditall, regeditalli): */


perform_regparse (regparse, regparsei): */
perform_regrab (regrab, regrabi, regraball, regraballi): */
perform_regmatch (regmatch, regmatchi): */
perform_grep (grep, grepi, wildgrep, regrep, regrepi): */
REG_CASELESS
0x01
/* XXX must equal PCRE_CASELESS */
REG_MATCH_ALL
0x02
/* operate on all matches in a list */
REG_TYPE
0x0c
/* mask to select grep type bits */
GREP_EXACT 0
GREP_WILD
4
GREP_REGEXP 8

/* from handle_trig
*
asind, acosd,
#define TRIG_OPER
#define TRIG_CO
#define TRIG_TAN
#define TRIG_ARC
/* #define TRIG_REC
#define TRIG_DEG
/* from
#define
#define
#define
#define

(sin, cos,
atand): */
0x0f
/*
0x01
/*
0x02
/*
0x04
/*
0x08
-0x10
/*

mask to select trig function bits */


co-function, like cos as opposed to sin */
tan-function, like cot as opposed to cos */
arc-function, like asin as opposed to sin */
reciprocal, like sec as opposed to sin */
angles are in degrees, not radians */

handle_pronoun (obj, poss, subj, aposs): */


PRONOUN_OBJ 0
PRONOUN_POSS
1
PRONOUN_SUBJ
2
PRONOUN_APOSS
3

/* from do_ufun(): */
#define U_LOCAL
0x01
#define U_PRIVATE
0x02
/* from
#define
#define
#define

tan, asin, acos, atan, sind, cosd, tand,

/* ulocal: preserve global registers */


/* ulocal: preserve global registers */

handle_ifelse() and handle_if() */


IFELSE_OPER 0x0f
/* mask */
IFELSE_BOOL 0x01
/* check for boolean (defaults to nonzero) */
IFELSE_FALSE
0x02
/* order false,true instead of true,false */
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\functions.h

530
531
532
533
534
535
536
537
538
539
540
541
542

#define IFELSE_DEFAULT
#define IFELSE_TOKEN

0x04
0x08

Saturday, June 16, 2012 11:08 PM

/* only two args, use condition as output */


/* allow switch-token substitution */

/* Miscellaneous */
#define LATTR_COUNT 0x01
/* nattr: just return attribute count */
#define LOCFN_WHERE 0x01
/* loc: where() vs. loc() */
#define NAMEFN_FULLNAME 0x01
/* name: fullname() vs. name() */
#define CHECK_PARENTS
0x01
/* hasattrp: recurse up the parent chain */
#define TIMESTAMP_MOD
0x01
/* timestamp: lastmod() vs. lastaccess() */
#define CONNINFO_IDLE
0x01
/* conninfo: idle() vs. conn() */
#endif /* __FUNCTIONS_H */

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funext.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:43 PM

/* funext.c - Functions that rely on external call-outs */


/* $Id: funext.c,v 1.22 2007/07/14 02:02:04 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

"functions.h" /* required by code */


"powers.h" /* required by code */
"command.h"
/* required by code */
"db_sql.h" /* required by code */

void FDECL(make_ulist, (dbref, char *, char **));


void FDECL(make_portlist, (dbref, dbref, char *, char **));
int FDECL(fetch_idle, (dbref, int));
int FDECL(fetch_connect, (dbref, int));
char * FDECL(get_doing, (dbref, int));
void FDECL(make_sessioninfo, (dbref, dbref, int, char *, char **));
dbref FDECL(get_programmer, (dbref));
void FDECL(cf_display, (dbref, char *, char *, char **));
void FDECL(help_helper, (dbref, int, int, char *, char *, char **));
INLINE int FDECL(safe_chr_real_fn, (char, char *, char **, int));

#define Find_Connection(x,s,t,p) \
p = t = NOTHING;
\
if (is_integer(s)) {
\
p = atoi(s);
\
} else {
\
t = lookup_player(x, s, 1); \
if (Good_obj(t) && Can_Hide(t) && Hidden(t) && \
!See_Hidden(x)) \
t = NOTHING;
\
}
/* --------------------------------------------------------------------------* config: Display a MUSH config parameter.
*/
FUNCTION(fun_config)
{
cf_display(player, fargs[0], buff, bufc);
}
/* --------------------------------------------------------------------------* fun_lwho: Return list of connected users.
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funext.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:43 PM

*/
FUNCTION(fun_lwho)
{
make_ulist(player, buff, bufc);
}
/* --------------------------------------------------------------------------* fun_ports: Returns a list of ports for a user.
*/
FUNCTION(fun_ports)
{
dbref target;
VaChk_Range(0, 1);

if (fargs[0] && *fargs[0]) {


target = lookup_player(player, fargs[0], 1);
if (!Good_obj(target) || !Connected(target)) {
return;
}
make_portlist(player, target, buff, bufc);
} else {
make_portlist(player, NOTHING, buff, bufc);
}

/* --------------------------------------------------------------------------* fun_doing: Returns a user's doing.


*/
FUNCTION(fun_doing)
{
dbref target;
int port;
char *str;
Find_Connection(player, fargs[0], target, port);
if ((port < 0) && (target == NOTHING)) {
return;
}

str = get_doing(target, port);


if (str) {
safe_str(str, buff, bufc);
}

/* --------------------------------------------------------------------------* handle_conninfo: return seconds idle or connected (IDLE, CONN).


*/

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funext.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:43 PM

FUNCTION(handle_conninfo)
{
dbref target;
int port;

Find_Connection(player, fargs[0], target, port);


if ((port < 0) && (target == NOTHING)) {
safe_known_str((char *) "-1", 2, buff, bufc);
return;
}
safe_ltos(buff, bufc, Is_Func(CONNINFO_IDLE) ?
fetch_idle(target, port) : fetch_connect(target, port));

/* --------------------------------------------------------------------------* fun_session: Return session info about a port.


*/
FUNCTION(fun_session)
{
dbref target;
int port;

Find_Connection(player, fargs[0], target, port);


if ((port < 0) && (target == NOTHING)) {
safe_str((char *) "-1 -1 -1", buff, bufc);
return;
}
make_sessioninfo(player, target, port, buff, bufc);

/* --------------------------------------------------------------------------* fun_programmer: Returns the dbref or #1- of an object in a @program.


*/
FUNCTION(fun_programmer)
{
dbref target;

target = lookup_player(player, fargs[0], 1);


if (!Good_obj(target) || !Connected(target) ||
!Examinable(player, target)) {
safe_nothing(buff, bufc);
return;
}
safe_dbref(buff, bufc, get_programmer(target));

/*--------------------------------------------------------------------------* fun_helptext: Read an entry from a helpfile.


*/
FUNCTION(fun_helptext)
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funext.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:43 PM

CMDENT *cmdp;
char *p;
if (!fargs[0] || !*fargs[0]) {
safe_str((char *) "#-1 NOT FOUND", buff, bufc);
return;
}
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
cmdp = (CMDENT *) hashfind(fargs[0], &mudstate.command_htab);
if (!cmdp || (cmdp->info.handler != do_help)) {
safe_str((char *) "#-1 NOT FOUND", buff, bufc);
return;
}
if (!Check_Cmd_Access(player, cmdp, cargs, ncargs)) {
safe_noperm(buff, bufc);
return;
}

help_helper(player, (cmdp->extra & ~HELP_RAWHELP),


(cmdp->extra & HELP_RAWHELP) ? 0 : 1, fargs[1], buff, bufc);

/*--------------------------------------------------------------------------* SQL stuff.


*/
FUNCTION(fun_sql)
{
Delim row_delim, field_delim;
/* Special -- the last two arguments are output delimiters */
VaChk_Range(1, 3);

VaChk_Sep(&row_delim, 2, DELIM_STRING|DELIM_NULL|DELIM_CRLF);
if (nfargs < 3) {
Delim_Copy(&field_delim, &row_delim);
} else {
VaChk_Sep(&field_delim, 3, DELIM_STRING|DELIM_NULL|DELIM_CRLF);
}
sql_query(player, fargs[0], buff, bufc, &row_delim, &field_delim);

/*--------------------------------------------------------------------------* Pueblo HTML-related functions.


*/
#ifdef PUEBLO_SUPPORT
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funext.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:43 PM

FUNCTION(fun_html_escape)
{
html_escape(fargs[0], buff, bufc);
}
FUNCTION(fun_html_unescape)
{
const char *msg_orig;
int ret = 0;

for (msg_orig = fargs[0]; msg_orig && *msg_orig && !ret; msg_orig++) {


switch (*msg_orig) {
case '&':
if (!strncmp(msg_orig, "&quot;", 6)) {
ret = safe_chr_fn('\"', buff, bufc);
msg_orig += 5;
} else if (!strncmp(msg_orig, "&lt;", 4)) {
ret = safe_chr_fn('<', buff, bufc);
msg_orig += 3;
} else if (!strncmp(msg_orig, "&gt;", 4)) {
ret = safe_chr_fn('>', buff, bufc);
msg_orig += 3;
} else if (!strncmp(msg_orig, "&amp;", 5)) {
ret = safe_chr_fn('&', buff, bufc);
msg_orig += 4;
} else {
ret = safe_chr_fn('&', buff, bufc);
}
break;
default:
ret = safe_chr_fn(*msg_orig, buff, bufc);
break;
}
}

FUNCTION(fun_url_escape)
{
/* These are the characters which are converted to %<hex> */
char *escaped_chars = "<>#%{}|\\^~[]';/?:@=&\"+";
const char *msg_orig;
int ret = 0;
char tbuf[10];
for (msg_orig = fargs[0]; msg_orig && *msg_orig && !ret; msg_orig++) {
if (strchr(escaped_chars, *msg_orig)) {
sprintf(tbuf, "%%%2x", *msg_orig);
ret = safe_str_fn(tbuf, buff, bufc);
} else if (*msg_orig == ' ') {
ret = safe_chr_fn('+', buff, bufc);
} else {
ret = safe_chr_fn(*msg_orig, buff, bufc);
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funext.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

Saturday, June 16, 2012 11:43 PM

}
}

FUNCTION(fun_url_unescape)
{
const char *msg_orig;
int ret = 0;
unsigned int tempchar;
char tempstr[10];
for (msg_orig = fargs[0]; msg_orig && *msg_orig && !ret;) {
switch (*msg_orig) {
case '+':
ret = safe_chr_fn(' ', buff, bufc);
msg_orig++;
break;
case '%':
strncpy(tempstr, msg_orig + 1, 2);
tempstr[2] = '\0';
if ((sscanf(tempstr, "%x", &tempchar) == 1) &&
(tempchar > 0x1F) && (tempchar < 0x7F)) {
ret = safe_chr_fn((char)tempchar, buff, bufc);
}
if (*msg_orig)
msg_orig++; /* Skip the '%' */
if (*msg_orig) /* Skip the 1st hex character. */
msg_orig++;
if (*msg_orig) /* Skip the 2nd hex character. */
msg_orig++;
break;
default:
ret = safe_chr_fn(*msg_orig, buff, bufc);
msg_orig++;
break;
}
}
return;

}
#endif /* PUEBLO_SUPPORT */

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:42 PM

/* funiter.c - functions for user-defined iterations over lists */


/* $Id: funiter.c,v 1.36 2008/04/27 16:25:06 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "functions.h" /* required by code */
#include "attrs.h" /* required by code */
#include "powers.h" /* required by code */
/* --------------------------------------------------------------------------* perform_loop: backwards-compatible looping constructs: LOOP, PARSE
* See notes on perform_iter for the explanation.
*/
FUNCTION(perform_loop)
{
Delim isep, osep;
int flag;
/* 0 is parse(), 1 is loop() */
char *curr, *objstring, *buff2, *buff3, *cp, *dp, *str, *result, *bb_p;
char tbuf[8];
int number = 0;
flag = Func_Mask(LOOP_NOTIFY);
if (flag) {
VaChk_Only_InEval(3);
} else {
VaChk_InEval_OutEval(2, 4);
}
dp = cp = curr = alloc_lbuf("perform_loop.1");
str = fargs[0];
exec(curr, &dp, player, caller, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
cp = trim_space_sep(cp, &isep);
if (!*cp) {
free_lbuf(curr);
return;
}
bb_p = *bufc;
while (cp && (mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:42 PM

!Too_Much_CPU()) {
if (!flag && (*bufc != bb_p)) {
print_sep(&osep, buff, bufc);
}
number++;
objstring = split_token(&cp, &isep);
buff2 = replace_string(BOUND_VAR, objstring, fargs[1]);
ltos(tbuf, number);
buff3 = replace_string(LISTPLACE_VAR, tbuf, buff2);
str = buff3;
if (!flag) {
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
} else {
dp = result = alloc_lbuf("perform_loop.2");
exec(result, &dp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
notify(cause, result);
free_lbuf(result);
}
free_lbuf(buff2);
free_lbuf(buff3);
}
free_lbuf(curr);

/* --------------------------------------------------------------------------* perform_iter: looping constructs


*
* iter() and list() parse an expression, substitute elements of
* a list, one at a time, using the '##' replacement token. Uses of these
* functions can be nested.
* In older versions of MUSH, these functions could not be nested.
* parse() and loop() exist for reasons of backwards compatibility,
* since the peculiarities of the way substitutions were done in the string
* replacements make it necessary to provide some way of doing backwards
* compatibility, in order to avoid breaking a lot of code that relies upon
* particular patterns of necessary escaping.
*
* whentrue() and whenfalse() work similarly to iter().
* whentrue() loops as long as the expression evaluates to true.
* whenfalse() loops as long as the expression evaluates to false.
*
* istrue() and isfalse() are inline filterbool() equivalents returning
* the elements of the list which are true or false, respectively.
*
* iter2(), list2(), etc. are two-list versions of all of the above.
*/
FUNCTION(perform_iter)
{
Delim isep, osep;
int flag;

/* 0 is iter(), 1 is list() */
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:42 PM

int bool_flag, filt_flag, two_flag;


int need_result, need_bool;
char *list_str, *lp, *input_p;
char *list_str2, *lp2, *input_p2;
char *str, *bb_p, *work_buf;
char *ep, *savep, *dp, *result;
int is_true, cur_lev, elen;
char tmpbuf[1] = "";
char tmpbuf2[1] = "";
/* Enforce maximum nesting level. */
if (mudstate.in_loop >= MAX_ITER_NESTING - 1) {
notify_quiet(player, "Exceeded maximum iteration nesting." );
return;
}
/* Figure out what functionality we're getting. */
flag = Func_Mask(LOOP_NOTIFY);
bool_flag = Func_Mask(BOOL_COND_TYPE);
filt_flag = Func_Mask(FILT_COND_TYPE);
two_flag = Func_Mask(LOOP_TWOLISTS);
need_result = (flag || (filt_flag != FILT_COND_NONE)) ? 1 : 0;
need_bool = ((bool_flag != BOOL_COND_NONE) ||
(filt_flag != FILT_COND_NONE)) ? 1 : 0;
if (!two_flag) {
if (flag) {
VaChk_Only_InEval(3);
} else {
VaChk_InEval_OutEval(2, 4);
}
ep = fargs[1];
} else {
if (flag) {
VaChk_Only_InEval(4);
} else {
VaChk_InEval_OutEval(3, 5);
}
ep = fargs[2];
}
/* The list argument is unevaluated. Go evaluate it. */
input_p = lp = list_str = alloc_lbuf("perform_iter.list");
str = fargs[0];
exec(list_str, &lp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
input_p = trim_space_sep(input_p, &isep);
/* Same thing for the second list arg, if we have it */
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:42 PM

if (two_flag) {
input_p2 = lp2 = list_str2 = alloc_lbuf("perform_iter.list2");
str = fargs[1];
exec(list_str2, &lp2, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
input_p2 = trim_space_sep(input_p2, &isep);
} else {
input_p2 = lp2 = list_str2 = NULL;
}
/* If both lists are empty, we're done */
if (!(input_p && *input_p) && !(input_p2 && *input_p2)) {
free_lbuf(list_str);
if (list_str2) {
free_lbuf(list_str2);
}
return;
}
cur_lev = mudstate.in_loop++;
mudstate.loop_token[cur_lev] = NULL;
mudstate.loop_token2[cur_lev] = NULL;
mudstate.loop_number[cur_lev] = 0;
bb_p = *bufc;
elen = strlen(ep);
while ((input_p || input_p2) &&
(mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
!Too_Much_CPU()) {
if (!need_result && (*bufc != bb_p)) {
print_sep(&osep, buff, bufc);
}
if (input_p)
mudstate.loop_token[cur_lev] = split_token(&input_p, &isep);
else
mudstate.loop_token[cur_lev] = tmpbuf;
if (input_p2)
mudstate.loop_token2[cur_lev] = split_token(&input_p2, &isep);
else
mudstate.loop_token2[cur_lev] = tmpbuf;
mudstate.loop_number[cur_lev] += 1;
work_buf = alloc_lbuf("perform_iter.eval");
StrCopyKnown(work_buf, ep, elen); /* we might nibble this */
str = work_buf;
savep = *bufc;
if (!need_result) {
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
if (need_bool) {
is_true = xlate(savep);
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:42 PM

}
} else {
dp = result = alloc_lbuf("perform_iter.out");
exec(result, &dp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
if (need_bool) {
is_true = xlate(result);
}
if (flag) {
notify(cause, result);
} else if (((filt_flag == FILT_COND_TRUE) && is_true) ||
((filt_flag == FILT_COND_FALSE) && !is_true)) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
safe_str(mudstate.loop_token[cur_lev], buff, bufc);
}
free_lbuf(result);
}
free_lbuf(work_buf);
if (bool_flag != BOOL_COND_NONE) {
if (!is_true && (bool_flag == BOOL_COND_TRUE))
break;
if (is_true && (bool_flag == BOOL_COND_FALSE))
break;
}
}

free_lbuf(list_str);
if (list_str2) {
free_lbuf(list_str2);
}
mudstate.in_loop--;

/* --------------------------------------------------------------------------* itext(), inum(), ilev(): Obtain nested iter tokens (##, #@, #!).
*/
FUNCTION(fun_ilev)
{
safe_ltos(buff, bufc, mudstate.in_loop - 1);
}
FUNCTION(fun_inum)
{
int lev;
lev = atoi(fargs[0]);
if ((lev > mudstate.in_loop - 1) || (lev < 0)) {
safe_chr('0', buff, bufc);
return;
}
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:42 PM

safe_ltos(buff, bufc, mudstate.loop_number[lev]);

FUNCTION(fun_itext)
{
int lev;
lev = atoi(fargs[0]);
if ((lev > mudstate.in_loop - 1) || (lev < 0))
return;
}

safe_str(mudstate.loop_token[lev], buff, bufc);

FUNCTION(fun_itext2)
{
int lev;
lev = atoi(fargs[0]);
if ((lev > mudstate.in_loop - 1) || (lev < 0))
return;
}

safe_str(mudstate.loop_token2[lev], buff, bufc);

/* --------------------------------------------------------------------------* fun_fold: iteratively eval an attrib with a list of arguments


*
and an optional base case. With no base case, the first list element
*
is passed as %0 and the second is %1. The attrib is then evaluated
*
with these args, the result is then used as %0 and the next arg is
*
%1 and so it goes as there are elements left in the list. The
*
optinal base case gives the user a nice starting point.
*
*
> &REP_NUM object=[%0][repeat(%1,%1)]
*
> say fold(OBJECT/REP_NUM,1 2 3 4 5,->)
*
You say "->122333444455555"
*
*
NOTE: To use added list separator, you must use base case!
*/
FUNCTION(fun_fold)
{
dbref aowner, thing;
int aflags, alen, anum, i;
ATTR *ap;
char *atext, *result, *curr, *bp, *str, *cp, *atextbuf;
char *op, *clist[3], *rstore;
Delim isep;
/* We need two to four arguments only */
VaChk_In(2, 4);
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:42 PM

/* Two possibilities for the first arg: <obj>/<attr> and <attr>. */


Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);
/* Evaluate it using the rest of the passed function args */
cp = curr = fargs[1];
atextbuf = alloc_lbuf("fun_fold");
StrCopyKnown(atextbuf, atext, alen);
/* may as well handle first case now */
i = 1;
clist[2] = alloc_sbuf("fun_fold.objplace");
op = clist[2];
safe_ltos(clist[2], &op, i);
if ((nfargs >= 3) && (fargs[2])) {
clist[0] = fargs[2];
clist[1] = split_token(&cp, &isep);
result = bp = alloc_lbuf("fun_fold");
str = atextbuf;
exec(result, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, clist, 3);
i++;
} else {
clist[0] = split_token(&cp, &isep);
clist[1] = split_token(&cp, &isep);
result = bp = alloc_lbuf("fun_fold");
str = atextbuf;
exec(result, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, clist, 3);
i += 2;
}
rstore = result;
result = NULL;
while (cp && (mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
!Too_Much_CPU()) {
clist[0] = rstore;
clist[1] = split_token(&cp, &isep);
op = clist[2];
safe_ltos(clist[2], &op, i);
StrCopyKnown(atextbuf, atext, alen);
result = bp = alloc_lbuf("fun_fold");
str = atextbuf;
exec(result, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, clist, 3);
strcpy(rstore, result);
free_lbuf(result);
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:42 PM

i++;
}
safe_str(rstore, buff, bufc);
free_lbuf(rstore);
free_lbuf(atext);
free_lbuf(atextbuf);
free_sbuf(clist[2]);

/* --------------------------------------------------------------------------* fun_filter: iteratively perform a function with a list of arguments


*
and return the arg, if the function evaluates to TRUE using the
*
arg.
*
*
> &IS_ODD object=mod(%0,2)
*
> say filter(object/is_odd,1 2 3 4 5)
*
You say "1 3 5"
*
> say filter(object/is_odd,1-2-3-4-5,-)
*
You say "1-3-5"
*
* NOTE: If you specify a separator it is used to delimit returned list
*/
FUNCTION(handle_filter)
{
Delim isep, osep;
int flag;
/* 0 is filter(), 1 is filterbool() */
dbref aowner, thing;
int aflags, alen, anum, i;
ATTR *ap;
char *atext, *result, *curr, *objs[2], *bp, *str, *cp, *op, *atextbuf;
char *bb_p;
flag = Func_Mask(LOGIC_BOOL);
VaChk_Only_In_Out(4);
/* Two possibilities for the first arg: <obj>/<attr> and <attr>. */
Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);
/* Now iteratively eval the attrib with the argument list */
cp = curr = trim_space_sep(fargs[1], &isep);
atextbuf = alloc_lbuf("fun_filter.atextbuf");
objs[1] = alloc_sbuf("fun_filter.objplace");
bb_p = *bufc;
i = 1;
while (cp) {
objs[0] = split_token(&cp, &isep);
op = objs[1];
safe_ltos(objs[1], &op, i);
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:42 PM

StrCopyKnown(atextbuf, atext, alen);


result = bp = alloc_lbuf("fun_filter");
str = atextbuf;
exec(result, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, objs, 2);
if ((!flag && (*result == '1')) || (flag && xlate(result))) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
safe_str(objs[0], buff, bufc);
}
free_lbuf(result);
i++;

}
free_lbuf(atext);
free_lbuf(atextbuf);
free_sbuf(objs[1]);

/* --------------------------------------------------------------------------* fun_map: iteratively evaluate an attribute with a list of arguments.


* > &DIV_TWO object=fdiv(%0,2)
* > say map(1 2 3 4 5,object/div_two)
* You say "0.5 1 1.5 2 2.5"
* > say map(object/div_two,1-2-3-4-5,-)
* You say "0.5-1-1.5-2-2.5"
*
*/
FUNCTION(fun_map)
{
dbref aowner, thing;
int aflags, alen, anum;
ATTR *ap;
char *atext, *objs[2], *str, *cp, *atextbuf, *bb_p, *op;
Delim isep, osep;
int i;
VaChk_Only_In_Out(4);
/* If we don't have anything for a second arg, don't bother. */
if (!fargs[1] || !*fargs[1])
return;
/* Two possibilities for the second arg: <obj>/<attr> and <attr>. */
Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);
/* now process the list one element at a time */
cp = trim_space_sep(fargs[1], &isep);
atextbuf = alloc_lbuf("fun_map.atextbuf");
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:42 PM

objs[1] = alloc_sbuf("fun_map.objplace");
bb_p = *bufc;
i = 1;
while (cp && (mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
!Too_Much_CPU()) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
objs[0] = split_token(&cp, &isep);
op = objs[1];
safe_ltos(objs[1], &op, i);
StrCopyKnown(atextbuf, atext, alen);
str = atextbuf;
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, objs, 2);
i++;
}
free_lbuf(atext);
free_lbuf(atextbuf);
free_sbuf(objs[1]);

/* --------------------------------------------------------------------------* fun_mix: Like map, but operates on two lists or more lists simultaneously,
* passing the elements as %0, %1, %2, etc.
*/
FUNCTION(fun_mix)
{
dbref aowner, thing;
int aflags, alen, anum, i, lastn, nwords, wc;
ATTR *ap;
char *str, *atext, *os[NUM_ENV_VARS], *atextbuf, *bb_p;
Delim isep;
char *cp[NUM_ENV_VARS];
int count[NUM_ENV_VARS];
char tmpbuf[1] = "";
/* Check to see if we have an appropriate number of arguments.
* If there are more than three arguments, the last argument is
* ALWAYS assumed to be a delimiter.
*/
VaChk_Range(3, 12);
if (nfargs < 4) {
isep.str[0] = ' ';
isep.len = 1;
lastn = nfargs - 1;
} else if (!delim_check( FUNCTION_ARGLIST, nfargs, &isep, DELIM_STRING)) {
return;
} else {
lastn = nfargs - 2;
}
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:42 PM

/* Get the attribute, check the permissions. */


Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);
for (i = 0; i < NUM_ENV_VARS; i++)
cp[i] = NULL;
bb_p = *bufc;
/* process the lists, one element at a time. */
nwords = 0;
for (i = 0; i < lastn; i++) {
cp[i] = trim_space_sep(fargs[i + 1], &isep);
count[i] = countwords(cp[i], &isep);
if (count[i] > nwords)
nwords = count[i];
}
atextbuf = alloc_lbuf("fun_mix");
for (wc = 0;
(wc < nwords) && (mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
!Too_Much_CPU();
wc++) {
for (i = 0; i < lastn; i++) {
if (wc < count[i]) {
os[i] = split_token(&cp[i], &isep);
} else {
os[i] = tmpbuf;
}
}
StrCopyKnown(atextbuf, atext, alen);
if (*bufc != bb_p) {
print_sep(&isep, buff, bufc);
}
str = atextbuf;

exec(buff, bufc, player, caller, cause,


EV_STRIP | EV_FCHECK | EV_EVAL, &str, os, lastn);
}
free_lbuf(atext);
free_lbuf(atextbuf);

/* --------------------------------------------------------------------------* fun_step: A little like a fusion of iter() and mix(), it takes elements
* of a list X at a time and passes them into a single function as %0, %1,
* etc.
step(<attribute>,<list>,<step size>,<delim>,<outdelim>)
*/
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:42 PM

FUNCTION(fun_step)
{
ATTR *ap;
dbref aowner, thing;
int aflags, alen, anum;
char *atext, *str, *cp, *atextbuf, *bb_p, *os[NUM_ENV_VARS];
Delim isep, osep;
int step_size, i;
VaChk_Only_In_Out(5);
step_size = atoi(fargs[2]);
if ((step_size < 1) || (step_size > NUM_ENV_VARS)) {
notify(player, "Illegal step size.");
return;
}
/* Get attribute. Check permissions. */
Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);

cp = trim_space_sep(fargs[1], &isep);
atextbuf = alloc_lbuf("fun_step");
bb_p = *bufc;
while (cp && (mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
!Too_Much_CPU()) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
for (i = 0; cp && (i < step_size); i++)
os[i] = split_token(&cp, &isep);
StrCopyKnown(atextbuf, atext, alen);
str = atextbuf;
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, &(os[0]), i);
}
free_lbuf(atext);
free_lbuf(atextbuf);

/* --------------------------------------------------------------------------* fun_foreach: like map(), but it operates on a string, rather than on a list,
* calling a user-defined function for each character in the string.
* No delimiter is inserted between the results.
*/
FUNCTION(fun_foreach)
{
dbref aowner, thing;
int aflags, alen, anum, i;
ATTR *ap;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:42 PM

char *str, *atext, *atextbuf, *cp, *cbuf[2], *op;


char start_token, end_token;
int in_string = 1;
VaChk_Range(2, 4);
Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);
atextbuf = alloc_lbuf("fun_foreach");
cbuf[0] = alloc_lbuf("fun_foreach.cbuf");
cp = Eat_Spaces(fargs[1]);
start_token = '\0';
end_token = '\0';
if (nfargs > 2) {
in_string = 0;
start_token = *fargs[2];
}
if (nfargs > 3) {
end_token = *fargs[3];
}
i = -1;
/* first letter in string is 0, not 1 */
cbuf[1] = alloc_sbuf("fun_foreach.objplace");
while (cp && *cp && (mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
!Too_Much_CPU()) {
if (!in_string) {
/* Look for a start token. */
while (*cp && (*cp != start_token)) {
safe_chr(*cp, buff, bufc);
cp++;
i++;
}
if (!*cp)
break;
/* Skip to the next character. Don't copy the start token. */
cp++;
i++;
if (!*cp)
break;
in_string = 1;
}
if (*cp == end_token) {
/* We've found an end token. Skip over it. Note that it's
* possible to have a start and end token next to one
* another.
*/
cp++;
i++;
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:42 PM

in_string = 0;
continue;

i++;
cbuf[0][0] = *cp++;
cbuf[0][1] = '\0';
op = cbuf[1];
safe_ltos(cbuf[1], &op, i);
StrCopyKnown(atextbuf, atext, alen);
str = atextbuf;
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cbuf, 2);
}

free_lbuf(atextbuf);
free_lbuf(atext);
free_lbuf(cbuf[0]);
free_sbuf(cbuf[1]);

/* --------------------------------------------------------------------------* fun_munge: combines two lists in an arbitrary manner.


*/
FUNCTION(fun_munge)
{
dbref aowner, thing;
int aflags, alen, anum, nptrs1, nptrs2, nresults, i, j;
ATTR *ap;
char *list1, *list2, *rlist, *st[2];
char **ptrs1, **ptrs2, **results;
char *atext, *bp, *str, *oldp;
Delim isep, osep;
oldp = *bufc;
if ((nfargs == 0) || !fargs[0] || !*fargs[0]) {
return;
}
VaChk_Only_In_Out(5);
/* Find our object and attribute */
Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);
/* Copy our lists and chop them up. */
list1 = alloc_lbuf("fun_munge.list1");
list2 = alloc_lbuf("fun_munge.list2");
strcpy(list1, fargs[1]);
strcpy(list2, fargs[2]);
nptrs1 = list2arr(&ptrs1, LBUF_SIZE / 2, list1, &isep);
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:42 PM

nptrs2 = list2arr(&ptrs2, LBUF_SIZE / 2, list2, &isep);


if (nptrs1 != nptrs2) {
safe_str("#-1 LISTS MUST BE OF EQUAL SIZE" , buff, bufc);
free_lbuf(atext);
free_lbuf(list1);
free_lbuf(list2);
XFREE(ptrs1, "fun_munge.ptrs1");
XFREE(ptrs2, "fun_munge.ptrs2");
return;
}
/* Call the u-function with the first list as %0. Pass the
* input separator as %1, which makes sorting, etc. easier.
*/
st[0] = fargs[1];
st[1] = alloc_lbuf("fun_munge.sep");
bp = st[1];
print_sep(&isep, st[1], &bp);
bp = rlist = alloc_lbuf("fun_munge.rlist");
str = atext;
exec(rlist, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, st, 2);
/* Now that we have our result, put it back into array form. Search
* through list1 until we find the element position, then
* copy the corresponding element from list2.
*/
nresults = list2arr(&results, LBUF_SIZE / 2, rlist, &isep);
for (i = 0; i < nresults; i++) {
for (j = 0; j < nptrs1; j++) {
if (!strcmp(results[i], ptrs1[j])) {
if (*bufc != oldp) {
print_sep(&osep, buff, bufc);
}
safe_str(ptrs2[j], buff, bufc);
ptrs1[j][0] = '\0';
break;
}
}
}
free_lbuf(atext);
free_lbuf(list1);
free_lbuf(list2);
free_lbuf(rlist);
free_lbuf(st[1]);
XFREE(ptrs1, "fun_munge.ptrs1");
XFREE(ptrs2, "fun_munge.ptrs2");
XFREE(results, "fun_munge.results");
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:42 PM

}
/* --------------------------------------------------------------------------* fun_while: Evaluate a list until a termination condition is met:
* while(EVAL_FN,CONDITION_FN,foo|flibble|baz|meep,1,|,-)
* where EVAL_FN is "[strlen(%0)]" and CONDITION_FN is "[strmatch(%0,baz)]"
* would result in '3-7-3' being returned.
* The termination condition is an EXACT not wild match.
*/
FUNCTION(fun_while)
{
Delim isep, osep;
dbref aowner1, thing1, aowner2, thing2;
int aflags1, aflags2, anum1, anum2, alen1, alen2, i, tmp_num;
int is_same, is_exact_same;
ATTR *ap, *ap2;
char *atext1, *atext2, *atextbuf, *condbuf;
char *objs[2], *cp, *str, *dp, *savep, *bb_p, *op;
VaChk_Only_In_Out(6);
/* If our third arg is null (empty list), don't bother. */
if (!fargs[2] || !*fargs[2])
return;
/* Our first and second args can be <obj>/<attr> or just <attr>.
* Use them if we can access them, otherwise return an empty string.
*
* Note that for user-defined attributes, atr_str() returns a pointer
* to a static, and that therefore we have to be careful about what
* we're doing.
*/
Parse_Uattr(player, fargs[0], thing1, anum1, ap);
Get_Uattr(player, thing1, ap, atext1, aowner1, aflags1, alen1);
tmp_num = ap->number;
Parse_Uattr(player, fargs[1], thing2, anum2, ap2);
if (!ap2) {
free_lbuf(atext1); /* we allocated this, remember? */
return;
}
/* If our evaluation and condition are the same, we can save ourselves
* some time later. There are two possibilities: we have the exact
* same obj/attr pair, or the attributes contain identical text.
*/
if ((thing1 == thing2) && (tmp_num == ap2->number)) {
is_same = 1;
is_exact_same = 1;
} else {
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:42 PM

is_exact_same = 0;
atext2 = atr_pget(thing2, ap2->number, &aowner2, &aflags2, &alen2);
if (!*atext2 || !See_attr(player, thing2, ap2, aowner2, aflags2)) {
free_lbuf(atext1);
free_lbuf(atext2);
return;
}
if (!strcmp(atext1, atext2))
is_same = 1;
else
is_same = 0;
}
/* Process the list one element at a time. */
cp = trim_space_sep(fargs[2], &isep);
atextbuf = alloc_lbuf("fun_while.eval");
if (!is_same)
condbuf = alloc_lbuf("fun_while.cond");
objs[1] = alloc_sbuf("fun_while.objplace");
bb_p = *bufc;
i = 1;
while (cp && (mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
!Too_Much_CPU()) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
objs[0] = split_token(&cp, &isep);
op = objs[1];
safe_ltos(objs[1], &op, i);
StrCopyKnown(atextbuf, atext1, alen1);
str = atextbuf;
savep = *bufc;
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, objs, 2);
if (!is_same) {
StrCopyKnown(atextbuf, atext2, alen2);
dp = savep = condbuf;
str = atextbuf;
exec(condbuf, &dp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, objs, 2);
}
if (!strcmp(savep, fargs[3]))
break;
i++;
}
free_lbuf(atext1);
if (!is_exact_same)
free_lbuf(atext2);
free_lbuf(atextbuf);
if (!is_same)
free_lbuf(condbuf);
free_sbuf(objs[1]);
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funiter.c

902
903

Saturday, June 16, 2012 11:42 PM

-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:42 PM

/* funlist.c - list functions */


/* $Id: funlist.c,v 1.59 2008/04/27 16:25:06 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"functions.h" /* required by code */


"attrs.h" /* required by code */
"powers.h" /* required by code */
"ansi.h"
/* required by code */

/* --------------------------------------------------------------------------* List management utilities.


*/
#define
#define
#define
#define
#define

ALPHANUM_LIST
NUMERIC_LIST
DBREF_LIST 3
FLOAT_LIST 4
NOCASE_LIST 5

1
2

static int autodetect_list(ptrs, nitems)


char *ptrs[];
int nitems;
{
int sort_type, i;
char *p;
sort_type = NUMERIC_LIST;
for (i = 0; i < nitems; i++) {
switch (sort_type) {
case NUMERIC_LIST:
if (!is_number(ptrs[i])) {
/* If non-numeric, switch to alphanum sort.
* Exception: if this is the first element
* and it is a good dbref, switch to a dbref
* sort. We're a little looser than the
* normal 'good dbref' rules, any number
* following the #-sign is accepted.
*/
if (i == 0) {
p = ptrs[i];
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:42 PM

if (*p++ != NUMBER_TOKEN) {
return ALPHANUM_LIST;
} else if (is_integer(p)) {
sort_type = DBREF_LIST;
} else {
return ALPHANUM_LIST;
}
} else {
return ALPHANUM_LIST;
}
} else if (strchr(ptrs[i], '.')) {
sort_type = FLOAT_LIST;
}
break;
case FLOAT_LIST:
if (!is_number(ptrs[i])) {
sort_type = ALPHANUM_LIST;
return ALPHANUM_LIST;
}
break;
case DBREF_LIST:
p = ptrs[i];
if (*p++ != NUMBER_TOKEN)
return ALPHANUM_LIST;
if (!is_integer(p))
return ALPHANUM_LIST;
break;
default:
return ALPHANUM_LIST;
}

}
return sort_type;

static int get_list_type(fargs, nfargs, type_pos, ptrs, nitems)


char *fargs[], *ptrs[];
int nfargs, nitems, type_pos;
{
if (nfargs >= type_pos) {
switch (tolower(*fargs[type_pos - 1])) {
case 'd':
return DBREF_LIST;
case 'n':
return NUMERIC_LIST;
case 'f':
return FLOAT_LIST;
case 'i':
return NOCASE_LIST;
case '\0':
return autodetect_list(ptrs, nitems);
default:
return ALPHANUM_LIST;
}
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:42 PM

}
return autodetect_list(ptrs, nitems);

static int dbnum(dbr)


char *dbr;
{
if ((*dbr != '#') || (dbr[1] == '\0'))
return 0;
else
return atoi(dbr + 1);
}
/* --------------------------------------------------------------------------* fun_words: Returns number of words in a string. Aka vdim.
* Added 1/28/91 Philip D. Wasson
*/
FUNCTION(fun_words)
{
Delim isep;

if (nfargs == 0) {
safe_chr('0', buff, bufc);
return;
}
VaChk_Only_In(2);
safe_ltos(buff, bufc, countwords(fargs[0], &isep));

/* --------------------------------------------------------------------------* fun_first: Returns first word in a string


*/
FUNCTION(fun_first)
{
char *s, *first;
Delim isep;
/* If we are passed an empty arglist return a null string */

if (nfargs == 0) {
return;
}
VaChk_Only_In(2);
s = trim_space_sep(fargs[0], &isep);
first = split_token(&s, &isep);
if (first) {
safe_str(first, buff, bufc);
}

/* leading spaces */

/* ---------------------------------------------------------------------------3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:42 PM

* fun_rest: Returns all but the first word in a string


*/
FUNCTION(fun_rest)
{
char *s, *rest;
Delim isep;
int ansi_state = ANST_NONE;
/* If we are passed an empty arglist return a null string */

if (nfargs == 0) {
return;
}
VaChk_Only_In(2);
s = trim_space_sep(fargs[0], &isep);
/* leading spaces */
rest = next_token_ansi(s, &isep, &ansi_state);
if (rest) {
safe_str(ansi_transition_esccode(ANST_NORMAL, ansi_state), buff, bufc);
safe_str(rest, buff, bufc);
}

/* --------------------------------------------------------------------------* fun_last: Returns last word in a string


*/
FUNCTION(fun_last)
{
char *s, *last;
Delim isep;
int ansi_state = ANST_NONE;
/* If we are passed an empty arglist return a null string */
if (nfargs == 0) {
return;
}
VaChk_Only_In(2);
if (isep.len == 1) {
last = s = trim_space_sep(fargs[0], &isep);
do {

/* this is like next_token(), but tracking ansi */


while (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
}
while (*s && (*s != isep.str[0])) {
++s;
while (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:42 PM

}
}
if (*s) {
++s;
if (isep.str[0] == ' ') {
while (*s == ' ')
++s;
}
last = s;
}
} while (*s);
safe_str(ansi_transition_esccode(ANST_NORMAL, ansi_state), buff, bufc);
safe_known_str(last, s - last, buff, bufc);
} else {
s = fargs[0];
/* Walk backwards through the string to find the separator.
* Find the last character, and compare the previous characters,
* to find the separator. If we can't find the last character
* or we know we're going to fall off the string, return
* the original string.
*/

if ((last = strrchr(s, isep.str[isep.len - 1])) == NULL) {


safe_str(s, buff, bufc);
return;
}
while (last >= s + isep.len - 1) {
if ((*last == isep.str[isep.len - 1]) &&
!strncmp(isep.str, last - isep.len + 1, isep.len)) {
safe_str(++last, buff, bufc);
return;
}
last--;
}
safe_str(s, buff, bufc);

/* --------------------------------------------------------------------------* fun_match: Match arg2 against each word of arg1, returning index of
* first match.
*/
FUNCTION(fun_match)
{
int wcount;
char *r, *s;
Delim isep;

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:42 PM

VaChk_Only_In(3);
/* Check each word individually, returning the word number of the
* first one that matches. If none match, return 0.
*/

wcount = 1;
s = trim_space_sep(fargs[0], &isep);
do {
r = split_token(&s, &isep);
if (quick_wild(fargs[1], r)) {
safe_ltos(buff, bufc, wcount);
return;
}
wcount++;
} while (s);
safe_chr('0', buff, bufc);

FUNCTION(fun_matchall)
{
int wcount;
char *r, *s, *old;
Delim isep, osep;
VaChk_Only_In_Out(4);
/* SPECIAL CASE: If there's no output delimiter specified, we use
* a space, NOT the delimiter given for the list!
*/
if (nfargs < 4) {
osep.str[0] = ' ';
osep.len = 1;
}
old = *bufc;
/* Check each word individually, returning the word number of all
* that match. If none match, return a null string.
*/
wcount = 1;
s = trim_space_sep(fargs[0], &isep);
do {
r = split_token(&s, &isep);
if (quick_wild(fargs[1], r)) {
if (old != *bufc) {
print_sep(&osep, buff, bufc);
}
safe_ltos(buff, bufc, wcount);
}
wcount++;
} while (s);
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:42 PM

}
/* --------------------------------------------------------------------------* fun_extract: extract words from string:
* extract(foo bar baz,1,2) returns 'foo bar'
* extract(foo bar baz,2,1) returns 'bar'
* extract(foo bar baz,2,2) returns 'bar baz'
*
* Now takes optional separator extract(foo-bar-baz,1,2,-) returns 'foo-bar'
*/
FUNCTION(fun_extract)
{
int start, len;
char *r, *s, *t;
Delim isep, osep;
VaChk_Only_In_Out(5);
s = fargs[0];
start = atoi(fargs[1]);
len = atoi(fargs[2]);
if ((start < 1) || (len < 1)) {
return;
}
/* Skip to the start of the string to save */
start--;
s = trim_space_sep(s, &isep);
while (start && s) {
s = next_token(s, &isep);
start--;
}
/* If we ran of the end of the string, return nothing */
if (!s || !*s) {
return;
}
/* If our delimiter is the same, we have an easy task. Otherwise
* we have to go token by token.
*/
if (!strcmp((&isep)->str, (&osep)->str)) {
/* Count off the words in the string to save */
r = s;
len--;
while (len && s) {
s = next_token(s, &isep);
len--;
}
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:42 PM

/* Chop off the rest of the string, if needed */


if (s && *s)
t = split_token(&s, &isep);
safe_str(r, buff, bufc);
} else {
r = *bufc;
do {
t = split_token(&s, &isep);
if (r != *bufc) {
print_sep(&osep, buff, bufc);
}
safe_str(t, buff, bufc);
len--;
} while (len && s && *s);
}

/* --------------------------------------------------------------------------* fun_index: like extract(), but it works with an arbitrary separator.


* index(a b | c d e | f gh | ij k, |, 2, 1) => c d e
* index(a b | c d e | f gh | ij k, |, 2, 2) => c d e | f g h
*/
FUNCTION(fun_index)
{
int start, end;
char c, *s, *p;
s = fargs[0];
c = *fargs[1];
start = atoi(fargs[2]);
end = atoi(fargs[3]);
if ((start < 1) || (end < 1) || (*s == '\0'))
return;
if (c == '\0')
c = ' ';
/* move s to point to the start of the item we want */
start--;
while (start && s && *s) {
if ((s = strchr(s, c)) != NULL)
s++;
start--;
}
/* skip over just spaces */
while (s && (*s == ' '))
s++;
if (!s || !*s)
return;
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:42 PM

/* figure out where to end the string */


p = s;
while (end && p && *p) {
if ((p = strchr(p, c)) != NULL) {
if (--end == 0) {
do {
p--;
} while ((*p == ' ') && (p > s));
*(++p) = '\0';
safe_str(s, buff, bufc);
return;
} else {
p++;
}
}
}
/* if we've gotten this far, we've run off the end of the string */
}

safe_str(s, buff, bufc);

/* --------------------------------------------------------------------------* ldelete: Remove a word from a string by place


* ldelete(<list>,<position>[,<separator>])
*
* insert: insert a word into a string by place
* insert(<list>,<position>,<new item> [,<separator>])
*
* replace: replace a word into a string by place
* replace(<list>,<position>,<new item>[,<separator>])
*
* lreplace: replace multiple words into a string by places
* lreplace(<list>,<replacement words>,<positions>[,<isep>,<osep>])
*/
#define IF_DELETE
#define IF_REPLACE
#define IF_INSERT

0
1
2

static void do_itemfuns(buff, bufc, str, el, word, sep, flag)


char *buff, **bufc, *str, *word;
const Delim *sep;
int el, flag;
{
int ct, overrun;
char *sptr, *iptr, *eptr;
char nullb;
/* If passed a null string return an empty string, except that we
* are allowed to append to a null string.
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:42 PM

*/
if ((!str || !*str) && ((flag != IF_INSERT) || (el != 1))) {
return;
}
/* we can't fiddle with anything before the first position */
if (el < 1) {
safe_str(str, buff, bufc);
return;
}
/* Split the list up into 'before', 'target', and 'after' chunks
* pointed to by sptr, iptr, and eptr respectively.
*/
nullb = '\0';
if (el == 1) {
/* No 'before' portion, just split off element 1 */
sptr = NULL;
if (!str || !*str) {
eptr = NULL;
iptr = NULL;
} else {
eptr = trim_space_sep(str, sep);
iptr = split_token(&eptr, sep);
}
} else {
/* Break off 'before' portion */
sptr = eptr = trim_space_sep(str, sep);
overrun = 1;
for (ct = el; ct > 2 && eptr;
eptr = next_token(eptr, sep), ct--) ;
if (eptr) {
overrun = 0;
iptr = split_token(&eptr, sep);
}
/* If we didn't make it to the target element, just return
* the string. Insert is allowed to continue if we are
* exactly at the end of the string, but replace
* and delete are not.
*/
if (!(eptr || ((flag == IF_INSERT) && !overrun))) {
safe_str(str, buff, bufc);
return;
}
/* Split the 'target' word from the 'after' portion. */
if (eptr)
iptr = split_token(&eptr, sep);
else
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:42 PM

iptr = NULL;

switch (flag) {
case IF_DELETE: /* deletion */
if (sptr) {
safe_str(sptr, buff, bufc);
if (eptr) {
print_sep(sep, buff, bufc);
}
}
if (eptr) {
safe_str(eptr, buff, bufc);
}
break;
case IF_REPLACE:
/* replacing */
if (sptr) {
safe_str(sptr, buff, bufc);
print_sep(sep, buff, bufc);
}
safe_str(word, buff, bufc);
if (eptr) {
print_sep(sep, buff, bufc);
safe_str(eptr, buff, bufc);
}
break;
case IF_INSERT: /* insertion */
if (sptr) {
safe_str(sptr, buff, bufc);
print_sep(sep, buff, bufc);
}
safe_str(word, buff, bufc);
if (iptr) {
print_sep(sep, buff, bufc);
safe_str(iptr, buff, bufc);
}
if (eptr) {
print_sep(sep, buff, bufc);
safe_str(eptr, buff, bufc);
}
break;
}

FUNCTION(fun_ldelete)
{
/* delete a word at position X of a list */
Delim isep;

VaChk_Only_In(3);
do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), NULL,
&isep, IF_DELETE);

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:42 PM

FUNCTION(fun_replace)
{
/* replace a word at position X of a list */
Delim isep;

VaChk_Only_In(4);
do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), fargs[2],
&isep, IF_REPLACE);

FUNCTION(fun_insert)
{
/* insert a word at position X of a list */
Delim isep;

VaChk_Only_In(4);
do_itemfuns(buff, bufc, fargs[0], atoi(fargs[1]), fargs[2],
&isep, IF_INSERT);

FUNCTION(fun_lreplace)
{
Delim isep;
Delim osep;
char *origlist, *replist, *poslist;
char **orig_p, **rep_p, **pos_p;
int norig, nrep, npos, i, cpos;
/* We're generous with the argument checking, in case the
* replacement list is blank, and/or the position list is blank.
*/
VaChk_In_Out(1, 5);
/* If there are no positions to replace, then we just return the
* original list.
*/
if ((nfargs < 3) || !fargs[2]) {
safe_str(fargs[0], buff, bufc);
return;
}
/* The number of elements we have in our replacement list must equal
* the number of elements in our position list.
*/
if (!fargs[1] ||
(countwords(fargs[1], &isep) != countwords(fargs[2], &SPACE_DELIM))) {
safe_str("#-1 NUMBER OF WORDS MUST BE EQUAL" , buff, bufc);
return;
}
/* Turn out lists into arrays for ease of manipulation. */

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:42 PM

origlist = alloc_lbuf("fun_lreplace.orig");
replist = alloc_lbuf("fun_lreplace.rep");
poslist = alloc_lbuf("fun_lreplace.pos");
strcpy(origlist, fargs[0]);
strcpy(replist, fargs[1]);
strcpy(poslist, fargs[2]);
norig = list2arr(&orig_p, LBUF_SIZE / 2, origlist, &isep);
nrep = list2arr(&rep_p, LBUF_SIZE / 2, replist, &isep);
npos = list2arr(&pos_p, LBUF_SIZE / 2, poslist, &SPACE_DELIM);
/* The positions we have aren't necessarily sequential, so we can't
* just walk through the list. We have to replace position by position.
* If we get an invalid position number, just ignore it.
*/
for (i = 0; i < npos; i++) {
cpos = atoi(pos_p[i]);
if ((cpos > 0) && (cpos <= norig))
orig_p[cpos - 1] = rep_p[i];
}

arr2list(orig_p, norig, buff, bufc, &osep);


XFREE(orig_p, "fun_lreplace.orig_p");
XFREE(rep_p, "fun_lreplace.rep_p");
XFREE(pos_p, "fun_lreplace.pos_p");
free_lbuf(origlist);
free_lbuf(replist);
free_lbuf(poslist);

/* --------------------------------------------------------------------------* fun_remove: Remove a word from a string


*/
FUNCTION(fun_remove)
{
char *s, *sp, *word, *bb_p;
Delim isep;
int found;
VaChk_Only_In(3);
if (((isep.len == 1) && strchr(fargs[1], isep.str[0])) ||
((isep.len > 1) && strstr(fargs[1], isep.str))) {
safe_str("#-1 CAN ONLY DELETE ONE ELEMENT" , buff, bufc);
return;
}
s = fargs[0];
word = fargs[1];
/* Walk through the string copying words until (if ever) we get to
* one that matches the target word.
*/
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:42 PM

sp = s;
found = 0;
bb_p = *bufc;
while (s) {
sp = split_token(&s, &isep);
if (found || strcmp(sp, word)) {
if (*bufc != bb_p) {
print_sep(&isep, buff, bufc);
}
safe_str(sp, buff, bufc);
} else {
found = 1;
}
}

/* --------------------------------------------------------------------------* fun_member: Is a word in a string


*/
FUNCTION(fun_member)
{
int wcount;
char *r, *s;
Delim isep;

VaChk_Only_In(3);
wcount = 1;
s = trim_space_sep(fargs[0], &isep);
do {
r = split_token(&s, &isep);
if (!strcmp(fargs[1], r)) {
safe_ltos(buff, bufc, wcount);
return;
}
wcount++;
} while (s);
safe_chr('0', buff, bufc);

/* --------------------------------------------------------------------------* fun_revwords: Reverse the order of words in a list.


*/
FUNCTION(fun_revwords)
{
char *bb_p, **elems;
Delim isep;
int n_elems, i;
/* If we are passed an empty arglist return a null string */

-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:42 PM

if (nfargs == 0) {
return;
}
VaChk_Only_In(2);
/* Nasty bounds checking */
if ((int)strlen(fargs[0]) >= LBUF_SIZE - (*bufc - buff) - 1) {
*(fargs[0] + (LBUF_SIZE - (*bufc - buff) - 1)) = '\0';
}
/* Chop it up into an array of words and reverse them. */

n_elems = list2arr(&elems, LBUF_SIZE / 2, fargs[0], &isep);


bb_p = *bufc;
for (i = n_elems - 1; i >= 0; i--) {
if (*bufc != bb_p) {
print_sep(&isep, buff, bufc);
}
safe_str(elems[i], buff, bufc);
}
XFREE(elems, "fun_revwords.elems");

/* --------------------------------------------------------------------------* fun_splice: given two lists and a word, merge the two lists
*
by replacing words in list1 that are the same as the given
*
word by the corresponding word in list2 (by position).
*
The lists must have the same number of words. Compare to MERGE().
*/
FUNCTION(fun_splice)
{
char *p1, *p2, *q1, *q2, *bb_p;
Delim isep, osep;
int words, i;
VaChk_Only_In_Out(5);
/* length checks */
if (countwords(fargs[2], &isep) > 1) {
safe_str("#-1 TOO MANY WORDS", buff, bufc);
return;
}
words = countwords(fargs[0], &isep);
if (words != countwords(fargs[1], &isep)) {
safe_str("#-1 NUMBER OF WORDS MUST BE EQUAL" , buff, bufc);
return;
}
/* loop through the two lists */
p1 = fargs[0];
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:42 PM

q1 = fargs[1];
bb_p = *bufc;
for (i = 0; i < words; i++) {
p2 = split_token(&p1, &isep);
q2 = split_token(&q1, &isep);
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
if (!strcmp(p2, fargs[2]))
safe_str(q2, buff, bufc);
/* replace */
else
safe_str(p2, buff, bufc);
/* copy */
}

/* --------------------------------------------------------------------------* handle_sort: Sort lists.


*/
typedef struct f_record f_rec;
typedef struct i_record i_rec;
typedef struct a_record a_rec;
struct f_record {
double data;
char *str;
int pos;
};
struct i_record {
long data;
char *str;
int pos;
};
struct a_record {
char *str;
int pos;
};
static int a_comp(s1, s2)
const void *s1, *s2;
{
return strcmp(*(char **)s1, *(char **)s2);
}
static int c_comp(s1, s2)
const void *s1, *s2;
{
return strcasecmp(*(char **)s1, *(char **)s2);
}
static int arec_comp(s1, s2)
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:42 PM

const void *s1, *s2;


{
return strcmp(((a_rec *) s1)->str, ((a_rec *) s2)->str);
}
static int crec_comp(s1, s2)
const void *s1, *s2;
{
return strcasecmp(((a_rec *) s1)->str, ((a_rec *) s2)->str);
}
static int f_comp(s1, s2)
const void *s1, *s2;
{
if (((f_rec *) s1)->data > ((f_rec *) s2)->data)
return 1;
if (((f_rec *) s1)->data < ((f_rec *) s2)->data)
return -1;
return 0;
}
static int i_comp(s1, s2)
const void *s1, *s2;
{
if (((i_rec *) s1)->data > ((i_rec *) s2)->data)
return 1;
if (((i_rec *) s1)->data < ((i_rec *) s2)->data)
return -1;
return 0;
}
#define Get_Poslist(p, n, l) \
l = (int *) XCALLOC(n, sizeof(int), "do_asort.poslist"); \
for (i = 0; i < n; i++) l[i] = p[i].pos;
static int *do_asort(s, n, sort_type, listpos_only)
char *s[];
int n, sort_type;
{
int i;
f_rec *fp = NULL;
i_rec *ip = NULL;
a_rec *ap = NULL;
int *poslist = NULL;
switch (sort_type) {
case ALPHANUM_LIST:
if (!listpos_only) {
qsort((void *)s, n, sizeof(char *),
(int (*)(const void *, const void *))a_comp);
} else {
ap = (a_rec *) XCALLOC(n, sizeof(a_rec), "do_asort");
for (i = 0; i < n; i++) {
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:42 PM

ap[i].str = s[i];
ap[i].pos = i + 1;

}
qsort((void *)ap, n, sizeof(a_rec),
(int (*)(const void *, const void *))arec_comp);
Get_Poslist(ap, n, poslist);
XFREE(ap, "do_asort");

}
break;
case NOCASE_LIST:
if (!listpos_only) {
qsort((void *)s, n, sizeof(char *),
(int (*)(const void *, const void *))c_comp);
} else {
ap = (a_rec *) XCALLOC(n, sizeof(a_rec), "do_asort");
for (i = 0; i < n; i++) {
ap[i].str = s[i];
ap[i].pos = i + 1;
}
qsort((void *)ap, n, sizeof(a_rec),
(int (*)(const void *, const void *))crec_comp);
Get_Poslist(ap, n, poslist);
XFREE(ap, "do_asort");
}
break;
case NUMERIC_LIST:
ip = (i_rec *) XCALLOC(n, sizeof(i_rec), "do_asort");
for (i = 0; i < n; i++) {
ip[i].str = s[i];
ip[i].data = atoi(s[i]);
ip[i].pos = i + 1;
}
qsort((void *)ip, n, sizeof(i_rec),
(int (*)(const void *, const void *))i_comp);
for (i = 0; i < n; i++) {
s[i] = ip[i].str;
}
if (listpos_only) {
Get_Poslist(ip, n, poslist);
}
XFREE(ip, "do_asort");
break;
case DBREF_LIST:
ip = (i_rec *) XCALLOC(n, sizeof(i_rec), "do_asort.2");
for (i = 0; i < n; i++) {
ip[i].str = s[i];
ip[i].data = dbnum(s[i]);
ip[i].pos = i + 1;
}
qsort((void *)ip, n, sizeof(i_rec),
(int (*)(const void *, const void *))i_comp);
for (i = 0; i < n; i++) {
s[i] = ip[i].str;
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:42 PM

}
if (listpos_only) {
Get_Poslist(ip, n, poslist);
}
XFREE(ip, "do_asort.2");
break;
case FLOAT_LIST:
fp = (f_rec *) XCALLOC(n, sizeof(f_rec), "do_asort.3");
for (i = 0; i < n; i++) {
fp[i].str = s[i];
fp[i].data = aton(s[i]);
fp[i].pos = i + 1;
}
qsort((void *)fp, n, sizeof(f_rec),
(int (*)(const void *, const void *))f_comp);
for (i = 0; i < n; i++) {
s[i] = fp[i].str;
}
if (listpos_only) {
Get_Poslist(fp, n, poslist);
}
XFREE(fp, "do_asort.3");
break;
}
return poslist;

FUNCTION(handle_sort)
{
int nitems, sort_type, oper, i;
char *list, **ptrs;
int *poslist;
Delim isep, osep;
/* If we are passed an empty arglist return a null string */
if (nfargs == 0) {
return;
}
VaChk_In_Out(1, 4);
oper = Func_Mask(SORT_POS);
/* Convert the list to an array */
list = alloc_lbuf("handle_sort");
strcpy(list, fargs[0]);
nitems = list2arr(&ptrs, LBUF_SIZE / 2, list, &isep);
sort_type = get_list_type(fargs, nfargs, 2, ptrs, nitems);
poslist = do_asort(ptrs, nitems, sort_type, oper);
if (oper == SORT_POS) {
for (i = 0; i < nitems; i++) {
if (i > 0) {
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:42 PM

print_sep(&osep, buff, bufc);


}
safe_ltos(buff, bufc, poslist[i]);

}
} else {
arr2list(ptrs, nitems, buff, bufc, &osep);
}
if (poslist) {
XFREE(poslist, "do_asort.poslist");
}
free_lbuf(list);
XFREE(ptrs, "handle_sort.ptrs");

/* --------------------------------------------------------------------------* sortby: Sort using a user-defined function.


*/
static char ucomp_buff[LBUF_SIZE];
static dbref ucomp_cause, ucomp_player, ucomp_caller;
static int u_comp(s1, s2)
const void *s1, *s2;
{
/* Note that this function is for use in conjunction with our own
* sane_qsort routine, NOT with the standard library qsort!
*/
char *result, *tbuf, *elems[2], *bp, *str;
int n;
if ((mudstate.func_invk_ctr > mudconf.func_invk_lim) ||
(mudstate.func_nest_lev > mudconf.func_nest_lim) ||
Too_Much_CPU())
return 0;

tbuf = alloc_lbuf("u_comp");
elems[0] = (char *)s1;
elems[1] = (char *)s2;
strcpy(tbuf, ucomp_buff);
result = bp = alloc_lbuf("u_comp");
str = tbuf;
exec(result, &bp, ucomp_player, ucomp_caller, ucomp_cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, elems, 2);
n = atoi(result);
free_lbuf(result);
free_lbuf(tbuf);
return n;

static void sane_qsort(array, left, right, compare)


void *array[];
int left, right;
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:42 PM

int (*compare) ();


{
/* Andrew Molitor's qsort, which doesn't require transitivity between
* comparisons (essential for preventing crashes due to
* boneheads who write comparison functions where a > b doesn't
* mean b < a).
*/
int i, last;
void *tmp;
loop:
if (left >= right)
return;
/* Pick something at random at swap it into the leftmost slot */
/* This is the pivot, we'll put it back in the right spot later */
i = Randomize(1 + (right - left));
tmp = array[left + i];
array[left + i] = array[left];
array[left] = tmp;
last = left;
for (i = left + 1; i <= right; i++) {
/* Walk the array, looking for stuff that's less than our */
/* pivot. If it is, swap it with the next thing along */
if ((*compare) (array[i], array[left]) < 0) {
last++;
if (last == i)
continue;

tmp = array[last];
array[last] = array[i];
array[i] = tmp;

/* Now we put the pivot back, it's now in the right spot, we never */
/* need to look at it again, trust me.
*/
tmp = array[last];
array[last] = array[left];
array[left] = tmp;
/* At this point everything underneath the 'last' index is < the */
/* entry at 'last' and everything above it is not < it.
*/
if ((last - left) < (right - last)) {
sane_qsort(array, left, last - 1, compare);
left = last + 1;
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

Saturday, June 16, 2012 11:42 PM

goto loop;
} else {
sane_qsort(array, last + 1, right, compare);
right = last - 1;
goto loop;
}

FUNCTION(fun_sortby)
{
char *atext, *list, **ptrs;
Delim isep, osep;
int nptrs, aflags, alen, anum;
dbref thing, aowner;
ATTR *ap;
if ((nfargs == 0) || !fargs[0] || !*fargs[0]) {
return;
}
VaChk_Only_In_Out(4);
Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);
strcpy(ucomp_buff, atext);
ucomp_player = thing;
ucomp_caller = player;
ucomp_cause = cause;
list = alloc_lbuf("fun_sortby");
strcpy(list, fargs[1]);
nptrs = list2arr(&ptrs, LBUF_SIZE / 2, list, &isep);
if (nptrs > 1)
/* pointless to sort less than 2 elements */
sane_qsort((void **)ptrs, 0, nptrs - 1, u_comp);

arr2list(ptrs, nptrs, buff, bufc, &osep);


free_lbuf(list);
free_lbuf(atext);
XFREE(ptrs, "fun_sortby.ptrs");

/* --------------------------------------------------------------------------* handle_sets: Set management: SETUNION, SETDIFF, SETINTER.


* Also LUNION, LDIFF, LINTER: Same thing, but takes a sort type like
* sort() does. There's an unavoidable PennMUSH conflict, as
* setunion() and friends have a 4th-arg output delimiter in TM3, but
* the 4th arg is used for the sort type in PennMUSH. Also, adding the
* sort type as a fifth arg for setunion(), etc. would be confusing,
* since the last two args are, by convention, delimiters. So we add
* new funcs.
*/

-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

Saturday, June 16, 2012 11:42 PM

#define NUMCMP(f1,f2) \
((f1 > f2) ? 1 : ((f1 < f2) ? -1 : 0))
#define GENCMP(x1,x2,s) \
((s == ALPHANUM_LIST) ? strcmp(ptrs1[x1],ptrs2[x2]) : \
((s == NOCASE_LIST) ? strcasecmp(ptrs1[x1],ptrs2[x2]) : \
((s == FLOAT_LIST) ? NUMCMP(fp1[x1],fp2[x2]) : NUMCMP(ip1[x1],ip2[x2]))))
FUNCTION(handle_sets)
{
Delim isep, osep;
int oper, type_arg;
char *list1, *list2, *oldp, *bb_p;
char **ptrs1, **ptrs2;
int i1, i2, n1, n2, val, sort_type;
int *ip1, *ip2;
double *fp1, *fp2;
oper = Func_Mask(SET_OPER);
type_arg = Func_Mask(SET_TYPE);
if (type_arg) {
VaChk_In_Out(2, 5);
} else {
VaChk_Only_In_Out(4);
}
list1 = alloc_lbuf("fun_setunion.1");
strcpy(list1, fargs[0]);
n1 = list2arr(&ptrs1, LBUF_SIZE, list1, &isep);
list2 = alloc_lbuf("fun_setunion.2");
strcpy(list2, fargs[1]);
n2 = list2arr(&ptrs2, LBUF_SIZE, list2, &isep);
if (type_arg) {
if (*fargs[0])
sort_type = get_list_type(fargs, nfargs, 3, ptrs1, n1);
else
sort_type = get_list_type(fargs, nfargs, 3, ptrs2, n2);
} else {
sort_type = ALPHANUM_LIST;
}
do_asort(ptrs1, n1, sort_type, SORT_ITEMS);
do_asort(ptrs2, n2, sort_type, SORT_ITEMS);
/* This conversion is inefficient, since it's already happened
* once in do_asort().
*/
ip1 = ip2 = NULL;
fp1 = fp2 = NULL;

-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

Saturday, June 16, 2012 11:42 PM

if (sort_type == NUMERIC_LIST) {
ip1 = (int *) XCALLOC(n1, sizeof(int), "handle_sets.n1");
ip2 = (int *) XCALLOC(n2, sizeof(int), "handle_sets.n2");
for (val = 0; val < n1; val++)
ip1[val] = atoi(ptrs1[val]);
for (val = 0; val < n2; val++)
ip2[val] = atoi(ptrs2[val]);
} else if (sort_type == DBREF_LIST) {
ip1 = (int *) XCALLOC(n1, sizeof(int), "handle_sets.n1");
ip2 = (int *) XCALLOC(n2, sizeof(int), "handle_sets.n2");
for (val = 0; val < n1; val++)
ip1[val] = dbnum(ptrs1[val]);
for (val = 0; val < n2; val++)
ip2[val] = dbnum(ptrs2[val]);
} else if (sort_type == FLOAT_LIST) {
fp1 = (double *) XCALLOC(n1, sizeof(double), "handle_sets.n1");
fp2 = (double *) XCALLOC(n2, sizeof(double), "handle_sets.n2");
for (val = 0; val < n1; val++)
fp1[val] = aton(ptrs1[val]);
for (val = 0; val < n2; val++)
fp2[val] = aton(ptrs2[val]);
}
i1 = i2 = 0;
bb_p = oldp = *bufc;
**bufc = '\0';
switch (oper) {
case SET_UNION: /* Copy elements common to both lists */
/* Handle case of two identical single-element lists */
if ((n1 == 1) && (n2 == 1) &&
(!strcmp(ptrs1[0], ptrs2[0]))) {
safe_str(ptrs1[0], buff, bufc);
break;
}
/* Process until one list is empty */
while ((i1 < n1) && (i2 < n2)) {
/* Skip over duplicates */
if ((i1 > 0) || (i2 > 0)) {
while ((i1 < n1) && !strcmp(ptrs1[i1],
oldp))
i1++;
while ((i2 < n2) && !strcmp(ptrs2[i2],
oldp))
i2++;
}
/* Compare and copy */

-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325

Saturday, June 16, 2012 11:42 PM

if ((i1 < n1) && (i2 < n2)) {


if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
oldp = *bufc;
if (GENCMP(i1, i2, sort_type) < 0) {
safe_str(ptrs1[i1], buff, bufc);
i1++;
} else {
safe_str(ptrs2[i2], buff, bufc);
i2++;
}
**bufc = '\0';
}

/* Copy rest of remaining list, stripping duplicates */


for (; i1 < n1; i1++) {
if (strcmp(oldp, ptrs1[i1])) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
oldp = *bufc;
safe_str(ptrs1[i1], buff, bufc);
**bufc = '\0';
}
}
for (; i2 < n2; i2++) {
if (strcmp(oldp, ptrs2[i2])) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
oldp = *bufc;
safe_str(ptrs2[i2], buff, bufc);
**bufc = '\0';
}
}
break;
case SET_INTERSECT: /* Copy elements not in both lists */
while ((i1 < n1) && (i2 < n2)) {
val = GENCMP(i1, i2, sort_type);
if (!val) {
/* Got a match, copy it */
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);

}
oldp = *bufc;
safe_str(ptrs1[i1], buff, bufc);
i1++;
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

Saturday, June 16, 2012 11:42 PM

i2++;
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;
while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
i2++;
} else if (val < 0) {
i1++;
} else {
i2++;
}

}
break;
case SET_DIFF:

/* Copy elements unique to list1 */

while ((i1 < n1) && (i2 < n2)) {


val = GENCMP(i1, i2, sort_type);
if (!val) {
/* Got a match, increment pointers */
oldp = ptrs1[i1];
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;
while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
i2++;
} else if (val < 0) {
/* Item in list1 not in list2, copy */
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);

}
safe_str(ptrs1[i1], buff, bufc);
oldp = ptrs1[i1];
i1++;
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;
} else {
/* Item in list2 but not in list1, discard */

oldp = ptrs2[i2];
i2++;
while ((i2 < n2) && !strcmp(ptrs2[i2], oldp))
i2++;

/* Copy remainder of list1 */


while (i1 < n1) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431

Saturday, June 16, 2012 11:42 PM

}
safe_str(ptrs1[i1], buff, bufc);
oldp = ptrs1[i1];
i1++;
while ((i1 < n1) && !strcmp(ptrs1[i1], oldp))
i1++;

}
free_lbuf(list1);
free_lbuf(list2);
if ((sort_type == NUMERIC_LIST) || (sort_type == DBREF_LIST)) {
XFREE(ip1, "handle_sets.n1");
XFREE(ip2, "handle_sets.n2");
} else if (sort_type == FLOAT_LIST) {
XFREE(fp1, "handle_sets.n1");
XFREE(fp2, "handle_sets.n2");
}
XFREE(ptrs1, "handle_sets.ptrs1");
XFREE(ptrs2, "handle_sets.ptrs2");

/*--------------------------------------------------------------------------* Format a list into columns.


*/
FUNCTION(fun_columns)
{
unsigned int spaces, number, ansinumber, striplen;
unsigned int count, i, indent = 0;
int isansi = 0, rturn = 1;
char *p, *q, *buf, *objstring, *cp, *cr = NULL;
Delim isep;
VaChk_Range(2, 4);
VaChk_InSep(3, 0);
number = (unsigned int) safe_atoi(fargs[1]);
indent = (unsigned int) safe_atoi(fargs[3]);
if (indent > 77) {
indent = 1;
}

/* unsigned int, always a positive number */

/* Must check number separately, since number + indent can


* result in an integer overflow.
*/
if ((number < 1) || (number > 77) ||
((unsigned int) (number + indent) > 78)) {
safe_str("#-1 OUT OF RANGE", buff, bufc);
return;
}

-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

Saturday, June 16, 2012 11:42 PM

cp = trim_space_sep(fargs[0], &isep);
if (!*cp) {
return;
}
for (i = 0; i < indent; i++)
safe_chr(' ', buff, bufc);
buf = alloc_lbuf("fun_columns");
while (cp) {
objstring = split_token(&cp, &isep);
ansinumber = number;
striplen = strip_ansi_len(objstring);
if (ansinumber > striplen)
ansinumber = striplen;
p = objstring;
q = buf;
count = 0;
while (p && *p) {
if (count == number) {
break;
}
if (*p == ESC_CHAR) {
/* Start of ANSI code. Skip to end. */
isansi = 1;
while (*p && !isalpha(*p))
*q++ = *p++;
if (*p)
*q++ = *p++;
} else {
*q++ = *p++;
count++;
}
}
if (isansi)
safe_ansi_normal(buf, &q);
*q = '\0';
isansi = 0;
safe_str(buf, buff, bufc);
if (striplen < number) {
/* We only need spaces if we need to pad out.
* Sanitize the number of spaces, too.
*/
spaces = number - striplen;
if (spaces > LBUF_SIZE) {
spaces = LBUF_SIZE;
}
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537

Saturday, June 16, 2012 11:42 PM

for (i = 0; i < spaces; i++)


safe_chr(' ', buff, bufc);

if (!(rturn % (int)((78 - indent) / number))) {


safe_crlf(buff, bufc);
cr = *bufc;
for (i = 0; i < indent; i++)
safe_chr(' ', buff, bufc);
} else {
cr = NULL;
}
}

rturn++;

if (cr) {
*bufc = cr;
**bufc = '\0';
} else {
safe_crlf(buff, bufc);
}
}

free_lbuf(buf);

/*--------------------------------------------------------------------------* fun_table: Turn a list into a table.


*
table(<list>,<field width>,<line length>,<list delim>,<field sep>,<pad>)
*
Only the <list> parameter is mandatory.
*
tables(<list>,<field widths>,<lead str>,<trail str>,
*
<list delim>,<field sep str>,<pad>)
*
Only the <list> and <field widths> parameters are mandatory.
*
* There are a couple of PennMUSH incompatibilities. The handling here is
* more complex and probably more desirable behavior. The issues are:
*
- ANSI states are preserved even if a word is truncated. Thus, the
*
next word will start with the correct color.
*
- ANSI does not bleed into the padding or field separators.
*
- Having a '%r' embedded in the list will start a new set of columns.
*
This allows a series of %r-separated lists to be table-ified
*
correctly, and doesn't mess up the character count.
*/
static void tables_helper(list, last_state, n_cols, col_widths,
lead_str, trail_str, list_sep, field_sep, pad_char,
buff, bufc, just)
char *list;
int *last_state, n_cols, col_widths[];
char *lead_str, *trail_str;
const Delim *list_sep, *field_sep, *pad_char;
char *buff, **bufc;
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590

Saturday, June 16, 2012 11:42 PM

int just;
int i, nwords, nstates, cpos, wcount, over, ansi_state;
int max, nleft, lead_chrs, lens[LBUF_SIZE / 2], states[LBUF_SIZE / 2 + 1];
char *s, **words;
/* Split apart the list. We need to find the length of each de-ansified
* word, as well as keep track of the state of each word.
* Overly-long words eventually get truncated, but the correct ANSI
* state is preserved nonetheless.
*/
nstates = list2ansi(states, last_state, LBUF_SIZE / 2, list, list_sep);
nwords = list2arr(&words, LBUF_SIZE / 2, list, list_sep);
if (nstates != nwords) {
safe_tprintf_str(buff, bufc, "#-1 STATE/WORD COUNT OFF: %d/%d" ,
nstates, nwords);
XFREE(words, "tables_helper.words");
return;
}
for (i = 0; i < nwords; i++)
lens[i] = strip_ansi_len(words[i]);
over = wcount = 0;
while ((wcount < nwords) && !over) {
/* Beginning of new line. Insert newline if this isn't the first
* thing we're writing. Write left margin, if appropriate.
*/
if (wcount != 0)
safe_crlf(buff, bufc);
if (lead_str)
over = safe_str_fn(lead_str, buff, bufc);
/* Do each column in the line. */
for (cpos = 0; (cpos < n_cols) && (wcount < nwords) && !over;
cpos++, wcount++) {
/* Write leading padding if we need it. */
if (just == JUST_RIGHT) {
nleft = col_widths[cpos] - lens[wcount];
print_padding(nleft, max, pad_char->str[0]);
} else if (just == JUST_CENTER) {
lead_chrs = (int)((col_widths[cpos] / 2) (lens[wcount] / 2) + .5);
print_padding(lead_chrs, max, pad_char->str[0]);
}
/* If we had a previous state, we have to write it. */
safe_str(ansi_transition_esccode(ANST_NONE, states[wcount]),
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

Saturday, June 16, 2012 11:42 PM

buff, bufc);
/* Copy in the word. */
if (lens[wcount] <= col_widths[cpos]) {
over = safe_str_fn(words[wcount], buff, bufc);
safe_str(ansi_transition_esccode(states[wcount + 1],
ANST_NONE),
buff, bufc);
} else {
/* Bleah. We have a string that's too long. Truncate it.
* Write an ANSI normal at the end at the end if we need
* one (we'll restore the correct ANSI code with the
* next word, if need be).
*/
ansi_state = states[wcount];
for (s = words[wcount], i = 0;
*s && (i < col_widths[cpos]); ) {
if (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
} else {
s++;
i++;
}
}
safe_known_str(words[wcount], s - words[wcount], buff, bufc);
safe_str(ansi_transition_esccode(ansi_state, ANST_NONE),
buff, bufc);
}
/* Writing trailing padding if we need it. */
if (just == JUST_LEFT) {
nleft = col_widths[cpos] - lens[wcount];
print_padding(nleft, max, pad_char->str[0]);
} else if (just == JUST_CENTER) {
nleft = col_widths[cpos] - lead_chrs - lens[wcount];
print_padding(nleft, max, pad_char->str[0]);
}
/* Insert the field separator if this isn't the last column
* AND this is not the very last word in the list.
*/

if ((cpos < n_cols - 1) && (wcount < nwords - 1)) {


print_sep(field_sep, buff, bufc);
}

if (!over && trail_str) {


/* If we didn't get enough columns to fill out a line, and
* this is the last line, then we have to pad it out.
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696

Saturday, June 16, 2012 11:42 PM

*/
if ((wcount == nwords) &&
((nleft = nwords % n_cols) > 0)) {
for (cpos = nleft; (cpos < n_cols) && !over; cpos++) {
print_sep(field_sep, buff, bufc);
print_padding(col_widths[cpos], max, pad_char->str[0]);
}
}

}
}

/* Write the right margin. */


over = safe_str_fn(trail_str, buff, bufc);

/* Save the ANSI state of the last word. */


*last_state = states[nstates - 1];

/* Clean up. */
XFREE(words, "tables_helper.words");

static void perform_tables(player, list, n_cols, col_widths,


lead_str, trail_str, list_sep, field_sep, pad_char,
buff, bufc, just)
dbref player;
char *list;
int n_cols, col_widths[];
char *lead_str, *trail_str;
const Delim *list_sep, *field_sep, *pad_char;
char *buff, **bufc;
int just;
{
char *p, *savep, *bb_p;
int ansi_state = ANST_NONE;
if (!list || !*list)
return;
bb_p = *bufc;
savep = list;
p = strchr(list, '\r');
while (p) {
*p = '\0';
if (*bufc != bb_p)
safe_crlf(buff, bufc);
tables_helper(savep, &ansi_state, n_cols, col_widths,
lead_str, trail_str, list_sep, field_sep, pad_char,
buff, bufc, just);
savep = p + 2; /* must skip '\n' too */
p = strchr(savep, '\r');
}
if (*bufc != bb_p)
safe_crlf(buff, bufc);
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

Saturday, June 16, 2012 11:42 PM

tables_helper(savep, &ansi_state, n_cols, col_widths, lead_str, trail_str,


list_sep, field_sep, pad_char, buff, bufc, just);

FUNCTION(process_tables)
{
int just;
int i, num, n_columns, *col_widths;
Delim list_sep, field_sep, pad_char;
char **widths;
just = Func_Mask(JUST_TYPE);
VaChk_Range(2, 7);
VaChk_Sep(&list_sep, 5, DELIM_STRING);
VaChk_Sep(&field_sep, 6, DELIM_STRING|DELIM_NULL|DELIM_CRLF);
VaChk_Sep(&pad_char, 7, 0);
n_columns = list2arr(&widths, LBUF_SIZE / 2, fargs[1], &SPACE_DELIM);
if (n_columns < 1) {
XFREE(widths, "process_tables.widths");
return;
}
col_widths = (int *) XCALLOC(n_columns, sizeof(int), "process_tables.col_widths");
for (i = 0; i < n_columns; i++) {
num = atoi(widths[i]);
col_widths[i] = (num < 1) ? 1 : num;
}
perform_tables(player, fargs[0], n_columns, col_widths,
((nfargs > 2) && *fargs[2]) ? fargs[2] : NULL,
((nfargs > 3) && *fargs[3]) ? fargs[3] : NULL,
&list_sep, &field_sep, &pad_char, buff, bufc, just);

XFREE(col_widths, "process_tables.col_widths");
XFREE(widths, "process_tables.widths");

FUNCTION(fun_table)
{
int line_length = 78;
int field_width = 10;
int i, field_sep_width, n_columns, *col_widths;
Delim list_sep, field_sep, pad_char;
VaChk_Range(1, 6);
VaChk_Sep(&list_sep, 4, DELIM_STRING);
VaChk_Sep(&field_sep, 5, DELIM_STRING|DELIM_NULL|DELIM_CRLF);
VaChk_Sep(&pad_char, 6, 0);
/* Get line length and column width. All columns are the same width.
* Calculate what we need to.
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

Saturday, June 16, 2012 11:42 PM

*/
if (nfargs > 2) {
line_length = atoi(fargs[2]);
if (line_length < 2)
line_length = 2;
}
if (nfargs > 1) {
field_width = atoi(fargs[1]);
if (field_width < 1)
field_width = 1;
else if (field_width > LBUF_SIZE - 1)
field_width = LBUF_SIZE - 1;
}
if (field_width >= line_length)
field_width = line_length - 1;
if (field_sep.len == 1) {
switch (field_sep.str[0]) {
case '\r':
case '\0':
case '\n':
case '\a':
field_sep_width = 0;
break;
default:
field_sep_width = 1;
break;
}
} else {
field_sep_width = strip_ansi_len(field_sep.str);
}
n_columns = (int)(line_length / (field_width + field_sep_width));
col_widths = (int *) XCALLOC(n_columns, sizeof(int), "fun_table.widths");
for (i = 0; i < n_columns; i++)
col_widths[i] = field_width;
perform_tables(player, fargs[0], n_columns, col_widths, NULL, NULL,
&list_sep, &field_sep, &pad_char, buff, bufc, JUST_LEFT);
}

XFREE(col_widths, "fun_table.widths");

/* --------------------------------------------------------------------------* fun_elements: given a list of numbers, get corresponding elements from


* the list. elements(ack bar eep foof yay,2 4) ==> bar foof
* The function takes a separator, but the separator only applies to the
* first list.
*/

-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

Saturday, June 16, 2012 11:42 PM

/* Borrowed from PennMUSH 1.50 */


FUNCTION(fun_elements)
{
int nwords, cur;
char **ptrs;
char *wordlist, *s, *r, *oldp;
Delim isep, osep;
VaChk_Only_In_Out(4);
oldp = *bufc;
/* Turn the first list into an array. */
wordlist = alloc_lbuf("fun_elements.wordlist");
strcpy(wordlist, fargs[0]);
nwords = list2arr(&ptrs, LBUF_SIZE / 2, wordlist, &isep);
s = Eat_Spaces(fargs[1]);
/* Go through the second list, grabbing the numbers and finding the
* corresponding elements.
*/
do {

r = split_token(&s, &SPACE_DELIM);
cur = atoi(r) - 1;
if ((cur >= 0) && (cur < nwords) && ptrs[cur]) {
if (oldp != *bufc) {
print_sep(&osep, buff, bufc);
}
safe_str(ptrs[cur], buff, bufc);
}
} while (s);
free_lbuf(wordlist);
XFREE(ptrs, "fun_elements.ptrs");

/* --------------------------------------------------------------------------* fun_grab: a combination of extract() and match(), sortof. We grab the


*
single element that we match.
*
*
grab(Test:1 Ack:2 Foof:3,*:2)
=> Ack:2
*
grab(Test-1+Ack-2+Foof-3,*o*,+) => Ack:2
*
* fun_graball: Ditto, but like matchall() rather than match(). We
*
grab all the elements that match, and we can take
*
an output delimiter.
*/
FUNCTION(fun_grab)
{
char *r, *s;
Delim isep;
-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

Saturday, June 16, 2012 11:42 PM

VaChk_Only_In(3);
/* Walk the wordstring, until we find the word we want. */

s = trim_space_sep(fargs[0], &isep);
do {
r = split_token(&s, &isep);
if (quick_wild(fargs[1], r)) {
safe_str(r, buff, bufc);
return;
}
} while (s);

FUNCTION(fun_graball)
{
char *r, *s, *bb_p;
Delim isep, osep;
VaChk_Only_In_Out(4);

s = trim_space_sep(fargs[0], &isep);
bb_p = *bufc;
do {
r = split_token(&s, &isep);
if (quick_wild(fargs[1], r)) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
safe_str(r, buff, bufc);
}
} while (s);

/* --------------------------------------------------------------------------* fun_shuffle: randomize order of words in a list.


*/
/* Borrowed from PennMUSH 1.50 */
static void swap(p, q)
char **p;
char **q;
{
/* swaps two points to strings */
char *temp;

temp = *p;
*p = *q;
*q = temp;

-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961

Saturday, June 16, 2012 11:42 PM

FUNCTION(fun_shuffle)
{
char **words;
int n, i, j;
Delim isep, osep;
if (!nfargs || !fargs[0] || !*fargs[0]) {
return;
}
VaChk_Only_In_Out(3);
n = list2arr(&words, LBUF_SIZE, fargs[0], &isep);

for (i = 0; i < n; i++) {


j = random_range(i, n - 1);
swap(&words[i], &words[j]);
}
arr2list(words, n, buff, bufc, &osep);
XFREE(words, "fun_shuffle.words");

/* --------------------------------------------------------------------------* ledit(<list of words>,<old words>,<new words>[,<delim>[,<output delim>]])


* If a <word> in <list of words> is in <old words>, replace it with the
* corresponding word from <new words>. This is basically a mass-edit.
* This is an EXACT, not a case-insensitive or wildcarded, match.
*/
FUNCTION(fun_ledit)
{
Delim isep, osep;
char *old_list, *new_list;
int nptrs_old, nptrs_new;
char **ptrs_old, **ptrs_new;
char *r, *s, *bb_p;
int i;
int got_it;
VaChk_Only_In_Out(5);
old_list = alloc_lbuf("fun_ledit.old");
new_list = alloc_lbuf("fun_ledit.new");
strcpy(old_list, fargs[1]);
strcpy(new_list, fargs[2]);
nptrs_old = list2arr(&ptrs_old, LBUF_SIZE / 2, old_list, &isep);
nptrs_new = list2arr(&ptrs_new, LBUF_SIZE / 2, new_list, &isep);
/* Iterate through the words. */
bb_p = *bufc;
s = trim_space_sep(fargs[0], &isep);
do {
if (*bufc != bb_p) {
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014

Saturday, June 16, 2012 11:42 PM

print_sep(&osep, buff, bufc);


}
r = split_token(&s, &isep);
for (i = 0, got_it = 0; i < nptrs_old; i++) {
if (!strcmp(r, ptrs_old[i])) {
got_it = 1;
if ((i < nptrs_new) && *ptrs_new[i]) {
/* If we specify more old words than we have new words,
* we assume we want to just nullify.
*/
safe_str(ptrs_new[i], buff, bufc);
}
break;
}
}
if (!got_it) {
safe_str(r, buff, bufc);
}
} while (s);

free_lbuf(old_list);
free_lbuf(new_list);
XFREE(ptrs_old, "fun_ledit.ptrs_old");
XFREE(ptrs_new, "fun_ledit.ptrs_new");

/* --------------------------------------------------------------------------* fun_itemize: Turn a list into a punctuated list.


*/
FUNCTION(fun_itemize)
{
Delim isep, osep;
int n_elems, i;
char *conj_str, **elems;
VaChk_Range(1, 4);
if (!fargs[0] || !*fargs[0])
return;
VaChk_InSep(2, 0);
if (nfargs < 3) {
conj_str = (char *) "and";
} else {
conj_str = fargs[2];
}
if (nfargs < 4) {
osep.str[0] = ',';
osep.len = 1;
} else {
VaChk_OutSep(4, 0);
}
n_elems = list2arr(&elems, LBUF_SIZE / 2, fargs[0], &isep);
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067

Saturday, June 16, 2012 11:42 PM

if (n_elems == 1) {
safe_str(elems[0], buff, bufc);
} else if (n_elems == 2) {
safe_str(elems[0], buff, bufc);
if (*conj_str) {
safe_chr(' ', buff, bufc);
safe_str(conj_str, buff, bufc);
}
safe_chr(' ', buff, bufc);
safe_str(elems[1], buff, bufc);
} else {
for (i = 0; i < (n_elems - 1); i++) {
safe_str(elems[i], buff, bufc);
print_sep(&osep, buff, bufc);
safe_chr(' ', buff, bufc);
}
if (*conj_str) {
safe_str(conj_str, buff, bufc);
safe_chr(' ', buff, bufc);
}
safe_str(elems[i], buff, bufc);
}
XFREE(elems, "fun_itemize.elems");

/* --------------------------------------------------------------------------* fun_choose: Weighted random choice from a list.


*
choose(<list of items>,<list of weights>,<input delim>)
*/
FUNCTION(fun_choose)
{
Delim isep;
char **elems, **weights;
int i, num, n_elems, n_weights, *ip;
int sum = 0;
VaChk_Only_In(3);
n_elems = list2arr(&elems, LBUF_SIZE / 2, fargs[0], &isep);
n_weights = list2arr(&weights, LBUF_SIZE / 2, fargs[1], &SPACE_DELIM);
if (n_elems != n_weights) {
safe_str("#-1 LISTS MUST BE OF EQUAL SIZE" , buff, bufc);
XFREE(elems, "fun_choose.elems");
XFREE(weights, "fun_choose.weights");
return;
}
/* Store the breakpoints, not the choose weights themselves. */
ip = (int *) XCALLOC(n_weights, sizeof(int), "fun_choose.ip");
for (i = 0; i < n_weights; i++) {
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120

Saturday, June 16, 2012 11:42 PM

num = atoi(weights[i]);
if (num < 0)
num = 0;
if (num == 0) {
ip[i] = 0;
} else {
sum += num;
ip[i] = sum;
}
}
num = (int) Randomize(sum);
for (i = 0; i < n_weights; i++) {
if ((ip[i] != 0) && (num < ip[i])) {
safe_str(elems[i], buff, bufc);
break;
}
}

XFREE(ip, "fun_choose.ip");
XFREE(elems, "fun_choose.elems");
XFREE(weights, "fun_choose.weights");

/* --------------------------------------------------------------------------* fun_group: group(<list>, <number of groups>, <idelim>, <odelim>, <gdelim>)


* Sort a list by numerical-size group, i.e., take every Nth
* element. Useful for passing to a column-type function where you want
* the list to go down rather than across, for instance.
*/
FUNCTION(fun_group)
{
char *bb_p, **elems;
Delim isep, osep, gsep;
int n_elems, n_groups, i, j;
/* Separator checking is weird in this, since we can delimit by group,
* too, as well as the element delimiter. The group delimiter defaults
* to the output delimiter.
*/
VaChk_Range(2, 5);
VaChk_InSep(3, 0);
VaChk_DefaultOut(4) {
VaChk_OutSep(4, 0);
}
if (nfargs < 5) {
Delim_Copy(&gsep, &osep);
} else {
VaChk_Sep(&gsep, 5, DELIM_NULL|DELIM_CRLF|DELIM_STRING);
}
-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funlist.c

2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153

Saturday, June 16, 2012 11:42 PM

/* Go do it, unless the group size doesn't make sense. */


n_groups = atoi(fargs[1]);
n_elems = list2arr(&elems, LBUF_SIZE / 2, fargs[0], &isep);
if (n_groups < 2) {
arr2list(elems, n_elems, buff, bufc, &osep);
XFREE(elems, "fun_group.elems");
return;
}
if (n_groups >= n_elems) {
arr2list(elems, n_elems, buff, bufc, &gsep);
XFREE(elems, "fun_group.elems");
return;
}
bb_p =
for (i
for (j
if
if

}
}
}

*bufc;
= 0; i < n_groups; i++) {
= 0; i + j < n_elems; j += n_groups) {
(*bufc != bb_p) {
(j == 0) {
print_sep(&gsep, buff, bufc);
} else {
print_sep(&osep, buff, bufc);
}
}
safe_str(elems[i + j], buff, bufc);

XFREE(elems, "fun_group.elems");

-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:41 PM

/* funmath.c - math and logic functions */


/* $Id: funmath.c,v 1.28 2007/12/28 21:55:44 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include <math.h>
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "functions.h"

/* required by code */

/* --------------------------------------------------------------------------* fval: copy the floating point value into a buffer and make it presentable
*/
#ifdef FLOATING_POINTS
#define FP_SIZE ((sizeof(double) + sizeof(unsigned int) - 1) / sizeof(unsigned int))
#define FP_EXP_WEIRD
0x1
#define FP_EXP_ZERO 0x2
typedef union {
double d;
unsigned int u[FP_SIZE];
} fp_union_uint;
static unsigned int fp_check_weird(buff, bufc, result)
char *buff, **bufc;
double result;
{
static fp_union_uint fp_sign_mask, fp_exp_mask, fp_mant_mask, fp_val;
static const double d_zero = 0.0;
static int fp_initted = 0;
unsigned int fp_sign, fp_exp, fp_mant;
int i;
if (!fp_initted) {
memset(fp_sign_mask.u, 0, sizeof(fp_sign_mask));
memset(fp_exp_mask.u, 0, sizeof(fp_exp_mask));
memset(fp_val.u, 0, sizeof(fp_val));
fp_exp_mask.d = 1.0 / d_zero;
fp_sign_mask.d = -1.0 / fp_exp_mask.d;
for (i = 0; i < FP_SIZE; i++) {
fp_mant_mask.u[i] = ~(fp_exp_mask.u[i] | fp_sign_mask.u[i]);
}
fp_initted = 1;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:41 PM

}
fp_val.d = result;
fp_sign = fp_mant = 0;
fp_exp = FP_EXP_ZERO | FP_EXP_WEIRD;
for (i = 0; (i < FP_SIZE) && fp_exp; i++) {
if (fp_exp_mask.u[i]) {
unsigned int x = (fp_exp_mask.u[i] & fp_val.u[i]);
if (x == fp_exp_mask.u[i]) {
/* these bits are all set. can't be zero
* exponent, but could still be max (weird)
* exponent.
*/
fp_exp &= ~FP_EXP_ZERO;
} else if (x == 0) {
/* none of these bits are set. can't be max
* exponent, but could still be zero exponent.
*/
fp_exp &= ~FP_EXP_WEIRD;
} else {
/* some bits were set but not others. can't
* be either zero exponent or max exponent.
*/
fp_exp = 0;
}
}
fp_sign |= (fp_sign_mask.u[i] & fp_val.u[i]);
fp_mant |= (fp_mant_mask.u[i] & fp_val.u[i]);

}
if (fp_exp == FP_EXP_WEIRD) {
if (fp_sign) {
safe_chr('-', buff, bufc);
}
if (fp_mant) {
safe_known_str("NaN", 3, buff, bufc);
} else {
safe_known_str("Inf", 3, buff, bufc);
}
}
return fp_exp;

static void fval(buff, bufc, result)


char *buff, **bufc;
double result;
{
char *p, *buf1;
switch (fp_check_weird(buff, bufc, result)) {
case FP_EXP_WEIRD: return;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:41 PM

case FP_EXP_ZERO:
result = 0.0; /* FALLTHRU */
default:
break;
}
buf1 = *bufc;
safe_tprintf_str(buff, bufc, "%.6f", result);
/* get double val
* into buffer
*/
**bufc = '\0';
p = strrchr(buf1, '0');
if (p == NULL) {
/* remove useless trailing 0's */
return;
} else if (*(p + 1) == '\0') {
while (*p == '0') {
*p-- = '\0';
}
*bufc = p + 1;
}
p = strrchr(buf1, '.'); /* take care of dangling '.' */
if ((p != NULL) && (*(p + 1) == '\0')) {
*p = '\0';
*bufc = p;
}
/* Handle bogus result of "-0" from sprintf.

Yay, cclib. */

if (!strcmp(buf1, "-0")) {
*buf1 = '0';
*bufc = buf1 + 1;
}

}
#else
#define fval(b,p,n)
#endif

safe_ltos(b,p,n)

/* --------------------------------------------------------------------------* Constant math funcs: PI, E


*/
FUNCTION(fun_pi)
{
safe_known_str("3.141592654", 11, buff, bufc);
}
FUNCTION(fun_e)
{
safe_known_str("2.718281828", 11, buff, bufc);
}
/* --------------------------------------------------------------------------* Math operations on one number: SIGN, ABS, FLOOR, CEIL, ROUND, TRUNC,
*
INC, DEC, SQRT, EXP, LN, [A][SIN,COS,TAN][D]
*/
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:41 PM

FUNCTION(fun_sign)
{
NVAL num;

num = aton(fargs[0]);
if (num < 0) {
safe_known_str("-1", 2, buff, bufc);
} else {
safe_bool(buff, bufc, (num > 0));
}

FUNCTION(fun_abs)
{
NVAL num;

num = aton(fargs[0]);
if (num == 0) {
safe_chr('0', buff, bufc);
} else if (num < 0) {
fval(buff, bufc, -num);
} else {
fval(buff, bufc, num);
}

FUNCTION(fun_floor)
{
#ifdef FLOATING_POINTS
char *oldp;
NVAL x;
oldp = *bufc;
x = floor(aton(fargs[0]));
switch (fp_check_weird(buff, bufc, x)) {
case FP_EXP_WEIRD: return;
case FP_EXP_ZERO:
x = 0.0; /* FALLTHRU */
default:
break;
}
safe_tprintf_str(buff, bufc, "%.0f", x);
/* Handle bogus result of "-0" from sprintf.
if (!strcmp(oldp, "-0")) {
*oldp = '0';
*bufc = oldp + 1;
}
#else
fval(buff, bufc, aton(fargs[0]));
#endif
}
FUNCTION(fun_ceil)
-4-

Yay, cclib. */

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:41 PM

{
#ifdef FLOATING_POINTS
char *oldp;
NVAL x;
oldp = *bufc;
x = ceil(aton(fargs[0]));
switch (fp_check_weird(buff, bufc, x)) {
case FP_EXP_WEIRD: return;
case FP_EXP_ZERO:
x = 0.0; /* FALLTHRU */
default:
break;
}
safe_tprintf_str(buff, bufc, "%.0f", x);
/* Handle bogus result of "-0" from sprintf.
if (!strcmp(oldp, "-0")) {
*oldp = '0';
*bufc = oldp + 1;
}
#else
fval(buff, bufc, aton(fargs[0]));
#endif
}
FUNCTION(fun_round)
{
#ifdef FLOATING_POINTS
const char *fstr;
char *oldp;
NVAL x;
oldp = *bufc;
switch (atoi(fargs[1])) {
case 1:
fstr = "%.1f";
break;
case 2:
fstr = "%.2f";
break;
case 3:
fstr = "%.3f";
break;
case 4:
fstr = "%.4f";
break;
case 5:
fstr = "%.5f";
break;
case 6:
fstr = "%.6f";
break;
default:
-5-

Yay, cclib. */

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:41 PM

fstr = "%.0f";
break;

}
x = aton(fargs[0]);
switch (fp_check_weird(buff, bufc, x)) {
case FP_EXP_WEIRD: return;
case FP_EXP_ZERO:
x = 0.0; /* FALLTHRU */
default:
break;
}
safe_tprintf_str(buff, bufc, (char *)fstr, x);
/* Handle bogus result of "-0" from sprintf.
if (!strcmp(oldp, "-0")) {
*oldp = '0';
*bufc = oldp + 1;
}
#else
fval(buff, bufc, aton(fargs[0]));
#endif
}
FUNCTION(fun_trunc)
{
#ifdef FLOATING_POINTS
NVAL x;
x = aton(fargs[0]);
x = (x >= 0) ? floor(x) : ceil(x);
switch (fp_check_weird(buff, bufc, x)) {
case FP_EXP_WEIRD: return;
case FP_EXP_ZERO:
x = 0.0; /* FALLTHRU */
default:
break;
}
fval(buff, bufc, x);
#else
fval(buff, bufc, aton(fargs[0]));
#endif
}
FUNCTION(fun_inc)
{
safe_ltos(buff, bufc, atoi(fargs[0]) + 1);
}
FUNCTION(fun_dec)
{
safe_ltos(buff, bufc, atoi(fargs[0]) - 1);
}
FUNCTION(fun_sqrt)
{
NVAL val;
-6-

Yay, cclib. */

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:41 PM

val = aton(fargs[0]);
if (val < 0) {
safe_str("#-1 SQUARE ROOT OF NEGATIVE" , buff, bufc);
} else if (val == 0) {
safe_chr('0', buff, bufc);
} else {
fval(buff, bufc, sqrt((double)val));
}

FUNCTION(fun_exp)
{
fval(buff, bufc, exp((double)aton(fargs[0])));
}
FUNCTION(fun_ln)
{
NVAL val;

val = aton(fargs[0]);
if (val > 0)
fval(buff, bufc, log((double)val));
else
safe_str("#-1 LN OF NEGATIVE OR ZERO", buff, bufc);

FUNCTION(handle_trig)
{
NVAL val;
int oper, flag;
static double (* const trig_funcs[8])(double) = {
sin, cos, tan, NULL, /* XXX no cotangent function */
asin, acos, atan, NULL
};
flag = Func_Flags(fargs);
oper = flag & TRIG_OPER;
val = aton(fargs[0]);
if ((flag & TRIG_ARC) && !(flag & TRIG_TAN) &&
((val < -1) || (val > 1))) {
safe_tprintf_str(buff, bufc, "#-1 %s ARGUMENT OUT OF RANGE" ,
((FUN *)fargs[-1])->name);
return;
}
if ((flag & TRIG_DEG) && !(flag & TRIG_ARC))
val = val * (M_PI / 180);
val = (trig_funcs[oper])((double)val);
if ((flag & TRIG_DEG) && (flag & TRIG_ARC))
val = (val * 180) / M_PI;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:41 PM

fval(buff, bufc, val);

/* --------------------------------------------------------------------------* Math comparison funcs: GT, GTE, LT, LTE, EQ, NEQ, NCOMP
*/
FUNCTION(fun_gt)
{
safe_bool(buff, bufc, (aton(fargs[0]) > aton(fargs[1])));
}
FUNCTION(fun_gte)
{
safe_bool(buff, bufc, (aton(fargs[0]) >= aton(fargs[1])));
}
FUNCTION(fun_lt)
{
safe_bool(buff, bufc, (aton(fargs[0]) < aton(fargs[1])));
}
FUNCTION(fun_lte)
{
safe_bool(buff, bufc, (aton(fargs[0]) <= aton(fargs[1])));
}
FUNCTION(fun_eq)
{
safe_bool(buff, bufc, (aton(fargs[0]) == aton(fargs[1])));
}
FUNCTION(fun_neq)
{
safe_bool(buff, bufc, (aton(fargs[0]) != aton(fargs[1])));
}
FUNCTION(fun_ncomp)
{
NVAL x, y;
x = aton(fargs[0]);
y = aton(fargs[1]);

if (x == y) {
safe_chr('0', buff, bufc);
} else if (x < y) {
safe_str("-1", buff, bufc);
} else {
safe_chr('1', buff, bufc);
}

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:41 PM

/* --------------------------------------------------------------------------* Two-argument math functions: SUB, DIV, FLOORDIV, FDIV, MODULO, REMAINDER,
*
POWER, LOG
*/
FUNCTION(fun_sub)
{
fval(buff, bufc, aton(fargs[0]) - aton(fargs[1]));
}
FUNCTION(fun_div)
{
int top, bot;
/* The C / operator is only fully specified for non-negative
* operands, so we try not to give it negative operands here
*/
top = atoi(fargs[0]);
bot = atoi(fargs[1]);
if (bot == 0) {
safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
return;
}

if (top < 0) {
if (bot < 0)
top = (-top) / (-bot);
else
top = -((-top) / bot);
} else {
if (bot < 0)
top = -(top / (-bot));
else
top = top / bot;
}
safe_ltos(buff, bufc, top);

FUNCTION(fun_floordiv)
{
int top, bot, res;
/* The C / operator is only fully specified for non-negative
* operands, so we try not to give it negative operands here
*/
top = atoi(fargs[0]);
bot = atoi(fargs[1]);
if (bot == 0) {
safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
return;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:41 PM

if (top < 0) {
if (bot < 0) {
res = (-top) / (-bot);
} else {
res = -((-top) / bot);
if (top % bot)
res--;
}
} else {
if (bot < 0) {
res = -(top / (-bot));
if (top % bot)
res--;
} else {
res = top / bot;
}
}
safe_ltos(buff, bufc, res);

FUNCTION(fun_fdiv)
{
NVAL bot;

bot = aton(fargs[1]);
if (bot == 0) {
safe_str("#-1 DIVIDE BY ZERO", buff, bufc);
} else {
fval(buff, bufc, (aton(fargs[0]) / bot));
}

FUNCTION(fun_modulo)
{
int top, bot;
/* The C % operator is only fully specified for non-negative
* operands, so we try not to give it negative operands here
*/
top = atoi(fargs[0]);
bot = atoi(fargs[1]);
if (bot == 0)
bot = 1;
if (top < 0) {
if (bot < 0)
top = -((-top) % (-bot));
else
top = (bot - ((-top) % bot)) % bot;
} else {
if (bot < 0)
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

else

Saturday, June 16, 2012 11:41 PM

top = -(((-bot) - (top % (-bot))) % (-bot));


top = top % bot;

}
safe_ltos(buff, bufc, top);

FUNCTION(fun_remainder)
{
int top, bot;
/* The C % operator is only fully specified for non-negative
* operands, so we try not to give it negative operands here
*/

top = atoi(fargs[0]);
bot = atoi(fargs[1]);
if (bot == 0)
bot = 1;
if (top < 0) {
if (bot < 0)
top = -((-top) % (-bot));
else
top = -((-top) % bot);
} else {
if (bot < 0)
top = top % (-bot);
else
top = top % bot;
}
safe_ltos(buff, bufc, top);

FUNCTION(fun_power)
{
NVAL val1, val2;

val1 = aton(fargs[0]);
val2 = aton(fargs[1]);
if (val1 < 0) {
safe_str("#-1 POWER OF NEGATIVE", buff, bufc);
} else {
fval(buff, bufc, pow((double)val1, (double)val2));
}

FUNCTION(fun_log)
{
NVAL val, base;
VaChk_Range(1, 2);
val = aton(fargs[0]);
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:41 PM

if (nfargs == 2)
base = aton(fargs[1]);
else
base = 10;

if ((val <= 0) || (base <= 0))


safe_str("#-1 LOG OF NEGATIVE OR ZERO" , buff, bufc);
else if (base == 1)
safe_str("#-1 DIVISION BY ZERO", buff, bufc);
else
fval(buff, bufc, log((double)val) / log((double)base));

/* -----------------------------------------------------------------------* Bitwise two-argument integer math functions: SHL, SHR, BAND, BOR, BNAND
*/
FUNCTION(fun_shl)
{
safe_ltos(buff, bufc, atoi(fargs[0]) << atoi(fargs[1]));
}
FUNCTION(fun_shr)
{
safe_ltos(buff, bufc, atoi(fargs[0]) >> atoi(fargs[1]));
}
FUNCTION(fun_band)
{
safe_ltos(buff, bufc, atoi(fargs[0]) & atoi(fargs[1]));
}
FUNCTION(fun_bor)
{
safe_ltos(buff, bufc, atoi(fargs[0]) | atoi(fargs[1]));
}
FUNCTION(fun_bnand)
{
safe_ltos(buff, bufc, atoi(fargs[0]) & ~(atoi(fargs[1])));
}
/* --------------------------------------------------------------------------* Multi-argument math functions: ADD, MUL, MAX, MIN
*/
FUNCTION(fun_add)
{
NVAL sum;
int i;
if (nfargs < 2) {
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:41 PM

safe_known_str("#-1 TOO FEW ARGUMENTS", 21, buff, bufc);


} else {
sum = aton(fargs[0]);
for (i = 1; i < nfargs; i++) {
sum += aton(fargs[i]);
}
fval(buff, bufc, sum);
}
return;

FUNCTION(fun_mul)
{
NVAL prod;
int i;

if (nfargs < 2) {
safe_known_str("#-1 TOO FEW ARGUMENTS", 21, buff, bufc);
} else {
prod = aton(fargs[0]);
for (i = 1; i < nfargs; i++) {
prod *= aton(fargs[i]);
}
fval(buff, bufc, prod);
}
return;

FUNCTION(fun_max)
{
int i;
NVAL max, val;

if (nfargs < 1) {
safe_known_str("#-1 TOO FEW ARGUMENTS", 21, buff, bufc);
} else {
max = aton(fargs[0]);
for (i = 1; i < nfargs; i++) {
val = aton(fargs[i]);
max = (max < val) ? val : max;
}
fval(buff, bufc, max);
}

FUNCTION(fun_min)
{
int i;
NVAL min, val;
if (nfargs < 1) {
safe_known_str("#-1 TOO FEW ARGUMENTS", 21, buff, bufc);
} else {
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:41 PM

min = aton(fargs[0]);
for (i = 1; i < nfargs; i++) {
val = aton(fargs[i]);
min = (min > val) ? val : min;
}
fval(buff, bufc, min);
}

/* --------------------------------------------------------------------------* Integer point distance functions: DIST2D, DIST3D


*/
FUNCTION(fun_dist2d)
{
int d;
double r;

d = atoi(fargs[0]) - atoi(fargs[2]);
r = (double)(d * d);
d = atoi(fargs[1]) - atoi(fargs[3]);
r += (double)(d * d);
d = (int)(sqrt(r) + 0.5);
safe_ltos(buff, bufc, d);

FUNCTION(fun_dist3d)
{
int d;
double r;

d = atoi(fargs[0]) - atoi(fargs[3]);
r = (double)(d * d);
d = atoi(fargs[1]) - atoi(fargs[4]);
r += (double)(d * d);
d = atoi(fargs[2]) - atoi(fargs[5]);
r += (double)(d * d);
d = (int)(sqrt(r) + 0.5);
safe_ltos(buff, bufc, d);

/* --------------------------------------------------------------------------* Math "accumulator" operations on a list: LADD, LMAX, LMIN


*/
FUNCTION(fun_ladd)
{
NVAL sum;
char *cp, *curr;
Delim isep;
if (nfargs == 0) {
safe_chr('0', buff, bufc);
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:41 PM

return;
}
VaChk_Only_In(2);

sum = 0;
cp = trim_space_sep(fargs[0], &isep);
while (cp) {
curr = split_token(&cp, &isep);
sum += aton(curr);
}
fval(buff, bufc, sum);

FUNCTION(fun_lmax)
{
NVAL max, val;
char *cp, *curr;
Delim isep;
VaChk_Only_In(2);

cp = trim_space_sep(fargs[0], &isep);
if (cp) {
curr = split_token(&cp, &isep);
max = aton(curr);
while (cp) {
curr = split_token(&cp, &isep);
val = aton(curr);
if (max < val)
max = val;
}
fval(buff, bufc, max);
}

FUNCTION(fun_lmin)
{
NVAL min, val;
char *cp, *curr;
Delim isep;
VaChk_Only_In(2);
cp = trim_space_sep(fargs[0], &isep);
if (cp) {
curr = split_token(&cp, &isep);
min = aton(curr);
while (cp) {
curr = split_token(&cp, &isep);
val = aton(curr);
if (min > val)
min = val;
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:41 PM

}
fval(buff, bufc, min);
}

/* --------------------------------------------------------------------------* Operations on a single vector: VMAG, VUNIT


* (VDIM is implemented by fun_words)
*/
FUNCTION(handle_vector)
{
char **v1;
int n, i, oper;
NVAL tmp, res = 0;
Delim isep, osep;
oper = Func_Mask(VEC_OPER);
if (oper == VEC_UNIT) {
VaChk_Only_In_Out(3);
} else {
VaChk_Only_In(2);
}
/* split the list up, or return if the list is empty */
if (!fargs[0] || !*fargs[0]) {
return;
}
n = list2arr(&v1, LBUF_SIZE, fargs[0], &isep);
/* calculate the magnitude */
for (i = 0; i < n; i++) {
tmp = aton(v1[i]);
res += tmp * tmp;
}
/* if we're just calculating the magnitude, return it */
if (oper == VEC_MAG) {
if (res > 0) {
fval(buff, bufc, sqrt(res));
} else {
safe_chr('0', buff, bufc);
}
XFREE(v1, "handle_vector.v1");
return;
}
if (res <= 0) {
safe_str("#-1 CAN'T MAKE UNIT VECTOR FROM ZERO-LENGTH VECTOR" ,
buff, bufc);
XFREE(v1, "handle_vector.v1");
return;
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:41 PM

}
res = sqrt(res);
fval(buff, bufc, aton(v1[0]) / res);
for (i = 1; i < n; i++) {
print_sep(&osep, buff, bufc);
fval(buff, bufc, aton(v1[i]) / res);
}
XFREE(v1, "handle_vector.v1");

/* --------------------------------------------------------------------------* Operations on a pair of vectors: VADD, VSUB, VMUL, VDOT


*/
FUNCTION(handle_vectors)
{
Delim isep, osep;
int oper;
char **v1, **v2;
NVAL scalar;
int n, m, i;
oper = Func_Mask(VEC_OPER);
if (oper != VEC_DOT) {
VaChk_Only_In_Out(4);
} else {
/* dot product returns a scalar, so no output delim */
VaChk_Only_In(3);
}
/*
* split the list up, or return if the list is empty
*/
if (!fargs[0] || !*fargs[0] || !fargs[1] || !*fargs[1]) {
return;
}
n = list2arr(&v1, LBUF_SIZE, fargs[0], &isep);
m = list2arr(&v2, LBUF_SIZE, fargs[1], &isep);
/* It's okay to have vmul() be passed a scalar first or second arg,
* but everything else has to be same-dimensional.
*/
if ((n != m) &&
!((oper == VEC_MUL) && ((n == 1) || (m == 1)))) {
safe_str("#-1 VECTORS MUST BE SAME DIMENSIONS" , buff, bufc);
XFREE(v1, "handle_vectors.v1");
XFREE(v2, "handle_vectors.v2");
return;
}
switch (oper) {
case VEC_ADD:
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:41 PM

fval(buff, bufc, aton(v1[0]) + aton(v2[0]));


for (i = 1; i < n; i++) {
print_sep(&osep, buff, bufc);
fval(buff, bufc, aton(v1[i]) + aton(v2[i]));
}
break;
case VEC_SUB:
fval(buff, bufc, aton(v1[0]) - aton(v2[0]));
for (i = 1; i < n; i++) {
print_sep(&osep, buff, bufc);
fval(buff, bufc, aton(v1[i]) - aton(v2[i]));
}
break;
case VEC_MUL:
/* if n or m is 1, this is scalar multiplication.
* otherwise, multiply elementwise.
*/
if (n == 1) {
scalar = aton(v1[0]);
fval(buff, bufc, aton(v2[0]) * scalar);
for (i = 1; i < m; i++) {
print_sep(&osep, buff, bufc);
fval(buff, bufc, aton(v2[i]) * scalar);
}
} else if (m == 1) {
scalar = aton(v2[0]);
fval(buff, bufc, aton(v1[0]) * scalar);
for (i = 1; i < n; i++) {
print_sep(&osep, buff, bufc);
fval(buff, bufc, aton(v1[i]) * scalar);
}
} else {
/* vector elementwise product.
*
* Note this is a departure from TinyMUX, but an imitation
* of the PennMUSH behavior: the documentation in Penn
* claims it's a dot product, but the actual behavior
* isn't. We implement dot product separately!
*/
fval(buff, bufc, aton(v1[0]) * aton(v2[0]));
for (i = 1; i < n; i++) {
print_sep(&osep, buff, bufc);
fval(buff, bufc, aton(v1[i]) * aton(v2[i]));
}
}
break;
case VEC_DOT:
/* dot product: (a,b,c) . (d,e,f) = ad + be + cf
*
* no cross product implementation yet: it would be
* (a,b,c) x (d,e,f) = (bf - ce, cd - af, ae - bd)
*/
scalar = 0;
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:41 PM

for (i = 0; i < n; i++) {


scalar += aton(v1[i]) * aton(v2[i]);
}
fval(buff, bufc, scalar);
break;
default:
/* If we reached this, we're in trouble. */
safe_str("#-1 UNIMPLEMENTED", buff, bufc);
break;
}
XFREE(v1, "handle_vectors.v1");
XFREE(v2, "handle_vectors.v2");

/* --------------------------------------------------------------------------* Simple boolean funcs: NOT, NOTBOOL, T


*/
FUNCTION(fun_not)
{
safe_bool(buff, bufc, !atoi(fargs[0]));
}
FUNCTION(fun_notbool)
{
safe_bool(buff, bufc, !xlate(fargs[0]));
}
FUNCTION(fun_t)
{
safe_bool(buff, bufc, xlate(fargs[0]));
}
/* --------------------------------------------------------------------------* Multi-argument boolean funcs: various combinations of
*
[L,C][AND,OR,XOR][BOOL]
*/
FUNCTION(handle_logic)
{
Delim isep;
int flag, oper, i, val;
char *str, *tbuf, *bp;
int (*cvtfun)(char *);
flag = Func_Flags(fargs);
cvtfun = (flag & LOGIC_BOOL) ? xlate : (int (*)(char *))atoi;
oper = (flag & LOGIC_OPER);
/* most logic operations on an empty string should be false */
val = 0;
if (flag & LOGIC_LIST) {
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmath.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:41 PM

if (nfargs == 0) {
safe_chr('0', buff, bufc);
return;

/* the arguments come in a pre-evaluated list */


VaChk_Only_In(2);
bp = trim_space_sep(fargs[0], &isep);
while (bp) {
tbuf = split_token(&bp, &isep);
val = ((oper == LOGIC_XOR) && val) ? !cvtfun(tbuf) : cvtfun(tbuf);
if (((oper == LOGIC_AND) && !val) ||
((oper == LOGIC_OR) && val))
break;
}
} else if (nfargs < 2) {
/* separate arguments, but not enough of them */
safe_known_str("#-1 TOO FEW ARGUMENTS", 21, buff, bufc);
return;
} else if (flag & FN_NO_EVAL) {
/* separate, unevaluated arguments */
tbuf = alloc_lbuf("handle_logic");
for (i = 0; i < nfargs; i++) {
str = fargs[i];
bp = tbuf;
exec(tbuf, &bp, player, caller, cause,
EV_EVAL | EV_STRIP | EV_FCHECK, &str, cargs, ncargs);
val = ((oper == LOGIC_XOR) && val) ? !cvtfun(tbuf) : cvtfun(tbuf);
if (((oper == LOGIC_AND) && !val) ||
((oper == LOGIC_OR) && val))
break;
}
free_lbuf(tbuf);
} else {
/* separate, pre-evaluated arguments */
for (i = 0; i < nfargs; i++) {
val = ((oper == LOGIC_XOR) && val) ? !cvtfun(fargs[i]) : cvtfun(fargs[i]);
if (((oper == LOGIC_AND) && !val) ||
((oper == LOGIC_OR) && val))
break;
}
}
}

safe_bool(buff, bufc, val);

-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:41 PM

/* funmisc.c - misc functions */


/* $Id: funmisc.c,v 1.41 2008/02/27 05:55:37 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include
#include

"functions.h" /* required by code */


"attrs.h" /* required by code */
"powers.h" /* required by code */
"command.h"
/* required by code */
"match.h" /* required by code */

extern NAMETAB indiv_attraccess_nametab[];


extern void FDECL(do_pemit_list, (dbref, char *, const char *, int));
extern void FDECL(do_pemit, (dbref, dbref, int, char *, char *));
extern void FDECL(set_attr_internal, (dbref, dbref, int, char *, int,
char *, char **));
/* --------------------------------------------------------------------------* fun_switch: Return value based on pattern matching (ala @switch/first)
* fun_switchall: Similar, but ala @switch/all
* fun_case: Like switch(), but a straight exact match instead of wildcard.
* NOTE: These functions expect that their arguments have not been evaluated.
*/
FUNCTION(fun_switchall)
{
int i, got_one;
char *mbuff, *tbuff, *bp, *str, *save_token;
/* If we don't have at least 2 args, return nothing */
if (nfargs < 2) {
return;
}
/* Evaluate the target in fargs[0] */
mbuff = bp = alloc_lbuf("fun_switchall");
str = fargs[0];
exec(mbuff, &bp, player, caller, cause, EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:41 PM

/* Loop through the patterns looking for a match */


mudstate.in_switch++;
save_token = mudstate.switch_token;
got_one = 0;
for (i = 1; (i < nfargs - 1) && fargs[i] && fargs[i + 1]; i += 2) {
tbuff = bp = alloc_lbuf("fun_switchall.2");
str = fargs[i];
exec(tbuff, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
if (quick_wild(tbuff, mbuff)) {
got_one = 1;
free_lbuf(tbuff);
mudstate.switch_token = mbuff;
str = fargs[i+1];
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
} else {
free_lbuf(tbuff);
}
}
/* If we didn't match, return the default if there is one */
if (!got_one && (i < nfargs) && fargs[i]) {
mudstate.switch_token = mbuff;
str = fargs[i];
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
}

free_lbuf(mbuff);
mudstate.in_switch--;
mudstate.switch_token = save_token;

FUNCTION(fun_switch)
{
int i;
char *mbuff, *tbuff, *bp, *str, *save_token;
/* If we don't have at least 2 args, return nothing */
if (nfargs < 2) {
return;
}
/* Evaluate the target in fargs[0] */
mbuff = bp = alloc_lbuf("fun_switch");
str = fargs[0];
exec(mbuff, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:41 PM

/* Loop through the patterns looking for a match */


mudstate.in_switch++;
save_token = mudstate.switch_token;
for (i = 1; (i < nfargs - 1) && fargs[i] && fargs[i + 1]; i += 2) {
tbuff = bp = alloc_lbuf("fun_switch.2");
str = fargs[i];
exec(tbuff, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
if (quick_wild(tbuff, mbuff)) {
free_lbuf(tbuff);
mudstate.switch_token = mbuff;
str = fargs[i+1];
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
free_lbuf(mbuff);
mudstate.in_switch--;
mudstate.switch_token = save_token;
return;
}
free_lbuf(tbuff);
}
/* Nope, return the default if there is one */

if ((i < nfargs) && fargs[i]) {


mudstate.switch_token = mbuff;
str = fargs[i];
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
}
free_lbuf(mbuff);
mudstate.in_switch--;
mudstate.switch_token = save_token;

FUNCTION(fun_case)
{
int i;
char *mbuff, *tbuff, *bp, *str;
/* If we don't have at least 2 args, return nothing */
if (nfargs < 2) {
return;
}
/* Evaluate the target in fargs[0] */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:41 PM

mbuff = bp = alloc_lbuf("fun_case");
str = fargs[0];
exec(mbuff, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
/* Loop through the patterns looking for an exact match */
for (i = 1; (i < nfargs - 1) && fargs[i] && fargs[i + 1]; i += 2) {
tbuff = bp = alloc_lbuf("fun_case.2");
str = fargs[i];
exec(tbuff, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
if (!strcmp(tbuff, mbuff)) {
free_lbuf(tbuff);
str = fargs[i + 1];
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
free_lbuf(mbuff);
return;
}
free_lbuf(tbuff);
}
free_lbuf(mbuff);
/* Nope, return the default if there is one */

if ((i < nfargs) && fargs[i]) {


str = fargs[i];
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
}
return;

FUNCTION(handle_ifelse)
{
/* This function now assumes that its arguments have not been
evaluated. */
char *str, *mbuff, *bp, *save_token;
int flag, n;
char *tbuf = NULL;
flag = Func_Flags(fargs);
if (flag & IFELSE_DEFAULT) {
VaChk_Range(1, 2);
} else {
VaChk_Range(2, 3);
}
mbuff = bp = alloc_lbuf("handle_ifelse");
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:41 PM

str = fargs[0];
exec(mbuff, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
/* We default to bool-style, but we offer the option of the
* MUX-style nonzero -- it's true if it's not empty or zero.
*/
if (!mbuff || !*mbuff) {
n = 0;
} else if (flag & IFELSE_BOOL) {
/* xlate() destructively modifies the string */
tbuf = XSTRDUP(mbuff, "handle_ifelse.tbuf");
n = xlate(tbuf);
XFREE(tbuf, "handle_ifelse.tbuf");
} else {
n = !((atoi(mbuff) == 0) && is_number(mbuff));
}
if (flag & IFELSE_FALSE)
n = !n;
if (flag & IFELSE_DEFAULT) {
/* If we got our condition, return the string, otherwise
* return our 'else' default clause.
*/
if (n) {
safe_str(mbuff, buff, bufc);
} else {
str = fargs[1];
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
}
free_lbuf(mbuff);
return;
}
/* Not default mode: Use our condition to execute result clause */
if (!n) {
if (nfargs != 3) {
free_lbuf(mbuff);
return;
}
/* Do 'false' clause */
str = fargs[2];
} else {
/* Do 'true' clause */
str = fargs[1];
}
if (flag & IFELSE_TOKEN) {
mudstate.in_switch++;
save_token = mudstate.switch_token;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:41 PM

mudstate.switch_token = mbuff;

exec(buff, bufc, player, caller, cause,


EV_STRIP | EV_FCHECK | EV_EVAL, &str, cargs, ncargs);
free_lbuf(mbuff);

if (flag & IFELSE_TOKEN) {


mudstate.in_switch--;
mudstate.switch_token = save_token;
}

/* --------------------------------------------------------------------------* fun_rand: Return a random number from 0 to arg1-1


*/
FUNCTION(fun_rand)
{
int num;

num = atoi(fargs[0]);
if (num < 1) {
safe_chr('0', buff, bufc);
} else {
safe_tprintf_str(buff, bufc, "%ld", Randomize(num));
}

/* --------------------------------------------------------------------------* die(<number of dice>,<sides>): Roll XdY dice.


* lrand(<range bottom>,<range top>,<times>[,<delim>]): Generate random list.
*/
FUNCTION(fun_die)
{
int n, die, count;
int total = 0;
if (!fargs[0] || !fargs[1]) {
safe_chr('0', buff, bufc);
return;
}
n = atoi(fargs[0]);
die = atoi(fargs[1]);
if ((n == 0) || (die <= 0)) {
safe_chr('0', buff, bufc);
return;
}
if ((n < 1) || (n > 100)) {
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:41 PM

safe_str("#-1 NUMBER OUT OF RANGE", buff, bufc);


return;

}
for (count = 0; count < n; count++)
total += (int) random_range(1, die);
}

safe_ltos(buff, bufc, total);

FUNCTION(fun_lrand)
{
Delim osep;
int n_times, r_bot, r_top, i;
double n_range;
unsigned int tmp;
char *bb_p;
/* Special: the delim is really an output delim. */
VaChk_Only_Out(4);
/* If we're generating no numbers, since this is a list function,
* we return empty, rather than returning 0.
*/
n_times = atoi(fargs[2]);
if (n_times < 1) {
return;
}
if (n_times > LBUF_SIZE) {
n_times = LBUF_SIZE;
}
r_bot = atoi(fargs[0]);
r_top = atoi(fargs[1]);
if (r_top < r_bot) {
/* This is an error condition. Just return an empty list. We
* obviously can't return a random number between X and Y if
* Y is less than X.
*/
return;
} else if (r_bot == r_top) {
/* Just generate a list of n repetitions. */
bb_p = *bufc;
for (i = 0; i < n_times; i++) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:41 PM

}
safe_ltos(buff, bufc, r_bot);

}
return;
}

/* We've hit this point, we have a range. Generate a list. */

n_range = (double) r_top - r_bot + 1;


bb_p = *bufc;
for (i = 0; i < n_times; i++) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
tmp = (unsigned int) Randomize(n_range);
safe_ltos(buff, bufc, r_bot + tmp);
}

/* --------------------------------------------------------------------------* fun_lnum: Return a list of numbers.


*/
#define Lnum_Place(x)

(((x) < 10) ? (2*(x)) : ((3*(x))-10))

FUNCTION(fun_lnum)
{
char tbuf[12];
Delim osep;
int bot, top, over, i;
char *bb_p, *startp, *endp;
static int lnum_init = 0;
static char lnum_buff[290];
if (nfargs == 0) {
return;
}
/* lnum() is special, since its single delimiter is really an output
* delimiter.
*/
VaChk_Out(1, 3);
if (nfargs >= 2) {
bot = atoi(fargs[0]);
top = atoi(fargs[1]);
} else {
bot = 0;
top = atoi(fargs[0]);
if (top-- < 1)
/* still want to generate if arg is 1 */
return;
}

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

425
426
427
428
429

430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474

Saturday, June 16, 2012 11:41 PM

/* We keep 0-100 pre-generated so we can do quick copies. */


if (!lnum_init) {
strcpy(lnum_buff,
(char *) "0
25 26 27 28
50 51 52 53
75 76 77 78
lnum_init = 1;
}

1 2 3
29 30
54 55
79 80

4 5 6
31 32
56 57
81 82

7 8 9
33 34
58 59
83 84

10
35
60
85

11
36
61
86

12
37
62
87

13
38
63
88

14
39
64
89

15
40
65
90

16
41
66
91

17
42
67
92

18
43
68
93

19
44
69
94

20
45
70
95

21
46
71
96

22
47
72
97

/* If it's an ascending sequence crossing from negative numbers into


* positive, get the negative numbers out of the way first.
*/
bb_p = *bufc;
over = 0;
if ((bot < 0) && (top >= 0) && (osep.len == 1) && (osep.str[0] == ' ')) {
while ((bot < 0) && !over) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
ltos(tbuf, bot);
over = safe_str_fn(tbuf, buff, bufc);
bot++;
}
if (over)
return;
}
/* Copy as much out of the pre-gen as we can. */
if ((bot >= 0) && (bot < 100) && (top > bot) &&
(osep.len == 1) && (osep.str[0] == ' ')) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
startp = lnum_buff + Lnum_Place(bot);
if (top >= 99) {
safe_str(startp, buff, bufc);
} else {
endp = lnum_buff + Lnum_Place(top+1) - 1;
*endp = '\0';
safe_str(startp, buff, bufc);
*endp = ' ';
}
if (top < 100)
return;
else
bot = 100;
}
/* Print a new list. */
-9-

23
48
73
98

24
49
74
99" );

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527

if (top == bot) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
safe_ltos(buff, bufc, bot);
return;
} else if (top > bot) {
for (i = bot; (i <= top) && !over;
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
ltos(tbuf, i);
over = safe_str_fn(tbuf, buff,
}
} else {
for (i = bot; (i >= top) && !over;
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
ltos(tbuf, i);
over = safe_str_fn(tbuf, buff,
}
}

Saturday, June 16, 2012 11:41 PM

i++) {

bufc);
i--) {

bufc);

/* --------------------------------------------------------------------------* fun_time: Returns nicely-formatted time.


*/
FUNCTION(fun_time)
{
char *temp;

temp = (char *)ctime(&mudstate.now);


temp[strlen(temp) - 1] = '\0';
safe_str(temp, buff, bufc);

/* --------------------------------------------------------------------------* fun_time: Seconds since 0:00 1/1/70


*/
FUNCTION(fun_secs)
{
safe_ltos(buff, bufc, mudstate.now);
}
/* --------------------------------------------------------------------------* fun_convsecs: converts seconds to time string, based off 0:00 1/1/70
*/
FUNCTION(fun_convsecs)
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580

Saturday, June 16, 2012 11:41 PM

char *temp;
time_t tt;
tt = atol(fargs[0]);
temp = (char *)ctime(&tt);
temp[strlen(temp) - 1] = '\0';
safe_str(temp, buff, bufc);

/* --------------------------------------------------------------------------* fun_convtime: converts time string to seconds, based off 0:00 1/1/70
*
additional auxiliary function and table used to parse time string,
*
since no ANSI standard function are available to do this.
*/
static const char *monthtab[] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
static const char daystab[] =
{31, 29, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31};
/* converts time string to a struct tm. Returns 1 on success, 0 on fail.
* Time string format is always 24 characters long, in format
* Ddd Mmm DD HH:MM:SS YYYY
*/
#define get_substr(buf, p) { \
p = strchr(buf, ' '); \
if (p) { \
*p++ = '\0'; \
while (*p == ' ') p++; \
} \
}
int do_convtime(str, ttm)
char *str;
struct tm *ttm;
{
char *buf, *p, *q;
int i;
if (!str || !ttm)
return 0;
while (*str == ' ')
str++;
buf = p = alloc_sbuf("do_convtime");
safe_sb_str(str, buf, &p);
*p = '\0';

/* make a temp copy of arg */

get_substr(buf, p); /* day-of-week or month */


-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633

Saturday, June 16, 2012 11:41 PM

if (!p || strlen(buf) != 3) {
free_sbuf(buf);
return 0;
}
for (i = 0; (i < 12) && string_compare(monthtab[i], p); i++) ;
if (i == 12) {
get_substr(p, q);
/* month */
if (!q || strlen(p) != 3) {
free_sbuf(buf);
return 0;
}
for (i = 0; (i < 12) && string_compare(monthtab[i], p); i++) ;
if (i == 12) {
free_sbuf(buf);
return 0;
}
p = q;
}
ttm->tm_mon = i;
get_substr(p, q);
/* day of month */
if (!q || (ttm->tm_mday = atoi(p)) < 1 || ttm->tm_mday > daystab[i]) {
free_sbuf(buf);
return 0;
}
p = strchr(q, ':'); /* hours */
if (!p) {
free_sbuf(buf);
return 0;
}
*p++ = '\0';
if ((ttm->tm_hour = atoi(q)) > 23 || ttm->tm_hour < 0) {
free_sbuf(buf);
return 0;
}
if (ttm->tm_hour == 0) {
while (isspace(*q))
q++;
if (*q != '0') {
free_sbuf(buf);
return 0;
}
}
q = strchr(p, ':'); /* minutes */
if (!q) {
free_sbuf(buf);
return 0;
}
*q++ = '\0';
if ((ttm->tm_min = atoi(p)) > 59 || ttm->tm_min < 0) {
free_sbuf(buf);
return 0;
}
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686

Saturday, June 16, 2012 11:41 PM

if (ttm->tm_min == 0) {
while (isspace(*p))
p++;
if (*p != '0') {
free_sbuf(buf);
return 0;
}
}
get_substr(q, p);
/* seconds */
if (!p || (ttm->tm_sec = atoi(q)) > 59 || ttm->tm_sec < 0) {
free_sbuf(buf);
return 0;
}
if (ttm->tm_sec == 0) {
while (isspace(*q))
q++;
if (*q != '0') {
free_sbuf(buf);
return 0;
}
}
get_substr(p, q);
/* year */
if ((ttm->tm_year = atoi(p)) == 0) {
while (isspace(*p))
p++;
if (*p != '0') {
free_sbuf(buf);
return 0;
}
}
free_sbuf(buf);
if (ttm->tm_year > 100)
ttm->tm_year -= 1900;
if (ttm->tm_year < 0) {
return 0;
}
/* We don't whether or not it's daylight savings time. */
ttm->tm_isdst = -1;
#define LEAPYEAR_1900(yr) ((yr)%400==100||((yr)%100!=0&&(yr)%4==0))
return (ttm->tm_mday != 29 || i != 1 || LEAPYEAR_1900(ttm->tm_year));
#undef LEAPYEAR_1900
}
FUNCTION(fun_convtime)
{
struct tm *ttm;
ttm = localtime(&mudstate.now);
if (do_convtime(fargs[0], ttm))
safe_ltos(buff, bufc, timelocal(ttm));
else
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

Saturday, June 16, 2012 11:41 PM

safe_known_str("-1", 2, buff, bufc);

/* --------------------------------------------------------------------------* fun_timefmt: Interface to strftime().


*/
FUNCTION(fun_timefmt)
{
time_t tt;
struct tm *ttm;
char str[LBUF_SIZE], tbuf[LBUF_SIZE], *tp, *p;
int len;
/* Check number of arguments. */
if ((nfargs < 1) || !fargs[0] || !*fargs[0])
return;
if (nfargs == 1) {
tt = mudstate.now;
} else if (nfargs == 2) {
tt = (time_t) atol(fargs[1]);
if (tt < 0) {
safe_str("#-1 INVALID TIME", buff, bufc);
return;
}
} else {
safe_tprintf_str(buff, bufc,
"#-1 FUNCTION (TIMEFMT) EXPECTS 1 OR 2 ARGUMENTS BUT GOT %d" ,
nfargs);
return;
}
/* Construct the format string. We need to convert instances of '$'
* into percent signs for strftime(), unless we get a '$$', which
* we treat as a literal '$'. Step on '$n' as invalid (output literal
* '%n'), because some strftime()s use it to insert a newline.
*/
for (tp = tbuf, p = fargs[0], len = 0;
*p && (len < LBUF_SIZE - 2);
tp++, p++) {
if (*p == '%') {
*tp++ = '%';
*tp = '%';
} else if (*p == '$') {
if (*(p+1) == '$') {
*tp = '$';
p++;
} else if (*(p+1) == 'n') {
*tp++ = '%';
*tp++ = '%';
*tp = 'n';
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792

Saturday, June 16, 2012 11:41 PM

p++;
} else {
*tp = '%';
}
} else {
*tp = *p;
}
}
*tp = '\0';
/* Get the time and format it. We do this using the local timezone. */

ttm = localtime(&tt);
strftime(str, LBUF_SIZE - 1, tbuf, ttm);
safe_str(str, buff, bufc);

/* --------------------------------------------------------------------------* fun_starttime: What time did this system last reboot?


*/
FUNCTION(fun_starttime)
{
char *temp;

temp = (char *)ctime(&mudstate.start_time);


temp[strlen(temp) - 1] = '\0';
safe_str(temp, buff, bufc);

/* --------------------------------------------------------------------------* fun_restarts: How many times have we restarted?


*/
FUNCTION(fun_restarts)
{
safe_ltos(buff, bufc, mudstate.reboot_nums);
}
/* --------------------------------------------------------------------------* fun_restarttime: When did we last restart?
*/
FUNCTION(fun_restarttime)
{
char *temp;

temp = (char *)ctime(&mudstate.restart_time);


temp[strlen(temp) - 1] = '\0';
safe_str(temp, buff, bufc);

FUNCTION(fun_version)
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

{
}

Saturday, June 16, 2012 11:41 PM

safe_str(mudstate.version, buff, bufc);

/* --------------------------------------------------------------------------* fun_mudname: Return the name of the mud.


*/
FUNCTION(fun_mudname)
{
safe_str(mudconf.mud_name, buff, bufc);
}
/* --------------------------------------------------------------------------* fun_hasmodule: Return 1 if a module is installed, 0 if it is not.
*/
FUNCTION(fun_hasmodule)
{
MODULE *mp;

WALK_ALL_MODULES(mp) {
if (!strcasecmp(fargs[0], mp->modname)) {
safe_chr('1', buff, bufc);
return;
}
}
safe_chr('0', buff, bufc);

/* --------------------------------------------------------------------------* fun_connrecord: Get max number of simultaneous connects.


*/
FUNCTION(fun_connrecord)
{
safe_ltos(buff, bufc, mudstate.record_players);
}
/* --------------------------------------------------------------------------* State of the invocation and recursion counters.
*/
FUNCTION(fun_fcount)
{
safe_ltos(buff, bufc, mudstate.func_invk_ctr);
}
FUNCTION(fun_fdepth)
{
safe_ltos(buff, bufc, mudstate.func_nest_lev);
}

-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898

Saturday, June 16, 2012 11:41 PM

FUNCTION(fun_ccount)
{
safe_ltos(buff, bufc, mudstate.cmd_invk_ctr);
}
FUNCTION(fun_cdepth)
{
safe_ltos(buff, bufc, mudstate.cmd_nest_lev);
}
/* --------------------------------------------------------------------------* fun_s: Force substitution to occur.
* fun_subeval: Like s(), but don't do function evaluations.
*/
FUNCTION(fun_s)
{
char *str;

str = fargs[0];
exec(buff, bufc, player, caller, cause, EV_FIGNORE | EV_EVAL, &str,
cargs, ncargs);

FUNCTION(fun_subeval)
{
char *str;

str = fargs[0];
exec(buff, bufc, player, caller, cause,
EV_NO_LOCATION|EV_NOFCHECK|EV_FIGNORE|EV_NO_COMPRESS,
&str, (char **)NULL, 0);

/*-----------------------------------------------------------------------* Side-effect functions.


*/
static int check_command(player, name, buff, bufc, cargs, ncargs)
dbref player;
char *name, *buff, **bufc;
char *cargs[];
int ncargs;
{
CMDENT *cmdp;
if ((cmdp = (CMDENT *) hashfind(name, &mudstate.command_htab))) {
/*
*
*
*
*

Note that these permission checks are NOT identical to the


ones in process_cmdent(). In particular, side-effects are NOT
subject to the CA_GBL_INTERP flag. This is a design decision
based on the concept that these are functions and not commands,
even though they behave like commands in many respects. This
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951

Saturday, June 16, 2012 11:41 PM

* is also the same reason why side-effects don't trigger hooks.


*/
if (Invalid_Objtype(player) ||
!Check_Cmd_Access(player, cmdp, cargs, ncargs) ||
(!Builder(player) && Protect(CA_GBL_BUILD) &&
!(mudconf.control_flags & CF_BUILD))) {

}
}
}

safe_noperm(buff, bufc);
return 1;

return 0;

FUNCTION(fun_link)
{
if (check_command(player, "@link", buff, bufc, cargs, ncargs))
return;
do_link(player, cause, 0, fargs[0], fargs[1]);
}
FUNCTION(fun_tel)
{
if (check_command(player, "@teleport", buff, bufc, cargs, ncargs))
return;
do_teleport(player, cause, 0, fargs[0], fargs[1]);
}
FUNCTION(fun_wipe)
{
if (check_command(player, "@wipe", buff, bufc, cargs, ncargs))
return;
do_wipe(player, cause, 0, fargs[0]);
}
FUNCTION(fun_pemit)
{
if (check_command(player, "@pemit", buff, bufc, cargs, ncargs))
return;
do_pemit_list(player, fargs[0], fargs[1], 0);
}
FUNCTION(fun_remit)
{
if (check_command(player, "@pemit", buff, bufc, cargs, ncargs))
return;
do_pemit_list(player, fargs[0], fargs[1], 1);
}
FUNCTION(fun_oemit)
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004

Saturday, June 16, 2012 11:41 PM

if (check_command(player, "@oemit", buff, bufc, cargs, ncargs))


return;
do_pemit(player, cause, PEMIT_OEMIT, fargs[0], fargs[1]);

FUNCTION(fun_force)
{
if (check_command(player, "@force", buff, bufc, cargs, ncargs))
return;
do_force(player, cause, FRC_NOW, fargs[0], fargs[1], cargs, ncargs);
}
FUNCTION(fun_trigger)
{
if (nfargs < 1) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
}
if (check_command(player, "@trigger", buff, bufc, cargs, ncargs))
return;
do_trigger(player, cause, TRIG_NOW, fargs[0], &(fargs[1]), nfargs - 1);
}
FUNCTION(fun_wait)
{
do_wait(player, cause, 0, fargs[0], fargs[1], cargs, ncargs);
}
FUNCTION(fun_command)
{
CMDENT *cmdp;
char tbuf1[1], tbuf2[1];
char *p;
int key;
if (!fargs[0] || !*fargs[0])
return;
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
cmdp = (CMDENT *) hashfind(fargs[0], &mudstate.command_htab);
if (!cmdp) {
notify(player, "Command not found.");
return;
}
if (Invalid_Objtype(player) ||
!Check_Cmd_Access(player, cmdp, cargs, ncargs) ||
(!Builder(player) && Protect(CA_GBL_BUILD) &&
!(mudconf.control_flags & CF_BUILD))) {
notify(player, NOPERM_MESSAGE);
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

Saturday, June 16, 2012 11:41 PM

return;
}
if (!(cmdp->callseq & CS_FUNCTION) || (cmdp->callseq & CS_ADDED)) {
notify(player, "Cannot call that command.");
return;
}
/* Strip command flags that are irrelevant. */
key = cmdp->extra;
key &= ~(SW_GOT_UNIQUE | SW_MULTIPLE | SW_NOEVAL);
/* Can't handle null args, so make sure there's something there. */
tbuf1[0] = '\0';
tbuf2[0] = '\0';

switch (cmdp->callseq & CS_NARG_MASK) {


case CS_NO_ARGS:
(*(cmdp->info.handler)) (player, cause, key);
break;
case CS_ONE_ARG:
(*(cmdp->info.handler)) (player, cause, key,
((fargs[1]) ? (fargs[1]) : tbuf1));
break;
case CS_TWO_ARG:
(*(cmdp->info.handler)) (player, cause, key,
((fargs[1]) ? (fargs[1]) : tbuf1),
((fargs[2]) ? (fargs[2]) : tbuf2));
break;
default:
notify(player, "Invalid command handler.");
return;
}

/*-----------------------------------------------------------------------* fun_create: Creates a room, thing or exit


*/
FUNCTION(fun_create)
{
dbref thing;
int cost;
char *name;
Delim isep;
VaChk_Only_InPure(3);
name = fargs[0];
if (!name || !*name) {
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110

Saturday, June 16, 2012 11:41 PM

safe_str("#-1 ILLEGAL NAME", buff, bufc);


return;

switch (isep.str[0]) {
case 'r':
if (check_command(player, "@dig", buff, bufc)) {
return;
}
thing = create_obj(player, TYPE_ROOM, name, 0);
break;
case 'e':
if (check_command(player, "@open", buff, bufc)) {
return;
}
thing = create_obj(player, TYPE_EXIT, name, 0);
if (thing != NOTHING) {
s_Exits(thing, player);
s_Next(thing, Exits(player));
s_Exits(player, thing);
}
break;
default:
if (check_command(player, "@create", buff, bufc)) {
return;
}
if (fargs[1] && *fargs[1]) {
cost = atoi(fargs[1]);
if (cost < mudconf.createmin || cost > mudconf.createmax) {
safe_str("#-1 COST OUT OF RANGE", buff, bufc);
return;
}
} else {
cost = mudconf.createmin;
}
thing = create_obj(player, TYPE_THING, name, cost);
if (thing != NOTHING) {
move_via_generic(thing, player, NOTHING, 0);
s_Home(thing, new_home(player));
}
break;
}
safe_dbref(buff, bufc, thing);

/*--------------------------------------------------------------------------* fun_set: sets an attribute on an object


*/
FUNCTION(fun_set)
{
dbref thing, thing2, aowner;
char *p, *buff2;
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

Saturday, June 16, 2012 11:41 PM

int atr, atr2, aflags, alen, clear, flagvalue, could_hear;


ATTR *attr, *attr2;
/* obj/attr form? */
if (check_command(player, "@set", buff, bufc))
return;
if (parse_attrib(player, fargs[0], &thing, &atr, 0)) {
if (atr != NOTHING) {
/* must specify flag name */
if (!fargs[1] || !*fargs[1]) {
safe_str("#-1 UNSPECIFIED PARAMETER", buff, bufc);
}
/* are we clearing? */
clear = 0;
p = fargs[1];
if (*fargs[1] == NOT_TOKEN) {
p++;
clear = 1;
}
/* valid attribute flag? */
flagvalue = search_nametab(player,
indiv_attraccess_nametab, p);
if (flagvalue < 0) {
safe_str("#-1 CAN NOT SET", buff, bufc);
return;
}
/* make sure attribute is present */
if (!atr_get_info(thing, atr, &aowner, &aflags)) {
safe_str("#-1 ATTRIBUTE NOT PRESENT ON OBJECT" , buff, bufc);
return;
}
/* can we write to attribute? */
attr = atr_num(atr);
if (!attr || !Set_attr(player, thing, attr, aflags)) {
safe_noperm(buff, bufc);
return;
}
/* just do it! */
if (clear)
aflags &= ~flagvalue;
else
aflags |= flagvalue;
could_hear = Hearer(thing);
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216

Saturday, June 16, 2012 11:41 PM

atr_set_flags(thing, atr, aflags);


return;

}
}
/* find thing */
if ((thing = match_controlled(player, fargs[0])) == NOTHING) {
safe_nothing(buff, bufc);
return;
}
/* check for attr set first */
for (p = fargs[1]; *p && (*p != ':'); p++) ;
if (*p) {
*p++ = 0;
atr = mkattr(fargs[1]);
if (atr <= 0) {
safe_str("#-1 UNABLE TO CREATE ATTRIBUTE" , buff, bufc);
return;
}
attr = atr_num(atr);
if (!attr) {
safe_noperm(buff, bufc);
return;
}
atr_get_info(thing, atr, &aowner, &aflags);
if (!Set_attr(player, thing, attr, aflags)) {
safe_noperm(buff, bufc);
return;
}
buff2 = alloc_lbuf("fun_set");
/* check for _ */
if (*p == '_') {
strcpy(buff2, p + 1);
if (!parse_attrib(player, p + 1, &thing2, &atr2, 0) ||
(atr == NOTHING)) {
free_lbuf(buff2);
safe_nomatch(buff, bufc);
return;
}
attr2 = atr_num(atr);
p = buff2;
atr_pget_str(buff2, thing2, atr2, &aowner,
&aflags, &alen);
if (!attr2 ||
!See_attr(player, thing2, attr2, aowner, aflags)) {
free_lbuf(buff2);
safe_noperm(buff, bufc);
return;
}
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funmisc.c

1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227

Saturday, June 16, 2012 11:41 PM

}
/* set it */
set_attr_internal(player, thing, atr, p, 0, buff, bufc);
free_lbuf(buff2);
return;

}
/* set/clear a flag */
flag_set(thing, player, fargs[1], 0);

-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:40 PM

/* funobj.c - object functions */


/* $Id: funobj.c,v 1.79 2008/04/27 16:25:06 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include
#include

"functions.h"
"match.h" /*
"attrs.h" /*
"powers.h" /*
"walkdb.h" /*

/* required by code */
required by code */
required by code */
required by code */
required by code */

extern char *FDECL(upcasestr, (char *));


extern dbref FDECL(find_connected_ambiguous, (dbref, char *));
extern NAMETAB attraccess_nametab[];
extern NAMETAB indiv_attraccess_nametab[];
/* --------------------------------------------------------------------------* nearby_or_control: Check if player is near or controls thing
*/
#define nearby_or_control(p,t) \
(Good_obj(p) && Good_obj(t) && (Controls(p,t) || nearby(p,t)))
/* --------------------------------------------------------------------------* fun_con: Returns first item in contents list of object/room
*/
FUNCTION(fun_con)
{
dbref it;
it = match_thing(player, fargs[0]);
if (Good_loc(it) &&
(Examinable(player, it) ||
(where_is(player) == it) ||
(it == cause))) {
safe_dbref(buff, bufc, Contents(it));
return;
}
safe_nothing(buff, bufc);
return;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:40 PM

}
/* --------------------------------------------------------------------------* fun_exit: Returns first exit in exits list of room.
*/
FUNCTION(fun_exit)
{
dbref it, exit;
int key;

it = match_thing(player, fargs[0]);
if (Good_obj(it) && Has_exits(it) && Good_obj(Exits(it))) {
key = 0;
if (Examinable(player, it))
key |= VE_LOC_XAM;
if (Dark(it))
key |= VE_LOC_DARK;
DOLIST(exit, Exits(it)) {
if (Exit_Visible(exit, player, key)) {
safe_dbref(buff, bufc, exit);
return;
}
}
}
safe_nothing(buff, bufc);
return;

/* --------------------------------------------------------------------------* fun_next: return next thing in contents or exits chain


*/
FUNCTION(fun_next)
{
dbref it, loc, exit, ex_here;
int key;
it = match_thing(player, fargs[0]);
if (Good_obj(it) && Has_siblings(it)) {
loc = where_is(it);
ex_here = Good_obj(loc) ? Examinable(player, loc) : 0;
if (ex_here || (loc == player) || (loc == where_is(player))) {
if (!isExit(it)) {
safe_dbref(buff, bufc, Next(it));
return;
} else {
key = 0;
if (ex_here)
key |= VE_LOC_XAM;
if (Dark(loc))
key |= VE_LOC_DARK;
DOLIST(exit, it) {
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:40 PM

if ((exit != it) &&


Exit_Visible(exit, player, key)) {
safe_dbref(buff, bufc, exit);
return;
}

}
}
safe_nothing(buff, bufc);
return;

/* --------------------------------------------------------------------------* handle_loc: Locate an object (LOC, WHERE).


* loc(): Returns the location of something.
* where(): Returns the "true" location of something
*/
FUNCTION(handle_loc)
{
dbref it;

it = match_thing(player, fargs[0]);
if (locatable(player, it, cause)) {
safe_dbref(buff, bufc,
Is_Func(LOCFN_WHERE) ? where_is(it) : Location(it));
} else {
safe_nothing(buff, bufc);
}

/* --------------------------------------------------------------------------* fun_rloc: Returns the recursed location of something (specifying #levels)


*/
FUNCTION(fun_rloc)
{
int i, levels;
dbref it;
levels = atoi(fargs[1]);
if (levels > mudconf.ntfy_nest_lim)
levels = mudconf.ntfy_nest_lim;
it = match_thing(player, fargs[0]);
if (locatable(player, it, cause)) {
for (i = 0; i < levels; i++) {
if (Good_obj(it) &&
(Has_location(it) || isExit(it))) {
it = Location(it);
} else {
break;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:40 PM

}
}
safe_dbref(buff, bufc, it);
return;

}
safe_nothing(buff, bufc);

/* --------------------------------------------------------------------------* fun_room: Find the room an object is ultimately in.


*/
FUNCTION(fun_room)
{
dbref it;
int count;

it = match_thing(player, fargs[0]);
if (locatable(player, it, cause)) {
for (count = mudconf.ntfy_nest_lim; count > 0; count--) {
it = Location(it);
if (!Good_obj(it))
break;
if (isRoom(it)) {
safe_dbref(buff, bufc, it);
return;
}
}
safe_nothing(buff, bufc);
} else if (isRoom(it)) {
safe_dbref(buff, bufc, it);
} else {
safe_nothing(buff, bufc);
}
return;

/* --------------------------------------------------------------------------* fun_owner: Return the owner of an object.


*/
FUNCTION(fun_owner)
{
dbref it, aowner;
int atr, aflags;
if (parse_attrib(player, fargs[0], &it, &atr, 1)) {
if (atr == NOTHING) {
it = NOTHING;
} else {
atr_pget_info(it, atr, &aowner, &aflags);
it = aowner;
}
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:40 PM

} else {
it = match_thing(player, fargs[0]);
if (Good_obj(it))
it = Owner(it);
}
safe_dbref(buff, bufc, it);

/* --------------------------------------------------------------------------* fun_controls: Does x control y?


*/
FUNCTION(fun_controls)
{
dbref x, y;

x = match_thing(player, fargs[0]);
if (!Good_obj(x)) {
safe_str("#-1 ARG1 NOT FOUND", buff, bufc);
return;
}
y = match_thing(player, fargs[1]);
if (!Good_obj(y)) {
safe_str("#-1 ARG2 NOT FOUND", buff, bufc);
return;
}
safe_bool(buff, bufc, Controls(x, y));

/* --------------------------------------------------------------------------* fun_sees: Can X see Y in the normal Contents list of the room. If X
*
or Y do not exist, 0 is returned.
*/
FUNCTION(fun_sees)
{
dbref it, thing;
it = match_thing(player, fargs[0]);
thing = match_thing(player, fargs[1]);
if (!Good_obj(it) || !Good_obj(thing)) {
safe_chr('0', buff, bufc);
return;
}

safe_bool(buff, bufc,
(isExit(thing) ?
Can_See_Exit(it, thing, Darkened(it, Location(thing))) :
Can_See(it, thing, Sees_Always(it, Location(thing)))));

/* --------------------------------------------------------------------------* fun_nearby: Return whether or not obj1 is near obj2.


-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:40 PM

*/
FUNCTION(fun_nearby)
{
dbref obj1, obj2;

obj1 = match_thing(player, fargs[0]);


obj2 = match_thing(player, fargs[1]);
if (!(nearby_or_control(player, obj1) ||
nearby_or_control(player, obj2))) {
safe_chr('0', buff, bufc);
} else {
safe_bool(buff, bufc, nearby(obj1, obj2));
}

/* --------------------------------------------------------------------------* Presence functions.


*
hears(<object>, <speaker>): Can <object> hear <speaker> speak?
*
knows(<object>, <target>): Can <object> know about <target>?
*
moves(<object>, <mover>): Can <object> see <mover> move?
*/
FUNCTION(handle_okpres)
{
int oper;
dbref object, actor;
object = match_thing(player, fargs[0]);
actor = match_thing(player, fargs[1]);
if (!Good_obj(object) || !Good_obj(actor)) {
safe_chr('0', buff, bufc);
return;
}
oper = Func_Mask(PRESFN_OPER);
if (oper == PRESFN_HEARS) {
safe_bool(buff, bufc,
((Unreal(actor) && !Check_Heard(object, actor)) ||
(Unreal(object) && !Check_Hears(actor, object))) ? 0 : 1);
} else if (oper == PRESFN_MOVES) {
safe_bool(buff, bufc,
((Unreal(actor) && !Check_Noticed(object, actor)) ||
(Unreal(object) && !Check_Notices(actor, object))) ? 0 : 1);
} else if (oper == PRESFN_KNOWS) {
safe_bool(buff, bufc,
((Unreal(actor) && !Check_Known(object, actor)) ||
(Unreal(object) && !Check_Knows(actor, object))) ? 0 : 1);
} else {
safe_chr('0', buff, bufc);
}
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:40 PM

}
/* --------------------------------------------------------------------------* handle_name: Get object name (NAME, FULLNAME).
* name(): Return the name of an object.
* fullname(): Return the fullname of an object (good for exits).
*/
FUNCTION(handle_name)
{
dbref it;

it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
return;
}
if (!mudconf.read_rem_name) {
if (!nearby_or_control(player, it) &&
!isPlayer(it) && !Long_Fingers(player)) {
safe_str("#-1 TOO FAR AWAY TO SEE", buff, bufc);
return;
}
}
if (!Is_Func(NAMEFN_FULLNAME) && isExit(it))
safe_exit_name(it, buff, bufc);
else
safe_name(it, buff, bufc);

/* --------------------------------------------------------------------------* handle_pronoun: perform pronoun sub for object (OBJ, POSS, SUBJ, APOSS).
*/
FUNCTION(handle_pronoun)
{
dbref it;
char *str;
char *pronouns[4] = { "%o", "%p", "%s", "%a" };

it = match_thing(player, fargs[0]);
if (!Good_obj(it) ||
(!isPlayer(it) && !nearby_or_control(player, it))) {
safe_nomatch(buff, bufc);
} else {
str = pronouns[Func_Flags(fargs)];
exec(buff, bufc, it, it, it, 0, &str, (char **)NULL, 0);
}

/* --------------------------------------------------------------------------* Locks.
*/
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:40 PM

FUNCTION(fun_lock)
{
dbref it, aowner;
int aflags, alen;
char *tbuf;
ATTR *attr;
struct boolexp *bool;
/* Parse the argument into obj + lock */
if (!get_obj_and_lock(player, fargs[0], &it, &attr, buff, bufc))
return;
/* Get the attribute and decode it if we can read it */

tbuf = atr_get(it, attr->number, &aowner, &aflags, &alen);


if (Read_attr(player, it, attr, aowner, aflags)) {
bool = parse_boolexp(player, tbuf, 1);
free_lbuf(tbuf);
tbuf = (char *)unparse_boolexp_function(player, bool);
free_boolexp(bool);
safe_str(tbuf, buff, bufc);
} else
free_lbuf(tbuf);

FUNCTION(fun_elock)
{
dbref it, victim, aowner;
int aflags, alen;
char *tbuf;
ATTR *attr;
struct boolexp *bool;
/* Parse lock supplier into obj + lock */
if (!get_obj_and_lock(player, fargs[0], &it, &attr, buff, bufc))
return;
/* Get the victim and ensure we can do it */
victim = match_thing(player, fargs[1]);
if (!Good_obj(victim)) {
safe_nomatch(buff, bufc);
} else if (!nearby_or_control(player, victim) &&
!nearby_or_control(player, it)) {
safe_str("#-1 TOO FAR AWAY", buff, bufc);
} else {
tbuf = atr_get(it, attr->number, &aowner, &aflags, &alen);
if ((attr->flags & AF_IS_LOCK) ||
Read_attr(player, it, attr, aowner, aflags)) {
if (Pass_Locks(victim)) {
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:40 PM

safe_chr('1', buff, bufc);


} else {
bool = parse_boolexp(player, tbuf, 1);
safe_bool(buff, bufc, eval_boolexp(victim, it, it,
bool));
free_boolexp(bool);
}
} else {
safe_chr('0', buff, bufc);
}
free_lbuf(tbuf);

FUNCTION(fun_elockstr)
{
dbref locked_obj, actor_obj;
BOOLEXP *okey;
locked_obj = match_thing(player, fargs[0]);
actor_obj = match_thing(player, fargs[1]);

if (!Good_obj(locked_obj) || !Good_obj(actor_obj)) {
safe_nomatch(buff, bufc);
} else if (!nearby_or_control(player, actor_obj)) {
safe_str("#-1 TOO FAR AWAY", buff, bufc);
} else if (!Controls(player, locked_obj)) {
safe_noperm(buff, bufc);
} else {
okey = parse_boolexp(player, fargs[2], 0);
if (okey == TRUE_BOOLEXP) {
safe_str("#-1 INVALID KEY", buff, bufc);
} else if (Pass_Locks(actor_obj)) {
safe_chr('1', buff, bufc);
} else {
safe_ltos(buff, bufc, eval_boolexp(actor_obj,
locked_obj, locked_obj, okey));
}
free_boolexp(okey);
}

/* --------------------------------------------------------------------------* fun_xcon: Return a partial list of contents of an object, starting from


*
a specified element in the list and copying a specified number
*
of elements.
*/
FUNCTION(fun_xcon)
{
dbref thing, it;
char *bb_p;
int i, first, last;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:40 PM

Delim osep;
VaChk_Only_Out(4);
it = match_thing(player, fargs[0]);
bb_p = *bufc;
if (Good_loc(it) &&
(Examinable(player, it) || (Location(player) == it) ||
(it == cause))) {
first = atoi(fargs[1]);
last = atoi(fargs[2]);
if ((first > 0) && (last > 0)) {
/* Move to the first object that we want */
for (thing = Contents(it), i = 1;
(i < first) && (thing != NOTHING) && (Next(thing) != thing);
thing = Next(thing), i++)
;
/* Grab objects until we reach the last one we want */
for (i = 0;
(i < last) && (thing != NOTHING) && (Next(thing) != thing);
thing = Next(thing), i++) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
safe_dbref(buff, bufc, thing);
}

}
} else
safe_nothing(buff, bufc);

/* --------------------------------------------------------------------------* fun_lcon: Return a list of contents.


*/
FUNCTION(fun_lcon)
{
dbref thing, it;
char *bb_p;
Delim osep;
VaChk_Only_Out(2);
it = match_thing(player, fargs[0]);
bb_p = *bufc;
if (Good_loc(it) &&
(Examinable(player, it) ||
(Location(player) == it) ||
(it == cause))) {
DOLIST(thing, Contents(it)) {
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:40 PM

if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
safe_dbref(buff, bufc, thing);

}
} else
safe_nothing(buff, bufc);

/* --------------------------------------------------------------------------* fun_lexits: Return a list of exits.


*/
FUNCTION(fun_lexits)
{
dbref thing, it, parent;
char *bb_p;
int exam, lev, key;
Delim osep;
VaChk_Only_Out(2);
it = match_thing(player, fargs[0]);
if (!Good_obj(it) || !Has_exits(it)) {
safe_nothing(buff, bufc);
return;
}
exam = Examinable(player, it);
if (!exam && (where_is(player) != it) && (it != cause)) {
safe_nothing(buff, bufc);
return;
}
/* Return info for all parent levels */
bb_p = *bufc;
ITER_PARENTS(it, parent, lev) {
/* Look for exits at each level */
if (!Has_exits(parent))
continue;
key = 0;
if (Examinable(player, parent))
key |= VE_LOC_XAM;
if (Dark(parent))
key |= VE_LOC_DARK;
if (Dark(it))
key |= VE_BASE_DARK;
DOLIST(thing, Exits(parent)) {
if (Exit_Visible(thing, player, key)) {
if (*bufc != bb_p) {
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:40 PM

print_sep(&osep, buff, bufc);


}
safe_dbref(buff, bufc, thing);

}
return;

/* --------------------------------------------------------------------------* fun_entrances: approximate equivalent of @entrances command.


* * borrowed in part from PennMUSH.
*/
FUNCTION(fun_entrances)
{
dbref thing, i;
char *bb_p;
int low_bound, high_bound, control_thing;
int find_ex, find_th, find_pl, find_rm;
VaChk_Range(0, 4);
if (nfargs >= 3) {
low_bound = atoi(fargs[2] + (fargs[2][0] == NUMBER_TOKEN));
if (!Good_dbref(low_bound))
low_bound = 0;
} else {
low_bound = 0;
}
if (nfargs == 4) {
high_bound = atoi(fargs[3] + (fargs[3][0] == NUMBER_TOKEN));
if (!Good_dbref(high_bound))
high_bound = mudstate.db_top - 1;
} else {
high_bound = mudstate.db_top - 1;
}
find_ex = find_th = find_pl = find_rm = 0;
if (nfargs >= 2) {
for (bb_p = fargs[1]; *bb_p; ++bb_p) {
switch(*bb_p) {
case 'a': case 'A':
find_ex = find_th = find_pl = find_rm = 1;
break;
case 'e': case 'E': find_ex = 1; break;
case 't': case 'T': find_th = 1; break;
case 'p': case 'P': find_pl = 1; break;
case 'r': case 'R': find_rm = 1; break;
default:
safe_str("#-1 INVALID TYPE", buff, bufc);
return;
}
}
}
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:40 PM

if (!find_ex && !find_th && !find_pl && !find_rm) {


find_ex = find_th = find_pl = find_rm = 1;
}
if (!fargs[0] || !*fargs[0]) {
if (Has_location(player))
thing = Location(player);
else
thing = player;
if (!Good_obj(thing)) {
safe_nothing(buff, bufc);
return;
}
} else {
init_match(player, fargs[0], NOTYPE);
match_everything(MAT_EXIT_PARENTS);
thing = noisy_match_result();
if (!Good_obj(thing)) {
safe_nothing(buff, bufc);
return;
}
}
if (!payfor(player, mudconf.searchcost)) {
notify(player, tprintf("You don't have enough %s.",
mudconf.many_coins));
safe_nothing(buff, bufc);
return;
}
control_thing = Examinable(player, thing);
bb_p = *bufc;
for (i = low_bound; i <= high_bound; i++) {
if (control_thing || Examinable(player, i)) {
if ((find_ex && isExit(i) && (Location(i) == thing)) ||
(find_rm && isRoom(i) && (Dropto(i) == thing)) ||
(find_th && isThing(i) && (Home(i) == thing)) ||
(find_pl && isPlayer(i) && (Home(i) == thing))) {
if (*bufc != bb_p)
safe_chr(' ', buff, bufc);
safe_dbref(buff, bufc, i);
}
}
}

/* -------------------------------------------------------------------------* fun_home: Return an object's home


*/
FUNCTION(fun_home)
{
dbref it;
it = match_thing(player, fargs[0]);
if (!Good_obj(it) || !Examinable(player, it)) {
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:40 PM

safe_nothing(buff, bufc);
} else if (Has_home(it)) {
safe_dbref(buff, bufc, Home(it));
} else if (Has_dropto(it)) {
safe_dbref(buff, bufc, Dropto(it));
} else if (isExit(it)) {
safe_dbref(buff, bufc, where_is(it));
} else {
safe_nothing(buff, bufc);
}
return;

/* --------------------------------------------------------------------------* fun_money: Return an object's value


*/
FUNCTION(fun_money)
{
dbref it;

it = match_thing(player, fargs[0]);
if (!Good_obj(it) || !Examinable(player, it))
safe_nothing(buff, bufc);
else
safe_ltos(buff, bufc, Pennies(it));

/* --------------------------------------------------------------------------* fun_findable: can X locate Y


*/
/* Borrowed from PennMUSH 1.50 */
FUNCTION(fun_findable)
{
dbref obj = match_thing(player, fargs[0]);
dbref victim = match_thing(player, fargs[1]);

if (!Good_obj(obj))
safe_str("#-1 ARG1 NOT FOUND", buff, bufc);
else if (!Good_obj(victim))
safe_str("#-1 ARG2 NOT FOUND", buff, bufc);
else
safe_bool(buff, bufc, locatable(obj, victim, obj));

/* --------------------------------------------------------------------------* fun_visible: Can X examine Y. If X does not exist, 0 is returned.


*
If Y, the object, does not exist, 0 is returned. If
*
Y the object exists, but the optional attribute does
*
not, X's ability to return Y the object is returned.
*/

-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:40 PM

/* Borrowed from PennMUSH 1.50 */


FUNCTION(fun_visible)
{
dbref it, thing, aowner;
int aflags, atr;
ATTR *ap;

it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_chr('0', buff, bufc);
return;
}
if (parse_attrib(player, fargs[1], &thing, &atr, 1)) {
if (atr == NOTHING) {
safe_bool(buff, bufc, Examinable(it, thing));
return;
}
ap = atr_num(atr);
atr_pget_info(thing, atr, &aowner, &aflags);
safe_bool(buff, bufc, See_attr_all(it, thing, ap, aowner,
aflags, 1));
return;
}
thing = match_thing(player, fargs[1]);
if (!Good_obj(thing)) {
safe_chr('0', buff, bufc);
return;
}
safe_bool(buff, bufc, Examinable(it, thing));

/* -----------------------------------------------------------------------* fun_writable: Returns 1 if player could set <obj>/<attr>.


*/
FUNCTION(fun_writable)
{
dbref it, thing, aowner;
int aflags, atr, retval;
ATTR *ap;
char *s;
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_chr('0', buff, bufc);
return;
}
retval = parse_attrib(player, fargs[1], &thing, &atr, 1);
/* Possibilities:
* retval is 0, which means we didn't match a thing.
* retval is NOTHING, which means we matched a thing but have a
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:40 PM

*
non-existent attribute.
* retval is 1; atr is either NOTHING (non-existent attribute or
*
no permission to see), or a valid attr number. In the case
*
of NOTHING we can't tell which it is, so must continue.
*/
if (retval == 0) {
safe_chr('0', buff, bufc);
return;
}
if ((retval == 1) && (atr != NOTHING)) {
ap = atr_num(atr);
atr_pget_info(thing, atr, &aowner, &aflags);
safe_bool(buff, bufc, Set_attr(it, thing, ap, aflags));
return;
}
/* Non-existent attribute. Go see if it's settable. */
if (!fargs[1] || !*fargs[1]) {
safe_chr('0', buff, bufc);
return;
}
if (((s = strchr(fargs[1], '/')) == NULL) || !*s++) {
safe_chr('0', buff, bufc);
return;
}

atr = mkattr(s);
if ((atr <= 0) || ((ap = atr_num(atr)) == NULL)) {
safe_chr('0', buff, bufc);
return;
}
atr_pget_info(thing, atr, &aowner, &aflags);
safe_bool(buff, bufc, Set_attr(it, thing, ap, aflags));

/* -----------------------------------------------------------------------* fun_flags: Returns the flags on an object.


* Because @switch is case-insensitive, not quite as useful as it could be.
*/
FUNCTION(fun_flags)
{
dbref it, aowner;
int atr, aflags;
char *buff2, xbuf[16], *xbufp;
if (parse_attrib(player, fargs[0], &it, &atr, 1)) {
if (atr == NOTHING) {
safe_nothing(buff, bufc);
} else {
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:40 PM

atr_pget_info(it, atr, &aowner, &aflags);


Print_Attr_Flags(aflags, xbuf, xbufp);
safe_str(xbuf, buff, bufc);
}
} else {
it = match_thing(player, fargs[0]);
if (Good_obj(it) &&
(mudconf.pub_flags || Examinable(player, it) ||
(it == cause))) {
buff2 = unparse_flags(player, it);
safe_str(buff2, buff, bufc);
free_sbuf(buff2);
} else
safe_nothing(buff, bufc);
}

/* --------------------------------------------------------------------------* andflags, orflags: Check a list of flags.


*/
FUNCTION(handle_flaglists)
{
char *s;
char flagletter[2];
FLAGSET fset;
FLAG p_type;
int negate, temp, type;
dbref it = match_thing(player, fargs[0]);
type = Is_Func(LOGIC_OR);
negate = temp = 0;
if (!Good_obj(it) ||
(!(mudconf.pub_flags || Examinable(player, it) || (it == cause)))) {
safe_chr('0', buff, bufc);
return;
}
for (s = fargs[1]; *s; s++) {
/* Check for a negation sign. If we find it, we note it and
* increment the pointer to the next character.
*/
if (*s == '!') {
negate = 1;
s++;
} else {
negate = 0;
}

-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:40 PM

if (!*s) {
safe_chr('0', buff, bufc);
return;
}
flagletter[0] = *s;
flagletter[1] = '\0';
if (!convert_flags(player, flagletter, &fset, &p_type)) {
/* Either we got a '!' that wasn't followed by a
* letter, or we couldn't find that flag. For
* AND, since we've failed a check, we can
* return false. Otherwise we just go on.
*/
if (!type) {
safe_chr('0', buff, bufc);
return;
} else
continue;
} else {
/* does the object have this flag? */
if ((Flags(it) & fset.word1) ||
(Flags2(it) & fset.word2) ||
(Flags3(it) & fset.word3) ||
(Typeof(it) == p_type)) {
if ((p_type == TYPE_PLAYER) &&
(fset.word2 == CONNECTED) &&
Can_Hide(it) && Hidden(it) &&
!See_Hidden(player))
temp = 0;
else
temp = 1;
} else {
temp = 0;
}
if (!(type ^ negate ^ temp)) {
/* Four ways to satisfy that test:
* AND, don't want flag but we have it;
* AND, do want flag but don't have it;
* OR, don't want flag and don't have it;
* OR, do want flag and do have it.
*/
safe_bool(buff, bufc, type);
return;

}
/* Otherwise, move on to check the next flag. */

-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:40 PM

}
safe_bool(buff, bufc, !type);

/*--------------------------------------------------------------------------* fun_hasflag: plus auxiliary function atr_has_flag.


*/
static int
atr_has_flag(player, thing, attr, aowner, aflags, flagname)
dbref player, thing;
ATTR *attr;
int aowner, aflags;
char *flagname;
{
int flagval;
if (!See_attr(player, thing, attr, aowner, aflags))
return 0;
flagval = search_nametab(player, indiv_attraccess_nametab, flagname);
if (flagval < 0)
flagval = search_nametab(player, attraccess_nametab, flagname);
if (flagval < 0)
return 0;
}

return (aflags & flagval);

FUNCTION(fun_hasflag)
{
dbref it, aowner;
int atr, aflags;
ATTR *ap;
if (parse_attrib(player, fargs[0], &it, &atr, 1)) {
if (atr == NOTHING) {
safe_str("#-1 NOT FOUND", buff, bufc);
} else {
ap = atr_num(atr);
atr_pget_info(it, atr, &aowner, &aflags);
safe_bool(buff, bufc,
atr_has_flag(player, it, ap, aowner, aflags, fargs[1]));
}
} else {
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
}
if (mudconf.pub_flags || Examinable(player, it) || (it == cause)) {
safe_bool(buff, bufc, has_flag(player, it, fargs[1]));
} else {
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

}
}

Saturday, June 16, 2012 11:40 PM

safe_noperm(buff, bufc);

FUNCTION(fun_haspower)
{
dbref it;

it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
}
if (mudconf.pub_flags || Examinable(player, it) || (it == cause)) {
safe_bool(buff, bufc, has_power(player, it, fargs[1]));
} else {
safe_noperm(buff, bufc);
}

/* --------------------------------------------------------------------------* hasflags(<object>, <flag list to AND>, <OR flag list to AND>, <etc.>)
*/
FUNCTION(fun_hasflags)
{
dbref it;
char **elems;
int n_elems, i, j, result;
if (nfargs < 2) {
safe_tprintf_str(buff, bufc,
"#-1 FUNCTION (HASFLAGS) EXPECTS AT LEAST 2 ARGUMENTS BUT GOT %d" ,
nfargs);
return;
}
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
}
/* Walk through each of the lists we've been passed. We need to have
* all the flags in a particular list (AND) in order to consider that
* list true. We return 1 if any of the lists are true. (i.e., we
* OR the list results).
*/
result = 0;
for (i = 1; !result && (i < nfargs); i++) {
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:40 PM

n_elems = list2arr(&elems, LBUF_SIZE / 2, fargs[i], &SPACE_DELIM);


if (n_elems > 0) {
result = 1;
for (j = 0; result && (j < n_elems); j++) {
if (*elems[j] == '!')
result = (has_flag(player, it, elems[j] + 1)) ? 0 : 1;
else
result = has_flag(player, it, elems[j]);
}
}
XFREE(elems, "fun_hasflags.elems");
}
}

safe_bool(buff, bufc, result);

/* --------------------------------------------------------------------------* handle_timestamp: Get timestamps (LASTACCESS, LASTMOD).


*/
FUNCTION(handle_timestamp)
{
dbref it = match_thing(player, fargs[0]);

if (!Good_obj(it) || !Examinable(player, it)) {


safe_known_str("-1", 2, buff, bufc);
} else {
safe_ltos(buff, bufc,
Is_Func(TIMESTAMP_MOD) ? ModTime(it) : AccessTime(it));
}

/* --------------------------------------------------------------------------* Parent-child relationships.


*/
FUNCTION(fun_parent)
{
dbref it;

it = match_thing(player, fargs[0]);
if (Good_obj(it) && (Examinable(player, it) || (it == cause))) {
safe_dbref(buff, bufc, Parent(it));
} else {
safe_nothing(buff, bufc);
}
return;

FUNCTION(fun_lparent)
{
dbref it, par;
int i;
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

Saturday, June 16, 2012 11:40 PM

Delim osep;
VaChk_Only_Out(2);
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
} else if (!(Examinable(player, it))) {
safe_noperm(buff, bufc);
return;
}
safe_dbref(buff, bufc, it);
par = Parent(it);

i = 1;
while (Good_obj(par) && Examinable(player, it) &&
(i < mudconf.parent_nest_lim)) {
print_sep(&osep, buff, bufc);
safe_dbref(buff, bufc, par);
it = par;
par = Parent(par);
i++;
}

FUNCTION(fun_children)
{
dbref i, it;
char *bb_p;
Delim osep;
VaChk_Only_Out(2);
if (!strcmp(fargs[0], "#-1")) {
it = NOTHING;
} else {
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
}
}
if (!Controls(player, it) && !See_All(player)) {
safe_noperm(buff, bufc);
return;
}
bb_p = *bufc;
DO_WHOLE_DB(i) {
if (Parent(i) == it) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

Saturday, June 16, 2012 11:40 PM

safe_dbref(buff, bufc, i);

/* --------------------------------------------------------------------------* Zones.
*/
FUNCTION(fun_zone)
{
dbref it;

if (!mudconf.have_zones) {
safe_str("#-1 ZONES DISABLED", buff, bufc);
return;
}
it = match_thing(player, fargs[0]);
if (!Good_obj(it) || !Examinable(player, it)) {
safe_nothing(buff, bufc);
return;
}
safe_dbref(buff, bufc, Zone(it));

FUNCTION(scan_zone)
{
dbref i, it;
int type;
char *bb_p;
type = Func_Mask(TYPE_MASK);
if (!mudconf.have_zones) {
safe_str("#-1 ZONES DISABLED", buff, bufc);
return;
}
if (!strcmp(fargs[0], "#-1")) {
it = NOTHING;
} else {
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
}
}
if (!Controls(player, it) && !WizRoy(player)) {
safe_noperm(buff, bufc);
return;
}
bb_p = *bufc;
DO_WHOLE_DB(i) {
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

Saturday, June 16, 2012 11:40 PM

if (Typeof(i) == type) {
if (Zone(i) == it) {
if (*bufc != bb_p) {
safe_chr(' ', buff, bufc);
}
safe_dbref(buff, bufc, i);
}
}

FUNCTION(fun_zfun)
{
dbref aowner;
int aflags, alen;
ATTR *ap;
char *tbuf1, *str;
dbref zone = Zone(player);
if (!mudconf.have_zones) {
safe_str("#-1 ZONES DISABLED", buff, bufc);
return;
}
if (zone == NOTHING) {
safe_str("#-1 INVALID ZONE", buff, bufc);
return;
}
if (!fargs[0] || !*fargs[0])
return;

/* find the user function attribute */


ap = atr_str(upcasestr(fargs[0]));
if (!ap) {
safe_str("#-1 NO SUCH USER FUNCTION", buff, bufc);
return;
}
tbuf1 = atr_pget(zone, ap->number, &aowner, &aflags, &alen);
if (!See_attr(player, zone, ap, aowner, aflags)) {
safe_str("#-1 NO PERMISSION TO GET ATTRIBUTE" , buff, bufc);
free_lbuf(tbuf1);
return;
}
str = tbuf1;
/* Behavior here is a little wacky. The enactor was always the player,
* not the cause. You can still get the caller, though.
*/
exec(buff, bufc, zone, caller, player,
EV_EVAL | EV_STRIP | EV_FCHECK, &str, &(fargs[1]), nfargs - 1);
free_lbuf(tbuf1);

/* ---------------------------------------------------------------------------24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325

Saturday, June 16, 2012 11:40 PM

* fun_hasattr: does object X have attribute Y.


*/
FUNCTION(fun_hasattr)
{
dbref thing, aowner;
int aflags, alen, check_parents;
ATTR *attr;
char *tbuf;
check_parents = Is_Func(CHECK_PARENTS);

thing = match_thing(player, fargs[0]);


if (!Good_obj(thing)) {
safe_nomatch(buff, bufc);
return;
} else if (!Examinable(player, thing)) {
safe_noperm(buff, bufc);
return;
}
attr = atr_str(fargs[1]);
if (!attr) {
safe_chr('0', buff, bufc);
return;
}
if (check_parents) {
atr_pget_info(thing, attr->number, &aowner, &aflags);
} else {
atr_get_info(thing, attr->number, &aowner, &aflags);
}
if (!See_attr(player, thing, attr, aowner, aflags)) {
safe_chr('0', buff, bufc);
} else {
if (check_parents) {
tbuf = atr_pget(thing, attr->number, &aowner, &aflags, &alen);
} else {
tbuf = atr_get(thing, attr->number, &aowner, &aflags, &alen);
}
if (*tbuf) {
safe_chr('1', buff, bufc);
} else {
safe_chr('0', buff, bufc);
}
free_lbuf(tbuf);
}

/* --------------------------------------------------------------------------* fun_v: Function form of %-substitution


*/
FUNCTION(fun_v)
{
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

Saturday, June 16, 2012 11:40 PM

dbref aowner;
int aflags, alen;
char *sbuf, *sbufc, *tbuf, *str;
ATTR *ap;
tbuf = fargs[0];
if (isalpha(tbuf[0]) && tbuf[1]) {
/* Fetch an attribute from me. First see if it exists,
* returning a null string if it does not.
*/
ap = atr_str(fargs[0]);
if (!ap) {
return;
}
/* If we can access it, return it, otherwise return a null
* string
*/
tbuf = atr_pget(player, ap->number, &aowner, &aflags, &alen);
if (See_attr(player, player, ap, aowner, aflags))
safe_known_str(tbuf, alen, buff, bufc);
free_lbuf(tbuf);
return;

}
/* Not an attribute, process as %<arg> */

sbuf = alloc_sbuf("fun_v");
sbufc = sbuf;
safe_sb_chr('%', sbuf, &sbufc);
safe_sb_str(fargs[0], sbuf, &sbufc);
*sbufc = '\0';
str = sbuf;
exec(buff, bufc, player, caller, cause, EV_FIGNORE, &str,
cargs, ncargs);
free_sbuf(sbuf);

/* --------------------------------------------------------------------------* perform_get: Get attribute from object: GET, XGET, GET_EVAL, EVAL(obj,atr)
*/
FUNCTION(perform_get)
{
dbref thing, aowner;
int attrib, aflags, alen, eval_it;
char *atr_gotten, *str;
eval_it = Is_Func(GET_EVAL);
if (Is_Func(GET_XARGS)) {
if (!*fargs[0] || !*fargs[1])
return;
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431

Saturday, June 16, 2012 11:40 PM

str = tprintf("%s/%s", fargs[0], fargs[1]);


} else {
str = fargs[0];
}

if (!parse_attrib(player, str, &thing, &attrib, 0)) {


safe_nomatch(buff, bufc);
return;
}
if (attrib == NOTHING) {
return;
}
/* There used to be code here to handle AF_IS_LOCK attributes,
* but parse_attrib can never return one of those. Use fun_lock
* instead.
*/
atr_gotten = atr_pget(thing, attrib, &aowner, &aflags, &alen);
if (eval_it) {
str = atr_gotten;
exec(buff, bufc, thing, player, player,
EV_FIGNORE | EV_EVAL, &str, (char **)NULL, 0);
} else {
safe_known_str(atr_gotten, alen, buff, bufc);
}
free_lbuf(atr_gotten);

FUNCTION(fun_eval)
{
char *str;
VaChk_Range(1, 2);
if (nfargs == 1) {
str = fargs[0];
exec(buff, bufc, player, caller, cause, EV_EVAL|EV_FCHECK,
&str, (char **)NULL, 0);
return;
}
}

perform_get( FUNCTION_ARGLIST );

/* --------------------------------------------------------------------------* do_ufun: Call a user-defined function: U, ULOCAL, UPRIVATE


*/
FUNCTION(do_ufun)
{
dbref aowner, thing;
int is_local, is_private, aflags, alen, anum, trace_flag;
ATTR *ap;
char *atext, *str;
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

Saturday, June 16, 2012 11:40 PM

GDATA *preserve;
is_local = Is_Func(U_LOCAL);
is_private = Is_Func(U_PRIVATE);
/* We need at least one argument */
if (nfargs < 1) {
safe_known_str("#-1 TOO FEW ARGUMENTS", 21, buff, bufc);
return;
}
/* First arg: <obj>/<attr> or <attr> or #lambda/<code> */
Get_Ulambda(player, thing, fargs[0],
anum, ap, atext, aowner, aflags, alen);
/* If we're evaluating locally, preserve the global registers.
* If we're evaluating privately, preserve and wipe out.
*/
if (is_local) {
preserve = save_global_regs("fun_ulocal.save");
} else if (is_private) {
preserve = mudstate.rdata;
mudstate.rdata = NULL;
}
/* If the trace flag is on this attr, set the object Trace */
if (!Trace(thing) && (aflags & AF_TRACE)) {
trace_flag = 1;
s_Trace(thing);
} else {
trace_flag = 0;
}
/* Evaluate it using the rest of the passed function args */
str = atext;
exec(buff, bufc, thing, player, cause, EV_FCHECK | EV_EVAL, &str,
&(fargs[1]), nfargs - 1);
free_lbuf(atext);
/* Reset the trace flag if we need to */
if (trace_flag) {
c_Trace(thing);
}
/* If we're evaluating locally, restore the preserved registers.
* If we're evaluating privately, free whatever data we had and
* restore.
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537

Saturday, June 16, 2012 11:40 PM

*/

if (is_local) {
restore_global_regs("fun_ulocal.restore", preserve);
} else if (is_private) {
Free_RegData(mudstate.rdata);
mudstate.rdata = preserve;
}

/* --------------------------------------------------------------------------* objcall: Call the text of a u-function from a specific object's


*
perspective. (i.e., get the text as the player, but execute
*
it as the specified object.
*/
FUNCTION(fun_objcall)
{
dbref obj, aowner, thing;
int aflags, alen, anum;
ATTR *ap;
char *atext, *str;
if (nfargs < 2) {
safe_known_str("#-1 TOO FEW ARGUMENTS", 21, buff, bufc);
return;
}
/* First arg: <obj>/<attr> or <attr> or #lambda/<code> */
Get_Ulambda(player, thing, fargs[1],
anum, ap, atext, aowner, aflags, alen);
/* Find our perspective. */
obj = match_thing(player, fargs[0]);
if (Cannot_Objeval(player, obj))
obj = player;
/* Evaluate using the rest of the passed function args. */

str = atext;
exec(buff, bufc, obj, player, cause, EV_FCHECK | EV_EVAL, &str,
&(fargs[2]), nfargs - 2);
free_lbuf(atext);

/* --------------------------------------------------------------------------* fun_localize: Evaluate a function with local scope (i.e., preserve and
* restore the r-registers). Essentially like calling ulocal() but with the
* function string directly.
*/

-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590

Saturday, June 16, 2012 11:40 PM

FUNCTION(fun_localize)
{
char *str;
GDATA *preserve;
preserve = save_global_regs("fun_localize_save");
str = fargs[0];
exec(buff, bufc, player, caller, cause,
EV_FCHECK | EV_STRIP | EV_EVAL, &str, cargs, ncargs);
}

restore_global_regs("fun_localize_restore", preserve);

/* --------------------------------------------------------------------------* fun_private: Evaluate a function with a strictly local scope -- do not


* pass global registers and discard any changes made to them. Like calling
* uprivate() but with the function string directly.
*/
FUNCTION(fun_private)
{
char *str;
GDATA *preserve;
preserve = mudstate.rdata;
mudstate.rdata = NULL;
str = fargs[0];
exec(buff, bufc, player, caller, cause,
EV_FCHECK | EV_STRIP | EV_EVAL, &str, cargs, ncargs);

Free_RegData(mudstate.rdata);
mudstate.rdata = preserve;

/* --------------------------------------------------------------------------* fun_default, fun_edefault, and fun_udefault:


* These check for the presence of an attribute. If it exists, then it
* is gotten, via the equivalent of get(), get_eval(), or u(), respectively.
* Otherwise, the default message is used.
* In the case of udefault(), the remaining arguments to the function
* are used as arguments to the u().
*/
FUNCTION(fun_default)
{
dbref thing, aowner;
int attrib, aflags, alen;
ATTR *attr;
char *objname, *atr_gotten, *bp, *str;
objname = bp = alloc_lbuf("fun_default");
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

Saturday, June 16, 2012 11:40 PM

str = fargs[0];
exec(objname, &bp, player, caller, cause,
EV_EVAL | EV_STRIP | EV_FCHECK, &str, cargs, ncargs);
/* First we check to see that the attribute exists on the object.
* If so, we grab it and use it.
*/
if (objname != NULL) {
if (parse_attrib(player, objname, &thing, &attrib, 0) &&
(attrib != NOTHING)) {
attr = atr_num(attrib);
if (attr && !(attr->flags & AF_IS_LOCK)) {
atr_gotten = atr_pget(thing, attrib,
&aowner, &aflags, &alen);
if (*atr_gotten) {
safe_known_str(atr_gotten, alen,
buff, bufc);
free_lbuf(atr_gotten);
free_lbuf(objname);
return;
}
free_lbuf(atr_gotten);
}
}
free_lbuf(objname);
}
/* If we've hit this point, we've not gotten anything useful, so we
* go and evaluate the default.
*/

str = fargs[1];
exec(buff, bufc, player, caller, cause,
EV_EVAL | EV_STRIP | EV_FCHECK, &str, cargs, ncargs);

FUNCTION(fun_edefault)
{
dbref thing, aowner;
int attrib, aflags, alen;
ATTR *attr;
char *objname, *atr_gotten, *bp, *str;
objname = bp = alloc_lbuf("fun_edefault");
str = fargs[0];
exec(objname, &bp, player, caller, cause,
EV_EVAL | EV_STRIP | EV_FCHECK, &str, cargs, ncargs);
/* First we check to see that the attribute exists on the object.
* If so, we grab it and use it.
*/
if (objname != NULL) {
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696

Saturday, June 16, 2012 11:40 PM

if (parse_attrib(player, objname, &thing, &attrib, 0) &&


(attrib != NOTHING)) {
attr = atr_num(attrib);
if (attr && !(attr->flags & AF_IS_LOCK)) {
atr_gotten = atr_pget(thing, attrib,
&aowner, &aflags, &alen);
if (*atr_gotten) {
str = atr_gotten;
exec(buff, bufc, thing, player,
player, EV_FIGNORE | EV_EVAL,
&str, (char **)NULL, 0);
free_lbuf(atr_gotten);
free_lbuf(objname);
return;
}
free_lbuf(atr_gotten);
}
}
free_lbuf(objname);

}
/* If we've hit this point, we've not gotten anything useful, so we
* go and evaluate the default.
*/

str = fargs[1];
exec(buff, bufc, player, caller, cause,
EV_EVAL | EV_STRIP | EV_FCHECK, &str, cargs, ncargs);

FUNCTION(fun_udefault)
{
dbref thing, aowner;
int aflags, alen, anum, i, j, trace_flag;
ATTR *ap;
char *objname, *atext, *str, *bp, *xargs[NUM_ENV_VARS];
if (nfargs < 2)
return;

/* must have at least two arguments */

str = fargs[0];
objname = bp = alloc_lbuf("fun_udefault");
exec(objname, &bp, player, caller, cause,
EV_EVAL | EV_STRIP | EV_FCHECK, &str, cargs, ncargs);
/* First we check to see that the attribute exists on the object.
* If so, we grab it and use it.
*/
if (objname != NULL) {
Parse_Uattr(player, objname, thing, anum, ap);
if (ap) {
atext = atr_pget(thing, ap->number, &aowner, &aflags, &alen);
if (*atext) {
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

Saturday, June 16, 2012 11:40 PM

/* Now we have a problem -- we've got to go eval


* all of those arguments to the function.
*/
for (i = 2, j = 0; j < NUM_ENV_VARS; i++, j++) {
if ((i < nfargs) && fargs[i]) {
bp = xargs[j] = alloc_lbuf("fun_udefault.args");
str = fargs[i];
exec(xargs[j], &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL,
&str, cargs, ncargs);
} else {
xargs[j] = NULL;
}
}
/* We have the args, now call the ufunction. Obey the trace
* flag on the attribute if there is one.
*/
if (!Trace(thing) && (aflags & AF_TRACE)) {
trace_flag = 1;
s_Trace(thing);
} else {
trace_flag = 0;
}
str = atext;
exec(buff, bufc, thing, player, cause, EV_FCHECK | EV_EVAL,
&str, xargs, nfargs - 2);
if (trace_flag) {
c_Trace(thing);
}
/* Then clean up after ourselves. */
for (j = 0; j < NUM_ENV_VARS; j++)
if (xargs[j])
free_lbuf(xargs[j]);
free_lbuf(atext);
free_lbuf(objname);
return;
}
free_lbuf(atext);

}
free_lbuf(objname);

}
/* If we've hit this point, we've not gotten anything useful, so we
* go and evaluate the default.
*/

-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

Saturday, June 16, 2012 11:40 PM

str = fargs[1];
exec(buff, bufc, player, caller, cause,
EV_EVAL | EV_STRIP | EV_FCHECK, &str, cargs, ncargs);

/*--------------------------------------------------------------------------* Evaluate from a specific object's perspective.


*/
FUNCTION(fun_objeval)
{
dbref obj;
char *name, *bp, *str;
if (!*fargs[0]) {
return;
}
name = bp = alloc_lbuf("fun_objeval");
str = fargs[0];
exec(name, &bp, player, caller, cause,
EV_FCHECK | EV_STRIP | EV_EVAL, &str, cargs, ncargs);
obj = match_thing(player, name);
/* In order to evaluate from something else's viewpoint, you must
* have the same owner as it, or be a wizard (unless
* objeval_requires_control is turned on, in which case you
* must control it, period). Otherwise, we default to evaluating
* from our own viewpoint. Also, you cannot evaluate things from
* the point of view of God.
*/
if (Cannot_Objeval(player, obj))
obj = player;

str = fargs[1];
exec(buff, bufc, obj, player, cause,
EV_FCHECK | EV_STRIP | EV_EVAL, &str, cargs, ncargs);
free_lbuf(name);

/* --------------------------------------------------------------------------* Matching functions.


*/
FUNCTION(fun_num)
{
safe_dbref(buff, bufc, match_thing(player, fargs[0]));
}
FUNCTION(fun_pmatch)
{
char *name, *temp, *tp;
dbref thing;
dbref *p_ptr;
-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

Saturday, June 16, 2012 11:40 PM

/* If we have a valid dbref, it's okay if it's a player. */


if ((*fargs[0] == NUMBER_TOKEN) && fargs[0][1]) {
thing = parse_dbref(fargs[0] + 1);
if (Good_obj(thing) && isPlayer(thing)) {
safe_dbref(buff, bufc, thing);
} else {
safe_nothing(buff, bufc);
}
return;
}
/* If we have *name, just advance past the *; it doesn't matter */
name = fargs[0];
if (*fargs[0] == LOOKUP_TOKEN) {
do {
name++;
} while (isspace(*name));
}
/* Look up the full name */
tp = temp = alloc_lbuf("fun_pmatch");
safe_str(name, temp, &tp);
for (tp = temp; *tp; tp++)
*tp = tolower(*tp);
p_ptr = (int *) hashfind(temp, &mudstate.player_htab);
free_lbuf(temp);
if (p_ptr) {
/* We've got it. Check to make sure it's a good object. */
if (Good_obj(*p_ptr) && isPlayer(*p_ptr)) {
safe_dbref(buff, bufc, (int) *p_ptr);
} else {
safe_nothing(buff, bufc);
}
return;
}
/* We haven't found anything. Now we try a partial match. */

thing = find_connected_ambiguous(player, name);


if (thing == AMBIGUOUS) {
safe_known_str("#-2", 3, buff, bufc);
} else if (Good_obj(thing) && isPlayer(thing)) {
safe_dbref(buff, bufc, thing);
} else {
safe_nothing(buff, bufc);
}

-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

Saturday, June 16, 2012 11:40 PM

FUNCTION(fun_pfind)
{
dbref thing;

if (*fargs[0] == '#') {
safe_dbref(buff, bufc, match_thing(player, fargs[0]));
return;
}
if (!((thing = lookup_player(player, fargs[0], 1)) == NOTHING)) {
safe_dbref(buff, bufc, thing);
return;
} else
safe_nomatch(buff, bufc);

/* --------------------------------------------------------------------------* fun_locate: Search for things with the perspective of another obj.
*/
FUNCTION(fun_locate)
{
int pref_type, check_locks, verbose, multiple;
dbref thing, what;
char *cp;
pref_type = NOTYPE;
check_locks = verbose = multiple = 0;
/* Find the thing to do the looking, make sure we control it. */
if (See_All(player))
thing = match_thing(player, fargs[0]);
else
thing = match_controlled(player, fargs[0]);
if (!Good_obj(thing)) {
safe_noperm(buff, bufc);
return;
}
/* Get pre- and post-conditions and modifiers */
for (cp = fargs[2];
switch (*cp) {
case 'E':
pref_type =
break;
case 'L':
check_locks
break;
case 'P':
pref_type =
break;
case 'R':
pref_type =

*cp; cp++) {
TYPE_EXIT;
= 1;
TYPE_PLAYER;
TYPE_ROOM;
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961

Saturday, June 16, 2012 11:40 PM

break;
case 'T':
pref_type = TYPE_THING;
break;
case 'V':
verbose = 1;
break;
case 'X':
multiple = 1;
break;
}

/* Set up for the search */


if (check_locks)
init_match_check_keys(thing, fargs[1], pref_type);
else
init_match(thing, fargs[1], pref_type);
/* Search for each requested thing */
for (cp = fargs[2]; *cp; cp++) {
switch (*cp) {
case 'a':
match_absolute();
break;
case 'c':
match_carried_exit_with_parents ();
break;
case 'e':
match_exit_with_parents();
break;
case 'h':
match_here();
break;
case 'i':
match_possession();
break;
case 'm':
match_me();
break;
case 'n':
match_neighbor();
break;
case 'p':
match_player();
break;
case '*':
match_everything(MAT_EXIT_PARENTS);
break;
}
}
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014

Saturday, June 16, 2012 11:40 PM

/* Get the result and return it to the caller */


if (multiple)
what = last_match_result();
else
what = match_result();
if (verbose)
(void)match_status(player, what);
}

safe_dbref(buff, bufc, what);

/* --------------------------------------------------------------------------* handle_lattr:
*
lattr: Return list of attributes I can see on the object.
*
nattr: Ditto, but just count 'em up.
*/
FUNCTION(handle_lattr)
{
dbref thing;
ATTR *attr;
char *bb_p;
int ca, total = 0, count_only;
Delim osep;
count_only = Is_Func(LATTR_COUNT);
if (!count_only) {
VaChk_Only_Out(2);
}
/* Check for wildcard matching. parse_attrib_wild checks for read
* permission, so we don't have to. Have p_a_w assume the
* slash-star if it is missing.
*/
olist_push();
if (parse_attrib_wild(player, fargs[0], &thing, 0, 0, 1, 1)) {
bb_p = *bufc;
for (ca = olist_first(); ca != NOTHING; ca = olist_next()) {
attr = atr_num(ca);
if (attr) {
if (count_only) {
total++;
} else {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
safe_str((char *)attr->name, buff, bufc);
}
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067

Saturday, June 16, 2012 11:40 PM

}
}
if (count_only)
safe_ltos(buff, bufc, total);
} else {
if (!mudconf.lattr_oldstyle) {
safe_nomatch(buff, bufc);
} else if (count_only) {
safe_chr('0', buff, bufc);
}
}
olist_pop();

/* --------------------------------------------------------------------------* fun_search: Search the db for things, returning a list of what matches
*/
FUNCTION(fun_search)
{
dbref thing;
char *bp, *nbuf;
SEARCH searchparm;
/* Set up for the search.

If any errors, abort. */

if (!search_setup(player, fargs[0], &searchparm)) {


safe_str("#-1 ERROR DURING SEARCH", buff, bufc);
return;
}
/* Do the search and report the results */

olist_push();
search_perform(player, cause, &searchparm);
bp = *bufc;
nbuf = alloc_sbuf("fun_search");
for (thing = olist_first(); thing != NOTHING; thing = olist_next()) {
if (bp == *bufc)
sprintf(nbuf, "#%d", thing);
else
sprintf(nbuf, " #%d", thing);
safe_str(nbuf, buff, bufc);
}
free_sbuf(nbuf);
olist_pop();

/* --------------------------------------------------------------------------* fun_stats: Get database size statistics.


*/
FUNCTION(fun_stats)
{
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120

Saturday, June 16, 2012 11:40 PM

dbref who;
STATS statinfo;

if ((!fargs[0]) || !*fargs[0] || !string_compare(fargs[0], "all")) {


who = NOTHING;
} else {
who = lookup_player(player, fargs[0], 1);
if (who == NOTHING) {
safe_str("#-1 NOT FOUND", buff, bufc);
return;
}
}
if (!get_stats(player, who, &statinfo)) {
safe_str("#-1 ERROR GETTING STATS", buff, bufc);
return;
}
safe_tprintf_str(buff, bufc, "%d %d %d %d %d %d %d %d",
statinfo.s_total, statinfo.s_rooms,
statinfo.s_exits, statinfo.s_things,
statinfo.s_players, statinfo.s_unknown,
statinfo.s_going, statinfo.s_garbage);

/* --------------------------------------------------------------------------* Memory usage.


*/
static int mem_usage(thing)
dbref thing;
{
int k;
int ca;
char *as, *str;
ATTR *attr;
k = sizeof(OBJ);

k += strlen(Name(thing)) + 1;
for (ca = atr_head(thing, &as); ca; ca = atr_next(&as)) {
str = atr_get_raw(thing, ca);
if (str && *str)
k += strlen(str);
attr = atr_num(ca);
if (attr) {
str = (char *)attr->name;
if (str && *str)
k += strlen(((ATTR *) atr_num(ca))->name);
}
}
return k;

static int mem_usage_attr(player, str)


-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173

Saturday, June 16, 2012 11:40 PM

dbref player;
char *str;
dbref thing, aowner;
int atr, aflags, alen;
char *abuf;
ATTR *ap;
int bytes_atext = 0;
abuf = alloc_lbuf("mem_usage_attr");
olist_push();
if (parse_attrib_wild(player, str, &thing, 0, 0, 1, 1)) {
for (atr = olist_first(); atr != NOTHING; atr = olist_next()) {
ap = atr_num(atr);
if (!ap)
continue;
abuf = atr_get_str(abuf, thing, atr, &aowner, &aflags, &alen);
/* Player must be able to read attribute with 'examine' */
if (Examinable(player, thing) &&
Read_attr(player, thing, ap, aowner, aflags))
bytes_atext += alen;
}
}
olist_pop();
free_lbuf(abuf);
return bytes_atext;

FUNCTION(fun_objmem)
{
dbref thing;
if (strchr(fargs[0], '/')) {
safe_ltos(buff, bufc, mem_usage_attr(player, fargs[0]));
return;
}

thing = match_thing(player, fargs[0]);


if (!Good_obj(thing) || !Examinable(player, thing)) {
safe_noperm(buff, bufc);
return;
}
safe_ltos(buff, bufc, mem_usage(thing));

FUNCTION(fun_playmem)
{
int tot = 0;
dbref thing;
dbref j;
thing = match_thing(player, fargs[0]);
if (!Good_obj(thing) || !Examinable(player, thing)) {
-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226

Saturday, June 16, 2012 11:40 PM

safe_noperm(buff, bufc);
return;

}
DO_WHOLE_DB(j)
if (Owner(j) == thing)
tot += mem_usage(j);
safe_ltos(buff, bufc, tot);

/* --------------------------------------------------------------------------* Type functions.


*/
FUNCTION(fun_type)
{
dbref it;

it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
}
switch (Typeof(it)) {
case TYPE_ROOM:
safe_known_str("ROOM", 4, buff, bufc);
break;
case TYPE_EXIT:
safe_known_str("EXIT", 4, buff, bufc);
break;
case TYPE_PLAYER:
safe_known_str("PLAYER", 6, buff, bufc);
break;
case TYPE_THING:
safe_known_str("THING", 5, buff, bufc);
break;
default:
safe_str("#-1 ILLEGAL TYPE", buff, bufc);
}
return;

FUNCTION(fun_hastype)
{
dbref it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
}
if (!fargs[1] || !*fargs[1]) {
safe_str("#-1 NO SUCH TYPE", buff, bufc);
return;
}
-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279

switch (*fargs[1]) {
case 'r':
case 'R':
safe_bool(buff, bufc,
break;
case 'e':
case 'E':
safe_bool(buff, bufc,
break;
case 'p':
case 'P':
safe_bool(buff, bufc,
break;
case 't':
case 'T':
safe_bool(buff, bufc,
break;
default:
safe_str("#-1 NO SUCH
break;
};

Saturday, June 16, 2012 11:40 PM

isRoom(it));

isExit(it));

isPlayer(it));

isThing(it));
TYPE", buff, bufc);

/* --------------------------------------------------------------------------* fun_lastcreate: Return the last object of type Y that X created.


*/
FUNCTION(fun_lastcreate)
{
int i, aowner, aflags, alen, obj_list[4], obj_type;
char *obj_str, *p, *tokst;
dbref obj = match_thing(player, fargs[0]);
if (!controls(player, obj)) {
safe_nothing(buff, bufc);
return;
}

/* Automatically checks for GoodObj */

switch (*fargs[1]) {
case 'R':
case 'r':
obj_type = 0;
break;
case 'E':
case 'e':
obj_type = 1;;
break;
case 'T':
case 't':
obj_type = 2;
break;
case 'P':
case 'p':
-43-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332

Saturday, June 16, 2012 11:40 PM

obj_type = 3;
break;
default:
notify_quiet(player, "Invalid object type.");
safe_nothing(buff, bufc);
return;
}
obj_str = atr_get(obj, A_NEWOBJS, &aowner, &aflags, &alen);
if (!*obj_str) {
free_lbuf(obj_str);
safe_nothing(buff, bufc);
return;
}
for (p = strtok_r(obj_str, " ", &tokst), i = 0;
p && (i < 4);
p = strtok_r(NULL, " ", &tokst), i++) {
obj_list[i] = atoi(p);
}
free_lbuf(obj_str);
}

safe_dbref(buff, bufc, obj_list[obj_type]);

/* --------------------------------------------------------------------------* fun_speak: Complex say-format-processing function.


*
* speak(<speaker>, <string>[, <substitute for "says,">
*
[, <transform>[, <empty>[, <open>[, <close>]]]]])
*
* <string> can be a plain string (treated like say), :<foo> (pose),
* : <foo> (pose/nospace), ;<foo> (pose/nospace), |<foo> (emit), or
* "<foo> (also treated like say).
*
* If we are given <transform>, we parse through the string, pulling out
* the things that fall between <open in> and <close in> (which default to
* double-quotes). We pass the speech between those things to the
* u-function (or everything, if a plain say string), with the speech
* as %0, <object>'s resolved dbref as %1, and the speech part number
* (plain say begins numbering at 0, others at 1) as %2.
*
* We rely on the u-function to do any necessary formatting of the
* return string, including putting quotes (or whatever) back around it
* if necessary.
*
* If the return string is null, we call <empty>, with <object>'s resolved
* dbref as %0, and the speech part number as %1.
*/
static void transform_say(speaker, sname,
str, key, say_str, trans_str, empty_str,
open_sep, close_sep,
-44-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

Saturday, June 16, 2012 11:40 PM

player, caller, cause, buff, bufc)


dbref speaker, player, caller, cause;
char *sname, *str, *say_str, *trans_str, *empty_str, *buff, **bufc;
const Delim *open_sep, *close_sep;
int key;
char *sp, *ep, *save, *tp, *bp;
char *result, *tstack[3], *estack[2], tbuf[LBUF_SIZE];
int spos, trans_len, empty_len;
int done = 0;
if (trans_str && *trans_str)
trans_len = strlen(trans_str);
else
return;
/* should never happen; caller should check */
/* Find the start of the speech string. Copy up to it. */
sp = str;
if (key == SAY_SAY) {
spos = 0;
} else {
save = split_token(&sp, open_sep);
safe_str(save, buff, bufc);
if (!sp)
return;
spos = 1;
}
tstack[1] = alloc_sbuf("transform_say.dbref1");
tstack[2] = alloc_sbuf("transform_say.pos1");
if (empty_str && *empty_str) {
empty_len = strlen(empty_str);
estack[0] = alloc_sbuf("transform_say.dbref2");
estack[1] = alloc_sbuf("transform_say.pos2");
} else {
empty_len = 0;
}
result = alloc_lbuf("transform_say.out");
while (!done) {
/* Find the end of the speech string. */
ep = sp;
sp = split_token(&ep, close_sep);
/* Pass the stuff in-between through the u-functions. */
tstack[0] = sp;
sprintf(tstack[1], "#%d", speaker);
-45-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438

Saturday, June 16, 2012 11:40 PM

sprintf(tstack[2], "%d", spos);


StrCopyKnown(tbuf, trans_str, trans_len);
tp = tbuf;
bp = result;
exec(result, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &tp, tstack, 3);
if (result && *result) {
if ((key == SAY_SAY) && (spos == 0)) {
safe_tprintf_str(buff, bufc, "%s %s %s",
sname, say_str, result);
} else {
safe_str(result, buff, bufc);
}
} else if (empty_len > 0) {
sprintf(estack[0], "#%d", speaker);
sprintf(estack[1], "%d", spos);
StrCopyKnown(tbuf, empty_str, empty_len);
tp = tbuf;
bp = result;
exec(result, &bp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &tp, estack, 2);
if (result && *result) {
safe_str(result, buff, bufc);
}
}
/* If there's more, find it and copy it. sp will point to the
* beginning of the next speech string.
*/
if (ep && *ep) {
sp = ep;
save = split_token(&sp, open_sep);
safe_str(save, buff, bufc);
if (!sp)
done = 1;
} else {
done = 1;
}
spos++;
}
free_lbuf(result);
free_sbuf(tstack[1]);
free_sbuf(tstack[2]);
if (empty_len > 0) {
free_sbuf(estack[0]);
free_sbuf(estack[1]);
}
if (trans_str)
free_lbuf(trans_str);
-46-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491

Saturday, June 16, 2012 11:40 PM

if (empty_str)
free_lbuf(empty_str);

FUNCTION(fun_speak)
{
dbref thing, obj1, obj2;
Delim isep, osep;
/* really open and close separators */
dbref aowner1, aowner2;
int aflags1, alen1, anum1, aflags2, alen2, anum2;
ATTR *ap1, *ap2;
char *atext1, *atext2, *str, *say_str, *s, *tname;
int is_transform, key;
/* Delimiter processing here is different. We have to do some
* funky stuff to make sure that a space delimiter is really an
* intended space, not delim_check() defaulting.
*/
VaChk_Range(2, 7);
VaChk_InSep(6, 0);
if ((isep.len == 1) && (isep.str[0] == ' ')) {
if ((nfargs < 6) || !fargs[5] || !*fargs[5]) {
isep.str[0] = '"';
}
}
VaChk_DefaultOut(7) {
VaChk_OutSep(7, 0);
}
/* We have three possible cases for the speaker:
*
<thing string>&<name string>
*
&<name string> (speaker defaults to player)
*
<thing string> (name string defaults to name of thing)
*/
if (*fargs[0] == '&') {
/* name only */
thing = player;
tname = fargs[0];
tname++;
} else if (((s = strchr(fargs[0], '&')) == NULL) || !*s++) {
/* thing only */
thing = match_thing(player, fargs[0]);
if (!Good_obj(thing)) {
safe_nomatch(buff, bufc);
return;
}
tname = Name(thing);
} else {
/* thing and name */
*(s-1) = '\0';
thing = match_thing(player, fargs[0]);
-47-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544

Saturday, June 16, 2012 11:40 PM

if (!Good_obj(thing)) {
safe_nomatch(buff, bufc);
return;
}
tname = s;
}
/* Must have an input string. Otherwise silent fail. */
if (!fargs[1] || !*fargs[1])
return;
/* Check if there's a string substituting for "says,". */
if ((nfargs >= 3) && fargs[2] && *fargs[2])
say_str = fargs[2];
else
say_str = (char *) (mudconf.comma_say ? "says," : "says");
/* Find the u-function. If we have a problem with it, we just default
* to no transformation.
*/
atext1 = atext2 = NULL;
is_transform = 0;
if (nfargs >= 4) {
Parse_Uattr(player, fargs[3], obj1, anum1, ap1);
if (ap1) {
atext1 = atr_pget(obj1, ap1->number,
&aowner1, &aflags1, &alen1);
if (!*atext1 || !(See_attr(player, obj1,
ap1, aowner1, aflags1))) {
free_lbuf(atext1);
atext1 = NULL;
} else {
is_transform = 1;
}
} else {
atext1 = NULL;
}
}
/* Do some up-front work on the empty-case u-function, too. */
if (nfargs >= 5) {
Parse_Uattr(player, fargs[4], obj2, anum2, ap2);
if (ap2) {
atext2 = atr_pget(obj2, ap2->number,
&aowner2, &aflags2, &alen2);
if (!*atext2 || !(See_attr(player, obj2,
ap2, aowner2, aflags2))) {
free_lbuf(atext2);
-48-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597

Saturday, June 16, 2012 11:40 PM

atext2 = NULL;
}
} else {
atext2 = NULL;
}
}
/* Take care of the easy case, no u-function. */
if (!is_transform) {
switch (*fargs[1]) {
case ':':
if (*(fargs[1] + 1) == ' ') {
safe_tprintf_str(buff, bufc, "%s%s", tname,
fargs[1] + 2);
} else {
safe_tprintf_str(buff, bufc, "%s %s", tname,
fargs[1] + 1);
}
break;
case ';':
safe_tprintf_str(buff, bufc, "%s%s", tname,
fargs[1] + 1);
break;
case '|':
safe_tprintf_str(buff, bufc, "%s", fargs[1] + 1);
break;
case '"':
safe_tprintf_str(buff, bufc, "%s %s \"%s\"",
tname, say_str, fargs[1] + 1);
break;
default:
safe_tprintf_str(buff, bufc, "%s %s \"%s\"",
tname, say_str, fargs[1]);
break;
}
return;
}
/* Now for the nasty stuff. */
switch (*fargs[1]) {
case ':':
safe_str(tname, buff, bufc);
if (*(fargs[1] + 1) != ' ') {
safe_chr(' ', buff, bufc);
str = fargs[1] + 1;
key = SAY_POSE;
} else {
str = fargs[1] + 2;
key = SAY_POSE_NOSPC;
}
break;
-49-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funobj.c

2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619

Saturday, June 16, 2012 11:40 PM

case ';':
safe_str(tname, buff, bufc);
str = fargs[1] + 1;
key = SAY_POSE_NOSPC;
break;
case '|':
str = fargs[1] + 1;
key = SAY_EMIT;
break;
case '"':
str = fargs[1] + 1;
key = SAY_SAY;
break;
default:
str = fargs[1];
key = SAY_SAY;
}

transform_say(thing, tname, str, key, say_str, atext1, atext2,


&isep, &osep, player, caller, cause, buff, bufc);

-50-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:40 PM

/* funstring.c - string functions */


/* $Id: funstring.c,v 1.65 2005/10/16 04:13:45 alierak Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "functions.h" /* required by code */
#include "powers.h" /* required by code */
#include "ansi.h"
/* required by code */
/* --------------------------------------------------------------------------* isword: is every character in the argument a letter?
*/
FUNCTION(fun_isword)
{
char *p;

for (p = fargs[0]; *p; p++) {


if (!isalpha(*p)) {
safe_chr('0', buff, bufc);
return;
}
}
safe_chr('1', buff, bufc);

/* --------------------------------------------------------------------------* isnum: is the argument a number?


*/
FUNCTION(fun_isnum)
{
safe_chr((is_number(fargs[0]) ? '1' : '0'), buff, bufc);
}
/* --------------------------------------------------------------------------* isdbref: is the argument a valid dbref?
*/
FUNCTION(fun_isdbref)
{
char *p;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:40 PM

dbref dbitem;

p = fargs[0];
if (*p++ == NUMBER_TOKEN) {
if (*p) {
/* just the string '#' won't do! */
dbitem = parse_dbref(p);
if (Good_obj(dbitem)) {
safe_chr('1', buff, bufc);
return;
}
}
}
safe_chr('0', buff, bufc);

/* --------------------------------------------------------------------------* fun_null: Just eat the contents of the string. Handy for those times
*
when you've output a bunch of junk in a function call and
*
just want to dispose of the output (like if you've done an
*
iter() that just did a bunch of side-effects, and now you have
*
bunches of spaces you need to get rid of.
*/
FUNCTION(fun_null)
{
return;
}
/* --------------------------------------------------------------------------* fun_squish: Squash occurrences of a given character down to 1.
*
We do this both on leading and trailing chars, as well as
*
internal ones; if the player wants to trim off the leading
*
and trailing as well, they can always call trim().
*/
FUNCTION(fun_squish)
{
char *tp, *bp;
Delim isep;
if (nfargs == 0) {
return;
}
VaChk_Only_InPure(2);
bp = tp = fargs[0];
while (*tp) {
/* Move over and copy the non-sep characters */
while (*tp && *tp != isep.str[0]) {
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:40 PM

if (*tp == ESC_CHAR) {
copy_esccode(tp, bp);
} else {
*bp++ = *tp++;
}

/* If we've reached the end of the string, leave the loop. */


if (!*tp)
break;
/* Otherwise, we've hit a sep char. Move over it, and then
* move on to the next non-separator. Note that we're
* overwriting our own string as we do this. However, the
* other pointer will always be ahead of our current copy
* pointer.
*/

*bp++ = *tp++;
while (*tp && (*tp == isep.str[0]))
tp++;

/* Must terminate the string */


*bp = '\0';
}

safe_str(fargs[0], buff, bufc);

/* --------------------------------------------------------------------------* trim: trim off unwanted white space.


*/
#define TRIM_L 0x1
#define TRIM_R 0x2
FUNCTION(fun_trim)
{
char *p, *q, *endchar, *ep;
Delim isep;
int trim;
if (nfargs == 0) {
return;
}
VaChk_In(1, 3);
if (nfargs >= 2) {
switch (tolower(*fargs[1])) {
case 'l':
trim = TRIM_L;
break;
case 'r':
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:40 PM

trim = TRIM_R;
break;
default:
trim = TRIM_L | TRIM_R;
break;
}
} else {
trim = TRIM_L | TRIM_R;
}
p = fargs[0];
/* Single-character delimiters are easy. */
if (isep.len == 1) {
if (trim & TRIM_L) {
while (*p == isep.str[0]) {
p++;
}
}
if (trim & TRIM_R) {
q = endchar = p;
while (*q != '\0') {
if (*q == ESC_CHAR) {
skip_esccode(q);
endchar = q;
} else if (*q++ != isep.str[0]) {
endchar = q;
}
}
*endchar = '\0';
}
safe_str(p, buff, bufc);
return;
}
/* Multi-character delimiters take more work. */
ep = p + strlen(fargs[0]) - 1; /* last char in string */
if (trim & TRIM_L) {
while (!strncmp(p, isep.str, isep.len) && (p <= ep))
p = p + isep.len;
if (p > ep)
return;
}
if (trim & TRIM_R) {
q = endchar = p;
while (q <= ep) {
if (*q == ESC_CHAR) {
skip_esccode(q);
endchar = q;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

}
}

Saturday, June 16, 2012 11:40 PM

} else if (!strncmp(q, isep.str, isep.len)) {


q = q + isep.len;
} else {
q++;
endchar = q;
}
}
*endchar = '\0';

safe_str(p, buff, bufc);

/* --------------------------------------------------------------------------* fun_after, fun_before: Return substring after or before a specified string.


*/
FUNCTION(fun_after)
{
char *bp, *cp, *mp, *np;
int ansi_needle, ansi_needle2, ansi_haystack, ansi_haystack2;
if (nfargs == 0) {
return;
}
VaChk_Range(1, 2);
bp = fargs[0]; /* haystack */
mp = fargs[1]; /* needle */
/* Sanity-check arg1 and arg2 */
if (bp == NULL)
bp = "";
if (mp == NULL)
mp = " ";
if (!mp || !*mp)
mp = (char *)" ";
if ((mp[0] == ' ') && (mp[1] == '\0'))
bp = Eat_Spaces(bp);
/* Get ansi state of the first needle char */
ansi_needle = ANST_NONE;
while (*mp == ESC_CHAR) {
track_esccode(mp, ansi_needle);
if (!*mp)
mp = (char *)" ";
}
ansi_haystack = ANST_NORMAL;
/* Look for the needle string */
while (*bp) {
while (*bp == ESC_CHAR) {
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

Saturday, June 16, 2012 11:40 PM

track_esccode(bp, ansi_haystack);

if ((*bp == *mp) &&


(ansi_needle == ANST_NONE ||
ansi_haystack == ansi_needle)) {
/* See if what follows is what we are looking for */
ansi_needle2 = ansi_needle;
ansi_haystack2 = ansi_haystack;
cp = bp;
np = mp;
while (1) {
while (*cp == ESC_CHAR) {
track_esccode(cp, ansi_haystack2);
}
while (*np == ESC_CHAR) {
track_esccode(np, ansi_needle2);
}
if ((*cp != *np) ||
(ansi_needle2 != ANST_NONE &&
ansi_haystack2 != ansi_needle2) ||
!*cp || !*np)
break;
++cp, ++np;
}

if (!*np) {
/* Yup, return what follows */
safe_str(ansi_transition_esccode(ANST_NORMAL, ansi_haystack2), buff,
bufc);
safe_str(cp, buff, bufc);
return;
}

/* Nope, continue searching */


if (*bp)
++bp;

/* Ran off the end without finding it */


return;

FUNCTION(fun_before)
{
char *haystack, *bp, *cp, *mp, *np;
int ansi_needle, ansi_needle2, ansi_haystack, ansi_haystack2;
if (nfargs == 0) {
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

Saturday, June 16, 2012 11:40 PM

return;
}
VaChk_Range(1, 2);
haystack = fargs[0];
/* haystack */
mp = fargs[1];
/* needle */
/* Sanity-check arg1 and arg2 */
if (haystack == NULL)
haystack = "";
if (mp == NULL)
mp = " ";
if (!mp || !*mp)
mp = (char *)" ";
if ((mp[0] == ' ') && (mp[1] == '\0'))
haystack = Eat_Spaces(haystack);
bp = haystack;
/* Get ansi state of the first needle char */
ansi_needle = ANST_NONE;
while (*mp == ESC_CHAR) {
track_esccode(mp, ansi_needle);
if (!*mp)
mp = (char *)" ";
}
ansi_haystack = ANST_NORMAL;
/* Look for the needle string */
while (*bp) {
/* See if what follows is what we are looking for */
ansi_needle2 = ansi_needle;
ansi_haystack2 = ansi_haystack;
cp = bp;
np = mp;
while (1) {
while (*cp == ESC_CHAR) {
track_esccode(cp, ansi_haystack2);
}
while (*np == ESC_CHAR) {
track_esccode(np, ansi_needle2);
}
if ((*cp != *np) ||
(ansi_needle2 != ANST_NONE &&
ansi_haystack2 != ansi_needle2) ||
!*cp || !*np)
break;
++cp, ++np;
}
if (!*np) {
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

Saturday, June 16, 2012 11:40 PM

/* Yup, return what came before this */


*bp = '\0';
safe_str(haystack, buff, bufc);
safe_str(ansi_transition_esccode(ansi_haystack, ANST_NORMAL), buff, bufc);
return;

/* Nope, continue searching */


while (*bp == ESC_CHAR) {
track_esccode(bp, ansi_haystack);
}

if (*bp)
++bp;

/* Ran off the end without finding it */


safe_str(haystack, buff, bufc);
return;

/* --------------------------------------------------------------------------* fun_lcstr, fun_ucstr, fun_capstr: Lowercase, uppercase, or capitalize str.


*/
FUNCTION(fun_lcstr)
{
char *ap;
ap = *bufc;
safe_str(fargs[0], buff, bufc);

while (*ap) {
if (*ap == ESC_CHAR) {
skip_esccode(ap);
} else {
*ap = tolower(*ap);
ap++;
}
}

FUNCTION(fun_ucstr)
{
char *ap;
ap = *bufc;
safe_str(fargs[0], buff, bufc);
while (*ap) {
if (*ap == ESC_CHAR) {
skip_esccode(ap);
} else {
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

Saturday, June 16, 2012 11:40 PM

*ap = toupper(*ap);
ap++;

FUNCTION(fun_capstr)
{
char *ap;
ap = *bufc;
safe_str(fargs[0], buff, bufc);
while (*ap == ESC_CHAR) {
skip_esccode(ap);
}
}

*ap = toupper(*ap);

/* --------------------------------------------------------------------------* fun_space: Make spaces.


*/
FUNCTION(fun_space)
{
int num, max;
if (!fargs[0] || !(*fargs[0])) {
num = 1;
} else {
num = atoi(fargs[0]);
}
if (num < 1) {
/* If negative or zero spaces return a single space,
* -except- allow 'space(0)' to return "" for calculated
* padding
*/

if (!is_integer(fargs[0]) || (num != 0)) {


num = 1;
}

max = LBUF_SIZE - 1 - (*bufc - buff);


num = (num > max) ? max : num;
memset(*bufc, ' ', num);
*bufc += num;
**bufc = '\0';

/* ---------------------------------------------------------------------------9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

Saturday, June 16, 2012 11:40 PM

* rjust, ljust, center: Justify or center text, specifying fill character


*/
FUNCTION(fun_ljust)
{
int spaces, max, i, slen;
char *tp, *fillchars;
VaChk_Range(2, 3);
spaces = atoi(fargs[1]) - strip_ansi_len(fargs[0]);
safe_str(fargs[0], buff, bufc);
/* Sanitize number of spaces */
if (spaces <= 0)
return; /* no padding needed, just return string */
tp = *bufc;
max = LBUF_SIZE - 1 - (tp - buff); /* chars left in buffer */
spaces = (spaces > max) ? max : spaces;
if (fargs[2]) {
fillchars = strip_ansi(fargs[2]);
slen = strlen(fillchars);
slen = (slen > spaces) ? spaces : slen;
if (slen == 0) {
/* NULL character fill */
memset(tp, ' ', spaces);
tp += spaces;
}
else if (slen == 1) {
/* single character fill */
memset(tp, *fillchars, spaces);
tp += spaces;
}
else {
/* multi character fill */
for (i = spaces; i >= slen; i -= slen) {
memcpy(tp, fillchars, slen);
tp += slen;
}
if (i) {
/* we have a remainder here */
memcpy(tp, fillchars, i);
tp += i;
}
}
}
else {
/* no fill character specified */
memset(tp, ' ', spaces);
tp += spaces;
}
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582

Saturday, June 16, 2012 11:40 PM

*tp = '\0';
*bufc = tp;

FUNCTION(fun_rjust)
{
int spaces, max, i, slen;
char *tp, *fillchars;
VaChk_Range(2, 3);
spaces = atoi(fargs[1]) - strip_ansi_len(fargs[0]);
/* Sanitize number of spaces */
if (spaces <= 0) {
/* no padding needed, just return string */
safe_str(fargs[0], buff, bufc);
return;
}
tp = *bufc;
max = LBUF_SIZE - 1 - (tp - buff); /* chars left in buffer */
spaces = (spaces > max) ? max : spaces;
if (fargs[2]) {
fillchars = strip_ansi(fargs[2]);
slen = strlen(fillchars);
slen = (slen > spaces) ? spaces : slen;
if (slen == 0) {
/* NULL character fill */
memset(tp, ' ', spaces);
tp += spaces;
}
else if (slen == 1) {
/* single character fill */
memset(tp, *fillchars, spaces);
tp += spaces;
}
else {
/* multi character fill */
for (i = spaces; i >= slen; i -= slen) {
memcpy(tp, fillchars, slen);
tp += slen;
}
if (i) {
/* we have a remainder here */
memcpy(tp, fillchars, i);
tp += i;
}
}
}
else {
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

Saturday, June 16, 2012 11:40 PM

/* no fill character specified */


memset(tp, ' ', spaces);
tp += spaces;

*bufc = tp;
safe_str(fargs[0], buff, bufc);

FUNCTION(fun_center)
{
char *tp, *fillchars;
int len, lead_chrs, trail_chrs, width, max, i, slen;
VaChk_Range(2, 3);
width = atoi(fargs[1]);
len = strip_ansi_len(fargs[0]);
width = (width > LBUF_SIZE - 1) ? LBUF_SIZE - 1 : width;
if (len >= width) {
safe_str(fargs[0], buff, bufc);
return;
}
lead_chrs = (int)((width / 2) - (len / 2) + .5);
tp = *bufc;
max = LBUF_SIZE - 1 - (tp - buff); /* chars left in buffer */
lead_chrs = (lead_chrs > max) ? max : lead_chrs;
if (fargs[2]) {
fillchars = (char *)strip_ansi(fargs[2]);
slen = strlen(fillchars);
slen = (slen > lead_chrs) ? lead_chrs : slen;
if (slen == 0) {
/* NULL character fill */
memset(tp, ' ', lead_chrs);
tp += lead_chrs;
}
else if (slen == 1) {
/* single character fill */
memset(tp, *fillchars, lead_chrs);
tp += lead_chrs;
}
else {
/* multi character fill */
for (i = lead_chrs; i >= slen; i -= slen) {
memcpy(tp, fillchars, slen);
tp += slen;
}
if (i) {
/* we have a remainder here */
memcpy(tp, fillchars, i);
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

Saturday, June 16, 2012 11:40 PM

tp += i;

}
else {
/* no fill character specified */
memset(tp, ' ', lead_chrs);
tp += lead_chrs;
}
*bufc = tp;
safe_str(fargs[0], buff, bufc);
trail_chrs = width - lead_chrs - len;
tp = *bufc;
max = LBUF_SIZE - 1 - (tp - buff);
trail_chrs = (trail_chrs > max) ? max : trail_chrs;
if (fargs[2]) {
if (slen == 0) {
/* NULL character fill */
memset(tp, ' ', trail_chrs);
tp += trail_chrs;
}
else if (slen == 1) {
/* single character fill */
memset(tp, *fillchars, trail_chrs);
tp += trail_chrs;
}
else {
/* multi character fill */
for (i = trail_chrs; i >= slen; i -= slen) {
memcpy(tp, fillchars, slen);
tp += slen;
}
if (i) {
/* we have a remainder here */
memcpy(tp, fillchars, i);
tp += i;
}
}
}
else {
/* no fill character specified */
memset(tp, ' ', trail_chrs);
tp += trail_chrs;
}

*tp = '\0';
*bufc = tp;

-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741

Saturday, June 16, 2012 11:40 PM

/* --------------------------------------------------------------------------* fun_left: Returns first n characters in a string


* fun_right: Returns last n characters in a string
* strtrunc: now an alias for left
*/
FUNCTION(fun_left)
{
char *s;
int count, nchars;
int ansi_state = ANST_NORMAL;
s = fargs[0];
nchars = atoi(fargs[1]);
if (nchars <= 0)
return;
for (count = 0; (count < nchars) && *s; count++) {
while (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
}
if (*s) {
++s;
}
}

safe_known_str(fargs[0], s - fargs[0], buff, bufc);


safe_str(ansi_transition_esccode(ansi_state, ANST_NORMAL), buff, bufc);

FUNCTION(fun_right)
{
char *s;
int count, start, nchars;
int ansi_state = ANST_NORMAL;
s = fargs[0];
nchars = atoi(fargs[1]);
start = strip_ansi_len(s) - nchars;
if (nchars <= 0)
return;
if (start < 0) {
nchars += start;
if (nchars <= 0)
return;
start = 0;
}
while (*s == ESC_CHAR) {
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794

Saturday, June 16, 2012 11:40 PM

track_esccode(s, ansi_state);
}
for (count = 0; (count < start) && *s; count++) {
++s;
while (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
}
}
if (*s) {
safe_str(ansi_transition_esccode(ANST_NORMAL, ansi_state), buff, bufc);
}
}

safe_str(s, buff, bufc);

/* --------------------------------------------------------------------------* fun_chomp: If the line ends with CRLF, CR, or LF, chop it off.
*/
FUNCTION(fun_chomp)
{
char *bb_p = *bufc;

safe_str(fargs[0], buff, bufc);


if (*bufc != bb_p && (*bufc)[-1] == '\n')
(*bufc)--;
if (*bufc != bb_p && (*bufc)[-1] == '\r')
(*bufc)--;

/* --------------------------------------------------------------------------* fun_comp: exact-string compare.


* fun_streq: non-case-sensitive string compare.
* fun_strmatch: wildcard string compare.
*/
FUNCTION(fun_comp)
{
int x;

x = strcmp(fargs[0], fargs[1]);
if (x > 0) {
safe_chr('1', buff, bufc);
} else if (x < 0) {
safe_str("-1", buff, bufc);
} else {
safe_chr('0', buff, bufc);
}

-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

Saturday, June 16, 2012 11:40 PM

FUNCTION(fun_streq)
{
safe_bool(buff, bufc, !string_compare(fargs[0], fargs[1]));
}
FUNCTION(fun_strmatch)
{
/* Check if we match the whole string.
}

If so, return 1 */

safe_bool(buff, bufc, quick_wild(fargs[1], fargs[0]));

/* --------------------------------------------------------------------------* fun_edit: Edit text.


*/
FUNCTION(fun_edit)
{
char *tstr;

edit_string(fargs[0], &tstr, fargs[1], fargs[2]);


safe_str(tstr, buff, bufc);
free_lbuf(tstr);

/* --------------------------------------------------------------------------* fun_merge: given two strings and a character, merge the two strings
*
by replacing characters in string1 that are the same as the given
*
character by the corresponding character in string2 (by position).
*
The strings must be of the same length.
*/
FUNCTION(fun_merge)
{
char *str, *rep;
char c;
/* do length checks first */
if (strlen(fargs[0]) != strlen(fargs[1])) {
safe_str("#-1 STRING LENGTHS MUST BE EQUAL" , buff, bufc);
return;
}
if (strlen(fargs[2]) > 1) {
safe_str("#-1 TOO MANY CHARACTERS", buff, bufc);
return;
}
/* find the character to look for. null character is considered a
* space
*/
if (!*fargs[2])
c = ' ';
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900

else

Saturday, June 16, 2012 11:40 PM

c = *fargs[2];

/* walk strings, copy from the appropriate string */


for (str = fargs[0], rep = fargs[1];
*str && *rep && ((*bufc - buff) < (LBUF_SIZE - 1));
str++, rep++, (*bufc)++) {
if (*str == c)
**bufc = *rep;
else
**bufc = *str;
}
}

return;

/* --------------------------------------------------------------------------* fun_secure, fun_escape: escape [, ], %, \, and the beginning of the string.


*/
FUNCTION(fun_secure)
{
char *s;

s = fargs[0];
while (*s) {
switch (*s) {
case ESC_CHAR:
safe_copy_esccode(s, buff, bufc);
continue;
case '%':
case '$':
case '\\':
case '[':
case ']':
case '(':
case ')':
case '{':
case '}':
case ',':
case ';':
safe_chr(' ', buff, bufc);
break;
default:
safe_chr(*s, buff, bufc);
}
++s;
}

FUNCTION(fun_escape)
{
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953

Saturday, June 16, 2012 11:40 PM

char *s, *d;


s = fargs[0];
if (!*s)
return;
safe_chr('\\', buff, bufc);
d = *bufc;

while (*s) {
switch (*s) {
case ESC_CHAR:
safe_copy_esccode(s, buff, bufc);
continue;
case '%':
case '\\':
case '[':
case ']':
case '{':
case '}':
case ';':
if (*bufc != d)
safe_chr('\\', buff, bufc);
/* FALLTHRU */
default:
safe_chr(*s, buff, bufc);
}
++s;
}

/* --------------------------------------------------------------------------* ANSI handlers.


*/
FUNCTION(fun_ansi)
{
char *s;
int ansi_state;
if (!mudconf.ansi_colors) {
safe_str(fargs[1], buff, bufc);
return;
}
if (!fargs[0] || !*fargs[0]) {
safe_str(fargs[1], buff, bufc);
return;
}
track_ansi_letters(s, fargs[0], ansi_state);
safe_str(ansi_transition_esccode(ANST_NONE, ansi_state), buff, bufc);
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006

Saturday, June 16, 2012 11:40 PM

s = fargs[1];
while (*s) {
if (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
} else {
++s;
}
}
safe_str(fargs[1], buff, bufc);
}

safe_str(ansi_transition_esccode(ansi_state, ANST_NONE), buff, bufc);

FUNCTION(fun_stripansi)
{
safe_str((char *)strip_ansi(fargs[0]), buff, bufc);
}
/*--------------------------------------------------------------------------* encrypt() and decrypt(): From DarkZone.
*/
/*
* Copy
*/
#define
#define
#define

over only alphanumeric chars


CRYPTCODE_LO
32
CRYPTCODE_HI 126
CRYPTCODE_MOD 95

/* space */
/* tilde */
/* count of printable ascii chars */

static void crunch_code(code)


char *code;
{
char *in, *out;

in = out = code;
while (*in) {
if ((*in >= CRYPTCODE_LO) && (*in <= CRYPTCODE_HI)) {
*out++ = *in++;
} else if (*in == ESC_CHAR) {
skip_esccode(in);
} else {
++in;
}
}
*out = '\0';

static void crypt_code(buff, bufc, code, text, type)


char *buff, **bufc, *code, *text;
int type;
{
char *p, *q;
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:40 PM

if (!*text)
return;
crunch_code(code);
if (!*code) {
safe_str(text, buff, bufc);
return;
}
q = code;
p = *bufc;
safe_str(text, buff, bufc);
/*
* Encryption: Simply go through each character of the text, get its
* ascii value, subtract LO, add the ascii value (less
* LO) of the code, mod the result, add LO. Continue
*/
while (*p) {
if ((*p >= CRYPTCODE_LO) && (*p <= CRYPTCODE_HI)) {
if (type) {
*p = (((*p - CRYPTCODE_LO) + (*q - CRYPTCODE_LO)) % CRYPTCODE_MOD) +
CRYPTCODE_LO;
} else {
*p = (((*p - *q) + 2 * CRYPTCODE_MOD) % CRYPTCODE_MOD) + CRYPTCODE_LO;
}
++p, ++q;

if (!*q) {
q = code;
}
} else if (*p == ESC_CHAR) {
skip_esccode(p);
} else {
++p;
}

FUNCTION(fun_encrypt)
{
crypt_code(buff, bufc, fargs[1], fargs[0], 1);
}
FUNCTION(fun_decrypt)
{
crypt_code(buff, bufc, fargs[1], fargs[0], 0);
}
/* --------------------------------------------------------------------------* fun_scramble: randomizes the letters in a string.
*/
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

Saturday, June 16, 2012 11:40 PM

/* Borrowed from PennMUSH 1.50 */


FUNCTION(fun_scramble)
{
int n, i, j, ansi_state, *ansi_map;
char *stripped;
if (!fargs[0] || !*fargs[0]) {
return;
}
n = ansi_map_states(fargs[0], &ansi_map, &stripped);
ansi_state = ANST_NORMAL;
for (i = 0; i < n; i++) {
j = random_range(i, n - 1);
if (ansi_state != ansi_map[j]) {
safe_str(ansi_transition_esccode(ansi_state,
ansi_map[j]),
buff, bufc);
ansi_state = ansi_map[j];
}

safe_chr(stripped[j], buff, bufc);


ansi_map[j] = ansi_map[i];
stripped[j] = stripped[i];

safe_str(ansi_transition_esccode(ansi_state, ANST_NORMAL),
buff, bufc);

/* --------------------------------------------------------------------------* fun_reverse: reverse a string


*/
FUNCTION(fun_reverse)
{
int n, *ansi_map, ansi_state;
char *stripped;
if (!fargs[0] || !*fargs[0]) {
return;
}
n = ansi_map_states(fargs[0], &ansi_map, &stripped);
ansi_state = ansi_map[n];
while (n--) {
if (ansi_state != ansi_map[n]) {
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

Saturday, June 16, 2012 11:40 PM

safe_str(ansi_transition_esccode(ansi_state,
ansi_map[n]),
buff, bufc);
ansi_state = ansi_map[n];

}
safe_chr(stripped[n], buff, bufc);

safe_str(ansi_transition_esccode(ansi_state, ANST_NORMAL),
buff, bufc);

/* --------------------------------------------------------------------------* fun_mid: mid(foobar,2,3) returns oba


*/
FUNCTION(fun_mid)
{
char *s, *savep;
int count, start, nchars;
int ansi_state = ANST_NORMAL;
s = fargs[0];
start = atoi(fargs[1]);
nchars = atoi(fargs[2]);
if (nchars <= 0)
return;
if (start < 0) {
nchars += start;
if (nchars <= 0)
return;
start = 0;
}
while (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
}
for (count = 0; (count < start) && *s; ++count) {
++s;
while (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
}
}
if (*s) {
safe_str(ansi_transition_esccode(ANST_NORMAL, ansi_state), buff, bufc);
}
savep = s;
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

Saturday, June 16, 2012 11:40 PM

for (count = 0; (count < nchars) && *s; ++count) {


while (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
}
if (*s) {
++s;
}
}
safe_known_str(savep, s - savep, buff, bufc);
}

safe_str(ansi_transition_esccode(ansi_state, ANST_NORMAL), buff, bufc);

/* --------------------------------------------------------------------------* fun_translate: Takes a string and a second argument. If the second argument
* is 0 or s, control characters are converted to spaces. If it's 1 or p,
* they're converted to percent substitutions.
*/
FUNCTION(fun_translate)
{
VaChk_Range(1, 2);
/* Strictly speaking, we're just checking the first char */

if (nfargs > 1 && (fargs[1][0] == 's' || fargs[1][0] == '0'))


safe_str(translate_string(fargs[0], 0), buff, bufc);
else if (nfargs > 1 && fargs[1][0] == 'p')
safe_str(translate_string(fargs[0], 1), buff, bufc);
else
safe_str(translate_string(fargs[0], 1), buff, bufc);

/* --------------------------------------------------------------------------* fun_pos: Find a word in a string


*/
FUNCTION(fun_pos)
{
int i = 1;
char *b, *s, *t, *u;
char tbuf[LBUF_SIZE];
i = 1;
strcpy(tbuf, strip_ansi(fargs[0])); /* copy from static buff */
b = tbuf;
s = strip_ansi(fargs[1]);
if (*b && !*(b+1)) {
t = strchr(s, *b);
if (t) {

/* single character */

-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

Saturday, June 16, 2012 11:40 PM

safe_ltos(buff, bufc, (int) (t - s + 1));


} else {
safe_nothing(buff, bufc);
}
return;

while (*s) {
u = s;
t = b;
while (*t && *t == *u)
++t, ++u;
if (*t == '\0') {
safe_ltos(buff, bufc, i);
return;
}
++i, ++s;
}
safe_nothing(buff, bufc);
return;

/* --------------------------------------------------------------------------* fun_lpos: Find all occurrences of a character in a string, and return


* a space-separated list of the positions, starting at 0. i.e.,
* lpos(a-bc-def-g,-) ==> 1 4 8
*/
FUNCTION(fun_lpos)
{
char *s, *bb_p, *scratch_chartab;
int i;
Delim osep;
if (!fargs[0] || !*fargs[0])
return;
VaChk_Only_Out(3);
scratch_chartab = (char *) XCALLOC(256, sizeof(char), "lpos.chartab");
if (!fargs[1] || !*fargs[1]) {
scratch_chartab[(unsigned char) ' '] = 1;
} else {
for (s = fargs[1]; *s; s++)
scratch_chartab[(unsigned char) *s] = 1;
}
bb_p = *bufc;
for (i = 0, s = strip_ansi(fargs[0]); *s; i++, s++) {
if (scratch_chartab[(unsigned char) *s]) {
if (*bufc != bb_p) {
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

}
}
}

Saturday, June 16, 2012 11:40 PM

print_sep(&osep, buff, bufc);


}
safe_ltos(buff, bufc, i);

XFREE(scratch_chartab, "lpos.chartab");

/* --------------------------------------------------------------------------* Take a character position and return which word that char is in.
* wordpos(<string>, <charpos>)
*/
FUNCTION(fun_wordpos)
{
int charpos, i;
char *cp, *tp, *xp;
Delim isep;
VaChk_Only_In(3);

charpos = atoi(fargs[1]);
cp = strip_ansi(fargs[0]);
if ((charpos > 0) && (charpos <= (int)strlen(cp))) {
tp = &(cp[charpos - 1]);
cp = trim_space_sep(cp, &isep);
xp = split_token(&cp, &isep);
for (i = 1; xp; i++) {
if (tp < (xp + strlen(xp)))
break;
xp = split_token(&cp, &isep);
}
safe_ltos(buff, bufc, i);
return;
}
safe_nothing(buff, bufc);
return;

/* --------------------------------------------------------------------------* Take a character position and return what color that character would be.
* ansipos(<string>, <charpos>[, <type>])
*/
FUNCTION(fun_ansipos)
{
int charpos, i, ansi_state;
char *s;
VaChk_Range(2, 3);
s = fargs[0];
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376

Saturday, June 16, 2012 11:40 PM

charpos = atoi(fargs[1]);
ansi_state = ANST_NORMAL;
i = 0;
while (*s && i < charpos) {
if (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
} else {
++s, ++i;
}
}

if (nfargs > 2 && (fargs[2][0] == 'e' || fargs[2][0] == '0'))


safe_str(ansi_transition_esccode(ANST_NONE, ansi_state),
buff, bufc);
else if (nfargs > 2 && (fargs[2][0] == 'p' || fargs[2][0] == '1'))
safe_str(ansi_transition_mushcode(ANST_NONE, ansi_state),
buff, bufc);
else
safe_str(ansi_transition_letters(ANST_NONE, ansi_state),
buff, bufc);

/* --------------------------------------------------------------------------* fun_repeat: repeats a string


*/
FUNCTION(fun_repeat)
{
int times, len, i, maxtimes;
times = atoi(fargs[1]);
if ((times < 1) || (fargs[0] == NULL) || (!*fargs[0])) {
return;
} else if (times == 1) {
safe_str(fargs[0], buff, bufc);
} else {
len = strlen(fargs[0]);
maxtimes = (LBUF_SIZE - 1 - (*bufc - buff)) / len;
maxtimes = (times > maxtimes) ? maxtimes : times;

for (i = 0; i < maxtimes; i++) {


memcpy(*bufc, fargs[0], len);
*bufc += len;
}
if (times > maxtimes) {
safe_known_str(fargs[0], len, buff, bufc);
}
}

/* --------------------------------------------------------------------------* perform_border: Turn a string of words into a bordered paragraph:


-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

Saturday, June 16, 2012 11:40 PM

* BORDER, CBORDER, RBORDER


* border(<words>,<width without margins>[,<L margin fill>[,<R margin fill>]])
*/
FUNCTION(perform_border)
{
int width, just;
char *l_fill, *r_fill, *bb_p;
char *sl, *el, *sw, *ew;
int sl_ansi_state, el_ansi_state, sw_ansi_state, ew_ansi_state;
int sl_pos, el_pos, sw_pos, ew_pos;
int nleft, max, lead_chrs;
just = Func_Mask(JUST_TYPE);
VaChk_Range(2, 4);
if (!fargs[0] || !*fargs[0])
return;
width = atoi(fargs[1]);
if (width < 1)
width = 1;
if (nfargs > 2) {
l_fill = fargs[2];
} else {
l_fill = NULL;
}
if (nfargs > 3) {
r_fill = fargs[3];
} else {
r_fill = NULL;
}
bb_p = *bufc;
sl = el = sw = NULL;
ew = fargs[0];
sl_ansi_state = el_ansi_state = ANST_NORMAL;
sw_ansi_state = ew_ansi_state = ANST_NORMAL;
sl_pos = el_pos = sw_pos = ew_pos = 0;
while (1) {
/* Locate the next start-of-word (SW) */
for (sw = ew, sw_ansi_state = ew_ansi_state, sw_pos = ew_pos;
*sw; ++sw) {
switch(*sw) {
case ESC_CHAR:
track_esccode(sw, sw_ansi_state);
--sw;
continue;
case '\t':
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482

Saturday, June 16, 2012 11:40 PM

case '\r':
*sw = ' ';
/* FALLTHRU */
case ' ':
++sw_pos;
continue;
case BEEP_CHAR:
continue;
default:
break;
}
break;
}
/* Three ways out of that loop: end-of-string (ES), end-of-line (EL),
* and start-of-word (SW)
*/
if (!*sw && sl == NULL) /* ES, and nothing left to output */
break;
/* Decide where start-of-line (SL) was */
if (sl == NULL) {
if (ew == fargs[0] || ew[-1] == '\n') {
/* Preserve indentation at SS or after explicit EL */
sl = ew;
sl_ansi_state = ew_ansi_state;
sl_pos = ew_pos;
} else {
/* Discard whitespace if previous line wrapped */
sl = sw;
sl_ansi_state = sw_ansi_state;
sl_pos = sw_pos;
}
}
if (*sw == '\n') { /* EL, so we have to output */
ew = sw;
ew_ansi_state = sw_ansi_state;
ew_pos = sw_pos;
} else {
/* Locate the next end-of-word (EW) */
for (ew = sw, ew_ansi_state = sw_ansi_state, ew_pos = sw_pos;
*ew; ++ew) {
switch(*ew) {
case ESC_CHAR:
track_esccode(ew, ew_ansi_state);
--ew;
continue;
case '\r':
case '\t':
*ew = ' ';
/* FALLTHRU */
case ' ':
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535

Saturday, June 16, 2012 11:40 PM

case '\n':
break;
case BEEP_CHAR:
continue;
default:
/* Break up long words */
if (ew_pos - sw_pos == width)
break;
++ew_pos;
continue;
}
break;

/* Three ways out of that loop: ES, EL, EW */


/* If it fits on the line, add it */
if (ew_pos - sl_pos <= width) {
el = ew;
el_ansi_state = ew_ansi_state;
el_pos = ew_pos;
}
/* If it's just EW, not ES or EL, and the line isn't too long,
* keep adding words to the line
*/
if (*ew && *ew != '\n' && (ew_pos - sl_pos <= width))
continue;
/* So now we definitely need to output a line */
}
/* Could be a blank line, no words fit */
if (el == NULL) {
el = sw;
el_ansi_state = sw_ansi_state;
el_pos = sw_pos;
}
/* Newline if this isn't the first line */
if (*bufc != bb_p) {
safe_crlf(buff, bufc);
}
/* Left border text */
safe_str(l_fill, buff, bufc);
/* Left space padding if needed */
if (just == JUST_RIGHT) {
nleft = width - el_pos + sl_pos;
print_padding(nleft, max, ' ');
} else if (just == JUST_CENTER) {
lead_chrs = (int)((width / 2) - ((el_pos - sl_pos) / 2) + .5);
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

Saturday, June 16, 2012 11:40 PM

print_padding(lead_chrs, max, ' ');


}
/* Restore previous ansi state */
safe_str(ansi_transition_esccode(ANST_NORMAL, sl_ansi_state),
buff, bufc);
/* Print the words */
safe_known_str(sl, el - sl, buff, bufc);
/* Back to ansi normal */
safe_str(ansi_transition_esccode(el_ansi_state, ANST_NORMAL),
buff, bufc);
/* Right space padding if needed */
if (just == JUST_LEFT) {
nleft = width - el_pos + sl_pos;
print_padding(nleft, max, ' ');
} else if (just == JUST_CENTER) {
nleft = width - lead_chrs - el_pos + sl_pos;
print_padding(nleft, max, ' ');
}
/* Right border text */
safe_str(r_fill, buff, bufc);

/* Update pointers for the next line */


if (!*el) {
/* ES, and nothing left to output */
break;
} else if (*ew == '\n' && sw == ew) {
/* EL already handled on this line, and no new word yet */
++ew;
sl = el = NULL;
} else if (sl == sw) {
/* No new word yet */
sl = el = NULL;
} else {
/* ES with more to output, EL for next line, or just a full line */
sl = sw;
sl_ansi_state = sw_ansi_state;
sl_pos = sw_pos;
el = ew;
el_ansi_state = ew_ansi_state;
el_pos = ew_pos;
}
}

/* --------------------------------------------------------------------------* Misc functions.


*/

-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641

Saturday, June 16, 2012 11:40 PM

FUNCTION(fun_cat)
{
int i;

safe_str(fargs[0], buff, bufc);


for (i = 1; i < nfargs; i++) {
safe_chr(' ', buff, bufc);
safe_str(fargs[i], buff, bufc);
}

FUNCTION(fun_strcat)
{
int i;

safe_str(fargs[0], buff, bufc);


for (i = 1; i < nfargs; i++) {
safe_str(fargs[i], buff, bufc);
}

FUNCTION(fun_strlen)
{
safe_ltos(buff, bufc, strip_ansi_len(fargs[0]));
}
FUNCTION(fun_delete)
{
char *s, *savep;
int count, start, nchars;
int ansi_state_l = ANST_NORMAL;
int ansi_state_r = ANST_NORMAL;
s = fargs[0];
start = atoi(fargs[1]);
nchars = atoi(fargs[2]);
if ((nchars <= 0) || (start + nchars <= 0)) {
safe_str(s, buff, bufc);
return;
}
savep = s;
for (count = 0; (count < start) && *s; ++count) {
while (*s == ESC_CHAR) {
track_esccode(s, ansi_state_l);
}
if (*s) {
++s;
}
}

-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694

Saturday, June 16, 2012 11:40 PM

safe_known_str(savep, s - savep, buff, bufc);


ansi_state_r = ansi_state_l;
while (*s == ESC_CHAR) {
track_esccode(s, ansi_state_r);
}
for ( ; (count < start + nchars) && *s; ++count) {
++s;
while (*s == ESC_CHAR) {
track_esccode(s, ansi_state_r);
}
}

if (*s) {
safe_str(ansi_transition_esccode(ansi_state_l, ansi_state_r),
buff, bufc);
safe_str(s, buff, bufc);
} else {
safe_str(ansi_transition_esccode(ansi_state_l, ANST_NORMAL),
buff, bufc);
}

/* --------------------------------------------------------------------------* Misc PennMUSH-derived functions.


*/
FUNCTION(fun_lit)
{
/* Just returns the argument, literally */
safe_str(fargs[0], buff, bufc);
}
FUNCTION(fun_art)
{
/* checks a word and returns the appropriate article, "a" or "an" */
char *s = fargs[0];
char c;
while (*s && (isspace(*s) || iscntrl(*s))) {
if (*s == ESC_CHAR) {
skip_esccode(s);
} else {
++s;
}
}
c = tolower(*s);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
safe_known_str("an", 2, buff, bufc);
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747

Saturday, June 16, 2012 11:40 PM

} else {
safe_chr('a', buff, bufc);
}

FUNCTION(fun_alphamax)
{
char *amax;
int i = 1;
if (!fargs[0]) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
} else
amax = fargs[0];
while ((i < nfargs) && fargs[i]) {
amax = (strcmp(amax, fargs[i]) > 0) ? amax : fargs[i];
i++;
}
}

safe_str(amax, buff, bufc);

FUNCTION(fun_alphamin)
{
char *amin;
int i = 1;
if (!fargs[0]) {
safe_str("#-1 TOO FEW ARGUMENTS", buff, bufc);
return;
} else
amin = fargs[0];
while ((i < nfargs) && fargs[i]) {
amin = (strcmp(amin, fargs[i]) < 0) ? amin : fargs[i];
i++;
}
}

safe_str(amin, buff, bufc);

FUNCTION(fun_valid)
{
/* Checks to see if a given <something> is valid as a parameter of a
* given type (such as an object name).
*/
if (!fargs[0] || !*fargs[0] || !fargs[1] || !*fargs[1]) {
safe_chr('0', buff, bufc);
} else if (!strcasecmp(fargs[0], "name")) {
safe_bool(buff, bufc, ok_name(fargs[1]));
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funstring.c

1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762

Saturday, June 16, 2012 11:40 PM

} else if (!strcasecmp(fargs[0], "attrname")) {


safe_bool(buff, bufc, ok_attr_name(fargs[1]));
} else if (!strcasecmp(fargs[0], "playername")) {
safe_bool(buff, bufc, (ok_player_name(fargs[1]) &&
badname_check(fargs[1])));
} else {
safe_nothing(buff, bufc);
}

FUNCTION(fun_beep)
{
safe_chr(BEEP_CHAR, buff, bufc);
}

-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:39 PM

/* funvars.c - structure, variable, stack, and regexp functions */


/* $Id: funvars.c,v 1.76 2008/10/25 19:01:53 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include
#include

"functions.h"
"match.h" /*
"attrs.h" /*
"powers.h" /*
"pcre.h"
/*

/* required by code */
required by code */
required by code */
required by code */
required by code */

/* --------------------------------------------------------------------------* setq, setr, r: set and read global registers.


*/
/*
* ASCII
*
* 0
* 48 * 64 * 80 * 96 * 112 * 128 */

character table for %qa - %qz


47
63
79
95
111
127
255

:
:
:
:
:
:
:

NULL to / (3 rows)
0 to ?
@, A to O
P to _
`, a to o
p to DEL
specials (8 rows)

char qidx_chartab[256] =
{
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
0, 1, 2, 3, 4, 5, 6, 7,
-1,10,11,12,13,14,15,16,
25,26,27,28,29,30,31,32,
-1,10,11,12,13,14,15,16,
25,26,27,28,29,30,31,32,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,

-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
8, 9, -1,-1,-1,-1,-1,-1,
17,18,19,20,21,22,23,24,
33,34,35,-1,-1,-1,-1,-1,
17,18,19,20,21,22,23,24,
33,34,35,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

};

-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,

Saturday, June 16, 2012 11:39 PM

-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1

int set_register(funcname, name, data)


const char *funcname;
char *name, *data;
{
/* Return number of characters set.
* -1 indicates a name error.
* -2 indicates that a limit was exceeded.
*/
int i, regnum, len, a_size, *tmp_lens;
char *p, **tmp_regs;
if (!name || !*name)
return -1;
if (name[1] == '\0') {
/* Single-letter q-register.
* We allocate these either as a block of 10 or a block of 36.
* (Most code won't go beyond %q0-%q9, especially legacy code
* which predates the larger number of global registers.)
*/
regnum = qidx_chartab[(unsigned char) *name];
if ((regnum < 0) || (regnum >= MAX_GLOBAL_REGS))
return -1;
/* Check to see if we're just clearing. If we're clearing a register
* that doesn't exist, then we do nothing. Otherwise we wipe out
* the data.
*/
if (!data || !*data) {
if (!mudstate.rdata || !mudstate.rdata->q_alloc ||
(regnum >= mudstate.rdata->q_alloc))
return 0;
if (mudstate.rdata->q_regs[regnum]) {
free_lbuf(mudstate.rdata->q_regs[regnum]);
mudstate.rdata->q_regs[regnum] = NULL;
mudstate.rdata->q_lens[regnum] = 0;
mudstate.rdata->dirty++;
}
return 0;
}
/* We're actually setting a register. Take care of allocating
* space first.
*/
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:39 PM

if (!mudstate.rdata) {
Init_RegData(funcname, mudstate.rdata);
}
if (!mudstate.rdata->q_alloc) {
a_size = (regnum < 10) ? 10 : MAX_GLOBAL_REGS;
mudstate.rdata->q_alloc = a_size;
mudstate.rdata->q_regs = XCALLOC(a_size, sizeof(char *), "q_regs");
mudstate.rdata->q_lens = XCALLOC(a_size, sizeof(int), "q_lens");
mudstate.rdata->q_alloc = a_size;
} else if (regnum >= mudstate.rdata->q_alloc) {
a_size = MAX_GLOBAL_REGS;
tmp_regs = XREALLOC(mudstate.rdata->q_regs,
a_size * sizeof(char *), "q_regs");
tmp_lens = XREALLOC(mudstate.rdata->q_lens,
a_size * sizeof(int), "q_lens");
memset(&tmp_regs[mudstate.rdata->q_alloc], (int) NULL,
(a_size - mudstate.rdata->q_alloc) * sizeof(char *));
memset(&tmp_lens[mudstate.rdata->q_alloc], 0,
(a_size - mudstate.rdata->q_alloc) * sizeof(int));
mudstate.rdata->q_regs = tmp_regs;
mudstate.rdata->q_lens = tmp_lens;
mudstate.rdata->q_alloc = a_size;
}
/* Set it. */
if (!mudstate.rdata->q_regs[regnum])
mudstate.rdata->q_regs[regnum] = alloc_lbuf(funcname);
len = strlen(data);
memcpy(mudstate.rdata->q_regs[regnum], data, len + 1);
mudstate.rdata->q_lens[regnum] = len;
mudstate.rdata->dirty++;
return len;
}
/* We have an arbitrarily-named register.
* Check for data-clearing first, since that's easier.
*/
if (!data || !*data) {
if (!mudstate.rdata || !mudstate.rdata->xr_alloc)
return 0;
for (p = name; *p; p++)
*p = tolower(*p);
for (i = 0; i < mudstate.rdata->xr_alloc; i++) {
if (mudstate.rdata->x_names[i] &&
!strcmp(name, mudstate.rdata->x_names[i])) {
if (mudstate.rdata->x_regs[i]) {
free_sbuf(mudstate.rdata->x_names[i]);
mudstate.rdata->x_names[i] = NULL;
free_lbuf(mudstate.rdata->x_regs[i]);
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:39 PM

mudstate.rdata->x_regs[i] = NULL;
mudstate.rdata->x_lens[i] = 0;
mudstate.rdata->dirty++;
return 0;
} else {
return 0;
}
}

}
return 0;
}

/* register unset, so just return */

/* Check for a valid name.


* We enforce names beginning with a letter, in case we want to do
* something special with naming conventions at some later date.
* We also limit the characters than can go into a name.
*/
if (strlen(name) >= SBUF_SIZE)
return -1;
if (!isalpha(*name))
return -1;
for (p = name; *p; p++) {
if (isalnum(*p) ||
(*p == '_') || (*p == '-') || (*p == '.') || (*p == '#'))
*p = tolower(*p);
else
return -1;
}
len = strlen(data);
/* If we have no existing data, life is easy; just set it. */
if (!mudstate.rdata) {
Init_RegData(funcname, mudstate.rdata);
}
if (!mudstate.rdata->xr_alloc) {
a_size = NUM_ENV_VARS;
mudstate.rdata->x_names = XCALLOC(a_size, sizeof(char *), "x_names");
mudstate.rdata->x_regs = XCALLOC(a_size, sizeof(char *), "x_regs");
mudstate.rdata->x_lens = XCALLOC(a_size, sizeof(int), "x_lens");
mudstate.rdata->xr_alloc = a_size;
mudstate.rdata->x_names[0] = alloc_sbuf(funcname);
strcpy(mudstate.rdata->x_names[0], name);
mudstate.rdata->x_regs[0] = alloc_lbuf(funcname);
memcpy(mudstate.rdata->x_regs[0], data, len + 1);
mudstate.rdata->x_lens[0] = len;
mudstate.rdata->dirty++;
return len;
}

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:39 PM

/* Search for an existing entry to replace. */


for (i = 0; i < mudstate.rdata->xr_alloc; i++) {
if (mudstate.rdata->x_names[i] &&
!strcmp(name, mudstate.rdata->x_names[i])) {
memcpy(mudstate.rdata->x_regs[i], data, len + 1);
mudstate.rdata->x_lens[i] = len;
mudstate.rdata->dirty++;
return len;
}
}
/* Check for an empty cell to insert into. */
for (i = 0; i < mudstate.rdata->xr_alloc; i++) {
if (mudstate.rdata->x_names[i] == NULL) {
mudstate.rdata->x_names[i] = alloc_sbuf(funcname);
strcpy(mudstate.rdata->x_names[i], name);
if (!mudstate.rdata->x_regs[i]) /* should never happen */
mudstate.rdata->x_regs[i] = alloc_lbuf(funcname);
memcpy(mudstate.rdata->x_regs[i], data, len + 1);
mudstate.rdata->x_lens[i] = len;
mudstate.rdata->dirty++;
return len;
}
}
/* Oops. We're out of room in our existing array. Go allocate
* more space, unless we're at our limit.
*/
regnum = mudstate.rdata->xr_alloc;
a_size = regnum + NUM_ENV_VARS;
if (a_size > mudconf.register_limit) {
a_size = mudconf.register_limit;
if (a_size <= regnum)
return -2;
}
tmp_regs = (char **) XREALLOC(mudstate.rdata->x_names,
a_size * sizeof(char *), funcname);
mudstate.rdata->x_names = tmp_regs;
tmp_regs = (char **) XREALLOC(mudstate.rdata->x_regs,
a_size * sizeof(char *), funcname);
mudstate.rdata->x_regs = tmp_regs;
tmp_lens = (int *) XREALLOC(mudstate.rdata->x_lens,
a_size * sizeof(int), funcname);
mudstate.rdata->x_lens = tmp_lens;
memset(&mudstate.rdata->x_names[mudstate.rdata->xr_alloc], (int) NULL,
(a_size - mudstate.rdata->xr_alloc) * sizeof(char *));
memset(&mudstate.rdata->x_regs[mudstate.rdata->xr_alloc], (int) NULL,
(a_size - mudstate.rdata->xr_alloc) * sizeof(char *));
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:39 PM

memset(&mudstate.rdata->x_lens[mudstate.rdata->xr_alloc], 0,
(a_size - mudstate.rdata->xr_alloc) * sizeof(int));
mudstate.rdata->xr_alloc = a_size;
/* Now we know we can insert into the first empty. */

mudstate.rdata->x_names[regnum] = alloc_sbuf(funcname);
strcpy(mudstate.rdata->x_names[regnum], name);
mudstate.rdata->x_regs[regnum] = alloc_lbuf(funcname);
memcpy(mudstate.rdata->x_regs[regnum], data, len + 1);
mudstate.rdata->x_lens[regnum] = len;
mudstate.rdata->dirty++;
return len;

FUNCTION(fun_setq)
{
int result, count, i;
if (nfargs < 2) {
safe_tprintf_str(buff, bufc,
"#-1 FUNCTION (SETQ) EXPECTS AT LEAST 2 ARGUMENTS BUT GOT %d" ,
nfargs);
return;
}
if (nfargs % 2 != 0) {
safe_tprintf_str(buff, bufc,
"#-1 FUNCTION (SETQ) EXPECTS AN EVEN NUMBER OF ARGUMENTS BUT GOT %d" ,
nfargs);
return;
}
if (nfargs > MAX_NFARGS - 2) {
/* Prevent people from doing something dumb by providing this
* too many arguments and thus having the fifteenth register
* contain the remaining args. Cut them off at the fourteenth.
*/
safe_tprintf_str(buff, bufc,
"#-1 FUNCTION (SETQ) EXPECTS NO MORE THAN %d ARGUMENTS BUT GOT %d" ,
MAX_NFARGS - 2, nfargs);
return;
}
if (nfargs == 2) {
result = set_register("fun_setq", fargs[0], fargs[1]);
if (result == -1)
safe_str("#-1 INVALID GLOBAL REGISTER" , buff, bufc);
else if (result == -2)
safe_str("#-1 REGISTER LIMIT EXCEEDED" , buff, bufc);
return;
}
count = 0;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:39 PM

for (i = 0; i < nfargs; i += 2) {


result = set_register("fun_setq", fargs[i], fargs[i + 1]);
if (result < 0)
count++;
}
if (count > 0)
safe_tprintf_str(buff, bufc, "#-1 ENCOUNTERED %d ERRORS", count);

FUNCTION(fun_setr)
{
int result;

result = set_register("fun_setr", fargs[0], fargs[1]);


if (result == -1)
safe_str("#-1 INVALID GLOBAL REGISTER" , buff, bufc);
else if (result == -2)
safe_str("#-1 REGISTER LIMIT EXCEEDED" , buff, bufc);
else if (result > 0)
safe_known_str(fargs[1], result, buff, bufc);

FUNCTION(fun_r)
{
int regnum;
char *p;
if (fargs[0][1] == '\0') {
regnum = qidx_chartab[(unsigned char) *fargs[0]];
if ((regnum < 0) || (regnum >= MAX_GLOBAL_REGS)) {
safe_str("#-1 INVALID GLOBAL REGISTER" , buff, bufc);
} else {
if (mudstate.rdata && (mudstate.rdata->q_alloc > regnum) &&
mudstate.rdata->q_regs[regnum]) {
safe_known_str(mudstate.rdata->q_regs[regnum],
mudstate.rdata->q_lens[regnum],
buff, bufc);
}
}
return;
}
if (!mudstate.rdata || !mudstate.rdata->xr_alloc)
return;
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
for (regnum = 0; regnum < mudstate.rdata->xr_alloc; regnum++) {
if (mudstate.rdata->x_names[regnum] &&
!strcmp(fargs[0], mudstate.rdata->x_names[regnum])) {
if (mudstate.rdata->x_regs[regnum]) {
safe_known_str(mudstate.rdata->x_regs[regnum],
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

}
}

return;

Saturday, June 16, 2012 11:39 PM

mudstate.rdata->x_lens[regnum],
buff, bufc);

/* -------------------------------------------------------------------------* lregs: List all the non-empty q-registers.


*/
FUNCTION(fun_lregs)
{
int i;
GDATA *g;
char *bb_p;
const char *qidx_str = "0123456789abcdefghijklmnopqrstuvwxyz" ;
if (!mudstate.rdata)
return;
bb_p = *bufc;
g = mudstate.rdata;
for (i = 0; i < g->q_alloc; i++) {
if (g->q_regs[i] && *(g->q_regs[i])) {
if (*bufc != bb_p) {
print_sep(&SPACE_DELIM, buff, bufc);
}
safe_chr(qidx_str[i], buff, bufc);
}
}

for (i = 0; i < g->xr_alloc; i++) {


if (g->x_names[i] && *(g->x_names[i]) &&
g->x_regs[i] && *(g->x_regs[i])) {
if (*bufc != bb_p) {
print_sep(&SPACE_DELIM, buff, bufc);
}
safe_str(g->x_names[i], buff, bufc);
}
}

/* -------------------------------------------------------------------------* wildmatch: Set the results of a wildcard match into the global registers.
*
wildmatch(<string>,<wildcard pattern>,<register list>)
*/
FUNCTION(fun_wildmatch)
{
int i, nqregs;
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:39 PM

char *t_args[NUM_ENV_VARS], **qregs; /* %0-%9 is limiting */


if (!wild(fargs[1], fargs[0], t_args, NUM_ENV_VARS)) {
safe_chr('0', buff, bufc);
return;
}
safe_chr('1', buff, bufc);
/* Parse the list of registers. Anything that we don't get is assumed
* to be -1. Fill them in.
*/
nqregs = list2arr(&qregs, NUM_ENV_VARS, fargs[2], &SPACE_DELIM);
for (i = 0; i < nqregs; i++) {
set_register("fun_wildmatch", qregs[i], t_args[i]);
}
/* Need to free up allocated memory from the match. */

for (i = 0; i < NUM_ENV_VARS; i++) {


if (t_args[i])
free_lbuf(t_args[i]);
}
XFREE(qregs, "fun_wildmatch.qregs");

/* -------------------------------------------------------------------------* qvars: Set the contents of a list into a named list of global registers
*
qvars(<register list>,<list of elements>[,<input delim>])
*/
FUNCTION(fun_qvars)
{
int i, nqregs, n_elems;
char **qreg_names, **elems;
char *varlist, *elemlist;
Delim isep;
VaChk_Only_In(3);
if (!fargs[0] || !*fargs[0] || !fargs[1] || !*fargs[1])
return;
varlist = alloc_lbuf("fun_qvars.vars");
strcpy(varlist, fargs[0]);
nqregs = list2arr(&qreg_names, LBUF_SIZE / 2, varlist, &SPACE_DELIM);
if (nqregs == 0) {
free_lbuf(varlist);
XFREE(qreg_names, "fun_qvars.qreg_names");
return;
}
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:39 PM

elemlist = alloc_lbuf("fun_qvars.elems");
strcpy(elemlist, fargs[1]);
n_elems = list2arr(&elems, LBUF_SIZE / 2, elemlist, &isep);
if (n_elems != nqregs) {
safe_str("#-1 LISTS MUST BE OF EQUAL SIZE" , buff, bufc);
free_lbuf(varlist);
free_lbuf(elemlist);
XFREE(qreg_names, "fun_qvars.qreg_names");
XFREE(elems, "fun_qvars.elems");
return;
}
for (i = 0; i < n_elems; i++) {
set_register("fun_qvars", qreg_names[i], elems[i]);
}

free_lbuf(varlist);
free_lbuf(elemlist);
XFREE(qreg_names, "fun_qvars.qreg_names");
XFREE(elems, "fun_qvars.elems");

/* -------------------------------------------------------------------------* Auxiliary stuff for structures and variables.


*/
#define Set_Max(x,y)

(x) = ((y) > (x)) ? (y) : (x);

static void print_htab_matches(obj, htab, buff, bufc)


dbref obj;
HASHTAB *htab;
char *buff;
char **bufc;
{
/* Lists out hashtable matches.
* Things which use this are computationally expensive, and should
* be discouraged.
*/
char tbuf[SBUF_SIZE], *tp, *bb_p;
HASHENT *hptr;
int i, len;
tp = tbuf;
safe_ltos(tbuf, &tp, obj);
safe_sb_chr('.', tbuf, &tp);
*tp = '\0';
len = strlen(tbuf);
bb_p = *bufc;

-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:39 PM

for (i = 0; i < htab->hashsize; i++) {


for (hptr = htab->entry[i]; hptr != NULL; hptr = hptr->next) {
if (!strncmp(tbuf, hptr->target.s, len)) {
if (*bufc != bb_p)
safe_chr(' ', buff, bufc);
safe_str(strchr(hptr->target.s, '.') + 1, buff, bufc);
}
}
}

/* --------------------------------------------------------------------------* fun_x: Returns a variable. x(<variable name>)


* fun_setx: Sets a variable. setx(<variable name>,<value>)
* fun_store: Sets and returns a variable. store(<variable name>,<value>)
* fun_xvars: Takes a list, parses it, sets it into variables.
*
xvars(<space-separated variable list>,<list>,<delimiter>)
* fun_let: Takes a list of variables and their values, sets them, executes
*
a function, and clears out the variables. (Scheme/ML-like.)
*
If <list> is empty, the values are reset to null.
*
let(<space-separated var list>,<list>,<body>,<delimiter>)
* fun_lvars: Shows a list of variables associated with that object.
* fun_clearvars: Clears all variables associated with that object.
*/
void set_xvar(obj, name, data)
dbref obj;
char *name;
char *data;
{
VARENT *xvar;
char tbuf[SBUF_SIZE], *tp, *p;
/* If we don't have at least one character in the name, toss it. */
if (!name || !*name)
return;
/* Variable string is '<dbref number minus #>.<variable name>'. We
* lowercase all names. Note that we're going to end up automatically
* truncating long names.
*/
tp = tbuf;
safe_ltos(tbuf, &tp, obj);
safe_sb_chr('.', tbuf, &tp);
for (p = name; *p; p++)
*p = tolower(*p);
safe_sb_str(name, tbuf, &tp);
*tp = '\0';
/* Search for it. If it exists, replace it. If we get a blank string,
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:39 PM

* delete the variable.


*/
if ((xvar = (VARENT *) hashfind(tbuf, &mudstate.vars_htab))) {
if (xvar->text) {
XFREE(xvar->text, "xvar_data");
}
if (data && *data) {
xvar->text = (char *) XMALLOC(sizeof(char) * (strlen(data) + 1),
"xvar_data");
if (!xvar->text)
return;
/* out of memory */
strcpy(xvar->text, data);
} else {
xvar->text = NULL;
XFREE(xvar, "xvar_struct");
hashdelete(tbuf, &mudstate.vars_htab);
s_VarsCount(obj, VarsCount(obj) - 1);
}
} else {
/* We haven't found it. If it's non-empty, set it, provided we're
* not running into a limit on the number of vars per object.
*/
if (VarsCount(obj) + 1 > mudconf.numvars_lim)
return;

if (data && *data) {


xvar = (VARENT *) XMALLOC(sizeof(VARENT), "xvar_struct");
if (!xvar)
return;
/* out of memory */
xvar->text = (char *) XMALLOC(sizeof(char) * (strlen(data) + 1),
"xvar_data");
if (!xvar->text)
return;
/* out of memory */
strcpy(xvar->text, data);
hashadd(tbuf, (int *) xvar, &mudstate.vars_htab, 0);
s_VarsCount(obj, VarsCount(obj) + 1);
Set_Max(mudstate.max_vars, mudstate.vars_htab.entries);
}
}

static void clear_xvars(obj, xvar_names, n_xvars)


dbref obj;
char **xvar_names;
int n_xvars;
{
/* Clear out an array of variable names. */
char pre[SBUF_SIZE], tbuf[SBUF_SIZE], *tp, *p;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:39 PM

VARENT *xvar;
int i;
/* Build our dbref bit first. */
tp = pre;
safe_ltos(pre, &tp, obj);
safe_sb_chr('.', pre, &tp);
*tp = '\0';
/* Go clear stuff. */
for (i = 0; i < n_xvars; i++) {
for (p = xvar_names[i]; *p; p++)
*p = tolower(*p);
tp = tbuf;
safe_sb_str(pre, tbuf, &tp);
safe_sb_str(xvar_names[i], tbuf, &tp);
*tp = '\0';
if ((xvar = (VARENT *) hashfind(tbuf, &mudstate.vars_htab))) {
if (xvar->text) {
XFREE(xvar->text, "xvar_data");
xvar->text = NULL;
}
XFREE(xvar, "xvar_struct");
hashdelete(tbuf, &mudstate.vars_htab);
}
}
}

s_VarsCount(obj, VarsCount(obj) - n_xvars);

void xvars_clr(player)
dbref player;
{
char tbuf[SBUF_SIZE], *tp;
HASHTAB *htab;
HASHENT *hptr, *last, *next;
int i, len;
VARENT *xvar;
tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_sb_chr('.', tbuf, &tp);
*tp = '\0';
len = strlen(tbuf);
htab = &mudstate.vars_htab;
for (i = 0; i < htab->hashsize; i++) {
last = NULL;
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:39 PM

for (hptr = htab->entry[i]; hptr != NULL; hptr = next) {


next = hptr->next;
if (!strncmp(tbuf, hptr->target.s, len)) {
if (last == NULL)
htab->entry[i] = next;
else
last->next = next;
xvar = (VARENT *) hptr->data;
XFREE(xvar->text, "xvar_data");
XFREE(xvar, "xvar_struct");
XFREE(hptr->target.s, "xvar_hptr_target");
XFREE(hptr, "xvar_hptr");
htab->deletes++;
htab->entries--;
if (htab->entry[i] == NULL)
htab->nulls++;
} else {
last = hptr;
}
}
}
}

s_VarsCount(player, 0);

FUNCTION(fun_x)
{
VARENT *xvar;
char tbuf[SBUF_SIZE], *tp, *p;
/* Variable string is '<dbref number minus #>.<variable name>' */
tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_sb_chr('.', tbuf, &tp);
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
safe_sb_str(fargs[0], tbuf, &tp);
*tp = '\0';

if ((xvar = (VARENT *) hashfind(tbuf, &mudstate.vars_htab)))


safe_str(xvar->text, buff, bufc);

FUNCTION(fun_setx)
{
set_xvar(player, fargs[0], fargs[1]);
}
FUNCTION(fun_store)
{
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:39 PM

set_xvar(player, fargs[0], fargs[1]);


safe_str(fargs[1], buff, bufc);

FUNCTION(fun_xvars)
{
char **xvar_names, **elems;
int n_xvars, n_elems;
char *varlist, *elemlist;
int i;
Delim isep;
VaChk_Only_In(3);
varlist = alloc_lbuf("fun_xvars.vars");
strcpy(varlist, fargs[0]);
n_xvars = list2arr(&xvar_names, LBUF_SIZE / 2, varlist, &SPACE_DELIM);
if (n_xvars == 0) {
free_lbuf(varlist);
XFREE(xvar_names, "fun_xvars.xvar_names");
return;
}
if (!fargs[1] || !*fargs[1]) {
/* Empty list, clear out the data. */
clear_xvars(player, xvar_names, n_xvars);
free_lbuf(varlist);
XFREE(xvar_names, "fun_xvars.xvar_names");
return;
}
elemlist = alloc_lbuf("fun_xvars.elems");
strcpy(elemlist, fargs[1]);
n_elems = list2arr(&elems, LBUF_SIZE / 2, elemlist, &isep);
if (n_elems != n_xvars) {
safe_str("#-1 LIST MUST BE OF EQUAL SIZE" , buff, bufc);
free_lbuf(varlist);
free_lbuf(elemlist);
XFREE(xvar_names, "fun_xvars.xvar_names");
XFREE(elems, "fun_xvars.elems");
return;
}
for (i = 0; i < n_elems; i++) {
set_xvar(player, xvar_names[i], elems[i]);
}
free_lbuf(varlist);
free_lbuf(elemlist);
XFREE(xvar_names, "fun_xvars.xvar_names");
XFREE(elems, "fun_xvars.elems");
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:39 PM

}
FUNCTION(fun_let)
{
char **xvar_names, **elems;
char *old_xvars[LBUF_SIZE / 2];
int n_xvars, n_elems;
char *varlist, *elemlist;
char *str, *bp, *p;
char pre[SBUF_SIZE], tbuf[SBUF_SIZE], *tp;
VARENT *xvar;
int i;
Delim isep;
VaChk_Only_In(4);
if (!fargs[0] || !*fargs[0])
return;
varlist = bp = alloc_lbuf("fun_let.vars");
str = fargs[0];
exec(varlist, &bp, player, caller, cause,
EV_FCHECK | EV_STRIP | EV_EVAL, &str, cargs, ncargs);
n_xvars = list2arr(&xvar_names, LBUF_SIZE / 2, varlist, &SPACE_DELIM);
if (n_xvars == 0) {
free_lbuf(varlist);
XFREE(xvar_names, "fun_let.xvar_names");
return;
}
/* Lowercase our variable names. */
for (i = 0, p = xvar_names[i]; *p; p++)
*p = tolower(*p);
/* Save our original values. Copying this stuff into an array is
* unnecessarily expensive because we allocate and free memory
* that we could theoretically just trade pointers around for -* but this way is cleaner.
*/
tp = pre;
safe_ltos(pre, &tp, player);
safe_sb_chr('.', pre, &tp);
*tp = '\0';
for (i = 0; i < n_xvars; i++) {
tp = tbuf;
safe_sb_str(pre, tbuf, &tp);
safe_sb_str(xvar_names[i], tbuf, &tp);
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:39 PM

*tp = '\0';
if ((xvar = (VARENT *) hashfind(tbuf, &mudstate.vars_htab))) {
if (xvar->text)
old_xvars[i] = XSTRDUP(xvar->text, "fun_let.preserve");
else
old_xvars[i] = NULL;
} else {
old_xvars[i] = NULL;
}
}
if (fargs[1] && *fargs[1]) {
/* We have data, so we should initialize variables to their values,
* ala xvars(). However, unlike xvars(), if we don't get a list,
* we just leave the values alone (we don't clear them out).
*/
elemlist = bp = alloc_lbuf("fun_let.elemlist");
str = fargs[1];
exec(elemlist, &bp, player, caller, cause,
EV_FCHECK | EV_STRIP | EV_EVAL, &str, cargs, ncargs);
n_elems = list2arr(&elems, LBUF_SIZE / 2, elemlist, &isep);
if (n_elems != n_xvars) {
safe_str("#-1 LIST MUST BE OF EQUAL SIZE" , buff, bufc);
free_lbuf(varlist);
free_lbuf(elemlist);
for (i = 0; i < n_xvars; i++) {
if (old_xvars[i])
XFREE(old_xvars[i], "fun_let");
}
XFREE(xvar_names, "fun_let.xvar_names");
XFREE(elems, "fun_let.elems");
return;
}
for (i = 0; i < n_elems; i++) {
set_xvar(player, xvar_names[i], elems[i]);
}
free_lbuf(elemlist);
}
/* Now we go to execute our function body. */
str = fargs[2];
exec(buff, bufc, player, caller, cause,
EV_FCHECK | EV_STRIP | EV_EVAL, &str, cargs, ncargs);
/* Restore the old values. */
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:39 PM

for (i = 0; i < n_xvars; i++) {


set_xvar(player, xvar_names[i], old_xvars[i]);
if (old_xvars[i])
XFREE(old_xvars[i], "fun_let");
}

free_lbuf(varlist);
XFREE(xvar_names, "fun_let.xvar_names");
XFREE(elems, "fun_let.elems");

FUNCTION(fun_lvars)
{
print_htab_matches(player, &mudstate.vars_htab, buff, bufc);
}
FUNCTION(fun_clearvars)
{
/* This is computationally expensive. Necessary, but its use should
* be avoided if possible.
*/
}

xvars_clr(player);

/* --------------------------------------------------------------------------* Structures.
*/
static int istype_char(str)
char *str;
{
if (strlen(str) == 1)
return 1;
else
return 0;
}
static int istype_dbref(str)
char *str;
{
dbref it;
if (*str++ != NUMBER_TOKEN)
return 0;
if (*str) {
it = parse_dbref(str);
return (Good_obj(it));
}
return 0;
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:39 PM

}
static int istype_int(str)
char *str;
{
return (is_integer(str));
}
static int istype_float(str)
char *str;
{
return (is_number(str));
}
static int istype_string(str)
char *str;
{
char *p;

for (p = str; *p; p++) {


if (isspace(*p))
return 0;
}
return 1;

FUNCTION(fun_structure)
{
Delim isep;
/* delim for default values */
Delim osep;
/* output delim for structure values */
char tbuf[SBUF_SIZE], *tp;
char cbuf[SBUF_SIZE], *cp;
char *p;
char *comp_names, *type_names, *default_vals;
char **comp_array, **type_array, **def_array;
int n_comps, n_types, n_defs;
int i;
STRUCTDEF *this_struct;
COMPONENT *this_comp;
int check_type = 0;
VaChk_Only_In_Out(6);
/* Prevent null delimiters and line delimiters. */
if ((osep.len > 1) || (osep.str[0] == '\0') || (osep.str[0] == '\r')) {
notify_quiet(player, "You cannot use that output delimiter." );
safe_chr('0', buff, bufc);
return;
}
/* Enforce limits. */
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:39 PM

if (StructCount(player) > mudconf.struct_lim) {


notify_quiet(player, "Too many structures.");
safe_chr('0', buff, bufc);
return;
}
/* If our structure name is too long, reject it. */
if (strlen(fargs[0]) > (SBUF_SIZE / 2) - 9) {
notify_quiet(player, "Structure name is too long." );
safe_chr('0', buff, bufc);
return;
}
/* No periods in structure names */
if (strchr(fargs[0], '.')) {
notify_quiet(player, "Structure names cannot contain periods." );
safe_chr('0', buff, bufc);
return;
}
/* The hashtable is indexed by <dbref number>.<structure name> */
tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_sb_chr('.', tbuf, &tp);
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
safe_sb_str(fargs[0], tbuf, &tp);
*tp = '\0';
/* If we have this structure already, reject. */
if (hashfind(tbuf, &mudstate.structs_htab)) {
notify_quiet(player, "Structure is already defined." );
safe_chr('0', buff, bufc);
return;
}
/* Split things up. Make sure lists are the same size.
* If everything eventually goes well, comp_names and default_vals will
* REMAIN allocated.
*/
comp_names = XSTRDUP(fargs[1], "struct.comps");
n_comps = list2arr(&comp_array, LBUF_SIZE / 2, comp_names, &SPACE_DELIM);
if (n_comps < 1) {
notify_quiet(player, "There must be at least one component." );
safe_chr('0', buff, bufc);
XFREE(comp_names, "struct.comps");
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:39 PM

XFREE(comp_array, "fun_structure.comp_array");
return;
}
/* Make sure that we have a sane name for the components. They must
* be smaller than half an SBUF.
*/
for (i = 0; i < n_comps; i++) {
if (strlen(comp_array[i]) > (SBUF_SIZE / 2) - 9) {
notify_quiet(player, "Component name is too long." );
safe_chr('0', buff, bufc);
XFREE(comp_names, "struct.comps");
XFREE(comp_array, "fun_structure.comp_array");
return;
}
}
type_names = alloc_lbuf("struct.types");
strcpy(type_names, fargs[2]);
n_types = list2arr(&type_array, LBUF_SIZE / 2, type_names, &SPACE_DELIM);
/* Make sure all types are valid. We look only at the first char, so
* typos will not be caught.
*/
for (i = 0; i < n_types; i++) {
switch (*(type_array[i])) {
case 'a': case 'A':
case 'c': case 'C':
case 'd': case 'D':
case 'i': case 'I':
case 'f': case 'F':
case 's': case 'S':
/* Valid types */
break;
default:
notify_quiet(player, "Invalid data type specified." );
safe_chr('0', buff, bufc);
XFREE(comp_names, "struct.comps");
XFREE(comp_array, "fun_structure.comp_array");
free_lbuf(type_names);
XFREE(type_array, "fun_structure.type_array");
return;
}
}
if (fargs[3] && *fargs[3]) {
default_vals = XSTRDUP(fargs[3], "struct.defaults");
n_defs = list2arr(&def_array, LBUF_SIZE / 2, default_vals, &isep);
} else {
default_vals = NULL;
n_defs = 0;
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

Saturday, June 16, 2012 11:39 PM

}
if ((n_comps != n_types) || (n_defs && (n_comps != n_defs))) {
notify_quiet(player, "List sizes must be identical." );
safe_chr('0', buff, bufc);
XFREE(comp_names, "struct.comps");
XFREE(comp_array, "fun_structure.comp_array");
free_lbuf(type_names);
XFREE(type_array, "fun_structure.type_array");
if (default_vals) {
XFREE(default_vals, "struct.defaults");
XFREE(def_array, "fun_structure.def_array");
}
return;
}
/* Allocate the structure and stuff it in the hashtable. Note that
* we retain one of the string arrays allocated by list2arr!
*/
this_struct = (STRUCTDEF *) XMALLOC(sizeof(STRUCTDEF), "struct_alloc");
this_struct->s_name = XSTRDUP(fargs[0], "struct.s_name");
this_struct->c_names = comp_array;
this_struct->c_array = (COMPONENT **) XCALLOC(n_comps, sizeof(COMPONENT *),
"struct.n_comps");
this_struct->c_count = n_comps;
this_struct->delim = osep.str[0];
this_struct->n_instances = 0;
this_struct->names_base = comp_names;
this_struct->defs_base = default_vals;
hashadd(tbuf, (int *) this_struct, &mudstate.structs_htab, 0);
Set_Max(mudstate.max_structs, mudstate.structs_htab.entries);
/* Now that we're done with the base name, we can stick the
* joining period on the end.
*/
safe_sb_chr('.', tbuf, &tp);
*tp = '\0';
/* Allocate each individual component. */
for (i = 0; i < n_comps; i++) {
cp = cbuf;
safe_sb_str(tbuf, cbuf, &cp);
for (p = comp_array[i]; *p; p++)
*p = tolower(*p);
safe_sb_str(comp_array[i], cbuf, &cp);
*cp = '\0';
this_comp = (COMPONENT *) XMALLOC(sizeof(COMPONENT), "comp_alloc");
this_comp->def_val = (default_vals ? def_array[i] : NULL);
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218

Saturday, June 16, 2012 11:39 PM

switch (*(type_array[i])) {
case 'a': case 'A':
this_comp->typer_func = NULL;
break;
case 'c': case 'C':
this_comp->typer_func = istype_char;
check_type = 1;
break;
case 'd': case 'D':
this_comp->typer_func = istype_dbref;
check_type = 1;
break;
case 'i': case 'I':
this_comp->typer_func = istype_int;
check_type = 1;
break;
case 'f': case 'F':
this_comp->typer_func = istype_float;
check_type = 1;
break;
case 's': case 'S':
this_comp->typer_func = istype_string;
check_type = 1;
break;
default:
/* Should never happen */
this_comp->typer_func = NULL;
}
this_struct->need_typecheck = check_type;
this_struct->c_array[i] = this_comp;
hashadd(cbuf, (int *) this_comp, &mudstate.cdefs_htab, 0);
Set_Max(mudstate.max_cdefs, mudstate.cdefs_htab.entries);
}
free_lbuf(type_names);
XFREE(type_array, "fun_structure.type_array");
if (default_vals) {
XFREE(def_array, "fun_structure.def_array");
}

s_StructCount(player, StructCount(player) + 1);


safe_chr('1', buff, bufc);

FUNCTION(fun_construct)
{
Delim isep;
char tbuf[SBUF_SIZE], *tp;
char ibuf[SBUF_SIZE], *ip;
char cbuf[SBUF_SIZE], *cp;
char *p;
STRUCTDEF *this_struct;
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271

Saturday, June 16, 2012 11:39 PM

char *comp_names, *init_vals;


char **comp_array, **vals_array;
int n_comps, n_vals;
int i;
COMPONENT *c_ptr;
INSTANCE *inst_ptr;
STRUCTDATA *d_ptr;
int retval;
/* This one is complicated: We need two, four, or five args. */
VaChk_In(2, 5);
if (nfargs == 3) {
safe_tprintf_str(buff, bufc,
"#-1 FUNCTION (CONSTRUCT) EXPECTS 2 OR 4 OR 5 ARGUMENTS BUT GOT %d" ,
nfargs);
return;
}
/* Enforce limits. */
if (InstanceCount(player) > mudconf.instance_lim) {
notify_quiet(player, "Too many instances.");
safe_chr('0', buff, bufc);
return;
}
/* If our instance name is too long, reject it. */
if (strlen(fargs[0]) > (SBUF_SIZE / 2) - 9) {
notify_quiet(player, "Instance name is too long.");
safe_chr('0', buff, bufc);
return;
}
/* Make sure this instance doesn't exist. */
ip = ibuf;
safe_ltos(ibuf, &ip, player);
safe_sb_chr('.', ibuf, &ip);
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
safe_sb_str(fargs[0], ibuf, &ip);
*ip = '\0';
if (hashfind(ibuf, &mudstate.instance_htab)) {
notify_quiet(player, "That instance has already been defined." );
safe_chr('0', buff, bufc);
return;
}
/* Look up the structure. */

-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324

Saturday, June 16, 2012 11:39 PM

tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_sb_chr('.', tbuf, &tp);
for (p = fargs[1]; *p; p++)
*p = tolower(*p);
safe_sb_str(fargs[1], tbuf, &tp);
*tp = '\0';
this_struct = (STRUCTDEF *) hashfind(tbuf, &mudstate.structs_htab);
if (!this_struct) {
notify_quiet(player, "No such structure.");
safe_chr('0', buff, bufc);
return;
}
/* Check to make sure that all the component names are valid, if we
* have been given defaults. Also, make sure that the defaults are
* of the appropriate type.
*/
safe_sb_chr('.', tbuf, &tp);
*tp = '\0';
if (fargs[2] && *fargs[2] && fargs[3] && *fargs[3]) {
comp_names = alloc_lbuf("construct.comps");
strcpy(comp_names, fargs[2]);
n_comps = list2arr(&comp_array, LBUF_SIZE / 2, comp_names, &SPACE_DELIM);
init_vals = alloc_lbuf("construct.vals");
strcpy(init_vals, fargs[3]);
n_vals = list2arr(&vals_array, LBUF_SIZE / 2, init_vals, &isep);
if (n_comps != n_vals) {
notify_quiet(player, "List sizes must be identical." );
safe_chr('0', buff, bufc);
free_lbuf(comp_names);
free_lbuf(init_vals);
XFREE(comp_array, "fun_construct.comp_array");
XFREE(vals_array, "fun_construct.vals_array");
return;
}
for (i = 0; i < n_comps; i++) {
cp = cbuf;
safe_sb_str(tbuf, cbuf, &cp);
for (p = comp_array[i]; *p; p++)
*p = tolower(*p);
safe_sb_str(comp_array[i], cbuf, &cp);
c_ptr = (COMPONENT *) hashfind(cbuf, &mudstate.cdefs_htab);
if (!c_ptr) {
notify_quiet(player, "Invalid component name.");
safe_chr('0', buff, bufc);
free_lbuf(comp_names);
free_lbuf(init_vals);
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377

Saturday, June 16, 2012 11:39 PM

XFREE(comp_array, "fun_construct.comp_array");
XFREE(vals_array, "fun_construct.vals_array");
return;
}
if (c_ptr->typer_func) {
retval = (*(c_ptr->typer_func)) (vals_array[i]);
if (!retval) {
notify_quiet(player, "Default value is of invalid type." );
safe_chr('0', buff, bufc);
free_lbuf(comp_names);
free_lbuf(init_vals);
XFREE(comp_array, "fun_construct.comp_array");
XFREE(vals_array, "fun_construct.vals_array");
return;
}
}

} else if ((!fargs[2] || !*fargs[2]) && (!fargs[3] || !*fargs[3])) {


/* Blank initializers. This is just fine. */
comp_names = init_vals = NULL;
comp_array = vals_array = NULL;
n_comps = n_vals = 0;
} else {
notify_quiet(player, "List sizes must be identical." );
safe_chr('0', buff, bufc);
return;
}
/* Go go gadget constructor.
* Allocate the instance. We should have already made sure that the
* instance doesn't exist.
*/
inst_ptr = (INSTANCE *) XMALLOC(sizeof(INSTANCE), "constructor.inst");
inst_ptr->datatype = this_struct;
hashadd(ibuf, (int *) inst_ptr, &mudstate.instance_htab, 0);
Set_Max(mudstate.max_instance, mudstate.instance_htab.entries);
/* Populate with default values. */
for (i = 0; i < this_struct->c_count; i++) {
d_ptr = (STRUCTDATA *) XMALLOC(sizeof(STRUCTDATA), "constructor.data");
if (this_struct->c_array[i]->def_val) {
d_ptr->text = (char *)
XSTRDUP(this_struct->c_array[i]->def_val, "constructor.dtext");
} else {
d_ptr->text = NULL;
}
tp = tbuf;
safe_sb_str(ibuf, tbuf, &tp);
safe_sb_chr('.', tbuf, &tp);
safe_sb_str(this_struct->c_names[i], tbuf, &tp);
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430

Saturday, June 16, 2012 11:39 PM

*tp = '\0';
hashadd(tbuf, (int *) d_ptr, &mudstate.instdata_htab, 0);
Set_Max(mudstate.max_instdata, mudstate.instdata_htab.entries);
}
/* Overwrite with component values. */
for (i = 0; i < n_comps; i++) {
tp = tbuf;
safe_sb_str(ibuf, tbuf, &tp);
safe_sb_chr('.', tbuf, &tp);
safe_sb_str(comp_array[i], tbuf, &tp);
*tp = '\0';
d_ptr = (STRUCTDATA *) hashfind(tbuf, &mudstate.instdata_htab);
if (d_ptr) {
if (d_ptr->text)
XFREE(d_ptr->text, "constructor.dtext");
if (vals_array[i] && *(vals_array[i]))
d_ptr->text = XSTRDUP(vals_array[i], "constructor.dtext");
else
d_ptr->text = NULL;
}
}

if (comp_names) {
free_lbuf(comp_names);
XFREE(comp_array, "fun_construct.comp_array");
}
if (init_vals) {
free_lbuf(init_vals);
XFREE(vals_array, "fun_construct.vals_array");
}
this_struct->n_instances += 1;
s_InstanceCount(player, InstanceCount(player) + 1);
safe_chr('1', buff, bufc);

static void load_structure(player, buff, bufc, inst_name, str_name, raw_text,


sep, use_def_delim)
dbref player;
char *buff, **bufc;
char *inst_name, *str_name, *raw_text;
char sep;
int use_def_delim;
{
char tbuf[SBUF_SIZE], *tp;
char ibuf[SBUF_SIZE], *ip;
char *p;
STRUCTDEF *this_struct;
char *val_list;
char **val_array;
int n_vals;
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483

Saturday, June 16, 2012 11:39 PM

INSTANCE *inst_ptr;
STRUCTDATA *d_ptr;
int i;
Delim isep;
/* Enforce limits. */
if (InstanceCount(player) > mudconf.instance_lim) {
notify_quiet(player, "Too many instances.");
safe_chr('0', buff, bufc);
return;
}
/* If our instance name is too long, reject it. */
if (strlen(inst_name) > (SBUF_SIZE / 2) - 9) {
notify_quiet(player, "Instance name is too long.");
safe_chr('0', buff, bufc);
return;
}
/* Make sure this instance doesn't exist. */
ip = ibuf;
safe_ltos(ibuf, &ip, player);
safe_sb_chr('.', ibuf, &ip);
for (p = inst_name; *p; p++)
*p = tolower(*p);
safe_sb_str(inst_name, ibuf, &ip);
*ip = '\0';
if (hashfind(ibuf, &mudstate.instance_htab)) {
notify_quiet(player, "That instance has already been defined." );
safe_chr('0', buff, bufc);
return;
}
/* Look up the structure. */
tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_sb_chr('.', tbuf, &tp);
for (p = str_name; *p; p++)
*p = tolower(*p);
safe_sb_str(str_name, tbuf, &tp);
*tp = '\0';
this_struct = (STRUCTDEF *) hashfind(tbuf, &mudstate.structs_htab);
if (!this_struct) {
notify_quiet(player, "No such structure.");
safe_chr('0', buff, bufc);
return;
}
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536

Saturday, June 16, 2012 11:39 PM

/* Chop up the raw stuff according to the delimiter. */


if (use_def_delim)
isep.str[0] = this_struct->delim;
else
isep.str[0] = sep;
val_list = alloc_lbuf("load.val_list");
strcpy(val_list, raw_text);
n_vals = list2arr(&val_array, LBUF_SIZE / 2, val_list, &isep);
if (n_vals != this_struct->c_count) {
notify_quiet(player, "Incorrect number of components." );
safe_chr('0', buff, bufc);
free_lbuf(val_list);
XFREE(val_array, "load_structure.val_array");
return;
}
/* Check the types of the data we've been passed. */
for (i = 0; i < n_vals; i++) {
if (this_struct->c_array[i]->typer_func &&
!((*(this_struct->c_array[i]->typer_func)) (val_array[i]))) {
notify_quiet(player, "Value is of invalid type.");
safe_chr('0', buff, bufc);
free_lbuf(val_list);
XFREE(val_array, "load_structure.val_array");
return;
}
}
/* Allocate the instance. We should have already made sure that the
* instance doesn't exist.
*/
inst_ptr = (INSTANCE *) XMALLOC(sizeof(INSTANCE), "constructor.inst");
inst_ptr->datatype = this_struct;
hashadd(ibuf, (int *) inst_ptr, &mudstate.instance_htab, 0);
Set_Max(mudstate.max_instance, mudstate.instance_htab.entries);
/* Stuff data into memory. */
for (i = 0; i < this_struct->c_count; i++) {
d_ptr = (STRUCTDATA *) XMALLOC(sizeof(STRUCTDATA), "constructor.data");
if (val_array[i] && *(val_array[i]))
d_ptr->text = XSTRDUP(val_array[i], "constructor.dtext");
else
d_ptr->text = NULL;
tp = tbuf;
safe_sb_str(ibuf, tbuf, &tp);
safe_sb_chr('.', tbuf, &tp);
safe_sb_str(this_struct->c_names[i], tbuf, &tp);
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589

Saturday, June 16, 2012 11:39 PM

*tp = '\0';
hashadd(tbuf, (int *) d_ptr, &mudstate.instdata_htab, 0);
Set_Max(mudstate.max_instdata, mudstate.instdata_htab.entries);
}

free_lbuf(val_list);
XFREE(val_array, "load_structure.val_array");
this_struct->n_instances += 1;
s_InstanceCount(player, InstanceCount(player) + 1);
safe_chr('1', buff, bufc);

FUNCTION(fun_load)
{
Delim isep;
VaChk_Only_InPure(4);

load_structure(player, buff, bufc,


fargs[0], fargs[1], fargs[2],
isep.str[0], (nfargs != 4) ? 1 : 0);

FUNCTION(fun_read)
{
dbref it, aowner;
int atr, aflags, alen;
char *atext;
if (!parse_attrib(player, fargs[0], &it, &atr, 1) || (atr == NOTHING)) {
safe_chr('0', buff, bufc);
return;
}

atext = atr_pget(it, atr, &aowner, &aflags, &alen);


load_structure(player, buff, bufc,
fargs[1], fargs[2], atext,
GENERIC_STRUCT_DELIM, 0);
free_lbuf(atext);

FUNCTION(fun_delimit)
{
dbref it, aowner;
int atr, aflags, alen, nitems, i, over = 0;
char *atext, **ptrs;
Delim isep;
/*
*
*
*
*

This function is unusual in that the second argument is a delimiter


string of arbitrary length, rather than a character. The input
delimiter is the final, optional argument; if it's not specified
it defaults to the "null" structure delimiter. (This function's
primary purpose is to extract out data that's been stored as a
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

Saturday, June 16, 2012 11:39 PM

* "null"-delimited structure, but it's also useful for transforming


* any delim-separated list to a list whose elements are separated
* by arbitrary strings.)
*/
VaChk_Only_InPure(3);
if (nfargs != 3)
isep.str[0] = GENERIC_STRUCT_DELIM;
if (!parse_attrib(player, fargs[0], &it, &atr, 1) || (atr == NOTHING)) {
safe_noperm(buff, bufc);
return;
}

atext = atr_pget(it, atr, &aowner, &aflags, &alen);


nitems = list2arr(&ptrs, LBUF_SIZE / 2, atext, &isep);
if (nitems) {
over = safe_str_fn(ptrs[0], buff, bufc);
}
for (i = 1; !over && (i < nitems); i++) {
over = safe_str_fn(fargs[1], buff, bufc);
if (!over)
over = safe_str_fn(ptrs[i], buff, bufc);
}
free_lbuf(atext);
XFREE(ptrs, "fun_delimit.ptrs");

FUNCTION(fun_z)
{
char tbuf[SBUF_SIZE], *tp;
char *p;
STRUCTDATA *s_ptr;
tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_sb_chr('.', tbuf, &tp);
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
safe_sb_str(fargs[0], tbuf, &tp);
safe_sb_chr('.', tbuf, &tp);
for (p = fargs[1]; *p; p++)
*p = tolower(*p);
safe_sb_str(fargs[1], tbuf, &tp);
*tp = '\0';

s_ptr = (STRUCTDATA *) hashfind(tbuf, &mudstate.instdata_htab);


if (!s_ptr || !s_ptr->text)
return;
safe_str(s_ptr->text, buff, bufc);

-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695

Saturday, June 16, 2012 11:39 PM

FUNCTION(fun_modify)
{
char tbuf[SBUF_SIZE], *tp;
char cbuf[SBUF_SIZE], *cp;
char *endp, *p;
INSTANCE *inst_ptr;
COMPONENT *c_ptr;
STRUCTDATA *s_ptr;
char **words, **vals;
int retval, nwords, nvals, i, n_mod;
Delim isep;
VaChk_Only_In(4);
/* Find the instance first, since this is how we get our typechecker. */
tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_sb_chr('.', tbuf, &tp);
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
safe_sb_str(fargs[0], tbuf, &tp);
*tp = '\0';
endp = tp;
/* save where we are */
inst_ptr = (INSTANCE *) hashfind(tbuf, &mudstate.instance_htab);
if (!inst_ptr) {
notify_quiet(player, "No such instance.");
safe_chr('0', buff, bufc);
return;
}
/* Process for each component in the list. */
nwords = list2arr(&words, LBUF_SIZE / 2, fargs[1], &SPACE_DELIM);
nvals = list2arr(&vals, LBUF_SIZE / 2, fargs[2], &isep);
n_mod = 0;
for (i = 0; i < nwords; i++) {
/* Find the component and check the type. */
if (inst_ptr->datatype->need_typecheck) {
cp = cbuf;
safe_ltos(cbuf, &cp, player);
safe_sb_chr('.', cbuf, &cp);
safe_sb_str(inst_ptr->datatype->s_name, cbuf, &cp);
safe_sb_chr('.', cbuf, &cp);
for (p = words[i]; *p; p++)
*p = tolower(*p);
safe_sb_str(words[i], cbuf, &cp);
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748

Saturday, June 16, 2012 11:39 PM

*cp = '\0';
c_ptr = (COMPONENT *) hashfind(cbuf, &mudstate.cdefs_htab);
if (!c_ptr) {
notify_quiet(player, "No such component.");
continue;
}

if (c_ptr->typer_func) {
retval = (*(c_ptr->typer_func)) (fargs[2]);
if (!retval) {
notify_quiet(player, "Value is of invalid type.");
continue;
}
}

/* Now go set it. */


tp = endp;
safe_sb_chr('.', tbuf, &tp);
safe_sb_str(words[i], tbuf, &tp);
*tp = '\0';
s_ptr = (STRUCTDATA *) hashfind(tbuf, &mudstate.instdata_htab);
if (!s_ptr) {
notify_quiet(player, "No such data.");
continue;
}
if (s_ptr->text)
XFREE(s_ptr->text, "modify.dtext");
if ((i < nvals) && vals[i] && *vals[i]) {
s_ptr->text = XSTRDUP(vals[i], "modify.dtext");
} else {
s_ptr->text = NULL;
}
n_mod++;
}

XFREE(words, "fun_modify.words");
XFREE(vals, "fun_modify.vals");
safe_ltos(buff, bufc, n_mod);

static void unload_structure(player, buff, bufc, inst_name, sep, use_def_delim)


dbref player;
char *buff, **bufc;
char *inst_name;
char sep;
int use_def_delim;
{
char tbuf[SBUF_SIZE], *tp;
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801

Saturday, June 16, 2012 11:39 PM

char ibuf[SBUF_SIZE], *ip;


INSTANCE *inst_ptr;
char *p;
STRUCTDEF *this_struct;
STRUCTDATA *d_ptr;
int i;
/* Get the instance. */
ip = ibuf;
safe_ltos(ibuf, &ip, player);
safe_sb_chr('.', ibuf, &ip);
for (p = inst_name; *p; p++)
*p = tolower(*p);
safe_sb_str(inst_name, ibuf, &ip);
*ip = '\0';
inst_ptr = (INSTANCE *) hashfind(ibuf, &mudstate.instance_htab);
if (!inst_ptr)
return;
/* From the instance, we can get a pointer to the structure. We then
* have the information we need to figure out what components are
* associated with this, and print them appropriately.
*/
safe_sb_chr('.', ibuf, &ip);
*ip = '\0';
this_struct = inst_ptr->datatype;
/* Our delimiter is a special case. */
if (use_def_delim)
sep = this_struct->delim;

for (i = 0; i < this_struct->c_count; i++) {


if (i != 0) {
safe_chr(sep, buff, bufc);
}
tp = tbuf;
safe_sb_str(ibuf, tbuf, &tp);
safe_sb_str(this_struct->c_names[i], tbuf, &tp);
*tp = '\0';
d_ptr = (STRUCTDATA *) hashfind(tbuf, &mudstate.instdata_htab);
if (d_ptr && d_ptr->text)
safe_str(d_ptr->text, buff, bufc);
}

FUNCTION(fun_unload)
{
Delim isep;

-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854

Saturday, June 16, 2012 11:39 PM

VaChk_Only_InPure(2);
unload_structure(player, buff, bufc, fargs[0], isep.str[0],
(nfargs != 2) ? 1 : 0);

FUNCTION(fun_write)
{
dbref it, aowner;
int atrnum, aflags;
char tbuf[LBUF_SIZE], *tp, *str;
ATTR *attr;
if (!parse_thing_slash(player, fargs[0], &str, &it)) {
safe_nomatch(buff, bufc);
return;
}

tp = tbuf;
*tp = '\0';
unload_structure(player, tbuf, &tp, fargs[1], GENERIC_STRUCT_DELIM, 0);
if (*tbuf) {
atrnum = mkattr(str);
if (atrnum <= 0) {
safe_str("#-1 UNABLE TO CREATE ATTRIBUTE" , buff, bufc);
return;
}
attr = atr_num(atrnum);
atr_pget_info(it, atrnum, &aowner, &aflags);
if (!attr || !Set_attr(player, it, attr, aflags) ||
(attr->check != NULL)) {
safe_noperm(buff, bufc);
} else {
atr_add(it, atrnum, tbuf, Owner(player), aflags | AF_STRUCTURE);
}
}

FUNCTION(fun_destruct)
{
char tbuf[SBUF_SIZE], *tp;
char ibuf[SBUF_SIZE], *ip;
INSTANCE *inst_ptr;
char *p;
STRUCTDEF *this_struct;
STRUCTDATA *d_ptr;
int i;
/* Get the instance. */
ip = ibuf;
safe_ltos(ibuf, &ip, player);
safe_sb_chr('.', ibuf, &ip);
-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907

Saturday, June 16, 2012 11:39 PM

for (p = fargs[0]; *p; p++)


*p = tolower(*p);
safe_sb_str(fargs[0], ibuf, &ip);
*ip = '\0';
inst_ptr = (INSTANCE *) hashfind(ibuf, &mudstate.instance_htab);
if (!inst_ptr) {
notify_quiet(player, "No such instance.");
safe_chr('0', buff, bufc);
return;
}
/* Now we can get a pointer to the structure and find the rest of the
* components.
*/
this_struct = inst_ptr->datatype;
XFREE(inst_ptr, "constructor.inst");
hashdelete(ibuf, &mudstate.instance_htab);
safe_sb_chr('.', ibuf, &ip);
*ip = '\0';
for (i = 0; i < this_struct->c_count; i++) {
tp = tbuf;
safe_sb_str(ibuf, tbuf, &tp);
safe_sb_str(this_struct->c_names[i], tbuf, &tp);
*tp = '\0';
d_ptr = (STRUCTDATA *) hashfind(tbuf, &mudstate.instdata_htab);
if (d_ptr) {
if (d_ptr->text)
XFREE(d_ptr->text, "constructor.data");
XFREE(d_ptr, "constructor.data");
hashdelete(tbuf, &mudstate.instdata_htab);
}
}

this_struct->n_instances -= 1;
s_InstanceCount(player, InstanceCount(player) - 1);
safe_chr('1', buff, bufc);

FUNCTION(fun_unstructure)
{
char tbuf[SBUF_SIZE], *tp;
char cbuf[SBUF_SIZE], *cp;
char *p;
STRUCTDEF *this_struct;
int i;
/* Find the structure */
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960

Saturday, June 16, 2012 11:39 PM

tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_sb_chr('.', tbuf, &tp);
for (p = fargs[0]; *p; p++)
*p = tolower(*p);
safe_sb_str(fargs[0], tbuf, &tp);
*tp = '\0';
this_struct = (STRUCTDEF *) hashfind(tbuf, &mudstate.structs_htab);
if (!this_struct) {
notify_quiet(player, "No such structure.");
safe_chr('0', buff, bufc);
return;
}
/* Can't delete what's in use. */
if (this_struct->n_instances > 0) {
notify_quiet(player, "This structure is in use.");
safe_chr('0', buff, bufc);
return;
}
/* Wipe the structure from the hashtable. */
hashdelete(tbuf, &mudstate.structs_htab);
/* Wipe out every component definition. */
safe_sb_chr('.', tbuf, &tp);
*tp = '\0';
for (i = 0; i < this_struct->c_count; i++) {
cp = cbuf;
safe_sb_str(tbuf, cbuf, &cp);
safe_sb_str(this_struct->c_names[i], cbuf, &cp);
*cp = '\0';
if (this_struct->c_array[i]) {
XFREE(this_struct->c_array[i], "comp_alloc");
}
hashdelete(cbuf, &mudstate.cdefs_htab);
}
/* Free up our bit of memory. */
XFREE(this_struct->s_name, "struct.s_name");
if (this_struct->names_base)
XFREE(this_struct->names_base, "struct.names_base");
if (this_struct->defs_base)
XFREE(this_struct->defs_base, "struct.defs_base");
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013

Saturday, June 16, 2012 11:39 PM

XFREE(this_struct->c_names, "struct.c_names");
XFREE(this_struct, "struct_alloc");

s_StructCount(player, StructCount(player) - 1);


safe_chr('1', buff, bufc);

FUNCTION(fun_lstructures)
{
print_htab_matches(player, &mudstate.structs_htab, buff, bufc);
}
FUNCTION(fun_linstances)
{
print_htab_matches(player, &mudstate.instance_htab, buff, bufc);
}
void structure_clr(thing)
dbref thing;
{
/* Wipe out all structure information associated with an object.
* Find all the object's instances. Destroy them.
* Then, find all the object's defined structures, and destroy those.
*/
HASHTAB *htab;
HASHENT *hptr;
char tbuf[SBUF_SIZE], ibuf[SBUF_SIZE], cbuf[SBUF_SIZE], *tp, *ip, *cp;
int i, j, len, count;
INSTANCE **inst_array;
char **name_array;
STRUCTDEF *this_struct;
STRUCTDATA *d_ptr;
STRUCTDEF **struct_array;
/* The instance table is indexed as <dbref number>.<instance name> */
tp = tbuf;
safe_ltos(tbuf, &tp, thing);
safe_sb_chr('.', tbuf, &tp);
*tp = '\0';
len = strlen(tbuf);
/* Because of the hashtable rechaining that's done, we cannot simply
* walk the hashtable and delete entries as we go. Instead, we've
* got to keep track of all of our pointers, and go back and do
* them one by one.
*/
inst_array = (INSTANCE **) XCALLOC(mudconf.instance_lim + 1,
sizeof(INSTANCE *),
"structure_clr.inst_array");
name_array = (char **) XCALLOC(mudconf.instance_lim + 1, sizeof(char *),
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066

Saturday, June 16, 2012 11:39 PM

"structure_clr.name_array");
htab = &mudstate.instance_htab;
count = 0;
for (i = 0; i < htab->hashsize; i++) {
for (hptr = htab->entry[i]; hptr != NULL; hptr = hptr->next) {
if (!strncmp(tbuf, hptr->target.s, len)) {
name_array[count] = (char *) hptr->target.s;
inst_array[count] = (INSTANCE *) hptr->data;
count++;
}
}
}
/* Now that we have the pointers to the instances, we can get the
* structure definitions, and use that to hunt down and wipe the
* components.
*/
if (count > 0) {
for (i = 0; i < count; i++) {
this_struct = inst_array[i]->datatype;
XFREE(inst_array[i], "constructor.inst");
hashdelete(name_array[i], &mudstate.instance_htab);
ip = ibuf;
safe_sb_str(name_array[i], ibuf, &ip);
safe_sb_chr('.', ibuf, &ip);
*ip = '\0';
for (j = 0; j < this_struct->c_count; j++) {
cp = cbuf;
safe_sb_str(ibuf, cbuf, &cp);
safe_sb_str(this_struct->c_names[j], cbuf, &cp);
*cp = '\0';
d_ptr = (STRUCTDATA *) hashfind(cbuf, &mudstate.instdata_htab);
if (d_ptr) {
if (d_ptr->text)
XFREE(d_ptr->text, "constructor.data");
XFREE(d_ptr, "constructor.data");
hashdelete(cbuf, &mudstate.instdata_htab);
}
}
this_struct->n_instances -= 1;
}
}
XFREE(inst_array, "structure_clr.inst_array");
XFREE(name_array, "structure_clr.name_array");
/* The structure table is indexed as <dbref number>.<struct name> */
tp = tbuf;
safe_ltos(tbuf, &tp, thing);
safe_sb_chr('.', tbuf, &tp);
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119

Saturday, June 16, 2012 11:39 PM

*tp = '\0';
len = strlen(tbuf);
/* Again, we have the hashtable rechaining problem. */
struct_array = (STRUCTDEF **) XCALLOC(mudconf.struct_lim + 1,
sizeof(STRUCTDEF *),
"structure_clr.struct_array");
name_array = (char **) XCALLOC(mudconf.struct_lim + 1, sizeof(char *),
"structure_clr.name_array2");
htab = &mudstate.structs_htab;
count = 0;
for (i = 0; i < htab->hashsize; i++) {
for (hptr = htab->entry[i]; hptr != NULL; hptr = hptr->next) {
if (!strncmp(tbuf, hptr->target.s, len)) {
name_array[count] = (char *) hptr->target.s;
struct_array[count] = (STRUCTDEF *) hptr->data;
count++;
}
}
}
/* We have the pointers to the structures. Flag a big error if they're
* still in use, wipe them from the hashtable, then wipe out every
* component definition. Free up the memory.
*/
if (count > 0) {
for (i = 0; i < count; i++) {
if (struct_array[i]->n_instances > 0) {
STARTLOG(LOG_ALWAYS, "BUG", "STRUCT")
log_name(thing);
log_printf(" structure %s has %d allocated instances uncleared." ,
name_array[i], struct_array[i]->n_instances);
ENDLOG
}
hashdelete(name_array[i], &mudstate.structs_htab);
ip = ibuf;
safe_sb_str(name_array[i], ibuf, &ip);
safe_sb_chr('.', ibuf, &ip);
*ip = '\0';
for (j = 0; j < struct_array[i]->c_count; j++) {
cp = cbuf;
safe_sb_str(ibuf, cbuf, &cp);
safe_sb_str(struct_array[i]->c_names[j], cbuf, &cp);
*cp = '\0';
if (struct_array[i]->c_array[j]) {
XFREE(struct_array[i]->c_array[j], "comp_alloc");
}
hashdelete(cbuf, &mudstate.cdefs_htab);
}
XFREE(struct_array[i]->s_name, "struct.s_name");
-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172

}
}

Saturday, June 16, 2012 11:39 PM

if (struct_array[i]->names_base)
XFREE(struct_array[i]->names_base, "struct.names_base");
if (struct_array[i]->defs_base)
XFREE(struct_array[i]->defs_base, "struct.defs_base");
XFREE(struct_array[i]->c_names, "struct.c_names");
XFREE(struct_array[i], "struct_alloc");

XFREE(struct_array, "structure_clr.struct_array");
XFREE(name_array, "structure_clr.name_array2");

/* -------------------------------------------------------------------------* Auxiliary functions for stacks.


*/
#define stack_get(x)

((OBJSTACK *) nhashfind(x, &mudstate.objstack_htab))

#define stack_object(p,x)
\
x = match_thing(p, fargs[0]);
if (!Good_obj(x)) {
\
return;
\
}
\
if (!Controls(p, x)) {
\
notify_quiet(p, NOPERM_MESSAGE);
return;
\
}

/* --------------------------------------------------------------------------* Object stack functions.


*/
void stack_clr(thing)
dbref thing;
{
OBJSTACK *sp, *tp, *xp;

sp = stack_get(thing);
if (sp) {
for (tp = sp; tp != NULL; ) {
XFREE(tp->data, "stack_clr_data");
xp = tp;
tp = tp->next;
XFREE(xp, "stack_clr");
}
nhashdelete(thing, &mudstate.objstack_htab);
s_StackCount(thing, 0);
}

static int stack_set(thing, sp)


dbref thing;
-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225

Saturday, June 16, 2012 11:39 PM

OBJSTACK *sp;
OBJSTACK *xsp;
int stat;
if (!sp) {
nhashdelete(thing, &mudstate.objstack_htab);
return 1;
}

xsp = stack_get(thing);
if (xsp) {
stat = nhashrepl(thing, (int *) sp, &mudstate.objstack_htab);
} else {
stat = nhashadd(thing, (int *) sp, &mudstate.objstack_htab);
Set_Max(mudstate.max_stacks, mudstate.objstack_htab.entries);
}
if (stat < 0) {
/* failure for some reason */
STARTLOG(LOG_BUGS, "STK", "SET")
log_name(thing);
ENDLOG
stack_clr(thing);
return 0;
}
return 1;

FUNCTION(fun_empty)
{
dbref it;
VaChk_Range(0, 1);
if (!fargs[0]) {
it = player;
} else {
stack_object(player, it);
}
}

stack_clr(it);

FUNCTION(fun_items)
{
dbref it;
if (!fargs[0]) {
it = player;
} else {
stack_object(player, it);
}
safe_ltos(buff, bufc, StackCount(it));
-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278

Saturday, June 16, 2012 11:39 PM

}
FUNCTION(fun_push)
{
dbref it;
char *data;
OBJSTACK *sp;
VaChk_Range(0, 2);
if (!fargs[1]) {
it = player;
if (!fargs[0] || !*fargs[0])
data = (char *) "";
else
data = fargs[0];
} else {
stack_object(player, it);
data = fargs[1];
}
if (StackCount(it) + 1 > mudconf.stack_lim)
return;

sp = (OBJSTACK *) XMALLOC(sizeof(OBJSTACK), "stack_push");


if (!sp)
/* out of memory, ouch */
return;
sp->next = stack_get(it);
sp->data = (char *) XMALLOC(sizeof(char) * (strlen(data) + 1),
"stack_push_data");
if (! sp->data)
return;
strcpy(sp->data, data);
if (stack_set(it, sp))
s_StackCount(it, StackCount(it) + 1);

FUNCTION(fun_dup)
{
dbref it;
OBJSTACK *hp;
/* head of stack */
OBJSTACK *tp;
/* temporary stack pointer */
OBJSTACK *sp;
/* new stack element */
int pos, count = 0;
VaChk_Range(0, 2);
if (!fargs[0]) {
it = player;
} else {
stack_object(player, it);
}
-43-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331

Saturday, June 16, 2012 11:39 PM

if (StackCount(it) + 1 > mudconf.stack_lim)


return;
if (!fargs[1] || !*fargs[1]) {
pos = 0;
} else {
pos = atoi(fargs[1]);
}
hp = stack_get(it);
for (tp = hp; (count != pos) && (tp != NULL); count++, tp = tp->next)
;
if (!tp) {
notify_quiet(player, "No such item on stack.");
return;
}

sp = (OBJSTACK *) XMALLOC(sizeof(OBJSTACK), "stack_dup");


if (!sp)
return;
sp->next = hp;
sp->data = (char *) XMALLOC(sizeof(char) * (strlen(tp->data) + 1),
"stack_dup_data");
if (!sp->data)
return;
strcpy(sp->data, tp->data);
if (stack_set(it, sp))
s_StackCount(it, StackCount(it) + 1);

FUNCTION(fun_swap)
{
dbref it;
OBJSTACK *sp, *tp;
VaChk_Range(0, 1);
if (!fargs[0]) {
it = player;
} else {
stack_object(player, it);
}
sp = stack_get(it);
if (!sp || (sp->next == NULL)) {
notify_quiet(player, "Not enough items on stack.");
return;
}
tp = sp->next;
sp->next = tp->next;
tp->next = sp;
-44-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384

Saturday, June 16, 2012 11:39 PM

stack_set(it, tp);

FUNCTION(handle_pop)
{
dbref it;
int pos, count = 0, peek_flag, toss_flag;
OBJSTACK *sp;
OBJSTACK *prev = NULL;
peek_flag = Is_Func(POP_PEEK);
toss_flag = Is_Func(POP_TOSS);
VaChk_Range(0, 2);
if (!fargs[0]) {
it = player;
} else {
stack_object(player, it);
}
if (!fargs[1] || !*fargs[1]) {
pos = 0;
} else {
pos = atoi(fargs[1]);
}
sp = stack_get(it);
if (!sp)
return;
while (count != pos) {
if (!sp)
return;
prev = sp;
sp = sp->next;
count++;
}
if (!sp)
return;
if (!toss_flag) {
safe_str(sp->data, buff, bufc);
}
if (!peek_flag) {
if (count == 0) {
stack_set(it, sp->next);
} else {
prev->next = sp->next;
}
XFREE(sp->data, "stack_pop_data");
XFREE(sp, "stack_pop");
s_StackCount(it, StackCount(it) - 1);
-45-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437

Saturday, June 16, 2012 11:39 PM

FUNCTION(fun_popn)
{
dbref it;
int pos, nitems, i, count = 0, over = 0;
OBJSTACK *sp, *tp, *xp;
OBJSTACK *prev = NULL;
Delim osep;
char *bb_p;
VaChk_Only_Out(4);
stack_object(player, it);
pos = atoi(fargs[1]);
nitems = atoi(fargs[2]);
sp = stack_get(it);
if (!sp)
return;
while (count != pos) {
if (!sp)
return;
prev = sp;
sp = sp->next;
count++;
}
if (!sp)
return;
/* We've now hit the start item, the first item. Copy 'em off. */
for (i = 0, tp = sp, bb_p = *bufc; (i < nitems) && (tp != NULL); i++) {
if (!over) {
/* We have to pop off the items regardless of whether
* or not there's an overflow, but we can save ourselves
* some copying if so.
*/
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
over = safe_str_fn(tp->data, buff, bufc);
}
xp = tp;
tp = tp->next;
XFREE(xp->data, "stack_popn_data");
XFREE(xp, "stack_popn");
s_StackCount(it, StackCount(it) - 1);
}
/* Relink the chain. */
-46-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490

Saturday, June 16, 2012 11:39 PM

if (count == 0) {
stack_set(it, tp);
} else {
prev->next = tp;
}

FUNCTION(fun_lstack)
{
Delim osep;
dbref it;
OBJSTACK *sp;
char *bp, *bb_p;
int over = 0;
VaChk_Out(0, 2);
if (!fargs[0]) {
it = player;
} else {
stack_object(player, it);
}

bp = buff;
bb_p = *bufc;
for (sp = stack_get(it); (sp != NULL) && !over; sp = sp->next) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
over = safe_str_fn(sp->data, buff, bufc);
}

/* -------------------------------------------------------------------------* regedit: Edit a string for sed/perl-like s//


*
regedit(<string>,<regexp>,<replacement>)
*
Derived from the PennMUSH code.
*/
FUNCTION(perform_regedit)
{
pcre *re;
pcre_extra *study = NULL;
const char *errptr;
int case_option, all_option;
int erroffset, subpatterns, len;
int offsets[PCRE_MAX_OFFSETS];
char *r, *start;
char tbuf[LBUF_SIZE];
char tmp;
int match_offset = 0;

-47-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543

Saturday, June 16, 2012 11:39 PM

case_option = Func_Mask(REG_CASELESS);
all_option = Func_Mask(REG_MATCH_ALL);
if ((re = pcre_compile(fargs[1], case_option,
&errptr, &erroffset, mudstate.retabs)) == NULL) {
/* Matching error. Note that this returns a null string rather
* than '#-1 REGEXP ERROR: <error>', as PennMUSH does, in order
* to remain consistent with our other regexp functions.
*/
notify_quiet(player, errptr);
return;
}
/* Study the pattern for optimization, if we're going to try multiple
* matches.
*/
if (all_option) {
study = pcre_study(re, 0, &errptr);
if (errptr != NULL) {
XFREE(re, "perform_regedit.re");
notify_quiet(player, errptr);
return;
}
}
len = strlen(fargs[0]);
start = fargs[0];
subpatterns = pcre_exec(re, study, fargs[0], len, 0, 0, offsets,
PCRE_MAX_OFFSETS);
/* If there's no match, just return the original. */
if (subpatterns < 0) {
XFREE(re, "perform_regedit.re");
if (study) {
XFREE(study, "perform_regedit.study");
}
safe_str(fargs[0], buff, bufc);
return;
}
do {
/* If we had too many subpatterns for the offsets vector, set the
* number to 1/3rd of the size of the offsets vector.
*/
if (subpatterns == 0)
subpatterns = PCRE_MAX_OFFSETS / 3;
/* Copy up to the start of the matched area. */
tmp = fargs[0][offsets[0]];
fargs[0][offsets[0]] = '\0';
safe_str(start, buff, bufc);
-48-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596

Saturday, June 16, 2012 11:39 PM

fargs[0][offsets[0]] = tmp;
/* Copy in the replacement, putting in captured sub-expressions. */
for (r = fargs[2]; *r; r++) {
int offset, have_brace = 0;
char *endsub;
if (*r != '$') {
safe_chr(*r, buff, bufc);
continue;
}
r++;
if (*r == '{') {
have_brace = 1;
r++;
}
offset = strtoul(r, &endsub, 10);
if (r == endsub || (have_brace && *endsub != '}')) {
/* Not a valid number. */
safe_chr('$', buff, bufc);
if (have_brace)
safe_chr('{', buff, bufc);
r--;
continue;
}
r = endsub - 1;
if (have_brace)
r++;

if (pcre_copy_substring(fargs[0], offsets, subpatterns, offset,


tbuf, LBUF_SIZE) >= 0) {
safe_str(tbuf, buff, bufc);
}

start = fargs[0] + offsets[1];


match_offset = offsets[1];
} while (all_option &&
(((offsets[0] == offsets[1]) &&
/* PCRE docs note:
* Perl special-cases the empty-string match in split and /g.
* To emulate, first try the match again at the same position
* with PCRE_NOTEMPTY, then advance the starting offset if that
* fails.
*/
(((subpatterns = pcre_exec(re, study, fargs[0], len,
match_offset, PCRE_NOTEMPTY, offsets,
PCRE_MAX_OFFSETS)) >= 0) ||
((match_offset++ < len) &&
(subpatterns = pcre_exec(re, study, fargs[0], len,
match_offset, 0, offsets,
-49-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649

Saturday, June 16, 2012 11:39 PM

PCRE_MAX_OFFSETS)) >= 0))) ||


((match_offset <= len) &&
(subpatterns = pcre_exec(re, study, fargs[0], len,
match_offset, 0, offsets,
PCRE_MAX_OFFSETS)) >= 0)));
/* Copy everything after the matched bit. */

safe_str(start, buff, bufc);


XFREE(re, "perform_regedit.re");
if (study) {
XFREE(study, "perform_regedit.study");
}

/* -------------------------------------------------------------------------* wildparse: Set the results of a wildcard match into named variables.
*
wildparse(<string>,<pattern>,<list of variable names>)
*/
FUNCTION(fun_wildparse)
{
int i, nqregs;
char *t_args[NUM_ENV_VARS], **qregs;
if (!wild(fargs[1], fargs[0], t_args, NUM_ENV_VARS))
return;
nqregs = list2arr(&qregs, NUM_ENV_VARS, fargs[2], &SPACE_DELIM);
for (i = 0; i < nqregs; i++) {
if (qregs[i] && *qregs[i])
set_xvar(player, qregs[i], t_args[i]);
}
/* Need to free up allocated memory from the match. */

for (i = 0; i < NUM_ENV_VARS; i++) {


if (t_args[i])
free_lbuf(t_args[i]);
}
XFREE(qregs, "wildparse.qregs");

/* --------------------------------------------------------------------------* perform_regparse: Slurp a string into up to ten named variables ($0 - $9).
*
REGPARSE, REGPARSEI. Unlike regmatch(), this returns no value.
*
regparse(string, pattern, named vars)
*/
FUNCTION(perform_regparse)
{
int i, nqregs;
int case_option;
-50-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702

Saturday, June 16, 2012 11:39 PM

char **qregs;
char matchbuf[LBUF_SIZE];
pcre *re;
const char *errptr;
int erroffset;
int offsets[PCRE_MAX_OFFSETS];
int subpatterns;
case_option = Func_Mask(REG_CASELESS);
if ((re = pcre_compile(fargs[1], case_option,
&errptr, &erroffset, mudstate.retabs)) == NULL) {
/* Matching error. */
notify_quiet(player, errptr);
return;
}
subpatterns = pcre_exec(re, NULL, fargs[0], strlen(fargs[0]),
0, 0, offsets, PCRE_MAX_OFFSETS);
/* If we had too many subpatterns for the offsets vector, set the
* number to 1/3rd of the size of the offsets vector.
*/
if (subpatterns == 0)
subpatterns = PCRE_MAX_OFFSETS / 3;
nqregs = list2arr(&qregs, NUM_ENV_VARS, fargs[2], &SPACE_DELIM);
for (i = 0; i < nqregs; i++) {
if (qregs[i] && *qregs[i]) {
if (pcre_copy_substring(fargs[0], offsets, subpatterns, i,
matchbuf, LBUF_SIZE) < 0) {
set_xvar(player, qregs[i], NULL);
} else {
set_xvar(player, qregs[i], matchbuf);
}
}
}

XFREE(re, "perform_regparse.re");
XFREE(qregs, "perform_regparse.qregs");

/* --------------------------------------------------------------------------* perform_regrab: Like grab() and graball(), but with a regexp pattern.
*
REGRAB, REGRABI. Derived from PennMUSH.
*/
FUNCTION(perform_regrab)
{
Delim isep, osep;
int case_option, all_option;
char *r, *s, *bb_p;
pcre *re;
-51-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755

Saturday, June 16, 2012 11:39 PM

pcre_extra *study;
const char *errptr;
int erroffset;
int offsets[PCRE_MAX_OFFSETS];
case_option = Func_Mask(REG_CASELESS);
all_option = Func_Mask(REG_MATCH_ALL);
if (all_option) {
VaChk_Only_In_Out(4);
} else {
VaChk_Only_In(3);
}
s = trim_space_sep(fargs[0], &isep);
bb_p = *bufc;
if ((re = pcre_compile(fargs[1], case_option, &errptr, &erroffset,
mudstate.retabs)) == NULL) {
/* Matching error.
* Note difference from PennMUSH behavior:
* Regular expression errors return 0, not #-1 with an error
* message.
*/
notify_quiet(player, errptr);
return;
}
study = pcre_study(re, 0, &errptr);
if (errptr != NULL) {
notify_quiet(player, errptr);
XFREE(re, "perform_regrab.re");
return;
}
do {
r = split_token(&s, &isep);
if (pcre_exec(re, study, r, strlen(r), 0, 0,
offsets, PCRE_MAX_OFFSETS) >= 0) {
if (*bufc != bb_p) { /* if true, all_option also true */
print_sep(&osep, buff, bufc);
}
safe_str(r, buff, bufc);
if (!all_option)
break;
}
} while (s);

XFREE(re, "perform_regrab.re");
if (study) {
XFREE(study, "perform_regrab.study");
}

-52-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808

Saturday, June 16, 2012 11:39 PM

/* --------------------------------------------------------------------------* perform_regmatch: Return 0 or 1 depending on whether or not a regular


* expression matches a string. If a third argument is specified, dump
* the results of a regexp pattern match into a set of arbitrary r()-registers.
* REGMATCH, REGMATCHI
*
* regmatch(string, pattern, list of registers)
* If the number of matches exceeds the registers, those bits are tossed
* out.
* If -1 is specified as a register number, the matching bit is tossed.
* Therefore, if the list is "-1 0 3 5", the regexp $0 is tossed, and
* the regexp $1, $2, and $3 become r(0), r(3), and r(5), respectively.
*
* PCRE modifications adapted from PennMUSH.
*
*/
FUNCTION(perform_regmatch)
{
int case_option;
int i, nqregs;
char **qregs;
pcre *re;
const char *errptr;
int erroffset;
int offsets[PCRE_MAX_OFFSETS];
int subpatterns;
char tbuf[LBUF_SIZE], *p;
case_option = Func_Mask(REG_CASELESS);
VaChk_Range(2, 3);
if ((re = pcre_compile(fargs[1], case_option,
&errptr, &erroffset, mudstate.retabs)) == NULL) {
/* Matching error.
* Note difference from PennMUSH behavior:
* Regular expression errors return 0, not #-1 with an error
* message.
*/
notify_quiet(player, errptr);
safe_chr('0', buff, bufc);
return;
}
subpatterns = pcre_exec(re, NULL, fargs[0], strlen(fargs[0]),
0, 0, offsets, PCRE_MAX_OFFSETS);
safe_bool(buff, bufc, (subpatterns >= 0));
/* If we had too many subpatterns for the offsets vector, set the
* number to 1/3rd of the size of the offsets vector.
*/
-53-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861

Saturday, June 16, 2012 11:39 PM

if (subpatterns == 0)
subpatterns = PCRE_MAX_OFFSETS / 3;
/* If we don't have a third argument, we're done. */
if (nfargs != 3) {
XFREE(re, "perform_regmatch.re");
return;
}
/* We need to parse the list of registers. Anything that we don't get
* is assumed to be -1. If we didn't match, or the match went wonky,
* then set the register to empty. Otherwise, fill the register
* with the subexpression.
*/
nqregs = list2arr(&qregs, NUM_ENV_VARS, fargs[2], &SPACE_DELIM);
for (i = 0; i < nqregs; i++) {
if (pcre_copy_substring(fargs[0], offsets, subpatterns, i,
tbuf, LBUF_SIZE) < 0) {
set_register("perform_regmatch", qregs[i], NULL);
} else {
set_register("perform_regmatch", qregs[i], tbuf);
}
}

XFREE(re, "perform_regmatch.re");
XFREE(qregs, "perform_regmatch.qregs");

/* --------------------------------------------------------------------------* fun_until: Much like while(), but operates on multiple lists ala mix().
* until(eval_fn,cond_fn,list1,list2,compare_str,delim,output delim)
* The delimiter terminators are MANDATORY.
* The termination condition is a REGEXP match (thus allowing this
* to be also used as 'eval until a termination condition is NOT met').
*/
FUNCTION(fun_until)
{
Delim isep, osep;
dbref aowner1, thing1, aowner2, thing2;
int aflags1, aflags2, anum1, anum2, alen1, alen2;
ATTR *ap, *ap2;
char *atext1, *atext2, *atextbuf, *condbuf;
char *cp[NUM_ENV_VARS], *os[NUM_ENV_VARS];
int count[LBUF_SIZE / 2];
int i, is_exact_same, is_same, nwords, lastn, wc;
char *str, *dp, *savep, *bb_p;
char tmpbuf[2];
pcre *re;
const char *errptr;
int erroffset;
int offsets[PCRE_MAX_OFFSETS];
-54-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914

Saturday, June 16, 2012 11:39 PM

int subpatterns;
/* We need at least 6 arguments. The last 2 args must be delimiters. */
VaChk_Range(6, 12);
VaChk_InSep(nfargs - 1, 0);
VaChk_OutSep(nfargs, 0);
lastn = nfargs - 4;
/* Make sure we have a valid regular expression. */
if ((re = pcre_compile(fargs[lastn + 1], 0,
&errptr, &erroffset, mudstate.retabs)) == NULL) {
/* Return nothing on a bad match. */
notify_quiet(player, errptr);
return;
}
/* Our first and second args can be <obj>/<attr> or just <attr>.
* Use them if we can access them, otherwise return an empty string.
*
* Note that for user-defined attributes, atr_str() returns a pointer
* to a static, and that therefore we have to be careful about what
* we're doing.
*/
Parse_Uattr(player, fargs[0], thing1, anum1, ap);
Get_Uattr(player, thing1, ap, atext1, aowner1, aflags1, alen1);
Parse_Uattr(player, fargs[1], thing2, anum2, ap2);
if (!ap2) {
free_lbuf(atext1); /* we allocated this, remember? */
return;
}
/* If our evaluation and condition are the same, we can save ourselves
* some time later. There are two possibilities: we have the exact
* same obj/attr pair, or the attributes contain identical text.
*/
if ((thing1 == thing2) && (ap->number == ap2->number)) {
is_same = 1;
is_exact_same = 1;
} else {
is_exact_same = 0;
atext2 = atr_pget(thing2, ap2->number, &aowner2, &aflags2, &alen2);
if (!*atext2 || !See_attr(player, thing2, ap2, aowner2, aflags2)) {
free_lbuf(atext1);
free_lbuf(atext2);
return;
}
if (!strcmp(atext1, atext2))
is_same = 1;
-55-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967

else
}

Saturday, June 16, 2012 11:39 PM

is_same = 0;

atextbuf = alloc_lbuf("fun_while.eval");
if (!is_same)
condbuf = alloc_lbuf("fun_while.cond");
bb_p = *bufc;
/* Process the list one element at a time. We need to find out what
* the longest list is; assume null-padding for shorter lists.
*/
for (i = 0; i < NUM_ENV_VARS; i++)
cp[i] = NULL;
cp[2] = trim_space_sep(fargs[2], &isep);
nwords = count[2] = countwords(cp[2], &isep);
for (i = 3; i <= lastn; i++) {
cp[i] = trim_space_sep(fargs[i], &isep);
count[i] = countwords(cp[i], &isep);
if (count[i] > nwords)
nwords = count[i];
}
for (wc = 0;
(wc < nwords) && (mudstate.func_invk_ctr < mudconf.func_invk_lim) &&
!Too_Much_CPU();
wc++) {
for (i = 2; i <= lastn; i++) {
if (count[i]) {
os[i - 2] = split_token(&cp[i], &isep);
} else {
tmpbuf[0] = '\0';
os[i - 2] = tmpbuf;
}
}
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
StrCopyKnown(atextbuf, atext1, alen1);
str = atextbuf;
savep = *bufc;
exec(buff, bufc, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, &(os[0]), lastn - 1);
if (!is_same) {
StrCopyKnown(atextbuf, atext2, alen2);
dp = savep = condbuf;
str = atextbuf;
exec(condbuf, &dp, player, caller, cause,
EV_STRIP | EV_FCHECK | EV_EVAL, &str, &(os[0]), lastn - 1);
}
-56-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020

Saturday, June 16, 2012 11:39 PM

subpatterns = pcre_exec(re, NULL, savep, strlen(savep),


0, 0, offsets, PCRE_MAX_OFFSETS);
if (subpatterns >= 0)
break;
}
XFREE(re, "until.re");
free_lbuf(atext1);
if (!is_exact_same)
free_lbuf(atext2);
free_lbuf(atextbuf);
if (!is_same)
free_lbuf(condbuf);

/* --------------------------------------------------------------------------* perform_grep: grep (exact match), wildgrep (wildcard match),


* regrep (regexp match), and case-insensitive versions. (There is no
* case-insensitive wildgrep, since all wildcard matches are caseless.)
*/
FUNCTION(perform_grep)
{
int grep_type, caseless;
pcre *re = NULL;
pcre_extra *study = NULL;
const char *errptr;
int erroffset;
int offsets[PCRE_MAX_OFFSETS];
char *patbuf, *patc, *attrib, *p, *bb_p;
int ca, aflags, alen;
dbref thing, aowner, it;
Delim osep;
VaChk_Only_Out(4);
grep_type = Func_Mask(REG_TYPE);
caseless = Func_Mask(REG_CASELESS);
it = match_thing(player, fargs[0]);
if (!Good_obj(it)) {
safe_nomatch(buff, bufc);
return;
} else if (!(Examinable(player, it))) {
safe_noperm(buff, bufc);
return;
}
/* Make sure there's an attribute and a pattern */
if (!fargs[1] || !*fargs[1]) {
safe_str("#-1 NO SUCH ATTRIBUTE", buff, bufc);
return;
-57-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073

Saturday, June 16, 2012 11:39 PM

}
if (!fargs[2] || !*fargs[2]) {
safe_str("#-1 INVALID GREP PATTERN", buff, bufc);
return;
}
switch (grep_type) {
case GREP_EXACT:
if (caseless) {
for (p = fargs[2]; *p; p++)
*p = tolower(*p);
}
break;
case GREP_REGEXP:
if ((re = pcre_compile(fargs[2], caseless, &errptr, &erroffset,
mudstate.retabs)) == NULL) {
notify_quiet(player, errptr);
return;
}
study = pcre_study(re, 0, &errptr);
if (errptr != NULL) {
XFREE(re, "perform_grep.re");
notify_quiet(player, errptr);
return;
}
break;
default:
/* No special set-up steps. */
break;
}
bb_p = *bufc;
patc = patbuf = alloc_lbuf("perform_grep.parse_attrib");
safe_tprintf_str(patbuf, &patc, "#%d/%s", it, fargs[1]);
olist_push();
if (parse_attrib_wild(player, patbuf, &thing, 0, 0, 1, 1)) {
for (ca = olist_first(); ca != NOTHING; ca = olist_next()) {
attrib = atr_get(thing, ca, &aowner, &aflags, &alen);
if ((grep_type == GREP_EXACT) && caseless) {
for (p = attrib; *p; p++)
*p = tolower(*p);
}
if (((grep_type == GREP_EXACT) && strstr(attrib, fargs[2])) ||
((grep_type == GREP_WILD) && quick_wild(fargs[2], attrib)) ||
((grep_type == GREP_REGEXP) &&
(pcre_exec(re, study, attrib, alen, 0, 0,
offsets, PCRE_MAX_OFFSETS) >= 0))) {
if (*bufc != bb_p) {
print_sep(&osep, buff, bufc);
}
safe_str((char *)(atr_num(ca))->name, buff, bufc);
}
free_lbuf(attrib);
-58-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\funvars.c

3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086

Saturday, June 16, 2012 11:39 PM

}
}

free_lbuf(patbuf);
olist_pop();
if (re) {
XFREE(re, "perform_grep.re");
}
if (study) {
XFREE(study, "perform_grep.study");
}

-59-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:38 PM

/* game.c - main program and misc functions */


/* $Id: game.c,v 1.194 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include <sys/stat.h>
#include <signal.h>
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include
#include
#include
#include

"db.h"
/* required by externs */
"udb.h"
/* required by code */
"externs.h"
/* required by interface */
"interface.h" /* required by code */

#include
#include
#include
#include
#include

"file_c.h" /*
"command.h"
"powers.h" /*
"attrs.h" /*
"pcre.h"
/*

extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

required by code */
/* required by code */
required by code */
required by code */
required by code */

void NDECL(init_attrtab);
void NDECL(init_cmdtab);
void NDECL(cf_init);
void NDECL(pcache_init);
int FDECL(cf_read, (char *fn));
void NDECL(init_functab);
void FDECL(close_sockets, (int emergency, char *message));
void NDECL(init_version);
void NDECL(init_logout_cmdtab);
void NDECL(init_timer);
void FDECL(raw_notify_html, (dbref, char *));
void FDECL(do_dbck, (dbref, dbref, int));
void FDECL(logfile_init, (char *));

extern void FDECL(init_genrand, (unsigned long));


void FDECL(fork_and_dump, (int));
void NDECL(dump_database);
dbref FDECL(db_read_flatfile, (FILE *, int *, int *, int *));
void NDECL(pcache_sync);
static void NDECL(init_rlimit);
extern int FDECL(add_helpfile, (dbref, char *, char *, int));
extern void NDECL(vattr_init);
extern void NDECL(load_restart_db);
extern int NDECL(sql_init);
extern void NDECL(sql_shutdown);
extern void NDECL(tcache_init);
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:38 PM

extern void FDECL(helpindex_load, (dbref));


extern void NDECL(helpindex_init);
extern int NDECL(dddb_optimize);
extern LOGFILETAB logfds_table[];
extern volatile pid_t slave_pid;
extern volatile int slave_socket;
extern char qidx_chartab[256];
#ifdef NEED_EMPTY_LTPLSYM
const lt_dlsymlist lt_preloaded_symbols[] = { {0, (lt_ptr_t) 0} };
#endif
extern char *optarg;
extern int optind;
/*
* used to allocate storage for temporary stuff, cleared before command
* execution
*/
void do_dump(player, cause, key)
dbref player, cause;
int key;
{
if (mudstate.dumping) {
notify(player, "Dumping. Please try again later." );
return;
}

notify(player, "Dumping...");
fork_and_dump(key);

/* ---------------------------------------------------------------------* Hashtable resize.


*/
void do_hashresize(player, cause, key)
dbref player, cause;
int key;
{
MODULE *mp;
MODHASHES *m_htab, *hp;
MODNHASHES *m_ntab, *np;
hashresize(&mudstate.command_htab, 512);
hashresize(&mudstate.player_htab, 16);
hashresize(&mudstate.nref_htab, 8);
hashresize(&mudstate.vattr_name_htab, 256);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:38 PM

nhashresize(&mudstate.fwdlist_htab, 8);
nhashresize(&mudstate.propdir_htab, 8);
nhashresize(&mudstate.redir_htab, 8);
hashresize(&mudstate.ufunc_htab, 8);
hashresize(&mudstate.structs_htab,
(mudstate.max_structs < 16) ? 16 : mudstate.max_structs);
hashresize(&mudstate.cdefs_htab,
(mudstate.max_cdefs < 16) ? 16 : mudstate.max_cdefs);
hashresize(&mudstate.instance_htab,
(mudstate.max_instance < 16) ? 16 : mudstate.max_instance);
hashresize(&mudstate.instdata_htab,
(mudstate.max_instdata < 16) ? 16 : mudstate.max_instdata);
nhashresize(&mudstate.objstack_htab,
(mudstate.max_stacks < 16) ? 16 : mudstate.max_stacks);
hashresize(&mudstate.vars_htab,
(mudstate.max_vars < 16) ? 16 : mudstate.max_vars);
hashresize(&mudstate.api_func_htab, 8);
WALK_ALL_MODULES(mp) {
m_htab = DLSYM_VAR(mp->handle, mp->modname,
"hashtable", MODHASHES *);
if (m_htab) {
for (hp = m_htab; hp->tabname != NULL; hp++) {
hashresize(hp->htab, hp->min_size);
}
}
m_ntab = DLSYM_VAR(mp->handle, mp->modname,
"nhashtable", MODNHASHES *);
if (m_ntab) {
for (np = m_ntab; np->tabname != NULL; np++) {
nhashresize(np->htab, np->min_size);
}
}
}

if (!mudstate.restarting)
notify(player, "Resized.");

/* ---------------------------------------------------------------------* regexp_match: Load a regular expression match and insert it into


* registers. PCRE modifications adapted from PennMUSH.
*/
#define PCRE_MAX_OFFSETS 99
int regexp_match(pattern, str, case_opt, args, nargs)
char *pattern;
char *str;
int case_opt;
char *args[];
int nargs;
{
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:38 PM

int i;
pcre *re;
const char *errptr;
int erroffset;
int offsets[PCRE_MAX_OFFSETS];
int subpatterns;
if ((re = pcre_compile(pattern, case_opt,
&errptr, &erroffset, mudstate.retabs)) == NULL) {
/*
* This is a matching error. We have an error message in
* errptr that we can ignore, since we're doing command-matching.
*/
return 0;
}
/*
* Now we try to match the pattern. The relevant fields will
* automatically be filled in by this.
*/
if ((subpatterns = pcre_exec(re, NULL, str, strlen(str), 0, 0,
offsets, PCRE_MAX_OFFSETS)) < 0) {
XFREE(re, "regexp_match.re");
return 0;
}
/* If we had too many subpatterns for the offsets vector, set the
* number to 1/3rd of the size of the offsets vector.
*/
if (subpatterns == 0)
subpatterns = PCRE_MAX_OFFSETS / 3;
/*
* Now we fill in our args vector. Note that in regexp matching,
* 0 is the entire string matched, and the parenthesized strings
* go from 1 to 9. We DO PRESERVE THIS PARADIGM, for consistency
* with other languages.
*/
for (i = 0; i < nargs; i++) {
args[i] = NULL;
}
for (i = 0; i < nargs; i++) {
args[i] = alloc_lbuf("regexp_match");
if (pcre_copy_substring(str, offsets, subpatterns, i,
args[i], LBUF_SIZE) < 0) {
/* Match behavior of wild(): clear out null values. */
free_lbuf(args[i]);
args[i] = NULL;
}
}

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:38 PM

XFREE(re, "regexp_match.re");
return 1;

/* ---------------------------------------------------------------------* atr_match: Check attribute list for wild card matches and queue them.
*/
static int atr_match1(thing, parent, player, type, str, raw_str, check_exclude,
hash_insert)
dbref thing, parent, player;
char type, *str, *raw_str;
int check_exclude, hash_insert;
{
dbref aowner;
int match, attr, aflags, alen, i;
char *buff, *s, *as;
char *args[NUM_ENV_VARS];
ATTR *ap;
/* See if we can do it.

Silently fail if we can't. */

if (!could_doit(player, parent, A_LUSE))


return -1;
match = 0;
buff = alloc_lbuf("atr_match1");
atr_push();
for (attr = atr_head(parent, &as); attr; attr = atr_next(&as)) {
ap = atr_num(attr);
/* Never check NOPROG attributes. */
if (!ap || (ap->flags & AF_NOPROG))
continue;
/* If we aren't the bottom level check if we saw this attr
* before. Also exclude it if the attribute type is PRIVATE.
*/
if (check_exclude &&
((ap->flags & AF_PRIVATE) ||
nhashfind(ap->number, &mudstate.parent_htab))) {
continue;
}
atr_get_str(buff, parent, attr, &aowner, &aflags, &alen);
/* Skip if private and on a parent */
if (check_exclude && (aflags & AF_PRIVATE)) {
continue;
}
/* If we aren't the top level remember this attr so we
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:38 PM

* exclude it from now on.


*/
if (hash_insert)
nhashadd(ap->number, (int *)&attr,
&mudstate.parent_htab);
/* Check for the leadin character after excluding the attrib
* This lets non-command attribs on the child block
* commands on the parent.
*/
if ((buff[0] != type) || (aflags & AF_NOPROG))
continue;
/* decode it: search for first un escaped : */
for (s = buff + 1;
*s && ((*s != ':') || (*(s - 1) == '\\'));
s++)
;
if (!*s)
continue;
*s++ = 0;
if ((!(aflags & (AF_REGEXP | AF_RMATCH)) &&
wild(buff + 1,
((aflags & AF_NOPARSE) ? raw_str: str),
args, NUM_ENV_VARS)) ||
((aflags & AF_REGEXP) &&
regexp_match(buff + 1,
((aflags & AF_NOPARSE) ? raw_str : str),
((aflags & AF_CASE) ? 0 : PCRE_CASELESS),
args, NUM_ENV_VARS)) ||
((aflags & AF_RMATCH) &&
register_match(buff + 1,
((aflags & AF_NOPARSE) ? raw_str : str),
args, NUM_ENV_VARS))) {
match = 1;
if (aflags & AF_NOW) {
process_cmdline(thing, player, s, args,
NUM_ENV_VARS, NULL);
} else {
wait_que(thing, player, 0, NOTHING, 0, s, args,
NUM_ENV_VARS, mudstate.rdata);
}
for (i = 0; i < NUM_ENV_VARS; i++) {
if (args[i])
free_lbuf(args[i]);
}
}

}
free_lbuf(buff);
atr_pop();

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:38 PM

return (match);

int atr_match(thing, player, type, str, raw_str, check_parents)


dbref thing, player;
char type, *str, *raw_str;
int check_parents;
{
int match, lev, result, exclude, insert;
dbref parent;
/* If thing is halted, or it doesn't have a COMMANDS flag and we're
* we're doing a $-match, don't check it.
*/
if (((type == AMATCH_CMD) &&
!Has_Commands(thing) && mudconf.req_cmds_flag) || Halted(thing))
return 0;
/* If not checking parents, just check the thing */
match = 0;
if (!check_parents || Orphan(thing))
return atr_match1(thing, thing, player, type, str, raw_str, 0, 0);
/* Check parents, ignoring halted objects */
exclude = 0;
insert = 1;
nhashflush(&mudstate.parent_htab, 0);
ITER_PARENTS(thing, parent, lev) {
if (!Good_obj(Parent(parent)))
insert = 0;
result = atr_match1(thing, parent, player, type, str, raw_str,
exclude, insert);
if (result > 0) {
match = 1;
} else if (result < 0) {
return match;
}
exclude = 1;
}
}

return match;

/* --------------------------------------------------------------------------* notify_check: notifies the object #target of the message msg, and
* optionally notify the contents, neighbors, and location also.
*/
int check_filter(object, player, filter, msg)
dbref object, player;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:38 PM

int filter;
const char *msg;
{
int aflags, alen;
dbref aowner;
char *buf, *nbuf, *cp, *dp, *str;
pcre *re;
const char *errptr;
int len, case_opt, erroffset, subpatterns;
int offsets[PCRE_MAX_OFFSETS];
GDATA *preserve;
buf = atr_pget(object, filter, &aowner, &aflags, &alen);
if (!*buf) {
free_lbuf(buf);
return (1);
}
if (!(aflags & AF_NOPARSE)) {
preserve = save_global_regs("check_filter.save");
nbuf = dp = alloc_lbuf("check_filter");
str = buf;
exec(nbuf, &dp, object, player, player,
EV_FIGNORE | EV_EVAL | EV_TOP, &str, (char **)NULL, 0);
dp = nbuf;
free_lbuf(buf);
restore_global_regs("check_filter.restore", preserve);
} else {
dp = buf;
nbuf = buf;
/* this way, buf will get freed correctly */
}
if (!(aflags & AF_REGEXP)) {
do {
cp = parse_to(&dp, ',', EV_STRIP);
if (quick_wild(cp, (char *)msg)) {
free_lbuf(nbuf);
return (0);
}
} while (dp != NULL);
} else {
len = strlen(msg);
case_opt = (aflags & AF_CASE) ? 0 : PCRE_CASELESS;
do {
cp = parse_to(&dp, ',', EV_STRIP);
re = pcre_compile(cp, case_opt, &errptr, &erroffset,
mudstate.retabs);
if (re != NULL) {
subpatterns = pcre_exec(re, NULL, (char *) msg, len,
0, 0, offsets, PCRE_MAX_OFFSETS);
if (subpatterns >= 0) {
XFREE(re, "check_filter.re");
free_lbuf(nbuf);
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:38 PM

return (0);
}
XFREE(re, "check_filter.re");

}
} while (dp != NULL);

}
free_lbuf(nbuf);
return (1);

static char *add_prefix(object, player, prefix, msg, dflt)


dbref object, player;
int prefix;
const char *msg, *dflt;
{
int aflags, alen;
dbref aowner;
char *buf, *nbuf, *cp, *str;
GDATA *preserve;

buf = atr_pget(object, prefix, &aowner, &aflags, &alen);


if (!*buf) {
cp = buf;
safe_str((char *)dflt, buf, &cp);
} else {
preserve = save_global_regs("add_prefix_save");
nbuf = cp = alloc_lbuf("add_prefix");
str = buf;
exec(nbuf, &cp, object, player, player,
EV_FIGNORE | EV_EVAL | EV_TOP, &str,
(char **)NULL, 0);
free_lbuf(buf);
restore_global_regs("add_prefix_restore", preserve);
buf = nbuf;
}
if (cp != buf) {
safe_chr(' ', buf, &cp);
}
safe_str((char *)msg, buf, &cp);
return (buf);

static char *dflt_from_msg(sender, sendloc)


dbref sender, sendloc;
{
char *tp, *tbuff;
tp = tbuff = alloc_lbuf("notify_check.fwdlist");
safe_known_str((char *)"From ", 5, tbuff, &tp);
if (Good_obj(sendloc))
safe_name(sendloc, tbuff, &tp);
else
safe_name(sender, tbuff, &tp);
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:38 PM

safe_chr(',', tbuff, &tp);


return tbuff;

#ifdef PUEBLO_SUPPORT
/* Do HTML escaping, converting < to &lt;, etc. 'dest' needs to be
* allocated & freed by the caller.
*
* If you're using this to append to a string, you can pass in the
* safe_{str|chr} (char **) so we can just do the append directly,
* saving you an alloc_lbuf()...free_lbuf(). If you want us to append
* from the start of 'dest', just pass in a 0 for 'destp'.
*/
void html_escape(src, dest, destp)
const char *src;
char *dest;
char **destp;
{
const char *msg_orig;
char *temp;
if (destp == 0) {
temp = dest;
destp = &temp;
}

for (msg_orig = src;


msg_orig && *msg_orig;
msg_orig++) {
switch (*msg_orig) {
case '<':
safe_known_str("&lt;", 4, dest, destp);
break;
case '>':
safe_known_str("&gt;", 4, dest, destp);
break;
case '&':
safe_known_str("&amp;", 5, dest, destp);
break;
case '\"':
safe_known_str("&quot;", 6, dest, destp);
break;
default:
safe_chr(*msg_orig, dest, destp);
break;
}
}
**destp = '\0';

#endif /* PUEBLO_SUPPORT */
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:38 PM

#define OK_To_Send(p,t) (!herekey || \


((!Unreal(p) || \
((key & MSG_SPEECH) && Check_Heard((t),(p))) || \
((key & MSG_MOVE) && Check_Noticed((t),(p))) || \
((key & MSG_PRESENCE) && Check_Known((t),(p)))) && \
(!Unreal(t) || \
((key & MSG_SPEECH) && Check_Hears((p),(t))) || \
((key & MSG_MOVE) && Check_Notices((p),(t))) || \
((key & MSG_PRESENCE) && Check_Knows((p),(t))))))
void notify_check(target, sender, msg, key)
dbref target, sender;
int key;
const char *msg;
{
char *msg_ns, *mp, *tbuff, *tp, *buff;
char *args[NUM_ENV_VARS];
dbref aowner, targetloc, recip, obj;
int i, nargs, aflags, alen, has_neighbors, pass_listen, herekey;
int check_listens, pass_uselock, is_audible, will_send;
FWDLIST *fp;
NUMBERTAB *np;
GDATA *preserve;
/* If speaker is invalid or message is empty, just exit */
if (!Good_obj(target) || !msg || !*msg)
return;
/* Enforce a recursion limit */
mudstate.ntfy_nest_lev++;
if (mudstate.ntfy_nest_lev >= mudconf.ntfy_nest_lim) {
mudstate.ntfy_nest_lev--;
return;
}
/* If we want NOSPOOF output, generate it. It is only needed if
* we are sending the message to the target object
*/
if (key & MSG_ME) {
mp = msg_ns = alloc_lbuf("notify_check");
if (Nospoof(target) &&
(target != sender) &&
(target != mudstate.curr_enactor) &&
(target != mudstate.curr_player)) {
if (sender != Owner(sender)) {
if (sender != mudstate.curr_enactor) {
safe_tprintf_str(msg_ns, &mp,
"[%s(#%d){%s}<-(#%d)] ",
Name(sender), sender,
Name(Owner(sender)),
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:38 PM

mudstate.curr_enactor);
} else {
safe_tprintf_str(msg_ns, &mp,
"[%s(#%d){%s}] ",
Name(sender), sender,
Name(Owner(sender)));
}
} else if (sender != mudstate.curr_enactor) {
safe_tprintf_str(msg_ns, &mp,
"[%s(#%d)<-(#%d)] ",
Name(sender), sender,
mudstate.curr_enactor);
} else {
safe_tprintf_str(msg_ns, &mp,
"[%s(#%d)] ",
Name(sender), sender);
}

}
safe_str((char *)msg, msg_ns, &mp);
} else {
msg_ns = NULL;
}

/* msg contains the raw message, msg_ns contains the NOSPOOFed msg */
s_Accessed(target);
check_listens = Halted(target) ? 0 : 1;
herekey = key & (MSG_SPEECH | MSG_MOVE | MSG_PRESENCE);
will_send = OK_To_Send(sender, target);
switch (Typeof(target)) {
case TYPE_PLAYER:
if (will_send) {
#ifndef PUEBLO_SUPPORT
if (key & MSG_ME)
raw_notify(target, msg_ns);
#else
if (key & MSG_ME) {
if (key & MSG_HTML) {
raw_notify_html(target, msg_ns);
} else {
if (Html(target)) {
char *msg_ns_escaped;

msg_ns_escaped = alloc_lbuf("notify_check_escape");
html_escape(msg_ns, msg_ns_escaped, 0);
raw_notify(target, msg_ns_escaped);
free_lbuf(msg_ns_escaped);
} else {
raw_notify(target, msg_ns);
}

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:38 PM

#endif /* ! PUEBLO_SUPPORT */
if (!mudconf.player_listen)
check_listens = 0;
}
case TYPE_THING:
case TYPE_ROOM:
/* If we're in a pipe, objects can receive raw_notify
* if they're not a player (players were already notified
* above). */
if (mudstate.inpipe && !isPlayer(target) && will_send) {
raw_notify(target, msg_ns);
}
/* Forward puppet message if it is for me */
has_neighbors = Has_location(target);
targetloc = where_is(target);
is_audible = Audible(target);
if (will_send && (key & MSG_ME) &&
Puppet(target) &&
(target != Owner(target)) &&
((key & MSG_PUP_ALWAYS) ||
((targetloc != Location(Owner(target))) &&
(targetloc != Owner(target))))) {
tp = tbuff = alloc_lbuf("notify_check.puppet");
safe_name(target, tbuff, &tp);
safe_known_str((char *)"> ", 2, tbuff, &tp);
safe_str(msg_ns, tbuff, &tp);

/* Criteria for redirection of a puppet is based


* on the "normal" conditions for hearing and
* not conditions based on who the target of
* the redirection. Use of raw_notify() means
* that recursion is avoided.
*/
if (H_Redirect(target)) {
np = (NUMBERTAB *) nhashfind(target,
&mudstate.redir_htab);
if (np && Good_obj(np->num)) {
raw_notify(Owner(np->num), tbuff);
}
} else {
raw_notify(Owner(target), tbuff);
}
free_lbuf(tbuff);

/* Make sure that we're passing an empty set of global


* registers to the evaluations we are going to run. We are
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:38 PM

* specifically not calling a save, since that doesn't


* empty the registers.
*/
preserve = mudstate.rdata;
mudstate.rdata = NULL;
/* Check for @Listen match if it will be useful */
pass_listen = 0;
nargs = 0;
if (will_send && check_listens &&
(key & (MSG_ME | MSG_INV_L)) && H_Listen(target)) {
tp = atr_get(target, A_LISTEN, &aowner, &aflags, &alen);
if (*tp &&
((!(aflags & AF_REGEXP) &&
wild(tp, (char *) msg, args, NUM_ENV_VARS)) ||
((aflags & AF_REGEXP) &&
regexp_match(tp, (char *) msg,
((aflags & AF_CASE) ?
0 : PCRE_CASELESS),
args, NUM_ENV_VARS)))) {
for (nargs = NUM_ENV_VARS;
nargs &&
(!args[nargs - 1] ||
!(*args[nargs - 1]));
nargs--) ;
pass_listen = 1;
}
free_lbuf(tp);
}
/* If we matched the @listen or are monitoring, check the * *
* USE lock
*/
pass_uselock = 0;
if (will_send && (key & MSG_ME) && check_listens &&
(pass_listen || Monitor(target)))
pass_uselock = could_doit(sender, target, A_LUSE);
/* Process AxHEAR if we pass LISTEN, USElock and it's for me */
if (will_send && (key & MSG_ME) &&
pass_listen && pass_uselock) {
if (sender != target)
did_it(sender, target,
A_NULL, NULL, A_NULL, NULL,
A_AHEAR, 0, args, nargs, 0);
else
did_it(sender, target,
A_NULL, NULL, A_NULL, NULL,
A_AMHEAR, 0, args, nargs, 0);
did_it(sender, target, A_NULL, NULL, A_NULL, NULL,
A_AAHEAR, 0, args, nargs, 0);
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:38 PM

}
/* Get rid of match arguments. We don't need them any more */
if (pass_listen) {
for (i = 0; i < nargs; i++)
if (args[i] != NULL)
free_lbuf(args[i]);
}
/* Process ^-listens if for me, MONITOR, and we pass UseLock */
if (will_send && (key & MSG_ME) && pass_uselock &&
(sender != target) && Monitor(target)) {
(void)atr_match(target, sender,
AMATCH_LISTEN, (char *)msg, (char *)msg, 0);
}
/* Deliver message to forwardlist members.
* No presence control is done on forwarders; if the target
* can get it, so can they.
*/
if (will_send && (key & MSG_FWDLIST) &&
Audible(target) && H_Fwdlist(target) &&
check_filter(target, sender, A_FILTER, msg)) {
tbuff = dflt_from_msg(sender, target);
buff = add_prefix(target, sender, A_PREFIX,
msg, tbuff);
free_lbuf(tbuff);

fp = fwdlist_get(target);
if (fp) {
for (i = 0; i < fp->count; i++) {
recip = fp->data[i];
if (!Good_obj(recip) ||
(recip == target))
continue;
notify_check(recip, sender, buff,
(MSG_ME | MSG_F_UP | MSG_F_CONTENTS | MSG_S_INSIDE));
}
}
free_lbuf(buff);

/* Deliver message through audible exits.


* If the exit can get it, we don't do further checking
* for whatever is beyond it. Otherwise we have to
* continue checking.
*/
if (will_send && (key & MSG_INV_EXITS)) {
DOLIST(obj, Exits(target)) {
recip = Location(obj);
if (Audible(obj) && ((recip != target) &&
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

Saturday, June 16, 2012 11:38 PM

check_filter(obj, sender, A_FILTER, msg))) {


buff = add_prefix(obj, target,
A_PREFIX, msg,
"From a distance,");
notify_check(recip, sender, buff,
MSG_ME | MSG_F_UP | MSG_F_CONTENTS | MSG_S_INSIDE | (
OK_To_Send(sender, obj) ? 0 : herekey));
free_lbuf(buff);
}

/* Deliver message through neighboring audible exits.


* Note that the target doesn't have to hear it in
* order for us to do this check.
* If the exit can get it, we don't do further checking
* for whatever is beyond it. Otherwise we have to
* continue checking.
*/
if (has_neighbors &&
((key & MSG_NBR_EXITS) ||
((key & MSG_NBR_EXITS_A) && is_audible))) {
/* If from inside, we have to add the prefix string
* of the container.
*/
if (key & MSG_S_INSIDE) {
tbuff = dflt_from_msg(sender, target);
buff = add_prefix(target, sender, A_PREFIX,
msg, tbuff);
free_lbuf(tbuff);
} else {
buff = (char *)msg;
}
DOLIST(obj, Exits(Location(target))) {
recip = Location(obj);
if (Good_obj(recip) && Audible(obj) &&
(recip != targetloc) &&
(recip != target) &&
check_filter(obj, sender, A_FILTER, msg)) {
tbuff = add_prefix(obj, target,
A_PREFIX, buff,
"From a distance,");
notify_check(recip, sender, tbuff,
MSG_ME | MSG_F_UP | MSG_F_CONTENTS | MSG_S_INSIDE | (
OK_To_Send(sender, obj) ? 0 : herekey));
free_lbuf(tbuff);
}
}
if (key & MSG_S_INSIDE) {
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899

Saturday, June 16, 2012 11:38 PM

free_lbuf(buff);

if (Bouncer(target))
pass_listen = 1;
/* Deliver message to contents only if target passes check.
* But things within it must still pass the check.
*/
if (will_send &&
((key & MSG_INV) ||
((key & MSG_INV_L) && pass_listen &&
check_filter(target, sender, A_INFILTER, msg)))) {
/* Don't prefix the message if we were given the
* MSG_NOPREFIX key.
*/
if (key & MSG_S_OUTSIDE) {
buff = add_prefix(target, sender, A_INPREFIX,
msg, "");
} else {
buff = (char *)msg;
}
DOLIST(obj, Contents(target)) {
if (obj != target) {
#ifdef PUEBLO_SUPPORT
notify_check(obj, sender, buff,
MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE | (key & MSG_HTML) | herekey);
#else
notify_check(obj, sender, buff,
MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE | herekey);
#endif /* PUEBLO_SUPPORT */
}
}
if (key & MSG_S_OUTSIDE)
free_lbuf(buff);
}
/* Deliver message to neighbors */
if (has_neighbors &&
((key & MSG_NBR) ||
((key & MSG_NBR_A) && is_audible &&
check_filter(target, sender, A_FILTER, msg)))) {
if (key & MSG_S_INSIDE) {
buff = add_prefix(target, sender, A_PREFIX,
msg, "");
} else {
buff = (char *)msg;
}
DOLIST(obj, Contents(targetloc)) {
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

Saturday, June 16, 2012 11:38 PM

if ((obj != target) && (obj != targetloc)) {


notify_check(obj, sender, buff,
MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE | herekey);
}

}
if (key & MSG_S_INSIDE) {
free_lbuf(buff);
}

}
/* Deliver message to container */
if (has_neighbors &&
((key & MSG_LOC) ||
((key & MSG_LOC_A) && is_audible &&
check_filter(target, sender, A_FILTER, msg)))) {
if (key & MSG_S_INSIDE) {
tbuff = dflt_from_msg(sender, target);
buff = add_prefix(target, sender, A_PREFIX,
msg, tbuff);
free_lbuf(tbuff);
} else {
buff = (char *)msg;
}
notify_check(targetloc, sender, buff,
MSG_ME | MSG_F_UP | MSG_S_INSIDE | herekey);
if (key & MSG_S_INSIDE) {
free_lbuf(buff);
}
}
/* mudstate.rdata should be empty, but empty it just in case */
Free_RegData(mudstate.rdata);
mudstate.rdata = preserve;

}
if (msg_ns)
free_lbuf(msg_ns);
mudstate.ntfy_nest_lev--;

void notify_except(loc, player, exception, msg, flags)


dbref loc, player, exception;
const char *msg;
int flags;
{
dbref first;
if (loc != exception)
notify_check(loc, player, msg,
(MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE | MSG_NBR_EXITS_A | flags));
DOLIST(first, Contents(loc)) {
if (first != exception) {
notify_check(first, player, msg,
(MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE | flags));
}
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

Saturday, June 16, 2012 11:38 PM

void notify_except2(loc, player, exc1, exc2, msg, flags)


dbref loc, player, exc1, exc2;
const char *msg;
int flags;
{
dbref first;

if ((loc != exc1) && (loc != exc2))


notify_check(loc, player, msg,
(MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE | MSG_NBR_EXITS_A | flags));
DOLIST(first, Contents(loc)) {
if (first != exc1 && first != exc2) {
notify_check(first, player, msg,
(MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE | flags));
}
}

/* ---------------------------------------------------------------------* Reporting of CPU information.


*/
#ifndef NO_TIMECHECKING
static void report_timecheck(player, yes_screen, yes_log, yes_clear)
dbref player;
int yes_screen, yes_log, yes_clear;
{
int thing, obj_counted;
long used_msecs, total_msecs;
struct timeval obj_time;
if (! (yes_log && (LOG_TIMEUSE & mudconf.log_options) != 0)) {
yes_log = 0;
STARTLOG(LOG_ALWAYS, "WIZ", "TIMECHECK")
log_name(player);
log_printf(" checks object time use over %d seconds\n" ,
(int) (time(NULL) - mudstate.cpu_count_from));
ENDLOG
} else {
STARTLOG(LOG_ALWAYS, "OBJ", "CPU")
log_name(player);
log_printf(" checks object time use over %d seconds\n" ,
(int) (time(NULL) - mudstate.cpu_count_from));
ENDLOG
}
obj_counted = 0;
total_msecs = 0;
/* Step through the db. Care only about the ones that are nonzero.
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:38 PM

* And yes, we violate several rules of good programming practice


* by failing to abstract our log calls. Oh well.
*/
DO_WHOLE_DB(thing) {
obj_time = Time_Used(thing);
if (obj_time.tv_sec || obj_time.tv_usec) {
obj_counted++;
used_msecs = (obj_time.tv_sec * 1000) + (obj_time.tv_usec / 1000);
total_msecs += used_msecs;
if (yes_log)
log_printf("#%d\t%ld\n", thing, used_msecs);
if (yes_screen)
raw_notify(player, tprintf("#%d\t%ld", thing, used_msecs));
if (yes_clear)
obj_time.tv_usec = obj_time.tv_sec = 0;
}
s_Time_Used(thing, obj_time);
}
if (yes_screen) {
raw_notify(player,
tprintf("Counted %d objects using %ld msecs over %d seconds." ,
obj_counted, total_msecs,
(int) (time(NULL) - mudstate.cpu_count_from)));
}
if (yes_log) {
log_printf("Counted %d objects using %ld msecs over %d seconds." ,
obj_counted, total_msecs,
(int) (time(NULL) - mudstate.cpu_count_from));
end_log();
}
if (yes_clear)
mudstate.cpu_count_from = time(NULL);

}
#else
static void report_timecheck(player, yes_screen, yes_log, yes_clear)
dbref player;
int yes_screen, yes_log, yes_clear;
{
raw_notify(player, "Sorry, this command has been disabled." );
}
#endif /* ! NO_TIMECHECKING */
void do_timecheck(player, cause, key)
dbref player, cause;
int key;
{
int yes_screen, yes_log, yes_clear;
yes_screen = yes_log = yes_clear = 0;
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

Saturday, June 16, 2012 11:38 PM

if (key == 0) {
/* No switches, default to printing to screen and clearing counters */
yes_screen = 1;
yes_clear = 1;
} else {
if (key & TIMECHK_RESET)
yes_clear = 1;
if (key & TIMECHK_SCREEN)
yes_screen = 1;
if (key & TIMECHK_LOG)
yes_log = 1;
}
}

report_timecheck(player, yes_screen, yes_log, yes_clear);

/* ---------------------------------------------------------------------* Miscellaneous startup/stop routines.


*/
void write_pidfile(fn)
char *fn;
{
FILE *f;

mudconf.pid_file = XSTRDUP(fn, "write_pidfile");


if ((f = fopen(fn, "w")) != NULL) {
fprintf(f, "%d\n", getpid());
fclose(f);
} else {
STARTLOG(LOG_ALWAYS, "PID", "FAIL")
log_printf("Failed to write pidfile %s\n" , fn);
ENDLOG
}

void do_shutdown(player, cause, key, message)


dbref player, cause;
int key;
char *message;
{
int fd;
if (key & SHUTDN_COREDUMP) {
if (player != NOTHING) {
raw_broadcast(0, "GAME: Aborted by %s", Name(Owner(player)));
STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN")
log_printf("Abort and coredump by ");
log_name(player);
ENDLOG
}
/* Don't bother to even shut down the network or dump. */
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

Saturday, June 16, 2012 11:38 PM

/* Die. Die now. */


abort();
if (mudstate.dumping) {
notify(player, "Dumping. Please try again later." );
return;

do_dbck(NOTHING, NOTHING, 0);

/* dump consistent state */

if (player != NOTHING) {
raw_broadcast(0, "GAME: Shutdown by %s", Name(Owner(player)));
STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN")
log_printf("Shutdown by ");
log_name(player);
ENDLOG
} else {
raw_broadcast(0, "GAME: Fatal Error: %s", message);
STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN")
log_printf("Fatal error: %s", message);
ENDLOG
}
STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN")
log_printf("Shutdown status: %s", message);
ENDLOG
fd = tf_open(mudconf.status_file, O_RDWR | O_CREAT | O_TRUNC);
(void)write(fd, message, strlen(message));
(void)write(fd, (char *)"\n", 1);
tf_close(fd);
/* Set up for normal shutdown */

mudstate.shutdown_flag = 1;
return;

void dump_database_internal(dump_type)
int dump_type;
{
char tmpfile[256], prevfile[256], *c;
FILE *f = NULL;
MODULE *mp;
switch(dump_type) {
case DUMP_DB_CRASH:
sprintf(tmpfile, "%s/%s", mudconf.dbhome, mudconf.crashdb);
unlink(tmpfile);
f = tf_fopen(tmpfile, O_WRONLY | O_CREAT | O_TRUNC);
if (f != NULL) {
db_write_flatfile(f, F_TINYMUSH, UNLOAD_VERSION | UNLOAD_OUTFLAGS);
tf_fclose(f);
} else {
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

Saturday, June 16, 2012 11:38 PM

log_perror("DMP", "FAIL", "Opening crash file",


tmpfile);

}
break;
case DUMP_DB_RESTART:
db_write();
break;
case DUMP_DB_FLATFILE:
/* Trigger modules to write their flat-text dbs */
WALK_ALL_MODULES(mp) {
if (mp->db_write_flatfile) {
f = db_module_flatfile(mp->modname, 1);
if (f) {
(*(mp->db_write_flatfile))(f);
tf_fclose(f);
}
}
if (mp->dump_database) {
f = db_module_flatfile(mp->modname, 1);
if (f) {
(*(mp->dump_database))(f);
tf_fclose(f);
}
}
}
/* Write the game's flatfile */

strcpy(prevfile, mudconf.gdbm);
if ((c = strchr(prevfile, '.')) != NULL)
*c = '\0';
sprintf(tmpfile, "%s/%s.FLAT", mudconf.dbhome, prevfile);
f = tf_fopen(tmpfile, O_WRONLY | O_CREAT | O_TRUNC);
if (f != NULL) {
db_write_flatfile(f, F_TINYMUSH,
UNLOAD_VERSION | UNLOAD_OUTFLAGS);
tf_fclose(f);
} else {
log_perror("DMP", "FAIL", "Opening flatfile",
tmpfile);
}
break;
case DUMP_DB_KILLED:
strcpy(prevfile, mudconf.gdbm);
if ((c = strchr(prevfile, '.')) != NULL)
*c = '\0';
sprintf(tmpfile, "%s/%s.KILLED", mudconf.dbhome, prevfile);
f = tf_fopen(tmpfile, O_WRONLY | O_CREAT | O_TRUNC);
if (f != NULL) {
/* Write a flatfile */
db_write_flatfile(f, F_TINYMUSH, UNLOAD_VERSION | UNLOAD_OUTFLAGS);
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

Saturday, June 16, 2012 11:38 PM

tf_fclose(f);
} else {
log_perror("DMP", "FAIL", "Opening killed file",
tmpfile);
}
break;
default:
db_write();
}
/* Call modules to write to DBM */
db_lock();
CALL_ALL_MODULES(db_write, ());
db_unlock();
/* Call modules to write to their flat-text database */

WALK_ALL_MODULES(mp) {
if (mp->dump_database) {
f = db_module_flatfile(mp->modname, 1);
if (f) {
(*(mp->dump_database))(f);
tf_fclose(f);
}
}
}

void NDECL(dump_database)
{
mudstate.epoch++;
mudstate.dumping = 1;
STARTLOG(LOG_DBSAVES, "DMP", "DUMP")
log_printf("Dumping: %s.#%d#",
mudconf.gdbm, mudstate.epoch);
ENDLOG
pcache_sync();
SYNC;
dump_database_internal(DUMP_DB_NORMAL);
STARTLOG(LOG_DBSAVES, "DMP", "DONE")
log_printf("Dump complete: %s.#%d#",
mudconf.gdbm, mudstate.epoch);
ENDLOG
mudstate.dumping = 0;
}
void fork_and_dump(key)
int key;
{
if (*mudconf.dump_msg)
raw_broadcast(0, "%s", mudconf.dump_msg);

-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

Saturday, June 16, 2012 11:38 PM

mudstate.epoch++;
mudstate.dumping = 1;
STARTLOG(LOG_DBSAVES, "DMP", "CHKPT")
if (!key || (key & DUMP_TEXT)) {
log_printf("SYNCing");
if (!key || (key & DUMP_STRUCT))
log_printf(" and ");
}
if (!key || (key & DUMP_STRUCT) || (key & DUMP_FLATFILE)) {
log_printf("Checkpointing: %s.#%d#",
mudconf.gdbm, mudstate.epoch);
}
ENDLOG
al_store();
/* Save cached modified attribute list */
if (!key || (key & DUMP_TEXT))
pcache_sync();
if (!(key & DUMP_FLATFILE)) {
SYNC;
if (mudconf.dbopt_interval &&
(mudstate.epoch % mudconf.dbopt_interval == 0)) {
OPTIMIZE;
}
}
if (!key || (key & DUMP_STRUCT) || (key & DUMP_FLATFILE)) {
if (mudconf.fork_dump) {
if (mudconf.fork_vfork) {
mudstate.dumper = vfork();
} else {
mudstate.dumper = fork();
}
} else {
mudstate.dumper = 0;
}
if (mudstate.dumper == 0) {
if (key & DUMP_FLATFILE) {
dump_database_internal(DUMP_DB_FLATFILE);
} else {
dump_database_internal(DUMP_DB_NORMAL);
}
if (mudconf.fork_dump)
_exit(0);
} else if (mudstate.dumper < 0) {
log_perror("DMP", "FORK", NULL, "fork()");
}
}
if (mudstate.dumper <= 0 || kill(mudstate.dumper, 0) == -1) {
mudstate.dumping = 0;
mudstate.dumper = 0;
}

-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375

Saturday, June 16, 2012 11:38 PM

if (*mudconf.postdump_msg)
raw_broadcast(0, "%s", mudconf.postdump_msg);

static int NDECL(load_game)


{
FILE *f;
MODULE *mp;
void (*modfunc)(FILE *);
STARTLOG(LOG_STARTUP, "INI", "LOAD")
log_printf("Loading object structures.");
ENDLOG
if (db_read() < 0) {
STARTLOG(LOG_ALWAYS, "INI", "FATAL")
log_printf("Error loading object structures." );
ENDLOG
return -1;
}
/* Call modules to load data from DBM */
CALL_ALL_MODULES_NOCACHE("db_read", (void ), ());
/* Call modules to load data from their flat-text database */
WALK_ALL_MODULES(mp) {
if ((modfunc = DLSYM(mp->handle, mp->modname, "load_database", (FILE *))) !=
NULL) {
f = db_module_flatfile(mp->modname, 0);
if (f) {
(*modfunc)(f);
tf_fclose(f);
}
}
}
STARTLOG(LOG_STARTUP, "INI", "LOAD")
log_printf("Load complete.");
ENDLOG
}

return (0);

/* match a list of things, using the no_command flag */


int list_check(thing, player, type, str, raw_str, check_parent, stop_status)
dbref thing, player;
char type, *str, *raw_str;
int check_parent, *stop_status;
{
int match;
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428

Saturday, June 16, 2012 11:38 PM

match = 0;
while (thing != NOTHING) {
if ((thing != player) &&
(atr_match(thing, player, type, str, raw_str,
check_parent) > 0)) {
match = 1;
if (Stop_Match(thing)) {
*stop_status = 1;
return match;
}
}
if (thing != Next(thing)) {
thing = Next(thing);
} else {
thing = NOTHING; /* make sure we don't infinite loop */
}
}
return match;

int Hearer(thing)
dbref thing;
{
char *as, *buff, *s;
dbref aowner;
int attr, aflags, alen;
ATTR *ap;
if (mudstate.inpipe && (thing == mudstate.poutobj))
return 1;
if (Connected(thing) || Puppet(thing) || H_Listen(thing))
return 1;
if (!Monitor(thing))
return 0;
buff = alloc_lbuf("Hearer");
atr_push();
for (attr = atr_head(thing, &as); attr; attr = atr_next(&as)) {
ap = atr_num(attr);
if (!ap || (ap->flags & AF_NOPROG))
continue;
atr_get_str(buff, thing, attr, &aowner, &aflags, &alen);
/* Make sure we can execute it */
if ((buff[0] != AMATCH_LISTEN) || (aflags & AF_NOPROG))
continue;
/* Make sure there's a : in it */
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481

Saturday, June 16, 2012 11:38 PM

for (s = buff + 1; *s && (*s != ':'); s++) ;


if (s) {
free_lbuf(buff);
atr_pop();
return 1;
}

}
free_lbuf(buff);
atr_pop();
return 0;

/* ---------------------------------------------------------------------* Write message to logfile.


*/
void do_logwrite(player, cause, key, msgtype, message)
dbref player, cause;
int key;
char *msgtype, *message;
{
const char *mt;
char *msg, *p;
/* If we don't have both a msgtype and a message, make msgtype LOCAL.
* Otherwise, truncate msgtype to five characters and capitalize.
*/
if (!message || !*message) {
mt = (const char *) "LOCAL";
msg = msgtype;
} else {
if (strlen(msgtype) > 5)
msgtype[5] = '\0';
for (p = msgtype; *p; p++)
*p = toupper(*p);
mt = (const char *) msgtype;
msg = message;
}
/* Just dump it to the log. */
STARTLOG(LOG_LOCAL, "MSG", mt)
log_name(player);
log_printf(": %s", msg);
ENDLOG
}

notify_quiet(player, "Logged.");

/* ---------------------------------------------------------------------* Log rotation.


-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534

Saturday, June 16, 2012 11:38 PM

*/
void do_logrotate(player, cause, key)
dbref player, cause;
int key;
{
LOGFILETAB *lp;
mudstate.mudlognum++;
if (mainlog_fp == stderr) {
notify(player, "Warning: can't rotate main log when logging to stderr." );
} else {
fclose(mainlog_fp);
rename(mudconf.mudlogname,
tprintf("%s.%ld", mudconf.mudlogname, (long) mudstate.now));
logfile_init(mudconf.mudlogname);
}
notify(player, "Logs rotated.");
STARTLOG(LOG_ALWAYS, "WIZ", "LOGROTATE")
log_name(player);
log_printf(": logfile rotation %d", mudstate.mudlognum);
ENDLOG
/* Any additional special ones */
for (lp = logfds_table; lp->log_flag; lp++) {
if (lp->filename && lp->fileptr) {
fclose(lp->fileptr);
rename(lp->filename,
tprintf("%s.%ld", lp->filename, (long) mudstate.now));
lp->fileptr = fopen(lp->filename, "w");
if (lp->fileptr)
setbuf(lp->fileptr, NULL);
}
}
}
/* ---------------------------------------------------------------------* Database and startup stuff.
*/
void do_readcache(player, cause, key)
dbref player, cause;
int key;
{
helpindex_load(player);
fcache_load(player);
}

-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587

Saturday, June 16, 2012 11:38 PM

static void NDECL(process_preload)


{
dbref thing, parent, aowner;
int aflags, alen, lev, i;
char *tstr;
char tbuf[SBUF_SIZE];
FWDLIST *fp;
PROPDIR *pp;
fp = (FWDLIST *) XMALLOC(sizeof(FWDLIST), "process_preload.fwdlist");
pp = (PROPDIR *) XMALLOC(sizeof(PROPDIR), "process_preload.propdir");
tstr = alloc_lbuf("process_preload.string");
i = 0;
DO_WHOLE_DB(thing) {
/* Ignore GOING objects */
if (Going(thing))
continue;
/* Look for a FORWARDLIST attribute. Load these before
* doing anything else, so startup notifications work
* correctly.
*/
if (H_Fwdlist(thing)) {
(void)atr_get_str(tstr, thing, A_FORWARDLIST,
&aowner, &aflags, &alen);
if (*tstr) {
fp->data = NULL;
fwdlist_load(fp, GOD, tstr);
if (fp->count > 0)
fwdlist_set(thing, fp);
if (fp->data) {
XFREE(fp->data,
"process_preload.fwdlist_data" );
}
}
}
/* Ditto for PROPDIRs */
if (H_Propdir(thing)) {
(void)atr_get_str(tstr, thing, A_PROPDIR,
&aowner, &aflags, &alen);
if (*tstr) {
pp->data = NULL;
propdir_load(pp, GOD, tstr);
if (pp->count > 0)
propdir_set(thing, pp);
if (pp->data) {
XFREE(pp->data,
"process_preload.propdir_data" );
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640

}
}

Saturday, June 16, 2012 11:38 PM

do_top(10);
/* Look for STARTUP and DAILY attributes on parents. */
ITER_PARENTS(thing, parent, lev) {
if (H_Startup(thing)) {
did_it(Owner(thing), thing,
A_NULL, NULL, A_NULL, NULL,
A_STARTUP, 0, (char **)NULL, 0, 0);
/* Process queue entries as we add them */

do_second();
do_top(10);
break;

ITER_PARENTS(thing, parent, lev) {


if (Flags2(thing) & HAS_DAILY) {
sprintf(tbuf, "0 %d * * *",
mudconf.events_daily_hour);
call_cron(thing, thing, A_DAILY, tbuf);
break;
}
}

}
XFREE(fp, "process_preload.fwdlist");
XFREE(pp, "process_preload.propdir");
free_lbuf(tstr);

/* --------------------------------------------------------------------------* info: display info about the file being read or written.
*/
void info(fmt, flags, ver)
int fmt, flags, ver;
{
const char *cp;
switch (fmt) {
case F_TINYMUSH:
cp = "TinyMUSH-3";
break;
case F_MUX:
cp = "TinyMUX";
break;
case F_MUSH:
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693

Saturday, June 16, 2012 11:38 PM

cp = "TinyMUSH";
break;
case F_MUSE:
cp = "TinyMUSE";
break;
case F_MUD:
cp = "TinyMUD";
break;
case F_MUCK:
cp = "TinyMUCK";
break;
default:
cp = "*unknown*";
break;
}
fprintf(mainlog_fp, "%s version %d:", cp, ver);
if (flags & V_ZONE)
fprintf(mainlog_fp, " Zone");
if (flags & V_LINK)
fprintf(mainlog_fp, " Link");
if (flags & V_GDBM)
fprintf(mainlog_fp, " GDBM");
if (flags & V_ATRNAME)
fprintf(mainlog_fp, " AtrName");
if (flags & V_ATRKEY) {
if ((fmt == F_MUSH) && (ver == 2))
fprintf(mainlog_fp, " ExtLocks");
else
fprintf(mainlog_fp, " AtrKey");
}
if (flags & V_PARENT)
fprintf(mainlog_fp, " Parent");
if (flags & V_COMM)
fprintf(mainlog_fp, " Comm");
if (flags & V_ATRMONEY)
fprintf(mainlog_fp, " AtrMoney");
if (flags & V_XFLAGS)
fprintf(mainlog_fp, " ExtFlags");
if (flags & V_3FLAGS)
fprintf(mainlog_fp, " MoreFlags");
if (flags & V_POWERS)
fprintf(mainlog_fp, " Powers");
if (flags & V_QUOTED)
fprintf(mainlog_fp, " QuotedStr");
if (flags & V_TQUOTAS)
fprintf(mainlog_fp, " TypedQuotas");
if (flags & V_TIMESTAMPS)
fprintf(mainlog_fp, " Timestamps");
if (flags & V_VISUALATTRS)
fprintf(mainlog_fp, " VisualAttrs");
fprintf(mainlog_fp, "\n");

-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734

Saturday, June 16, 2012 11:38 PM

void usage(prog)
char *prog;
{
fprintf(mainlog_fp, "Usage: %s [options] gdbm-file [< in-file] [> out-file]\n" , prog
);
fprintf(mainlog_fp, "
Available flags are:\n");
fprintf(mainlog_fp, "
-c <filename> - Config file
-C - Perform consistency
check\n");
fprintf(mainlog_fp, "
-d <path> - Data directory
-D <filename> - gdbm
database\n");
fprintf(mainlog_fp, "
-r <filename> - gdbm crash db\n" );
fprintf(mainlog_fp, "
-G - Write in gdbm format
-g - Write in flat file
format\n");
fprintf(mainlog_fp, "
-K - Store key as an attribute -k - Store key in the
header\n");
fprintf(mainlog_fp, "
-L - Include link information
-l - Don't include link
information\n");
fprintf(mainlog_fp, "
-M - Store attr map if GDBM
-m - Don't store attr
map if GDBM\n");
fprintf(mainlog_fp, "
-N - Store name as an attribute -n - Store name in the
header\n");
fprintf(mainlog_fp, "
-P - Include parent information -p - Don't include
parent information\n");
fprintf(mainlog_fp, "
-W - Write the output file b
-w - Don't write the
output file.\n");
fprintf(mainlog_fp, "
-X - Create a default GDBM db
-x - Create a default
flat file db\n");
fprintf(mainlog_fp, "
-Z - Include zone information
-z - Don't include zone
information\n");
fprintf(mainlog_fp, "
-<number> - Set output version number\n" );
}
int dbconvert(argc, argv)
int argc;
char *argv[];
{
int setflags, clrflags, ver;
int db_ver, db_format, db_flags, do_check, do_write;
int c, dbclean, errflg = 0;
char
char
char
char

*opt_conf
*opt_datadir
*opt_gdbmfile
*opt_crashfile

=
=
=
=

(char
(char
(char
(char

*)
*)
*)
*)

CONF_FILE;
DATA_DIR;
DB_FILE;
CRASH_FILE;

FILE *f;
MODULE *mp;
void (*modfunc)(FILE *);
logfile_init(NULL);
/* Decide what conversions to do and how to format the output file */

-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787

Saturday, June 16, 2012 11:38 PM

setflags = clrflags = ver = do_check = 0;


do_write = 1;
dbclean = V_DBCLEAN;
while ((c = getopt(argc, argv, "c:d:D:CqGgZzLlNnKkPpWwXx0123456789" )) != -1) {
switch (c) {
case 'c':
opt_conf = optarg;
break;
case 'd':
opt_datadir = optarg;
break;
case 'D':
opt_gdbmfile = optarg;
break;
case 'r':
opt_crashfile = optarg;
break;
case 'C':
do_check = 1;
break;
case 'q':
dbclean = 0;
break;
case 'G':
setflags |= V_GDBM;
break;
case 'g':
clrflags |= V_GDBM;
break;
case 'Z':
setflags |= V_ZONE;
break;
case 'z':
clrflags |= V_ZONE;
break;
case 'L':
setflags |= V_LINK;
break;
case 'l':
clrflags |= V_LINK;
break;
case 'N':
setflags |= V_ATRNAME;
break;
case 'n':
clrflags |= V_ATRNAME;
break;
case 'K':
setflags |= V_ATRKEY;
break;
case 'k':
clrflags |= V_ATRKEY;
-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840

Saturday, June 16, 2012 11:38 PM

break;
case 'P':
setflags |= V_PARENT;
break;
case 'p':
clrflags |= V_PARENT;
break;
case 'W':
do_write = 1;
break;
case 'w':
do_write = 0;
break;
case 'X':
clrflags = 0xffffffff;
setflags = OUTPUT_FLAGS;
ver = OUTPUT_VERSION;
break;
case 'x':
clrflags = 0xffffffff;
setflags = UNLOAD_OUTFLAGS;
ver = UNLOAD_VERSION;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
ver = ver * 10 + (c - '0');
break;
default:
errflg++;

if (errflg || optind >= argc) {


usage(argv[0]);
exit(1);
}
LTDL_SET_PRELOADED_SYMBOLS();
lt_dlinit();
pool_init(POOL_LBUF, LBUF_SIZE);
pool_init(POOL_MBUF, MBUF_SIZE);
pool_init(POOL_SBUF, SBUF_SIZE);
pool_init(POOL_BOOL, sizeof(struct boolexp));

-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892

Saturday, June 16, 2012 11:38 PM

mudconf.dbhome = XSTRDUP(opt_datadir, "argv");


mudconf.crashdb = XSTRDUP(opt_crashfile, "argv");
mudconf.gdbm = XSTRDUP(opt_gdbmfile, "argv");
cf_init();
mudstate.standalone = 1;
cf_read(opt_conf);
/* Open the gdbm file */
vattr_init();
if (init_gdbm_db(argv[optind]) < 0) {
fprintf(mainlog_fp, "Can't open GDBM file\n");
exit(1);
}
/* Lock the database */
db_lock();
/* Go do it */
if (!(setflags & V_GDBM)) {
db_read();
/* Call all modules to read from GDBM */
CALL_ALL_MODULES_NOCACHE("db_read", (void), ());
db_format = F_TINYMUSH;
db_ver = OUTPUT_VERSION;
db_flags = OUTPUT_FLAGS;
} else {
db_read_flatfile(stdin, &db_format, &db_ver, &db_flags);
/* Call modules to load their flatfiles */

WALK_ALL_MODULES(mp) {
if ((modfunc = DLSYM(mp->handle, mp->modname, "db_read_flatfile", (FILE *)))
!= NULL) {
f = db_module_flatfile(mp->modname, 0);
if (f) {
(*modfunc)(f);
tf_fclose(f);
}
}
}

fprintf(mainlog_fp, "Input: ");


info(db_format, db_flags, db_ver);
if (do_check)
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944

Saturday, June 16, 2012 11:38 PM

do_dbck(NOTHING, NOTHING, DBCK_FULL);


if (do_write) {
db_flags = (db_flags & ~clrflags) | setflags;
if (ver != 0)
db_ver = ver;
else
db_ver = 3;
fprintf(mainlog_fp, "Output: ");
info(F_TINYMUSH, db_flags, db_ver);
if (db_flags & V_GDBM) {
db_write();
/* Call all modules to write to GDBM */
db_lock();
CALL_ALL_MODULES_NOCACHE("db_write", (void), ());
db_unlock();
} else {
db_write_flatfile(stdout, F_TINYMUSH, db_ver | db_flags | dbclean);
/* Call all modules to write to flatfile */

WALK_ALL_MODULES(mp) {
if ((modfunc = DLSYM(mp->handle, mp->modname, "db_write_flatfile", (FILE
*))) != NULL) {
f = db_module_flatfile(mp->modname, 1);
if (f) {
(*modfunc)(f);
tf_fclose(f);
}
}
}

/* Unlock the database */


db_unlock();

CLOSE;
exit(0);

int main(argc, argv)


int argc;
char *argv[];
{
int mindb = 0;
CMDENT *cmdp;
int i, c;
int errflg = 0;
char *opt_logfile

= (char *) LOG_FILE;
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997

char *opt_conf
= (char
char *opt_pidfile
= (char
char *opt_bindir
= (char
char *opt_txtdir
= (char
char *opt_datadir
= (char
char *opt_gdbmfile = (char
char *opt_crashfile = (char
char *s;
MODULE *mp;
char *bp;
MODHASHES *m_htab, *hp;
MODNHASHES *m_ntab, *np;

*)
*)
*)
*)
*)
*)
*)

Saturday, June 16, 2012 11:38 PM

CONF_FILE;
PID_FILE;
BIN_DIR;
TXT_DIR;
DATA_DIR;
DB_FILE;
CRASH_FILE;

/* Try to get the binary name */


s = strrchr(argv[0], (int) '/');
if (s) {
s++;
} else {
s = argv[0];
}
/* If we are called with the name 'dbconvert', do a DB conversion
* and exit */
if (s && *s && !strcmp(s, "dbconvert")) {
dbconvert(argc, argv);
}
#if !defined(TEST_MALLOC) && defined(RAW_MEMTRACKING)
/* Do this first, before anything gets a chance to allocate memory. */
mudstate.raw_allocs = NULL;
#endif
/* Parse options */
while ((c = getopt(argc, argv, "c:l:p:b:t:d:g:k:s")) != -1) {
switch (c) {
case 'c':
opt_conf = optarg;
break;
case 'l':
opt_logfile = optarg;
break;
case 'p':
opt_pidfile = optarg;
break;
case 's':
mindb = 1;
break;
case 'b':
opt_bindir = optarg;
break;
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048

Saturday, June 16, 2012 11:38 PM

case 't':
opt_txtdir = optarg;
break;
case 'd':
opt_datadir = optarg;
break;
case 'g':
opt_gdbmfile = optarg;
break;
case 'k':
opt_crashfile = optarg;
break;
default:
errflg++;
break;
}

if (errflg) {
fprintf(stderr, "Usage: %s [-s] [-c conf_file] [-l log_file] [-p pid_file] [-d
data dir] [-g gdbm db] [-k crash db]\n" ,
argv[0]);
exit(1);
}
write_pidfile(opt_pidfile);
/* Abort if someone tried to set the number of global registers
* to something stupid. Also adjust the character table if we
* need to.
*/
if ((MAX_GLOBAL_REGS < 10) || (MAX_GLOBAL_REGS > 36)) {
fprintf(stderr,
"You have compiled TinyMUSH with MAX_GLOBAL_REGS defined to be less than 10
or more than 36. Please fix this error and recompile.\n" );
exit(1);
}
if (MAX_GLOBAL_REGS < 36) {
for (i = 0; i < 36 - MAX_GLOBAL_REGS; i++) {
qidx_chartab[90 - i] = -1;
qidx_chartab[122 - i] = -1;
}
}
logfile_init(opt_logfile);
tf_init();
LTDL_SET_PRELOADED_SYMBOLS();
lt_dlinit();
time(&mudstate.start_time);
mudstate.restart_time = mudstate.start_time;
time(&mudstate.cpu_count_from);
pool_init(POOL_LBUF, LBUF_SIZE);
pool_init(POOL_MBUF, MBUF_SIZE);
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101

Saturday, June 16, 2012 11:38 PM

pool_init(POOL_SBUF, SBUF_SIZE);
pool_init(POOL_BOOL, sizeof(struct boolexp));
pool_init(POOL_DESC, sizeof(DESC));
pool_init(POOL_QENTRY, sizeof(BQUE));
tcache_init();
pcache_init();
/* Initialize directories, crashdb and gdbm with
* values from the command line. We do it
* here so the config file can still
* override the command line for backward
* compatibility.
*/
mudconf.dbhome = XSTRDUP(opt_datadir, "argv");
mudconf.crashdb = XSTRDUP(opt_crashfile, "argv");
mudconf.gdbm = XSTRDUP(opt_gdbmfile, "argv");
mudconf.txthome = XSTRDUP(opt_txtdir, "argv");
mudconf.binhome = XSTRDUP(opt_bindir, "argv");
cf_init();
init_rlimit();
init_cmdtab();
init_logout_cmdtab();
init_flagtab();
init_powertab();
init_functab();
init_attrtab();
init_version();
hashinit(&mudstate.player_htab, 250 * HASH_FACTOR, HT_STR);
hashinit(&mudstate.nref_htab, 5 * HASH_FACTOR, HT_STR);
nhashinit(&mudstate.fwdlist_htab, 25 * HASH_FACTOR);
nhashinit(&mudstate.propdir_htab, 25 * HASH_FACTOR);
nhashinit(&mudstate.redir_htab, 5 * HASH_FACTOR);
nhashinit(&mudstate.objstack_htab, 50 * HASH_FACTOR);
nhashinit(&mudstate.parent_htab, 5 * HASH_FACTOR);
nhashinit(&mudstate.desc_htab, 25 * HASH_FACTOR);
hashinit(&mudstate.vars_htab, 250 * HASH_FACTOR, HT_STR);
hashinit(&mudstate.structs_htab, 15 * HASH_FACTOR, HT_STR);
hashinit(&mudstate.cdefs_htab, 15 * HASH_FACTOR, HT_STR);
hashinit(&mudstate.instance_htab, 15 * HASH_FACTOR, HT_STR);
hashinit(&mudstate.instdata_htab, 25 * HASH_FACTOR, HT_STR);
hashinit(&mudstate.api_func_htab, 5 * HASH_FACTOR, HT_STR);
s = (char *) XMALLOC(MBUF_SIZE, "main_add_helpfile");
sprintf(s, "help %s/help", mudconf.txthome);
add_helpfile(GOD, (char *)"main:add_helpfile", s , 1);
sprintf(s, "wizhelp %s/wizhelp", mudconf.txthome);
add_helpfile(GOD, (char *)"main:add_helpfile", s, 1);
-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154

Saturday, June 16, 2012 11:38 PM

sprintf(s, "qhelp %s/qhelp", mudconf.txthome);


add_helpfile(GOD, (char *)"main:add_helpfile", s, 1);
XFREE(s, "main_add_helpfile");
cmdp = (CMDENT *) hashfind((char *) "wizhelp", &mudstate.command_htab);
if (cmdp)
cmdp->perms |= CA_WIZARD;
vattr_init();
cf_read(opt_conf);
bp = mudstate.modloaded;
WALK_ALL_MODULES(mp) {
if (bp != mudstate.modloaded) {
safe_mb_chr(' ', mudstate.modloaded, &bp);
}
safe_mb_str(mp->modname, mudstate.modloaded, &bp);
}
mudconf.exec_path = XSTRDUP(argv[0], "argv");
mudconf.mudlogname = XSTRDUP(opt_logfile, "argv");
fcache_init();
helpindex_init();
if (mindb)
unlink(mudconf.gdbm);
if (init_gdbm_db(mudconf.gdbm) < 0) {
STARTLOG(LOG_ALWAYS, "INI", "LOAD")
log_printf("Couldn't load text database: %s" ,
mudconf.gdbm);
ENDLOG
exit(2);
}
mudstate.record_players = 0;
mudstate.loading_db = 1;
if (mindb) {
db_make_minimal();
CALL_ALL_MODULES_NOCACHE("make_minimal", (void), ());
} else if (load_game() < 0) {
STARTLOG(LOG_ALWAYS, "INI", "LOAD")
log_printf("Couldn't load objects.");
ENDLOG
exit(2);
}
mudstate.loading_db = 0;

-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207

Saturday, June 16, 2012 11:38 PM

init_genrand(getpid() | (time(NULL) << 16));


set_signals();
/* Do a consistency check and set up the freelist */
if (!Good_obj(GOD) || !isPlayer(GOD)) {
STARTLOG(LOG_ALWAYS, "CNF", "VRFY")
log_printf("Fatal error: GOD object #%d is not a valid player." ,
GOD);
ENDLOG
exit(3);
}
do_dbck(NOTHING, NOTHING, 0);
/* Reset all the hash stats */
hashreset(&mudstate.command_htab);
hashreset(&mudstate.logout_cmd_htab);
hashreset(&mudstate.func_htab);
hashreset(&mudstate.ufunc_htab);
hashreset(&mudstate.powers_htab);
hashreset(&mudstate.flags_htab);
hashreset(&mudstate.attr_name_htab);
hashreset(&mudstate.vattr_name_htab);
hashreset(&mudstate.player_htab);
hashreset(&mudstate.nref_htab);
nhashreset(&mudstate.desc_htab);
nhashreset(&mudstate.fwdlist_htab);
nhashreset(&mudstate.propdir_htab);
nhashreset(&mudstate.objstack_htab);
nhashreset(&mudstate.parent_htab);
hashreset(&mudstate.vars_htab);
hashreset(&mudstate.structs_htab);
hashreset(&mudstate.cdefs_htab);
hashreset(&mudstate.instance_htab);
hashreset(&mudstate.instdata_htab);
hashreset(&mudstate.api_func_htab);
for (i = 0; i < mudstate.helpfiles; i++)
hashreset(&mudstate.hfile_hashes[i]);
WALK_ALL_MODULES(mp) {
m_htab = DLSYM_VAR(mp->handle, mp->modname,
"hashtable", MODHASHES *);
if (m_htab) {
for (hp = m_htab; hp->tabname != NULL; hp++) {
hashreset(hp->htab);
}
}
m_ntab = DLSYM_VAR(mp->handle, mp->modname,
"nhashtable", MODNHASHES *);
if (m_ntab) {
for (np = m_ntab; np->tabname != NULL; np++) {
-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260

}
}

Saturday, June 16, 2012 11:38 PM

nhashreset(np->htab);

mudstate.now = time(NULL);
/* Initialize PCRE tables for locale. */
mudstate.retabs = pcre_maketables();
/* Go do restart things. */
load_restart_db();
if (!mudstate.restarting) {
/*
* CAUTION:
* We do this here rather than up at the top of this function
* because we need to know if we're restarting. If we are,
* our previous process closed stdout at inception,
* and therefore we don't need to do so.
* More importantly, on a restart, the file descriptor normally
* allocated to stdout could have been used for a player
* socket descriptor. Thus, closing it like a stream is
* really, really bad.
* Moreover, stdin gets closed and its descriptor reused in
* tf_init. A double fclose of stdin would be a really bad idea.
*/
fclose(stdout);
}
/* We have to do an update, even though we're starting up, because
* there may be players connected from a restart, as well as objects.
*/
CALL_ALL_MODULES_NOCACHE("cleanup_startup", (void), ());
sql_init();

/* Make a connection to external SQL db */

/* You must do your startups AFTER you load your restart database,
* or softcode that depends on knowing who is connected and so forth
* will be hosed.
*/
process_preload();
STARTLOG(LOG_STARTUP, "INI", "LOAD")
log_printf("Startup processing complete." );
ENDLOG
/* Clear all reference flags in the cache-- what happens when the game
* loads is NOT representative of normal cache behavior :) Neither is
* creating a new db, but in that case the objects exist only in the
* cache...
*/

-43-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313

Saturday, June 16, 2012 11:38 PM

if (!mindb)
cache_reset();
/* Start the DNS and identd lookup slave process */
boot_slave();
/* This must happen after startups are run, in order to get a
* really good idea of what's actually out there.
*/
do_hashresize(GOD, GOD, 0);
STARTLOG(LOG_STARTUP, "INI", "LOAD")
log_printf("Cleanup completed.");
ENDLOG
if (mudstate.restarting) {
raw_broadcast(0, "GAME: Restart finished.");
}
#ifdef MCHECK
mtrace();
#endif
/* go do it */
init_timer();
shovechars(mudconf.port);
#ifdef MCHECK
muntrace();
#endif
sql_shutdown();
/* Terminate external SQL db connection */
close_sockets(0, (char *)"Going down - Bye");
dump_database();
CLOSE;
if (slave_socket != -1) {
shutdown(slave_socket, 2);
close(slave_socket);
slave_socket = -1;
}
if (slave_pid != 0) {
kill(slave_pid, SIGKILL);
}
}

exit(0);

static void NDECL(init_rlimit)


{
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
-44-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\game.c

2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333

Saturday, June 16, 2012 11:38 PM

struct rlimit *rlp;


rlp = (struct rlimit *) XMALLOC(sizeof(struct rlimit), "rlimit");
if (getrlimit(RLIMIT_NOFILE, rlp)) {
log_perror("RLM", "FAIL", NULL, "getrlimit()");
free_lbuf(rlp);
return;
}
rlp->rlim_cur = rlp->rlim_max;
if (setrlimit(RLIMIT_NOFILE, rlp))
log_perror("RLM", "FAIL", NULL, "setrlimit()");
XFREE(rlp, "rlimit");
#else
#if defined(_SEQUENT_) && defined(NUMFDS_LIMIT)
setdtablesize(NUMFDS_LIMIT);
#endif /* Sequent and unlimiting #define'd */
#endif /* HAVE_SETRLIMIT */
}

-45-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\gdbm.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

/* gdbm.h
/*

Saturday, June 16, 2012 11:08 PM

The include file for dbm users.

*/

This file is part of GDBM, the GNU data base manager, by Philip A. Nelson.
Copyright (C) 1990, 1991, 1993 Free Software Foundation, Inc.
GDBM 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, or (at your option)
any later version.
GDBM 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 GDBM; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
You may contact the author by:
e-mail: phil@cs.wwu.edu
us-mail: Philip A. Nelson
Computer Science Department
Western Washington University
Bellingham, WA 98226

*************************************************************************/
/* Protection for multiple includes. */
#ifndef _GDBM_H_
#define _GDBM_H_
/* Parameters to gdbm_open for
can create the database. */
#define GDBM_READER 0
/*
#define GDBM_WRITER 1
/*
#define GDBM_WRCREAT 2
/*
#define GDBM_NEWDB
3
/*
#define GDBM_FAST
0x10 /*
#define GDBM_SYNC
0x20 /*
#define GDBM_NOLOCK 0x40 /*

READERS, WRITERS, and WRITERS who


A reader. */
A writer. */
A writer. Create the db if needed. */
A writer. Always create a new db. */
Write fast! => No fsyncs. OBSOLETE. */
Sync operations to the disk. */
Don't do file locking operations. */

/* Parameters to gdbm_store for simple insertion or replacement in the


case that the key is already in the database. */
#define GDBM_INSERT 0
/* Never replace old data with new. */
#define GDBM_REPLACE 1
/* Always replace old data with new. */
/* Parameters to gdbm_setopt, specifying the type of operation to perform. */
#define GDBM_CACHESIZE 1
/* Set the cache size. */
#define GDBM_FASTMODE 2
/* Toggle fast mode. OBSOLETE. */
#define GDBM_SYNCMODE 3
/* Turn on or off sync operations. */
#define GDBM_CENTFREE 4
/* Keep all free blocks in the header. */
#define GDBM_COALESCEBLKS 5
/* Attempt to coalesce free blocks. */
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\gdbm.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

/* The data and key structure.


typedef struct {
char *dptr;
int
dsize;
} datum;

Saturday, June 16, 2012 11:08 PM

This structure is defined for compatibility. */

/* The file information header. This is good enough for most applications. */
typedef struct {int dummy[10];} *GDBM_FILE;
/* Determine if the C(++) compiler requires complete function prototype
#ifndef __P
#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
#define __P(x) x
#else
#define __P(x) ()
#endif
#endif
/* External variable, the gdbm build release string. */
extern char *gdbm_version;
/* GDBM C++ support */
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/* These are the routines! */
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

GDBM_FILE gdbm_open __P((char *, int, int, int, void (*)()));


void gdbm_close __P((GDBM_FILE));
int gdbm_store __P((GDBM_FILE, datum, datum, int));
datum gdbm_fetch __P((GDBM_FILE, datum));
int gdbm_delete __P((GDBM_FILE, datum));
datum gdbm_firstkey __P((GDBM_FILE));
datum gdbm_nextkey __P((GDBM_FILE, datum));
int gdbm_reorganize __P((GDBM_FILE));
void gdbm_sync __P((GDBM_FILE));
int gdbm_exists __P((GDBM_FILE, datum));
int gdbm_setopt __P((GDBM_FILE, int, int *, int));
int gdbm_fdesc __P((GDBM_FILE));

#if defined(__cplusplus) || defined(c_plusplus)


}
#endif
#define
#define
#define
#define
#define

GDBM_NO_ERROR
0
GDBM_MALLOC_ERROR
1
GDBM_BLOCK_SIZE_ERROR
GDBM_FILE_OPEN_ERROR
GDBM_FILE_WRITE_ERROR

2
3
4
-2-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\gdbm.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

Saturday, June 16, 2012 11:08 PM

#define GDBM_FILE_SEEK_ERROR
5
#define GDBM_FILE_READ_ERROR
6
#define GDBM_BAD_MAGIC_NUMBER
7
#define GDBM_EMPTY_DATABASE 8
#define GDBM_CANT_BE_READER 9
#define GDBM_CANT_BE_WRITER 10
#define GDBM_READER_CANT_DELETE 11
#define GDBM_READER_CANT_STORE 12
#define GDBM_READER_CANT_REORGANIZE 13
#define GDBM_UNKNOWN_UPDATE 14
#define GDBM_ITEM_NOT_FOUND 15
#define GDBM_REORGANIZE_FAILED 16
#define GDBM_CANNOT_REPLACE 17
#define GDBM_ILLEGAL_DATA
18
#define GDBM_OPT_ALREADY_SET
19
#define GDBM_OPT_ILLEGAL
29
typedef int gdbm_error;
/* For compatibilities sake. */
extern gdbm_error gdbm_errno;
/* extra prototypes */
/* GDBM C++ support */
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
extern char *gdbm_strerror __P((gdbm_error));
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\getpagesize.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Saturday, June 16, 2012 11:08 PM

/* Emulate getpagesize on systems that lack it.


#ifndef HAVE_GETPAGESIZE
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _SC_PAGESIZE
#define getpagesize() sysconf(_SC_PAGESIZE)
#else
#include <sys/param.h>
#ifdef EXEC_PAGESIZE
#define getpagesize() EXEC_PAGESIZE
#else
#ifdef NBPG
#define getpagesize() NBPG * CLSIZE
#ifndef CLSIZE
#define CLSIZE 1
#endif /* no CLSIZE */
#else /* no NBPG */
#ifdef PAGESIZE
#define getpagesize() PAGESIZE
#else /* no PAGESIZE */
#ifdef NBPC
#define getpagesize() NBPC
#endif
#endif /* PAGESIZE */
#endif /* no NBPG */
#endif /* no EXEC_PAGESIZE */
#endif /* no _SC_PAGESIZE */
#endif /* not HAVE_GETPAGESIZE */

-1-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\help.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:37 PM

/* help.c - commands for giving help */


/* $Id: help.c,v 1.31 2004/02/23 04:35:14 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "help.h"

/* required by code */

int helpindex_read(htab, filename)


HASHTAB *htab;
char *filename;
{
help_indx entry;
char *p;
int count;
FILE *fp;
struct help_entry *htab_entry;
/* Let's clean out our hash table, before we throw it away. */
for (p = hash_firstkey(htab); p; p = hash_nextkey(htab)) {
if (!(hashfindflags(p, htab) & HASH_ALIAS)) {
htab_entry = (struct help_entry *)hashfind(p, htab);
XFREE(htab_entry, "helpindex_read.hent0");
}
}
hashflush(htab, 0);
if ((fp = tf_fopen(filename, O_RDONLY)) == NULL) {
STARTLOG(LOG_PROBLEMS, "HLP", "RINDX")
log_printf("Can't open %s for reading.", filename);
ENDLOG
return -1;
}
count = 0;
while ((fread((char *)&entry, sizeof(help_indx), 1, fp)) == 1) {
/* Lowercase the entry and add all leftmost substrings.
* Substrings already added will be rejected by hashadd.
*/
for (p = entry.topic; *p; p++)
*p = tolower(*p);
htab_entry = (struct help_entry *)XMALLOC(sizeof(struct help_entry),
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\help.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:37 PM

"helpindex_read.hent1");
htab_entry->pos = entry.pos;
htab_entry->len = entry.len;
if (hashadd(entry.topic, (int *)htab_entry, htab, 0) == 0) {
count++;
while (p > (entry.topic + 1)) {
p--;
*p = '\0';
if (!isspace(*(p-1))) {
if (hashadd(entry.topic, (int *)htab_entry, htab, HASH_ALIAS) == 0) {
count++;
} else {
/* It didn't make it into the hash
* table
*/
break;
}
}
}
} else {
STARTLOG(LOG_ALWAYS, "HLP", "RINDX")
log_printf("Topic already exists: %s",
entry.topic);
ENDLOG
XFREE(htab_entry, "helpindex_read.hent1");
}

}
tf_fclose(fp);
hashreset(htab);
return count;

void helpindex_load(player)
dbref player;
{
int i;
char buf[SBUF_SIZE + 8];
if (!mudstate.hfiletab) {
if ((player != NOTHING) && !Quiet(player))
notify(player, "No indexed files have been configured." );
return;
}
for (i = 0; i < mudstate.helpfiles; i++) {
sprintf(buf, "%s.indx", mudstate.hfiletab[i]);
helpindex_read(&mudstate.hfile_hashes[i], buf);
}
if ((player != NOTHING) && !Quiet(player))
notify(player, "Indexed file cache updated." );
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\help.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:37 PM

}
void NDECL(helpindex_init)
{
/* We do not need to do hashinits here, as this will already have
* been done by the add_helpfile() calls.
*/
}

helpindex_load(NOTHING);

void help_write(player, topic, htab, filename, eval)


dbref player;
char *topic, *filename;
HASHTAB *htab;
int eval;
{
FILE *fp;
char *p, *line, *result, *str, *bp;
int entry_offset, entry_length;
struct help_entry *htab_entry;
char matched;
char *topic_list, *buffp;
if (*topic == '\0')
topic = (char *)"help";
else
for (p = topic; *p; p++)
*p = tolower(*p);
htab_entry = (struct help_entry *)hashfind(topic, htab);
if (htab_entry) {
entry_offset = htab_entry->pos;
entry_length = htab_entry->len;
} else if (strpbrk(topic, "*?\\")) {
matched = 0;
for (result = hash_firstkey(htab); result != NULL;
result = hash_nextkey(htab)) {
if (!(hashfindflags(result, htab) & HASH_ALIAS) &&
quick_wild(topic, result)) {
if (matched == 0) {
matched = 1;
topic_list = alloc_lbuf("help_write");
buffp = topic_list;
}
safe_str(result, topic_list, &buffp);
safe_chr(' ', topic_list, &buffp);
safe_chr(' ', topic_list, &buffp);
}
}
if (matched == 0)
notify(player, tprintf("No entry for '%s'.", topic));
else {
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\help.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:37 PM

notify(player, tprintf("Here are the entries which match '%s':" , topic));


*buffp = '\0';
notify(player, topic_list);
free_lbuf(topic_list);

}
return;
} else {
notify(player, tprintf("No entry for '%s'.", topic));
return;
}
if ((fp = tf_fopen(filename, O_RDONLY)) == NULL) {
notify(player,
"Sorry, that function is temporarily unavailable." );
STARTLOG(LOG_PROBLEMS, "HLP", "OPEN")
log_printf("Can't open %s for reading.", filename);
ENDLOG
return;
}
if (fseek(fp, entry_offset, 0) < 0L) {
notify(player,
"Sorry, that function is temporarily unavailable." );
STARTLOG(LOG_PROBLEMS, "HLP", "SEEK")
log_printf("Seek error in file %s.", filename);
ENDLOG
tf_fclose(fp);
return;
}
line = alloc_lbuf("help_write");
if (eval) {
result = alloc_lbuf("help_write.2");
}
for (;;) {
if (fgets(line, LBUF_SIZE - 1, fp) == NULL)
break;
if (line[0] == '&')
break;
for (p = line; *p != '\0'; p++)
if (*p == '\n')
*p = '\0';
if (eval) {
str = line;
bp = result;
exec(result, &bp, 0, player, player,
EV_NO_COMPRESS | EV_FIGNORE | EV_EVAL, &str,
(char **)NULL, 0);
notify(player, result);
} else
notify(player, line);
}
tf_fclose(fp);
free_lbuf(line);
if (eval) {
free_lbuf(result);
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\help.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:37 PM

/* --------------------------------------------------------------------------* help_helper: Write entry into a buffer for a function.


*/
void help_helper(player, hf_num, eval, topic, buff, bufc)
dbref player;
int hf_num, eval;
char *topic, *buff, **bufc;
{
char tbuf[SBUF_SIZE + 8];
char tname[LBUF_SIZE];
char *p, *q, *line, *result, *str, *bp;
struct help_entry *htab_entry;
int entry_offset, entry_length, count;
FILE *fp;
if (hf_num >= mudstate.helpfiles) {
STARTLOG(LOG_BUGS, "BUG", "HELP")
log_printf("Unknown help file number: %d" , hf_num);
ENDLOG
safe_str((char *) "#-1 NOT FOUND", buff, bufc);
return;
}
if (!topic || !*topic) {
strcpy(tname, (char *) "help");
} else {
for (p = topic, q = tname; *p; p++, q++)
*q = tolower(*p);
*q = '\0';
}
htab_entry = (struct help_entry *) hashfind(tname,
&mudstate.hfile_hashes[hf_num]);
if (!htab_entry) {
safe_str((char *) "#-1 NOT FOUND", buff, bufc);
return;
}
entry_offset = htab_entry->pos;
entry_length = htab_entry->len;
sprintf(tbuf, "%s.txt", mudstate.hfiletab[hf_num]);
if ((fp = tf_fopen(tbuf, O_RDONLY)) == NULL) {
STARTLOG(LOG_PROBLEMS, "HLP", "OPEN")
log_printf("Can't open %s for reading.", tbuf);
ENDLOG
safe_str((char *) "#-1 ERROR", buff, bufc);
return;
}
if (fseek(fp, entry_offset, 0) < 0L) {
STARTLOG(LOG_PROBLEMS, "HLP", "SEEK")
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\help.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:37 PM

log_printf("Seek error in file %s.", tbuf);


ENDLOG
tf_fclose(fp);
safe_str((char *) "#-1 ERROR", buff, bufc);
return;
}

line = alloc_lbuf("help_helper");
if (eval) {
result = alloc_lbuf("help_helper.2");
}
count = 0;
for (;;) {
if (fgets(line, LBUF_SIZE - 1, fp) == NULL)
break;
if (line[0] == '&')
break;
for (p = line; *p != '\0'; p++)
if (*p == '\n')
*p = '\0';
if (count > 0) {
safe_crlf(buff, bufc);
}
if (eval) {
str = line;
bp = result;
exec(result, &bp, 0, player, player,
EV_NO_COMPRESS | EV_FIGNORE | EV_EVAL, &str,
(char **)NULL, 0);
safe_str(result, buff, bufc);
} else {
safe_str(line, buff, bufc);
}
count++;
}
tf_fclose(fp);
free_lbuf(line);
if (eval) {
free_lbuf(result);
}

/* --------------------------------------------------------------------------* do_help: display information from new-format news and help files
*/
void do_help(player, cause, key, message)
dbref player, cause;
int key;
char *message;
{
char tbuf[SBUF_SIZE + 8];
int hf_num;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\help.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

Saturday, June 16, 2012 11:37 PM

hf_num = key & ~HELP_RAWHELP;


if (hf_num >= mudstate.helpfiles) {
STARTLOG(LOG_BUGS, "BUG", "HELP")
log_printf("Unknown help file number: %d" , hf_num);
ENDLOG
notify(player, "No such indexed file found." );
return;
}

sprintf(tbuf, "%s.txt", mudstate.hfiletab[hf_num]);


help_write(player, message, &mudstate.hfile_hashes[hf_num], tbuf,
(key & HELP_RAWHELP) ? 0 : 1);

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\help.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Saturday, June 16, 2012 11:08 PM

/* help.h */
/* $Id: help.h,v 1.6 2001/01/27 22:22:07 dpassmor Exp $ */
#include "copyright.h"
#ifndef __HELP_H
#define __HELP_H
#define

LINE_SIZE

#define

TOPIC_NAME_LEN

90
30

typedef struct {
long pos;
/* index into help file */
int len;
/* length of help entry */
char topic[TOPIC_NAME_LEN + 1];
/* topic of help entry */
} help_indx;
/* Pointers to this struct is what gets stored in the help_htab's */
struct help_entry {
int pos;
/* Position, copied from help_indx */
int len;
/* Length of entry, copied from help_indx */
};
#endif /* __HELP_H */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:37 PM

/* htab.c - table hashing routines */


/* $Id: htab.c,v 1.27 2002/10/20 18:26:43 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
/* --------------------------------------------------------------------------* hashval: Compute hash value of a string for a hash table.
*/
int hashval(str, hashmask)
char *str;
int hashmask;
{
int hash = 0;
char *sp;
/* If the string pointer is null, return 0. If not, add up the
* numeric value of all the characters and return the sum,
* modulo the size of the hash table.
*/

if (str == NULL)
return 0;
for (sp = str; *sp; sp++)
hash = (hash << 5) + hash + *sp;
return (hash & hashmask);

/* ---------------------------------------------------------------------* get_hashmask: Get hash mask for mask-style hashing.


*/
int get_hashmask(size)
int *size;
{
int tsize;
/* Get next power-of-two >= size, return power-1 as the mask for
* ANDing
*/
for (tsize = 1; tsize < *size; tsize = tsize << 1) ;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:37 PM

*size = tsize;
return tsize - 1;

/* --------------------------------------------------------------------------* hashinit: Initialize a new hash table.


*/
void hashinit(htab, size, flags)
HASHTAB *htab;
int size, flags;
{
int i;
htab->mask = get_hashmask(&size);
htab->hashsize = size;
htab->checks = 0;
htab->scans = 0;
htab->max_scan = 0;
htab->hits = 0;
htab->entries = 0;
htab->deletes = 0;
htab->nulls = size;
if ((flags & HT_TYPEMASK) == HT_NUM) {
/* Numeric hashtabs implicitly store keys by reference */
flags |= HT_KEYREF;
}
htab->flags = flags;
htab->entry = (HASHENT **) XCALLOC(size, sizeof(HASHENT *),
"hashinit");

for (i = 0; i < size; i++)


htab->entry[i] = NULL;

/* --------------------------------------------------------------------------* hashreset: Reset hash table stats.


*/
void hashreset(htab)
HASHTAB *htab;
{
htab->checks = 0;
htab->scans = 0;
htab->hits = 0;
}
/* --------------------------------------------------------------------------* hashfind_generic: Look up an entry in a hash table and return a pointer
* to its hash data. Works for both string and numeric hash tables.
*/
int *hashfind_generic(key, htab)
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:37 PM

HASHKEY key;
HASHTAB *htab;
{
int htype, hval, numchecks;
HASHENT *hptr, *prev;
numchecks = 0;
htab->scans++;
htype = htab->flags & HT_TYPEMASK;
if (htype == HT_STR) {
hval = hashval(key.s, htab->mask);
} else {
hval = (key.i & htab->mask);
}
for (prev = hptr = htab->entry[hval]; hptr != NULL; hptr = hptr->next) {
numchecks++;
if ((htype == HT_STR && strcmp(key.s, hptr->target.s) == 0) ||
(htype == HT_NUM && key.i == hptr->target.i)) {
htab->hits++;
if (numchecks > htab->max_scan)
htab->max_scan = numchecks;
htab->checks += numchecks;
return hptr->data;

}
prev = hptr;

}
if (numchecks > htab->max_scan)
htab->max_scan = numchecks;
htab->checks += numchecks;
return NULL;

/* --------------------------------------------------------------------------* hashfindflags_generic: Look up an entry in a hash table and return


* its flags. Works for both string and numeric hash tables.
*/
int hashfindflags_generic(key, htab)
HASHKEY key;
HASHTAB *htab;
{
int htype, hval, numchecks;
HASHENT *hptr, *prev;
numchecks = 0;
htab->scans++;
htype = htab->flags & HT_TYPEMASK;
if (htype == HT_STR) {
hval = hashval(key.s, htab->mask);
} else {
hval = (key.i & htab->mask);
}
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:37 PM

for (prev = hptr = htab->entry[hval]; hptr != NULL; hptr = hptr->next) {


numchecks++;
if ((htype == HT_STR && strcmp(key.s, hptr->target.s) == 0) ||
(htype == HT_NUM && key.i == hptr->target.i)) {
htab->hits++;
if (numchecks > htab->max_scan)
htab->max_scan = numchecks;
htab->checks += numchecks;
return hptr->flags;

}
prev = hptr;

}
if (numchecks > htab->max_scan)
htab->max_scan = numchecks;
htab->checks += numchecks;
return 0;

/* --------------------------------------------------------------------------* hashadd_generic: Add a new entry to a hash table. Works for both string
* and numeric hashtables.
*/
int hashadd_generic(key, hashdata, htab, flags)
HASHKEY key;
int *hashdata;
HASHTAB *htab;
int flags;
{
int htype, hval;
HASHENT *hptr;
/*
* Make sure that the entry isn't already in the hash table. If it
* is, exit with an error. Otherwise, create a new hash block and
* link it in at the head of its thread.
*/
if (hashfind_generic(key, htab) != NULL)
return (-1);
htype = htab->flags & HT_TYPEMASK;
if (htype == HT_STR) {
hval = hashval(key.s, htab->mask);
} else {
hval = (key.i & htab->mask);
}
htab->entries++;
if (htab->entry[hval] == NULL)
htab->nulls--;
hptr = (HASHENT *) XMALLOC(sizeof(HASHENT), "hashadd");
if (htab->flags & HT_KEYREF) {
hptr->target = key;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:37 PM

} else {
hptr->target.s = XSTRDUP(key.s, "hashadd.target");
}
hptr->data = hashdata;
hptr->flags = flags;
hptr->next = htab->entry[hval];
htab->entry[hval] = hptr;
return (0);

/* --------------------------------------------------------------------------* hashdelete_generic: Remove an entry from a hash table. Works for both
* string and numeric hashtables.
*/
void hashdelete_generic(key, htab)
HASHKEY key;
HASHTAB *htab;
{
int htype, hval;
HASHENT *hptr, *last;

htype = htab->flags & HT_TYPEMASK;


if (htype == HT_STR) {
hval = hashval(key.s, htab->mask);
} else {
hval = (key.i & htab->mask);
}
last = NULL;
for (hptr = htab->entry[hval];
hptr != NULL;
last = hptr, hptr = hptr->next) {
if ((htype == HT_STR && strcmp(key.s, hptr->target.s) == 0) ||
(htype == HT_NUM && key.i == hptr->target.i)) {
if (last == NULL)
htab->entry[hval] = hptr->next;
else
last->next = hptr->next;
if (!(htab->flags & HT_KEYREF)) {
XFREE(hptr->target.s, "hashdelete.target");
}
XFREE(hptr, "hashdelete.hptr");
htab->deletes++;
htab->entries--;
if (htab->entry[hval] == NULL)
htab->nulls++;
return;
}
}

void hashdelall(old, htab)


int *old;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:37 PM

HASHTAB *htab;
{
int hval;
HASHENT *hptr, *prev, *nextp;

for (hval = 0; hval < htab->hashsize; hval++) {


prev = NULL;
for (hptr = htab->entry[hval];
hptr != NULL;
hptr = nextp) {
nextp = hptr->next;
if (hptr->data == old) {
if (prev == NULL)
htab->entry[hval] = nextp;
else
prev->next = nextp;
if (!(htab->flags & HT_KEYREF)) {
XFREE(hptr->target.s, "hashdelall.target");
}
XFREE(hptr, "hashdelall.hptr");
htab->deletes++;
htab->entries--;
if (htab->entry[hval] == NULL)
htab->nulls++;
continue;
}
prev = hptr;
}
}

/* --------------------------------------------------------------------------* hashflush: free all the entries in a hashtable.


*/
void hashflush(htab, size)
HASHTAB *htab;
int size;
{
HASHENT *hent, *thent;
int i;
for (i = 0; i < htab->hashsize; i++) {
hent = htab->entry[i];
while (hent != NULL) {
thent = hent;
hent = hent->next;
if (!(htab->flags & HT_KEYREF)) {
XFREE(thent->target.s, "hashflush.target");
}
XFREE(thent, "hashflush.hent");
}
htab->entry[i] = NULL;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:37 PM

}
/* Resize if needed.

Otherwise, just zero all the stats */

if ((size > 0) && (size != htab->hashsize)) {


XFREE(htab->entry, "hashflush.table");
hashinit(htab, size, htab->flags);
} else {
htab->checks = 0;
htab->scans = 0;
htab->max_scan = 0;
htab->hits = 0;
htab->entries = 0;
htab->deletes = 0;
htab->nulls = htab->hashsize;
}

/* --------------------------------------------------------------------------* hashrepl_generic: replace the data part of a hash entry. Works for both
* string and numeric hashtables.
*/
int hashrepl_generic(key, hashdata, htab)
HASHKEY key;
int *hashdata;
HASHTAB *htab;
{
HASHENT *hptr;
int htype, hval;

htype = htab->flags & HT_TYPEMASK;


if (htype == HT_STR) {
hval = hashval(key.s, htab->mask);
} else {
hval = (key.i & htab->mask);
}
for (hptr = htab->entry[hval];
hptr != NULL;
hptr = hptr->next) {
if ((htype == HT_STR && strcmp(key.s, hptr->target.s) == 0) ||
(htype == HT_NUM && key.i == hptr->target.i)) {
hptr->data = hashdata;
return 1;
}
}
return 0;

void hashreplall(old, new, htab)


int *old, *new;
HASHTAB *htab;
{
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:37 PM

int hval;
HASHENT *hptr;

for (hval = 0; hval < htab->hashsize; hval++)


for (hptr = htab->entry[hval]; hptr != NULL; hptr = hptr->next) {
if (hptr->data == old)
hptr->data = new;
}

/* --------------------------------------------------------------------------* hashinfo: return an mbuf with hashing stats


*/
char *hashinfo(tab_name, htab)
const char *tab_name;
HASHTAB *htab;
{
char *buff;

buff = alloc_mbuf("hashinfo");
sprintf(buff, "%-15s %5d%8d%8d%8d%8d%8d%8d%8d" ,
tab_name, htab->hashsize, htab->entries, htab->deletes,
htab->nulls, htab->scans, htab->hits, htab->checks,
htab->max_scan);
return buff;

/* Returns the data for the first hash entry in 'htab'. */


int *hash_firstentry(htab)
HASHTAB *htab;
{
int hval;

for (hval = 0; hval < htab->hashsize; hval++)


if (htab->entry[hval] != NULL) {
htab->last_hval = hval;
htab->last_entry = htab->entry[hval];
return htab->entry[hval]->data;
}
return NULL;

int *hash_nextentry(htab)
HASHTAB *htab;
{
int hval;
HASHENT *hptr;
hval = htab->last_hval;
hptr = htab->last_entry;
if (hptr->next != NULL) {

/* We can stay in the same chain */


-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:37 PM

htab->last_entry = hptr->next;
return hptr->next->data;

}
/* We were at the end of the previous chain, go to the next one */
hval++;
while (hval < htab->hashsize) {
if (htab->entry[hval] != NULL) {
htab->last_hval = hval;
htab->last_entry = htab->entry[hval];
return htab->entry[hval]->data;
}
hval++;
}
return NULL;

/* Returns the key for the first hash entry in 'htab'. */


HASHKEY hash_firstkey_generic(htab)
HASHTAB *htab;
{
int hval;
for (hval = 0; hval < htab->hashsize; hval++)
if (htab->entry[hval] != NULL) {
htab->last_hval = hval;
htab->last_entry = htab->entry[hval];
return htab->entry[hval]->target;
}

if ((htab->flags & HT_TYPEMASK) == HT_STR) {


return (HASHKEY) ((char *) NULL);
} else {
return (HASHKEY) ((int) -1);
}

HASHKEY hash_nextkey_generic(htab)
HASHTAB *htab;
{
int hval;
HASHENT *hptr;
hval = htab->last_hval;
hptr = htab->last_entry;
if (hptr->next != NULL) {
/* We can stay in the same chain */
htab->last_entry = hptr->next;
return hptr->next->target;
}
/* We were at the end of the previous chain, go to the next one */
hval++;
while (hval < htab->hashsize) {
if (htab->entry[hval] != NULL) {
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:37 PM

htab->last_hval = hval;
htab->last_entry = htab->entry[hval];
return htab->entry[hval]->target;

}
hval++;

if ((htab->flags & HT_TYPEMASK) == HT_STR) {


return (HASHKEY) ((char *) NULL);
} else {
return (HASHKEY) ((int) -1);
}

/* --------------------------------------------------------------------------* hashresize: Resize a hash table, to adjust the number of slots to be


* a power of 2 appropriate to the number of entries in it.
*/
void hashresize(htab, min_size)
HASHTAB *htab;
int min_size;
{
int size, i, htype, hval;
HASHTAB new_htab;
HASHENT *hent, *thent;
size = (htab->entries) * HASH_FACTOR;
size = (size < min_size) ? min_size : size;
get_hashmask(&size);
if ((size > 512) && (size > htab->entries * 1.33 * HASH_FACTOR))
size /= 2;
if (size == htab->hashsize) {
/* We're already at the correct size. Don't do anything. */
return;
}
hashinit(&new_htab, size, htab->flags);
htype = htab->flags & HT_TYPEMASK;
for (i = 0; i < htab->hashsize; i++) {
hent = htab->entry[i];
while (hent != NULL) {
thent = hent;
hent = hent->next;
/* don't free and reallocate entries, just copy the pointers */
if (htype == HT_STR) {
hval = hashval(thent->target.s, new_htab.mask);
} else {
hval = (thent->target.i & new_htab.mask);
}
if (new_htab.entry[hval] == NULL)
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:37 PM

new_htab.nulls--;
thent->next = new_htab.entry[hval];
new_htab.entry[hval] = thent;

}
}
XFREE(htab->entry, "hashinit");

htab->hashsize = new_htab.hashsize;
htab->mask = new_htab.mask;
htab->checks = new_htab.checks;
htab->scans = new_htab.scans;
htab->max_scan = new_htab.max_scan;
htab->hits = new_htab.hits;
htab->deletes = new_htab.deletes;
htab->nulls = new_htab.nulls;
htab->entry = new_htab.entry;
htab->last_hval = new_htab.last_hval;
htab->last_entry = new_htab.last_entry;
/* number of entries doesn't change */
/* flags don't change */

/* --------------------------------------------------------------------------* search_nametab: Search a name table for a match and return the flag value.
*/
int search_nametab(player, ntab, flagname)
dbref player;
NAMETAB *ntab;
char *flagname;
{
NAMETAB *nt;

for (nt = ntab; nt->name; nt++) {


if (minmatch(flagname, nt->name, nt->minlen)) {
if (check_access(player, nt->perm)) {
return nt->flag;
} else
return -2;
}
}
return -1;

/* --------------------------------------------------------------------------* find_nametab_ent: Search a name table for a match and return a pointer to it.
*/
NAMETAB *find_nametab_ent(player, ntab, flagname)
dbref player;
NAMETAB *ntab;
char *flagname;
{
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:37 PM

NAMETAB *nt;

for (nt = ntab; nt->name; nt++) {


if (minmatch(flagname, nt->name, nt->minlen)) {
if (check_access(player, nt->perm)) {
return nt;
}
}
}
return NULL;

/* --------------------------------------------------------------------------* find_nametab_ent_flag: Search a name table for a match by flag value


* and return a pointer to it.
*/
NAMETAB *find_nametab_ent_flag(player, ntab, flag)
dbref player;
NAMETAB *ntab;
int flag;
{
NAMETAB *nt;

for (nt = ntab; nt->name; nt++) {


if (flag == nt->flag) {
if (check_access(player, nt->perm)) {
return nt;
}
}
}
return NULL;

/* --------------------------------------------------------------------------* display_nametab: Print out the names of the entries in a name table.
*/
void display_nametab(player, ntab, prefix, list_if_none)
dbref player;
NAMETAB *ntab;
char *prefix;
int list_if_none;
{
char *buf, *bp, *cp;
NAMETAB *nt;
int got_one;
buf = alloc_lbuf("display_nametab");
bp = buf;
got_one = 0;
for (cp = prefix; *cp; cp++)
*bp++ = *cp;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:37 PM

for (nt = ntab; nt->name; nt++) {


if (God(player) || check_access(player, nt->perm)) {
*bp++ = ' ';
for (cp = nt->name; *cp; cp++)
*bp++ = *cp;
got_one = 1;
}
}
*bp = '\0';
if (got_one || list_if_none)
notify(player, buf);
free_lbuf(buf);

/* --------------------------------------------------------------------------* interp_nametab: Print values for flags defined in name table.


*/
void interp_nametab(player, ntab, flagword, prefix, true_text, false_text)
dbref player;
NAMETAB *ntab;
int flagword;
char *prefix, *true_text, *false_text;
{
char *buf, *bp, *cp;
NAMETAB *nt;
buf = alloc_lbuf("interp_nametab");
bp = buf;
for (cp = prefix; *cp; cp++)
*bp++ = *cp;
nt = ntab;
while (nt->name) {
if (God(player) || check_access(player, nt->perm)) {
*bp++ = ' ';
for (cp = nt->name; *cp; cp++)
*bp++ = *cp;
*bp++ = '.';
*bp++ = '.';
*bp++ = '.';
if ((flagword & nt->flag) != 0)
cp = true_text;
else
cp = false_text;
while (*cp)
*bp++ = *cp++;
if ((++nt)->name)
*bp++ = ';';
}
}
*bp = '\0';
notify(player, buf);
free_lbuf(buf);
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:37 PM

}
/* --------------------------------------------------------------------------* listset_nametab: Print values for flags defined in name table.
*/
void listset_nametab(player, ntab, flagword, prefix, list_if_none)
dbref player;
NAMETAB *ntab;
int flagword, list_if_none;
char *prefix;
{
char *buf, *bp, *cp;
NAMETAB *nt;
int got_one;

buf = bp = alloc_lbuf("listset_nametab");
for (cp = prefix; *cp; cp++)
*bp++ = *cp;
nt = ntab;
got_one = 0;
while (nt->name) {
if (((flagword & nt->flag) != 0) &&
(God(player) || check_access(player, nt->perm))) {
*bp++ = ' ';
for (cp = nt->name; *cp; cp++)
*bp++ = *cp;
got_one = 1;
}
nt++;
}
*bp = '\0';
if (got_one || list_if_none)
notify(player, buf);
free_lbuf(buf);

/* --------------------------------------------------------------------------* cf_ntab_access: Change the access on a nametab entry.


*/
CF_HAND(cf_ntab_access)
{
NAMETAB *np;
char *ap;
for (ap = str; *ap && !isspace(*ap); ap++) ;
if (*ap)
*ap++ = '\0';
while (*ap && isspace(*ap))
ap++;
for (np = (NAMETAB *) vp; np->name; np++) {
if (minmatch(str, np->name, np->minlen)) {
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.c

743
744
745
746
747
748
749
750
751

Saturday, June 16, 2012 11:37 PM

return cf_modify_bits(&(np->perm), ap, extra,


player, cmd);

}
cf_log_notfound(player, cmd, "Entry", str);
return -1;

-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:07 PM

/* htab.h - Structures and declarations needed for table hashing */


/* $Id: htab.h,v 1.15 2002/10/20 18:26:43 rmg Exp $ */
#include "copyright.h"
#ifndef __HTAB_H
#define __HTAB_H
typedef union {
char *s;
int i;
} HASHKEY;
typedef struct hashentry HASHENT;
struct hashentry {
HASHKEY
target;
int
*data;
int
flags;
struct hashentry
*next;
};
#define NHSHENT HASHENT
typedef struct hashtable HASHTAB;
struct hashtable {
int
hashsize;
int
mask;
int
checks;
int
scans;
int
max_scan;
int
hits;
int
entries;
int
deletes;
int
nulls;
int
flags;
HASHENT
**entry;
int
last_hval; /* Used for hashfirst & hashnext. */
HASHENT
*last_entry;
/* like last_hval */
};
#define NHSHTAB HASHTAB
typedef struct mod_hashes MODHASHES;
struct mod_hashes {
char *tabname;
HASHTAB *htab;
int size_factor;
int min_size;
};
#define MODNHASHES MODHASHES
typedef struct name_table NAMETAB;
struct name_table {
char
*name;
int minlen;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

};

Saturday, June 16, 2012 11:07 PM

int perm;
int flag;

/* Hash entry flags */


#define HASH_ALIAS

0x00000001

/* This entry is just a copy */

/* Hash table flags */


#define
#define
#define
#define

HT_STR
HT_NUM
HT_TYPEMASK
HT_KEYREF

0x00000000
0x00000001
0x0000000f
0x00000010

/*
/*
/*
/*

String-keyed hashtable */
Numeric-keyed hashtable */
Reserve up to 16 key types */
Store keys by reference not copy */

extern void FDECL(hashinit, (HASHTAB *, int, int));


#define nhashinit(h,sz)
hashinit((h), (sz), HT_NUM)
extern void FDECL(hashreset, (HASHTAB *));
#define nhashreset(h)
hashreset((h))
extern int FDECL(hashval, (char *, int));
extern int FDECL(get_hashmask, (int *));
extern int FDECL(*hashfind_generic, (HASHKEY, HASHTAB *));
#define hashfind(s,h)
hashfind_generic((HASHKEY) (s), (h))
#define nhashfind(n,h)
hashfind_generic((HASHKEY) (n), (h))
extern int FDECL(hashfindflags_generic, (HASHKEY, HASHTAB *));
#define hashfindflags(s,h) hashfindflags_generic((HASHKEY) (s), (h))
extern int FDECL(hashadd_generic, (HASHKEY, int *, HASHTAB *, int));
#define hashadd(s,d,h,f)
hashadd_generic((HASHKEY) (s), (d), (h), (f))
#define nhashadd(n,d,h)
hashadd_generic((HASHKEY) (n), (d), (h), 0)
extern void FDECL(hashdelete_generic, (HASHKEY, HASHTAB *));
#define hashdelete(s,h)
hashdelete_generic((HASHKEY) (s), (h))
#define nhashdelete(n,h)
hashdelete_generic((HASHKEY) (n), (h))
extern void FDECL(hashdelall, (int *, HASHTAB *));
extern void FDECL(hashflush, (HASHTAB *, int));
#define nhashflush(h,sz)
hashflush((h), (sz))
extern int FDECL(hashrepl_generic, (HASHKEY, int *, HASHTAB *));
#define hashrepl(s,d,h)
hashrepl_generic((HASHKEY) (s), (d), (h))
#define nhashrepl(n,d,h)
hashrepl_generic((HASHKEY) (n), (d), (h))
extern void FDECL(hashreplall, (int *, int *, HASHTAB *));
extern char FDECL(*hashinfo, (const char *, HASHTAB *));
#define nhashinfo(t,h)
hashinfo((t), (h))
extern int FDECL(*hash_nextentry, (HASHTAB *htab));
extern int FDECL(*hash_firstentry, (HASHTAB *htab));
extern HASHKEY FDECL(hash_firstkey_generic, (HASHTAB *htab));
#define hash_firstkey(h)
(hash_firstkey_generic((h)).s)
extern HASHKEY FDECL(hash_nextkey_generic, (HASHTAB *htab));
#define hash_nextkey(h)
(hash_nextkey_generic((h)).s)
extern void FDECL(hashresize, (HASHTAB *, int));
#define nhashresize(h,sz)
hashresize((h), (sz))
extern int FDECL(search_nametab, (dbref, NAMETAB *, char *));
extern NAMETAB *FDECL(find_nametab_ent, (dbref, NAMETAB *, char *));
extern NAMETAB *FDECL(find_nametab_ent_flag, (dbref, NAMETAB *, int));
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\htab.h

107
108
109
110
111
112
113
114
115

Saturday, June 16, 2012 11:07 PM

extern void FDECL(display_nametab, (dbref, NAMETAB *, char *, int));


extern void FDECL(interp_nametab, (dbref, NAMETAB *, int, char *, char *,
char *));
extern void FDECL(listset_nametab, (dbref, NAMETAB *, int, char *, int));
extern NAMETAB powers_nametab[];
#endif /* __HTAB_H */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\interface.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:07 PM

/* interface.h -- network-related definitions */


/* $Id: interface.h,v 1.21 2007/10/04 22:58:20 lwl Exp $ */
#include "copyright.h"
#ifndef __INTERFACE_H
#define __INTERFACE_H
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
/* (Dis)connection reason codes */
#define
#define
#define
#define

R_GUEST
R_CREATE
R_CONNECT
R_DARK

1
2
3
4

#define
#define
#define
#define
#define
#define
#define
#define
#define

R_QUIT
5
R_TIMEOUT
6
R_BOOT
7
R_SOCKDIED 8
R_GOING_DOWN
R_BADLOGIN 10
R_GAMEDOWN 11
R_LOGOUT
12
R_GAMEFULL 13

/*
/*
/*
/*

Guest connection */
User typed 'create' */
User typed 'connect' */
User typed 'cd' */

/*
/*
/*
/*
9
/*
/*
/*
/*

User quit */
Inactivity timeout */
Victim of @boot, @toad, or @destroy */
Other end of socket closed it */
/* Game is going down */
Too many failed login attempts */
Not admitting users now */
Logged out w/o disconnecting */
Too many players logged in */

/* Logged out command table definitions */


#define
#define
#define
#define
#define
#define
#define
#define
#define

CMD_QUIT
1
CMD_WHO
2
CMD_DOING
3
CMD_PREFIX 5
CMD_SUFFIX 6
CMD_LOGOUT 7
CMD_SESSION 8
CMD_PUEBLOCLIENT 9
CMD_INFO
10

#define CMD_MASK
#define CMD_NOxFIX

0xff
0x100

extern NAMETAB logout_cmdtable[];


typedef struct cmd_block CBLK;
typedef struct cmd_block_hdr CBLKHDR;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\interface.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:07 PM

struct cmd_block_hdr {
struct cmd_block *nxt;
};
struct cmd_block {
CBLKHDR hdr;
char
cmd[LBUF_SIZE - sizeof(CBLKHDR)];
};
typedef struct text_block TBLOCK;
typedef struct text_block_hdr TBLKHDR;
struct text_block_hdr {
struct text_block *nxt;
char
*start;
char
*end;
int nchars;
};
struct text_block {
TBLKHDR hdr;
char
data[OUTPUT_BLOCK_SIZE - sizeof(TBLKHDR)];
};
typedef struct prog_data PROG;
struct prog_data {
dbref wait_cause;
GDATA *wait_data;
};
typedef struct descriptor_data DESC;
struct descriptor_data {
int descriptor;
int flags;
int retries_left;
int command_count;
int timeout;
int host_info;
char addr[51];
char username[11];
char doing[DOING_LEN];
dbref player;
int *colormap;
char *output_prefix;
char *output_suffix;
int output_size;
int output_tot;
int output_lost;
TBLOCK *output_head;
TBLOCK *output_tail;
int input_size;
int input_tot;
int input_lost;
CBLK *input_head;
CBLK *input_tail;
CBLK *raw_input;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\interface.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

};

Saturday, June 16, 2012 11:07 PM

char *raw_input_at;
time_t connected_at;
time_t last_time;
int quota;
PROG *program_data;
struct sockaddr_in address;
/* added 3/6/90 SCG */
struct descriptor_data *hashnext;
struct descriptor_data *next;
struct descriptor_data **prev;

/* flags in the flag field */


#define DS_CONNECTED
0x0001
#define DS_AUTODARK 0x0002
#define DS_PUEBLOCLIENT 0x0004

/* player is connected */
/* Wizard was auto set dark. */
/* Client is Pueblo-enhanced. */

extern DESC *descriptor_list;


#ifndef HAVE_GETTIMEOFDAY
#define get_tod(x) { (x)->tv_sec = time(NULL); (x)->tv_usec = 0; }
#else
#define get_tod(x) gettimeofday(x, NULL)
#endif
/* from the net interface */
extern
extern
extern
extern

void
void
void
void

NDECL(emergency_shutdown);
FDECL(shutdownsock, (DESC *, int));
FDECL(shovechars, (int));
NDECL(set_signals);

/* from netcommon.c */
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

struct timeval
FDECL(timeval_sub, (struct timeval, struct timeval));
int FDECL(msec_diff, (struct timeval now, struct timeval then));
struct timeval
FDECL(msec_add, (struct timeval, int));
struct timeval
FDECL(update_quotas, (struct timeval, struct timeval));
void FDECL(raw_notify, (dbref, char *));
void FDECL(raw_notify_newline, (dbref));
void FDECL(clearstrings, (DESC *));
void FDECL(queue_write, (DESC *, const char *, int));
INLINE void FDECL(queue_string, (DESC *, const char *));
void FDECL(freeqs, (DESC *));
void FDECL(welcome_user, (DESC *));
void FDECL(save_command, (DESC *, CBLK *));
void FDECL(announce_disconnect, (dbref, DESC *, const char *));
int FDECL(boot_off, (dbref, char *));
int FDECL(boot_by_port, (int, int, char *));
void NDECL(check_idle);
void NDECL(process_commands);
int FDECL(site_check, (struct in_addr, SITE *));
dbref
FDECL(find_connected_name, (dbref, char *));

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\interface.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

Saturday, June 16, 2012 11:07 PM

/* From predicates.c */
#define alloc_desc(s) (DESC *)pool_alloc(POOL_DESC,s)
#define free_desc(b) pool_free(POOL_DESC,((char **)&(b)))
#define
for
#define
for

DESC_ITER_PLAYER(p,d) \
(d=(DESC *)nhashfind((int)p,&mudstate.desc_htab);d;d=d->hashnext)
DESC_ITER_CONN(d) \
(d=descriptor_list;(d);d=(d)->next) \
if ((d)->flags & DS_CONNECTED)
#define DESC_ITER_ALL(d) \
for (d=descriptor_list;(d);d=(d)->next)
#define DESC_SAFEITER_PLAYER(p,d,n) \
for (d=(DESC *)nhashfind((int)p,&mudstate.desc_htab), \
n=((d!=NULL) ? d->hashnext : NULL); \
d; \
d=n,n=((n!=NULL) ? n->hashnext : NULL))
#define DESC_SAFEITER_CONN(d,n) \
for (d=descriptor_list,n=((d!=NULL) ? d->next : NULL); \
d; \
d=n,n=((n!=NULL) ? n->next : NULL)) \
if ((d)->flags & DS_CONNECTED)
#define DESC_SAFEITER_ALL(d,n) \
for (d=descriptor_list,n=((d!=NULL) ? d->next : NULL); \
d; \
d=n,n=((n!=NULL) ? n->next : NULL))
#endif /* __INTERFACE_H */

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\log.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Saturday, June 16, 2012 11:37 PM

/* log.c - logging routines */


/* $Id: log.c,v 1.28 2008/01/12 06:53:52 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "ansi.h"

/* required by code */

FILE *mainlog_fp;
static FILE *log_fp = NULL;
#define MUDLOGNAME (*(mudconf.mud_shortname) ? (mudconf.mud_shortname) :
(mudconf.mud_name))
/* *INDENT-OFF* */
NAMETAB logdata_nametab[] =
{(char *)"flags",
1,
{(char *)"location",
{(char *)"owner",
1,
{(char *)"timestamp",
{ NULL,
0, 0,

{
0, LOGOPT_FLAGS},
1, 0, LOGOPT_LOC},
0, LOGOPT_OWNER},
1, 0, LOGOPT_TIMESTAMP},
0}};

NAMETAB logoptions_nametab[] = {
{(char *)"accounting",
2, 0, LOG_ACCOUNTING},
{(char *)"all_commands",
2, 0, LOG_ALLCOMMANDS},
{(char *)"bad_commands",
2, 0, LOG_BADCOMMANDS},
{(char *)"buffer_alloc",
3, 0, LOG_ALLOCATE},
{(char *)"bugs",
3, 0, LOG_BUGS},
{(char *)"checkpoints",
2, 0, LOG_DBSAVES},
{(char *)"config_changes", 2, 0, LOG_CONFIGMODS},
{(char *)"create",
2, 0, LOG_PCREATES},
{(char *)"keyboard_commands",
2, 0, LOG_KBCOMMANDS},
{(char *)"killing",
1, 0, LOG_KILLS},
{(char *)"local",
3, 0, LOG_LOCAL},
{(char *)"logins",
3, 0, LOG_LOGIN},
{(char *)"network",
1, 0, LOG_NET},
{(char *)"problems",
1, 0, LOG_PROBLEMS},
{(char *)"security",
2, 0, LOG_SECURITY},
{(char *)"shouts",
2, 0, LOG_SHOUTS},
{(char *)"startup",
2, 0, LOG_STARTUP},
{(char *)"suspect_commands",
2, 0, LOG_SUSPECTCMDS},
{(char *)"time_usage",
1, 0, LOG_TIMEUSE},
{(char *)"wizard",
1, 0, LOG_WIZARD},
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\log.c

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

{ NULL,

0,

0,

Saturday, June 16, 2012 11:37 PM

0}};

LOGFILETAB logfds_table[] = {
{ LOG_ACCOUNTING,
NULL,
NULL},
{ LOG_ALLCOMMANDS, NULL,
NULL},
{ LOG_BADCOMMANDS, NULL,
NULL},
{ LOG_ALLOCATE,
NULL,
NULL},
{ LOG_BUGS,
NULL,
NULL},
{ LOG_DBSAVES,
NULL,
NULL},
{ LOG_CONFIGMODS,
NULL,
NULL},
{ LOG_PCREATES,
NULL,
NULL},
{ LOG_KBCOMMANDS,
NULL,
NULL},
{ LOG_KILLS,
NULL,
NULL},
{ LOG_LOCAL,
NULL,
NULL},
{ LOG_LOGIN,
NULL,
NULL},
{ LOG_NET,
NULL,
NULL},
{ LOG_PROBLEMS,
NULL,
NULL},
{ LOG_SECURITY,
NULL,
NULL},
{ LOG_SHOUTS,
NULL,
NULL},
{ LOG_STARTUP,
NULL,
NULL},
{ LOG_SUSPECTCMDS, NULL,
NULL},
{ LOG_TIMEUSE,
NULL,
NULL},
{ LOG_WIZARD,
NULL,
NULL},
{ 0,
NULL,
NULL}};
/* *INDENT-ON* */
/* --------------------------------------------------------------------------* logfile_init: Initialize the main logfile.
*/
void logfile_init(filename)
char *filename;
{
if (!filename) {
mainlog_fp = stderr;
return;
}
mainlog_fp = fopen(filename, "w");
if (!mainlog_fp) {
fprintf(stderr, "Could not open logfile %s for writing.\n" ,
filename);
mainlog_fp = stderr;
return;
}
}

setbuf(mainlog_fp, NULL);

/* unbuffered */

/* --------------------------------------------------------------------------* start_log: see if it is OK to log something, and if so, start writing the
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\log.c

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

Saturday, June 16, 2012 11:37 PM

* log entry.
*/
int start_log(primary, secondary, key)
const char *primary, *secondary;
int key;
{
struct tm *tp;
time_t now;
LOGFILETAB *lp;
static int last_key = 0;
if (!mudstate.standalone) {
if (mudconf.log_diversion & key) {
if (key != last_key) {
/* Try to save ourselves some lookups */
last_key = key;
for (lp = logfds_table; lp->log_flag; lp++) {
/* Though keys can be OR'd, use the first one
* matched
*/
if (lp->log_flag & key) {
log_fp = lp->fileptr;
break;
}

}
if (!log_fp)
log_fp = mainlog_fp;
}
} else {
last_key = key;
log_fp = mainlog_fp;
}
} else {
log_fp = mainlog_fp;
}
mudstate.logging++;
switch (mudstate.logging) {
case 1:
case 2:

if (!mudstate.standalone) {
/* Format the timestamp */
if ((mudconf.log_info & LOGOPT_TIMESTAMP) != 0) {
time((time_t *) (&now));
tp = localtime((time_t *) (&now));
fprintf(log_fp, "%02d%02d%02d.%02d%02d%02d ",
(tp->tm_year % 100), tp->tm_mon + 1,
tp->tm_mday, tp->tm_hour,
tp->tm_min, tp->tm_sec);
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\log.c

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

Saturday, June 16, 2012 11:37 PM

}
/* Write the header to the log */

if (secondary && *secondary)


fprintf(log_fp, "%s %3s/%-5s: ",
MUDLOGNAME, primary, secondary);
else
fprintf(log_fp, "%s %-9s: ",
MUDLOGNAME, primary);

/* If a recursive call, log it and return indicating no log */

if (mudstate.logging == 1)
return 1;
fprintf(mainlog_fp, "Recursive logging request.\r\n" );
default:
mudstate.logging--;
}
return 0;

/* --------------------------------------------------------------------------* end_log: Finish up writing a log entry


*/
void NDECL(end_log)
{
fprintf(log_fp, "\n");
fflush(log_fp);
mudstate.logging--;
}
/* --------------------------------------------------------------------------* log_perror: Write perror message to the log
*/
void log_perror(primary, secondary, extra, failing_object)
const char *primary, *secondary, *extra, *failing_object;
{
int my_errno = errno;

start_log(primary, secondary, LOG_ALWAYS);


if (extra && *extra) {
log_printf("(%s) ", extra);
}
log_printf("%s: %s", failing_object, strerror(my_errno));
end_log();

/* --------------------------------------------------------------------------* log_printf: Format text and print to the log file.


-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\log.c

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

Saturday, June 16, 2012 11:37 PM

*/
#if defined(__STDC__) && defined(STDC_HEADERS)
void log_printf(const char *format,...)
#else
void log_printf(va_alist)
va_dcl
#endif
{

va_list ap;

#if defined(__STDC__) && defined(STDC_HEADERS)


va_start(ap, format);
#else
char *format;
va_start(ap);
format = va_arg(ap, char *);
#endif
vfprintf(log_fp, format, ap);
va_end(ap);
}
void log_vprintf(format, ap)
const char *format;
va_list ap;
{
vfprintf(log_fp, format, ap);
}
/* --------------------------------------------------------------------------* log_name: write the name, db number, and flags of an object to the log.
* If the object does not own itself, append the name, db number, and flags
* of the owner.
*/
void log_name(target)
dbref target;
{
char *tp;
if (mudstate.standalone) {
fprintf(stderr, "%s(#%d)", Name(target), target);
return;
}
if ((mudconf.log_info & LOGOPT_FLAGS) != 0)
tp = unparse_object((dbref) GOD, target, 0);
else
tp = unparse_object_numonly(target);
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\log.c

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

Saturday, June 16, 2012 11:37 PM

fprintf(log_fp, "%s", strip_ansi(tp));


free_lbuf(tp);
if (((mudconf.log_info & LOGOPT_OWNER) != 0) &&
(target != Owner(target))) {
if ((mudconf.log_info & LOGOPT_FLAGS) != 0)
tp = unparse_object((dbref) GOD, Owner(target), 0);
else
tp = unparse_object_numonly(Owner(target));
fprintf(log_fp, "[%s]", strip_ansi(tp));
free_lbuf(tp);
}
return;

/* --------------------------------------------------------------------------* log_name_and_loc: Log both the name and location of an object


*/
void log_name_and_loc(player)
dbref player;
{
log_name(player);
if ((mudconf.log_info & LOGOPT_LOC) && Has_location(player)) {
log_printf(" in ");
log_name(Location(player));
}
}
char *OBJTYP(thing)
dbref thing;
{
if (!Good_dbref(thing)) {
return (char *)"??OUT-OF-RANGE??";
}
switch (Typeof(thing)) {
case TYPE_PLAYER:
return (char *)"PLAYER";
case TYPE_THING:
return (char *)"THING";
case TYPE_ROOM:
return (char *)"ROOM";
case TYPE_EXIT:
return (char *)"EXIT";
case TYPE_GARBAGE:
return (char *)"GARBAGE";
default:
return (char *)"??ILLEGAL??";
}
}
void log_type_and_name(thing)
dbref thing;
{
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\log.c

318
319
320
321

Saturday, June 16, 2012 11:37 PM

log_printf("%s ", OBJTYP(thing));


log_name(thing);

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\logwatch.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Saturday, June 16, 2012 11:36 PM

/* logwatch.c - A very basic log watcher */


/* $Id: logwatch.c,v 1.1 2004/10/12 19:42:53 tyrspace Exp $ */
#include "copyright.h"
#include "autoconf.h"
extern char *optarg;
int main(argc, argv)
int argc;
char *argv[];
{
char *searchstr = (char *) NULL;
char *logfile = (char *) NULL;
char *s = (char *) NULL;
FILE *fptr;
int c=0, delay=0, timeout=30;
long pos=0, newpos;
/* Parse the command line */
while ((c = getopt(argc, argv, "s:l:t:")) != -1) {
switch(c) {
case 's':
searchstr = optarg;
break;
case 'l':
logfile = optarg;
break;
case 't':
timeout = atoi(optarg);
if (timeout < 1) {
fprintf( stderr, "Warning - Invalid timeout specified.\n" \
"Using default value of 30 seconds\n" );
timeout = 30;
}
break;
}
}
/* Die if we don't have everything we need */
if ( (searchstr == (char *) NULL ) || (logfile == (char *) NULL ) ) {
fprintf( stderr, "Usage : %s -l <logfile> -s <searchstring> [-t <timeout>]\n" ,
argv[0]);
exit(1);
}
c = 0;
/* Open the logfile, die if we can't */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\logwatch.c

if ( (fptr = fopen(logfile, "r")) == NULL) {


fprintf( stderr, "Error - Unable to open %s.\n" , logfile);
exit(1);
}

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

Saturday, June 16, 2012 11:36 PM

s = (char *) malloc(1024);
while( c == 0 ) {
/* Find the length of the logfile */
fseek(fptr, (long) 0, SEEK_END);
newpos=ftell(fptr);
/* file grew? print the new content */
if ( newpos > pos ) {
fseek(fptr, pos, SEEK_SET);
while ( fgets(s, 1024, fptr) != NULL) {
fprintf( stdout, "%s", s);
if (strstr(s, searchstr) != NULL) {
c++;
break;
}
}
pos = ftell(fptr);
} else if(delay < timeout) {
sleep(1);
delay++;
} else {
fprintf( stderr, "Timeout - String '%s' not found in '%s'. Giving up.\n" ,
searchstr, logfile);
break;
}
}
free(s);

fclose(fptr);
exit(0);

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:36 PM

/* look.c - commands which look at things */


/* $Id: look.c,v 1.77 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include
#include

"match.h" /*
"powers.h" /*
"attrs.h" /*
"command.h"
"ansi.h"
/*

required by code */
required by code */
required by code */
/* required by code */
required by code */

static void FDECL(show_a_desc, (dbref, dbref, const char *));


extern void FDECL(ufun, (char *, char *, int, int, int, dbref, dbref));
static int did_attr(player, thing, what)
dbref player, thing;
int what;
{
/* If the attribute exists, get it, notify the player, return 1.
* If not, return 0.
*/
char *buff;

buff = master_attr(player, thing, what, NULL, 0, NULL);


if (buff) {
notify(player, buff);
free_lbuf(buff);
return 1;
}
return 0;

static void look_exits(player, loc, exit_name)


dbref player, loc;
const char *exit_name;
{
dbref thing, parent;
char *buff, *e, *buff1, *e1;
int foundany, lev, isdark;
/* make sure location has exits */
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:36 PM

if (!Good_obj(loc) || !Has_exits(loc))
return;
/* Check to see if we're formatting exits in a player-specified way. */
if (did_attr(player, loc, A_LEXITS_FMT))
return;
/* make sure there is at least one visible exit */
foundany = 0;
isdark = Darkened(player, loc);
ITER_PARENTS(loc, parent, lev) {
if (!Has_exits(parent))
continue;
DOLIST(thing, Exits(parent)) {
if (Can_See_Exit(player, thing, isdark)) {
foundany = 1;
break;
}
}
if (foundany)
break;
}
if (!foundany)
return;
/* Display the list of exit names */
notify(player, exit_name);
e = buff = alloc_lbuf("look_exits");
e1 = buff1 = alloc_lbuf("look_exits2");
ITER_PARENTS(loc, parent, lev) {
if (Transparent(loc)) {
DOLIST(thing, Exits(parent)) {
if (Can_See_Exit(player, thing, isdark)) {
e = buff;
safe_exit_name(thing, buff, &e);
if (Location(thing) == NOTHING) {
notify(player,
tprintf("%s leads nowhere.", buff));
} else if (Location(thing) == AMBIGUOUS) {
notify(player,
tprintf("%s leads somewhere.", buff));
} else if (Location(thing) == HOME) {
notify(player,
tprintf("%s leads home.", buff));
} else if (Good_obj(Location(thing))) {
notify(player, tprintf("%s leads to %s.",
buff, Name(Location(thing))));
} else {
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:36 PM

notify(player, tprintf("%s leads elsewhere.", buff));


}

}
}
} else {
DOLIST(thing, Exits(parent)) {
if (Can_See_Exit(player, thing, isdark)) {
if (buff != e)
safe_known_str((char *)" ", 2, buff, &e);
#ifdef PUEBLO_SUPPORT
if (Html(player)) {
e1 = buff1;
safe_exit_name(thing, buff1, &e1);
safe_str((char *) "<a xch_cmd=\"", buff, &e);
/* XXX Just stripping ansi isn't really enough. */
safe_str(strip_ansi(buff1), buff, &e);
safe_str((char *) "\">", buff, &e);
/* XXX The exit name needs to be HTML escaped. */
html_escape(buff1, buff, &e);
safe_str((char *) "</a>", buff, &e);
} else {
#endif
/* Append this exit to the list */
safe_exit_name(thing, buff, &e);
#ifdef PUEBLO_SUPPORT
}
#endif
}
}
}
}
#ifdef PUEBLO_SUPPORT
if (!(Transparent(loc))) {
if (Html(player)) {
safe_chr('\r', buff, &e);
safe_chr('\n', buff, &e);
*e = '\0';
notify_html(player, buff);
} else {
*e = '\0';
notify(player, buff);
}
}
#else
if (!(Transparent(loc))) {
*e = '\0';
notify(player, buff);
}
#endif /* PUEBLO_SUPPORT */
free_lbuf(buff);
free_lbuf(buff1);
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:36 PM

}
#define CONTENTS_LOCAL 0
#define CONTENTS_NESTED 1
#define CONTENTS_REMOTE 2
static void look_contents(player, loc, contents_name, style)
dbref player, loc;
const char *contents_name;
int style;
{
dbref thing;
dbref can_see_loc;
char *buff;
#ifdef PUEBLO_SUPPORT
char *html_buff, *html_cp;
char remote_num[32];
#endif
/* Check if we're formatting contents in a player-specified way. */
if (did_attr(player, loc, A_LCON_FMT, NULL))
return;
#ifdef PUEBLO_SUPPORT
html_buff = html_cp = alloc_lbuf("look_contents");
#endif
/* check to see if he can see the location */
can_see_loc = Sees_Always(player, loc);
/* check to see if there is anything there */
DOLIST(thing, Contents(loc)) {
if (Can_See(player, thing, can_see_loc)) {
/* something exists!

show him everything */

notify(player, contents_name);
DOLIST(thing, Contents(loc)) {
if (Can_See(player, thing, can_see_loc)) {
buff = unparse_object(player, thing, 1);
#ifdef PUEBLO_SUPPORT
html_cp = html_buff;
if (Html(player)) {
safe_str("<a xch_cmd=\"look ",
html_buff, &html_cp);
/* XXX Just stripping ansi isn't enough. */
switch (style) {
case CONTENTS_LOCAL:
safe_str(PureName(thing),
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

#endif

Saturday, June 16, 2012 11:36 PM

html_buff, &html_cp);
break;
case CONTENTS_NESTED:
safe_str(PureName(Location(thing)),
html_buff, &html_cp);
safe_str("'s ",
html_buff, &html_cp);
safe_str(PureName(thing),
html_buff, &html_cp);
break;
case CONTENTS_REMOTE:
sprintf(remote_num, "#%d", thing);
safe_str(remote_num,
html_buff, &html_cp);
break;
default:
break;
}
safe_str("\">", html_buff, &html_cp);
html_escape(buff, html_buff, &html_cp);
safe_str("</a>\r\n", html_buff, &html_cp);
*html_cp = 0;
notify_html(player, html_buff);
} else {

notify(player, buff);
#ifdef PUEBLO_SUPPORT
}
#endif
free_lbuf(buff);
}
}
break;

/* we're done */

}
}
#ifdef PUEBLO_SUPPORT
free_lbuf(html_buff);
#endif
}

static void pairs_print(player, atext, buff, bufc)


dbref player;
char *atext, *buff;
char **bufc;
{
int pos, depth;
char *str, *strbuf, *parenlist, *endp;
static char *colors[5] = {ANSI_MAGENTA, ANSI_GREEN, ANSI_YELLOW,
ANSI_CYAN, ANSI_BLUE};
static char *revcolors[5] = {"m53[\033", "m23[\033", "m33[\033",
"m63[\033", "m43[\033"};
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:36 PM

static char *REVERSE_NORMAL = "m0[\033";


static char *REVERSE_HIRED = "m13[\033m1[\033";
str = strip_ansi(atext);
strbuf = alloc_lbuf("fun_parenmatch");
parenlist = alloc_lbuf("fun_parenmatch");
endp = strbuf;
parenlist[0] = 0;
depth = 0;
for (pos = 0; pos < (int)strlen(str); pos++) {
switch (str[pos]) {
case '(': case '{': case '[':
if (str[pos - 1] != '\\') {
depth++;
parenlist[depth] = str[pos];
safe_str(colors[depth%5], strbuf, &endp);
safe_chr(str[pos], strbuf, &endp);
safe_ansi_normal(strbuf, &endp);
} else {
safe_chr(str[pos], strbuf, &endp);
}
break;
case ']': case '}': case ')':
/*
* ASCII hack to check for matching parens.
* Since parenlist[0] is 0, this also catches
* the too many close parens bug.
*/
if (str[pos - 1] != '\\') {
if ((parenlist[depth] & 96) == (str[pos] & 96)) {
safe_str(colors[depth%5], strbuf, &endp);
safe_chr(str[pos], strbuf, &endp);
safe_ansi_normal(strbuf, &endp);
depth--;
} else {
safe_str(ANSI_HILITE, strbuf, &endp);
safe_str(ANSI_RED, strbuf, &endp);
safe_chr(str[pos], strbuf, &endp);
safe_ansi_normal(strbuf, &endp);
*endp = '\0';
safe_str(strbuf, buff, bufc);
safe_str(str + pos + 1, buff, bufc);
free_lbuf(strbuf);
free_lbuf(parenlist);
return;
}
} else {
safe_chr(str[pos], strbuf, &endp);
}
break;
default:
safe_chr(str[pos], strbuf, &endp);
break;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:36 PM

}
}
if (depth == 0) {
*endp = '\0';
safe_str(strbuf, buff, bufc);
free_lbuf(strbuf);
free_lbuf(parenlist);
return;
}
/*
* If we reach this point there were too many left parens.
* We've gotta go back.
*/
endp = strbuf;
parenlist[0] = 0;
depth = 0;
for (pos = strlen(str) - 1; pos >= 0; pos--) {
switch (str[pos]) {
case ']': case '}': case ')':
depth++;
parenlist[depth] = str[pos];
safe_str(REVERSE_NORMAL, strbuf, &endp);
safe_chr(str[pos], strbuf, &endp);
safe_str(revcolors[depth%5], strbuf, &endp);
break;
case '(': case '{': case '[':
/*
* ASCII hack to check for matching parens.
* Since parenlist[0] is 0, this also catches
* the too many close parens bug.
*/
if ((parenlist[depth] & 96) == (str[pos] & 96)) {
safe_str(REVERSE_NORMAL, strbuf, &endp);
safe_chr(str[pos], strbuf, &endp);
safe_str(revcolors[depth%5], strbuf, &endp);
depth--;
} else {
safe_str(REVERSE_NORMAL, strbuf, &endp);
safe_chr(str[pos], strbuf, &endp);
safe_str(REVERSE_HIRED, strbuf, &endp);
str[pos] = '\0';
safe_str(str, buff, bufc);
for (endp--; endp >= strbuf; endp--)
safe_chr(*endp, buff, bufc);
**bufc = '\0';
free_lbuf(strbuf);
free_lbuf(parenlist);
return;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

}
}

Saturday, June 16, 2012 11:36 PM

}
break;
default:
safe_chr(str[pos], strbuf, &endp);
break;

/* We won't get here, but what the hell. */

for (endp--; endp >= strbuf; endp--)


safe_chr(*endp, buff, bufc);
**bufc = '\0';
free_lbuf(strbuf);
free_lbuf(parenlist);

static void pretty_format(dest, cp, p)


char *dest;
char **cp;
char *p;
{
/* Pretty-print an attribute into a buffer (assumed to be an lbuf). */
int indent_lev, i;
indent_lev = 0;
safe_crlf(dest, cp);
while (*p) {
switch (*p) {
case '\\':
/* Skip escaped chars */
safe_chr(*p, dest, cp);
p++;
safe_chr(*p, dest, cp);
if (!*p)
return; /* we're done */
break;
case '{':
safe_crlf(dest, cp);
for (i = 0; i < indent_lev; i++)
safe_str((char *) INDENT_STR, dest, cp);
safe_chr(*p, dest, cp);
safe_crlf(dest, cp);
indent_lev++;
for (i = 0; i < indent_lev; i++)
safe_str((char *) INDENT_STR, dest, cp);
while (p[1] == ' ')
p++;
break;
case '}':
if (indent_lev > 0)
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:36 PM

indent_lev--;
safe_crlf(dest, cp);
for (i = 0; i < indent_lev; i++)
safe_str((char *) INDENT_STR, dest, cp);
safe_chr(*p, dest, cp);
safe_crlf(dest, cp);
for (i = 0; i < indent_lev; i++)
safe_str((char *) INDENT_STR, dest, cp);
while (p[1] == ' ')
p++;
break;
case ';':
safe_chr(*p, dest, cp);
safe_crlf(dest, cp);
for (i = 0; i < indent_lev; i++)
safe_str((char *) INDENT_STR, dest, cp);
while (p[1] == ' ')
p++;
break;
default:
safe_chr(*p, dest, cp);
break;

}
p++;
}
if (*(*cp - 1) != '\n')
safe_crlf(dest, cp);

static void pretty_print(dest, name, text)


char *dest, *name, *text;
{
char *cp, *p, *word;
cp = dest;
p = text;
safe_str(name, dest, &cp);
/* Pretty-print contents of text into dest. */
switch (*text) {
case '$':
case '^':
/* Do: $command:<text to format>
* Nibble up the first bit then fall through to format the rest.
*/
while (*p && (*p != ':')) {
safe_chr(*p, dest, &cp);
p++;
}
/* Do the ':' */
if (*p == ':') {
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:36 PM

safe_chr(':', dest, &cp);


do {
p++;
} while (isspace(*p));
} else {
return;
}
/* FALLTHRU */
case '@':
case '&':
/* Normal formatting */
pretty_format(dest, &cp, p);
break;
case '#':
/* Special case: If the first word starts with #, there is a
* second word, and it does NOT start with a #, this is a
* @force command.
*/
word = p;
while (*word && !isspace(*word))
word++;
while (*word && isspace(*word))
word++;
if (!*word || (*word == '#')) {
/* This is a list of dbrefs, probably. Bail. */
safe_str(p, dest, &cp);
return;
}
pretty_format(dest, &cp, p);
break;

default:
/* Ordinary text */
safe_str(p, dest, &cp);
}
if ((cp - 1) && (*(cp -1) != '\n'))
safe_crlf(dest, &cp);
safe_chr('-', dest, &cp);

static void view_atr(player, thing, ap, raw_text, aowner, aflags,


skip_tag, is_special)
dbref player, thing, aowner;
int aflags, skip_tag, is_special;
ATTR *ap;
char *raw_text;
{
char *text, *buf, *bp, *name_buf, *bb_p;
char xbuf[16], gbuf[16]; /* larger than number of attr flags! */
char flag_buf[32];
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:36 PM

char *xbufp, *gbufp, *fbp;


BOOLEXP *bool;
if (ap->flags & AF_IS_LOCK) {
bool = parse_boolexp(player, raw_text, 1);
text = unparse_boolexp(player, bool);
free_boolexp(bool);
} else if (aflags & AF_STRUCTURE) {
text = replace_string(GENERIC_STRUCT_STRDELIM,
mudconf.struct_dstr,
raw_text);
} else {
text = raw_text;
}
/* If we don't control the object or own the attribute, hide the
* attr owner and flag info.
*/
if (!Controls(player, thing) && (Owner(player) != aowner)) {
if (skip_tag && (ap->number == A_DESC)) {
buf = text;
notify(player, buf);
} else {
if (is_special == 0) {
buf = tprintf("%s%s:%s %s",
ANSI_HILITE, ap->name, ANSI_NORMAL, text);
notify(player, buf);
} else if (is_special == 1) {
buf = alloc_lbuf("view_atr.pretty");
pretty_print(buf,
tprintf("%s%s:%s ",
ANSI_HILITE, ap->name, ANSI_NORMAL),
text);
notify(player, buf);
free_lbuf(buf);
} else {
buf = alloc_lbuf("view_atr.pairs");
bp = buf;
safe_tprintf_str(buf, &bp, "%s%s:%s ",
ANSI_HILITE, ap->name, ANSI_NORMAL);
pairs_print(player, text, buf, &bp);
*bp = '\0';
notify(player, buf);
free_lbuf(buf);
}
return;
}
}
/* Generate flags */
Print_Attr_Flags(aflags, xbuf, xbufp);
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:36 PM

Print_Attr_Flags(ap->flags, gbuf, gbufp);


fbp = xbuf;
if (*xbuf && *gbuf) {
sprintf(flag_buf, "%s(%s)", xbuf, gbuf);
fbp = flag_buf;
} else if (*gbuf) {
sprintf(flag_buf, "(%s)", gbuf);
fbp = flag_buf;
}
if (is_special == 1) {
if ((aowner != Owner(thing)) && (aowner != NOTHING)) {
name_buf = tprintf("%s%s [#%d%s]:%s ",
ANSI_HILITE, ap->name, aowner, fbp,
ANSI_NORMAL);
} else if (*fbp) {
name_buf = tprintf("%s%s [%s]:%s ",
ANSI_HILITE, ap->name, fbp, ANSI_NORMAL);
} else if (!skip_tag || (ap->number != A_DESC)) {
name_buf = tprintf("%s%s:%s ", ANSI_HILITE, ap->name,
ANSI_NORMAL);
} else {
name_buf = (char *) "";
buf = text;
}
buf = alloc_lbuf("view_atr.pretty_print");
pretty_print(buf, name_buf, text);
notify(player, buf);
free_lbuf(buf);
} else if (is_special == 2) {
buf = alloc_lbuf("view_atr.pairs_print");
bb_p = buf;
if ((aowner != Owner(thing)) && (aowner != NOTHING)) {
safe_tprintf_str(buf, &bb_p, "%s%s [#%d%s]:%s ",
ANSI_HILITE, ap->name, aowner, fbp,
ANSI_NORMAL);
} else if (*fbp) {
safe_tprintf_str(buf, &bb_p, "%s%s [%s]:%s ",
ANSI_HILITE, ap->name, fbp, ANSI_NORMAL);
} else if (!skip_tag || (ap->number != A_DESC)) {
safe_tprintf_str(buf, &bb_p, "%s%s:%s ",
ANSI_HILITE, ap->name, ANSI_NORMAL);
} else {
/* Just fine the way it is */
}
pairs_print(player, text, buf, &bb_p);
*bb_p = '\0';
notify(player, buf);
free_lbuf(buf);
} else {
if ((aowner != Owner(thing)) && (aowner != NOTHING)) {
buf = tprintf("%s%s [#%d%s]:%s %s",
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:36 PM

ANSI_HILITE, ap->name, aowner, fbp,


ANSI_NORMAL, text);
} else if (*fbp) {
buf = tprintf("%s%s [%s]:%s %s",
ANSI_HILITE, ap->name, fbp, ANSI_NORMAL, text);
} else if (!skip_tag || (ap->number != A_DESC)) {
buf = tprintf("%s%s:%s %s", ANSI_HILITE, ap->name,
ANSI_NORMAL, text);
} else {
buf = text;
}
notify(player, buf);

if ((aflags & AF_STRUCTURE) && text)


free_lbuf(text);

static void look_atrs1(player, thing, othing, check_exclude, hash_insert,


is_special)
dbref player, thing, othing;
int check_exclude, hash_insert, is_special;
{
dbref aowner;
int ca, aflags, alen;
ATTR *attr, *cattr;
char *as, *buf;
cattr = (ATTR *) XMALLOC(sizeof(ATTR), "look_atrs1");
for (ca = atr_head(thing, &as); ca; ca = atr_next(&as)) {
if ((ca == A_DESC) || (ca == A_LOCK))
continue;
attr = atr_num(ca);
if (!attr)
continue;
memcpy((char *)cattr, (char *)attr, sizeof(ATTR));
/* Should we exclude this attr?
* We have a couple of things we exclude:
* Attributes explicitly marked no_inherit.
* Locks. Note that UseLock is NOT, strictly speaking, an
*
inherited lock, since it's just checked when the child
*
tries to inherit $commands from the parent; the child
*
itself doesn't acquire the parent's uselock.
* Attributes already slurped by upper-level objects.
*/
if (check_exclude &&
((cattr->flags & AF_PRIVATE) ||
(cattr->flags & AF_IS_LOCK) ||
nhashfind(ca, &mudstate.parent_htab)))
continue;
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:36 PM

buf = atr_get(thing, ca, &aowner, &aflags, &alen);


if (Read_attr_all(player, othing, cattr, aowner, aflags, 1)) {
if (!(check_exclude && (aflags & AF_PRIVATE))) {
if (hash_insert)
nhashadd(ca, (int *)cattr,
&mudstate.parent_htab);
view_atr(player, thing, cattr, buf,
aowner, aflags, 0, is_special);
}

}
free_lbuf(buf);

}
XFREE(cattr, "look_atrs1");

static void look_atrs(player, thing, check_parents, is_special)


dbref player, thing;
int check_parents, is_special;
{
dbref parent;
int lev, check_exclude, hash_insert;

if (!check_parents) {
look_atrs1(player, thing, thing, 0, 0, is_special);
} else {
hash_insert = 1;
check_exclude = 0;
nhashflush(&mudstate.parent_htab, 0);
ITER_PARENTS(thing, parent, lev) {
if (!Good_obj(Parent(parent)))
hash_insert = 0;
look_atrs1(player, parent, thing,
check_exclude, hash_insert, is_special);
check_exclude = 1;
}
}

static void look_simple(player, thing, obey_terse)


dbref player, thing;
int obey_terse;
{
char *buff;
/* Only makes sense for things that can hear */
if (!Hearer(player))
return;
/* Get the name and db-number if we can examine it. */

-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:36 PM

if (Examinable(player, thing)) {
buff = unparse_object(player, thing, 1);
notify(player, buff);
free_lbuf(buff);
}
if (obey_terse && Terse(player))
did_it(player, thing, A_NULL, "You see nothing special.",
A_ODESC, NULL, A_ADESC, 0, (char **)NULL, 0,
MSG_PRESENCE);
else
#ifndef PUEBLO_SUPPORT
did_it(player, thing, A_DESC, "You see nothing special.",
A_ODESC, NULL, A_ADESC, 0, (char **) NULL, 0,
MSG_PRESENCE);
#else
show_a_desc(player, thing, "You see nothing special.");
#endif

if (!mudconf.quiet_look && (!Terse(player) || mudconf.terse_look)) {


look_atrs(player, thing, 0, 0);
}

#ifdef PUEBLO_SUPPORT
static void show_a_desc(player, loc, msg)
dbref player, loc;
const char *msg;
{
char *got2;
dbref aowner;
int aflags, alen, indent = 0;
indent = (isRoom(loc) && mudconf.indent_desc && atr_get_raw(loc, A_DESC));
if (Html(player)) {
got2 = atr_pget(loc, A_HTDESC, &aowner, &aflags, &alen);
if (*got2)
did_it(player, loc, A_HTDESC, msg, A_ODESC, NULL,
A_ADESC, 0, (char **) NULL, 0, MSG_PRESENCE);
else {
if (indent)
raw_notify_newline(player);
did_it(player, loc, A_DESC, msg, A_ODESC, NULL,
A_ADESC, 0, (char **) NULL, 0, MSG_PRESENCE);
if (indent)
raw_notify_newline(player);
}
free_lbuf(got2);
}
else {
if (indent)
raw_notify_newline(player);
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:36 PM

did_it(player, loc, A_DESC, msg, A_ODESC, NULL,


A_ADESC, 0, (char **) NULL, 0, MSG_PRESENCE);
if (indent)
raw_notify_newline(player);

}
#endif
static void show_desc(player, loc, key)
dbref player, loc;
int key;
{
char *got;
dbref aowner;
int aflags, alen, indent = 0;
indent = (isRoom(loc) && mudconf.indent_desc && atr_get_raw(loc, A_DESC));
if ((key & LK_OBEYTERSE) && Terse(player))
did_it(player, loc, A_NULL, NULL, A_ODESC, NULL,
A_ADESC, 0, (char **)NULL, 0, MSG_PRESENCE);
else if ((Typeof(loc) != TYPE_ROOM) && (key & LK_IDESC)) {
if (*(got = atr_pget(loc, A_IDESC, &aowner, &aflags, &alen)))
did_it(player, loc, A_IDESC, NULL, A_ODESC, NULL,
A_ADESC, 0, (char **)NULL, 0, MSG_PRESENCE);
else {
#ifdef PUEBLO_SUPPORT
show_a_desc(player, loc, NULL);
#else
if (indent)
raw_notify_newline(player);
did_it(player, loc, A_DESC, NULL, A_ODESC, NULL,
A_ADESC, 0, (char **) NULL, 0, MSG_PRESENCE);
if (indent)
raw_notify_newline(player);
#endif
}
free_lbuf(got);
} else {
#ifdef PUEBLO_SUPPORT
show_a_desc(player, loc, NULL);
#else
if (indent)
raw_notify_newline(player);
did_it(player, loc, A_DESC, NULL, A_ODESC, NULL, A_ADESC, 0,
(char **) NULL, 0, MSG_PRESENCE);
if (indent)
raw_notify_newline(player);
#endif
}
}
void look_in(player, loc, key)
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:36 PM

dbref player, loc;


int key;
{
int pattr, oattr, aattr, is_terse, showkey;
char *buff;
is_terse = (key & LK_OBEYTERSE) ? Terse(player) : 0;
/* Only makes sense for things that can hear */
if (!Hearer(player))
return;
#ifdef PUEBLO_SUPPORT
/* If he needs the VRML URL, send it: */
if (key & LK_SHOWVRML)
show_vrml_url(player, loc);
#endif
/* If we can't format it in a player-specified way, then show
* the name (and unparse info, if relevant). We only invoke
* the Pueblo formatting if we weren't given a @nameformat.
*/
if (!did_attr(player, loc, A_NAME_FMT)) {
buff = unparse_object(player, loc, 1);
#ifdef PUEBLO_SUPPORT
if (Html(player)) {
notify_html(player, "<center><h3>");
notify(player, buff);
notify_html(player, "</h3></center>");
} else {
notify(player, buff);
}
#else
notify(player, buff);
#endif
free_lbuf(buff);
}
if (!Good_obj(loc))
return;
/* If we went to NOTHING et al, skip the
* rest */
/* tell him the description */
showkey = 0;
if (loc == Location(player))
showkey |= LK_IDESC;
if (key & LK_OBEYTERSE)
showkey |= LK_OBEYTERSE;
show_desc(player, loc, showkey);

-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:36 PM

/* tell him the appropriate messages if he has the key */


if (Typeof(loc) == TYPE_ROOM) {
if (could_doit(player, loc, A_LOCK)) {
pattr = A_SUCC;
oattr = A_OSUCC;
aattr = A_ASUCC;
} else {
pattr = A_FAIL;
oattr = A_OFAIL;
aattr = A_AFAIL;
}
if (is_terse)
pattr = 0;
did_it(player, loc, pattr, NULL, oattr, NULL,
aattr, 0, (char **)NULL, 0, MSG_PRESENCE);
}
/* tell him the attributes, contents and exits */

if ((key & LK_SHOWATTR) && !mudconf.quiet_look && !is_terse)


look_atrs(player, loc, 0, 0);
if (!is_terse || mudconf.terse_contents)
look_contents(player, loc, "Contents:", CONTENTS_LOCAL);
if ((key & LK_SHOWEXIT) && (!is_terse || mudconf.terse_exits))
look_exits(player, loc, "Obvious exits:");

static void look_here(player, thing, key, look_key)


dbref player, thing;
int key;
int look_key;
{
if (Good_obj(thing)) {
if (key & LOOK_OUTSIDE) {
if ((isRoom(thing)) || Opaque(thing)) {
notify_quiet(player, "You can't look outside.");
return;
}
thing = Location(thing);
}
look_in(player, thing, look_key);
}
}
void do_look(player, cause, key, name)
dbref player, cause;
int key;
char *name;
{
dbref thing, loc, look_key;
look_key = LK_SHOWATTR | LK_SHOWEXIT;
if (!mudconf.terse_look)
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:36 PM

look_key |= LK_OBEYTERSE;
loc = Location(player);
if (!name || !*name) {
look_here(player, loc, key, look_key);
return;
}
/* Look for the target locally */
thing = (key & LOOK_OUTSIDE) ? loc : player;
init_match(thing, name, NOTYPE);
match_exit_with_parents();
match_neighbor();
match_possession();
if (Long_Fingers(player)) {
match_absolute();
match_player();
}
match_here();
match_me();
match_master_exit();
thing = match_result();
/* Not found locally, check possessive */
if (!Good_obj(thing)) {
thing = match_status(player,
match_possessed(player,
((key & LOOK_OUTSIDE) ? loc : player),
(char *)name, thing, 0));
}
/* First make sure that we aren't looking at our own location, since
* that gets handled a little differently.
*/
if (thing == loc) {
look_here(player, thing, key, look_key);
return;
}
/* If we found something, go handle it */
if (Good_obj(thing)) {
switch (Typeof(thing)) {
case TYPE_ROOM:
look_in(player, thing, look_key);
break;
case TYPE_THING:
case TYPE_PLAYER:
look_simple(player, thing, !mudconf.terse_look);
if (!Opaque(thing) &&
(!Terse(player) || mudconf.terse_contents)) {
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:36 PM

look_contents(player, thing, "Carrying:", CONTENTS_NESTED);


}
break;
case TYPE_EXIT:
look_simple(player, thing, !mudconf.terse_look);
if (Transparent(thing) && Good_obj(Location(thing))) {
look_key &= ~LK_SHOWATTR;
look_in(player, Location(thing), look_key);
}
break;
default:
look_simple(player, thing, !mudconf.terse_look);
}

static void debug_examine(player, thing)


dbref player, thing;
{
dbref aowner;
char *buf;
int aflags, alen, ca;
BOOLEXP *bool;
ATTR *attr;
char *as, *cp, nbuf[20];
notify(player, tprintf("Number
if (!Good_obj(thing))
return;

= %d", thing));

notify(player, tprintf("Name
= %s", Name(thing)));
notify(player, tprintf("Location= %d", Location(thing)));
notify(player, tprintf("Contents= %d", Contents(thing)));
notify(player, tprintf("Exits
= %d", Exits(thing)));
notify(player, tprintf("Link
= %d", Link(thing)));
notify(player, tprintf("Next
= %d", Next(thing)));
notify(player, tprintf("Owner
= %d", Owner(thing)));
notify(player, tprintf("Pennies = %d", Pennies(thing)));
notify(player, tprintf("Zone
= %d", Zone(thing)));
buf = flag_description(player, thing);
notify(player, tprintf("Flags
= %s", buf));
free_mbuf(buf);
buf = power_description(player, thing);
notify(player, tprintf("Powers = %s", buf));
free_mbuf(buf);
buf = atr_get(thing, A_LOCK, &aowner, &aflags, &alen);
bool = parse_boolexp(player, buf, 1);
free_lbuf(buf);
notify(player, tprintf("Lock
= %s", unparse_boolexp(player, bool)));
free_boolexp(bool);
buf = alloc_lbuf("debug_examine");
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:36 PM

cp = buf;
safe_str((char *)"Attr list: ", buf, &cp);
for (ca = atr_head(thing, &as); ca; ca = atr_next(&as)) {
attr = atr_num(ca);
if (!attr)
continue;
atr_get_info(thing, ca, &aowner, &aflags);
if (Read_attr(player, thing, attr, aowner, aflags)) {
if (attr) { /* Valid attr. */
safe_str((char *)attr->name, buf, &cp);
safe_chr(' ', buf, &cp);
} else {
ltos(nbuf, ca);
safe_str(nbuf, buf, &cp);
safe_chr(' ', buf, &cp);
}
}

}
notify(player, buf);
free_lbuf(buf);

for (ca = atr_head(thing, &as); ca; ca = atr_next(&as)) {


attr = atr_num(ca);
if (!attr)
continue;

buf = atr_get(thing, ca, &aowner, &aflags, &alen);


if (Read_attr_all(player, thing, attr, aowner, aflags, 1))
view_atr(player, thing, attr, buf, aowner, aflags,
0, 0);
free_lbuf(buf);

static void exam_wildattrs(player, thing, do_parent, is_special)


dbref player, thing;
int do_parent, is_special;
{
int atr, aflags, alen, got_any;
char *buf;
dbref aowner;
ATTR *ap;
got_any = 0;
for (atr = olist_first(); atr != NOTHING; atr = olist_next()) {
ap = atr_num(atr);
if (!ap)
continue;
if (do_parent && !(ap->flags & AF_PRIVATE))
buf = atr_pget(thing, atr, &aowner, &aflags, &alen);
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

else

Saturday, June 16, 2012 11:36 PM

buf = atr_get(thing, atr, &aowner, &aflags, &alen);

/*
* Decide if the player should see the attr:
* If obj is Examinable and has rights to see, yes.
* If a player and has rights to see, yes...
*
except if faraway, attr=DESC, and
*
remote DESC-reading is not turned on.
* If I own the attrib and have rights to see, yes...
*
except if faraway, attr=DESC, and
*
remote DESC-reading is not turned on.
*/
if (Examinable(player, thing) &&
Read_attr_all(player, thing, ap, aowner, aflags, 1)) {
got_any = 1;
view_atr(player, thing, ap, buf,
aowner, aflags, 0, is_special);
} else if ((Typeof(thing) == TYPE_PLAYER) &&
Read_attr_all(player, thing, ap,
aowner, aflags, 1)) {
got_any = 1;
if (aowner == Owner(player)) {
view_atr(player, thing, ap, buf,
aowner, aflags, 0, is_special);
} else if ((atr == A_DESC) &&
(mudconf.read_rem_desc ||
nearby(player, thing))) {
show_desc(player, thing, 0);
} else if (atr != A_DESC) {
view_atr(player, thing, ap, buf,
aowner, aflags, 0, is_special);
} else {
notify(player,
"<Too far away to get a good look>" );
}
} else if (Read_attr_all(player, thing, ap,
aowner, aflags, 1)) {
got_any = 1;
if (aowner == Owner(player)) {
view_atr(player, thing, ap, buf,
aowner, aflags, 0, is_special);
} else if ((atr == A_DESC) &&
(mudconf.read_rem_desc ||
nearby(player, thing))) {
show_desc(player, thing, 0);
} else if (nearby(player, thing)) {
view_atr(player, thing, ap, buf,
aowner, aflags, 0, is_special);
} else {
notify(player,
"<Too far away to get a good look>" );
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

Saturday, June 16, 2012 11:36 PM

}
}
free_lbuf(buf);

}
if (!got_any)
notify_quiet(player, "No matching attributes found." );

void do_examine(player, cause, key, name)


dbref player, cause;
int key;
char *name;
{
dbref thing, content, exit, aowner, loc;
char savec;
char *temp, *buf, *buf2, timebuf[32];
BOOLEXP *bool;
int control, aflags, alen, do_parent, is_special;
time_t save_access_time;
/* This command is pointless if the player can't hear. */
if (!Hearer(player))
return;
do_parent = key & EXAM_PARENT;
is_special = 0;
if (key & EXAM_PRETTY)
is_special = 1;
if (key & EXAM_PAIRS)
is_special = 2;
thing = NOTHING;
if (!name || !*name) {
if ((thing = Location(player)) == NOTHING)
return;
} else {
/* Check for obj/attr first. */
olist_push();
if (parse_attrib_wild(player, name, &thing, do_parent,
1, 0, 1)) {
exam_wildattrs(player, thing, do_parent, is_special);
olist_pop();
return;
}
olist_pop();
/* Look it up */
init_match(player, name, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
thing = noisy_match_result();
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

Saturday, June 16, 2012 11:36 PM

if (!Good_obj(thing))
return;

/* We have to save our access time, because the very act of


* trying to examine the object will have touched it.
*/
save_access_time = AccessTime(thing);
/* Check for the /debug switch */
if (key & EXAM_DEBUG) {
if (!Examinable(player, thing)) {
notify_quiet(player, NOPERM_MESSAGE);
} else {
debug_examine(player, thing);
}
return;
}
control = (Examinable(player, thing) || Link_exit(player, thing));
if (control && !(key & EXAM_OWNER)) {
buf2 = unparse_object(player, thing, 0);
notify(player, buf2);
free_lbuf(buf2);
if (mudconf.ex_flags) {
buf2 = flag_description(player, thing);
notify(player, buf2);
free_mbuf(buf2);
}
} else {
if ((key & EXAM_OWNER) ||
((key & EXAM_DEFAULT) && !mudconf.exam_public)) {
if (mudconf.read_rem_name) {
buf2 = alloc_lbuf("do_examine.pub_name");
strcpy(buf2, Name(thing));
notify(player,
tprintf("%s is owned by %s",
buf2, Name(Owner(thing))));
free_lbuf(buf2);
} else {
notify(player,
tprintf("Owned by %s",
Name(Owner(thing))));
}
return;
}
}
temp = alloc_lbuf("do_examine.info");
if (control || mudconf.read_rem_desc || nearby(player, thing)) {
temp = atr_get_str(temp, thing, A_DESC, &aowner, &aflags, &alen);
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325

Saturday, June 16, 2012 11:36 PM

if (*temp) {
if (Examinable(player, thing) ||
(aowner == Owner(player))) {
view_atr(player, thing, atr_num(A_DESC), temp,
aowner, aflags, 1, is_special);
} else {
show_desc(player, thing, 0);
}
}
} else {
notify(player, "<Too far away to get a good look>" );
}
if (control) {
/* print owner, key, and value */
savec = mudconf.many_coins[0];
mudconf.many_coins[0] =
(islower(savec) ? toupper(savec) : savec);
buf2 = atr_get(thing, A_LOCK, &aowner, &aflags, &alen);
bool = parse_boolexp(player, buf2, 1);
buf = unparse_boolexp(player, bool);
free_boolexp(bool);
strcpy(buf2, Name(Owner(thing)));
notify(player,
tprintf("Owner: %s Key: %s %s: %d", buf2, buf,
mudconf.many_coins, Pennies(thing)));
free_lbuf(buf2);
mudconf.many_coins[0] = savec;
buf2 = (char *) ctime(&save_access_time);
buf2[strlen(buf2) - 1] = '\0';
strcpy(timebuf, buf2);
buf2 = (char *) ctime(&ModTime(thing));
buf2[strlen(buf2) - 1] = '\0';
notify(player,
tprintf("Accessed: %s
Modified: %s" ,
timebuf, buf2));
/* Print the zone */
if (mudconf.have_zones) {
buf2 = unparse_object(player, Zone(thing), 0);
notify(player, tprintf("Zone: %s", buf2));
free_lbuf(buf2);
}
/* print parent */
loc = Parent(thing);
if (loc != NOTHING) {
buf2 = unparse_object(player, loc, 0);
notify(player, tprintf("Parent: %s", buf2));
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

Saturday, June 16, 2012 11:36 PM

free_lbuf(buf2);

/* Show the powers */


buf2 = power_description(player, thing);
notify(player, buf2);
free_mbuf(buf2);
}
CALL_ALL_MODULES(examine, (player, cause, thing, control, key));
if (!((key & EXAM_OWNER) || (key & EXAM_BRIEF)))
look_atrs(player, thing, do_parent, is_special);
/* show him interesting stuff */
if (control) {
/* Contents */
if (Contents(thing) != NOTHING) {
notify(player, "Contents:");
DOLIST(content, Contents(thing)) {
buf2 = unparse_object(player, content, 0);
notify(player, buf2);
free_lbuf(buf2);
}
}
/* Show stuff that depends on the object type */
switch (Typeof(thing)) {
case TYPE_ROOM:
/* tell him about exits */
if (Exits(thing) != NOTHING) {
notify(player, "Exits:");
DOLIST(exit, Exits(thing)) {
buf2 = unparse_object(player, exit, 0);
notify(player, buf2);
free_lbuf(buf2);
}
} else {
notify(player, "No exits.");
}
/* print dropto if present */
if (Dropto(thing) != NOTHING) {
buf2 = unparse_object(player,
Dropto(thing), 0);
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431

Saturday, June 16, 2012 11:36 PM

notify(player,
tprintf("Dropped objects go to: %s",
buf2));
free_lbuf(buf2);

}
break;
case TYPE_THING:
case TYPE_PLAYER:

/* tell him about exits */


if (Exits(thing) != NOTHING) {
notify(player, "Exits:");
DOLIST(exit, Exits(thing)) {
buf2 = unparse_object(player, exit, 0);
notify(player, buf2);
free_lbuf(buf2);
}
} else {
notify(player, "No exits.");
}
/* print home */
loc = Home(thing);
buf2 = unparse_object(player, loc, 0);
notify(player, tprintf("Home: %s", buf2));
free_lbuf(buf2);
/* print location if player can link to it */
loc = Location(thing);
if ((Location(thing) != NOTHING) &&
(Examinable(player, loc) ||
Examinable(player, thing) ||
Linkable(player, loc))) {
buf2 = unparse_object(player, loc, 0);
notify(player, tprintf("Location: %s", buf2));
free_lbuf(buf2);
}
break;
case TYPE_EXIT:
buf2 = unparse_object(player, Exits(thing), 0);
notify(player, tprintf("Source: %s", buf2));
free_lbuf(buf2);
/* print destination */
switch (Location(thing)) {
case NOTHING:
/* Special case. unparse_object() normally
* returns -1 as '*NOTHING*'.
*/
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

Saturday, June 16, 2012 11:36 PM

notify(player, "Destination: *UNLINKED*");


break;
default:
buf2 = unparse_object(player,
Location(thing), 0);
notify(player,
tprintf("Destination: %s", buf2));
free_lbuf(buf2);
break;
}
break;
default:
break;
}
} else if (!Opaque(thing) && nearby(player, thing)) {
if (Has_contents(thing))
look_contents(player, thing, "Contents:", CONTENTS_REMOTE);
if (!isExit(thing))
look_exits(player, thing, "Obvious exits:");
}
free_lbuf(temp);

if (!control) {
if (mudconf.read_rem_name) {
buf2 = alloc_lbuf("do_examine.pub_name");
strcpy(buf2, Name(thing));
notify(player,
tprintf("%s is owned by %s",
buf2, Name(Owner(thing))));
free_lbuf(buf2);
} else {
notify(player,
tprintf("Owned by %s",
Name(Owner(thing))));
}
}

void do_score(player, cause, key)


dbref player, cause;
int key;
{
notify(player,
tprintf("You have %d %s.", Pennies(player),
(Pennies(player) == 1) ?
mudconf.one_coin : mudconf.many_coins));
}
void do_inventory(player, cause, key)
dbref player, cause;
int key;
{
dbref thing;
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537

Saturday, June 16, 2012 11:36 PM

char *buff, *e;


thing = Contents(player);
if (thing == NOTHING) {
notify(player, "You aren't carrying anything." );
} else {
notify(player, "You are carrying:");
DOLIST(thing, thing) {
buff = unparse_object(player, thing, 1);
notify(player, buff);
free_lbuf(buff);
}
}

thing = Exits(player);
if (thing != NOTHING) {
notify(player, "Exits:");
e = buff = alloc_lbuf("look_exits");
DOLIST(thing, thing) {
if (e != buff) {
safe_known_str((char *)" ", 2, buff, &e);
}
safe_exit_name(thing, buff, &e);
}
*e = '\0';
notify(player, buff);
free_lbuf(buff);
}
do_score(player, player, 0);

void do_entrances(player, cause, key, name)


dbref player, cause;
int key;
char *name;
{
dbref thing, i, j;
char *exit, *message;
int control_thing, count, low_bound, high_bound;
FWDLIST *fp;
PROPDIR *pp;
parse_range(&name, &low_bound, &high_bound);
if (!name || !*name) {
if (Has_location(player))
thing = Location(player);
else
thing = player;
if (!Good_obj(thing))
return;
} else {
init_match(player, name, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590

Saturday, June 16, 2012 11:36 PM

thing = noisy_match_result();
if (!Good_obj(thing))
return;

if (!payfor(player, mudconf.searchcost)) {
notify(player,
tprintf("You don't have enough %s.",
mudconf.many_coins));
return;
}
message = alloc_lbuf("do_entrances");
control_thing = Examinable(player, thing);
count = 0;
for (i = low_bound; i <= high_bound; i++) {
if (control_thing || Examinable(player, i)) {
switch (Typeof(i)) {
case TYPE_EXIT:
if (Location(i) == thing) {
exit = unparse_object(player,
Exits(i), 0);
notify(player,
tprintf("%s (%s)",
exit, Name(i)));
free_lbuf(exit);
count++;
}
break;
case TYPE_ROOM:
if (Dropto(i) == thing) {
exit = unparse_object(player, i, 0);
notify(player,
tprintf("%s [dropto]", exit));
free_lbuf(exit);
count++;
}
break;
case TYPE_THING:
case TYPE_PLAYER:
if (Home(i) == thing) {
exit = unparse_object(player, i, 0);
notify(player,
tprintf("%s [home]", exit));
free_lbuf(exit);
count++;
}
break;
}
/* Check for parents */
if (Parent(i) == thing) {
exit = unparse_object(player, i, 0);
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

Saturday, June 16, 2012 11:36 PM

notify(player,
tprintf("%s [parent]", exit));
free_lbuf(exit);
count++;

/* Check for propdir */


if (H_Propdir(i)) {
pp = propdir_get(i);
if (!pp)
continue;
for (j = 0; j < pp->count; j++) {
if (pp->data[j] != thing)
continue;
exit = unparse_object(player, i, 0);
notify(player,
tprintf("%s [propdir]", exit));
free_lbuf(exit);
count++;
}
}
/* Check for forwarding */
if (H_Fwdlist(i)) {
fp = fwdlist_get(i);
if (!fp)
continue;
for (j = 0; j < fp->count; j++) {
if (fp->data[j] != thing)
continue;
exit = unparse_object(player, i, 0);
notify(player,
tprintf("%s [forward]", exit));
free_lbuf(exit);
count++;
}
}

}
}
free_lbuf(message);
notify(player, tprintf("%d entrance%s found.", count,
(count == 1) ? "" : "s"));

/* check the current location for bugs */


static void sweep_check(player, what, key, is_loc)
dbref player, what;
int key, is_loc;
{
dbref aowner, parent;
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696

Saturday, June 16, 2012 11:36 PM

int canhear, cancom, isplayer, ispuppet, isconnected, is_audible, attr, aflags, alen;
int is_parent, lev;
char *buf, *buf2, *bp, *as, *buff, *s;
ATTR *ap;
canhear = 0;
cancom = 0;
isplayer = 0;
ispuppet = 0;
isconnected = 0;
is_audible = 0;
is_parent = 0;
if ((key & SWEEP_LISTEN) &&
((isExit(what) || is_loc) && Audible(what))) {
is_audible = 1;
}
if (key & SWEEP_LISTEN) {
if (H_Listen(what) || Bouncer(what)) {
canhear = 1;
} else if (Monitor(what)) {
buff = alloc_lbuf("Hearer");
for (attr = atr_head(what, &as); attr; attr = atr_next(&as)) {
ap = atr_num(attr);
if (!ap || (ap->flags & AF_NOPROG))
continue;
atr_get_str(buff, what, attr, &aowner,
&aflags, &alen);
/* Make sure we can execute it */
if ((buff[0] != AMATCH_LISTEN) ||
(aflags & AF_NOPROG))
continue;
/* Make sure there's a : in it */
for (s = buff + 1; *s && (*s != ':'); s++) ;
if (s) {
canhear = 1;
break;
}

}
free_lbuf(buff);

}
}
if ((key & SWEEP_COMMANDS) && !isExit(what)) {
/* Look for commands on the object and parents too */
ITER_PARENTS(what, parent, lev) {
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

Saturday, June 16, 2012 11:36 PM

if (Commer(parent)) {
cancom = 1;
if (lev) {
is_parent = 1;
break;
}
}

}
}
if (key & SWEEP_CONNECT) {
if (Connected(what) ||
(Puppet(what) && Connected(Owner(what))) ||
(mudconf.player_listen && (Typeof(what) == TYPE_PLAYER) &&
canhear && Connected(Owner(what))))
isconnected = 1;
}
if (key & SWEEP_PLAYER || isconnected) {
if (Typeof(what) == TYPE_PLAYER)
isplayer = 1;
if (Puppet(what))
ispuppet = 1;
}
if (canhear || cancom || isplayer || ispuppet || isconnected ||
is_audible || is_parent) {
buf = alloc_lbuf("sweep_check.types");
bp = buf;
if (cancom)
safe_str((char *)"commands ", buf, &bp);
if (canhear)
safe_str((char *)"messages ", buf, &bp);
if (is_audible)
safe_str((char *) "audible ", buf, &bp);
if (isplayer)
safe_str((char *)"player ", buf, &bp);
if (ispuppet) {
safe_str((char *)"puppet(", buf, &bp);
safe_name(Owner(what), buf, &bp);
safe_str((char *)") ", buf, &bp);
}
if (isconnected)
safe_str((char *)"connected ", buf, &bp);
if (is_parent)
safe_str((char *)"parent ", buf, &bp);
*--bp = '\0';
/* nuke the space at the end */
if (!isExit(what)) {
notify(player,
tprintf(" %s is listening. [%s]",
Name(what), buf));
} else {
bp = buf2 = alloc_lbuf("sweep_check.name");
safe_exit_name(what, buf2, &bp);
notify(player,
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

Saturday, June 16, 2012 11:36 PM

tprintf(" %s is listening. [%s]", buf2, buf));


free_lbuf(buf2);

}
free_lbuf(buf);

void do_sweep(player, cause, key, where)


dbref player, cause;
int key;
char *where;
{
dbref here, sweeploc;
int where_key, what_key;
where_key = key & (SWEEP_ME | SWEEP_HERE | SWEEP_EXITS);
what_key =
key & (SWEEP_COMMANDS | SWEEP_LISTEN | SWEEP_PLAYER | SWEEP_CONNECT);
if (where && *where) {
sweeploc = match_controlled(player, where);
if (!Good_obj(sweeploc))
return;
} else {
sweeploc = player;
}
if (!where_key)
where_key = -1;
if (!what_key)
what_key = -1;
else if (what_key == SWEEP_VERBOSE)
what_key = SWEEP_VERBOSE | SWEEP_COMMANDS;
/* Check my location.

If I have none or it is dark, check just me. */

if (where_key & SWEEP_HERE) {


notify(player, "Sweeping location...");
if (Has_location(sweeploc)) {
here = Location(sweeploc);
if ((here == NOTHING) ||
(Dark(here) && !mudconf.sweep_dark &&
!Examinable(player, here))) {
notify_quiet(player,
"Sorry, it is dark here and you can't search for bugs" );
sweep_check(player, sweeploc, what_key, 0);
} else {
sweep_check(player, here, what_key, 1);
for (here = Contents(here); here != NOTHING; here = Next(here))
sweep_check(player, here, what_key, 0);
}
} else {
sweep_check(player, sweeploc, what_key, 0);
-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

Saturday, June 16, 2012 11:36 PM

}
}
/* Check exits in my location */
if ((where_key & SWEEP_EXITS) && Has_location(sweeploc)) {
notify(player, "Sweeping exits...");
for (here = Exits(Location(sweeploc)); here != NOTHING; here = Next(here))
sweep_check(player, here, what_key, 0);
}
/* Check my inventory */
if ((where_key & SWEEP_ME) && Has_contents(sweeploc)) {
notify(player, "Sweeping inventory...");
for (here = Contents(sweeploc); here != NOTHING; here = Next(here))
sweep_check(player, here, what_key, 0);
}
/* Check carried exits */

if ((where_key & SWEEP_EXITS) && Has_exits(sweeploc)) {


notify(player, "Sweeping carried exits...");
for (here = Exits(sweeploc); here != NOTHING; here = Next(here))
sweep_check(player, here, what_key, 0);
}
notify(player, "Sweep complete.");

/* Output the sequence of commands needed to duplicate the specified


* object. If you're moving things to another system, your mileage
* will almost certainly vary. (i.e. different flags, etc.)
*/
extern NAMETAB indiv_attraccess_nametab[];
void do_decomp(player, cause, key, name, qual)
dbref player, cause;
int key;
char *name, *qual;
{
BOOLEXP *bool;
char *got, *thingname, *as, *ltext, *buff, *tbuf, *tmp;
dbref aowner, thing;
int val, aflags, alen, ca, wild_decomp;
ATTR *attr;
NAMETAB *np;
/* Check for obj/attr first */
olist_push();
if (parse_attrib_wild(player, name, &thing, 0, 1, 0, 1)) {
wild_decomp = 1;
} else {
wild_decomp = 0;
init_match(player, name, TYPE_THING);
-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

Saturday, June 16, 2012 11:36 PM

match_everything(MAT_EXIT_PARENTS);
thing = noisy_match_result();

/* get result */
if (thing == NOTHING) {
olist_pop();
return;
}
if (!Examinable(player, thing)) {
notify_quiet(player,
"You can only decompile things you can examine." );
olist_pop();
return;
}
thingname = atr_get(thing, A_LOCK, &aowner, &aflags, &alen);
bool = parse_boolexp(player, thingname, 1);
/* Determine the name of the thing to use in reporting and then
* report the command to make the thing.
*/
if (qual && *qual) {
StringCopy(thingname, qual);
} else {
switch (Typeof(thing)) {
case TYPE_THING:
StringCopy(thingname, Name(thing));
val = OBJECT_DEPOSIT(Pennies(thing));
notify(player,
tprintf("@create %s=%d", translate_string(thingname, 1),
val));
break;
case TYPE_ROOM:
StringCopy(thingname, Name(thing));
notify(player,
tprintf("@dig/teleport %s",
translate_string(thingname, 1)));
StringCopy(thingname, "here");
break;
case TYPE_EXIT:
StringCopy(thingname, Name(thing));
notify(player,
tprintf("@open %s", translate_string(thingname, 1)));
got = thingname;
safe_exit_name(thing, thingname, &got);
break;
case TYPE_PLAYER:
StringCopy(thingname, "me");
break;
}
}
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961

Saturday, June 16, 2012 11:36 PM

StringCopy(thingname, strip_ansi(thingname));
/* Report the lock (if any) */
if (!wild_decomp && (bool != TRUE_BOOLEXP)) {
notify(player,
tprintf("@lock %s=%s", thingname,
unparse_boolexp_decompile(player, bool)));
}
free_boolexp(bool);
/* Report attributes */
buff = alloc_mbuf("do_decomp.attr_name");
for (ca = (wild_decomp ? olist_first() : atr_head(thing, &as));
(wild_decomp) ? (ca != NOTHING) : (ca != (int) NULL);
ca = (wild_decomp ? olist_next() : atr_next(&as))) {
if ((ca == A_NAME) || (ca == A_LOCK))
continue;
attr = atr_num(ca);
if (!attr)
continue;
if ((attr->flags & AF_NOCMD) && !(attr->flags & AF_IS_LOCK))
continue;
got = atr_get(thing, ca, &aowner, &aflags, &alen);
if (aflags & AF_STRUCTURE) {
tmp = replace_string(GENERIC_STRUCT_STRDELIM,
mudconf.struct_dstr,
got);
free_lbuf(got);
got = tmp;
}
if (Read_attr_all(player, thing, attr, aowner, aflags, 1)) {
if (attr->flags & AF_IS_LOCK) {
bool = parse_boolexp(player, got, 1);
ltext = unparse_boolexp_decompile(player,
bool);
free_boolexp(bool);
notify(player,
tprintf("@lock/%s %s=%s",
attr->name, thingname, ltext));
} else {
StringCopy(buff, attr->name);
if (key & DECOMP_PRETTY) {
tbuf = alloc_lbuf("do_decomp.pretty");
pretty_print(tbuf,
tprintf("%c%s %s=",
((ca < A_USER_START) ?
'@' : '&'),
buff, thingname),
got);
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014

Saturday, June 16, 2012 11:36 PM

notify(player, tbuf);
free_lbuf(tbuf);
} else {
notify(player,
tprintf("%c%s %s=%s",
((ca < A_USER_START) ?
'@' : '&'),
buff, thingname,
got));
}
for (np = indiv_attraccess_nametab;
np->name;
np++) {
if ((aflags & np->flag) &&
check_access(player, np->perm) &&
(!(np->perm & CA_NO_DECOMP))) {

}
}

notify(player,
tprintf("@set %s/%s = %s",
thingname,
buff,
np->name));

if (aflags & AF_LOCK) {


notify(player, tprintf("@lock %s/%s",
thingname, buff));
}

}
free_lbuf(got);

}
free_mbuf(buff);

if (!wild_decomp) {
decompile_flags(player, thing, thingname);
decompile_powers(player, thing, thingname);
}
/* If the object has a parent, report it */
if (!wild_decomp && (Parent(thing) != NOTHING))
notify(player,
tprintf("@parent %s=#%d", thingname, Parent(thing)));
/* If the object has a zone, report it */
if (!wild_decomp && (Zone(thing) != NOTHING))
notify(player,
tprintf("@chzone %s=#%d", thingname, Zone(thing)));

-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\look.c

2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048

Saturday, June 16, 2012 11:36 PM

free_lbuf(thingname);
olist_pop();

#ifdef PUEBLO_SUPPORT
void show_vrml_url(thing, loc)
dbref thing, loc;
{
char *vrml_url;
dbref aowner;
int aflags, alen;
/* If they don't care about HTML, just return. */
if (!Html(thing))
return;
vrml_url = atr_pget(loc, A_VRML_URL, &aowner, &aflags, &alen);
if (*vrml_url) {
char *vrml_message, *vrml_cp;
vrml_message = vrml_cp = alloc_lbuf("show_vrml_url");
safe_str("<img xch_graph=load href=\"" , vrml_message, &vrml_cp);
safe_str(vrml_url, vrml_message, &vrml_cp);
safe_str("\">", vrml_message, &vrml_cp);
*vrml_cp = 0;
notify_html(thing, vrml_message);
free_lbuf(vrml_message);
} else {
notify_html(thing, "<img xch_graph=hide>");
}
free_lbuf(vrml_url);

}
#endif

-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:35 PM

/* ltdl.c -- system independent dlopen wrapper


Copyright (C) 1998-1999 Free Software Foundation, Inc.
Originally by Thomas Tanner <tanner@ffii.org>
This file is part of GNU Libtool.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
As a special exception to the GNU Library General Public License,
if you distribute this file as part of a program that uses GNU libtool
to create libraries and programs, you may include it under the same
distribution terms that you use for the rest of that program.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
#include "autoconf.h"
#define _LTDL_COMPILE_
#if HAVE_CONFIG_H
#include <config.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_STRINGS_H
#include <strings.h>
#endif
#if HAVE_CTYPE_H
#include <ctype.h>
#endif
#if HAVE_MALLOC_H
#include <malloc.h>
#endif
#if HAVE_MEMORY_H
#include <memory.h>
#endif
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:35 PM

#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_STDIO_H
#include <stdio.h>
#endif
#include "ltdl.h"
/* max. filename length */
#ifndef LTDL_FILENAME_MAX
#define LTDL_FILENAME_MAX 1024
#endif
#undef LTDL_READTEXT_MODE
/* fopen() mode flags for reading a text file */
#ifdef _WIN32
#define LTDL_READTEXT_MODE "rt"
#else
#define LTDL_READTEXT_MODE "r"
#endif
#undef LTDL_SYMBOL_LENGTH
/* This is the maximum symbol size that won't require malloc/free */
#define LTDL_SYMBOL_LENGTH 128
#undef LTDL_SYMBOL_OVERHEAD
/* This accounts for the _LTX_ separator */
#define LTDL_SYMBOL_OVERHEAD
5
static const char objdir[] = LTDL_OBJDIR;
#ifdef LTDL_SHLIB_EXT
static const char shlib_ext[] = LTDL_SHLIB_EXT;
#endif
static
static
static
static
static
static
static
static
static
static
static

const
const
const
const
const
const
const
const
const
const
const

char
char
char
char
char
char
char
char
char
char
char

unknown_error[] = "unknown error";


dlopen_not_supported_error[] = "dlopen support not available" ;
file_not_found_error[] = "file not found";
no_symbols_error[] = "no symbols defined";
cannot_open_error[] = "can't open the module";
cannot_close_error[] = "can't close the module";
symbol_error[] = "symbol not found";
memory_error[] = "not enough memory";
invalid_handle_error[] = "invalid handle";
buffer_overflow_error[] = "internal buffer overflow";
shutdown_error[] = "library already shutdown";

#ifndef HAVE_PRELOADED_SYMBOLS
/* If libtool won't define it, we'd better do */
const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } };
#endif
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

Saturday, June 16, 2012 11:35 PM

static const char *last_error = 0;


lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))
malloc;
void
(*lt_dlfree) LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))
free;
typedef struct lt_dltype_t {
struct lt_dltype_t *next;
const char *sym_prefix; /* prefix for symbols */
int (*mod_init) LTDL_PARAMS((void));
int (*mod_exit) LTDL_PARAMS((void));
int (*lib_open) LTDL_PARAMS((lt_dlhandle handle, const char *filename));
int (*lib_close) LTDL_PARAMS((lt_dlhandle handle));
lt_ptr_t (*find_sym) LTDL_PARAMS((lt_dlhandle handle, const char *symbol));
} lt_dltype_t;
#define LTDL_TYPE_TOP 0
typedef struct lt_dlhandle_t {
struct lt_dlhandle_t *next;
lt_dltype_t *type; /* dlopening interface */
char
*filename; /* file name */
char
*name;
/* module name */
int usage;
/* usage */
int depcount;
/* number of dependencies */
lt_dlhandle *deplibs;
/* dependencies */
lt_ptr_t handle;
/* system handle */
lt_ptr_t system;
/* system specific data */
} lt_dlhandle_t;
#undef strdup
#define strdup xstrdup
static inline char *
strdup(str)
const char *str;
{
char *tmp;

if (!str)
return 0;
tmp = (char*) lt_dlmalloc(strlen(str)+1);
if (tmp)
strcpy(tmp, str);
return tmp;

#if ! HAVE_STRCHR
# if HAVE_INDEX

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

Saturday, June 16, 2012 11:35 PM

define strchr index

# else
#

define strchr xstrchr

static inline const char*


strchr(str, ch)
const char *str;
int ch;
{
const char *p;
for (p = str; *p != (char)ch && *p != '\0'; p++)
/*NOWORK*/;
}

return (*p == (char)ch) ? p : 0;

# endif
#endif
#if ! HAVE_STRRCHR
# if HAVE_RINDEX
#

define strrchr rindex

# else
#

define strrchr xstrrchr

static inline const char*


strrchr(str, ch)
const char *str;
int ch;
{
const char *p;
for (p = str; *p != '\0'; p++)
/*NOWORK*/;
while (*p != (char)ch && p >= str)
p--;
}

return (*p == (char)ch) ? p : 0;

# endif
#endif

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

Saturday, June 16, 2012 11:35 PM

#if HAVE_LIBDL
/* dynamic linking with dlopen/dlsym */
#if HAVE_DLFCN_H
# include <dlfcn.h>
#endif
#ifdef RTLD_GLOBAL
# define LTDL_GLOBAL
#else
# ifdef DL_GLOBAL
# define LTDL_GLOBAL
# else
# define LTDL_GLOBAL
# endif
#endif

RTLD_GLOBAL
DL_GLOBAL
0

/* We may have to define LTDL_LAZY_OR_NOW in the command line if we


find out it does not work in some platform. */
#ifndef LTDL_LAZY_OR_NOW
# ifdef RTLD_LAZY
# define LTDL_LAZY_OR_NOW RTLD_LAZY
# else
# ifdef DL_LAZY
#
define LTDL_LAZY_OR_NOW DL_LAZY
# else
#
ifdef RTLD_NOW
#
define LTDL_LAZY_OR_NOW
RTLD_NOW
#
else
#
ifdef DL_NOW
#
define LTDL_LAZY_OR_NOW
DL_NOW
#
else
#
define LTDL_LAZY_OR_NOW
0
#
endif
#
endif
# endif
# endif
#endif
static int
sys_dl_init LTDL_PARAMS((void))
{
return 0;
}
static int
sys_dl_exit LTDL_PARAMS((void))
{
return 0;
}
static int
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

Saturday, June 16, 2012 11:35 PM

sys_dl_open (handle, filename)


lt_dlhandle handle;
const char *filename;
{
handle->handle = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW);
if (!handle->handle) {
#if HAVE_DLERROR
last_error = dlerror();
#else
last_error = cannot_open_error;
#endif
return 1;
}
return 0;
}
static int
sys_dl_close (handle)
lt_dlhandle handle;
{
if (dlclose(handle->handle) != 0) {
#if HAVE_DLERROR
last_error = dlerror();
#else
last_error = cannot_close_error;
#endif
return 1;
}
return 0;
}
static lt_ptr_t
sys_dl_sym (handle, symbol)
lt_dlhandle handle;
const char *symbol;
{
lt_ptr_t address = dlsym(handle->handle, symbol);
if (!address)
#if HAVE_DLERROR
last_error = dlerror();
#else
last_error = symbol_error;
#endif
return address;
}
static
lt_dltype_t
#ifdef NEED_USCORE
sys_dl = { LTDL_TYPE_TOP, "_", sys_dl_init, sys_dl_exit,
sys_dl_open, sys_dl_close, sys_dl_sym };
#else
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

Saturday, June 16, 2012 11:35 PM

sys_dl = { LTDL_TYPE_TOP, 0, sys_dl_init, sys_dl_exit,


sys_dl_open, sys_dl_close, sys_dl_sym };
#endif
#undef LTDL_TYPE_TOP
#define LTDL_TYPE_TOP &sys_dl
#endif
#if HAVE_SHL_LOAD
/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
#ifdef HAVE_DL_H
#include <dl.h>
#endif
/* some flags are missing on some systems, so we provide
* harmless defaults.
*
* Mandatory:
* BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
* BIND_DEFERRED
- Delay code symbol resolution until actual reference.
*
* Optionally:
* BIND_FIRST
- Place the library at the head of the symbol search order.
* BIND_NONFATAL
- The default BIND_IMMEDIATE behavior is to treat all unsatisfied
*
symbols as fatal. This flag allows binding of unsatisfied code
*
symbols to be deferred until use.
*
[Perl: For certain libraries, like DCE, deferred binding often
*
causes run time problems. Adding BIND_NONFATAL to BIND_IMMEDIATE
*
still allows unresolved references in situations like this.]
* BIND_NOSTART
- Do not call the initializer for the shared library when the
*
library is loaded, nor on a future call to shl_unload().
* BIND_VERBOSE
- Print verbose messages concerning possible unsatisfied symbols.
*
* hp9000s700/hp9000s800:
* BIND_RESTRICTED - Restrict symbols visible by the library to those present at
*
library load time.
* DYNAMIC_PATH
- Allow the loader to dynamically search for the library specified
*
by the path argument.
*/
#ifndef
#define
#endif
#ifndef
#define
#endif

DYNAMIC_PATH
DYNAMIC_PATH
0
/* DYNAMIC_PATH */
BIND_RESTRICTED
BIND_RESTRICTED 0
/* BIND_RESTRICTED */

#define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)


static int
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

Saturday, June 16, 2012 11:35 PM

sys_shl_init LTDL_PARAMS((void))
{
return 0;
}
static int
sys_shl_exit LTDL_PARAMS((void))
{
return 0;
}
static int
sys_shl_open (handle, filename)
lt_dlhandle handle;
const char *filename;
{
handle->handle = shl_load(filename, LTDL_BIND_FLAGS, 0L);
if (!handle->handle) {
last_error = cannot_open_error;
return 1;
}
return 0;
}
static int
sys_shl_close (handle)
lt_dlhandle handle;
{
if (shl_unload((shl_t) (handle->handle)) != 0) {
last_error = cannot_close_error;
return 1;
}
return 0;
}
static lt_ptr_t
sys_shl_sym (handle, symbol)
lt_dlhandle handle;
const char *symbol;
{
lt_ptr_t address;

if (handle->handle && shl_findsym((shl_t*) &(handle->handle),


symbol, TYPE_UNDEFINED, &address) == 0)
if (address)
return address;
last_error = symbol_error;
return 0;

static
lt_dltype_t
sys_shl = { LTDL_TYPE_TOP, 0, sys_shl_init, sys_shl_exit,
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

Saturday, June 16, 2012 11:35 PM

sys_shl_open, sys_shl_close, sys_shl_sym };


#undef LTDL_TYPE_TOP
#define LTDL_TYPE_TOP &sys_shl
#endif
#if HAVE_DLD
/* dynamic linking with dld */
#if HAVE_DLD_H
#include <dld.h>
#endif
static int
sys_dld_init LTDL_PARAMS((void))
{
return 0;
}
static int
sys_dld_exit LTDL_PARAMS((void))
{
return 0;
}
static int
sys_dld_open (handle, filename)
lt_dlhandle handle;
const char *filename;
{
handle->handle = strdup(filename);
if (!handle->handle) {
last_error = memory_error;
return 1;
}
if (dld_link(filename) != 0) {
last_error = cannot_open_error;
lt_dlfree(handle->handle);
return 1;
}
return 0;
}
static int
sys_dld_close (handle)
lt_dlhandle handle;
{
if (dld_unlink_by_file((char*)(handle->handle), 1) != 0) {
last_error = cannot_close_error;
return 1;
}
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

Saturday, June 16, 2012 11:35 PM

lt_dlfree(handle->filename);
return 0;

static lt_ptr_t
sys_dld_sym (handle, symbol)
lt_dlhandle handle;
const char *symbol;
{
lt_ptr_t address = dld_get_func(symbol);

if (!address)
last_error = symbol_error;
return address;

static
lt_dltype_t
sys_dld = { LTDL_TYPE_TOP, 0, sys_dld_init, sys_dld_exit,
sys_dld_open, sys_dld_close, sys_dld_sym };
#undef LTDL_TYPE_TOP
#define LTDL_TYPE_TOP &sys_dld
#endif
#ifdef _WIN32
/* dynamic linking for Win32 */
#include <windows.h>
static int
sys_wll_init LTDL_PARAMS((void))
{
return 0;
}
static int
sys_wll_exit LTDL_PARAMS((void))
{
return 0;
}
/* Forward declaration; required to implement handle search below. */
static lt_dlhandle handles;
static int
sys_wll_open (handle, filename)
lt_dlhandle handle;
const char *filename;
{
lt_dlhandle cur;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

Saturday, June 16, 2012 11:35 PM

char *searchname = NULL;


char *ext = strrchr(filename, '.');
if (ext) {
/* FILENAME already has an extension. */
searchname = strdup(filename);
} else {
/* Append a `.' to stop Windows from adding an
implicit `.dll' extension. */
searchname = (char*)lt_dlmalloc(2+ strlen(filename));
strcpy(searchname, filename);
strcat(searchname, ".");
}
handle->handle = LoadLibrary(searchname);
lt_dlfree(searchname);
/* libltdl expects this function to fail if it is unable
to physically load the library. Sadly, LoadLibrary
will search the loaded libraries for a match and return
one of them if the path search load fails.
We check whether LoadLibrary is returning a handle to
an already loaded module, and simulate failure if we
find one. */
cur = handles;
while (cur) {
if (!cur->handle) {
cur = 0;
break;
}
if (cur->handle == handle->handle)
break;
cur = cur->next;
}
if (cur || !handle->handle) {
last_error = cannot_open_error;
return 1;
}
}

return 0;

static int
sys_wll_close (handle)
lt_dlhandle handle;
{
if (FreeLibrary(handle->handle) == 0) {
last_error = cannot_close_error;
return 1;
}
return 0;
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

Saturday, June 16, 2012 11:35 PM

}
static lt_ptr_t
sys_wll_sym (handle, symbol)
lt_dlhandle handle;
const char *symbol;
{
lt_ptr_t address = GetProcAddress(handle->handle, symbol);

if (!address)
last_error = symbol_error;
return address;

static
lt_dltype_t
sys_wll = { LTDL_TYPE_TOP, 0, sys_wll_init, sys_wll_exit,
sys_wll_open, sys_wll_close, sys_wll_sym };
#undef LTDL_TYPE_TOP
#define LTDL_TYPE_TOP &sys_wll
#endif
#ifdef __BEOS__
/* dynamic linking for BeOS */
#include <kernel/image.h>
static int
sys_bedl_init LTDL_PARAMS((void))
{
return 0;
}
static int
sys_bedl_exit LTDL_PARAMS((void))
{
return 0;
}
static int
sys_bedl_open (handle, filename)
lt_dlhandle handle;
const char *filename;
{
image_id image = 0;
if (filename) {
image = load_add_on(filename);
} else {
image_info info;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687

Saturday, June 16, 2012 11:35 PM

int32 cookie = 0;
if (get_next_image_info(0, &cookie, &info) == B_OK)
image = load_add_on(info.name);

}
if (image <= 0) {
last_error = cannot_open_error;
return 1;
}
handle->handle = (void*) image;
return 0;

static int
sys_bedl_close (handle)
lt_dlhandle handle;
{
if (unload_add_on((image_id)handle->handle) != B_OK) {
last_error = cannot_close_error;
return 1;
}
return 0;
}
static lt_ptr_t
sys_bedl_sym (handle, symbol)
lt_dlhandle handle;
const char *symbol;
{
lt_ptr_t address = 0;
image_id image = (image_id)handle->handle;

if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY,


&address) != B_OK) {
last_error = symbol_error;
return 0;
}
return address;

static
lt_dltype_t
sys_bedl = { LTDL_TYPE_TOP, 0, sys_bedl_init, sys_bedl_exit,
sys_bedl_open, sys_bedl_close, sys_bedl_sym };
#undef LTDL_TYPE_TOP
#define LTDL_TYPE_TOP &sys_bedl
#endif
/* emulate dynamic linking using preloaded_symbols */
typedef struct lt_dlsymlists_t {
struct lt_dlsymlists_t *next;
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

Saturday, June 16, 2012 11:35 PM

const lt_dlsymlist *syms;


} lt_dlsymlists_t;
static const lt_dlsymlist *default_preloaded_symbols = 0;
static lt_dlsymlists_t *preloaded_symbols = 0;
static int
presym_init LTDL_PARAMS((void))
{
preloaded_symbols = 0;
if (default_preloaded_symbols)
return lt_dlpreload(default_preloaded_symbols);
return 0;
}
static int
presym_free_symlists LTDL_PARAMS((void))
{
lt_dlsymlists_t *lists = preloaded_symbols;
while (lists) {
lt_dlsymlists_t *tmp = lists;
lists = lists->next;
lt_dlfree(tmp);

}
preloaded_symbols = 0;
return 0;

static int
presym_exit LTDL_PARAMS((void))
{
presym_free_symlists();
return 0;
}
static int
presym_add_symlist (preloaded)
const lt_dlsymlist *preloaded;
{
lt_dlsymlists_t *tmp;
lt_dlsymlists_t *lists = preloaded_symbols;
while (lists) {
if (lists->syms == preloaded)
return 0;
lists = lists->next;
}
tmp = (lt_dlsymlists_t*) lt_dlmalloc(sizeof(lt_dlsymlists_t));
if (!tmp) {
last_error = memory_error;
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

Saturday, June 16, 2012 11:35 PM

return 1;
}
tmp->syms = preloaded;
tmp->next = 0;
if (!preloaded_symbols)
preloaded_symbols = tmp;
else {
/* append to the end */
lists = preloaded_symbols;
while (lists->next)
lists = lists->next;
lists->next = tmp;
}
return 0;

static int
presym_open (handle, filename)
lt_dlhandle handle;
const char *filename;
{
lt_dlsymlists_t *lists = preloaded_symbols;
if (!lists) {
last_error = no_symbols_error;
return 1;
}
if (!filename)
filename = "@PROGRAM@";
while (lists) {
const lt_dlsymlist *syms = lists->syms;
while (syms->name) {
if (!syms->address &&
strcmp(syms->name, filename) == 0) {
handle->handle = (lt_ptr_t) syms;
return 0;
}
syms++;
}
lists = lists->next;

}
last_error = file_not_found_error;
return 1;

static int
presym_close (handle)
lt_dlhandle handle;
{
/* Just to silence gcc -Wall */
handle = 0;
return 0;
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

Saturday, June 16, 2012 11:35 PM

}
static lt_ptr_t
presym_sym (handle, symbol)
lt_dlhandle handle;
const char *symbol;
{
lt_dlsymlist *syms = (lt_dlsymlist*)(handle->handle);

syms++;
while (syms->address) {
if (strcmp(syms->name, symbol) == 0)
return syms->address;
syms++;
}
last_error = symbol_error;
return 0;

static
lt_dltype_t
presym = { LTDL_TYPE_TOP, 0, presym_init, presym_exit,
presym_open, presym_close, presym_sym };
#undef LTDL_TYPE_TOP
#define LTDL_TYPE_TOP &presym
static char *user_search_path = 0;
static lt_dlhandle handles = 0;
static int initialized = 0;
static lt_dltype_t *types = LTDL_TYPE_TOP;
#undef LTDL_TYPE_TOP
int
lt_dlinit LTDL_PARAMS((void))
{
/* initialize libltdl */
lt_dltype_t **type = &types;
int typecount = 0;
if (initialized) { /* Initialize only at first call. */
initialized++;
return 0;
}
handles = 0;
user_search_path = 0; /* empty search path */
while (*type) {
if ((*type)->mod_init())
*type = (*type)->next; /* Remove it from the list */
else {
type = &(*type)->next; /* Keep it */
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899

Saturday, June 16, 2012 11:35 PM

typecount++;

}
if (typecount == 0) {
last_error = dlopen_not_supported_error;
return 1;
}
last_error = 0;
initialized = 1;
return 0;

int
lt_dlpreload (preloaded)
const lt_dlsymlist *preloaded;
{
if (preloaded)
return presym_add_symlist(preloaded);
presym_free_symlists();
if (default_preloaded_symbols)
return lt_dlpreload(default_preloaded_symbols);
return 0;
}
int
lt_dlpreload_default (preloaded)
const lt_dlsymlist *preloaded;
{
default_preloaded_symbols = preloaded;
return 0;
}
int
lt_dlexit LTDL_PARAMS((void))
{
/* shut down libltdl */
lt_dltype_t *type = types;
int errors;
if (!initialized) {
last_error = shutdown_error;
return 1;
}
if (initialized != 1) { /* shut down only at last call. */
initialized--;
return 0;
}
/* close all modules */
errors = 0;
while (handles) {
/* FIXME: what if a module depends on another one? */
if (lt_dlclose(handles))
errors++;
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

Saturday, June 16, 2012 11:35 PM

}
initialized = 0;
while (type) {
if (type->mod_exit())
errors++;
type = type->next;
}
return errors;

static int
tryall_dlopen (handle, filename)
lt_dlhandle *handle;
const char *filename;
{
lt_dlhandle cur;
lt_dltype_t *type = types;
const char *saved_error = last_error;
/* check whether the module was already opened */
cur = handles;
while (cur) {
if (!cur->filename && !filename)
break;
if (cur->filename && filename &&
strcmp(cur->filename, filename) == 0)
break;
cur = cur->next;
}
if (cur) {
cur->usage++;
*handle = cur;
return 0;
}
cur = *handle;
if (filename) {
cur->filename = strdup(filename);
if (!cur->filename) {
last_error = memory_error;
return 1;
}
} else
cur->filename = 0;
while (type) {
if (type->lib_open(cur, filename) == 0)
break;
type = type->next;
}
if (!type) {
if (cur->filename)
lt_dlfree(cur->filename);
return 1;
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

Saturday, June 16, 2012 11:35 PM

}
cur->type = type;
last_error = saved_error;
return 0;

static int
find_module (handle, dir, libdir, dlname, old_name, installed)
lt_dlhandle *handle;
const char *dir;
const char *libdir;
const char *dlname;
const char *old_name;
int installed;
{
int error;
char
*filename;
/* try to open the old library first; if it was dlpreopened,
we want the preopened version of it, even if a dlopenable
module is available */
if (old_name && tryall_dlopen(handle, old_name) == 0)
return 0;
/* try to open the dynamic library */
if (dlname) {
/* try to open the installed module */
if (installed && libdir) {
filename = (char*)
lt_dlmalloc(strlen(libdir)+1+strlen(dlname)+1);
if (!filename) {
last_error = memory_error;
return 1;
}
strcpy(filename, libdir);
strcat(filename, "/");
strcat(filename, dlname);
error = tryall_dlopen(handle, filename) == 0;
lt_dlfree(filename);
if (error)
return 0;
}
/* try to open the not-installed module */
if (!installed) {
filename = (char*)
lt_dlmalloc((dir ? strlen(dir) : 0)
+ strlen(objdir) + strlen(dlname) + 1);
if (!filename) {
last_error = memory_error;
return 1;
}
if (dir)
strcpy(filename, dir);
else
*filename = 0;
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:35 PM

strcat(filename, objdir);
strcat(filename, dlname);
error = tryall_dlopen(handle, filename) == 0;
lt_dlfree(filename);
if (error)
return 0;

}
/* hmm, maybe it was moved to another directory */
{
filename = (char*)
lt_dlmalloc((dir ? strlen(dir) : 0)
+ strlen(dlname) + 1);
if (dir)
strcpy(filename, dir);
else
*filename = 0;
strcat(filename, dlname);
error = tryall_dlopen(handle, filename) == 0;
lt_dlfree(filename);
if (error)
return 0;
}

}
last_error = file_not_found_error;
return 1;

static lt_ptr_t
find_file (basename, search_path, pdir, handle)
const char *basename;
const char *search_path;
char **pdir;
lt_dlhandle *handle;
{
/* when handle != NULL search a library, otherwise a file */
/* return NULL on failure, otherwise the file/handle */
char
*filename = 0;
int
filenamesize = 0;
const char *next = search_path;
int lenbase = strlen(basename);
if (!next || !*next) {
last_error = file_not_found_error;
return 0;
}
while (next) {
int lendir;
const char *cur = next;
next = strchr(cur, ':');
if (!next)
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

Saturday, June 16, 2012 11:35 PM

next = cur + strlen(cur);


lendir = next - cur;
if (*next == ':')
++next;
else
next = 0;
if (lendir == 0)
continue;
if (lendir + 1 + lenbase >= filenamesize) {
if (filename)
lt_dlfree(filename);
filenamesize = lendir + 1 + lenbase + 1;
filename = (char*) lt_dlmalloc(filenamesize);
if (!filename) {
last_error = memory_error;
return 0;
}
}
strncpy(filename, cur, lendir);
if (filename[lendir-1] != '/')
filename[lendir++] = '/';
strcpy(filename+lendir, basename);
if (handle) {
if (tryall_dlopen(handle, filename) == 0) {
lt_dlfree(filename);
return (lt_ptr_t) handle;
}
} else {
FILE *file = fopen(filename, LTDL_READTEXT_MODE);
if (file) {
if (*pdir)
lt_dlfree(*pdir);
filename[lendir] = '\0';
*pdir = strdup(filename);
if (!*pdir) {
/* We could have even avoided the
strdup, but there would be some
memory overhead. */
*pdir = filename;
} else
lt_dlfree(filename);
return (lt_ptr_t) file;
}
}

}
if (filename)
lt_dlfree(filename);
last_error = file_not_found_error;
return 0;

static int
load_deplibs(handle, deplibs)
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

Saturday, June 16, 2012 11:35 PM

lt_dlhandle handle;
const char *deplibs;
/* FIXME: load deplibs */
handle->depcount = 0;
handle->deplibs = 0;
/* Just to silence gcc -Wall */
deplibs = 0;
return 0;

static int
unload_deplibs(handle)
lt_dlhandle handle;
{
/* FIXME: unload deplibs */
/* Just to silence gcc -Wall */
handle = 0;
return 0;
}
static inline int
trim (dest, str)
char **dest;
const char *str;
{
/* remove the leading and trailing "'" from str
and store the result in dest */
char *tmp;
const char *end = strrchr(str, '\'');
int len = strlen(str);

if (*dest)
lt_dlfree(*dest);
if (len > 3 && str[0] == '\'') {
tmp = (char*) lt_dlmalloc(end - str);
if (!tmp) {
last_error = memory_error;
return 1;
}
strncpy(tmp, &str[1], (end - str) - 1);
tmp[len-3] = '\0';
*dest = tmp;
} else
*dest = 0;
return 0;

static inline int


free_vars(dir, name, dlname, oldname, libdir, deplibs)
char *dir;
char *name;
char *dlname;
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

Saturday, June 16, 2012 11:35 PM

char *oldname;
char *libdir;
char *deplibs;
if (dir)
lt_dlfree(dir);
if (name)
lt_dlfree(name);
if (dlname)
lt_dlfree(dlname);
if (oldname)
lt_dlfree(oldname);
if (libdir)
lt_dlfree(libdir);
if (deplibs)
lt_dlfree(deplibs);
return 0;

lt_dlhandle
lt_dlopen (filename)
const char *filename;
{
lt_dlhandle handle, newhandle;
const char *basename, *ext;
const char *saved_error = last_error;
char
*dir = 0, *name = 0;
if (!filename) {
handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
if (!handle) {
last_error = memory_error;
return 0;
}
handle->usage = 0;
handle->depcount = 0;
handle->deplibs = 0;
newhandle = handle;
if (tryall_dlopen(&newhandle, 0) != 0) {
lt_dlfree(handle);
return 0;
}
goto register_handle;
}
basename = strrchr(filename, '/');
if (basename) {
basename++;
dir = (char*) lt_dlmalloc(basename - filename + 1);
if (!dir) {
last_error = memory_error;
return 0;
}
strncpy(dir, filename, basename - filename);
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

Saturday, June 16, 2012 11:35 PM

dir[basename - filename] = '\0';


} else
basename = filename;
/* check whether we open a libtool module (.la extension) */
ext = strrchr(basename, '.');
if (ext && strcmp(ext, ".la") == 0) {
/* this seems to be a libtool module */
FILE
*file;
int i;
char
*dlname = 0, *old_name = 0;
char
*libdir = 0, *deplibs = 0;
char
*line;
int error = 0;
/* if we can't find the installed flag, it is probably an
installed libtool archive, produced with an old version
of libtool */
int
installed = 1;
/* extract the module name from the file name */
name = (char*) lt_dlmalloc(ext - basename + 1);
if (!name) {
last_error = memory_error;
if (dir)
lt_dlfree(dir);
return 0;
}
/* canonicalize the module name */
for (i = 0; i < ext - basename; i++)
if (isalnum((int)(basename[i])))
name[i] = basename[i];
else
name[i] = '_';
name[ext - basename] = '\0';
/* now try to open the .la file */
file = fopen(filename, LTDL_READTEXT_MODE);
if (!file)
last_error = file_not_found_error;
if (!file && !dir) {
/* try other directories */
file = (FILE*) find_file(basename,
user_search_path,
&dir, 0);
if (!file)
file = (FILE*) find_file(basename,
getenv("LTDL_LIBRARY_PATH"),
&dir, 0);
#ifdef LTDL_SHLIBPATH_VAR
if (!file)
file = (FILE*) find_file(basename,
getenv(LTDL_SHLIBPATH_VAR),
&dir, 0);
#endif
}
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

#
#

#
#

#
#

#
#

Saturday, June 16, 2012 11:35 PM

if (!file) {
if (name)
lt_dlfree(name);
if (dir)
lt_dlfree(dir);
return 0;
}
line = (char*) lt_dlmalloc(LTDL_FILENAME_MAX);
if (!line) {
fclose(file);
last_error = memory_error;
return 0;
}
/* read the .la file */
while (!feof(file)) {
if (!fgets(line, LTDL_FILENAME_MAX, file))
break;
if (line[0] == '\n' || line[0] == '#')
continue;
undef STR_DLNAME
define STR_DLNAME
"dlname="
if (strncmp(line, STR_DLNAME,
sizeof(STR_DLNAME) - 1) == 0)
error = trim(&dlname,
&line[sizeof(STR_DLNAME) - 1]);
else
undef STR_OLD_LIBRARY
define STR_OLD_LIBRARY "old_library="
if (strncmp(line, STR_OLD_LIBRARY,
sizeof(STR_OLD_LIBRARY) - 1) == 0)
error = trim(&old_name,
&line[sizeof(STR_OLD_LIBRARY) - 1]);
else
undef STR_LIBDIR
define STR_LIBDIR
"libdir="
if (strncmp(line, STR_LIBDIR,
sizeof(STR_LIBDIR) - 1) == 0)
error = trim(&libdir,
&line[sizeof(STR_LIBDIR) - 1]);
else
undef STR_DL_DEPLIBS
define STR_DL_DEPLIBS
"dl_dependency_libs="
if (strncmp(line, STR_DL_DEPLIBS,
sizeof(STR_DL_DEPLIBS) - 1) == 0)
error = trim(&deplibs,
&line[sizeof(STR_DL_DEPLIBS) - 1]);
else
if (strcmp(line, "installed=yes\n") == 0)
installed = 1;
else
if (strcmp(line, "installed=no\n") == 0)
installed = 0;
if (error)
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376

Saturday, June 16, 2012 11:35 PM

break;
}
fclose(file);
lt_dlfree(line);
/* allocate the handle */
handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
if (!handle || error) {
if (handle)
lt_dlfree(handle);
if (!error)
last_error = memory_error;
free_vars(name, dir, dlname, old_name, libdir, deplibs);
return 0;
}
handle->usage = 0;
if (load_deplibs(handle, deplibs) == 0) {
newhandle = handle;
/* find_module may replace newhandle */
if (find_module(&newhandle, dir, libdir,
dlname, old_name, installed)) {
unload_deplibs(handle);
error = 1;
}
} else
error = 1;
if (error) {
lt_dlfree(handle);
free_vars(name, dir, dlname, old_name, libdir, deplibs);
return 0;
}
if (handle != newhandle) {
unload_deplibs(handle);
}
} else {
/* not a libtool module */
handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
if (!handle) {
last_error = memory_error;
if (dir)
lt_dlfree(dir);
return 0;
}
handle->usage = 0;
/* non-libtool modules don't have dependencies */
handle->depcount = 0;
handle->deplibs = 0;
newhandle = handle;
if (tryall_dlopen(&newhandle, filename)
&& (dir
|| (!find_file(basename, user_search_path,
0, &newhandle)
&& !find_file(basename,
getenv("LTDL_LIBRARY_PATH"),
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429

Saturday, June 16, 2012 11:35 PM

0, &newhandle)
#ifdef LTDL_SHLIBPATH_VAR
&& !find_file(basename,
getenv(LTDL_SHLIBPATH_VAR),
0, &newhandle)
#endif
))) {
lt_dlfree(handle);
if (dir)
lt_dlfree(dir);
return 0;
}
}
register_handle:
if (newhandle != handle) {
lt_dlfree(handle);
handle = newhandle;
}
if (!handle->usage) {
handle->usage = 1;
handle->name = name;
handle->next = handles;
handles = handle;
} else if (name)
lt_dlfree(name);
if (dir)
lt_dlfree(dir);
last_error = saved_error;
return handle;
}
lt_dlhandle
lt_dlopenext (filename)
const char *filename;
{
lt_dlhandle handle;
char
*tmp;
int len;
const char *saved_error = last_error;
if (!filename)
return lt_dlopen(filename);
len = strlen(filename);
if (!len) {
last_error = file_not_found_error;
return 0;
}
/* try the normal file name */
handle = lt_dlopen(filename);
if (handle)
return handle;
/* try "filename.la" */
tmp = (char*) lt_dlmalloc(len+4);
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482

Saturday, June 16, 2012 11:35 PM

if (!tmp) {
last_error = memory_error;
return 0;
}
strcpy(tmp, filename);
strcat(tmp, ".la");
handle = lt_dlopen(tmp);
if (handle) {
last_error = saved_error;
lt_dlfree(tmp);
return handle;
}
#ifdef LTDL_SHLIB_EXT
/* try "filename.EXT" */
if (strlen(shlib_ext) > 3) {
lt_dlfree(tmp);
tmp = (char*) lt_dlmalloc(len + strlen(shlib_ext) + 1);
if (!tmp) {
last_error = memory_error;
return 0;
}
strcpy(tmp, filename);
} else
tmp[len] = '\0';
strcat(tmp, shlib_ext);
handle = lt_dlopen(tmp);
if (handle) {
last_error = saved_error;
lt_dlfree(tmp);
return handle;
}
#endif
last_error = file_not_found_error;
lt_dlfree(tmp);
return 0;
}
int
lt_dlclose (handle)
lt_dlhandle handle;
{
lt_dlhandle cur, last;
/* check whether the handle is valid */
last = cur = handles;
while (cur && handle != cur) {
last = cur;
cur = cur->next;
}
if (!cur) {
last_error = invalid_handle_error;
return 1;
}
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535

Saturday, June 16, 2012 11:35 PM

handle->usage--;
if (!handle->usage) {
int error;
if (handle != handles)
last->next = handle->next;
else
handles = handle->next;
error = handle->type->lib_close(handle);
error += unload_deplibs(handle);
if (handle->filename)
lt_dlfree(handle->filename);
if (handle->name)
lt_dlfree(handle->name);
lt_dlfree(handle);
return error;

}
return 0;

lt_ptr_t
lt_dlsym (handle, symbol)
lt_dlhandle handle;
const char *symbol;
{
int lensym;
char
lsym[LTDL_SYMBOL_LENGTH];
char
*sym;
lt_ptr_t address;
if (!handle) {
last_error = invalid_handle_error;
return 0;
}
if (!symbol) {
last_error = symbol_error;
return 0;
}
lensym = strlen(symbol);
if (handle->type->sym_prefix)
lensym += strlen(handle->type->sym_prefix);
if (handle->name)
lensym += strlen(handle->name);
if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH)
sym = lsym;
else
sym = (char*) lt_dlmalloc(lensym + LTDL_SYMBOL_OVERHEAD + 1);
if (!sym) {
last_error = buffer_overflow_error;
return 0;
}
if (handle->name) {
const char *saved_error = last_error;
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

Saturday, June 16, 2012 11:35 PM

/* this is a libtool module */


if (handle->type->sym_prefix) {
strcpy(sym, handle->type->sym_prefix);
strcat(sym, handle->name);
} else
strcpy(sym, handle->name);
strcat(sym, "_LTX_");
strcat(sym, symbol);
/* try "modulename_LTX_symbol" */
address = handle->type->find_sym(handle, sym);
if (address) {
if (sym != lsym)
lt_dlfree(sym);
return address;
}
last_error = saved_error;

}
/* otherwise try "symbol" */
if (handle->type->sym_prefix) {
strcpy(sym, handle->type->sym_prefix);
strcat(sym, symbol);
} else
strcpy(sym, symbol);
address = handle->type->find_sym(handle, sym);
if (sym != lsym)
lt_dlfree(sym);
return address;

const char *
lt_dlerror LTDL_PARAMS((void))
{
const char *error = last_error;

last_error = 0;
return error;

int
lt_dladdsearchdir (search_dir)
const char *search_dir;
{
if (!search_dir || !strlen(search_dir))
return 0;
if (!user_search_path) {
user_search_path = strdup(search_dir);
if (!user_search_path) {
last_error = memory_error;
return 1;
}
} else {
char
*new_search_path = (char*)
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.c

1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624

Saturday, June 16, 2012 11:35 PM

lt_dlmalloc(strlen(user_search_path) +
strlen(search_dir) + 2); /* ':' + '\0' == 2 */
if (!new_search_path) {
last_error = memory_error;
return 1;
}
strcpy(new_search_path, user_search_path);
strcat(new_search_path, ":");
strcat(new_search_path, search_dir);
lt_dlfree(user_search_path);
user_search_path = new_search_path;

}
return 0;

int
lt_dlsetsearchpath (search_path)
const char *search_path;
{
if (user_search_path)
lt_dlfree(user_search_path);
user_search_path = 0; /* reset the search path */
if (!search_path || !strlen(search_path))
return 0;
user_search_path = strdup(search_path);
if (!user_search_path)
return 1;
return 0;
}
const char *
lt_dlgetsearchpath LTDL_PARAMS((void))
{
return user_search_path;
}

-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Saturday, June 16, 2012 11:07 PM

/* ltdl.h -- generic dlopen functions


Copyright (C) 1998-1999 Free Software Foundation, Inc.
Originally by Thomas Tanner <tanner@ffii.org>
This file is part of GNU Libtool.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
As a special exception to the GNU Library General Public License,
if you distribute this file as part of a program that uses GNU libtool
to create libraries and programs, you may include it under the same
distribution terms that you use for the rest of that program.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
/* Only include this header file once. */
#ifndef _LTDL_H_
#define _LTDL_H_ 1
/* __BEGIN_DECLS should be used at the beginning of your declarations,
so that C++ compilers don't mangle their names. Use __END_DECLS at
the end of C declarations. */
#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS /* empty */
# define __END_DECLS /* empty */
#endif
/* LTDL_PARAMS is a macro used to wrap function prototypes, so that compilers
that don't understand ANSI C prototypes still work, and ANSI C
compilers can issue warnings about type mismatches. */
#undef LTDL_PARAMS
#undef lt_ptr_t
#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined
(_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus)
# define LTDL_PARAMS(protos)
protos
# define lt_ptr_t
void*
#else
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\ltdl.h

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

# define LTDL_PARAMS(protos)
# define lt_ptr_t
char*
#endif

Saturday, June 16, 2012 11:07 PM

()

#include <stdlib.h>
#ifdef _LTDL_COMPILE_
typedef struct lt_dlhandle_t *lt_dlhandle;
#else
typedef lt_ptr_t lt_dlhandle;
#endif
typedef struct {
const char *name;
lt_ptr_t address;
} lt_dlsymlist;
__BEGIN_DECLS
extern int lt_dlinit LTDL_PARAMS((void));
extern int lt_dlpreload LTDL_PARAMS((const lt_dlsymlist *preloaded));
extern int lt_dlpreload_default LTDL_PARAMS((const lt_dlsymlist *preloaded));
extern int lt_dlexit LTDL_PARAMS((void));
extern lt_dlhandle lt_dlopen LTDL_PARAMS((const char *filename));
extern lt_dlhandle lt_dlopenext LTDL_PARAMS((const char *filename));
extern int lt_dlclose LTDL_PARAMS((lt_dlhandle handle));
extern lt_ptr_t lt_dlsym LTDL_PARAMS((lt_dlhandle handle, const char *name));
extern const char *lt_dlerror LTDL_PARAMS((void));
extern int lt_dladdsearchdir LTDL_PARAMS((const char *search_dir));
extern int lt_dlsetsearchpath LTDL_PARAMS((const char *search_path));
extern const char *lt_dlgetsearchpath LTDL_PARAMS((void));
extern const lt_dlsymlist lt_preloaded_symbols[];
#define LTDL_SET_PRELOADED_SYMBOLS() lt_dlpreload_default(lt_preloaded_symbols)
extern lt_ptr_t (*lt_dlmalloc)LTDL_PARAMS((size_t size));
extern void (*lt_dlfree)LTDL_PARAMS((lt_ptr_t ptr));
__END_DECLS
#endif /* !_LTDL_H_ */

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:35 PM

/* DO NOT EDIT THIS FILE -- it is automagically generated.

-*- C -*- */

#define _MALLOC_INTERNAL
/* The malloc headers and source files from the C library follow here.
/* Declarations for `malloc' and friends.
Copyright 1990, 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
Written May 1989 by Mike Haertel.

*/

This library is free software; you can redistribute it and/or


modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#ifndef _MALLOC_H
#define _MALLOC_H

#ifdef _MALLOC_INTERNAL
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define NO_FIX_MALLOC
#include "copyright.h"
#include "autoconf.h"
#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
#include <string.h>
#else
#ifndef memset
#define memset(s, zero, n) bzero ((s), (n))
#endif
#ifndef memcpy
#define memcpy(d, s, n)
bcopy ((s), (d), (n))
#endif
#endif
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:35 PM

#if defined (__GNU_LIBRARY__) || (defined (__STDC__) && __STDC__)


#include <limits.h>
#else
#ifndef CHAR_BIT
#define CHAR_BIT
8
#endif
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif

/* _MALLOC_INTERNAL.

*/

#ifdef __cplusplus
extern "C"
{
#endif
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
#undef __P
#define __P(args)
args
#undef __ptr_t
#define __ptr_t
void *
#else /* Not C++ or ANSI C. */
#undef __P
#define __P(args)
()
#undef const
#define const
#undef __ptr_t
#define __ptr_t
char *
#endif /* C++ or ANSI C. */
#if defined (__STDC__) && __STDC__
#include <stddef.h>
#define __malloc_size_t
size_t
#define __malloc_ptrdiff_t ptrdiff_t
#else
#define __malloc_size_t
unsigned int
#define __malloc_ptrdiff_t int
#endif
#ifndef NULL
#define NULL
#endif

/* Allocate SIZE bytes of memory. */


extern __ptr_t malloc __P ((__malloc_size_t __size));
/* Re-allocate the previously allocated block
in __ptr_t, making the new block SIZE bytes long. */
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:35 PM

extern __ptr_t realloc __P ((__ptr_t __ptr, __malloc_size_t __size));


/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
extern __ptr_t calloc __P ((__malloc_size_t __nmemb, __malloc_size_t __size));
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
extern void free __P ((__ptr_t __ptr));
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
extern __ptr_t memalign __P ((__malloc_size_t __alignment,
__malloc_size_t __size));
/* Allocate SIZE bytes on a page boundary. */
extern __ptr_t valloc __P ((__malloc_size_t __size));
#ifdef _MALLOC_INTERNAL
/* The allocator divides the heap into blocks of fixed size; large
requests receive one or more whole blocks, and small requests
receive a fragment of a block. Fragment sizes are powers of two,
and all fragments of a block are the same size. When all the
fragments in a block have been freed, the block itself is freed. */
#define INT_BIT
(CHAR_BIT * sizeof(int))
#define BLOCKLOG
(INT_BIT > 16 ? 12 : 9)
#define BLOCKSIZE
(1 << BLOCKLOG)
#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
/* Determine the amount of memory spanned by the initial heap table
(not an absolute limit). */
#define HEAP
(INT_BIT > 16 ? 4194304 : 65536)
/* Number of contiguous free blocks allowed to build up at the end of
memory before they will be returned to the system. */
#define FINAL_FREE_BLOCKS
8
/* Data structure giving per-block information. */
typedef union
{
/* Heap information for a busy block. */
struct
{
/* Zero for a large (multiblock) object, or positive giving the
logarithm to the base two of the fragment size. */
int type;
union
{
struct
{
__malloc_size_t nfree; /* Free frags in a fragmented block. */
__malloc_size_t first; /* First free fragment of the block. */
} frag;
/* For a large object, in its first block, this has the number
of blocks in the object. In the other blocks, this has a
negative number which says how far back the first block is. */
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:35 PM

__malloc_ptrdiff_t size;
} info;
} busy;
/* Heap information for a free block
(that may be the first of a free cluster). */
struct
{
__malloc_size_t size;
/* Size (in blocks) of a free cluster.
__malloc_size_t next;
/* Index of next free cluster. */
__malloc_size_t prev;
/* Index of previous free cluster. */
} free;
} malloc_info;
/* Pointer to first block of the heap.
extern char *_heapbase;

*/

*/

/* Table indexed by block number giving per-block information.


extern malloc_info *_heapinfo;

*/

/* Address to block number and vice versa. */


#define BLOCK(A)
(((char *) (A) - _heapbase) / BLOCKSIZE + 1)
#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
/* Current search index for the heap table.
extern __malloc_size_t _heapindex;
/* Limit of valid info table indices.
extern __malloc_size_t _heaplimit;

*/

*/

/* Doubly linked lists of free fragments.


struct list
{
struct list *next;
struct list *prev;
};

*/

/* Free list headers for each fragment size.


extern struct list _fraghead[];

*/

/* List of blocks allocated with `memalign' (or `valloc'). */


struct alignlist
{
struct alignlist *next;
__ptr_t aligned;
/* The address that memaligned returned.
__ptr_t exact;
/* The address that malloc returned. */
};
extern struct alignlist *_aligned_blocks;
/* Instrumentation. */
extern __malloc_size_t _chunks_used;
extern __malloc_size_t _bytes_used;
extern __malloc_size_t _chunks_free;
extern __malloc_size_t _bytes_free;
-4-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:35 PM

/* Internal version of `free' used in `morecore' (malloc.c). */


extern void _free_internal __P ((__ptr_t __ptr));
#endif /* _MALLOC_INTERNAL.

*/

/* Given an address in the middle of a malloc'd object,


return the address of the beginning of the object. */
extern __ptr_t malloc_find_object_address __P ((__ptr_t __ptr));
/* Underlying allocation function; successive calls should
return contiguous pieces of memory. */
extern __ptr_t (*__morecore) __P ((__malloc_ptrdiff_t __size));
/* Default value of `__morecore'. */
extern __ptr_t __default_morecore __P ((__malloc_ptrdiff_t __size));
/* If not NULL, this function is called after each time
`__morecore' is called to increase the data size. */
extern void (*__after_morecore_hook) __P ((void));
/* Nonzero if `malloc' has been called and done its initialization.
extern int __malloc_initialized;

*/

/* Hooks for debugging versions. */


extern void (*__malloc_initialize_hook) __P ((void));
extern void (*__free_hook) __P ((__ptr_t __ptr));
extern __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size));
extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size));
extern __ptr_t (*__memalign_hook) __P ((__malloc_size_t __size,
__malloc_size_t __alignment));
/* Return values for `mprobe': these are the kinds of inconsistencies that
`mcheck' enables detection of. */
enum mcheck_status
{
MCHECK_DISABLED = -1,
/* Consistency checking is not turned on. */
MCHECK_OK,
/* Block is fine. */
MCHECK_FREE,
/* Block freed twice. */
MCHECK_HEAD,
/* Memory before the block was clobbered. */
MCHECK_TAIL
/* Memory after the block was clobbered. */
};
/* Activate a standard collection of debugging hooks. This must be called
before `malloc' is ever called. ABORTFUNC is called with an error code
(see enum above) when an inconsistency is detected. If ABORTFUNC is
null, the standard function prints on stderr and then calls `abort'. */
extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status))));
/* Check for aberrations in a particular malloc'd block. You must have
called `mcheck' already. These are the same checks that `mcheck' does
when you free or reallocate a block. */
extern enum mcheck_status mprobe __P ((__ptr_t __ptr));
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:35 PM

/* Activate a standard collection of tracing hooks.


extern void mtrace __P ((void));
extern void muntrace __P ((void));

*/

/* Statistics available to the user. */


struct mstats
{
__malloc_size_t bytes_total; /* Total size of the heap. */
__malloc_size_t chunks_used; /* Chunks allocated by the user. */
__malloc_size_t bytes_used; /* Byte total of user-allocated chunks. */
__malloc_size_t chunks_free; /* Chunks in the free list. */
__malloc_size_t bytes_free; /* Byte total of chunks in the free list. */
};
/* Pick up the current statistics. */
extern struct mstats mstats __P ((void));
/* Call WARNFUN with a warning message when memory usage is high.
extern void memory_warnings __P ((__ptr_t __start,
void (*__warnfun) __P ((const char *))));
/* Relocating allocator.

*/

*/

/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */


extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size));
/* Free the storage allocated in HANDLEPTR. */
extern void r_alloc_free __P ((__ptr_t *__handleptr));
/* Adjust the block at HANDLEPTR to be SIZE bytes long. */
extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size));
#ifdef
}
#endif

__cplusplus

#endif /* malloc.h */
/* Allocate memory on a page boundary.
Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:35 PM

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#if defined (__GNU_LIBRARY__) || defined (_LIBC)
#include <stddef.h>
#include <sys/cdefs.h>
extern size_t __getpagesize __P ((void));
#else
#include "getpagesize.h"
#define __getpagesize()
getpagesize()
#endif
#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include <malloc.h>
#endif
static __malloc_size_t pagesize;
__ptr_t
valloc (size)
__malloc_size_t size;
{
if (pagesize == 0)
pagesize = __getpagesize ();
return memalign (pagesize, size);
}
/* Memory allocator `malloc'.
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
Written May 1989 by Mike Haertel.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:35 PM

or (US mail) as Mike Haertel c/o Free Software Foundation.

*/

#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include <malloc.h>
#endif
/* How to really get more memory. */
__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
/* Debugging hook for `malloc'. */
__ptr_t (*__malloc_hook) __P ((__malloc_size_t __size));
/* Pointer to the base of the first block.
char *_heapbase;
/* Block information table.
malloc_info *_heapinfo;

*/

Allocated with align/__free (not malloc/free).

/* Number of info entries. */


static __malloc_size_t heapsize;
/* Search index in the info table.
__malloc_size_t _heapindex;

*/

/* Limit of valid info table indices.


__malloc_size_t _heaplimit;

*/

/* Free lists for each fragment size.


struct list _fraghead[BLOCKLOG];

*/

/* Instrumentation. */
__malloc_size_t _chunks_used;
__malloc_size_t _bytes_used;
__malloc_size_t _chunks_free;
__malloc_size_t _bytes_free;
/* Are you experienced? */
int __malloc_initialized;
void (*__malloc_initialize_hook) __P ((void));
void (*__after_morecore_hook) __P ((void));
/* Aligned allocation. */
static __ptr_t align __P ((__malloc_size_t));
static __ptr_t
align (size)
__malloc_size_t size;
{
__ptr_t result;
unsigned long int adj;
result = (*__morecore) (size);
-8-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:35 PM

adj = (unsigned long int) ((unsigned long int) ((char *) result (char *) NULL)) % BLOCKSIZE;
if (adj != 0)
{
adj = BLOCKSIZE - adj;
(void) (*__morecore) (adj);
result = (char *) result + adj;
}
if (__after_morecore_hook)
(*__after_morecore_hook) ();
}

return result;

/* Set everything up and remember that we have.


static int initialize __P ((void));
static int
initialize ()
{
if (__malloc_initialize_hook)
(*__malloc_initialize_hook) ();

*/

heapsize = HEAP / BLOCKSIZE;


_heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
if (_heapinfo == NULL)
return 0;
memset ((void *)_heapinfo, 0, heapsize * sizeof (malloc_info));
_heapinfo[0].free.size = 0;
_heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
_heapindex = 0;
_heapbase = (char *) _heapinfo;
/* Account for the _heapinfo block itself in the statistics.
_bytes_used = heapsize * sizeof (malloc_info);
_chunks_used = 1;

__malloc_initialized = 1;
return 1;

/* Get neatly aligned memory, initializing or


growing the heap info table as necessary. */
static __ptr_t morecore __P ((__malloc_size_t));
static __ptr_t
morecore (size)
__malloc_size_t size;
{
__ptr_t result;
malloc_info *newinfo, *oldinfo;
__malloc_size_t newsize;
result = align (size);
-9-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:35 PM

if (result == NULL)
return NULL;
/* Check if we need to grow the info table. */
if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize)
{
newsize = heapsize;
while ((__malloc_size_t) BLOCK ((char *) result + size) > newsize)
newsize *= 2;
newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
if (newinfo == NULL)
{
(*__morecore) (-size);
return NULL;
}
memcpy ((void *)newinfo, (const void *)_heapinfo, heapsize * sizeof (malloc_info));
memset ((void *)&newinfo[heapsize], 0,
(newsize - heapsize) * sizeof (malloc_info));
oldinfo = _heapinfo;
newinfo[BLOCK (oldinfo)].busy.type = 0;
newinfo[BLOCK (oldinfo)].busy.info.size
= BLOCKIFY (heapsize * sizeof (malloc_info));
_heapinfo = newinfo;
/* Account for the _heapinfo block itself in the statistics. */
_bytes_used += newsize * sizeof (malloc_info);
++_chunks_used;
_free_internal (oldinfo);
heapsize = newsize;
}

_heaplimit = BLOCK ((char *) result + size);


return result;

/* Allocate memory from the heap. */


__ptr_t
malloc (size)
__malloc_size_t size;
{
__ptr_t result;
__malloc_size_t block, blocks, lastblocks, start;
register __malloc_size_t i;
struct list *next;
/* ANSI C allows `malloc (0)' to either return NULL, or to return a
valid address you can realloc and free (though not dereference).
It turns out that some extant code (sunrpc, at least Ultrix's version)
expects `malloc (0)' to return non-NULL and breaks otherwise.
Be compatible. */
#if 0
if (size == 0)
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:35 PM

return NULL;
#endif
if (__malloc_hook != NULL)
return (*__malloc_hook) (size);
if (!__malloc_initialized)
if (!initialize ())
return NULL;
if (size < sizeof (struct list))
size = sizeof (struct list);
#ifdef SUNOS_LOCALTIME_BUG
if (size < 16)
size = 16;
#endif
/* Determine the allocation policy
if (size <= BLOCKSIZE / 2)
{
/* Small allocation to receive
Determine the logarithm to base
register __malloc_size_t log =
--size;
while ((size /= 2) != 0)
++log;

based on the request size.

*/

a fragment of a block.
two of the fragment size. */
1;

/* Look in the fragment lists for a


free fragment of the desired size. */
next = _fraghead[log].next;
if (next != NULL)

/* There are free fragments of this size.


Pop a fragment out of the fragment list and return it.
Update the block's nfree and first counters. */
result = (__ptr_t) next;
next->prev->next = next->next;
if (next->next != NULL)
next->next->prev = next->prev;
block = BLOCK (result);
if (--_heapinfo[block].busy.info.frag.nfree != 0)
_heapinfo[block].busy.info.frag.first = (unsigned long int)
((unsigned long int) ((char *) next->next - (char *) NULL)
% BLOCKSIZE) >> log;
/* Update the statistics.
++_chunks_used;
_bytes_used += 1 << log;
--_chunks_free;
_bytes_free -= 1 << log;

*/

else
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:35 PM

/* No free fragments of the desired size, so get a new block


and break it into fragments, returning the first. */
result = malloc (BLOCKSIZE);
if (result == NULL)
return NULL;
/* Link all fragments but the first into the free list. */
for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> log); ++i)
{
next = (struct list *) ((char *) result + (i << log));
next->next = _fraghead[log].next;
next->prev = &_fraghead[log];
next->prev->next = next;
if (next->next != NULL)
next->next->prev = next;
}
/* Initialize the nfree and first counters for this block.
block = BLOCK (result);
_heapinfo[block].busy.type = log;
_heapinfo[block].busy.info.frag.nfree = i - 1;
_heapinfo[block].busy.info.frag.first = i - 1;

}
}
else
{

*/

_chunks_free += (BLOCKSIZE >> log) - 1;


_bytes_free += BLOCKSIZE - (1 << log);
_bytes_used -= BLOCKSIZE - (1 << log);

/* Large allocation to receive one or more blocks.


Search the free list in a circle starting at the last place visited.
If we loop completely around without finding a large enough
space we will have to get more memory from the system. */
blocks = BLOCKIFY (size);
start = block = _heapindex;
while (_heapinfo[block].free.size < blocks)
block = _heapinfo[block].free.next;
if (block == start)
{
/* Need to get more from the system. Check to see if
the new core will be contiguous with the final free
block; if so we don't need to get as much. */
block = _heapinfo[0].free.prev;
lastblocks = _heapinfo[block].free.size;
if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
(*__morecore) (0) == ADDRESS (block + lastblocks) &&
(morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL)
{
/* Which block we are extending (the `final free
block' referred to above) might have changed, if
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:35 PM

it got combined with a freed info table. */


block = _heapinfo[0].free.prev;
_heapinfo[block].free.size += (blocks - lastblocks);
_bytes_free += (blocks - lastblocks) * BLOCKSIZE;
continue;

result = morecore (blocks * BLOCKSIZE);


if (result == NULL)
return NULL;
block = BLOCK (result);
_heapinfo[block].busy.type = 0;
_heapinfo[block].busy.info.size = blocks;
++_chunks_used;
_bytes_used += blocks * BLOCKSIZE;
return result;
}
/* At this point we have found a suitable free list entry.
Figure out how to remove what we need from the list. */
result = ADDRESS (block);
if (_heapinfo[block].free.size > blocks)

}
{

/* The block we found has a bit left over,


so relink the tail end back into the free list. */
_heapinfo[block + blocks].free.size
= _heapinfo[block].free.size - blocks;
_heapinfo[block + blocks].free.next
= _heapinfo[block].free.next;
_heapinfo[block + blocks].free.prev
= _heapinfo[block].free.prev;
_heapinfo[_heapinfo[block].free.prev].free.next
= _heapinfo[_heapinfo[block].free.next].free.prev
= _heapindex = block + blocks;
else
/* The block exactly matches our requirements,
so just remove it from the list. */
_heapinfo[_heapinfo[block].free.next].free.prev
= _heapinfo[block].free.prev;
_heapinfo[_heapinfo[block].free.prev].free.next
= _heapindex = _heapinfo[block].free.next;
--_chunks_free;
_heapinfo[block].busy.type = 0;
_heapinfo[block].busy.info.size = blocks;
++_chunks_used;
_bytes_used += blocks * BLOCKSIZE;
_bytes_free -= blocks * BLOCKSIZE;
/* Mark all the blocks of the object just allocated except for the
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:35 PM

first with a negative number so you can find the first block by
adding that adjustment. */
while (--blocks > 0)
_heapinfo[block + blocks].busy.info.size = -blocks;
}
return result;

}
FF
#ifndef _LIBC

/* On some ANSI C systems, some libc functions call _malloc, _free


and _realloc. Make them use the GNU functions. */
__ptr_t
_malloc (size)
__malloc_size_t size;
{
return malloc (size);
}
void
_free (ptr)
__ptr_t ptr;
{
free (ptr);
}
__ptr_t
_realloc (ptr, size)
__ptr_t ptr;
__malloc_size_t size;
{
return realloc (ptr, size);
}
#endif
/* Free a block of memory allocated by `malloc'.
Copyright 1990, 1991, 1992, 1994 Free Software Foundation, Inc.
Written May 1989 by Mike Haertel.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:35 PM

not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include <malloc.h>
#endif
/* Debugging hook for free. */
void (*__free_hook) __P ((__ptr_t __ptr));
/* List of blocks allocated by memalign. */
struct alignlist *_aligned_blocks = NULL;
/* Return memory to the heap.
Like `free' but don't call a __free_hook if there is one.
void
_free_internal (ptr)
__ptr_t ptr;
{
int type;
__malloc_size_t block, blocks;
register __malloc_size_t i;
struct list *prev, *next;

*/

block = BLOCK (ptr);


type = _heapinfo[block].busy.type;
switch (type)
{
case 0:
/* Get as many statistics as early as we can. */
--_chunks_used;
_bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
_bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
/* Find the free cluster previous to this one in the free list.
Start searching at the last block referenced; this may benefit
programs with locality of allocation. */
i = _heapindex;
if (i > block)
while (i > block)
i = _heapinfo[i].free.prev;
else
{
do
i = _heapinfo[i].free.next;
while (i > 0 && i < block);
i = _heapinfo[i].free.prev;
}
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:35 PM

/* Determine how to link this block into the free list.


if (block == i + _heapinfo[i].free.size)

*/

/* Coalesce this block with its predecessor. */


_heapinfo[i].free.size += _heapinfo[block].busy.info.size;
block = i;
else

/* Really link this block back into the free list. */


_heapinfo[block].free.size = _heapinfo[block].busy.info.size;
_heapinfo[block].free.next = _heapinfo[i].free.next;
_heapinfo[block].free.prev = i;
_heapinfo[i].free.next = block;
_heapinfo[_heapinfo[block].free.next].free.prev = block;
++_chunks_free;
/* Now that the block is linked in, see if we can coalesce it
with its successor (by deleting its successor from the list
and adding in its size). */
if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)

_heapinfo[block].free.size
+= _heapinfo[_heapinfo[block].free.next].free.size;
_heapinfo[block].free.next
= _heapinfo[_heapinfo[block].free.next].free.next;
_heapinfo[_heapinfo[block].free.next].free.prev = block;
--_chunks_free;
/* Now see if we can return stuff to the system. */
blocks = _heapinfo[block].free.size;
if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
&& (*__morecore) (0) == ADDRESS (block + blocks))
register __malloc_size_t bytes = blocks * BLOCKSIZE;
_heaplimit -= blocks;
(*__morecore) (-bytes);
_heapinfo[_heapinfo[block].free.prev].free.next
= _heapinfo[block].free.next;
_heapinfo[_heapinfo[block].free.next].free.prev
= _heapinfo[block].free.prev;
block = _heapinfo[block].free.prev;
--_chunks_free;
_bytes_free -= bytes;
/* Set the next search to begin at this block.
_heapindex = block;
break;

-16-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

default:
/* Do some of the statistics.
--_chunks_used;
_bytes_used -= 1 << type;
++_chunks_free;
_bytes_free += 1 << type;

Saturday, June 16, 2012 11:35 PM

*/

/* Get the address of the first free fragment in this block.


prev = (struct list *) ((char *) ADDRESS (block) +
(_heapinfo[block].busy.info.frag.first << type));
{

if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)


/* If all fragments of this block are free, remove them
from the fragment list and free the whole block. */
next = prev;
for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> type); ++i)
next = next->next;
prev->prev->next = next;
if (next != NULL)
next->prev = prev->prev;
_heapinfo[block].busy.type = 0;
_heapinfo[block].busy.info.size = 1;
/* Keep the statistics accurate. */
++_chunks_used;
_bytes_used += BLOCKSIZE;
_chunks_free -= BLOCKSIZE >> type;
_bytes_free -= BLOCKSIZE;

}
{

}
{

*/

free (ADDRESS (block));


else if (_heapinfo[block].busy.info.frag.nfree != 0)
/* If some fragments of this block are free, link this
fragment into the fragment list after the first free
fragment of this block. */
next = (struct list *) ptr;
next->next = prev->next;
next->prev = prev;
prev->next = next;
if (next->next != NULL)
next->next->prev = next;
++_heapinfo[block].busy.info.frag.nfree;
else
/* No fragments of this block are free, so link this
fragment into the fragment list and announce that
it is the first free fragment of this block. */
prev = (struct list *) ptr;
_heapinfo[block].busy.info.frag.nfree = 1;
_heapinfo[block].busy.info.frag.first = (unsigned long int)
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

}
}

Saturday, June 16, 2012 11:35 PM

((unsigned long int) ((char *) ptr - (char *) NULL)


% BLOCKSIZE >> type);
prev->next = _fraghead[type].next;
prev->prev = &_fraghead[type];
prev->prev->next = prev;
if (prev->next != NULL)
prev->next->prev = prev;
break;

/* Return memory to the heap. */


void
free (ptr)
__ptr_t ptr;
{
register struct alignlist *l;
if (ptr == NULL)
return;
for (l = _aligned_blocks; l != NULL; l = l->next)
if (l->aligned == ptr)
{
l->aligned = NULL; /* Mark the slot in the list as free.
ptr = l->exact;
break;
}

*/

if (__free_hook != NULL)
(*__free_hook) (ptr);
else
_free_internal (ptr);

}
/* Change the size of a block allocated by `malloc'.
Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
Written May 1989 by Mike Haertel.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:35 PM

The author may be reached (Email) at the address mike@ai.mit.edu,


or (US mail) as Mike Haertel c/o Free Software Foundation. */
#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include <malloc.h>
#endif
#if

(defined (MEMMOVE_MISSING) || \
!defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))

/* Snarfed directly from Emacs src/dispnew.c:


XXX Should use system bcopy if it handles overlap.
#ifndef emacs
/* Like bcopy except never gets confused by overlap.

*/
*/

static void
safe_bcopy (from, to, size)
char *from, *to;
int size;
{
if (size <= 0 || from == to)
return;
/* If the source and destination don't overlap, then bcopy can
handle it. If they do overlap, but the destination is lower in
memory than the source, we'll assume bcopy can handle that. */
if (to < from || from + size <= to)
bcopy (from, to, size);
/* Otherwise, we'll copy from the end.
else
{
register char *endf = from + size;
register char *endt = to + size;

*/

/* If TO - FROM is large, then we should break the copy into


nonoverlapping chunks of TO - FROM bytes each. However, if
TO - FROM is small, then the bcopy function call overhead
makes this not worth it. The crossover point could be about
anywhere. Since I don't think the obvious copy loop is too
bad, I'm trying to err in its favor. */
if (to - from < 64)

}
{

do

*--endt = *--endf;
while (endf != from);
else
for (;;)
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:35 PM

endt -= (to - from);


endf -= (to - from);

if (endt < to)


break;
}

}
}

}
#endif

bcopy (endf, endt, to - from);

/* If SIZE wasn't a multiple of TO - FROM, there will be a


little left over. The amount left over is
(endt + (to - from)) - to, which is endt - from. */
bcopy (from, to, endt - from);

/* Not emacs.

*/

#define memmove(to, from, size)

bcopy((from), (to), (size))

#endif
#define min(A, B) ((A) < (B) ? (A) : (B))
/* Debugging hook for realloc. */
__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size));
/* Resize the given region to the new size, returning a pointer
to the (possibly moved) region. This is optimized for speed;
some benchmarks seem to indicate that greater compactness is
achieved by unconditionally allocating and copying to a
new region. This module has incestuous knowledge of the
internals of both free and malloc. */
__ptr_t
realloc (ptr, size)
__ptr_t ptr;
__malloc_size_t size;
{
__ptr_t result;
int type;
__malloc_size_t block, blocks, oldlimit;
if (size == 0)
{
free (ptr);
return malloc (0);
}
else if (ptr == NULL)
return malloc (size);
if (__realloc_hook != NULL)
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:35 PM

return (*__realloc_hook) (ptr, size);


block = BLOCK (ptr);
type = _heapinfo[block].busy.type;
switch (type)
{
case 0:
/* Maybe reallocate a large block to a small fragment.
if (size <= BLOCKSIZE / 2)
{
result = malloc (size);
if (result != NULL)
{
memcpy (result, ptr, size);
_free_internal (ptr);
return result;
}
}

*/

/* The new size is a large allocation as well;


see if we can hold it in place. */
blocks = BLOCKIFY (size);
if (blocks < _heapinfo[block].busy.info.size)

/* The new size is smaller; return


excess memory to the free list. */
_heapinfo[block + blocks].busy.type = 0;
_heapinfo[block + blocks].busy.info.size
= _heapinfo[block].busy.info.size - blocks;
_heapinfo[block].busy.info.size = blocks;
/* We have just created a new chunk by splitting a chunk in two.
Now we will free this chunk; increment the statistics counter
so it doesn't become wrong when _free_internal decrements it.
++_chunks_used;
_free_internal (ADDRESS (block + blocks));
result = ptr;

else if (blocks == _heapinfo[block].busy.info.size)


/* No size change necessary. */
result = ptr;
else
{
/* Won't fit, so allocate a new region that will.
Free the old region first in case there is sufficient
adjacent free space to grow without moving. */
blocks = _heapinfo[block].busy.info.size;
/* Prevent free from actually returning memory to the system.
oldlimit = _heaplimit;
_heaplimit = 0;
_free_internal (ptr);
_heaplimit = oldlimit;
result = malloc (size);
-21-

*/

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

Saturday, June 16, 2012 11:35 PM

if (result == NULL)
{
/* Now we're really in trouble. We have to unfree
the thing we just freed. Unfortunately it might
have been coalesced with its neighbors. */
if (_heapindex == block)
(void) malloc (blocks * BLOCKSIZE);
else
{
__ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
(void) malloc (blocks * BLOCKSIZE);
_free_internal (previous);
}
return NULL;
}
if (ptr != result)
bcopy (ptr, result, blocks * BLOCKSIZE);
break;

default:
/* Old size is a fragment; type is logarithm
to base two of the fragment size. */
if (size > (__malloc_size_t) (1 << (type - 1)) &&
size <= (__malloc_size_t) (1 << type))
/* The new size is the same kind of fragment. */
result = ptr;
else
{
/* The new size is different; allocate a new space,
and copy the lesser of the new size and the old. */
result = malloc (size);
if (result == NULL)
return NULL;
memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type));
free (ptr);
}
break;
}
return result;

}
/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

Saturday, June 16, 2012 11:35 PM

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include <malloc.h>
#endif
/* Allocate an array of NMEMB elements each SIZE bytes long.
The entire array is initialized to zeros. */
__ptr_t
calloc (nmemb, size)
register __malloc_size_t nmemb;
register __malloc_size_t size;
{
register __ptr_t result = malloc (nmemb * size);
if (result != NULL)
(void) memset (result, 0, nmemb * size);
return result;

}
/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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, or (at your option)
any later version.
The GNU C Library 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 the GNU C Library; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include <malloc.h>
#endif
#ifndef __GNU_LIBRARY__
#define __sbrk sbrk
#endif
-23-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

Saturday, June 16, 2012 11:35 PM

#ifdef __GNU_LIBRARY__
/* It is best not to declare this and cast its result on foreign operating
systems with potentially hostile include files. */
extern __ptr_t __sbrk __P ((int increment));
#endif
#ifndef NULL
#define NULL 0
#endif
/* Allocate INCREMENT more bytes of data space,
and return the start of data space, or NULL on errors.
If INCREMENT is negative, shrink data space. */
__ptr_t
__default_morecore (increment)
#ifdef __STDC__
ptrdiff_t increment;
#else
int increment;
#endif
{
__ptr_t result = (__ptr_t) __sbrk ((int) increment);
if (result == (__ptr_t) -1)
return NULL;
return result;
}
/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include <malloc.h>
#endif
__ptr_t (*__memalign_hook) __P ((size_t __size, size_t __alignment));
__ptr_t
memalign (alignment, size)
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.c

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313

Saturday, June 16, 2012 11:35 PM

__malloc_size_t alignment;
__malloc_size_t size;
__ptr_t result;
unsigned long int adj;
if (__memalign_hook)
return (*__memalign_hook) (alignment, size);
size = ((size + alignment - 1) / alignment) * alignment;
result = malloc (size);
if (result == NULL)
return NULL;
adj = (unsigned long int) ((unsigned long int) ((char *) result (char *) NULL)) % alignment;
if (adj != 0)
{
struct alignlist *l;
for (l = _aligned_blocks; l != NULL; l = l->next)
if (l->aligned == NULL)
/* This slot is free. Use it. */
break;
if (l == NULL)
{
l = (struct alignlist *) malloc (sizeof (struct alignlist));
if (l == NULL)
{
free (result);
return NULL;
}
l->next = _aligned_blocks;
_aligned_blocks = l;
}
l->exact = result;
result = l->aligned = (char *) result + alignment - adj;
}

return result;

-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:06 PM

/* Declarations for `malloc' and friends.


Copyright 1990, 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
Written May 1989 by Mike Haertel.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is
but WITHOUT ANY
MERCHANTABILITY
Library General

distributed in the hope that it will be useful,


WARRANTY; without even the implied warranty of
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#ifndef MALLOC_H
#define MALLOC_H

#ifdef _MALLOC_INTERNAL
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
#include <string.h>
#else
#ifndef memset
#define memset(s, zero, n) bzero ((s), (n))
#endif
#ifndef memcpy
#define memcpy(d, s, n)
bcopy ((s), (d), (n))
#endif
#endif
#if defined (__GNU_LIBRARY__) || (defined (__STDC__) && __STDC__)
#include <limits.h>
#else
#ifndef CHAR_BIT
#define CHAR_BIT
8
#endif
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:06 PM

#endif
#endif

/* _MALLOC_INTERNAL.

*/

#ifdef __cplusplus
extern "C"
{
#endif
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
#undef __P
#define __P(args)
args
#undef __ptr_t
#define __ptr_t
void *
#else /* Not C++ or ANSI C. */
#undef __P
#define __P(args)
()
#undef const
#define const
#undef __ptr_t
#define __ptr_t
char *
#endif /* C++ or ANSI C. */
#if defined (__STDC__) && __STDC__
#include <stddef.h>
#define __malloc_size_t
size_t
#define __malloc_ptrdiff_t ptrdiff_t
#else
#define __malloc_size_t
unsigned int
#define __malloc_ptrdiff_t int
#endif
#ifndef NULL
#define NULL
#endif

/* Allocate SIZE bytes of memory. */


extern __ptr_t malloc __P ((__malloc_size_t __size));
/* Re-allocate the previously allocated block
in __ptr_t, making the new block SIZE bytes long. */
extern __ptr_t realloc __P ((__ptr_t __ptr, __malloc_size_t __size));
/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
extern __ptr_t calloc __P ((__malloc_size_t __nmemb, __malloc_size_t __size));
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
extern void free __P ((__ptr_t __ptr));
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
extern __ptr_t memalign __P ((__malloc_size_t __alignment,
__malloc_size_t __size));
/* Allocate SIZE bytes on a page boundary.
-2-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:06 PM

extern __ptr_t valloc __P ((__malloc_size_t __size));


/* The allocator divides the heap into blocks of fixed size; large
requests receive one or more whole blocks, and small requests
receive a fragment of a block. Fragment sizes are powers of two,
and all fragments of a block are the same size. When all the
fragments in a block have been freed, the block itself is freed. */
#define INT_BIT
(CHAR_BIT * sizeof(int))
#define BLOCKLOG
(INT_BIT > 16 ? 12 : 9)
#define BLOCKSIZE
(1 << BLOCKLOG)
#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
/* Determine the amount of memory spanned by the initial heap table
(not an absolute limit). */
#define HEAP
(INT_BIT > 16 ? 4194304 : 65536)
/* Number of contiguous free blocks allowed to build up at the end of
memory before they will be returned to the system. */
#define FINAL_FREE_BLOCKS
8
/* Data structure giving per-block information. */
typedef union
{
/* Heap information for a busy block. */
struct
{
/* Zero for a large (multiblock) object, or positive giving the
logarithm to the base two of the fragment size. */
int type;
union
{
struct
{
__malloc_size_t nfree; /* Free frags in a fragmented block. */
__malloc_size_t first; /* First free fragment of the block. */
} frag;
/* For a large object, in its first block, this has the number
of blocks in the object. In the other blocks, this has a
negative number which says how far back the first block is. */
__malloc_ptrdiff_t size;
} info;
} busy;
/* Heap information for a free block
(that may be the first of a free cluster). */
struct
{
__malloc_size_t size;
/* Size (in blocks) of a free cluster. */
__malloc_size_t next;
/* Index of next free cluster. */
__malloc_size_t prev;
/* Index of previous free cluster. */
} free;
} malloc_info;

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

/* Pointer to first block of the heap.


extern char *_heapbase;

Saturday, June 16, 2012 11:06 PM

*/

/* Table indexed by block number giving per-block information.


extern malloc_info *_heapinfo;

*/

/* Address to block number and vice versa. */


#define BLOCK(A)
(((char *) (A) - _heapbase) / BLOCKSIZE + 1)
#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
/* Current search index for the heap table.
extern __malloc_size_t _heapindex;
/* Limit of valid info table indices.
extern __malloc_size_t _heaplimit;

*/

*/

/* Doubly linked lists of free fragments.


struct list
{
struct list *next;
struct list *prev;
};

*/

/* Free list headers for each fragment size.


extern struct list _fraghead[];

*/

/* List of blocks allocated with `memalign' (or `valloc'). */


struct alignlist
{
struct alignlist *next;
__ptr_t aligned;
/* The address that memaligned returned.
__ptr_t exact;
/* The address that malloc returned. */
};
extern struct alignlist *_aligned_blocks;
/* Instrumentation. */
extern __malloc_size_t _chunks_used;
extern __malloc_size_t _bytes_used;
extern __malloc_size_t _chunks_free;
extern __malloc_size_t _bytes_free;
/* Internal version of `free' used in `morecore' (malloc.c). */
extern void _free_internal __P ((__ptr_t __ptr));
/* Given an address in the middle of a malloc'd object,
return the address of the beginning of the object. */
extern __ptr_t malloc_find_object_address __P ((__ptr_t __ptr));
/* Underlying allocation function; successive calls should
return contiguous pieces of memory. */
extern __ptr_t (*__morecore) __P ((__malloc_ptrdiff_t __size));
/* Default value of `__morecore'.

*/
-4-

*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:06 PM

extern __ptr_t __default_morecore __P ((__malloc_ptrdiff_t __size));


/* If not NULL, this function is called after each time
`__morecore' is called to increase the data size. */
extern void (*__after_morecore_hook) __P ((void));
/* Nonzero if `malloc' has been called and done its initialization.
extern int __malloc_initialized;

*/

/* Hooks for debugging versions. */


extern void (*__malloc_initialize_hook) __P ((void));
extern void (*__free_hook) __P ((__ptr_t __ptr));
extern __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size));
extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size));
extern __ptr_t (*__memalign_hook) __P ((__malloc_size_t __size,
__malloc_size_t __alignment));
/* Return values for `mprobe': these are the kinds of inconsistencies that
`mcheck' enables detection of. */
enum mcheck_status
{
MCHECK_DISABLED = -1,
/* Consistency checking is not turned on. */
MCHECK_OK,
/* Block is fine. */
MCHECK_FREE,
/* Block freed twice. */
MCHECK_HEAD,
/* Memory before the block was clobbered. */
MCHECK_TAIL
/* Memory after the block was clobbered. */
};
/* Activate a standard collection of debugging hooks. This must be called
before `malloc' is ever called. ABORTFUNC is called with an error code
(see enum above) when an inconsistency is detected. If ABORTFUNC is
null, the standard function prints on stderr and then calls `abort'. */
extern int mcheck __P ((void));
/* Check for aberrations in a particular malloc'd block. You must have
called `mcheck' already. These are the same checks that `mcheck' does
when you free or reallocate a block. */
extern enum mcheck_status mprobe __P ((__ptr_t __ptr));
/* Activate a standard collection of tracing hooks.
extern void mtrace __P ((void));
extern void muntrace __P ((void));

*/

/* Statistics available to the user. */


struct mstats
{
__malloc_size_t bytes_total; /* Total size of the heap. */
__malloc_size_t chunks_used; /* Chunks allocated by the user. */
__malloc_size_t bytes_used; /* Byte total of user-allocated chunks. */
__malloc_size_t chunks_free; /* Chunks in the free list. */
__malloc_size_t bytes_free; /* Byte total of chunks in the free list. */
};

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\malloc.h

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

Saturday, June 16, 2012 11:06 PM

/* Pick up the current statistics. */


extern struct mstats mstats __P ((void));
/* Call WARNFUN with a warning message when memory usage is high.
extern void memory_warnings __P ((__ptr_t __start,
void (*__warnfun) __P ((const char *))));
/* Relocating allocator.

*/

*/

/* Allocate SIZE bytes, and store the address in *HANDLEPTR. */


extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size));
/* Free the storage allocated in HANDLEPTR. */
extern void r_alloc_free __P ((__ptr_t *__handleptr));
/* Adjust the block at HANDLEPTR to be SIZE bytes long. */
extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size));
#ifdef
}
#endif

__cplusplus

#endif /* malloc.h

*/

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:34 PM

/* match.c - Routines for parsing arguments */


/* $Id: match.c,v 1.21 2005/10/19 23:11:55 alierak Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "match.h" /* required by code */
#include "attrs.h" /* required by code */
#include "powers.h" /* required by code */
#define
#define
#define
#define
#define
#define

CON_LOCAL
CON_TYPE
CON_LOCK
CON_COMPLETE
CON_TOKEN
CON_DBREF

0x01
0x02
0x04

/* Match is near me */
/* Match is of requested type */
/* I pass the lock on match */
0x08
/* Name given is the full name */
0x10
/* Name is a special token */
0x20
/* Name is a dbref */

static MSTATE md;


static void promote_match(what, confidence)
dbref what;
int confidence;
{
/* Check for type and locks, if requested */
if (md.pref_type != NOTYPE) {
if (Good_obj(what) && (Typeof(what) == md.pref_type))
confidence |= CON_TYPE;
}
if (md.check_keys) {
MSTATE save_md;
save_match_state(&save_md);
if (Good_obj(what) && could_doit(md.player, what, A_LOCK))
confidence |= CON_LOCK;
restore_match_state(&save_md);

}
/* If nothing matched, take it */
if (md.count == 0) {
md.match = what;
md.confidence = confidence;
md.count = 1;
return;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:34 PM

}
/* If confidence is lower, ignore */
if (confidence < md.confidence) {
return;
}
/* If confidence is higher, replace */
if (confidence > md.confidence) {
md.match = what;
md.confidence = confidence;
md.count = 1;
return;
}
/* Equal confidence, pick randomly */
md.count++;
if (Randomize(md.count) == 0) {
md.match = what;
}
return;

}
/* --------------------------------------------------------------------------* This function removes repeated spaces from the template to which object
* names are being matched. It also removes initial and terminal spaces.
*/
static char *munge_space_for_match(name)
char *name;
{
static char buffer[LBUF_SIZE];
char *p, *q;

p = name;
q = buffer;
while (isspace(*p))
p++;
/* remove inital spaces */
while (*p) {
while (*p && !isspace(*p))
*q++ = *p++;
while (*p && isspace(*++p)) ;
if (*p)
*q++ = ' ';
}
*q = '\0';
/* remove terminal spaces and terminate
* string
*/
return (buffer);

void NDECL(match_player)
{
dbref match;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:34 PM

if (md.confidence >= CON_DBREF) {


return;
}
if (Good_obj(md.absolute_form) && isPlayer(md.absolute_form)) {
promote_match(md.absolute_form, CON_DBREF);
return;
}
if (*md.string == LOOKUP_TOKEN) {
match = lookup_player(NOTHING, md.string, 1);
if (Good_obj(match)) {
promote_match(match, CON_TOKEN);
}
}

/* returns object dbref associated with named reference, else NOTHING */


static dbref absolute_nref(str)
char *str;
{
char *p, *q, *buf, *bp;
dbref *np, nref;
/* Global or local reference? Global references are automatically
* prepended with an additional underscore. i.e., #__foo_ is a global
* reference, and #_foo_ is a local reference.
* Our beginning and end underscores have already been stripped, so
* we would see only _foo or foo.
*
* We are not allowed to nibble our buffer, because we've got a
* pointer into the match string. Therefore we must copy it.
* If we're matching locally we copy the dbref of the owner first,
* which means that we then need to worry about buffer size.
*/
buf = alloc_lbuf("absolute_nref");
if (*str == '_') {
for (p = buf, q = str; *q; p++, q++)
*p = tolower(*q);
*p = '\0';
} else {
bp = buf;
safe_ltos(buf, &bp, Owner(md.player));
safe_chr('.', buf, &bp);
for (q = str; *q; q++)
safe_chr(tolower(*q), buf, &bp);
*bp = '\0';
}
np = (int *) hashfind(buf, &mudstate.nref_htab);
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:34 PM

if (np && Good_obj(*np))


nref = *np;
else
nref = NOTHING;
free_lbuf(buf);
}

return nref;

/* returns nnn if name = #nnn, else NOTHING */


static dbref absolute_name(need_pound)
int need_pound;
{
dbref match;
char *mname;

mname = md.string;
if (need_pound) {
if (*md.string != NUMBER_TOKEN) {
return NOTHING;
} else {
mname++;
}
if ((*mname == '_') && *(mname + 1)) {
return absolute_nref(mname + 1);
}
}
if (*mname) {
match = parse_dbref(mname);
if (Good_obj(match)) {
return match;
}
}
return NOTHING;

void NDECL(match_absolute)
{
if (md.confidence >= CON_DBREF)
return;
if (Good_obj(md.absolute_form))
promote_match(md.absolute_form, CON_DBREF);
}
void NDECL(match_numeric)
{
dbref match;
if (md.confidence >= CON_DBREF)
return;
match = absolute_name(0);
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:34 PM

if (Good_obj(match))
promote_match(match, CON_DBREF);

void NDECL(match_me)
{
if (md.confidence >= CON_DBREF)
return;
if (Good_obj(md.absolute_form) && (md.absolute_form == md.player)) {
promote_match(md.player, CON_DBREF | CON_LOCAL);
return;
}
if (!string_compare(md.string, "me"))
promote_match(md.player, CON_TOKEN | CON_LOCAL);
return;
}
void NDECL(match_home)
{
if (md.confidence >= CON_DBREF)
return;
if (!string_compare(md.string, "home"))
promote_match(HOME, CON_TOKEN);
return;
}
void NDECL(match_here)
{
dbref loc;

if (md.confidence >= CON_DBREF)


return;
if (Good_obj(md.player) && Has_location(md.player)) {
loc = Location(md.player);
if (Good_obj(loc)) {
if (loc == md.absolute_form) {
promote_match(loc, CON_DBREF | CON_LOCAL);
} else if (!string_compare(md.string, "here")) {
promote_match(loc, CON_TOKEN | CON_LOCAL);
} else if (!string_compare(md.string,
(char *)PureName(loc))) {
promote_match(loc, CON_COMPLETE | CON_LOCAL);
}
}
}

static void match_list(first, local)


dbref first;
int local;
{
char *namebuf;

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:34 PM

if (md.confidence >= CON_DBREF)


return;
DOLIST(first, first) {
if (first == md.absolute_form) {
promote_match(first, CON_DBREF | local);
return;
}
/*
* Warning: make sure there are no other calls to Name() in
* promote_match or its called subroutines; they
* would overwrite Name()'s static buffer which is
* needed by string_match().
*/
namebuf = (char *)PureName(first);

if (!string_compare(namebuf, md.string)) {
promote_match(first, CON_COMPLETE | local);
} else if (string_match(namebuf, md.string)) {
promote_match(first, local);
}

void NDECL(match_possession)
{
if (md.confidence >= CON_DBREF)
return;
if (Good_loc(md.player))
match_list(Contents(md.player), CON_LOCAL);
}
void NDECL(match_neighbor)
{
dbref loc;

if (md.confidence >= CON_DBREF)


return;
if (Good_obj(md.player) && Has_location(md.player)) {
loc = Location(md.player);
if (Good_obj(loc)) {
match_list(Contents(loc), CON_LOCAL);
}
}

static int match_exit_internal(loc, baseloc, local)


dbref loc, baseloc;
int local;
{
dbref exit;
int result, key;
if (!Good_obj(loc) || !Has_exits(loc))
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:34 PM

return 1;

result = 0;
DOLIST(exit, Exits(loc)) {
if (exit == md.absolute_form) {
key = 0;
if (Examinable(md.player, loc))
key |= VE_LOC_XAM;
if (Dark(loc))
key |= VE_LOC_DARK;
if (Dark(baseloc))
key |= VE_BASE_DARK;
if (Exit_Visible(exit, md.player, key)) {
promote_match(exit, CON_DBREF | local);
return 1;
}
}
if (matches_exit_from_list(md.string,
(char *)PureName(exit))) {
promote_match(exit, CON_COMPLETE | local);
result = 1;
}
}
return result;

void NDECL(match_exit)
{
dbref loc;

if (md.confidence >= CON_DBREF)


return;
loc = Location(md.player);
if (Good_obj(md.player) && Has_location(md.player))
(void)match_exit_internal(loc, loc, CON_LOCAL);

void NDECL(match_exit_with_parents)
{
dbref loc, parent;
int lev;

if (md.confidence >= CON_DBREF)


return;
if (Good_obj(md.player) && Has_location(md.player)) {
loc = Location(md.player);
ITER_PARENTS(loc, parent, lev) {
if (match_exit_internal(parent, loc, CON_LOCAL))
break;
}
}

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:34 PM

void NDECL(match_carried_exit)
{
if (md.confidence >= CON_DBREF)
return;
if (Good_obj(md.player) && Has_exits(md.player))
(void)match_exit_internal(md.player, md.player, CON_LOCAL);
}
void NDECL(match_carried_exit_with_parents )
{
dbref parent;
int lev;

if (md.confidence >= CON_DBREF)


return;
if (Good_obj(md.player) && Has_exits(md.player)) {
ITER_PARENTS(md.player, parent, lev) {
if (match_exit_internal(parent, md.player, CON_LOCAL))
break;
}
}

void NDECL(match_master_exit)
{
if (md.confidence >= CON_DBREF)
return;
if (Good_obj(md.player) && Has_exits(md.player))
(void)match_exit_internal(mudconf.master_room,
mudconf.master_room, 0);
}
void NDECL(match_zone_exit)
{
if (md.confidence >= CON_DBREF)
return;
if (Good_obj(md.player) && Has_exits(md.player))
(void)match_exit_internal(Zone(md.player),
Zone(md.player), 0);
}
void match_everything(key)
int key;
{
/*
* Try matching me, then here, then absolute, then player FIRST, since
* this will hit most cases. STOP if we get something, since those are
* exact matches.
*/
match_me();
match_here();
match_absolute();
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:34 PM

if (key & MAT_NUMERIC)


match_numeric();
if (key & MAT_HOME)
match_home();
match_player();
if (md.confidence >= CON_TOKEN)
return;

if (!(key & MAT_NO_EXITS)) {


if (key & MAT_EXIT_PARENTS) {
match_carried_exit_with_parents ();
match_exit_with_parents();
} else {
match_carried_exit();
match_exit();
}
}
match_neighbor();
match_possession();

dbref NDECL(match_result)
{
switch (md.count) {
case 0:
return NOTHING;
case 1:
return md.match;
default:
return ((mudconf.no_ambiguous_match) ? (md.match) : AMBIGUOUS);
}
}
/* use this if you don't care about ambiguity */
dbref NDECL(last_match_result)
{
return md.match;
}
dbref match_status(player, match)
dbref player, match;
{
switch (match) {
case NOTHING:
notify(player, NOMATCH_MESSAGE);
return NOTHING;
case AMBIGUOUS:
notify(player, AMBIGUOUS_MESSAGE);
return NOTHING;
case NOPERM:
notify(player, NOPERM_MESSAGE);
return NOTHING;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:34 PM

}
return match;

dbref NDECL(noisy_match_result)
{
return match_status(md.player, match_result());
}
void save_match_state(m_state)
MSTATE *m_state;
{
m_state->confidence = md.confidence;
m_state->count = md.count;
m_state->pref_type = md.pref_type;
m_state->check_keys = md.check_keys;
m_state->absolute_form = md.absolute_form;
m_state->match = md.match;
m_state->player = md.player;
m_state->string = alloc_lbuf("save_match_state");
StringCopy(m_state->string, md.string);
}
void restore_match_state(m_state)
MSTATE *m_state;
{
md.confidence = m_state->confidence;
md.count = m_state->count;
md.pref_type = m_state->pref_type;
md.check_keys = m_state->check_keys;
md.absolute_form = m_state->absolute_form;
md.match = m_state->match;
md.player = m_state->player;
StringCopy(md.string, m_state->string);
free_lbuf(m_state->string);
}
void init_match(player, name, type)
dbref player;
const char *name;
int type;
{
md.confidence = -1;
md.count = md.check_keys = 0;
md.pref_type = type;
md.match = NOTHING;
md.player = player;
md.string = munge_space_for_match((char *)name);
md.absolute_form = absolute_name(1);
}
void init_match_check_keys(player, name, type)
dbref player;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.c

531
532
533
534
535
536
537

Saturday, June 16, 2012 11:34 PM

const char *name;


int type;
{
init_match(player, name, type);
md.check_keys = 1;
}

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:06 PM

/* match.h */
/* $Id: match.h,v 1.6 2000/11/25 23:06:48 lwl Exp $ */
#include "copyright.h"
#ifndef __MATCH_H
#define __MATCH_H
typedef struct match_state
struct match_state {
int confidence;
/*
int count;
/*
int pref_type;
/*
int check_keys;
/*
dbref
absolute_form;
dbref
match;
dbref
player;
char
*string;
};

MSTATE;
How confident are we? CON_xx */
# of matches at this confidence */
The preferred object type */
Should we test locks? */
/* If #num, then the number */
/* What I've found so far */
/* Who is performing match */
/* The string to search for */

/* Match functions
* Usage:
* init_match(player, name, type);
* match_this();
* match_that();
* ...
* thing = match_result()
*/
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

void FDECL(init_match, (dbref, const char *, int));


void FDECL(init_match_check_keys, (dbref, const char *, int));
void NDECL(match_player);
void NDECL(match_absolute);
void NDECL(match_numeric);
void NDECL(match_me);
void NDECL(match_here);
void NDECL(match_home);
void NDECL(match_possession);
void NDECL(match_neighbor);
void NDECL(match_exit);
void NDECL(match_exit_with_parents);
void NDECL(match_carried_exit);
void NDECL(match_carried_exit_with_parents );
void NDECL(match_master_exit);
void NDECL(match_zone_exit);
void FDECL(match_everything, (int));
dbref
NDECL(match_result);
dbref
NDECL(last_match_result);
dbref
FDECL(match_status, (dbref, dbref));
dbref
NDECL(noisy_match_result);
void FDECL(save_match_state, (MSTATE *));
void FDECL(restore_match_state, (MSTATE *));

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\match.h

54
55
56
57
58
59
60
61
62
63
64

Saturday, June 16, 2012 11:06 PM

#define NOMATCH_MESSAGE "I don't see that here."


#define AMBIGUOUS_MESSAGE "I don't know which one you mean!"
#define NOPERM_MESSAGE "Permission denied."
#define
#define
#define
#define

MAT_NO_EXITS
MAT_EXIT_PARENTS
MAT_NUMERIC
4
MAT_HOME
8

1
/* Don't
2
/* Check
/* Check for
/* Check for

check for exits */


for exits in parents */
un-#ified dbrefs */
'home' */

#endif /* __MATCH_H */

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mcheck.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:34 PM

/*
* Standard debugging hooks for `malloc'.
* * Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
* * Written May 1989 by Mike Haertel.
* *
* * This library is free software; you can redistribute it and/or
* * modify it under the terms of the GNU Library General Public License as
* * published by the Free Software Foundation; either version 2 of the
* * License, or (at your option) any later version.
* *
* * This library 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
* * Library General Public License for more details.
* *
* * You should have received a copy of the GNU Library General Public
* * License along with this library; see the file COPYING.LIB. If
* * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
* * Cambridge, MA 02139, USA.
* *
* * The author may be reached (Email) at the address mike@ai.mit.edu,
* * or (US mail) as Mike Haertel c/o Free Software Foundation.
*/
#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include <stdio.h>
#endif
#include
#include
#include
#include
/*
* Old
*/
static
static
static

"copyright.h"
"autoconf.h"
"externs.h"
"malloc.h"

hook values.
void (*old_free_hook) __P((__ptr_t ptr));
__ptr_t(*old_malloc_hook) __P((__malloc_size_t size));
__ptr_t(*old_realloc_hook) __P((__ptr_t ptr, __malloc_size_t size));

/*
* Function to call when something awful happens.
*/
static void (*abortfunc) __P((enum mcheck_status));
/*
* Arbitrary magical numbers.
*/
#define MAGICWORD
0xfedabeeb
#define MAGICFREE
0xd8675309
#define MAGICBYTE
((char) 0xd7)
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mcheck.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:34 PM

#define MALLOCFLOOD ((char) 0x93)


#define FREEFLOOD
((char) 0x95)
struct hdr {
__malloc_size_t size;
/*
* Exact size requested by user.
*/
unsigned long int magic;
/*
* Magic number to check header * *
* integrity.
*/
};
#if defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
#define flood memset
#else
static void flood __P((__ptr_t, int, __malloc_size_t));
static void flood(ptr, val, size)
__ptr_t ptr;
int val;
__malloc_size_t size;
{
char *cp = ptr;
while (size--)
*cp++ = val;

}
#endif

static enum mcheck_status checkhdr __P((const struct hdr *));


static enum mcheck_status checkhdr(hdr)
const struct hdr *hdr;
{
enum mcheck_status status;

switch (hdr->magic) {
default:
status = MCHECK_HEAD;
break;
case MAGICFREE:
status = MCHECK_FREE;
break;
case MAGICWORD:
if (((char *)&hdr[1])[hdr->size] != MAGICBYTE)
status = MCHECK_TAIL;
else
status = MCHECK_OK;
break;
}
if (status != MCHECK_OK)
(*abortfunc) (status);
return status;

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mcheck.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:34 PM

static void freehook __P((__ptr_t));


static void freehook(ptr)
__ptr_t ptr;
{
struct hdr *hdr = ((struct hdr *)ptr) - 1;

checkhdr(hdr);
hdr->magic = MAGICFREE;
flood(ptr, FREEFLOOD, hdr->size);
__free_hook = old_free_hook;
free(hdr);
__free_hook = freehook;

static __ptr_t mallochook __P((__malloc_size_t));


static __ptr_t
mallochook(size)
__malloc_size_t size;
{
struct hdr *hdr;
__malloc_hook = old_malloc_hook;
hdr = (struct hdr *)malloc(sizeof(struct hdr) + size + 1);
__malloc_hook = mallochook;
if (hdr == NULL)
return NULL;

hdr->size = size;
hdr->magic = MAGICWORD;
((char *)&hdr[1])[size] = MAGICBYTE;
flood((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
return (__ptr_t) (hdr + 1);

static __ptr_t reallochook __P((__ptr_t, __malloc_size_t));


static __ptr_t
reallochook(ptr, size)
__ptr_t ptr;
__malloc_size_t size;
{
struct hdr *hdr = ((struct hdr *)ptr) - 1;
__malloc_size_t osize = hdr->size;
checkhdr(hdr);
if (size < osize)
flood((char *)ptr + size, FREEFLOOD, osize - size);
__free_hook = old_free_hook;
__malloc_hook = old_malloc_hook;
__realloc_hook = old_realloc_hook;
hdr = (struct hdr *)realloc((__ptr_t) hdr, sizeof(struct hdr) + size + 1);

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mcheck.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:34 PM

__free_hook = freehook;
__malloc_hook = mallochook;
__realloc_hook = reallochook;
if (hdr == NULL)
return NULL;

hdr->size = size;
hdr->magic = MAGICWORD;
((char *)&hdr[1])[size] = MAGICBYTE;
if (size > osize)
flood((char *)(hdr + 1) + osize, MALLOCFLOOD, size - osize);
return (__ptr_t) (hdr + 1);

static void mabort(status)


enum mcheck_status status;
{
const char *msg;
switch (status) {
case MCHECK_OK:
msg = "memory is consistent, library is buggy" ;
break;
case MCHECK_HEAD:
msg = "memory clobbered before allocated block" ;
break;
case MCHECK_TAIL:
msg = "memory clobbered past end of allocated block" ;
break;
case MCHECK_FREE:
msg = "block freed twice";
break;
default:
msg = "bogus mcheck_status, library is buggy" ;
break;
}

STARTLOG(LOG_ALWAYS, "BUG", "MLLOC")


log_printf("mcheck: %s\n", msg);
ENDLOG

static int mcheck_used = 0;


int mcheck(void)
{
abortfunc = &mabort;
/*
* These hooks may not be safely inserted if malloc is already in * *
* use.
*/
if (!__malloc_initialized && !mcheck_used) {
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mcheck.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

Saturday, June 16, 2012 11:34 PM

old_free_hook = __free_hook;
__free_hook = freehook;
old_malloc_hook = __malloc_hook;
__malloc_hook = mallochook;
old_realloc_hook = __realloc_hook;
__realloc_hook = reallochook;
mcheck_used = 1;

}
return mcheck_used ? 0 : -1;

enum mcheck_status mprobe(__ptr_t ptr)


{
return mcheck_used ? checkhdr(ptr) : MCHECK_DISABLED;
}

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mguests.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:33 PM

/* mguests.c - multiguest code originally ported from DarkZone */


/* $Id: mguests.c,v 1.18 2002/09/28 10:58:09 rmg Exp $ */
#include "autoconf.h"
#include "copyright.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include "attrs.h" /* required by code */
#include "powers.h" /* required by code */
extern void FDECL(do_lock, (dbref, dbref, int, char *, char *));
typedef int object_flag_type;
dbref create_guest(num)
int num;
{
dbref player, aowner;
int found, same_str, aflags;
char name[LBUF_SIZE * 2];
char base[PLAYER_NAME_LIMIT * 2];
char prefixes[LBUF_SIZE], suffixes[LBUF_SIZE], *pp, *sp, *tokp, *toks;
if (!Wizard(mudconf.guest_nuker) || !Good_obj(mudconf.guest_nuker))
mudconf.guest_nuker = GOD;
/* If basename only is provided, guests are named <basename><number>.
* if guest_prefixes and/or guest_suffixes is provided, names will
* be generated using a sequential combination of the two lists,
* and the guests created will get an alias of <basename><number>.
* If we run out of possible name combinations before we run into
* the max number of guests, we start calling guests <basename><number>.
* If we generate a name longer than the limit, we also fall back on
* the basename scheme.
*/
found = 0;
if (*mudconf.guest_prefixes && *mudconf.guest_suffixes) {
strcpy(prefixes, mudconf.guest_prefixes);
for (pp = strtok_r(prefixes, " \t", &tokp); pp && !found;
pp = strtok_r(NULL, " \t", &tokp)) {
strcpy(suffixes, mudconf.guest_suffixes);
for (sp = strtok_r(suffixes, " \t", &toks); sp && !found;
sp = strtok_r(NULL, " \t", &toks)) {
sprintf(name, "%s%s", pp, sp);
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mguests.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:33 PM

if (lookup_player(GOD, name, 0) == NOTHING)


found = 1;
}

}
} else if (*mudconf.guest_prefixes || *mudconf.guest_suffixes) {
strcpy(prefixes, (*mudconf.guest_prefixes ?
mudconf.guest_prefixes :
mudconf.guest_suffixes));
for (pp = strtok_r(prefixes, " \t", &tokp); pp && !found;
pp = strtok_r(NULL, " \t", &tokp)) {
if (lookup_player(GOD, pp, 0) == NOTHING) {
strcpy(name, pp);
found = 1;
}
}
}
sprintf(base, "%s%d", mudconf.guest_basename, num + 1);
same_str = 1;
if (!found || (strlen(name) >= PLAYER_NAME_LIMIT)) {
strcpy(name, base);
} else if (strcasecmp(name, base)) {
if (!badname_check(base) || !ok_player_name(base) ||
(lookup_player(GOD, base, 0) != NOTHING)) {
STARTLOG(LOG_SECURITY | LOG_PCREATES, "CON", "BAD")
log_printf("Guest connect failed in alias check: %s" , base);
ENDLOG
return NOTHING;
}
same_str = 0;
}
/* Make the player. */
player = create_player(name, mudconf.guest_password,
mudconf.guest_nuker, 0, 1);
if (player == NOTHING) {
STARTLOG(LOG_SECURITY | LOG_PCREATES, "CON", "BAD")
log_printf("Guest connect failed in create_player: %s" , name);
ENDLOG
return NOTHING;
}
/* Add an alias for the basename. */
if (!same_str) {
atr_pget_info(player, A_ALIAS, &aowner, &aflags);
atr_add(player, A_ALIAS, base, player, aflags);
add_player_name(player, base);
}
/* Turn the player into a guest. */
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mguests.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:33 PM

s_Guest(player);
move_object(player, (Good_loc(mudconf.guest_start_room) ? mudconf.guest_start_room :
(Good_loc(mudconf.start_room) ? mudconf.start_room :
0)));
s_Flags(player, (Flags(mudconf.guest_char) & ~TYPE_MASK &
~mudconf.stripped_flags.word1) | TYPE_PLAYER);
s_Flags2(player, Flags2(mudconf.guest_char) &
~mudconf.stripped_flags.word2);
s_Flags3(player, Flags3(mudconf.guest_char) &
~mudconf.stripped_flags.word3);
s_Pennies(player, Pennies(mudconf.guest_char));
s_Zone(player, Zone(mudconf.guest_char));
s_Parent(player, Parent(mudconf.guest_char));
/* Make sure the guest is locked. */
do_lock(player, player, A_LOCK, tprintf("#%d", player), "me");
do_lock(player, player, A_LENTER, tprintf("#%d", player), "me");
do_lock(player, player, A_LUSE, tprintf("#%d", player), "me");
/* Copy all attributes. */

atr_cpy(GOD, player, mudconf.guest_char);


return player;

void destroy_guest(guest)
dbref guest;
{
if (!Wizard(mudconf.guest_nuker) || !Good_obj(mudconf.guest_nuker))
mudconf.guest_nuker = GOD;
if (!Guest(guest))
return;

atr_add_raw(guest, A_DESTROYER, tprintf("%d", mudconf.guest_nuker));


destroy_player(guest);
destroy_obj(mudconf.guest_nuker, guest);

char *make_guest(d)
DESC *d;
{
int i;
dbref guest;
char name[SBUF_SIZE];
/* Nuke extra guests. */
for (i = 0; i < mudconf.number_guests; i++) {
sprintf(name, "%s%d", mudconf.guest_basename, i + 1);
guest = lookup_player(GOD, name, 0);
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mguests.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

Saturday, June 16, 2012 11:33 PM

if ((guest != NOTHING) && !Connected(guest))


destroy_guest(guest);
}
/* Find the first free guest ID. */
for (i = 0; i < mudconf.number_guests; i++) {
sprintf(name, "%s%d", mudconf.guest_basename, i + 1);
if (lookup_player(GOD, name, 0) == NOTHING)
break;
}
if (i == mudconf.number_guests) {
queue_string(d,
"GAME: All guests are currently in use. Please try again later.\n" );
return NULL;
}

if ((guest = create_guest(i)) == NOTHING) {


queue_string(d,
"GAME: Error creating guest ID, please try again later.\n" );
STARTLOG(LOG_SECURITY | LOG_PCREATES, "CON", "BAD")
log_printf("Error creating guest ID. '%s' already exists.\n" ,
name);
ENDLOG
return NULL;
}
return Name(guest);

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mkindx.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:33 PM

/* mkindx.c - make help/news file indexes */


/* $Id: mkindx.c,v 1.10 2000/11/25 21:40:52 merlin Exp $ */
/*
* mkindx now supports multiple tags for a single entry.
* example:
*
*
& foo
*
& bar
*
This is foo and bar.
*
& baz
*
This is baz.
*
*/
#include "copyright.h"
#include "autoconf.h"
#include

"help.h"

char line[LINE_SIZE + 1];


typedef struct _help_indx_list {
help_indx
entry;
struct _help_indx_list *next;
} help_indx_list;
int dump_entries(FILE *wfp, long pos, help_indx_list *entries);
int main(argc, argv)
int argc;
char *argv[];
{
long pos;
int i, n, lineno, ntopics, actualdata;
char *s, *topic;
help_indx_list *entries, *ep;
FILE *rfp, *wfp;
if (argc < 2 || argc > 3) {
printf("Usage:\tmkindx <file_to_be_indexed> <output_index_filename>\n" );
exit(-1);
}
if ((rfp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "can't open %s for reading\n" , argv[1]);
exit(-1);
}
if ((wfp = fopen(argv[2], "w")) == NULL) {
fprintf(stderr, "can't open %s for writing\n" , argv[2]);
exit(-1);
}
pos = 0L;
lineno = 0;
ntopics = 0;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mkindx.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:33 PM

actualdata = 0;
/* create initial entry storage */
entries = (help_indx_list *)malloc(sizeof(help_indx_list));
memset(entries, 0, sizeof(help_indx_list));
while (fgets(line, LINE_SIZE, rfp) != NULL) {
++lineno;
n = strlen(line);
if (line[n - 1] != '\n') {
fprintf(stderr, "line %d: line too long\n", lineno);
}
if (line[0] == '&') {
++ntopics;
if ( (ntopics > 1) && actualdata ) {
/*
* we've hit the next topic, time to write the ones we've been
* building
*/
actualdata = 0;
if (dump_entries(wfp, pos, entries)) {
fprintf(stderr, "error writing %s\n", argv[2]);
exit(-1);
}
memset(entries, 0, sizeof(help_indx_list));
}
if (entries->entry.pos) {
/*
* we're already working on an entry... time to start nesting
*/
ep = entries;
entries = (help_indx_list *)malloc(sizeof(help_indx_list));
memset(entries, 0, sizeof(help_indx_list));
entries->next = ep;
}
for (topic = &line[1];
(*topic == ' ' || *topic == '\t') && *topic != '\0';
topic++) ;
for (i = -1, s = topic; *s != '\n' && *s != '\0'; s++) {
if (i >= TOPIC_NAME_LEN - 1)
break;
if (*s != ' ' || entries->entry.topic[i] != ' ')
entries->entry.topic[++i] = *s;
}
entries->entry.topic[++i] = '\0';
entries->entry.pos = pos + (long)n;

}
else if (n > 1) {
/*

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mkindx.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:33 PM

* a non blank line. we can flush entries to the .indx file the next
* time we run into a topic line...
*/
actualdata = 1;

}
pos += n;

}
if (dump_entries(wfp, pos, entries)) {
fprintf(stderr, "error writing %s\n", argv[2]);
exit(-1);
}
fclose(rfp);
fclose(wfp);

printf("%d topics indexed\n", ntopics);


exit(0);

int dump_entries(FILE *wfp, long pos, help_indx_list *entries)


{
int truepos;
int truelen;
int depth;
help_indx_list *prev_ep, *ep;
/*
* if we have more than one entry, the one on the top of the chain
* is going to have the actual pos we want to use to index with
*/
truepos = (long)entries->entry.pos;
truelen = (int)(pos - entries->entry.pos);
prev_ep = 0;
depth = 0;
for (ep = entries; ep; ep = ep->next) {
ep->entry.pos = (long)truepos;
ep->entry.len = truelen;
if (fwrite(&ep->entry, sizeof(help_indx), 1, wfp) < 1)
return(-1);
if (prev_ep)
free(prev_ep);
if (depth++)
/* don't want to try to free the top of the chain */
prev_ep = ep;

}
/*
* no attempt is made to free the last remaining struct as its actually the
* one on the top of the chain, ie. the statically allocated struct.
*/
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mkindx.c

160
161
162
163

Saturday, June 16, 2012 11:33 PM

return(0);

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:32 PM

/* move.c - Routines for moving about */


/* $Id: move.c,v 1.33 2008/02/22 18:54:07 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "match.h" /* required by code */
#include "attrs.h" /* required by code */
#include "powers.h" /* required by code */
/* --------------------------------------------------------------------------* process_leave_loc: Generate messages and actions resulting from leaving
* a place.
*/
static void process_leave_loc(thing, dest, cause, canhear, hush)
dbref thing, dest, cause;
int canhear, hush;
{
dbref loc;
int quiet, pattr, oattr, aattr;
loc = Location(thing);
if ((loc == NOTHING) || (loc == dest))
return;
if (dest == HOME)
dest = Home(thing);
#ifdef PUEBLO_SUPPORT
if (Html(thing)) {
notify_html(thing, "<xch_page clear=links>");
}
#endif
/* Hook support first */
call_move_hook(thing, cause, 0);
/*
*
*
*
*

Run the LEAVE attributes in the current room if we meet any of


following criteria:
- The current room has wizard privs.
- Neither the current room nor the moving object are dark.
- The moving object can hear and does not hav wizard
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

*
*/

Saturday, June 16, 2012 11:32 PM

privs. EXCEPT if we were called with the HUSH_LEAVE key.

quiet = (!(Wizard(loc) ||
(!Dark(thing) && !Dark(loc)) ||
(canhear && !DarkMover(thing)))) ||
(hush & HUSH_LEAVE);
oattr = quiet ? A_NULL : A_OLEAVE;
aattr = (!quiet || (mudconf.dark_actions && !(hush & HUSH_LEAVE))) ?
A_ALEAVE : A_NULL;
pattr = (!mudconf.terse_movemsg && Terse(thing)) ? A_NULL : A_LEAVE;
did_it(thing, loc, pattr, NULL, oattr, NULL, aattr, 0,
(char **)NULL, 0, MSG_MOVE);
/* Do OXENTER for receiving room */
if ((dest != NOTHING) && !quiet)
did_it(thing, dest, A_NULL, NULL, A_OXENTER, NULL, A_NULL, 0,
(char **)NULL, 0, MSG_MOVE);
/* Display the 'has left' message if we meet any of the following
* criteria:
* - Neither the current room nor the moving object are dark.
* - The object can hear and is not a dark wizard.
*/

if (!quiet && !Blind(thing) && !Blind(loc)) {


if ((!Dark(thing) && !Dark(loc)) ||
(canhear && !DarkMover(thing))) {
notify_except2(loc, thing, thing, cause,
tprintf("%s has left.", Name(thing)),
MSG_MOVE);
}
}

/* --------------------------------------------------------------------------* process_enter_loc: Generate messages and actions resulting from entering


* a place.
*/
static void process_enter_loc(thing, src, cause, canhear, hush)
dbref thing, src, cause;
int canhear, hush;
{
dbref loc;
int quiet, pattr, oattr, aattr;
loc = Location(thing);
if ((loc == NOTHING) || (loc == src))
return;
#ifdef PUEBLO_SUPPORT
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:32 PM

show_vrml_url(thing, loc);
#endif
/* Hook support first */
call_move_hook(thing, cause, 1);
/* Run the ENTER attributes in the current room if we meet any of
* following criteria:
* - The current room has wizard privs.
* - Neither the current room nor the moving object are dark.
* - The moving object can hear and does not hav wizard
*
privs. EXCEPT if we were called with the HUSH_ENTER key.
*/
quiet = (!(Wizard(loc) ||
(!Dark(thing) && !Dark(loc)) ||
(canhear && !DarkMover(thing)))) ||
(hush & HUSH_ENTER);
oattr = quiet ? A_NULL : A_OENTER;
aattr = (!quiet || (mudconf.dark_actions && !(hush & HUSH_ENTER))) ?
A_AENTER : A_NULL;
pattr = (!mudconf.terse_movemsg && Terse(thing)) ? A_NULL : A_ENTER;
did_it(thing, loc, pattr, NULL, oattr, NULL, aattr, 0,
(char **)NULL, 0, MSG_MOVE);
/* Do OXLEAVE for sending room */
if ((src != NOTHING) && !quiet)
did_it(thing, src, A_NULL, NULL, A_OXLEAVE, NULL, A_NULL, 0,
(char **)NULL, 0, MSG_MOVE);
/* Display the 'has arrived' message if we meet all of the following
* criteria:
* - The moving object can hear.
* - The object is not a dark wizard.
*/

if (!quiet && canhear &&


!Blind(thing) && !Blind(loc) && !DarkMover(thing)) {
notify_except2(loc, thing, thing, cause,
tprintf("%s has arrived.", Name(thing)),
MSG_MOVE);
}

/* --------------------------------------------------------------------------* move_object: Physically move an object from one place to another.


* Does not generate any messages or actions.
*/
void move_object(thing, dest)
dbref thing, dest;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:32 PM

dbref src;
/* Remove from the source location */
src = Location(thing);
if (src != NOTHING)
s_Contents(src, remove_first(Contents(src), thing));
/* Special check for HOME */
if (dest == HOME)
dest = Home(thing);
/* Add to destination location */
if (dest != NOTHING) {
s_Contents(dest, insert_first(Contents(dest), thing));
} else {
s_Next(thing, NOTHING);
}
s_Location(thing, dest);
/* Look around and do the penny check */

look_in(thing, dest, (LK_SHOWEXIT | LK_OBEYTERSE));


if (isPlayer(thing) &&
(mudconf.payfind > 0) &&
(Pennies(thing) < mudconf.paylimit) &&
(!Controls(thing, dest)) &&
(Randomize(mudconf.payfind) == 0)) {
giveto(thing, 1);
notify(thing, tprintf("You found a %s!", mudconf.one_coin));
}

/* --------------------------------------------------------------------------* send_dropto, process_sticky_dropto, process_dropped_dropto,


* process_sacrifice_dropto: Check for and process droptos.
*/
/* send_dropto: Send an object through the dropto of a room */
static void send_dropto(thing, player)
dbref thing, player;
{
if (!Sticky(thing))
move_via_generic(thing, Dropto(Location(thing)), player, 0);
else
move_via_generic(thing, HOME, player, 0);
divest_object(thing);
}
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:32 PM

/* process_sticky_dropto: Call when an object leaves the room to see if


* we should empty the room
*/
static void process_sticky_dropto(loc, player)
dbref loc, player;
{
dbref dropto, thing, next;
/* Do nothing if checking anything but a sticky room */
if (!Good_obj(loc) || !Has_dropto(loc) || !Sticky(loc))
return;
/* Make sure dropto loc is valid */
dropto = Dropto(loc);
if ((dropto == NOTHING) || (dropto == loc))
return;
/* Make sure no players hanging out */
DOLIST(thing, Contents(loc)) {
if (Dropper(thing))
return;
}
/* Send everything through the dropto */

s_Contents(loc, reverse_list(Contents(loc)));
SAFE_DOLIST(thing, next, Contents(loc)) {
send_dropto(thing, player);
}

/* process_dropped_dropto: Check what to do when someone drops an object. */


static void process_dropped_dropto(thing, player)
dbref thing, player;
{
dbref loc;
/* If STICKY, send home */
if (Sticky(thing)) {
move_via_generic(thing, HOME, player, 0);
divest_object(thing);
return;
}
/* Process the dropto if location is a room and is not STICKY */
loc = Location(thing);
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:32 PM

if (Has_dropto(loc) && (Dropto(loc) != NOTHING) && !Sticky(loc))


send_dropto(thing, player);

/* --------------------------------------------------------------------------* move_via_generic: Generic move routine, generates standard messages and


* actions.
*/
void move_via_generic(thing, dest, cause, hush)
dbref thing, dest, cause;
int hush;
{
dbref src;
int canhear;

if (dest == HOME)
dest = Home(thing);
src = Location(thing);
canhear = Hearer(thing);
process_leave_loc(thing, dest, cause, canhear, hush);
move_object(thing, dest);
did_it(thing, thing, A_MOVE, NULL, A_OMOVE, NULL, A_AMOVE, 0,
(char **)NULL, 0, MSG_MOVE);
process_enter_loc(thing, src, cause, canhear, hush);

/* --------------------------------------------------------------------------* move_via_exit: Exit move routine, generic + exit messages + dropto check.
*/
void move_via_exit(thing, dest, cause, exit, hush)
dbref thing, dest, cause, exit;
int hush;
{
dbref src;
int canhear, darkwiz, quiet, pattr, oattr, aattr;
if (dest == HOME)
dest = Home(thing);
src = Location(thing);
canhear = Hearer(thing);
/* Dark wizzes and Cloak powered things don't trigger OSUCC/ASUCC */
darkwiz = DarkMover(thing);
quiet = darkwiz || (hush & HUSH_EXIT);
oattr = quiet ? A_NULL : A_OSUCC;
aattr = (!quiet || (mudconf.dark_actions && !(hush & HUSH_EXIT))) ?
A_ASUCC : A_NULL;
pattr = (!mudconf.terse_movemsg && Terse(thing)) ? A_NULL : A_SUCC;
did_it(thing, exit, pattr, NULL, oattr, NULL, aattr, 0,
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:32 PM

(char **)NULL, 0, MSG_MOVE);


process_leave_loc(thing, dest, cause, canhear, hush);
move_object(thing, dest);
/* Dark wizards don't trigger ODROP/ADROP */
oattr = quiet ? A_NULL : A_ODROP;
aattr = (!quiet || (mudconf.dark_actions && !(hush & HUSH_EXIT))) ?
A_ADROP : A_NULL;
pattr = (!mudconf.terse_movemsg && Terse(thing)) ? A_NULL : A_DROP;
did_it(thing, exit, pattr, NULL, oattr, NULL, aattr, 0,
(char **)NULL, 0, MSG_MOVE);

did_it(thing, thing, A_MOVE, NULL, A_OMOVE, NULL, A_AMOVE, 0,


(char **)NULL, 0, MSG_MOVE);
process_enter_loc(thing, src, cause, canhear, hush);
process_sticky_dropto(src, thing);

/* --------------------------------------------------------------------------* move_via_teleport: Teleport move routine, generic + teleport messages +


* divestiture + dropto check.
*/
int move_via_teleport(thing, dest, cause, hush)
dbref thing, dest, cause;
int hush;
{
dbref src, curr;
int canhear, count;
char *failmsg;
src = Location(thing);
if ((dest != HOME) && Good_obj(src)) {
curr = src;
for (count = mudconf.ntfy_nest_lim; count > 0; count--) {
if (!could_doit(thing, curr, A_LTELOUT)) {
if ((thing == cause) || (cause == NOTHING))
failmsg = (char *)
"You can't teleport out!";
else {
failmsg = (char *)
"You can't be teleported out!" ;
notify_quiet(cause,
"You can't teleport that out!" );
}
did_it(thing, src,
A_TOFAIL, failmsg, A_OTOFAIL, NULL,
A_ATOFAIL, 0, (char **)NULL, 0,
MSG_MOVE);
return 0;
}
if (isRoom(curr))
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:32 PM

break;
curr = Location(curr);

}
if (dest == HOME)
dest = Home(thing);
canhear = Hearer(thing);
if (!(hush & HUSH_LEAVE))
did_it(thing, thing, A_NULL, NULL, A_OXTPORT, NULL,
A_NULL, 0, (char **)NULL, 0, MSG_MOVE);
process_leave_loc(thing, dest, NOTHING, canhear, hush);
move_object(thing, dest);
if (!(hush & HUSH_ENTER))
did_it(thing, thing, A_TPORT, NULL, A_OTPORT, NULL,
A_ATPORT, 0, (char **)NULL, 0, MSG_MOVE);
did_it(thing, thing, A_MOVE, NULL, A_OMOVE, NULL, A_AMOVE, 0,
(char **)NULL, 0, MSG_MOVE);
process_enter_loc(thing, src, NOTHING, canhear, hush);
divest_object(thing);
process_sticky_dropto(src, thing);
return 1;

/* --------------------------------------------------------------------------* find_var_dest: Find a variable exit destination (DESTINATION attr).


*/
static dbref find_var_dest(player, exit)
dbref player;
dbref exit;
{
char *buf, *ebuf, *ep, *str;
dbref aowner, dest_room;
int aflags, alen;
GDATA *preserve;
buf = atr_pget(exit, A_EXITVARDEST, &aowner, &aflags, &alen);
if (!*buf) {
free_lbuf(buf);
return NOTHING;
}
preserve = save_global_regs("find_var_dest_save");
ebuf = ep = alloc_lbuf("find_var_dest");
str = buf;
exec(ebuf, &ep, exit, player, player, EV_FCHECK | EV_EVAL | EV_TOP,
&str, (char **) NULL, 0);
free_lbuf(buf);
restore_global_regs("find_var_dest_save", preserve);
if (*ebuf == '#')
dest_room = parse_dbref(ebuf + 1);
else
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:32 PM

dest_room = NOTHING;

free_lbuf(ebuf);
return dest_room;

/* --------------------------------------------------------------------------* move_exit: Try to move a player through an exit.


*/
void move_exit(player, exit, divest, failmsg, hush)
dbref player, exit;
int divest, hush;
const char *failmsg;
{
dbref loc;
int oattr, aattr;
loc = Location(exit);
switch (loc) {
case HOME:
loc = Home(player);
break;
case AMBIGUOUS:
loc = find_var_dest(player, exit);
break;
default:
/* EMPTY */
break;
}
if (Good_obj(loc) && could_doit(player, exit, A_LOCK)) {
switch (Typeof(loc)) {
case TYPE_ROOM:
move_via_exit(player, loc, NOTHING, exit, hush);
if (divest)
divest_object(player);
break;
case TYPE_PLAYER:
case TYPE_THING:
if (Going(loc)) {
notify(player, "You can't go that way.");
return;
}
move_via_exit(player, loc, NOTHING, exit, hush);
divest_object(player);
break;
case TYPE_EXIT:
notify(player, "You can't go that way.");
return;
}
} else {
oattr = (Dark(player) || (hush & HUSH_EXIT)) ?
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:32 PM

A_NULL : A_OFAIL;
aattr = ((hush & HUSH_EXIT) ||
(Dark(player) && !mudconf.dark_actions)) ?
A_NULL : A_AFAIL;
did_it(player, exit, A_FAIL, failmsg, oattr, NULL, aattr, 0,
(char **)NULL, 0, MSG_MOVE);

/* --------------------------------------------------------------------------* do_move: Move from one place to another via exits or 'home'.
*/
void do_move(player, cause, key, direction)
dbref player, cause;
int key;
char *direction;
{
dbref exit, loc;
int i, quiet;
if (!string_compare(direction, "home")) {
/* go home w/o stuff */
if (((Fixed(player)) || (Fixed(Owner(player)))) &&
!(WizRoy(player))) {
notify(player, mudconf.fixed_home_msg);
return;
}
if ((loc = Location(player)) != NOTHING &&
!Dark(player) && !Dark(loc)) {
/* tell all */
notify_except(loc, player, player,
tprintf("%s goes home.", Name(player)),
MSG_MOVE);

}
/* give the player the messages */

for (i = 0; i < 3; i++)


notify(player, "There's no place like home..." );
move_via_generic(player, HOME, NOTHING, 0);
divest_object(player);
process_sticky_dropto(loc, player);
return;

}
/* find the exit */

if (mudconf.move_match_more) {
init_match_check_keys(player, direction, TYPE_EXIT);
match_exit_with_parents();
exit = last_match_result();
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:32 PM

if (exit == NOTHING) {
init_match_check_keys(player, direction, TYPE_EXIT);
match_master_exit();
exit = last_match_result();
}
if (exit == NOTHING) {
init_match_check_keys(player, direction, TYPE_EXIT);
match_zone_exit();
exit = last_match_result();
}
} else {
init_match_check_keys(player, direction, TYPE_EXIT);
match_exit();
exit = match_result();
}

switch (exit) {
case NOTHING:
/* try to force the object */
notify(player, "You can't go that way.");
break;
case AMBIGUOUS:
notify(player, "I don't know which way you mean!" );
break;
default:
quiet = 0;
if ((key & MOVE_QUIET) && Controls(player, exit))
quiet = HUSH_EXIT;
move_exit(player, exit, 0, "You can't go that way.", quiet);
}

/* --------------------------------------------------------------------------* do_get: Get an object.


*/
void do_get(player, cause, key, what)
dbref player, cause;
int key;
char *what;
{
dbref thing, playerloc, thingloc;
char *failmsg;
int oattr, aattr, quiet;
playerloc = Location(player);
if (!Good_obj(playerloc))
return;
/* You can only pick up things in rooms and ENTER_OK objects/players */
if (!isRoom(playerloc) && !Enter_ok(playerloc) &&
!controls(player, playerloc)) {
notify(player, NOPERM_MESSAGE);
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:32 PM

return;
}
/* Look for the thing locally */
init_match_check_keys(player, what, TYPE_THING);
match_neighbor();
match_exit();
if (Long_Fingers(player))
match_absolute();
/* long fingers */
thing = match_result();
/* Look for the thing in other people's inventories */
if (!Good_obj(thing))
thing = match_status(player,
match_possessed(player, player, what, thing, 1));
if (!Good_obj(thing))
return;
/* If we found it, get it */
quiet = 0;
switch (Typeof(thing)) {
case TYPE_PLAYER:
case TYPE_THING:
/* You can't take what you already have */
thingloc = Location(thing);
if (thingloc == player) {
notify(player, "You already have that!");
break;
}
if ((key & GET_QUIET) && Controls(player, thing))
quiet = 1;
if (thing == player) {
notify(player, "You cannot get yourself!");
} else if (could_doit(player, thing, A_LOCK)) {
if (thingloc != Location(player)) {
notify(thingloc,
tprintf("%s was taken from you.",
Name(thing)));
}
move_via_generic(thing, player, player, 0);
notify(thing, "Taken.");
oattr = quiet ? 0 : A_OSUCC;
aattr = quiet ? 0 : A_ASUCC;
did_it(player, thing, A_SUCC, "Taken.", oattr, NULL,
aattr, 0, (char **)NULL, 0, MSG_MOVE);
} else {
oattr = quiet ? 0 : A_OFAIL;
aattr = quiet ? 0 : A_AFAIL;
if (thingloc != Location(player))
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

else

Saturday, June 16, 2012 11:32 PM

failmsg = (char *)"You can't take that from there." ;

failmsg = (char *)"You can't pick that up.";


did_it(player, thing,
A_FAIL, failmsg,
oattr, NULL, aattr, 0, (char **)NULL, 0,
MSG_MOVE);

}
break;
case TYPE_EXIT:
/* You can't take what you already have */

thingloc = Exits(thing);
if (thingloc == player) {
notify(player, "You already have that!");
break;
}
/* You must control either the exit or the location */
playerloc = Location(player);
if (!Controls(player, thing) && !Controls(player, playerloc)) {
notify(player, NOPERM_MESSAGE);
break;
}
/* Do it */

s_Exits(thingloc, remove_first(Exits(thingloc), thing));


s_Exits(player, insert_first(Exits(player), thing));
s_Exits(thing, player);
if (!Quiet(player))
notify(player, "Exit taken.");
break;
default:
notify(player, "You can't take that!");
break;
}

/* --------------------------------------------------------------------------* do_drop: Drop an object.


*/
void do_drop(player, cause, key, name)
dbref player, cause;
int key;
char *name;
{
dbref loc, exitloc, thing;
char *buf, *bp;
int quiet, oattr, aattr;
loc = Location(player);
if (!Good_obj(loc))
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:32 PM

return;
init_match(player, name, TYPE_THING);
match_possession();
match_carried_exit();
switch (thing = match_result()) {
case NOTHING:
notify(player, "You don't have that!");
return;
case AMBIGUOUS:
notify(player, "I don't know which you mean!" );
return;
}
switch (Typeof(thing)) {
case TYPE_THING:
case TYPE_PLAYER:
/* You have to be carrying it */
if (((Location(thing) != player) && !Wizard(player)) ||
(!could_doit(player, thing, A_LDROP))) {
did_it(player, thing, A_DFAIL, "You can't drop that.",
A_ODFAIL, NULL, A_ADFAIL, 0, (char **)NULL, 0,
MSG_MOVE);
return;
}
/* Move it */
move_via_generic(thing, Location(player), player, 0);
notify(thing, "Dropped.");
quiet = 0;
if ((key & DROP_QUIET) && Controls(player, thing))
quiet = 1;
bp = buf = alloc_lbuf("do_drop.did_it");
safe_tprintf_str(buf, &bp, "dropped %s.", Name(thing));
oattr = quiet ? 0 : A_ODROP;
aattr = quiet ? 0 : A_ADROP;
did_it(player, thing, A_DROP, "Dropped.", oattr, buf,
aattr, 0, (char **)NULL, 0, MSG_MOVE);
free_lbuf(buf);
/* Process droptos */
process_dropped_dropto(thing, player);
break;
case TYPE_EXIT:
/* You have to be carrying it */
if ((Exits(thing) != player) && !Wizard(player)) {
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:32 PM

notify(player, "You can't drop that.");


return;

}
if (!Controls(player, loc) && !Open_Anywhere(player)) {
notify(player, NOPERM_MESSAGE);
return;
}
/* Do it */
exitloc = Exits(thing);
s_Exits(exitloc, remove_first(Exits(exitloc), thing));
s_Exits(loc, insert_first(Exits(loc), thing));
s_Exits(thing, loc);
if (!Quiet(player))
notify(player, "Exit dropped.");
break;
default:
notify(player, "You can't drop that.");
}
}
/* --------------------------------------------------------------------------* do_enter, do_leave: The enter and leave commands.
*/
void do_enter_internal(player, thing, quiet)
dbref player, thing;
int quiet;
{
dbref loc;
int oattr, aattr;
if (!Enter_ok(thing) && !controls(player, thing)) {
oattr = quiet ? 0 : A_OEFAIL;
aattr = quiet ? 0 : A_AEFAIL;
did_it(player, thing, A_EFAIL, NOPERM_MESSAGE,
oattr, NULL, aattr, 0, (char **)NULL, 0, MSG_MOVE);
} else if (player == thing) {
notify(player, "You can't enter yourself!");
} else if (could_doit(player, thing, A_LENTER)) {
loc = Location(player);
oattr = quiet ? HUSH_ENTER : 0;
move_via_generic(player, thing, NOTHING, oattr);
divest_object(player);
process_sticky_dropto(loc, player);
} else {
oattr = quiet ? 0 : A_OEFAIL;
aattr = quiet ? 0 : A_AEFAIL;
did_it(player, thing, A_EFAIL, "You can't enter that.",
oattr, NULL, aattr, 0, (char **)NULL, 0, MSG_MOVE);
}
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:32 PM

}
void do_enter(player, cause, key, what)
dbref player, cause;
int key;
char *what;
{
dbref thing;
int quiet;
init_match(player, what, TYPE_THING);
match_neighbor();
if (Long_Fingers(player))
match_absolute();
/* the wizard has long fingers */
if ((thing = noisy_match_result()) == NOTHING)
return;

switch (Typeof(thing)) {
case TYPE_PLAYER:
case TYPE_THING:
quiet = 0;
if ((key & MOVE_QUIET) && Controls(player, thing))
quiet = 1;
do_enter_internal(player, thing, quiet);
break;
default:
notify(player, NOPERM_MESSAGE);
}
return;

void do_leave(player, cause, key)


dbref player, cause;
int key;
{
dbref loc;
int quiet, oattr, aattr;
loc = Location(player);
if (!Good_obj(loc) || isRoom(loc) || Going(loc)) {
notify(player, "You can't leave.");
return;
}
quiet = 0;
if ((key & MOVE_QUIET) && Controls(player, loc))
quiet = HUSH_LEAVE;
if (could_doit(player, loc, A_LLEAVE)) {
move_via_generic(player, Location(loc), NOTHING, quiet);
} else {
oattr = quiet ? 0 : A_OLFAIL;
aattr = quiet ? 0 : A_ALFAIL;
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\move.c

849
850
851
852
853

Saturday, June 16, 2012 11:32 PM

did_it(player, loc, A_LFAIL, "You can't leave.",


oattr, NULL, aattr, 0, (char **)NULL, 0, MSG_MOVE);

-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mstats.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

Saturday, June 16, 2012 11:32 PM

/*
* Access the statistics maintained by `malloc'.
* * Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
* * Written May 1989 by Mike Haertel.
* *
* * This library is free software; you can redistribute it and/or
* * modify it under the terms of the GNU Library General Public License as
* * published by the Free Software Foundation; either version 2 of the
* * License, or (at your option) any later version.
* *
* * This library 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
* * Library General Public License for more details.
* *
* * You should have received a copy of the GNU Library General Public
* * License along with this library; see the file COPYING.LIB. If
* * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
* * Cambridge, MA 02139, USA.
* *
* * The author may be reached (Email) at the address mike@ai.mit.edu,
* * or (US mail) as Mike Haertel c/o Free Software Foundation.
*/
#include "malloc.h"
struct mstats mstats()
{
struct mstats result;

result.bytes_total = (char *)(*__morecore) (0) - _heapbase;


result.chunks_used = _chunks_used;
result.bytes_used = _bytes_used;
result.chunks_free = _chunks_free;
result.bytes_free = _bytes_free;
return result;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mtrace.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:32 PM

/*
* More debugging hooks for `malloc'.
* * Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
* * Written April 2, 1991 by John Gilmore of Cygnus Support.
* * Based on mcheck.c by Mike Haertel.
* *
* * This library is free software; you can redistribute it and/or
* * modify it under the terms of the GNU Library General Public License as
* * published by the Free Software Foundation; either version 2 of the
* * License, or (at your option) any later version.
* *
* * This library 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
* * Library General Public License for more details.
* *
* * You should have received a copy of the GNU Library General Public
* * License along with this library; see the file COPYING.LIB. If
* * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
* * Cambridge, MA 02139, USA.
* *
* * The author may be reached (Email) at the address mike@ai.mit.edu,
* * or (US mail) as Mike Haertel c/o Free Software Foundation.
*/
#include <stdio.h>
#include "copyright.h"
#include "autoconf.h"
#include "malloc.h"
static FILE *mallstream;
static char mallbuf[BUFSIZ];

/*

* Buffer for the output.


*/
/*
* Address to breakpoint on accesses to...
*/
__ptr_t mallwatch;
/*
* File name and line number information, for callers that had
* * the foresight to call through a macro.
*/
char *_mtrace_file;
int _mtrace_line;
/*
* Old hook values.
*/
static void (*tr_old_free_hook) __P((__ptr_t ptr));
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mtrace.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:32 PM

static __ptr_t(*tr_old_malloc_hook) __P((__malloc_size_t size));


static __ptr_t(*tr_old_realloc_hook) __P((__ptr_t ptr, __malloc_size_t size));
/*
* This function is called when the block being alloc'd, realloc'd, or
* * freed has an address matching the variable "mallwatch". In a debugger,
* * set "mallwatch" to the address of interest, then put a breakpoint on
* * tr_break.
*/
void tr_break __P((void));
void tr_break()
{
}
static void tr_where __P((void));
static void tr_where()
{
if (_mtrace_file) {
fprintf(mallstream, "@ %s:%d ", _mtrace_file, _mtrace_line);
fflush(mallstream);
_mtrace_file = NULL;
}
}
static void tr_freehook __P((__ptr_t));
static void tr_freehook(ptr)
__ptr_t ptr;
{
tr_where();
fprintf(mallstream, "- %p\n", ptr); /*
* Be sure to print it first.
*
* fflush(mallstream);
*
* *
*/
if (ptr == mallwatch)
tr_break();
__free_hook = tr_old_free_hook;
free(ptr);
__free_hook = tr_freehook;
}
static __ptr_t tr_mallochook __P((__malloc_size_t));
static __ptr_t
tr_mallochook(size)
__malloc_size_t size;
{
__ptr_t hdr;
__malloc_hook = tr_old_malloc_hook;
hdr = (__ptr_t) malloc(size);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mtrace.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:32 PM

__malloc_hook = tr_mallochook;
tr_where();
/*
* We could be printing a NULL here; that's OK.
*/
fprintf(mallstream, "+ %p %lx\n", hdr, (unsigned long)size);
fflush(mallstream);
if (hdr == mallwatch)
tr_break();
}

return hdr;

static __ptr_t tr_reallochook __P((__ptr_t, __malloc_size_t));


static __ptr_t
tr_reallochook(ptr, size)
__ptr_t ptr;
__malloc_size_t size;
{
__ptr_t hdr;
if (ptr == mallwatch)
tr_break();
__free_hook = tr_old_free_hook;
__malloc_hook = tr_old_malloc_hook;
__realloc_hook = tr_old_realloc_hook;
hdr = (__ptr_t) realloc(ptr, size);
__free_hook = tr_freehook;
__malloc_hook = tr_mallochook;
__realloc_hook = tr_reallochook;
tr_where();
if (hdr == NULL)
/*
* Failed realloc.
*/
fprintf(mallstream, "! %p %lx\n", ptr, (unsigned long)size);
else
fprintf(mallstream, "< %p\n> %p %lx\n", ptr, hdr, (unsigned long)size);
fflush(mallstream);
if (hdr == mallwatch)
tr_break();
}

return hdr;

void mtrace()
{
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mtrace.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

Saturday, June 16, 2012 11:32 PM

const char *mallfile = MTRACE_FILE;


/*
* Don't panic if we're called more than once.
*/
if (mallstream != NULL)
return;
if (mallfile != NULL || mallwatch != NULL) {
mallstream = fopen(mallfile != NULL ? mallfile : "/dev/null", "w");
if (mallstream != NULL) {
/*
* Be sure it doesn't malloc its buffer!
*/
setbuf(mallstream, mallbuf);
fprintf(mallstream, "= Start\n");
fflush(mallstream);

tr_old_free_hook = __free_hook;
__free_hook = tr_freehook;
tr_old_malloc_hook = __malloc_hook;
__malloc_hook = tr_mallochook;
tr_old_realloc_hook = __realloc_hook;
__realloc_hook = tr_reallochook;

void muntrace()
{
if (mallstream == NULL)
return;
fprintf(mallstream, "= End\n");
fflush(mallstream);

fclose(mallstream);
mallstream = NULL;
__free_hook = tr_old_free_hook;
__malloc_hook = tr_old_malloc_hook;
__realloc_hook = tr_old_realloc_hook;

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:06 PM

/* mudconf.h */
/* $Id: mudconf.h,v 1.141 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#ifndef __MUDCONF_H
#define __MUDCONF_H
#include <netinet/in.h>
#include "ltdl.h"
#include "udb.h"
/* Type definitions */
typedef unsigned char Uchar;
typedef struct hookentry HOOKENT;
struct hookentry {
dbref thing;
int atr;
};
typedef struct key_linked_list KEYLIST;
struct key_linked_list {
char *name;
int data;
struct key_linked_list *next;
};
typedef struct named_function NAMEDFUNC;
struct named_function {
char *fn_name;
int (*handler)(dbref);
};
typedef struct external_funcs EXTFUNCS;
struct external_funcs {
int num_funcs;
NAMEDFUNC **ext_funcs;
};
typedef struct global_register_data GDATA;
struct global_register_data {
int q_alloc;
char **q_regs;
int *q_lens;
int xr_alloc;
char **x_names;
char **x_regs;
int *x_lens;
int dirty;
};

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:06 PM

typedef struct bque BQUE;


/* Command queue */
struct bque {
BQUE
*next;
dbref
player;
/* player who will do command */
dbref
cause;
/* player causing command (for %N) */
dbref
sem;
/* blocking semaphore */
int waittime;
/* time to run command */
int attr;
/* blocking attribute */
char
*text;
/* buffer for comm, env, and scr text */
char
*comm;
/* command */
char
*env[NUM_ENV_VARS]; /* environment vars */
GDATA
*gdata;
/* temp vars */
int nargs;
/* How many args I have */
};
/* --------------------------------------------------------------------------* Modules and related things.
*/
typedef struct module_linked_list MODULE;
struct module_linked_list {
char *modname;
lt_dlhandle handle;
struct module_linked_list *next;
int (*process_command)(dbref, dbref, int, char *, char *[], int);
int (*process_no_match)(dbref, dbref, int, char *, char *, char *[], int);
int (*did_it)(dbref, dbref, dbref,
int, const char *, int, const char *, int,
int, char *[], int, int);
void (*create_obj)(dbref, dbref);
void (*destroy_obj)(dbref, dbref);
void (*create_player)(dbref, dbref, int, int);
void (*destroy_player)(dbref, dbref);
void (*announce_connect)(dbref, const char *, int);
void (*announce_disconnect)(dbref, const char *, int);
void (*examine)(dbref, dbref, dbref, int, int);
void (*dump_database)(FILE *);
void (*db_write)(void);
void (*db_grow)(int, int);
void (*db_write_flatfile)(FILE *);
void (*do_second)(void);
void (*cache_put_notify)(DBData, unsigned int);
void (*cache_del_notify)(DBData, unsigned int);
};
typedef struct api_function_data API_FUNCTION;
struct api_function_data {
const char *name;
const char *param_fmt;
void (*handler)(void *, void *);
};
/* ---------------------------------------------------------------------------2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

* CONFDATA:
*/

Saturday, June 16, 2012 11:06 PM

runtime configurable parameters

typedef struct confparm CONF;


struct confparm {
char *pname;
/* parm name */
int (*interpreter) (); /* routine to interp parameter */
int flags;
/* control flags */
int rperms;
/* read permission flags */
int *loc;
/* where to store value */
long extra;
/* extra data for interpreter */
};
typedef struct confdata CONFDATA;
struct confdata {
int cache_size; /* Maximum size of cache */
int cache_width;
/* Number of cache cells */
int paylimit;
/* getting money gets hard over this much */
int digcost;
/* cost of @dig command */
int linkcost;
/* cost of @link command */
int opencost;
/* cost of @open command */
int robotcost; /* cost of @robot command */
int createmin; /* default (and minimum) cost of @create cmd */
int createmax; /* max cost of @create command */
int quotas;
/* TRUE = have building quotas */
int room_quota; /* quota needed to make a room */
int exit_quota; /* quota needed to make an exit */
int thing_quota;
/* quota needed to make a thing */
int player_quota;
/* quota needed to make a robot player */
int sacfactor; /* sacrifice earns (obj_cost/sfactor) + sadj */
int sacadjust; /* ... */
dbref
start_room; /* initial location for non-Guest players */
dbref
start_home; /* initial HOME for players */
dbref
default_home;
/* HOME when home is inaccessible */
dbref
guest_start_room; /* initial location for Guests */
int vattr_flags;
/* Attr flags for all user-defined attrs */
KEYLIST *vattr_flag_list; /* Linked list, for attr_type conf */
int log_options;
/* What gets logged */
int log_info;
/* Info that goes into log entries */
int log_diversion; /* What logs get diverted? */
Uchar
markdata[8];
/* Masks for marking/unmarking */
int ntfy_nest_lim; /* Max nesting of notifys */
int fwdlist_lim;
/* Max objects in @forwardlist */
int propdir_lim;
/* Max objects in @propdir */
int dbopt_interval; /* Optimize db every N dumps */
char
*dbhome;
/* Database home directory */
char
*txthome;
/* Text files home directory */
char
*binhome;
/* Binary home */
char
*config_file;
/* name of config file, used by @restart */
char
*crashdb;
/* write database here on crash */
char
*gdbm;
/* use this gdbm file if we need one */
char
*status_file;
/* Where to write arg to @shutdown */
char
*mudlogname;
/* Name of the game log file */
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:06 PM

char
*pid_file; /* Name of the game pid file */
int have_pueblo;
/* Is Pueblo support compiled in? */
int have_zones; /* Should zones be active? */
int port;
/* user port */
int conc_port; /* concentrator port */
int init_size; /* initial db size */
int use_global_aconn;
/* Do we want to use global @aconn code? */
int global_aconn_uselocks; /* global @aconn obeys uselocks? */
int have_guest; /* Do we wish to allow a GUEST character? */
int guest_char; /* player num of prototype GUEST character */
int
guest_nuker;
/* Wiz who nukes the GUEST characters. */
int
number_guests; /* number of guest characters allowed */
char
*guest_basename; /* Base name or alias for guest char */
char
*guest_prefixes; /* Prefixes for the guest char's name */
char
*guest_suffixes; /* Suffixes for the guest char's name */
char
*guest_password; /* Default password for guests */
char
*guest_file;
/* display if guest connects */
char
*conn_file; /* display on connect if no registration */
char
*creg_file; /* display on connect if registration */
char
*regf_file; /* display on (failed) create if reg is on */
char
*motd_file; /* display this file on login */
char
*wizmotd_file; /* display this file on login to wizards */
char
*quit_file; /* display on quit */
char
*down_file; /* display this file if no logins */
char
*full_file; /* display when max users exceeded */
char
*site_file; /* display if conn from bad site */
char
*crea_file; /* display this on login for new users */
char
*motd_msg; /* Wizard-settable login message */
char
*wizmotd_msg; /* Login message for wizards only */
char
*downmotd_msg; /* Settable 'logins disabled' message */
char
*fullmotd_msg; /* Settable 'Too many players' message */
char
*dump_msg; /* Message displayed when @dump-ing */
char
*postdump_msg; /* Message displayed after @dump-ing */
char
*fixed_home_msg; /* Message displayed when going home and FIXED */
char
*fixed_tel_msg; /* Message displayed when teleporting and FIXED */
char
*huh_msg;
/* Message displayed when a Huh? is gotten */
#ifdef PUEBLO_SUPPORT
char
*pueblo_msg;
/* Message displayed to Pueblo clients */
char
*htmlconn_file; /* display on PUEBLOCLIENT message */
#endif
char
*exec_path; /* argv[0] */
char
*sql_host; /* IP address of SQL database */
char
*sql_db;
/* Database to use */
char
*sql_username; /* Username for database */
char
*sql_password; /* Password for database */
int sql_reconnect; /* Auto-reconnect if connection dropped? */
int indent_desc;
/* Newlines before and after descs? */
int name_spaces;
/* allow player names to have spaces */
int site_chars; /* where to truncate site name */
int fork_dump; /* perform dump in a forked process */
int fork_vfork; /* use vfork to fork */
int sig_action; /* What to do with fatal signals */
int paranoid_alloc; /* Rigorous buffer integrity checks */
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int

Saturday, June 16, 2012 11:06 PM

max_players;
/* Max # of connected players */
dump_interval; /* interval between checkpoint dumps in secs */
check_interval; /* interval between db check/cleans in secs */
events_daily_hour; /* At what hour should @daily be executed? */
dump_offset;
/* when to take first checkpoint dump */
check_offset;
/* when to perform first check and clean */
idle_timeout;
/* Boot off players idle this long in secs */
conn_timeout;
/* Allow this long to connect before booting */
idle_interval; /* when to check for idle users */
retry_limit;
/* close conn after this many bad logins */
output_limit;
/* Max # chars queued for output */
paycheck;
/* players earn this much each day connected */
paystart;
/* new players start with this much money */
start_quota;
/* Quota for new players */
start_room_quota;
/* Room quota for new players */
start_exit_quota;
/* Exit quota for new players */
start_thing_quota;
/* Thing quota for new players */
start_player_quota;
/* Player quota for new players */
payfind;
/* chance to find a penny with wandering */
killmin;
/* default (and minimum) cost of kill cmd */
killmax;
/* max cost of kill command */
killguarantee; /* cost of kill cmd that guarantees success */
pagecost;
/* cost of @page command */
searchcost; /* cost of commands that search the whole DB */
waitcost;
/* cost of @wait (refunded when finishes) */
building_limit; /* max number of objects in the db */
queuemax;
/* max commands a player may have in queue */
queue_chunk;
/* # cmds to run from queue when idle */
active_q_chunk; /* # cmds to run from queue when active */
machinecost;
/* One in mc+1 cmds costs 1 penny (POW2-1) */
clone_copy_cost;/* Does @clone copy value? */
use_hostname;
/* TRUE = use machine NAME rather than quad */
typed_quotas;
/* TRUE = use quotas by type */
ex_flags;
/* TRUE = show flags on examine */
robot_speak;
/* TRUE = allow robots to speak in public */
pub_flags; /* TRUE = flags() works on anything */
quiet_look; /* TRUE = don't see attribs when looking */
exam_public;
/* Does EXAM show public attrs by default? */
read_rem_desc; /* Can the DESCs of nonlocal objs be read? */
read_rem_name; /* Can the NAMEs of nonlocal objs be read? */
sweep_dark; /* Can you sweep dark places? */
player_listen; /* Are AxHEAR triggered on players? */
quiet_whisper; /* Can others tell when you whisper? */
dark_sleepers; /* Are sleeping players 'dark'? */
see_own_dark;
/* Do you see your own dark stuff? */
idle_wiz_dark; /* Do idling wizards get set dark? */
visible_wizzes; /* Do dark wizards show up on contents? */
pemit_players; /* Can you @pemit to faraway players? */
pemit_any; /* Can you @pemit to ANY remote object? */
int addcmd_match_blindly;
/* Does @addcommand produce a Huh?
* if syntax issues mean no wildcard
* is matched?
*/
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:06 PM

int addcmd_obey_stop;
/* Does @addcommand still multiple
* match on STOP objs?
*/
int addcmd_obey_uselocks;
/* Does @addcommand obey uselocks? */
int lattr_oldstyle; /* Bad lattr() return empty or #-1 NO MATCH? */
int bools_oldstyle; /* TinyMUSH 2.x and TinyMUX bools */
int match_mine; /* Should you check yourself for $-commands? */
int match_mine_pl; /* Should players check selves for $-cmds? */
int switch_df_all; /* Should @switch match all by default? */
int fascist_objeval; /* Does objeval() require victim control? */
int fascist_tport; /* Src of teleport must be owned/JUMP_OK */
int terse_look; /* Does manual look obey TERSE */
int terse_contents; /* Does TERSE look show exits */
int terse_exits;
/* Does TERSE look show obvious exits */
int terse_movemsg; /* Show move msgs (SUCC/LEAVE/etc) if TERSE? */
int trace_topdown; /* Is TRACE output top-down or bottom-up? */
int safe_unowned;
/* Are objects not owned by you safe? */
int trace_limit;
/* Max lines of trace output if top-down */
int wiz_obey_linklock; /* Do wizards obey linklocks? */
int local_masters; /* Do we check Zone rooms as local masters? */
int match_zone_parents; /* Objects in local master rooms
* inherit commands from their
* parents, just like normal?
*/
int req_cmds_flag; /* COMMANDS flag required to check $-cmds? */
int ansi_colors;
/* allow ANSI colors? */
int safer_passwords;/* enforce reasonably good password choices? */
int space_compress; /* Convert multiple spaces into one space */
int instant_recycle;/* Do destroy_ok objects get insta-nuke? */
int dark_actions;
/* Trigger @a-actions even when dark? */
int no_ambiguous_match; /* match_result() -> last_match_result() */
int exit_calls_move; /* Matching an exit in the main command
* parser invokes the 'move' command.
*/
int move_match_more; /* Exit matches in 'move' parse like the
* main command parser (local, global, zone;
* pick random on ambiguous).
*/
int autozone;
/* New objs are zoned to creator's zone */
int page_req_equals; /* page command must always contain '=' */
int comma_say; /* Use grammatically-correct comma in says */
int you_say;
/* Show 'You say' to the player */
int c_cmd_subst;
/* Is %c last command or ansi? */
dbref
master_room;
/* Room containing default cmds/exits/etc */
dbref
player_proto;
/* Player prototype to clone */
dbref
room_proto; /* Room prototype to clone */
dbref
exit_proto; /* Exit prototype to clone */
dbref
thing_proto;
/* Thing prototype to clone */
dbref
player_defobj; /* Players use this for attr template */
dbref
room_defobj;
/* Rooms use this for attr template */
dbref
exit_defobj;
/* Exits use this for attr template */
dbref
thing_defobj;
/* Things use this for attr template */
dbref
player_parent; /* Parent that players start with */
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

};

Saturday, June 16, 2012 11:06 PM

dbref
room_parent;
/* Parent that rooms start with */
dbref
exit_parent;
/* Parent that exits start with */
dbref
thing_parent;
/* Parent that things start with */
FLAGSET player_flags;
/* Flags players start with */
FLAGSET room_flags; /* Flags rooms start with */
FLAGSET exit_flags; /* Flags exits start with */
FLAGSET thing_flags;
/* Flags things start with */
FLAGSET robot_flags;
/* Flags robots start with */
FLAGSET stripped_flags; /* Flags stripped by @clone and @chown */
char
*mud_name; /* Name of the mud */
char
*mud_shortname; /* Shorter name, for log */
char
*one_coin; /* name of one coin (ie. "penny") */
char
*many_coins;
/* name of many coins (ie. "pennies") */
int timeslice; /* How often do we bump people's cmd quotas? */
int cmd_quota_max; /* Max commands at one time */
int cmd_quota_incr; /* Bump #cmds allowed by this each timeslice */
int lag_check; /* Is CPU usage checking compiled in? */
int max_cmdsecs;
/* Threshhold for real time taken by command */
int control_flags; /* Global runtime control flags */
int wild_times_lim; /* Max recursions in wildcard match */
int cmd_nest_lim;
/* Max nesting of commands like @switch/now */
int cmd_invk_lim;
/* Max commands in one queue entry */
int func_nest_lim; /* Max nesting of functions */
int func_invk_lim; /* Max funcs invoked by a command */
int func_cpu_lim_secs; /* Max secs of func CPU time by a cmd */
clock_t func_cpu_lim;
/* Max clock ticks of func CPU time by a cmd */
int lock_nest_lim; /* Max nesting of lock evals */
int parent_nest_lim;/* Max levels of parents */
int zone_nest_lim; /* Max nesting of zones */
int numvars_lim;
/* Max number of variables per object */
int stack_lim; /* Max number of items on an object stack */
int struct_lim; /* Max number of defined structures for obj */
int instance_lim;
/* Max number of struct instances for obj */
int max_player_aliases; /* Max number of aliases for a player */
int register_limit; /* Max number of named q-registers */
char
*struct_dstr;
/* Delim string used for struct 'examine' */

extern CONFDATA mudconf;


/* --------------------------------------------------------------------------* Various types.
*/
typedef struct site_data SITE;
struct site_data {
struct site_data *next;
/* Next site in chain */
struct in_addr address;
/* Host or network address */
struct in_addr mask;
/* Mask to apply before comparing */
int flag;
/* Value to return on match */
};
typedef struct objlist_block OBLOCK;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:06 PM

struct objlist_block {
struct objlist_block *next;
dbref
data[(LBUF_SIZE - sizeof(OBLOCK *)) / sizeof(dbref)];
};
#define OBLOCK_SIZE ((LBUF_SIZE - sizeof(OBLOCK *)) / sizeof(dbref))
typedef struct objlist_stack OLSTK;
struct objlist_stack {
struct objlist_stack *next; /* Next object list in stack */
OBLOCK *head;
/* Head of object list */
OBLOCK *tail;
/* Tail of object list */
OBLOCK *cblock;
/* Current block for scan */
int count;
/* Number of objs in last obj list block */
int citm;
/* Current item for scan */
};
typedef struct markbuf MARKBUF;
struct markbuf {
char
chunk[5000];
};
typedef struct alist ALIST;
struct alist {
char
*data;
int len;
struct alist *next;
};
typedef struct badname_struc BADNAME;
struct badname_struc {
char
*name;
struct badname_struc
*next;
};
typedef struct forward_list FWDLIST;
struct forward_list {
int count;
int *data;
};
typedef struct propdir_list PROPDIR;
struct propdir_list {
int count;
int *data;
};
/* --------------------------------------------------------------------------* State data.
*/
typedef struct statedata STATEDATA;
struct statedata {
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:06 PM

int record_players; /* The maximum # of player logged on */


int db_block_size; /* Block size of database */
Obj *objpipes[NUM_OBJPIPES];
/* Number of object pipelines */
unsigned int objc; /* Object reference counter */
char
*version;
/* MUSH version string */
char
*short_ver; /* Short version number (for INFO) */
char
*buildinfo; /* Compile info */
char
modloaded[MBUF_SIZE];
/* Modules loaded */
int initializing;
/* Are we reading config file at startup? */
int loading_db; /* Are we loading the db? */
int standalone; /* Are we converting the database? */
int panicking; /* Are we in the middle of dying horribly? */
int restarting; /* Are we restarting? */
int dumping;
/* Are we dumping? */
pid_t
dumper;
/* If forked-dumping, with what pid? */
int logging;
/* Are we in the middle of logging? */
int epoch;
/* Generation number for dumps */
int generation; /* DB global generation number */
int mudlognum; /* Number of logfile */
int helpfiles; /* Number of external indexed helpfiles */
int hfiletab_size; /* Size of the table storing path pointers */
char
**hfiletab; /* Array of path pointers */
HASHTAB *hfile_hashes; /* Pointer to an array of index hashtables */
dbref
curr_enactor;
/* Who initiated the current command */
dbref
curr_player;
/* Who is running the current command */
char
*curr_cmd; /* The current command */
int alarm_triggered;/* Has periodic alarm signal occurred? */
time_t now;
/* What time is it now? */
time_t dump_counter;
/* Countdown to next db dump */
time_t check_counter; /* Countdown to next db check */
time_t idle_counter;
/* Countdown to next idle check */
time_t mstats_counter; /* Countdown to next mstats snapshot */
time_t events_counter; /* Countdown to next events check */
int shutdown_flag; /* Should interface be shut down? */
int flatfile_flag; /* Dump a flatfile when we have the chance */
time_t start_time; /* When was MUSH started */
time_t restart_time;
/* When did we last restart? */
int reboot_nums;
/* How many times have we restarted? */
time_t cpu_count_from; /* When did we last reset CPU counters? */
char
*debug_cmd; /* The command we are executing (if any) */
char
doing_hdr[DOING_LEN]; /* Doing column header in WHO display */
SITE
*access_list;
/* Access states for sites */
SITE
*suspect_list; /* Sites that are suspect */
HASHTAB command_htab;
/* Commands hashtable */
HASHTAB logout_cmd_htab;/* Logged-out commands hashtable (WHO, etc) */
HASHTAB func_htab; /* Functions hashtable */
HASHTAB ufunc_htab; /* Local functions hashtable */
HASHTAB powers_htab;
/* Powers hashtable */
HASHTAB flags_htab; /* Flags hashtable */
HASHTAB attr_name_htab; /* Attribute names hashtable */
HASHTAB vattr_name_htab;/* User attribute names hashtable */
HASHTAB player_htab;
/* Player name->number hashtable */
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:06 PM

HASHTAB nref_htab; /* Object name reference #_name_ mapping */


NHSHTAB desc_htab; /* Socket descriptor hashtable */
NHSHTAB fwdlist_htab;
/* Room forwardlists */
NHSHTAB propdir_htab;
/* Propdir lists */
NHSHTAB redir_htab; /* Redirections */
NHSHTAB objstack_htab; /* Object stacks */
NHSHTAB parent_htab;
/* Parent $-command exclusion */
HASHTAB vars_htab; /* Persistent variables hashtable */
HASHTAB structs_htab;
/* Structure hashtable */
HASHTAB cdefs_htab; /* Components hashtable */
HASHTAB instance_htab; /* Instances hashtable */
HASHTAB instdata_htab; /* Structure data hashtable */
HASHTAB api_func_htab; /* Registered module API functions */
MODULE *modules_list;
/* Loadable modules hashtable */
int max_structs;
int max_cdefs;
int max_instance;
int max_instdata;
int max_stacks;
int max_vars;
int attr_next; /* Next attr to alloc when freelist is empty */
BQUE
*qfirst;
/* Head of player queue */
BQUE
*qlast;
/* Tail of player queue */
BQUE
*qlfirst;
/* Head of object queue */
BQUE
*qllast;
/* Tail of object queue */
BQUE
*qwait;
/* Head of wait queue */
BQUE
*qsemfirst; /* Head of semaphore queue */
BQUE
*qsemlast; /* Tail of semaphore queue */
BADNAME *badname_head; /* List of disallowed names */
int mstat_ixrss[2]; /* Summed shared size */
int mstat_idrss[2]; /* Summed private data size */
int mstat_isrss[2]; /* Summed private stack size */
int mstat_secs[2]; /* Time of samples */
int mstat_curr; /* Which sample is latest */
ALIST
iter_alist; /* Attribute list for iterations */
char
*mod_alist; /* Attribute list for modifying */
int mod_size;
/* Length of modified buffer */
dbref
mod_al_id; /* Where did mod_alist come from? */
OLSTK
*olist;
/* Stack of object lists for nested searches */
dbref
freelist;
/* Head of object freelist */
int min_size;
/* Minimum db size (from file header) */
int db_top;
/* Number of items in the db */
int db_size;
/* Allocated size of db structure */
unsigned int moduletype_top;
/* Highest module DBTYPE */
int *guest_free;
/* Table to keep track of free guests */
MARKBUF *markbits; /* temp storage for marking/unmarking */
int in_loop;
/* In a loop() statement? */
char
*loop_token[MAX_ITER_NESTING]; /* Value of ## */
char
*loop_token2[MAX_ITER_NESTING]; /* Value of #? */
int loop_number[MAX_ITER_NESTING]; /* Value of #@ */
int in_switch; /* In a switch() statement? */
char
*switch_token; /* Value of #$ */
int func_nest_lev; /* Current nesting of functions */
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:06 PM

int func_invk_ctr; /* Functions invoked so far by this command */


int ntfy_nest_lev; /* Current nesting of notifys */
int lock_nest_lev; /* Current nesting of lock evals */
int cmd_nest_lev;
/* Current nesting of commands like @sw/now */
int cmd_invk_ctr;
/* Commands invoked so far by this qentry */
int wild_times_lev; /* Wildcard matching tries. */
GDATA
*rdata;
/* Global register data */
int zone_nest_num; /* Global current zone nest position */
int break_called;
/* Boolean flag for @break and @assert */
int inpipe;
/* Boolean flag for command piping */
char
*pout;
/* The output of the pipe used in %| */
char
*poutnew;
/* The output being build by the current command */
char
*poutbufc; /* Buffer position for poutnew */
dbref
poutobj;
/* Object doing the piping */
int sql_socket; /* Socket fd for SQL database connection */
clock_t cputime_base;
/* CPU baselined at beginning of command */
clock_t cputime_now;
/* CPU time recorded during command */
const unsigned char *retabs; /* PCRE regexp tables */
#if !defined(TEST_MALLOC) && defined(RAW_MEMTRACKING)
MEMTRACK *raw_allocs;
/* Tracking of raw memory allocations */
#endif
int dbm_fd;
/* File descriptor of our DBM database */
};
extern STATEDATA mudstate;
/* --------------------------------------------------------------------------* Configuration parameter handler definition
*/
#define CF_HAND(proc)
int proc (vp, str, extra, player, cmd) \
int *vp; \
char
*str, *cmd; \
long
extra; \
dbref
player;
/* This is for the DEC Alpha, which can't cast a pointer to an int. */
#define CF_AHAND(proc) int proc (vp, str, extra, player, cmd) \
long
**vp; \
char
*str, *cmd; \
long
extra; \
dbref
player;
#define CF_HDCL(proc)

int FDECL(proc, (int *, char *, long, dbref, char *))

/* --------------------------------------------------------------------------* Misc. constants.


*/
/* Global flags */
/* Game control flags in mudconf.control_flags */
#define CF_LOGIN

0x0001

/* Allow nonwiz logins to the MUSH */


-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\mudconf.h

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

#define CF_BUILD
0x0002
#define CF_INTERP
0x0004
#define CF_CHECKPOINT
0x0008
#define CF_DBCHECK 0x0010
#define CF_IDLECHECK
0x0020
/* empty
0x0040 */
/* empty
0x0080 */
#define CF_DEQUEUE 0x0100
#define CF_GODMONITOR
0x0200
#define CF_EVENTCHECK
0x0400
/* Host information codes */
#define
#define
#define
#define

Saturday, June 16, 2012 11:06 PM

/* Allow building commands */


/* Allow object triggering */
/* Perform auto-checkpointing */
/* Periodically check/clean the DB */
/* Periodically check for idle users */
/* Remove entries from the queue */
/* Display commands to the God. */
/* Allow events checking */

H_REGISTRATION 0x0001 /* Registration ALWAYS on */


H_FORBIDDEN 0x0002 /* Reject all connects */
H_SUSPECT
0x0004 /* Notify wizards of connects/disconnects */
H_GUEST
0x0008 /* Don't permit guests from here */

/* Logging options */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

LOG_ALLCOMMANDS 0x00000001
LOG_ACCOUNTING 0x00000002
LOG_BADCOMMANDS 0x00000004
LOG_BUGS
0x00000008 /*
LOG_DBSAVES 0x00000010 /*
LOG_CONFIGMODS 0x00000020
LOG_PCREATES
0x00000040
LOG_KILLS
0x00000080 /*
LOG_LOGIN
0x00000100 /*
LOG_NET
0x00000200 /*
LOG_SECURITY
0x00000400
LOG_SHOUTS 0x00000800 /*
LOG_STARTUP 0x00001000 /*
LOG_WIZARD 0x00002000 /*
LOG_ALLOCATE
0x00004000
LOG_PROBLEMS
0x00008000
LOG_KBCOMMANDS 0x00010000
LOG_SUSPECTCMDS 0x00020000
LOG_TIMEUSE 0x00040000 /*
LOG_LOCAL
0x00080000 /*
LOG_ALWAYS 0x80000000 /*

/* Log all commands */


/* Write accounting info on logout */
/* Log bad commands */
Log program bugs found */
Log database dumps */
/* Log changes to configuration */
/* Log character creations */
Log KILLs */
Log logins and logouts */
Log net connects and disconnects */
/* Log security-related events */
Log shouts */
Log nonfatal errors in startup */
Log dangerous things */
/* Log alloc/free from buffer pools */
/* Log runtime problems */
/* Log keyboard commands */
/* Log SUSPECT player keyboard cmds */
Log CPU time usage */
Log user stuff via @log */
Always log it */

#define
#define
#define
#define

LOGOPT_FLAGS
0x01
/* Report flags on object */
LOGOPT_LOC
0x02
/* Report loc of obj when requested */
LOGOPT_OWNER
0x04
/* Report owner of obj if not obj */
LOGOPT_TIMESTAMP
0x08
/* Timestamp log entries */

#endif /* __MUDCONF_H */

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:31 PM

/* netcommon.c */
/* $Id: netcommon.c,v 1.89 2008/04/29 20:07:37 lwl Exp $ */
/* This file contains routines used by the networking code that do not
* depend on the implementation of the networking code. The network-specific
* portions of the descriptor data structure are not used.
*/
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include
#include
#include
extern
extern
extern
extern
extern
extern
extern
extern

"file_c.h" /*
"command.h"
"attrs.h" /*
"ansi.h"
/*
"powers.h" /*
"match.h" /*

required by code */
/* required by code */
required by code */
required by code */
required by code */
required by code */

int FDECL(process_output, (DESC * d));


void FDECL(handle_prog, (DESC *, char *));
void FDECL(record_login, (dbref, int, char *, char *, char *));
dbref FDECL(connect_player, (char *, char *, char *, char *, char *));
char * FDECL(make_guest, (DESC *));
const char *conn_reasons[];
const char *conn_messages[];
int ansi_nchartab[];

/* --------------------------------------------------------------------------* timeval_sub: return difference between two times as a timeval


*/
struct timeval timeval_sub(now, then)
struct timeval now, then;
{

now.tv_sec -= then.tv_sec;
now.tv_usec -= then.tv_usec;
if (now.tv_usec < 0) {
now.tv_usec += 1000000;
now.tv_sec--;
}
return now;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:31 PM

/* --------------------------------------------------------------------------* msec_diff: return difference between two times in milliseconds


*/
int msec_diff(now, then)
struct timeval now, then;
{
return ((now.tv_sec - then.tv_sec) * 1000 +
(now.tv_usec - then.tv_usec) / 1000);
}
/* --------------------------------------------------------------------------* msec_add: add milliseconds to a timeval
*/
struct timeval msec_add(t, x)
struct timeval t;
int x;
{
t.tv_sec += x / 1000;
t.tv_usec += (x % 1000) *
if (t.tv_usec >= 1000000)
t.tv_sec += t.tv_usec
t.tv_usec = t.tv_usec
}
return t;
}

1000;
{
/ 1000000;
% 1000000;

/* --------------------------------------------------------------------------* update_quotas: Update timeslice quotas


*/
struct timeval update_quotas(last, current)
struct timeval last, current;
{
int nslices;
DESC *d;
nslices = msec_diff(current, last) / mudconf.timeslice;

if (nslices > 0) {
DESC_ITER_ALL(d) {
d->quota += mudconf.cmd_quota_incr * nslices;
if (d->quota > mudconf.cmd_quota_max)
d->quota = mudconf.cmd_quota_max;
}
}
return msec_add(last, nslices * mudconf.timeslice);

#ifdef PUEBLO_SUPPORT
/* raw_notify_html() -- raw_notify() without the newline */
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:31 PM

void raw_notify_html(player, msg)


dbref player;
char *msg;
{
DESC *d;
if (!msg || !*msg)
return;
if (mudstate.inpipe && (player == mudstate.poutobj)) {
safe_str(msg, mudstate.poutnew, &mudstate.poutbufc);
return;
}
if (!Connected(player))
return;
if (!Html(player))
return;

/* Don't splooge HTML at a non-HTML player. */

DESC_ITER_PLAYER(player, d) {
queue_string(d, msg);
}

}
#endif

/* --------------------------------------------------------------------------* raw_notify: write a message to a player


*/
void raw_notify(player, msg)
dbref player;
char *msg;
{
DESC *d;
if (!msg || !*msg)
return;
if (mudstate.inpipe && (player == mudstate.poutobj)) {
safe_str(msg, mudstate.poutnew, &mudstate.poutbufc);
safe_crlf(mudstate.poutnew, &mudstate.poutbufc);
return;
}
if (!Connected(player))
return;

DESC_ITER_PLAYER(player, d) {
queue_string(d, msg);
queue_write(d, "\r\n", 2);
}

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:31 PM

void raw_notify_newline(player)
dbref player;
{
DESC *d;
if (mudstate.inpipe && (player == mudstate.poutobj)) {
safe_crlf(mudstate.poutnew, &mudstate.poutbufc);
return;
}
if (!Connected(player))
return;

DESC_ITER_PLAYER(player, d) {
queue_write(d, "\r\n", 2);
}

/* --------------------------------------------------------------------------* raw_broadcast: Send message to players who have indicated flags


*/
#if defined(__STDC__) && defined(STDC_HEADERS)
void raw_broadcast(int inflags, char *template,...)
#else
void raw_broadcast(va_alist)
va_dcl
#endif
{
#ifdef HAVE_VSNPRINTF
char buff[LBUF_SIZE];
#else
char buff[20000];
#endif
DESC *d;
int test_flag, which_flag, p_flag;
va_list ap;
#if defined(__STDC__) && defined(STDC_HEADERS)
va_start(ap, template);
#else
int inflags;
char *template;
va_start(ap);
inflags = va_arg(ap, int);
template = va_arg(ap, char *);
#endif
if (!template || !*template)
return;

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:31 PM

#ifdef HAVE_VSNPRINTF
vsnprintf(buff, LBUF_SIZE, template, ap);
#else
vsprintf(buff, template, ap);
#endif
/* Note that this use of the flagwords precludes testing for
* type in this function. (Not that this matters, since we
* look at connected descriptors, which must be players.)
*/
test_flag = inflags & ~(FLAG_WORD2 | FLAG_WORD3);
if (inflags & FLAG_WORD2)
which_flag = 2;
else if (inflags & FLAG_WORD3)
which_flag = 3;
else
which_flag = 1;
DESC_ITER_CONN(d) {
switch (which_flag) {
case 1:
p_flag = Flags(d->player); break;
case 2:
p_flag = Flags2(d->player); break;
case 3:
p_flag = Flags3(d->player); break;
default:
p_flag = Flags(d->player);
}
/* If inflags is 0, broadcast to everyone */
if ((p_flag & test_flag) || (!test_flag)) {
queue_string(d, buff);
queue_write(d, "\r\n", 2);
process_output(d);
}

}
va_end(ap);

/* --------------------------------------------------------------------------* clearstrings: clear out prefix and suffix strings


*/
void clearstrings(d)
DESC *d;
{
if (d->output_prefix) {
free_lbuf(d->output_prefix);
d->output_prefix = NULL;
}
if (d->output_suffix) {
free_lbuf(d->output_suffix);
d->output_suffix = NULL;
}
}

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:31 PM

/* --------------------------------------------------------------------------* queue_write: Add text to the output queue for the indicated descriptor.
*/
void queue_write(d, b, n)
DESC *d;
const char *b;
int n;
{
int left;
TBLOCK *tp;
if (n <= 0)
return;
if (d->output_size + n > mudconf.output_limit)
process_output(d);
left = mudconf.output_limit - d->output_size - n;
if (left < 0) {
tp = d->output_head;
if (tp == NULL) {
STARTLOG(LOG_PROBLEMS, "QUE", "WRITE")
log_printf("Flushing when output_head is null!" );
ENDLOG
} else {
STARTLOG(LOG_NET, "NET", "WRITE")
log_printf("[%d/%s] Output buffer overflow, %d chars discarded by " ,
d->descriptor, d->addr, tp->hdr.nchars);
log_name(d->player);
ENDLOG
d->output_size -= tp->hdr.nchars;
d->output_head = tp->hdr.nxt;
d->output_lost += tp->hdr.nchars;
if (d->output_head == NULL)
d->output_tail = NULL;
XFREE(tp, "queue_write.tp");
}
}
/* Allocate an output buffer if needed */
if (d->output_head == NULL) {
tp = (TBLOCK *) XMALLOC(OUTPUT_BLOCK_SIZE, "queue_write");
tp->hdr.nxt = NULL;
tp->hdr.start = tp->data;
tp->hdr.end = tp->data;
tp->hdr.nchars = 0;
d->output_head = tp;
d->output_tail = tp;
} else {
tp = d->output_tail;
}

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:31 PM

/* Now tp points to the last buffer in the chain */


d->output_size += n;
d->output_tot += n;
do {
/* See if there is enough space in the buffer to hold the
* string. If so, copy it and update the pointers..
*/
left = OUTPUT_BLOCK_SIZE - (tp->hdr.end - (char *)tp + 1);
if (n <= left) {
strncpy(tp->hdr.end, b, n);
tp->hdr.end += n;
tp->hdr.nchars += n;
n = 0;
} else {
/* It didn't fit. Copy what will fit and then
* allocate * another buffer and retry.
*/
if (left > 0) {
strncpy(tp->hdr.end, b, left);
tp->hdr.end += left;
tp->hdr.nchars += left;
b += left;
n -= left;
}
tp = (TBLOCK *) XMALLOC(OUTPUT_BLOCK_SIZE, "queue_write.2");
tp->hdr.nxt = NULL;
tp->hdr.start = tp->data;
tp->hdr.end = tp->data;
tp->hdr.nchars = 0;
d->output_tail->hdr.nxt = tp;
d->output_tail = tp;

}
} while (n > 0);

INLINE void queue_string(d, s)


DESC *d;
const char *s;
{
char *new;
if (s) {
if (!mudconf.ansi_colors) {
queue_write(d, s, strlen(s));
} else {
if (!Ansi(d->player) && strchr(s, ESC_CHAR))
new = strip_ansi(s);
else if (NoBleed(d->player))
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:31 PM

new = normal_to_white(s);
else if (d->colormap)
new = remap_colors(s, d->colormap);
else
new = (char *) s;
queue_write(d, new, strlen(new));
}

INLINE void queue_rawstring(d, s)


DESC *d;
const char *s;
{
if (s)
queue_write(d, s, strlen(s));
}
void freeqs(d)
DESC *d;
{
TBLOCK *tb, *tnext;
CBLK *cb, *cnext;
tb = d->output_head;
while (tb) {
tnext = tb->hdr.nxt;
XFREE(tb, "freeqs.tb");
tb = tnext;
}
d->output_head = NULL;
d->output_tail = NULL;
cb = d->input_head;
while (cb) {
cnext = (CBLK *) cb->hdr.nxt;
free_lbuf(cb);
cb = cnext;
}
d->input_head = NULL;
d->input_tail = NULL;

if (d->raw_input)
free_lbuf(d->raw_input);
d->raw_input = NULL;
d->raw_input_at = NULL;

/* --------------------------------------------------------------------------* desc_addhash: Add a net descriptor to its player hash list.


*/

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:31 PM

void desc_addhash(d)
DESC *d;
{
dbref player;
DESC *hdesc;

player = d->player;
hdesc = (DESC *) nhashfind((int)player, &mudstate.desc_htab);
if (hdesc == NULL) {
d->hashnext = NULL;
nhashadd((int)player, (int *)d, &mudstate.desc_htab);
} else {
d->hashnext = hdesc;
nhashrepl((int)player, (int *)d, &mudstate.desc_htab);
}

/* --------------------------------------------------------------------------* desc_delhash: Remove a net descriptor from its player hash list.
*/
static void desc_delhash(d)
DESC *d;
{
DESC *hdesc, *last;
dbref player;

player = d->player;
last = NULL;
hdesc = (DESC *) nhashfind((int)player, &mudstate.desc_htab);
while (hdesc != NULL) {
if (d == hdesc) {
if (last == NULL) {
if (d->hashnext == NULL) {
nhashdelete((int)player,
&mudstate.desc_htab);
} else {
nhashrepl((int)player,
(int *)d->hashnext,
&mudstate.desc_htab);
}
} else {
last->hashnext = d->hashnext;
}
break;
}
last = hdesc;
hdesc = hdesc->hashnext;
}
d->hashnext = NULL;

void welcome_user(d)
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

DESC *d;
{
#ifdef PUEBLO_SUPPORT
queue_rawstring(d,
#endif
if (d->host_info &
fcache_dump(d,
else
fcache_dump(d,
}

Saturday, June 16, 2012 11:31 PM

PUEBLO_SUPPORT_MSG);
H_REGISTRATION)
FC_CONN_REG);
FC_CONN);

void save_command(d, command)


DESC *d;
CBLK *command;
{

command->hdr.nxt = NULL;
if (d->input_tail == NULL)
d->input_head = command;
else
d->input_tail->hdr.nxt = command;
d->input_tail = command;

static void set_userstring(userstring, command)


char **userstring;
const char *command;
{
while (*command && isascii(*command) && isspace(*command))
command++;
if (!*command) {
if (*userstring != NULL) {
free_lbuf(*userstring);
*userstring = NULL;
}
} else {
if (*userstring == NULL) {
*userstring = alloc_lbuf("set_userstring");
}
strcpy(*userstring, command);
}
}
static void parse_connect(msg, command, user, pass)
const char *msg;
char *command, *user, *pass;
{
char *p;
if (strlen(msg) > MBUF_SIZE) {
*command = '\0';
*user = '\0';
*pass = '\0';
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:31 PM

return;
}
while (*msg && isascii(*msg) && isspace(*msg))
msg++;
p = command;
while (*msg && isascii(*msg) && !isspace(*msg))
*p++ = *msg++;
*p = '\0';
while (*msg && isascii(*msg) && isspace(*msg))
msg++;
p = user;
if (mudconf.name_spaces && (*msg == '\"')) {
for (; *msg && (*msg == '\"' || isspace(*msg)); msg++) ;
while (*msg && *msg != '\"') {
while (*msg && !isspace(*msg) && (*msg != '\"'))
*p++ = *msg++;
if (*msg == '\"')
break;
while (*msg && isspace(*msg))
msg++;
if (*msg && (*msg != '\"'))
*p++ = ' ';
}
for (; *msg && *msg == '\"'; msg++) ;
} else
while (*msg && isascii(*msg) && !isspace(*msg))
*p++ = *msg++;
*p = '\0';
while (*msg && isascii(*msg) && isspace(*msg))
msg++;
p = pass;
while (*msg && isascii(*msg) && !isspace(*msg))
*p++ = *msg++;
*p = '\0';

static const char *time_format_1(dt)


time_t dt;
{
register struct tm *delta;
static char buf[64];
if (dt < 0)
dt = 0;
delta = gmtime(&dt);
if (delta->tm_yday > 0) {
sprintf(buf, "%dd %02d:%02d",
delta->tm_yday, delta->tm_hour, delta->tm_min);
} else {
sprintf(buf, "%02d:%02d",
delta->tm_hour, delta->tm_min);
}
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:31 PM

return buf;

static const char *time_format_2(dt)


time_t dt;
{
register struct tm *delta;
static char buf[64];
if (dt < 0)
dt = 0;

delta = gmtime(&dt);
if (delta->tm_yday > 0) {
sprintf(buf, "%dd", delta->tm_yday);
} else if (delta->tm_hour > 0) {
sprintf(buf, "%dh", delta->tm_hour);
} else if (delta->tm_min > 0) {
sprintf(buf, "%dm", delta->tm_min);
} else {
sprintf(buf, "%ds", delta->tm_sec);
}
return buf;

static void announce_connattr(d, player, loc, reason, num, attr)


DESC *d;
dbref player, loc;
const char *reason;
int num, attr;
{
dbref aowner, obj, zone;
int aflags, alen, argn;
char *buf;
char *argv[7];
/* Pass
*
%0
*
%1
*
%2
*
%3
*
%4
*
%5
*
%6
*/

session information on the stack:


- reason message
- current number of connections
- connect time
- last input
- number of commands entered
- bytes input
- bytes output

argv[0] = (char *)reason;


argv[1] = alloc_sbuf("announce_connchange.num");
sprintf(argv[1], "%d", num);
if (attr == A_ADISCONNECT) {
argn = 7;
argv[2] = alloc_sbuf("announce_connchange.conn");
argv[3] = alloc_sbuf("announce_connchange.last");
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:31 PM

argv[4] = alloc_sbuf("announce_connchange.cmds");
argv[5] = alloc_sbuf("announce_connchange.in");
argv[6] = alloc_sbuf("announce_connchange.out");
sprintf(argv[2], "%ld", (long) d->connected_at);
sprintf(argv[3], "%ld", (long) d->last_time);
sprintf(argv[4], "%d", d->command_count);
sprintf(argv[5], "%d", d->input_tot);
sprintf(argv[6], "%d", d->output_tot);
} else {
argn = 2;
}
buf = atr_pget(player, attr, &aowner, &aflags, &alen);
if (*buf)
wait_que(player, player, 0, NOTHING, 0, buf, argv, argn, NULL);
free_lbuf(buf);
if (Good_loc(mudconf.master_room) && mudconf.use_global_aconn) {
buf = atr_pget(mudconf.master_room, attr, &aowner,
&aflags, &alen);
if (*buf)
wait_que(mudconf.master_room, player, 0, NOTHING, 0,
buf, argv, argn, NULL);
free_lbuf(buf);
DOLIST(obj, Contents(mudconf.master_room)) {
if (!mudconf.global_aconn_uselocks ||
could_doit(player, obj, A_LUSE)) {
buf = atr_pget(obj, attr, &aowner,
&aflags, &alen);
if (*buf) {
wait_que(obj, player, 0, NOTHING, 0,
buf, argv, argn, NULL);
}
free_lbuf(buf);
}
}
}
/* do the zone of the player's location's possible a(dis)connect */
if (mudconf.have_zones && ((zone = Zone(loc)) != NOTHING)) {
switch (Typeof(zone)) {
case TYPE_THING:
buf = atr_pget(zone, attr, &aowner, &aflags, &alen);
if (*buf) {
wait_que(zone, player, 0, NOTHING, 0, buf,
argv, argn, NULL);
}
free_lbuf(buf);
break;
case TYPE_ROOM:
/* check every object in the room for a (dis)connect
* action
*/
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:31 PM

DOLIST(obj, Contents(zone)) {
buf = atr_pget(obj, attr, &aowner, &aflags, &alen);
if (*buf) {
wait_que(obj, player, 0, NOTHING, 0,
buf, argv, argn, NULL);
}
free_lbuf(buf);
}
break;
default:
STARTLOG(LOG_PROBLEMS, "OBJ", "DAMAG")
log_printf("Invalid zone #%d for ", zone);
log_name(player);
log_printf(" has bad type %d", Typeof(zone));
ENDLOG
}

free_sbuf(argv[1]);
if (attr == A_ADISCONNECT) {
free_sbuf(argv[2]);
free_sbuf(argv[3]);
free_sbuf(argv[4]);
free_sbuf(argv[5]);
free_sbuf(argv[6]);
}

static void announce_connect(player, d, reason)


dbref player;
DESC *d;
const char *reason;
{
dbref loc, aowner, temp;
int aflags, alen, num, key, count;
char *buf, *time_str;
DESC *dtemp;
desc_addhash(d);
count = 0;
DESC_ITER_CONN(dtemp)
count++;
if (mudstate.record_players < count)
mudstate.record_players = count;
buf = atr_pget(player, A_TIMEOUT, &aowner, &aflags, &alen);
d->timeout = atoi(buf);
if (d->timeout <= 0)
d->timeout = mudconf.idle_timeout;
free_lbuf(buf);

-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:31 PM

loc = Location(player);
s_Connected(player);
#ifdef PUEBLO_SUPPORT
if (d->flags & DS_PUEBLOCLIENT) {
s_Html(player);
}
#endif
if (*mudconf.motd_msg) {
if (mudconf.ansi_colors) {
raw_notify(player, tprintf("\n%sMOTD:%s %s\n",
ANSI_HILITE, ANSI_NORMAL,
mudconf.motd_msg));
} else {
raw_notify(player, tprintf("\nMOTD: %s\n",
mudconf.motd_msg));
}
}
if (Wizard(player)) {
if (*mudconf.wizmotd_msg) {
if (mudconf.ansi_colors) {
raw_notify(player,
tprintf("%sWIZMOTD:%s %s\n",
ANSI_HILITE, ANSI_NORMAL,
mudconf.wizmotd_msg));
} else {
raw_notify(player,
tprintf("WIZMOTD: %s\n",
mudconf.wizmotd_msg));
}
}
if (!(mudconf.control_flags & CF_LOGIN)) {
raw_notify(player, "*** Logins are disabled.");
}
}
buf = atr_get(player, A_LPAGE, &aowner, &aflags, &alen);
if (*buf) {
raw_notify(player,
"REMINDER: Your PAGE LOCK is set. You may be unable to receive some pages." );
}
if (Dark(player)) {
raw_notify(player, "REMINDER: You are set DARK." );
}
num = 0;
DESC_ITER_PLAYER(player, dtemp) num++;
/* Reset vacation flag */
s_Flags2(player, Flags2(player) & ~VACATION);
if (num < 2) {
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:31 PM

sprintf(buf, "%s has connected.", Name(player));


if (Hidden(player)) {
raw_broadcast(WATCHER | FLAG_WORD2,
(char *)"GAME: %s has DARK-connected." ,
Name(player));
} else {
raw_broadcast(WATCHER | FLAG_WORD2,
(char *)"GAME: %s has connected.",
Name(player));
}
} else {
sprintf(buf, "%s has reconnected.", Name(player));
raw_broadcast(WATCHER | FLAG_WORD2,
(char *)"GAME: %s has reconnected.",
Name(player));
}
key = MSG_INV;
if ((loc != NOTHING) && !(Hidden(player) && Can_Hide(player)))
key |= (MSG_NBR | MSG_NBR_EXITS | MSG_LOC | MSG_FWDLIST);
temp = mudstate.curr_enactor;
mudstate.curr_enactor = player;
notify_check(player, player, buf, key);
free_lbuf(buf);
CALL_ALL_MODULES(announce_connect, (player, reason, num));
if (Suspect(player)) {
raw_broadcast(WIZARD, (char *)"[Suspect] %s has connected." ,
Name(player));
}
if (d->host_info & H_SUSPECT) {
raw_broadcast(WIZARD,
(char *)"[Suspect site: %s] %s has connected." ,
d->addr, Name(player));
}
announce_connattr(d, player, loc, reason, num, A_ACONNECT);
time_str = ctime(&mudstate.now);
time_str[strlen(time_str) - 1] = '\0';
record_login(player, 1, time_str, d->addr, d->username);
#ifdef PUEBLO_SUPPORT
look_in(player, Location(player), (LK_SHOWEXIT | LK_OBEYTERSE | LK_SHOWVRML));
#else
look_in(player, Location(player), (LK_SHOWEXIT | LK_OBEYTERSE));
#endif
mudstate.curr_enactor = temp;
}

-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:31 PM

void announce_disconnect(player, d, reason)


dbref player;
DESC *d;
const char *reason;
{
dbref loc, temp;
int num, key;
char *buf;
DESC *dtemp;
if (Suspect(player)) {
raw_broadcast(WIZARD,
(char *)"[Suspect] %s has disconnected." ,
Name(player));
}
if (d->host_info & H_SUSPECT) {
raw_broadcast(WIZARD,
(char *)"[Suspect site: %s] %s has disconnected." ,
d->addr, Name(d->player));
}
loc = Location(player);
num = -1;
DESC_ITER_PLAYER(player, dtemp) num++;
temp = mudstate.curr_enactor;
mudstate.curr_enactor = player;
if (num < 1) {
buf = alloc_mbuf("announce_disconnect.only");
sprintf(buf, "%s has disconnected.", Name(player));
key = MSG_INV;
if ((loc != NOTHING) && !(Hidden(player) && Can_Hide(player)))
key |= (MSG_NBR | MSG_NBR_EXITS | MSG_LOC | MSG_FWDLIST);
notify_check(player, player, buf, key);
free_mbuf(buf);
raw_broadcast(WATCHER | FLAG_WORD2,
(char *)"GAME: %s has disconnected.",
Name(player));
/* Must reset flags before we do module stuff. */
c_Connected(player);
#ifdef PUEBLO_SUPPORT
c_Html(player);
#endif
} else {
buf = alloc_mbuf("announce_disconnect.partial" );
sprintf(buf, "%s has partially disconnected." , Name(player));
key = MSG_INV;
if ((loc != NOTHING) && !(Hidden(player) && Can_Hide(player)))
key |= (MSG_NBR | MSG_NBR_EXITS | MSG_LOC | MSG_FWDLIST);
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:31 PM

notify_check(player, player, buf, key);


raw_broadcast(WATCHER | FLAG_WORD2,
(char *)"GAME: %s has partially disconnected." ,
Name(player));
free_mbuf(buf);

CALL_ALL_MODULES(announce_disconnect, (player, reason, num));


announce_connattr(d, player, loc, reason, num, A_ADISCONNECT);
if (num < 1) {
if (d->flags & DS_AUTODARK) {
s_Flags(d->player, Flags(d->player) & ~DARK);
d->flags &= ~DS_AUTODARK;
}

if (Guest(player))
s_Flags(player, Flags(player) | DARK);

mudstate.curr_enactor = temp;
desc_delhash(d);

int boot_off(player, message)


dbref player;
char *message;
{
DESC *d, *dnext;
int count;

count = 0;
DESC_SAFEITER_PLAYER(player, d, dnext) {
if (message && *message) {
queue_rawstring(d, message);
queue_write(d, "\r\n", 2);
}
shutdownsock(d, R_BOOT);
count++;
}
return count;

int boot_by_port(port, no_god, message)


int port, no_god;
char *message;
{
DESC *d, *dnext;
int count;
count = 0;
DESC_SAFEITER_ALL(d, dnext) {
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:31 PM

if ((d->descriptor == port) && (!no_god || !God(d->player))) {


if (message && *message) {
queue_rawstring(d, message);
queue_write(d, "\r\n", 2);
}
shutdownsock(d, R_BOOT);
count++;
}

}
return count;

/* --------------------------------------------------------------------------* desc_reload: Reload parts of net descriptor that are based on db info.
*/
void desc_reload(player)
dbref player;
{
DESC *d;
char *buf;
dbref aowner;
int aflags, alen;

DESC_ITER_PLAYER(player, d) {
buf = atr_pget(player, A_TIMEOUT, &aowner, &aflags, &alen);
d->timeout = atoi(buf);
if (d->timeout <= 0)
d->timeout = mudconf.idle_timeout;
free_lbuf(buf);
}

/* --------------------------------------------------------------------------* fetch_idle, fetch_connect: Return smallest idle time/largest connect time


* for a player (or -1 if not logged in)
*/
int fetch_idle(target, port_num)
dbref target;
int port_num;
{
DESC *d;
int result, idletime;
result = -1;
if (port_num < 0) {
DESC_ITER_PLAYER(target, d) {
idletime = (mudstate.now - d->last_time);
if ((result == -1) || (idletime < result))
result = idletime;
}
} else {
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:31 PM

DESC_ITER_CONN(d) {
if (d->descriptor == port_num) {
idletime = (mudstate.now - d->last_time);
if ((result == -1) || (idletime < result))
result = idletime;
return result;
}
}

}
return result;

int fetch_connect(target, port_num)


dbref target;
int port_num;
{
DESC *d;
int result, conntime;

result = -1;
if (port_num < 0) {
DESC_ITER_PLAYER(target, d) {
conntime = (mudstate.now - d->connected_at);
if (conntime > result)
result = conntime;
}
} else {
DESC_ITER_CONN(d) {
if (d->descriptor == port_num) {
conntime = (mudstate.now - d->connected_at);
if (conntime > result)
result = conntime;
return result;
}
}
}
return result;

void NDECL(check_idle)
{
DESC *d, *dnext;
time_t idletime;
DESC_SAFEITER_ALL(d, dnext) {
if (d->flags & DS_CONNECTED) {
idletime = mudstate.now - d->last_time;
if ((idletime > d->timeout) &&
!Can_Idle(d->player)) {
queue_rawstring(d,
"*** Inactivity Timeout ***\r\n" );
shutdownsock(d, R_TIMEOUT);
} else if (mudconf.idle_wiz_dark &&
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:31 PM

(idletime > mudconf.idle_timeout) &&


Can_Idle(d->player) &&
Can_Hide(d->player) && !Hidden(d->player)) {
raw_notify(d->player,
"*** Inactivity AutoDark ***" );
s_Flags(d->player, Flags(d->player) | DARK);
d->flags |= DS_AUTODARK;

}
} else {
idletime = mudstate.now - d->connected_at;
if (idletime > mudconf.conn_timeout) {
queue_rawstring(d,
"*** Login Timeout ***\r\n");
shutdownsock(d, R_TIMEOUT);
}
}

static char *trimmed_name(player)


dbref player;
{
static char cbuff[18];
if (strlen(Name(player)) <= 16)
return Name(player);
strncpy(cbuff, Name(player), 16);
cbuff[16] = '\0';
return cbuff;

}
static char *trimmed_site(name)
char *name;
{
static char buff[MBUF_SIZE];

if (((int)strlen(name) <= mudconf.site_chars) || (mudconf.site_chars == 0))


return name;
strncpy(buff, name, mudconf.site_chars);
buff[mudconf.site_chars + 1] = '\0';
return buff;

}
static void dump_users(e, match, key)
DESC *e;
char *match;
int key;
{
DESC *d;
int count;
char *buf, *fp, *sp, flist[4], slist[4];
dbref room_it;

while (match && *match && isspace(*match))


match++;
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

Saturday, June 16, 2012 11:31 PM

if (!match || !*match)
match = NULL;
#ifdef PUEBLO_SUPPORT
if ((e->flags & DS_PUEBLOCLIENT) && (Html(e->player)))
queue_string(e, "<pre>");
#endif
buf = alloc_mbuf("dump_users");
if (key == CMD_SESSION) {
queue_rawstring(e, "
" );
queue_rawstring(e,
"
Characters Input---- Characters Output---\r\n" );
}
queue_rawstring(e, "Player Name
On For Idle " );
if (key == CMD_SESSION) {
queue_rawstring(e,
"Port Pend Lost
Total Pend Lost
Total\r\n" );
} else if ((e->flags & DS_CONNECTED) && (Wizard_Who(e->player)) &&
(key == CMD_WHO)) {
queue_rawstring(e, " Room
Cmds
Host\r\n");
} else {
if (Wizard_Who(e->player) || See_Hidden(e->player))
queue_string(e, " ");
else
queue_string(e, " ");
queue_string(e, mudstate.doing_hdr);
queue_string(e, "\r\n");
}
count = 0;
DESC_ITER_CONN(d) {
if (!Hidden(d->player) ||
((e->flags & DS_CONNECTED) && See_Hidden(e->player))) {
count++;
if (match && !(string_prefix(Name(d->player), match)))
continue;
if ((key == CMD_SESSION) &&
!(Wizard_Who(e->player) && (e->flags & DS_CONNECTED)) &&
(d->player != e->player))
continue;
/* Get choice flags for wizards */
fp
sp
if
if

= flist;
= slist;
((e->flags & DS_CONNECTED) && Wizard_Who(e->player)) {
(Hidden(d->player)) {
if (d->flags & DS_AUTODARK)
*fp++ = 'd';
else
*fp++ = 'D';

}
if (!Findable(d->player)) {

-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

Saturday, June 16, 2012 11:31 PM

*fp++ = 'U';
} else {
room_it = where_room(d->player);
if (Good_obj(room_it)) {
if (Hideout(room_it))
*fp++ = 'u';
} else {
*fp++ = 'u';
}
}
if (Suspect(d->player))
*fp++ = '+';
if (d->host_info & H_FORBIDDEN)
*sp++ = 'F';
if (d->host_info & H_REGISTRATION)
*sp++ = 'R';
if (d->host_info & H_SUSPECT)
*sp++ = '+';
if (d->host_info & H_GUEST)
*sp++ = 'G';
} else if ((e->flags & DS_CONNECTED) &&
See_Hidden(e->player)) {
if (Hidden(d->player)) {
if (d->flags & DS_AUTODARK)
*fp++ = 'd';
else
*fp++ = 'D';
}
}
*fp = '\0';
*sp = '\0';
if ((e->flags & DS_CONNECTED) && Wizard_Who(e->player) &&
(key == CMD_WHO)) {
sprintf(buf,
"%-16s%9s %4s%-3s#%-6d%5d%3s%-25s\r\n" ,
trimmed_name(d->player),
time_format_1(mudstate.now - d->connected_at),
time_format_2(mudstate.now - d->last_time), flist,
Location(d->player), d->command_count, slist,
trimmed_site(((d->username[0] != '\0') ?
tprintf("%s@%s", d->username, d->addr) :
d->addr)));
} else if (key == CMD_SESSION) {
sprintf(buf,
"%-16s%9s %4s%5d%5d%6d%10d%6d%6d%10d\r\n" ,
trimmed_name(d->player),
time_format_1(mudstate.now - d->connected_at),
time_format_2(mudstate.now - d->last_time),
d->descriptor,
d->input_size, d->input_lost, d->input_tot,
d->output_size, d->output_lost, d->output_tot);
} else if (Wizard_Who(e->player) || See_Hidden(e->player)) {
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

}
}

Saturday, June 16, 2012 11:31 PM

sprintf(buf, "%-16s%9s %4s%-3s%s\r\n",


trimmed_name(d->player),
time_format_1(mudstate.now - d->connected_at),
time_format_2(mudstate.now - d->last_time),
flist, d->doing);
} else {
sprintf(buf, "%-16s%9s %4s %s\r\n",
trimmed_name(d->player),
time_format_1(mudstate.now - d->connected_at),
time_format_2(mudstate.now - d->last_time),
d->doing);
}
queue_string(e, buf);

/* sometimes I like the ternary operator.... */


sprintf(buf, "%d Player%slogged in, %d record, %s maximum.\r\n" , count,
(count == 1) ? " " : "s ", mudstate.record_players,
(mudconf.max_players == -1) ?
"no" : tprintf("%d", mudconf.max_players));
queue_rawstring(e, buf);
#ifdef PUEBLO_SUPPORT
if ((e->flags & DS_PUEBLOCLIENT) && (Html(e->player)))
queue_string(e, "</pre>");
#endif
}

free_mbuf(buf);

static void dump_info(call_by)


DESC *call_by;
{
DESC *d;
char *temp;
int count = 0;
queue_rawstring(call_by, "### Begin INFO 1\r\n");
queue_rawstring(call_by, tprintf("Name: %s\r\n", mudconf.mud_name));
temp = (char *) ctime(&mudstate.start_time);
temp[strlen(temp) - 1] = '\0';
queue_rawstring(call_by, tprintf("Uptime: %s\r\n", temp));
DESC_ITER_CONN(d) {
if (!Hidden(d->player) ||
((call_by->flags & DS_CONNECTED) && See_Hidden(call_by->player)))
count++;
}
queue_rawstring(call_by, tprintf("Connected: %d\r\n", count));
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325

Saturday, June 16, 2012 11:31 PM

queue_rawstring(call_by, tprintf("Size: %d\r\n", mudstate.db_top));


queue_rawstring(call_by, tprintf("Version: %s\r\n", mudstate.short_ver));
queue_rawstring(call_by, "### End INFO\r\n");

/* --------------------------------------------------------------------------* do_colormap: Remap ANSI colors in output.


*/
void do_colormap(player, cause, key, fstr, tstr)
dbref player, cause;
int key;
char *fstr, *tstr;
{
DESC *d;
int from_color, to_color, i, x;
from_color = ansi_nchartab[(unsigned char) *fstr];
to_color = ansi_nchartab[(unsigned char) *tstr];
if ((from_color
notify(player,
return;
}
if ((to_color <
notify(player,
return;
}

< I_ANSI_BLACK) || (from_color >= I_ANSI_NUM)) {


"That's not a valid color to change." );
I_ANSI_BLACK) || (to_color >= I_ANSI_NUM)) {
"That's not a valid color to remap to." );

DESC_ITER_PLAYER(player, d) {
if (d->colormap) {
if (from_color == to_color) {
d->colormap[from_color - I_ANSI_BLACK] = 0;
/* If no changes, clear colormap */
x = 0;
for (i = 0; i < I_ANSI_NUM - I_ANSI_BLACK; i++)
if (d->colormap[i] != 0)
x++;
if (!x) {
XFREE(d->colormap, "colormap");
notify(player, "Colors restored to standard." );
} else {
notify(player, "Color restored to standard." );
}
} else {
d->colormap[from_color - I_ANSI_BLACK] = to_color;
notify(player, "Color remapped.");
}
} else {
if (from_color == to_color) {
notify(player, "No color change.");
} else {
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

Saturday, June 16, 2012 11:31 PM

d->colormap = (int *) XCALLOC(I_ANSI_NUM - I_ANSI_BLACK,


sizeof(int), "colormap");
d->colormap[from_color - I_ANSI_BLACK] = to_color;
notify(player, "Color remapped.");

/* --------------------------------------------------------------------------* do_doing: Set the doing string that appears in the WHO report.
* Idea from R'nice@TinyTIM.
*/
static int sane_doing(arg, buff)
char *arg, *buff;
{
char *p, *bp;
int over = 0;
for (p = arg; *p; p++)
if ((*p == '\t') || (*p == '\r') || (*p == '\n'))
*p = ' ';
bp = buff;
if (!mudconf.ansi_colors || !strchr(arg, ESC_CHAR)) {
over = safe_copy_str_fn(arg, buff, &bp, DOING_LEN - 1);
} else {
over = safe_copy_str_fn(arg, buff, &bp, DOING_LEN - 5);
strcpy(bp, ANSI_NORMAL);
}
}

return over;

void do_doing(player, cause, key, arg)


dbref player, cause;
int key;
char *arg;
{
DESC *d;
int foundany, over;
over = 0;
if (key & DOING_HEADER) {
if (!(Can_Poll(player))) {
notify(player, NOPERM_MESSAGE);
return;
}
if (!arg || !*arg) {
StringCopy(mudstate.doing_hdr, "Doing");
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431

Saturday, June 16, 2012 11:31 PM

over = 0;
} else {
over = sane_doing(arg, mudstate.doing_hdr);
}
if (over) {
notify(player,
tprintf("Warning: %d characters lost." , over));
}
if (!Quiet(player) && !(key & DOING_QUIET))
notify(player, "Set.");
} else if (key & DOING_POLL) {
notify(player, tprintf("Poll: %s", mudstate.doing_hdr));
} else {
foundany = 0;
DESC_ITER_PLAYER(player, d) {
over = sane_doing(arg, d->doing);
foundany = 1;
}
if (foundany) {
if (over) {
notify(player,
tprintf("Warning: %d characters lost." ,
over));
}
if (!Quiet(player) && !(key & DOING_QUIET) )
notify(player, "Set.");
} else {
notify(player, "Not connected.");
}
}

}
/* *INDENT-OFF* */

NAMETAB logout_cmdtable[] = {
{(char *)"DOING",
5, CA_PUBLIC, CMD_DOING},
{(char *)"LOGOUT", 6, CA_PUBLIC, CMD_LOGOUT},
{(char *)"OUTPUTPREFIX",12, CA_PUBLIC, CMD_PREFIX|CMD_NOxFIX},
{(char *)"OUTPUTSUFFIX",12, CA_PUBLIC, CMD_SUFFIX|CMD_NOxFIX},
{(char *)"QUIT",
4, CA_PUBLIC, CMD_QUIT},
{(char *)"SESSION", 7, CA_PUBLIC, CMD_SESSION},
{(char *)"WHO",
3, CA_PUBLIC, CMD_WHO},
{(char *)"PUEBLOCLIENT", 12,
CA_PUBLIC,
CMD_PUEBLOCLIENT},
{(char *)"INFO",
4, CA_PUBLIC, CMD_INFO},
{NULL,
0, 0,
0}};
/* *INDENT-ON* */
void NDECL(init_logout_cmdtab)
{
NAMETAB *cp;
/* Make the htab bigger than the number of entries so that we find
* things on the first check. Remember that the admin can add
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

Saturday, June 16, 2012 11:31 PM

* aliases.
*/

hashinit(&mudstate.logout_cmd_htab, 3 * HASH_FACTOR, HT_STR);


for (cp = logout_cmdtable; cp->flag; cp++)
hashadd(cp->name, (int *)cp, &mudstate.logout_cmd_htab, 0);

static void failconn(logcode, logtype, logreason, d, disconnect_reason,


player, filecache, motd_msg, command, user, password, cmdsave)
const char *logcode, *logtype, *logreason;
char *motd_msg, *command, *user, *password, *cmdsave;
DESC *d;
int disconnect_reason, filecache;
dbref player;
{
STARTLOG(LOG_LOGIN | LOG_SECURITY, logcode, "RJCT")
log_printf("[%d/%s] %s rejected to ",
d->descriptor, d->addr, logtype);
if (player != NOTHING)
log_name(player);
else
log_printf("%s", user);
log_printf(" (%s)", logreason);
ENDLOG
fcache_dump(d, filecache);
if (*motd_msg) {
queue_string(d, motd_msg);
queue_write(d, "\r\n", 2);
}
free_lbuf(command);
free_lbuf(user);
free_lbuf(password);
shutdownsock(d, disconnect_reason);
mudstate.debug_cmd = cmdsave;
return;
}
static const char *connect_fail =
"Either that player does not exist, or has a different password.\r\n" ;
static const char *create_fail =
"Either there is already a player with that name, or that name is illegal.\r\n" ;
static int check_connect(d, msg)
DESC *d;
char *msg;
{
char *command, *user, *password, *buff, *cmdsave;
dbref player, aowner;
int aflags, alen, nplayers, reason;
DESC *d2;
char *p;

-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537

Saturday, June 16, 2012 11:31 PM

cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< check_connect >";
/* Hide the password length from SESSION */
d->input_tot -= (strlen(msg) + 1);
/* Crack the command apart */
command = alloc_lbuf("check_conn.cmd");
user = alloc_lbuf("check_conn.user");
password = alloc_lbuf("check_conn.pass");
parse_connect(msg, command, user, password);
if (!strncmp(command, "co", 2) || !strncmp(command, "cd", 2)) {
if ((string_prefix(user, mudconf.guest_basename)) &&
Good_obj(mudconf.guest_char) &&
(mudconf.control_flags & CF_LOGIN)) {
if ((p = make_guest(d)) == NULL) {
queue_string(d, "All guests are tied up, please try again later.\n" );
free_lbuf(command);
free_lbuf(user);
free_lbuf(password);
return 0;
}
StringCopy(user, p);
StringCopy(password, mudconf.guest_password);
}
/* See if this connection would exceed the max #players */
if (mudconf.max_players < 0) {
nplayers = mudconf.max_players - 1;
} else {
nplayers = 0;
DESC_ITER_CONN(d2)
nplayers++;
}
player = connect_player(user, password, d->addr, d->username,
inet_ntoa((d->address).sin_addr));
if (player == NOTHING) {
/* Not a player, or wrong password */
queue_rawstring(d, connect_fail);
STARTLOG(LOG_LOGIN | LOG_SECURITY, "CON", "BAD")
log_printf("[%d/%s] Failed connect to '%s'" ,
d->descriptor, d->addr, user);
ENDLOG
user[3800] = '\0';
if (--(d->retries_left) <= 0) {
free_lbuf(command);
free_lbuf(user);
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590

Saturday, June 16, 2012 11:31 PM

free_lbuf(password);
shutdownsock(d, R_BADLOGIN);
mudstate.debug_cmd = cmdsave;
return 0;

}
} else if (((mudconf.control_flags & CF_LOGIN) &&
(nplayers < mudconf.max_players)) ||
WizRoy(player) || God(player)) {
if (Guest(player)) {
reason = R_GUEST;
} else if (!strncmp(command, "cd", 2) &&
(Wizard(player) || God(player))) {
s_Flags(player, Flags(player) | DARK);
reason = R_DARK;
} else {
reason = R_CONNECT;
}
/* First make sure we don't have a guest from a bad host. */
if (Guest(player) && (d->host_info & H_GUEST)) {
failconn("CON", "Connect", "Guest Site Forbidden", d,
R_GAMEDOWN, player, FC_CONN_SITE,
mudconf.downmotd_msg, command, user, password,
cmdsave);
return 0;
}
/* Logins are enabled, or wiz or god */
STARTLOG(LOG_LOGIN, "CON", "LOGIN")
log_printf("[%d/%s] %s ",
d->descriptor, d->addr,
conn_reasons[reason]);
log_name_and_loc(player);
ENDLOG
d->flags |= DS_CONNECTED;
d->connected_at = time(NULL);
d->player = player;
/* Check to see if the player is currently running
* an @program. If so, drop the new descriptor into
* it.
*/
DESC_ITER_PLAYER(player, d2) {
if (d2->program_data != NULL) {
d->program_data = d2->program_data;
break;
}
}

-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

Saturday, June 16, 2012 11:31 PM

/* Give the player the MOTD file and the settable


* MOTD message(s). Use raw notifies so the
* player doesn't try to match on the text.
*/
if (Guest(player)) {
fcache_dump(d, FC_CONN_GUEST);
} else {
buff = atr_get(player, A_LAST, &aowner, &aflags, &alen);
if (!*buff)
fcache_dump(d, FC_CREA_NEW);
else
fcache_dump(d, FC_MOTD);
if (Wizard(player))
fcache_dump(d, FC_WIZMOTD);
free_lbuf(buff);
}
announce_connect(player, d, conn_messages[reason]);
/* If stuck in an @prog, show the prompt */
if (d->program_data != NULL)
queue_rawstring(d, "> \377\371");
} else if (!(mudconf.control_flags & CF_LOGIN)) {
failconn("CON", "Connect", "Logins Disabled", d,
R_GAMEDOWN, player, FC_CONN_DOWN,
mudconf.downmotd_msg, command, user, password,
cmdsave);
return 0;
} else {
failconn("CON", "Connect", "Game Full", d,
R_GAMEFULL, player, FC_CONN_FULL,
mudconf.fullmotd_msg, command, user, password,
cmdsave);
return 0;
}
} else if (!strncmp(command, "cr", 2)) {
reason = R_CREATE;
/* Enforce game down */
if (!(mudconf.control_flags & CF_LOGIN)) {
failconn("CRE", "Create", "Logins Disabled", d,
R_GAMEDOWN, NOTHING, FC_CONN_DOWN,
mudconf.downmotd_msg, command, user, password,
cmdsave);
return 0;
}
/* Enforce max #players */
if (mudconf.max_players < 0) {
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696

Saturday, June 16, 2012 11:31 PM

nplayers = mudconf.max_players;
} else {
nplayers = 0;
DESC_ITER_CONN(d2)
nplayers++;
}
if (nplayers > mudconf.max_players) {
/* Too many players on, reject the attempt */
failconn("CRE", "Create", "Game Full", d,
R_GAMEFULL, NOTHING, FC_CONN_FULL,
mudconf.fullmotd_msg, command, user, password,
cmdsave);
return 0;

}
if (d->host_info & H_REGISTRATION) {
fcache_dump(d, FC_CREA_REG);
} else {
player = create_player(user, password, NOTHING, 0, 0);
if (player == NOTHING) {
queue_rawstring(d, create_fail);
STARTLOG(LOG_SECURITY | LOG_PCREATES, "CON", "BAD")
log_printf("[%d/%s] Create of '%s' failed" ,
d->descriptor, d->addr, user);
ENDLOG
} else {
STARTLOG(LOG_LOGIN | LOG_PCREATES, "CON", "CREA")
log_printf("[%d/%s] %s ",
d->descriptor, d->addr,
conn_reasons[reason]);
log_name(player);
ENDLOG
move_object(player, (Good_loc(mudconf.start_room) ?
mudconf.start_room : 0));
d->flags |= DS_CONNECTED;
d->connected_at = time(NULL);
d->player = player;
fcache_dump(d, FC_CREA_NEW);
announce_connect(player, d, conn_messages[R_CREATE]);
}
}
} else {
welcome_user(d);
STARTLOG(LOG_LOGIN | LOG_SECURITY, "CON", "BAD")
log_printf("[%d/%s] Failed connect: '%s'" ,
d->descriptor, d->addr, msg);
ENDLOG
msg[150] = '\0';
}
free_lbuf(command);
free_lbuf(user);
free_lbuf(password);
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

Saturday, June 16, 2012 11:31 PM

mudstate.debug_cmd = cmdsave;
return 1;

static void logged_out_internal(d, key, arg)


DESC *d;
int key;
char *arg;
{
switch (key) {
case CMD_QUIT:
shutdownsock(d, R_QUIT);
break;
case CMD_LOGOUT:
shutdownsock(d, R_LOGOUT);
break;
case CMD_WHO:
case CMD_DOING:
case CMD_SESSION:
dump_users(d, arg, key);
break;
case CMD_PREFIX:
set_userstring(&d->output_prefix, arg);
break;
case CMD_SUFFIX:
set_userstring(&d->output_suffix, arg);
break;
case CMD_INFO:
dump_info(d);
break;
case CMD_PUEBLOCLIENT:
#ifdef PUEBLO_SUPPORT
/* Set the descriptor's flag */
d->flags |= DS_PUEBLOCLIENT;
/* If we're already connected, set the player's flag */
if (d->flags & DS_CONNECTED) {
s_Html(d->player);
}
queue_rawstring(d, mudconf.pueblo_msg);
queue_write(d, "\r\n", 2);
fcache_dump(d, FC_CONN_HTML);
STARTLOG(LOG_LOGIN, "CON", "HTML")
log_printf("[%d/%s] PuebloClient enabled." ,
d->descriptor, d->addr);
ENDLOG
#else
queue_rawstring(d, "Sorry. This MUSH does not have Pueblo support enabled.\r\n" );
#endif
break;
default:
STARTLOG(LOG_BUGS, "BUG", "PARSE")
log_printf("Logged-out command with no handler: '%s'" ,
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

ENDLOG

Saturday, June 16, 2012 11:31 PM

mudstate.debug_cmd);

void do_command(d, command, first)


DESC *d;
char *command;
int first;
{
char *arg, *cmdsave, *log_cmdbuf;
NAMETAB *cp;
long begin_time, used_time;
cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< do_command >";
if (d->flags & DS_CONNECTED) {
/* Normal logged-in command processing */
d->command_count++;
if (d->output_prefix) {
queue_string(d, d->output_prefix);
queue_write(d, "\r\n", 2);
}
mudstate.curr_player = d->player;
mudstate.curr_enactor = d->player;
Free_RegData(mudstate.rdata);
mudstate.rdata = NULL;
#ifndef NO_LAG_CHECK
begin_time = time(NULL);
#endif /* NO_LAG_CHECK */
mudstate.cmd_invk_ctr = 0;
log_cmdbuf = process_command(d->player, d->player, 1,
command, (char **)NULL, 0);
#ifndef NO_LAG_CHECK
used_time = time(NULL) - begin_time;
if (used_time >= mudconf.max_cmdsecs) {
STARTLOG(LOG_PROBLEMS, "CMD", "CPU")
log_name_and_loc(d->player);
log_printf(" entered command taking %ld secs: %s" ,
used_time, log_cmdbuf);
ENDLOG
}
#endif /* NO_LAG_CHECK */
mudstate.curr_cmd = (char *) "";
if (d->output_suffix) {
queue_string(d, d->output_suffix);
queue_write(d, "\r\n", 2);
}
mudstate.debug_cmd = cmdsave;
return;
}

-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

Saturday, June 16, 2012 11:31 PM

/* Login screen (logged-out) command processing. */


/* Split off the command from the arguments */
arg = command;
while (*arg && !isspace(*arg))
arg++;
if (*arg)
*arg++ = '\0';
/* Look up the command in the logged-out command table. */
cp = (NAMETAB *) hashfind(command, &mudstate.logout_cmd_htab);
if (cp == NULL) {
/* Not in the logged-out command table, so maybe a
* connect attempt.
*/
if (*arg)
*--arg = ' ';
/* restore nullified space */
mudstate.debug_cmd = cmdsave;
check_connect(d, command);
return;
}
/* The command was in the logged-out command table. Perform prefix
* and suffix processing, and invoke the command handler.
*/

d->command_count++;
if (!(cp->flag & CMD_NOxFIX)) {
if (d->output_prefix) {
queue_string(d, d->output_prefix);
queue_write(d, "\r\n", 2);
}
}
if (cp->perm != CA_PUBLIC) {
queue_rawstring(d, "Permission denied.\r\n");
} else {
mudstate.debug_cmd = cp->name;
logged_out_internal(d, cp->flag & CMD_MASK, arg);
}
/* QUIT or LOGOUT will close the connection and cause the
* descriptor to be freed!
*/
if (((cp->flag & CMD_MASK) != CMD_QUIT) &&
((cp->flag & CMD_MASK) != CMD_LOGOUT) &&
!(cp->flag & CMD_NOxFIX)) {
if (d->output_suffix) {
queue_string(d, d->output_suffix);
queue_write(d, "\r\n", 2);
}
}
mudstate.debug_cmd = cmdsave;

-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

Saturday, June 16, 2012 11:31 PM

void logged_out(player, cause, key, arg)


dbref player, cause;
int key;
char *arg;
{
DESC *d, *dlast;

if (key == CMD_PUEBLOCLIENT) {
/* PUEBLOCLIENT affects all the player's connections. */
DESC_ITER_PLAYER(player, d) {
logged_out_internal(d, key, arg);
}
} else {
/* Other logged-out commands affect only the player's
* most recently used connection.
*/
dlast = NULL;
DESC_ITER_PLAYER(player, d) {
if (dlast == NULL || d->last_time > dlast->last_time)
dlast = d;
}
if (dlast)
logged_out_internal(dlast, key, arg);
}

void NDECL(process_commands)
{
int nprocessed;
DESC *d, *dnext;
CBLK *t;
char *cmdsave;
cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"process_commands";
do {

nprocessed = 0;
DESC_SAFEITER_ALL(d, dnext) {
if (d->quota > 0 && (t = d->input_head)) {
d->quota--;
nprocessed++;
d->input_head = (CBLK *) t->hdr.nxt;
if (!d->input_head)
d->input_tail = NULL;
d->input_size -= (strlen(t->cmd) + 1);
STARTLOG(LOG_KBCOMMANDS, "CMD", "KBRD")
log_printf("[%d/%s] Cmd: %s",
d->descriptor, d->addr, t->cmd);
ENDLOG
/* ignore the IDLE psuedo-command */
if (strcmp(t->cmd, (char *) "IDLE")) {
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961

Saturday, June 16, 2012 11:31 PM

d->last_time = mudstate.now;
if (d->program_data != NULL)
handle_prog(d, t->cmd);
else
do_command(d, t->cmd, 1);

}
free_lbuf(t);

}
}
} while (nprocessed > 0);
mudstate.debug_cmd = cmdsave;

/* --------------------------------------------------------------------------* site_check: Check for site flags in a site list.


*/
int site_check(host, site_list)
struct in_addr host;
SITE *site_list;
{
SITE *this;
int flag = 0;

for (this = site_list; this; this = this->next) {


if ((host.s_addr & this->mask.s_addr) == this->address.s_addr)
flag |= this->flag;
}
return flag;

/* -------------------------------------------------------------------------* list_sites: Display information in a site list


*/
#define S_SUSPECT
#define S_ACCESS

1
2

static const char *stat_string(strtype, flag)


int strtype, flag;
{
const char *str;
switch (strtype) {
case S_SUSPECT:
if (flag)
str = "Suspected";
else
str = "Trusted";
break;
case S_ACCESS:
switch (flag) {
case H_FORBIDDEN:
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014

Saturday, June 16, 2012 11:31 PM

str = "Forbidden";
break;
case H_REGISTRATION:
str = "Registration";
break;
case H_GUEST:
str = "NoGuest";
break;
case 0:
str = "Unrestricted";
break;
default:
str = "Strange";
}
break;
default:
str = "Strange";
}
return str;

static unsigned int mask_to_prefix(mask_num)


unsigned int mask_num;
{
unsigned int i, result, tmp;
/* The number of bits in the mask is equal to the number of left
* shifts before it becomes zero. Binary search for that number.
*/
for (i = 16, result = 0; i && mask_num; i >>= 1)
if ((tmp = (mask_num << i))) {
result |= i;
mask_num = tmp;
}
if (mask_num)
result++;
}

return result;

static void list_sites(player, site_list, header_txt, stat_type)


dbref player;
SITE *site_list;
const char *header_txt;
int stat_type;
{
char *buff, *str, *maskaddr;
SITE *this;
unsigned int bits;
buff = alloc_mbuf("list_sites.buff");
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067

Saturday, June 16, 2012 11:31 PM

sprintf(buff, "----- %s -----", header_txt);


notify(player, buff);
notify(player, "IP Prefix
Mask

Status" );

for (this = site_list; this; this = this->next) {


str = (char *) stat_string(stat_type, this->flag);
bits = mask_to_prefix(ntohl(this->mask.s_addr));
/* special-case 0, can't shift by 32 */
if ((bits == 0 && htonl(0) == this->mask.s_addr) ||
htonl(0xFFFFFFFFU << (32 - bits)) == this->mask.s_addr) {
sprintf(buff, "%-17s /%-16d %s", inet_ntoa(this->address),
bits, str);
} else {
/* Deal with bizarre stuff not along CIDRized boundaries.
* inet_ntoa() points to a static buffer, so we've got to
* allocate something temporary.
*/
maskaddr = alloc_mbuf("list_sites.mask");
strcpy(maskaddr, inet_ntoa(this->mask));
sprintf(buff, "%-17s %-17s %s", inet_ntoa(this->address),
maskaddr, str);
free_mbuf(maskaddr);
}
}
}

notify(player, buff);

free_mbuf(buff);

/* --------------------------------------------------------------------------* list_siteinfo: List information about specially-marked sites.


*/
void list_siteinfo(player)
dbref player;
{
list_sites(player, mudstate.access_list, "Site Access",
S_ACCESS);
list_sites(player, mudstate.suspect_list, "Suspected Sites",
S_SUSPECT);
}
/* --------------------------------------------------------------------------* make_ulist: Make a list of connected user numbers for the LWHO function.
*/
void make_ulist(player, buff, bufc)
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120

Saturday, June 16, 2012 11:31 PM

dbref player;
char *buff, **bufc;
{
char *cp;
DESC *d;

cp = *bufc;
DESC_ITER_CONN(d) {
if (!See_Hidden(player) && Hidden(d->player))
continue;
if (cp != *bufc)
safe_chr(' ', buff, bufc);
safe_chr('#', buff, bufc);
safe_ltos(buff, bufc, d->player);
}

/* --------------------------------------------------------------------------* make_portlist: Make a list of ports for PORTS().


*/
void make_portlist(player, target, buff, bufc)
dbref player;
dbref target;
char *buff, **bufc;
{
DESC *d;
int i = 0;

DESC_ITER_CONN(d) {
if ((target == NOTHING) || (d->player == target)) {
safe_str(tprintf("%d ", d->descriptor), buff, bufc);
i = 1;
}
}
if (i)
(*bufc)--;
**bufc = '\0';

/* --------------------------------------------------------------------------* make_sessioninfo: Return information about a port, for SESSION().


* List of numbers: command_count input_tot output_tot
*/
void make_sessioninfo(player, target, port_num, buff, bufc)
dbref player, target;
int port_num;
char *buff, **bufc;
{
DESC *d;
DESC_ITER_CONN(d) {
-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173

Saturday, June 16, 2012 11:31 PM

if ((d->descriptor == port_num) || (d->player == target)) {


if (Wizard_Who(player) || Controls(player, d->player)) {
safe_str(tprintf("%d %d %d", d->command_count,
d->input_tot, d->output_tot), buff, bufc);
return;
} else {
notify_quiet(player, NOPERM_MESSAGE);
safe_str((char *) "-1 -1 -1", buff, bufc);
return;
}
}
}
/* Not found, return error. */
}

safe_str((char *) "-1 -1 -1", buff, bufc);

/* --------------------------------------------------------------------------* get_doing: Return the DOING string of a player.


*/
char *get_doing(target, port_num)
dbref target;
int port_num;
{
DESC *d;

if (port_num < 0) {
DESC_ITER_PLAYER(target, d) {
return d->doing;
}
} else {
DESC_ITER_CONN(d) {
if (d->descriptor == port_num)
return d->doing;
}
}
return NULL;

/* --------------------------------------------------------------------------* get_programmer: Get the dbref of the controlling programmer, if any.


*/
dbref get_programmer(target)
dbref target;
{
DESC *d;
DESC_ITER_CONN(d) {
if ((d->player == target) && (d->program_data != NULL))
return (d->program_data->wait_cause);
-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226

Saturday, June 16, 2012 11:31 PM

}
return NOTHING;

/* --------------------------------------------------------------------------* find_connected_name: Resolve a playername from the list of connected


* players using prefix matching. We only return a match if the prefix
* was unique.
*/
dbref find_connected_name(player, name)
dbref player;
char *name;
{
DESC *d;
dbref found;

found = NOTHING;
DESC_ITER_CONN(d) {
if (Good_obj(player) &&
!See_Hidden(player) && Hidden(d->player))
continue;
if (!string_prefix(Name(d->player), name))
continue;
if ((found != NOTHING) && (found != d->player))
return NOTHING;
found = d->player;
}
return found;

/* --------------------------------------------------------------------------* find_connected_ambiguous: Resolve a playername from the list of connected


* players using prefix matching. If the prefix is non-unique, we return
* the AMBIGUOUS token; if it does not exist, we return the NOTHING token.
* was unique.
*/
dbref find_connected_ambiguous(player, name)
dbref player;
char *name;
{
DESC *d;
dbref found;
found = NOTHING;
DESC_ITER_CONN(d) {
if (Good_obj(player) && !See_Hidden(player) && Hidden(d->player))
continue;
if (!string_prefix(Name(d->player), name))
continue;
if ((found != NOTHING) && (found != d->player))
-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\netcommon.c

2227
2228
2229
2230
2231
2232

Saturday, June 16, 2012 11:31 PM

return AMBIGUOUS;
found = d->player;
}
return found;

-43-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:31 PM

/* object.c - low-level object manipulation routines */


/* $Id: object.c,v 1.67 2008/10/25 22:35:10 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "powers.h" /* required by code */
#include "attrs.h" /* required by code */
#include "match.h" /* required by code */
#define IS_CLEAN(i) (IS(i, TYPE_GARBAGE, GOING) && \
(Location(i) == NOTHING) && \
(Contents(i) == NOTHING) && (Exits(i) == NOTHING) && \
(Next(i) == NOTHING) && (Owner(i) == GOD))
#define ZAP_LOC(i)

{ s_Location(i, NOTHING); s_Next(i, NOTHING); }

static int check_type;


extern int FDECL(boot_off, (dbref, char *));
extern
extern
extern
extern
extern
extern

void NDECL(cf_verify);
void FDECL(fwdlist_clr, (dbref));
void FDECL(propdir_clr, (dbref));
void FDECL(stack_clr, (dbref));
void FDECL(xvars_clr, (dbref));
int FDECL(structure_clr, (dbref));

/* --------------------------------------------------------------------------* Log_pointer_err, Log_header_err, Log_simple_damage: Write errors to the


* log file.
*/
static void Log_pointer_err(prior, obj, loc, ref, reftype, errtype)
dbref prior, obj, loc, ref;
const char *reftype, *errtype;
{
STARTLOG(LOG_PROBLEMS, "OBJ", "DAMAG")
log_type_and_name(obj);
if (loc != NOTHING) {
log_printf(" in ");
log_type_and_name(loc);
}
log_printf(": %s ", ((prior == NOTHING) ? reftype : "Next pointer"));
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:31 PM

log_type_and_name(ref);
log_printf(" %s", errtype);
ENDLOG

static void Log_header_err(obj, loc, val, is_object, valtype, errtype)


dbref obj, loc, val;
int is_object;
const char *valtype, *errtype;
{
STARTLOG(LOG_PROBLEMS, "OBJ", "DAMAG")
log_type_and_name(obj);
if (loc != NOTHING) {
log_printf(" in ");
log_type_and_name(loc);
}
log_printf(": %s ", valtype);
if (is_object)
log_type_and_name(val);
else
log_printf("%d", val);
log_printf(" %s", errtype);
ENDLOG
}
static void Log_simple_err(obj, loc, errtype)
dbref obj, loc;
const char *errtype;
{
STARTLOG(LOG_PROBLEMS, "OBJ", "DAMAG")
log_type_and_name(obj);
if (loc != NOTHING) {
log_printf(" in ");
log_type_and_name(loc);
}
log_printf(": %s", errtype);
ENDLOG
}
/* --------------------------------------------------------------------------* can_set_home, new_home, clone_home:
* Routines for validating and determining homes.
*/
int can_set_home(player, thing, home)
dbref player, thing, home;
{
if (!Good_obj(player) || !Good_obj(home) || (thing == home))
return 0;
switch (Typeof(home)) {
case TYPE_PLAYER:
case TYPE_ROOM:
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:31 PM

case TYPE_THING:
if (Going(home))
return 0;
if (Controls(player, home) || Abode(home) ||
LinkAnyHome(player))
return 1;
}
return 0;

dbref new_home(player)
dbref player;
{
dbref loc;

loc = Location(player);
if (can_set_home(Owner(player), player, loc))
return loc;
loc = Home(Owner(player));
if (can_set_home(Owner(player), player, loc))
return loc;
return (Good_home(mudconf.default_home) ? mudconf.default_home :
(Good_home(mudconf.start_home) ? mudconf.start_home :
(Good_home(mudconf.start_room) ? mudconf.start_room :
0)));

dbref clone_home(player, thing)


dbref player, thing;
{
dbref loc;

loc = Home(thing);
if (can_set_home(Owner(player), player, loc))
return loc;
return new_home(player);

/* --------------------------------------------------------------------------* update_newobjs: Update a player's most-recently-created objects.


*/
static void update_newobjs(player, obj_num, obj_type)
dbref player;
dbref obj_num;
int obj_type;
{
int i, aowner, aflags, alen;
char *newobj_str, *p, tbuf[SBUF_SIZE], *tokst;
int obj_list[4];
newobj_str = atr_get(player, A_NEWOBJS, &aowner, &aflags, &alen);

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:31 PM

if (!*newobj_str) {
for (i = 0; i < 4; i++)
obj_list[i] = -1;
} else {
for (p = strtok_r(newobj_str, " ", &tokst), i = 0;
p && (i < 4);
p = strtok_r(NULL, " ", &tokst), i++) {
obj_list[i] = atoi(p);
}
}
free_lbuf(newobj_str);
switch (obj_type) {
case TYPE_ROOM:
obj_list[0] = obj_num;
break;
case TYPE_EXIT:
obj_list[1] = obj_num;
break;
case TYPE_THING:
obj_list[2] = obj_num;
break;
case TYPE_PLAYER:
obj_list[3] = obj_num;
break;
}

sprintf(tbuf, "%d %d %d %d", obj_list[0], obj_list[1], obj_list[2],


obj_list[3]);
atr_add_raw(player, A_NEWOBJS, tbuf);

/* --------------------------------------------------------------------------* ok_exit_name: Make sure an exit name contains no blank components.


*/
static int ok_exit_name(name)
char *name;
{
char *p, *lastp, *s;
char buff[LBUF_SIZE];
strcpy(buff, name);

/* munchable buffer */

/* walk down the string, checking lengths. skip leading spaces. */


for (p = buff, lastp = buff;
(p = strchr(lastp, ';')) != NULL;
lastp = p) {
*p++ = '\0';
s = lastp;
while (isspace(*s))
s++;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:31 PM

if (strlen(s) < 1)
return 0;
}
/* check last component */
while (isspace(*lastp))
lastp++;
if (strlen(lastp) < 1)
return 0;
}

return 1;

/* --------------------------------------------------------------------------* create_obj: Create an object of the indicated type IF the player can
* afford it.
*/
dbref create_obj(player, objtype, name, cost)
dbref player;
int objtype, cost;
char *name;
{
dbref obj, owner;
dbref parent = NOTHING;
dbref proto = NOTHING;
int quota, okname = 0, value, self_owned, require_inherit;
FLAG f1, f2, f3;
time_t tt;
char *buff;
const char *tname;
struct timeval obj_time;
/* First check to see whether or not we're allowed to grow the
* database any further (we must either have an object in the
* freelist, or we have to be under the limit).
*/
if ((mudstate.db_top + 1 >= mudconf.building_limit) &&
(mudstate.freelist == NOTHING)) {
notify(player, "The database building limit has been reached." );
return NOTHING;
}
value = 0;
quota = 0;
self_owned = 0;
require_inherit = 0;
switch (objtype) {
case TYPE_ROOM:
cost = mudconf.digcost;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:31 PM

quota = mudconf.room_quota;
f1 = mudconf.room_flags.word1;
f2 = mudconf.room_flags.word2;
f3 = mudconf.room_flags.word3;
okname = ok_name(name);
tname = "a room";
if (Good_obj(mudconf.room_parent))
parent = mudconf.room_parent;
if (Good_obj(mudconf.room_proto))
proto = mudconf.room_proto;
break;
case TYPE_THING:
if (cost < mudconf.createmin)
cost = mudconf.createmin;
if (cost > mudconf.createmax)
cost = mudconf.createmax;
quota = mudconf.thing_quota;
f1 = mudconf.thing_flags.word1;
f2 = mudconf.thing_flags.word2;
f3 = mudconf.thing_flags.word3;
value = OBJECT_ENDOWMENT(cost);
okname = ok_name(name);
tname = "a thing";
if (Good_obj(mudconf.thing_parent))
parent = mudconf.thing_parent;
if (Good_obj(mudconf.thing_proto))
proto = mudconf.thing_proto;
break;
case TYPE_EXIT:
cost = mudconf.opencost;
quota = mudconf.exit_quota;
f1 = mudconf.exit_flags.word1;
f2 = mudconf.exit_flags.word2;
f3 = mudconf.exit_flags.word3;
okname = ok_name(name) && ok_exit_name(name);
tname = "an exit";
if (Good_obj(mudconf.exit_parent))
parent = mudconf.exit_parent;
if (Good_obj(mudconf.exit_proto))
proto = mudconf.exit_proto;
break;
case TYPE_PLAYER:
if (cost) {
cost = mudconf.robotcost;
quota = mudconf.player_quota;
f1 = mudconf.robot_flags.word1;
f2 = mudconf.robot_flags.word2;
f3 = mudconf.robot_flags.word3;
value = 0;
tname = "a robot";
require_inherit = 1;
} else {
cost = 0;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:31 PM

quota = 0;
f1 = mudconf.player_flags.word1;
f2 = mudconf.player_flags.word2;
f3 = mudconf.player_flags.word3;
value = mudconf.paystart;
quota = mudconf.start_quota;
self_owned = 1;
tname = "a player";

}
if (Good_obj(mudconf.player_parent))
parent = mudconf.player_parent;
if (Good_obj(mudconf.player_proto))
proto = mudconf.player_proto;
buff = munge_space(name);
if (!badname_check(buff)) {
notify(player, "That name is not allowed.");
free_lbuf(buff);
return NOTHING;
}
if (!ok_player_name(buff)) {
free_lbuf(buff);
break;
}
if (lookup_player(NOTHING, buff, 0) != NOTHING) {
notify(player,
tprintf("The name %s is already taken." , name));
free_lbuf(buff);
return NOTHING;
}
++okname;
free_lbuf(buff);
break;
default:
STARTLOG(LOG_BUGS, "BUG", "OTYPE")
log_printf("Bad object type in create_obj: %d." ,
objtype);
ENDLOG
return NOTHING;
}
if (!okname) {
notify(player, tprintf("That's a silly name for %s!" , tname));
return NOTHING;
}
if (!self_owned) {
if (!Good_obj(player))
return NOTHING;
owner = Owner(player);
if (!Good_obj(owner))
return NOTHING;
} else {
owner = NOTHING;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:31 PM

}
if (require_inherit) {
if (!Inherits(player)) {
notify(player, NOPERM_MESSAGE);
return NOTHING;
}
}
/* Make sure the creator can pay for the object. */
if ((player != NOTHING) &&
!canpayfees(player, player, cost, quota, objtype))
return NOTHING;
else if (player != NOTHING)
payfees(player, cost, quota, objtype);
/* Get the first object from the freelist. If the object is not
* clean, discard the remainder of the freelist and go get a
* completely new object.
*/
obj = NOTHING;
if (mudstate.freelist != NOTHING) {
obj = mudstate.freelist;
if (Good_dbref(obj) && IS_CLEAN(obj)) {
mudstate.freelist = Link(obj);
} else {
STARTLOG(LOG_PROBLEMS, "FRL", "DAMAG")
log_printf("Freelist damaged, bad object #%d." ,
obj);
ENDLOG
obj = NOTHING;
mudstate.freelist = NOTHING;
}
}
if (obj == NOTHING) {
obj = mudstate.db_top;
db_grow(mudstate.db_top + 1);
}
atr_free(obj);
/* just in case... */
/* Set things up according to the object type */
s_Location(obj, NOTHING);
s_Contents(obj, NOTHING);
s_Exits(obj, NOTHING);
s_Next(obj, NOTHING);
s_Link(obj, NOTHING);
/* We do not autozone players to their creators. */
if (mudconf.autozone && (player != NOTHING) &&
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:31 PM

(objtype != TYPE_PLAYER)) {
s_Zone(obj, Zone(player));
} else {
if (proto != NOTHING) {
s_Zone(obj, Zone(proto));
} else {
s_Zone(obj, NOTHING);
}
}
if (proto != NOTHING) {
s_Parent(obj, Parent(proto));
s_Flags(obj, objtype | (Flags(proto) & ~TYPE_MASK));
s_Flags2(obj, Flags2(proto));
s_Flags3(obj, Flags3(proto));
} else {
s_Parent(obj, parent);
s_Flags(obj, objtype | f1);
s_Flags2(obj, f2);
s_Flags3(obj, f3);
}
s_Owner(obj, (self_owned ? obj : owner));
s_Pennies(obj, value);
Unmark(obj);
buff = munge_space((char *)name);
s_Name(obj, buff);
free_lbuf(buff);
#ifndef NO_TIMECHECKING
obj_time.tv_sec = obj_time.tv_usec = 0;
s_Time_Used(obj, obj_time);
#endif
s_Accessed(obj);
s_Modified(obj);
s_StackCount(obj, 0);
s_VarsCount(obj, 0);
s_StructCount(obj, 0);
s_InstanceCount(obj, 0);
if (proto != NOTHING)
atr_cpy(GOD, obj, proto);
if (objtype == TYPE_PLAYER) {
time(&tt);
buff = (char *)ctime(&tt);
buff[strlen(buff) - 1] = '\0';
atr_add_raw(obj, A_LAST, buff);
buff = alloc_sbuf("create_obj.quota");
sprintf(buff, "%d %d %d %d %d", quota, mudconf.start_room_quota,
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:31 PM

mudconf.start_exit_quota, mudconf.start_thing_quota,
mudconf.start_player_quota);
atr_add_raw(obj, A_QUOTA, buff);
atr_add_raw(obj, A_RQUOTA, buff);
add_player_name(obj, Name(obj));
free_sbuf(buff);
if (!cost)
payfees(obj, 0, mudconf.player_quota, TYPE_PLAYER);

}
if (player != NOTHING) {
update_newobjs(player, obj, objtype);
}
CALL_ALL_MODULES(create_obj, (player, obj));
return obj;

/* --------------------------------------------------------------------------* destroy_obj: Destroy an object. Assumes it has already been removed from
* all lists and has no contents or exits.
*/
void destroy_obj(player, obj)
dbref player, obj;
{
dbref owner;
int good_owner, val, quota;
char *tname;
if (!Good_obj(obj))
return;
/* Validate the owner */
owner = Owner(obj);
good_owner = Good_owner(owner);
/* Halt any pending commands (waiting or semaphore) */
if (halt_que(NOTHING, obj) > 0) {
if (good_owner && !Quiet(obj) && !Quiet(owner)) {
notify(owner, "Halted.");
}
}
nfy_que(GOD, obj, 0, NFY_DRAIN, 0);
cron_clr(obj, NOTHING);
/* Remove forwardlists, stacks, etc. from the hash tables. */
fwdlist_clr(obj);
propdir_clr(obj);
stack_clr(obj);
xvars_clr(obj);
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:31 PM

structure_clr(obj);
CALL_ALL_MODULES(destroy_obj, (player, obj));
/* Compensate the owner for the object */
val = 1;
quota = 1;
if (good_owner && (owner != obj)) {
switch (Typeof(obj)) {
case TYPE_ROOM:
val = mudconf.digcost;
quota = mudconf.room_quota;
break;
case TYPE_THING:
val = OBJECT_DEPOSIT(Pennies(obj));
quota = mudconf.thing_quota;
break;
case TYPE_EXIT:
val = mudconf.opencost;
quota = mudconf.exit_quota;
break;
case TYPE_PLAYER:
if (Robot(obj))
val = mudconf.robotcost;
else
val = 0;
quota = mudconf.player_quota;
}
payfees(owner, -val, -quota, Typeof(obj));
if (!Quiet(owner) && !Quiet(obj))
notify(owner,
tprintf("You get back your %d %s deposit for %s(#%d)." ,
val, mudconf.one_coin, Name(obj), obj));
}
if ((player != NOTHING) && !Quiet(player)) {
if (good_owner && Owner(player) != owner) {
if (owner == obj) {
notify(player,
tprintf("Destroyed. %s(#%d)",
Name(obj), obj));
} else {
tname = alloc_sbuf("destroy_obj");
strcpy(tname, Name(owner));
notify(player,
tprintf("Destroyed. %s's %s(#%d)",
tname, Name(obj), obj));
free_sbuf(tname);
}
} else if (!Quiet(obj)) {
notify(player, "Destroyed.");
}
}

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:31 PM

atr_free(obj);
s_Name(obj, NULL);
s_Flags(obj, (TYPE_GARBAGE | GOING));
s_Flags2(obj, 0);
s_Flags3(obj, 0);
s_Powers(obj, 0);
s_Powers2(obj, 0);
s_Location(obj, NOTHING);
s_Contents(obj, NOTHING);
s_Exits(obj, NOTHING);
s_Next(obj, NOTHING);
s_Link(obj, NOTHING);
s_Owner(obj, GOD);
s_Pennies(obj, 0);
s_Parent(obj, NOTHING);
s_Zone(obj, NOTHING);

/* --------------------------------------------------------------------------* do_freelist: Grab a garbage object, and move it to the top of the freelist.
*/
void do_freelist(player, cause, key, str)
dbref player, cause;
int key;
char *str;
{
dbref i, thing;
/* We can only take a dbref; don't bother calling match_absolute() even,
* since we're dealing with the garbage pile anyway.
*/
if (*str != '#') {
notify(player, NOMATCH_MESSAGE);
return;
}
str++;
if (!*str) {
notify(player, NOMATCH_MESSAGE);
return;
}
thing = atoi(str);
if (!Good_dbref(thing)) {
notify(player, NOMATCH_MESSAGE);
return;
}
/* The freelist is a linked list going from the lowest-numbered
* objects to the highest-numbered objects. We need to make sure an
* object is clean before we muck with it.
*/
if (IS_CLEAN(thing)) {
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:31 PM

if (mudstate.freelist == thing) {
notify(player, "That object is already at the head of the freelist." );
return;
}
/* We've got to find this thing's predecessor so we avoid
* circular chaining.
*/
DO_WHOLE_DB(i) {
if (Link(i) == thing) {
if (IS_CLEAN(i)) {
s_Link(i, Link(thing));
break; /* shouldn't have more than one linkage */
} else {
notify(player, "Unable to relink freelist at this time." );
return;
}
}
}
s_Link(thing, mudstate.freelist);
mudstate.freelist = thing;
notify(player, "Object placed at the head of the freelist." );

} else {
notify(player, "That object is not clean garbage." );
}

/* --------------------------------------------------------------------------* make_freelist: Build a freelist


*/
static void NDECL(make_freelist)
{
dbref i;
mudstate.freelist = NOTHING;
DO_WHOLE_DB_BACKWARDS(i) {
if (IS_CLEAN(i)) {
/* If there's clean garbage at the end of the db, just
* trim it off. Memory will be reused if new objects are
* needed, but can be eliminated by restarting.
*/
mudstate.db_top--;
} else {
break;
}
}
DO_WHOLE_DB_BACKWARDS(i) {
if (IS_CLEAN(i)) {
s_Link(i, mudstate.freelist);
mudstate.freelist = i;
}
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

Saturday, June 16, 2012 11:31 PM

/* --------------------------------------------------------------------------* divest_object: Get rid of KEY contents of object.


*/
void divest_object(thing)
dbref thing;
{
dbref curr, temp;

SAFE_DOLIST(curr, temp, Contents(thing)) {


if (!Controls(thing, curr) &&
Has_location(curr) && Key(curr)) {
move_via_generic(curr, HOME, NOTHING, 0);
}
}

/* --------------------------------------------------------------------------* empty_obj, purge_going: Get rid of GOING objects in the db.


*/
void empty_obj(obj)
dbref obj;
{
dbref targ, next;
/* Send the contents home */
SAFE_DOLIST(targ, next, Contents(obj)) {
if (!Has_location(targ)) {
Log_simple_err(targ, obj,
"Funny object type in contents list of GOING location. Flush
terminated.");
break;
} else if (Location(targ) != obj) {
Log_header_err(targ, obj, Location(targ), 1,
"Location",
"indicates object really in another location during cleanup of
GOING location. Flush terminated." );
break;
} else {
ZAP_LOC(targ);
if (Home(targ) == obj) {
s_Home(targ, new_home(targ));
}
move_via_generic(targ, HOME, NOTHING, 0);
divest_object(targ);
}
}

-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

741
742
743
744
745
746

/* Destroy the exits */

747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

Saturday, June 16, 2012 11:31 PM

SAFE_DOLIST(targ, next, Exits(obj)) {


if (!isExit(targ)) {
Log_simple_err(targ, obj,
"Funny object type in exit list of GOING location. Flush
terminated.");
break;
} else if (Exits(targ) != obj) {
Log_header_err(targ, obj, Exits(targ), 1,
"Location",
"indicates exit really in another location during cleanup of
GOING location. Flush terminated." );
break;
} else {
destroy_obj(NOTHING, targ);
}
}

/* --------------------------------------------------------------------------* destroy_exit, destroy_thing, destroy_player


*/
void destroy_exit(exit)
dbref exit;
{
dbref loc;

loc = Exits(exit);
s_Exits(loc, remove_first(Exits(loc), exit));
destroy_obj(NOTHING, exit);

void destroy_thing(thing)
dbref thing;
{
move_via_generic(thing, NOTHING, Owner(thing), 0);
empty_obj(thing);
destroy_obj(NOTHING, thing);
}
void destroy_player(victim)
dbref victim;
{
dbref aowner, player;
int count, aflags, alen;
char *buf, *a_dest;
/* Bye bye... */
a_dest = atr_get_raw(victim, A_DESTROYER);
if (a_dest) {
player = atoi(a_dest);
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844

Saturday, June 16, 2012 11:31 PM

if (!Good_owner(player))
player = GOD;
} else {
player = GOD;
}
boot_off(victim, (char *)"You have been destroyed!");
halt_que(victim, NOTHING);
count = chown_all(victim, player, player, 0);
/* Remove the name from the name hash table */
delete_player_name(victim, Name(victim));
buf = atr_pget(victim, A_ALIAS, &aowner, &aflags, &alen);
Clear_Player_Aliases(victim, buf);
free_lbuf(buf);

move_via_generic(victim, NOTHING, player, 0);


CALL_ALL_MODULES(destroy_player, (player, victim));
destroy_obj(NOTHING, victim);
notify_quiet(player, tprintf("(%d objects @chowned to you)" , count));

static void NDECL(purge_going)


{
dbref i;
DO_WHOLE_DB(i) {
if (!Going(i))
continue;
switch (Typeof(i)) {
case TYPE_PLAYER:
destroy_player(i);
break;
case TYPE_ROOM:
/* Room scheduled for destruction... do it */
empty_obj(i);
destroy_obj(NOTHING, i);
break;
case TYPE_THING:
destroy_thing(i);
break;
case TYPE_EXIT:
destroy_exit(i);
break;
case TYPE_GARBAGE:
break;
default:
/* Something else... How did this happen? */
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897

Saturday, June 16, 2012 11:31 PM

Log_simple_err(i, NOTHING,
"GOING object with unexpected type.
destroy_obj(NOTHING, i);

Destroyed." );

/* --------------------------------------------------------------------------* check_dead_refs: Look for references to GOING or illegal objects.


*/
static void check_pennies(thing, limit, qual)
dbref thing;
int limit;
const char *qual;
{
int j;

if (Going(thing))
return;
j = Pennies(thing);
if (isRoom(thing) || isExit(thing)) {
if (j) {
Log_header_err(thing, NOTHING, j, 0,
qual, "is strange. Reset.");
s_Pennies(thing, 0);
}
} else if (j == 0) {
Log_header_err(thing, NOTHING, j, 0, qual, "is zero.");
} else if (j < 0) {
Log_header_err(thing, NOTHING, j, 0, qual, "is negative.");
} else if (j > limit) {
Log_header_err(thing, NOTHING, j, 0, qual, "is excessive.");
}

#define check_ref_targ(crt__label, crt__setref, crt__newref) \


do { \
if (Good_obj(targ)) { \
if (Going(targ)) { \
crt__setref(i, crt__newref); \
if (!mudstate.standalone) { \
owner = Owner(i); \
if (Good_owner(owner) && \
!Quiet(i) && !Quiet(owner)) { \
notify(owner, \
tprintf("%s cleared on %s(#%d)", \
crt__label, Name(i), i)); \
} \
} else { \
Log_header_err(i, Location(i), targ, 1, \
crt__label, "is invalid. Cleared."); \
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950

Saturday, June 16, 2012 11:31 PM

} \
} \
} else if (targ != NOTHING) { \
Log_header_err(i, Location(i), targ, 1, \
crt__label, "is invalid. Cleared."); \
crt__setref(i, crt__newref); \
} \
} while (0)
static NDECL(void check_dead_refs)
{
dbref targ, owner, i, j;
int aflags, dirty;
char *str;
FWDLIST *fp;
PROPDIR *pp;
DO_WHOLE_DB(i) {
/* Check the parent */
targ = Parent(i);
check_ref_targ("Parent", s_Parent, NOTHING);
/* Check the zone */
targ = Zone(i);
check_ref_targ("Zone", s_Zone, NOTHING);
switch (Typeof(i)) {
case TYPE_PLAYER:
case TYPE_THING:
if (Going(i))
break;
/* Check the home */
targ = Home(i);
check_ref_targ("Home", s_Home, new_home(i));
/* Check the location */
targ = Location(i);
if (!Good_obj(targ)) {
Log_pointer_err(NOTHING, i, NOTHING, targ,
"Location",
"is invalid. Moved to home." );
ZAP_LOC(i);
move_object(i, HOME);
}
/* Check for self-referential Next() */
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003

Saturday, June 16, 2012 11:31 PM

if (Next(i) == i) {
Log_simple_err(i, NOTHING,
"Next points to self.
s_Next(i, NOTHING);
}

Next cleared." );

if (check_type & DBCK_FULL) {


/* Check wealth or value */
targ = OBJECT_ENDOWMENT(mudconf.createmax);
if (OwnsOthers(i)) {
targ += mudconf.paylimit;
check_pennies(i, targ, "Wealth");
} else {
check_pennies(i, targ, "Value");
}

}
break;
case TYPE_ROOM:

/* Check the dropto */


targ = Dropto(i);
if (targ != HOME) {
check_ref_targ("Dropto", s_Dropto, NOTHING);
}
if (check_type & DBCK_FULL) {
/* NEXT should be null */
if (Next(i) != NOTHING) {
Log_header_err(i, NOTHING, Next(i), 1,
"Next pointer",
"should be NOTHING. Reset.");
s_Next(i, NOTHING);
}
/* LINK should be null */
if (Link(i) != NOTHING) {
Log_header_err(i, NOTHING, Link(i), 1,
"Link pointer ",
"should be NOTHING. Reset.");
s_Link(i, NOTHING);
}
/* Check value */
check_pennies(i, 1, "Value");
}
break;
case TYPE_EXIT:

-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056

Saturday, June 16, 2012 11:31 PM

/* If it points to something GOING, set it going */


targ = Location(i);
if (Good_obj(targ)) {
if (Going(targ)) {
s_Going(i);
}
} else if ((targ == HOME) || (targ == AMBIGUOUS)) {
/* null case, always valid */
} else if (targ != NOTHING) {
Log_header_err(i, Exits(i), targ, 1,
"Destination",
"is invalid. Exit destroyed." );
s_Going(i);
} else {
if (!Has_contents(targ)) {
Log_header_err(i, Exits(i), targ, 1,
"Destination",
"is not a valid type. Exit destroyed." );
s_Going(i);
}
}
/* Check for self-referential Next() */
if (Next(i) == i) {
Log_simple_err(i, NOTHING,
"Next points to self.
s_Next(i, NOTHING);
}

Next cleared." );

if (check_type & DBCK_FULL) {


/* CONTENTS should be null */
if (Contents(i) != NOTHING) {
Log_header_err(i, Exits(i),
Contents(i), 1, "Contents",
"should be NOTHING. Reset.");
s_Contents(i, NOTHING);
}
/* LINK should be null */
if (Link(i) != NOTHING) {
Log_header_err(i, Exits(i), Link(i), 1,
"Link",
"should be NOTHING. Reset.");
s_Link(i, NOTHING);
}
/* Check value */
}

check_pennies(i, 1, "Value");

-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109

Saturday, June 16, 2012 11:31 PM

break;
case TYPE_GARBAGE:
break;
default:
/* Funny object type, destroy it */

Log_simple_err(i, NOTHING,
"Funny object type.
destroy_obj(NOTHING, i);

Destroyed." );

/* Check forwardlist */
dirty = 0;
if (H_Fwdlist(i) && ((fp = fwdlist_get(i)) != NULL)) {
for (j = 0; j < fp->count; j++) {
targ = fp->data[j];
if (Good_obj(targ) && Going(targ)) {
fp->data[j] = NOTHING;
dirty = 1;
} else if (!Good_obj(targ) &&
(targ != NOTHING)) {
fp->data[j] = NOTHING;
dirty = 1;
}
}
}
if (dirty) {
str = alloc_lbuf("purge_going");
(void)fwdlist_rewrite(fp, str);
atr_get_info(i, A_FORWARDLIST, &owner, &aflags);
atr_add(i, A_FORWARDLIST, str, owner, aflags);
free_lbuf(str);
}
/* Check propdir */
dirty = 0;
if (H_Propdir(i) && ((pp = propdir_get(i)) != NULL)) {
for (j = 0; j < pp->count; j++) {
targ = pp->data[j];
if (Good_obj(targ) && Going(targ)) {
pp->data[j] = NOTHING;
dirty = 1;
} else if (!Good_obj(targ) &&
(targ != NOTHING)) {
pp->data[j] = NOTHING;
dirty = 1;
}
}
}
if (dirty) {
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162

Saturday, June 16, 2012 11:31 PM

str = alloc_lbuf("purge_going");
(void)propdir_rewrite(pp, str);
atr_get_info(i, A_PROPDIR, &owner, &aflags);
atr_add(i, A_PROPDIR, str, owner, aflags);
free_lbuf(str);

/* Check owner */
owner = Owner(i);
if (!Good_obj(owner)) {
Log_header_err(i, NOTHING, owner, 1,
"Owner", "is invalid. Set to GOD.");
owner = GOD;
s_Owner(i, owner);
if (!mudstate.standalone)
halt_que(NOTHING, i);
s_Halted(i);
} else if (check_type & DBCK_FULL) {
if (Going(owner)) {
Log_header_err(i, NOTHING, owner, 1,
"Owner", "is set GOING. Set to GOD.");
s_Owner(i, owner);
if (!mudstate.standalone)
halt_que(NOTHING, i);
s_Halted(i);
} else if (!OwnsOthers(owner)) {
Log_header_err(i, NOTHING, owner, 1,
"Owner", "is not a valid owner type.");
} else if (isPlayer(i) && (owner != i)) {
Log_header_err(i, NOTHING, owner, 1,
"Player", "is the owner instead of the player." );
}
}
if (check_type & DBCK_FULL) {
/* Check for wizards */

if (Wizard(i)) {
if (isPlayer(i)) {
Log_simple_err(i, NOTHING,
"Player is a WIZARD.");
}
if (!Wizard(Owner(i))) {
Log_header_err(i, NOTHING, Owner(i), 1,
"Owner",
"of a WIZARD object is not a wizard" );
}
}

-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215

Saturday, June 16, 2012 11:31 PM

#undef check_ref_targ
/* --------------------------------------------------------------------------* check_loc_exits, check_exit_chains: Validate the exits chains
* of objects and attempt to correct problems. The following errors are
* found and corrected:
*
Location not in database
- skip it.
*
Location GOING
- skip it.
*
Location not a PLAYER, ROOM, or THING
- skip it.
*
Location already visited
- skip it.
*
Exit/next pointer not in database
- NULL it.
*
Member is not an EXIT
- terminate chain.
*
Member is GOING
- destroy exit.
*
Member already checked (is in another list)
- terminate chain.
*
Member in another chain (recursive check)
- terminate chain.
*
Location of member is not specified location
- reset it.
*/
static void check_loc_exits(loc)
dbref loc;
{
dbref exit, back, temp, exitloc, dest;
if (!Good_obj(loc))
return;
/* Only check players, rooms, and things that aren't GOING */
if (isExit(loc) || Going(loc))
return;
/* If marked, we've checked here already */
if (Marked(loc))
return;
Mark(loc);
/* Check all the exits */
back = NOTHING;
exit = Exits(loc);
while (exit != NOTHING) {
exitloc = NOTHING;
dest = NOTHING;
if (Good_obj(exit)) {
exitloc = Exits(exit);
dest = Location(exit);
}
if (!Good_obj(exit)) {
/* A bad pointer - terminate chain */
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268

Saturday, June 16, 2012 11:31 PM

Log_pointer_err(back, loc, NOTHING, exit, "Exit list",


"is invalid. List nulled.");
if (back != NOTHING) {
s_Next(back, NOTHING);
} else {
s_Exits(loc, NOTHING);
}
exit = NOTHING;
} else if (!isExit(exit)) {
/* Not an exit - terminate chain */
Log_pointer_err(back, loc, NOTHING, exit,
"Exitlist member",
"is not an exit. List terminated." );
if (back != NOTHING) {
s_Next(back, NOTHING);
} else {
s_Exits(loc, NOTHING);
}
exit = NOTHING;
} else if (Going(exit)) {
/* Going - silently filter out */
temp = Next(exit);
if (back != NOTHING) {
s_Next(back, temp);
} else {
s_Exits(loc, temp);
}
destroy_obj(NOTHING, exit);
exit = temp;
continue;
} else if (Marked(exit)) {
/* Already in another list - terminate chain */
Log_pointer_err(back, loc, NOTHING, exit,
"Exitlist member",
"is in another exitlist. Cleared." );
if (back != NOTHING) {
s_Next(back, NOTHING);
} else {
s_Exits(loc, NOTHING);
}
exit = NOTHING;
} else if (!Good_obj(dest) && (dest != HOME) &&
(dest != AMBIGUOUS) && (dest != NOTHING)) {
/* Destination is not in the db.

-24-

Null it. */

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321

Saturday, June 16, 2012 11:31 PM

Log_pointer_err(back, loc, NOTHING, exit,


"Destination", "is invalid. Cleared.");
s_Location(exit, NOTHING);
} else if (exitloc != loc) {
/* Exit thinks it's in another place. Check the
* exitlist there and see if it contains this
* exit. If it does, then our exitlist
* somehow pointed into the middle of their
* exitlist. If not, assume we own the exit.
*/
check_loc_exits(exitloc);
if (Marked(exit)) {
/* It's in the other list, give it up */
Log_pointer_err(back, loc, NOTHING, exit, "",
"is in another exitlist. List terminated." );
if (back != NOTHING) {
s_Next(back, NOTHING);
} else {
s_Exits(loc, NOTHING);
}
exit = NOTHING;
} else {
/* Not in the other list, assume in ours */
Log_header_err(exit, loc, exitloc, 1,
"Not on chain for location",
"Reset.");
s_Exits(exit, loc);

}
}
if (exit != NOTHING) {

/* All OK (or all was made OK) */


if (check_type & DBCK_FULL) {
/* Make sure exit owner owns at least one of
* the source or destination. Just
* warn if he doesn't.
*/
temp = Owner(exit);
if ((temp != Owner(loc)) &&
(temp != Owner(Location(exit)))) {
Log_header_err(exit, loc, temp, 1,
"Owner",
"does not own either the source or destination." );
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374

}
}
return;

Saturday, June 16, 2012 11:31 PM

}
}
Mark(exit);
back = exit;
exit = Next(exit);

static void NDECL(check_exit_chains)


{
dbref i;

Unmark_all(i);
DO_WHOLE_DB(i)
check_loc_exits(i);
DO_WHOLE_DB(i) {
if (isExit(i) && !Marked(i)) {
Log_simple_err(i, NOTHING,
"Disconnected exit.
destroy_obj(NOTHING, i);
}
}

Destroyed." );

/* --------------------------------------------------------------------------* check_misplaced_obj, check_loc_contents, check_contents_chains: Validate


* the contents chains of objects and attempt to correct problems. The
* following errors are found and corrected:
*
Location not in database
- skip it.
*
Location GOING
- skip it.
*
Location not a PLAYER, ROOM, or THING
- skip it.
*
Location already visited
- skip it.
*
Contents/next pointer not in database
- NULL it.
*
Member is not an PLAYER or THING
- terminate chain.
*
Member is GOING
- destroy exit.
*
Member already checked (is in another list)
- terminate chain.
*
Member in another chain (recursive check)
- terminate chain.
*
Location of member is not specified location
- reset it.
*/
static void FDECL(check_loc_contents, (dbref));
static void check_misplaced_obj(obj, back, loc)
dbref *obj, back, loc;
{
/* Object thinks it's in another place. Check the contents list
* there and see if it contains this object. If it does, then
* our contents list somehow pointed into the middle of their
* contents list and we should truncate our list. If not,
* assume we own the object.
*/
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427

Saturday, June 16, 2012 11:31 PM

if (!Good_obj(*obj))
return;
loc = Location(*obj);
Unmark(*obj);
if (Good_obj(loc)) {
check_loc_contents(loc);
}
if (Marked(*obj)) {
/* It's in the other list, give it up */
Log_pointer_err(back, loc, NOTHING, *obj, "",
"is in another contents list. Cleared." );
if (back != NOTHING) {
s_Next(back, NOTHING);
} else {
s_Contents(loc, NOTHING);
}
*obj = NOTHING;
} else {
/* Not in the other list, assume in ours */
Log_header_err(*obj, loc, Contents(*obj), 1,
"Location", "is invalid. Reset.");
s_Contents(*obj, loc);

}
return;

static void check_loc_contents(loc)


dbref loc;
{
dbref obj, back, temp;
if (!Good_obj(loc))
return;
/* Only check players, rooms, and things that aren't GOING */
if (isExit(loc) || Going(loc))
return;
/* Check all the exits */
back = NOTHING;
obj = Contents(loc);
while (obj != NOTHING) {
if (!Good_obj(obj)) {
/* A bad pointer - terminate chain */
Log_pointer_err(back, loc, NOTHING, obj,
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480

Saturday, June 16, 2012 11:31 PM

"Contents list", "is invalid.


if (back != NOTHING) {
s_Next(back, NOTHING);
} else {
s_Contents(loc, NOTHING);
}
obj = NOTHING;
} else if (!Has_location(obj)) {

Cleared.");

/* Not a player or thing - terminate chain */


Log_pointer_err(back, loc, NOTHING, obj,
"Contents list member",
"is not a player or thing. Cleared." );
if (back != NOTHING) {
s_Next(back, NOTHING);
} else {
s_Contents(loc, NOTHING);
}
obj = NOTHING;
} else if (Going(obj) && (Typeof(obj) == TYPE_GARBAGE)) {
/* Going - silently filter out */
temp = Next(obj);
if (back != NOTHING) {
s_Next(back, temp);
} else {
s_Contents(loc, temp);
}
destroy_obj(NOTHING, obj);
obj = temp;
continue;
} else if (Marked(obj)) {
/* Already visited - either truncate or ignore */
if (Location(obj) != loc) {
/* Location wrong - either truncate or fix */
check_misplaced_obj(&obj, back, loc);
} else {
/* Location right - recursive contents */
}
} else if (Location(obj) != loc) {
/* Location wrong - either truncate or fix */
check_misplaced_obj(&obj, back, loc);
}
if (obj != NOTHING) {
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533

Saturday, June 16, 2012 11:31 PM

/* All OK (or all was made OK) */


if (check_type & DBCK_FULL) {
/* Check for wizard command-handlers inside
* nonwiz. Just warn if we find one.
*/
if (Wizard(obj) && !Wizard(loc)) {
if (Commer(obj)) {
Log_simple_err(obj, loc,
"Wizard command handling object inside nonwizard." );
}
}
/* Check for nonwizard objects inside wizard
* objects.
*/
if (Wizard(loc) &&
!Wizard(obj) && !Wizard(Owner(obj))) {
Log_simple_err(obj, loc,
"Nonwizard object inside wizard." );
}

}
Mark(obj);
back = obj;
obj = Next(obj);

}
return;

static void NDECL(check_contents_chains)


{
dbref i;

Unmark_all(i);
DO_WHOLE_DB(i)
check_loc_contents(i);
DO_WHOLE_DB(i)
if (!Going(i) && !Marked(i) && Has_location(i)) {
Log_simple_err(i, Location(i),
"Orphaned object, moved home." );
ZAP_LOC(i);
move_via_generic(i, HOME, NOTHING, 0);
}

/* --------------------------------------------------------------------------* do_dbck: Perform a database consistency check and clean up damage.


*/

-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\object.c

1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552

Saturday, June 16, 2012 11:31 PM

void do_dbck(player, cause, key)


dbref player, cause;
int key;
{
check_type = key;
make_freelist();
if (!mudstate.standalone)
cf_verify();
check_dead_refs();
check_exit_chains();
check_contents_chains();
purge_going();
if (!mudstate.standalone && (player != NOTHING)) {
alarm(1);
if (!Quiet(player))
notify(player, "Done.");
}
}

-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\patchlevel.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Saturday, June 16, 2012 11:06 PM

/* patchlevel.h - version information */


/* $Id: patchlevel.h,v 1.74 2009/01/12 01:14:06 lwl Exp $ */
#include "copyright.h"
#ifndef __PATCHLEVEL_H
#define __PATCHLEVEL_H
#define
#define
#define
#define

MUSH_VERSION
"3.1"
/* Base version number */
PATCHLEVEL
6
/* Patchlevel or beta number */
MUSH_RELEASE_DATE
"01/12/2009"
/* Source release date */
MUSH_RELEASE_STATUS 0
/* 0 gamma, 1 beta, 2 alpha */

#endif /* __PATCHLEVEL_H */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:29 PM

/*************************************************
*
Perl-Compatible Regular Expressions
*
*************************************************/
/*
This is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language. See
the file Tech.Notes for some information on the internals.
Written by: Philip Hazel <ph10@cam.ac.uk>
Copyright (c) 1997-2001 University of Cambridge
----------------------------------------------------------------------------Permission is granted to anyone to use this software for any purpose on any
computer system, and to redistribute it freely, subject to the following
restrictions:
1. This software 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.
2. The origin of this software must not be misrepresented, either by
explicit claim or by omission.
3. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original software.
4. If PCRE is embedded in any software that is released under the GNU
General Purpose Licence (GPL), then the terms of that licence shall
supersede any condition above with which it is incompatible.
----------------------------------------------------------------------------*/
/* Modifications made for TinyMUSH 3. Changes include:
*
Crunched down to a single file.
*
Included headers conform with TM3 standard.
*
Function prototypes conform with TM3 standard.
*
DEBUG define is now PCRE_DEBUG.
*
Removed UTF-8 support.
*
Removed pcre_version(), pcre_info(), pcre_fullinfo().
*
Altered syntax of calls to pcre_malloc() and pcre_free() so macros
*
work.
*
Functions altered to deal with excessive backtracking.
*
Patched to protect against integer overflow in repeat counts.
*
Search code comments for 'TM3 modification:' for more.
*/
#include
#include
#include
#include
#include

"copyright.h"
"autoconf.h"
"alloc.h"
"config.h"
"flags.h"
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:29 PM

#include "htab.h"
#include "mudconf.h"
#include "pcre.h"
/* Define PCRE_DEBUG to get debugging output on stdout. */
/* #define PCRE_DEBUG */
/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
inline, and there are *still* stupid compilers about that don't like indented
pre-processor statements. I suppose it's only been 10 years... */
#ifdef PCRE_DEBUG
#define DPRINTF(p) printf p
#else
#define DPRINTF(p) /*nothing*/
#endif
/* Allow compilation as C++ source code, should anybody want to do that. */
#ifdef __cplusplus
#define class pcre_class
#endif
/* Maximum number of items on the nested bracket stacks at compile time. This
applies to the nesting of all kinds of parentheses. It does not limit
un-nested, non-capturing parentheses. This number can be made bigger if
necessary - it is used to dimension one int and one unsigned char vector at
compile time. */
#define BRASTACK_SIZE 200
/* The number of bytes in a literal character string above which we can't add
any more is different when UTF-8 characters may be encountered. */
#define MAXLIT 255
/* Min and max values for the common repeats; for the maxima, 0 => infinity */
static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
/* Text forms of OP_ values and things, for debugging (not all used) */
#ifdef PCRE_DEBUG
static const char *OP_names[] = {
"End", "\\A", "\\B", "\\b", "\\D", "\\d",
"\\S", "\\s", "\\W", "\\w", "\\Z", "\\z",
"Opt", "^", "$", "Any", "chars", "not",
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:29 PM

"*", "*?", "+", "+?", "?", "??", "{", "{", "{",


"*", "*?", "+", "+?", "?", "??", "{", "{", "{",
"*", "*?", "+", "+?", "?", "??", "{", "{", "{",
"*", "*?", "+", "+?", "?", "??", "{", "{",
"class", "Ref", "Recurse",
"Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not",
"AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cref",
"Brazero", "Braminzero", "Branumber", "Bra"

};
#endif

/* Table for handling escaped characters in the range '0'-'z'. Positive returns
are simple data values; negative values are for special things like \d and so
on. Zero means further processing is needed (for things like \x), or the escape
is invalid. */
static const short int escapes[] = {
0,
0,
0,
0,
0,
0,
0,
':',
';',
'<',
'@', -ESC_A, -ESC_B,
0, -ESC_D,
0,
0,
0,
0,
0,
0,
0,
0, -ESC_S,
0,
0,
0, -ESC_Z,
'[',
'\\',
'`',
7, -ESC_b,
0, -ESC_d,
0,
0,
0,
0,
0,
0,
0, ESC_R, -ESC_s, ESC_T,
0,
0, -ESC_z
};

0,
'=',
0,
0,
0,
']',
ESC_E,
0,
0,

0,
0,
'>',
'?',
0,
0,
0,
0,
0, -ESC_W,
'^',
'_',
ESC_F,
0,
ESC_N,
0,
0, -ESC_w,

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

0
8
@
H
P
X
`
h
p
x

7
?
G
O
W
_
g
o
w
z

*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

/* Tables of names of POSIX character classes and their lengths. The list is
terminated by a zero length entry. The first three must be alpha, upper, lower,
as this is assumed for handling case independence. */
static const char *posix_names[] = {
"alpha", "lower", "upper",
"alnum", "ascii", "cntrl", "digit", "graph",
"print", "punct", "space", "word", "xdigit" };
static const uschar posix_name_lengths[] = {
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
/* Table of class bit maps for each POSIX class; up to three may be combined
to form the class. */
static const int posix_class_maps[] = {
cbit_lower, cbit_upper, -1,
cbit_lower, -1,
-1,
cbit_upper, -1,
-1,
cbit_digit, cbit_lower, cbit_upper,
cbit_print, cbit_cntrl, -1,
cbit_cntrl, -1,
-1,
cbit_digit, -1,
-1,
cbit_graph, -1,
-1,

/*
/*
/*
/*
/*
/*
/*
/*
-3-

alpha
lower
upper
alnum
ascii
cntrl
digit
graph

*/
*/
*/
*/
*/
*/
*/
*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

};

cbit_print, -1,
cbit_punct, -1,
cbit_space, -1,
cbit_word, -1,
cbit_xdigit,-1,

Saturday, June 16, 2012 11:29 PM

-1,
-1,
-1,
-1,
-1

/*
/*
/*
/*
/*

print */
punct */
space */
word */
xdigit */

/* Definition to allow mutual recursion */


static BOOL FDECL(compile_regex,
(int, int, int *, uschar **, const uschar **, const char **,
BOOL, int, int *, int *, compile_data *));
/* Structure for building a chain of data that actually lives on the
stack, for holding the values of the subject pointer at the start of each
subpattern, so as to detect when an empty string has been matched by a
subpattern - to break infinite loops. */
typedef struct eptrblock {
struct eptrblock *prev;
const uschar *saved_eptr;
} eptrblock;
/* Flag bits for the match() function */
#define match_condassert
#define match_isgroup

0x01
0x02

/* Called to check a condition assertion */


/* Set if start of bracketed group */

/*************************************************
*
Global variables
*
*************************************************/
/*************************************************
*
Macros and tables for character handling
*
*************************************************/
/* When UTF-8 encoding is being used, a character is no longer just a single
byte. The macros for character handling generate simple sequences when used in
byte-mode, and more complicated ones for UTF-8 characters. */
#define GETCHARINC(c, eptr) c = *eptr++;
#define GETCHARLEN(c, eptr, len) c = *eptr;
#define BACKCHAR(eptr)
/*************************************************
*
Default character tables
*
*************************************************/
/* A default set of character tables is included in the PCRE binary. Its source
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:29 PM

is built by the maketables auxiliary program, which uses the default C ctypes
functions, and put in the file chartables.c. These tables are used by PCRE
whenever the caller of pcre_compile() does not provide an alternate set of
tables. */
/* TM3 modification: Include these directly here. */
static unsigned char pcre_default_tables[] = {
/* This table is a lower casing table. */
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122, 91, 92, 93, 94, 95,
96, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122,123,124,125,126,127,
128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,
152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,
168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,
184,185,186,187,188,189,190,191,
192,193,194,195,196,197,198,199,
200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,
224,225,226,227,228,229,230,231,
232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255,
/* This table is a case flipping table. */
0,
8,
16,
24,
32,
40,
48,

1,
9,
17,
25,
33,
41,
49,

2,
10,
18,
26,
34,
42,
50,

3,
11,
19,
27,
35,
43,
51,

4,
12,
20,
28,
36,
44,
52,

5,
13,
21,
29,
37,
45,
53,

6,
14,
22,
30,
38,
46,
54,

7,
15,
23,
31,
39,
47,
55,
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:29 PM

56, 57, 58, 59, 60, 61, 62, 63,


64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,
120,121,122, 91, 92, 93, 94, 95,
96, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90,123,124,125,126,127,
128,129,130,131,132,133,134,135,
136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,
152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,
168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,
184,185,186,187,188,189,190,191,
192,193,194,195,196,197,198,199,
200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,
224,225,226,227,228,229,230,231,
232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,
248,249,250,251,252,253,254,255,
/* This table contains bit maps for various character classes.
Each map is 32 bytes long and the bits run from the least
significant end of each byte. The classes that have their own
maps are: space, xdigit, digit, upper, lower, word, graph
print, punct, and cntrl. Other classes are built from combinations. */
0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:29 PM

0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* This table identifies various classes of character by individual bits:
0x01
white space character
0x02
letter
0x04
decimal digit
0x08
hexadecimal digit
0x10
alphanumeric or '_'
0x80
regular expression metacharacter or binary zero
*/
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00,
0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12,
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
0x12,0x12,0x12,0x80,0x00,0x00,0x80,0x10,
0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12,
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
-7-

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

081624( 0 8 @ H P X ` h p -

7
15
23
31
'
/
7
?
G
O
W
_
g
o
w

*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:29 PM

0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/*

x -127
128-135
136-143
144-151
152-159
160-167
168-175
176-183
184-191
192-199
200-207
208-215
216-223
224-231
232-239
240-247
248-255

*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

#ifdef PCRE_DEBUG
/*************************************************
*
Debugging function to print chars
*
*************************************************/
/* Print a sequence of chars in printable format, stopping at the end of the
subject if the requested.
Arguments:
p
length
is_subject
md
Returns:
*/

points to characters
number to print
TRUE if printing from within md->start_subject
pointer to matching data block, if is_subject is TRUE
nothing

static void pchars(p, length, is_subject, match_data)


const uschar *p;
int length;
BOOL is_subject;
match_data *md;
{
int c;
if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
while (length-- > 0)
if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c);
}
#endif
/*************************************************
*
Handle escapes
*
*************************************************/
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:29 PM

/* This function is called when a \ has been encountered. It either returns a


positive value for a simple escape such as \n, or a negative value which
encodes one of the more complicated things such as \d. When UTF-8 is enabled,
a positive value greater than 255 may be returned. On entry, ptr is pointing at
the \. On exit, it is on the final character of the escape sequence.
Arguments:
ptrptr
errorptr
bracount
options
isclass
cd
Returns:
*/

points to the pattern position pointer


points to the pointer to the error message
number of previous extracting brackets
the options bits
TRUE if inside a character class
pointer to char tables block
zero or positive => a data character
negative => a special escape sequence
on error, errorptr is set

static int check_escape(ptrptr, errorptr, bracount, options, isclass, cd)


const uschar **ptrptr;
const char **errorptr;
int bracount, options;
BOOL isclass;
compile_data *cd;
{
const uschar *ptr = *ptrptr;
int c, i;
/* If backslash is at the end of the pattern, it's an error. */
c = *(++ptr);
if (c == 0) *errorptr = ERR1;
/* Digits or letters may have special meaning; all others are literals. */
else if (c < '0' || c > 'z') {}
/* Do an initial lookup in a table. A non-zero result is something that can be
returned immediately. Otherwise further processing may be required. */
else if ((i = escapes[c - '0']) != 0) c = i;
/* Escapes that need further processing, or are illegal. */
else
{
const uschar *oldptr;
switch (c)
{
/* The handling of escape sequences consisting of a string of digits
starting with one that is not zero is not straightforward. By experiment,
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:29 PM

the way Perl works seems to be as follows:


Outside a character class, the digits are read as a decimal number. If the
number is less than 10, or if there are that many previous extracting
left brackets, then it is a back reference. Otherwise, up to three octal
digits are read to form an escaped byte. Thus \123 is likely to be octal
123 (cf \0123, which is octal 012 followed by the literal 3). If the octal
value is greater than 377, the least significant 8 bits are taken. Inside a
character class, \ followed by a digit is always an octal number. */
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
if (!isclass)
{
oldptr = ptr;
c -= '0';
while ((cd->ctypes[ptr[1]] & ctype_digit) != 0)
c = c * 10 + *(++ptr) - '0';
if (c < 10 || c <= bracount)
{
c = -(ESC_REF + c);
break;
}
ptr = oldptr;
/* Put the pointer back and fall through */
}
/* Handle an octal number following \. If the first digit is 8 or 9, Perl
generates a binary zero byte and treats the digit as a following literal.
Thus we have to pull back the pointer by one. */
if ((c = *ptr) >= '8')
{
ptr--;
c = 0;
break;
}
/* \0 always starts an octal number, but we may drop through to here with a
larger first octal digit. */
case '0':
c -= '0';
while(i++ < 2 && (cd->ctypes[ptr[1]] & ctype_digit) != 0 &&
ptr[1] != '8' && ptr[1] != '9')
c = c * 8 + *(++ptr) - '0';
c &= 255;
/* Take least significant 8 bits */
break;
/* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number
which can be greater than 0xff, but only if the ddd are hex digits. */
case 'x':
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:29 PM

/* Read just a single hex char */


c = 0;
while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_xdigit) != 0)
{
ptr++;
c = c * 16 + cd->lcc[*ptr] (((cd->ctypes[*ptr] & ctype_digit) != 0)? '0' : 'W');
}
break;
/* Other special escapes not starting with a digit are straightforward */
case 'c':
c = *(++ptr);
if (c == 0)
{
*errorptr = ERR2;
return 0;
}
/* A letter is upper-cased; then the 0x40 bit is flipped */
if (c >= 'a' && c <= 'z') c = cd->fcc[c];
c ^= 0x40;
break;
/* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any
other alphameric following \ is an error if PCRE_EXTRA was set; otherwise,
for Perl compatibility, it is a literal. This code looks a bit odd, but
there used to be some cases other than the default, and there may be again
in future, so I haven't "optimized" it. */

default:
if ((options & PCRE_EXTRA) != 0) switch(c)
{
default:
*errorptr = ERR3;
break;
}
break;
}

*ptrptr = ptr;
return c;
}

/*************************************************
*
Check for counted repeat
*
*************************************************/
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:29 PM

/* This function is called when a '{' is encountered in a place where it might


start a quantifier. It looks ahead to see if it really is a quantifier or not.
It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd}
where the ddds are digits.
Arguments:
p
cd
Returns:
*/

pointer to the first char after '{'


pointer to char tables block
TRUE or FALSE

static BOOL is_counted_repeat(p, cd)


const uschar *p;
compile_data *cd;
{
if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
if (*p == '}') return TRUE;
if (*p++ != ',') return FALSE;
if (*p == '}') return TRUE;
if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
return (*p == '}');
}

/*************************************************
*
Read repeat counts
*
*************************************************/
/* Read an item of the form {n,m} and return the values. This is called only
after is_counted_repeat() has confirmed that a repeat-count quantifier exists,
so the syntax is guaranteed to be correct, but we need to check the values.
Arguments:
p
minp
maxp
errorptr
cd
Returns:
*/

pointer to first char after '{'


pointer to int for min
pointer to int for max
returned as -1 if no max
points to pointer to error message
pointer to character tables clock
pointer to '}' on success;
current ptr on error, with errorptr set

static const uschar *read_repeat_counts(p, minp, maxp, errorptr, cd)


const uschar *p;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:29 PM

int *minp, *maxp;


const char **errorptr;
compile_data *cd;

{
int min = 0;
int max = -1;

while ((cd->ctypes[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0';


if (*p == '}') max = min; else
{
if (*(++p) != '}')
{
max = 0;
while((cd->ctypes[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0';
if (max < min)
{
*errorptr = ERR4;
return p;
}
}
}
/* Do paranoid checks, then fill in the required variables, and pass back the
pointer to the terminating '}'. */
if (min < 0 || 65535 < min ||
max < -1 || 65535 < max)
*errorptr = ERR5;
else
{
*minp = min;
*maxp = max;
}
return p;
}

/*************************************************
*
Find the fixed length of a pattern
*
*************************************************/
/* Scan a pattern and compute the fixed length of subject that will match it,
if the length is fixed. This is needed for dealing with backward assertions.
Arguments:
code
points to the start of the pattern (the bracket)
options the compiling options
Returns:
*/

the fixed length, or -1 if there is no fixed length

-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:29 PM

static int find_fixedlength(code, options)


uschar *code;
int options;
{
int length = -1;
register int branchlength = 0;
register uschar *cc = code + 3;
/* Scan along the opcodes for this branch. If we get to the end of the
branch, check the length against that of the other branches. */
for (;;)
{
int d;
register int op = *cc;
if (op >= OP_BRA) op = OP_BRA;
switch (op)
{
case OP_BRA:
case OP_ONCE:
case OP_COND:
d = find_fixedlength(cc, options);
if (d < 0) return -1;
branchlength += d;
do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
cc += 3;
break;
/* Reached end of a branch; if it's a ket it is the end of a nested
call. If it's ALT it is an alternation in a nested call. If it is
END it's the end of the outer call. All can be handled by the same code. */
case OP_ALT:
case OP_KET:
case OP_KETRMAX:
case OP_KETRMIN:
case OP_END:
if (length < 0) length = branchlength;
else if (length != branchlength) return -1;
if (*cc != OP_ALT) return length;
cc += 3;
branchlength = 0;
break;
/* Skip over assertive subpatterns */
case OP_ASSERT:
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:29 PM

cc += 3;
break;
/* Skip over things that don't match chars */
case OP_REVERSE:
case OP_BRANUMBER:
case OP_CREF:
cc++;
/* Fall through */
case OP_OPT:
cc++;
/* Fall through */
case OP_SOD:
case OP_EOD:
case OP_EODN:
case OP_CIRC:
case OP_DOLL:
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
cc++;
break;
/* Handle char strings. In UTF-8 mode we must count characters, not bytes.
This requires a scan of the string, unfortunately. We assume valid UTF-8
strings, so all we do is reduce the length by one for byte whose bits are
10xxxxxx. */
case OP_CHARS:
branchlength += *(++cc);
cc += *cc + 1;
break;
/* Handle exact repetitions */
case OP_EXACT:
case OP_TYPEEXACT:
branchlength += (cc[1] << 8) + cc[2];
cc += 4;
break;
/* Handle single-char matchers */
case OP_NOT_DIGIT:
case OP_DIGIT:
case OP_NOT_WHITESPACE:
case OP_WHITESPACE:
case OP_NOT_WORDCHAR:
case OP_WORDCHAR:
case OP_ANY:
branchlength++;
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:29 PM

cc++;
break;
/* Check a class for variable quantification */
case OP_CLASS:
cc += 33;
switch (*cc)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRQUERY:
case OP_CRMINQUERY:
return -1;
case OP_CRRANGE:
case OP_CRMINRANGE:
if ((cc[1] << 8) + cc[2] != (cc[3] << 8) + cc[4]) return -1;
branchlength += (cc[1] << 8) + cc[2];
cc += 5;
break;
default:
branchlength++;
}
break;
/* Anything else is variable length */
default:
return -1;
}

}
/* Control never gets here */
}

/*************************************************
*
Check for POSIX class syntax
*
*************************************************/
/* This function is called when the sequence "[:" or "[." or "[=" is
encountered in a character class. It checks whether this is followed by an
optional ^ and then a sequence of letters, terminated by a matching ":]" or
".]" or "=]".
Argument:
ptr
endptr

pointer to the initial [


where to return the end pointer
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

cd
Returns:
*/

Saturday, June 16, 2012 11:29 PM

pointer to compile data


TRUE or FALSE

static BOOL check_posix_syntax(ptr, endptr, cd)


const uschar *ptr;
const uschar **endptr;
compile_data *cd;
{
int terminator;
/* Don't combine these lines; the Solaris cc */
terminator = *(++ptr);
/* compiler warns about "non-constant" initializer. */
if (*(++ptr) == '^') ptr++;
while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++;
if (*ptr == terminator && ptr[1] == ']')
{
*endptr = ptr;
return TRUE;
}
return FALSE;
}

/*************************************************
*
Check POSIX class name
*
*************************************************/
/* This function is called to check the name given in a POSIX-style class entry
such as [:alnum:].
Arguments:
ptr
len
Returns:
*/

points to the first letter


the length of the name
a value representing the name, or -1 if unknown

static int check_posix_name(ptr, len)


const uschar *ptr;
int len;
{
register int yield = 0;
while (posix_name_lengths[yield] != 0)
{
if (len == posix_name_lengths[yield] &&
strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield;
yield++;
}
return -1;
}

-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:29 PM

/*************************************************
*
Compile one branch
*
*************************************************/
/* Scan the pattern, compiling it into the code vector.
Arguments:
options
brackets
code
ptrptr
errorptr
optchanged
reqchar
countlits
cd
Returns:
*/

the option bits


points to number of extracting brackets used
points to the pointer to the current code point
points to the current pattern pointer
points to pointer to error message
set to the value of the last OP_OPT item compiled
set to the last literal character required, else -1
set to count of mandatory literal characters
contains pointers to tables
TRUE on success
FALSE, with *errorptr set on error

static BOOL compile_branch(options, brackets, codeptr, ptrptr, errorptr,


optchanged, reqchar, countlits, cd)
int options, *brackets;
uschar **codeptr;
const uschar **ptrptr;
const char **errorptr;
int *optchanged, *reqchar, *countlits;
compile_data *cd;
{
int repeat_type, op_type;
int repeat_min, repeat_max;
int bravalue, length;
int greedy_default, greedy_non_default;
int prevreqchar;
int condcount = 0;
int subcountlits = 0;
register int c;
register uschar *code = *codeptr;
uschar *tempcode;
const uschar *ptr = *ptrptr;
const uschar *tempptr;
uschar *previous = NULL;
uschar class[32];
/* Set up the default and non-default settings for greediness */
greedy_default = ((options & PCRE_UNGREEDY) != 0);
greedy_non_default = greedy_default ^ 1;

-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:29 PM

/* Initialize no required char, and count of literals */


*reqchar = prevreqchar = -1;
*countlits = 0;
/* Switch on next character until the end of the branch */
for (;; ptr++)
{
BOOL negate_class;
int class_charcount;
int class_lastchar;
int newoptions;
int skipbytes;
int subreqchar;
c = *ptr;
if ((options & PCRE_EXTENDED) != 0)
{
if ((cd->ctypes[c] & ctype_space) != 0) continue;
if (c == '#')
{
/* The space before the ; is to avoid a warning on a silly compiler
on the Macintosh. */
while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
continue;
}
}
switch(c)
{
/* The branch terminates at end of string, |, or ). */
case 0:
case '|':
case ')':
*codeptr = code;
*ptrptr = ptr;
return TRUE;
/* Handle single-character metacharacters */
case '^':
previous = NULL;
*code++ = OP_CIRC;
break;
case '$':
previous = NULL;
*code++ = OP_DOLL;
break;
case '.':
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:29 PM

previous = code;
*code++ = OP_ANY;
break;
/* Character classes. These always build a 32-byte bitmap of the permitted
characters, except in the special case where there is only one character.
For negated classes, we build the map as usual, then invert it at the end.
*/
case '[':
previous = code;
*code++ = OP_CLASS;
/* If the first character is '^', set the negation flag and skip it. */
if ((c = *(++ptr)) == '^')
{
negate_class = TRUE;
c = *(++ptr);
}
else negate_class = FALSE;
/* Keep a count of chars so that we can optimize the case of just a single
character. */
class_charcount = 0;
class_lastchar = -1;
/* Initialize the 32-char bit map to all zeros. We have to build the
map in a temporary bit of store, in case the class contains only 1
character, because in that case the compiled code doesn't use the
bit map. */
memset(class, 0, 32 * sizeof(uschar));
/* Process characters until ] is reached. By writing this as a "do" it
means that an initial ] is taken as a data character. */
do

{
if (c == 0)
{
*errorptr = ERR6;
goto FAILED;
}

/* Handle POSIX class names. Perl allows a negation extension of the


form [:^name]. A square bracket that doesn't match the syntax is
treated as a literal. We also recognize the POSIX constructions
[.ch.] and [=ch=] ("collating elements") and fault them, as Perl
5.6 does. */
if (c == '[' &&
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

Saturday, June 16, 2012 11:29 PM

(ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&


check_posix_syntax(ptr, &tempptr, cd))

{
BOOL local_negate = FALSE;
int posix_class, i;
register const uschar *cbits = cd->cbits;
if (ptr[1] != ':')
{
*errorptr = ERR31;
goto FAILED;
}
ptr += 2;
if (*ptr == '^')
{
local_negate = TRUE;
ptr++;
}

posix_class = check_posix_name(ptr, tempptr - ptr);


if (posix_class < 0)
{
*errorptr = ERR30;
goto FAILED;
}
/* If matching is caseless, upper and lower are converted to
alpha. This relies on the fact that the class table starts with
alpha, lower, upper as the first 3 entries. */
if ((options & PCRE_CASELESS) != 0 && posix_class <= 2)
posix_class = 0;
/* Or into the map we are building up to 3 of the static class
tables, or their negations. */
posix_class *= 3;
for (i = 0; i < 3; i++)
{
int taboffset = posix_class_maps[posix_class + i];
if (taboffset < 0) break;
if (local_negate)
for (c = 0; c < 32; c++) class[c] |= ~cbits[c+taboffset];
else
for (c = 0; c < 32; c++) class[c] |= cbits[c+taboffset];
}
ptr = tempptr + 1;
class_charcount = 10;
continue;
}

/* Set > 1; assumes more than 1 per class */

-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

Saturday, June 16, 2012 11:29 PM

/* Backslash may introduce a single character, or it may introduce one


of the specials, which just set a flag. Escaped items are checked for
validity in the pre-compiling pass. The sequence \b is a special case.
Inside a class (and only there) it is treated as backspace. Elsewhere
it marks a word boundary. Other escapes have preset maps ready to
or into the one we are building. We assume they have more than one
character in them, so set class_count bigger than one. */
if (c == '\\')
{
c = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
if (-c == ESC_b) c = '\b';
else if (c < 0)
{
register const uschar *cbits = cd->cbits;
class_charcount = 10;
switch (-c)
{
case ESC_d:
for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit];
continue;
case ESC_D:
for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit];
continue;
case ESC_w:
for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_word];
continue;
case ESC_W:
for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_word];
continue;
case ESC_s:
for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space];
continue;
case ESC_S:
for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space];
continue;

default:
*errorptr = ERR7;
goto FAILED;
}

/* Fall through if single character, but don't at present allow


chars > 255 in UTF-8 mode. */
}

-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219

Saturday, June 16, 2012 11:29 PM

/* A single character may be followed by '-' to form a range. However,


Perl does not permit ']' to be the end of the range. A '-' character
here is treated as a literal. */
if (ptr[1] == '-' && ptr[2] != ']')
{
int d;
ptr += 2;
d = *ptr;
if (d == 0)
{
*errorptr = ERR6;
goto FAILED;
}
/* The second part of a range can be a single-character escape, but
not any of the other escapes. Perl 5.6 treats a hyphen as a literal
in such circumstances. */
if (d == '\\')
{
const uschar *oldptr = ptr;
d = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
/* \b is backslash; any other special means the '-' was literal */
if (d < 0)
{
if (d == -ESC_b) d = '\b'; else
{
ptr = oldptr - 2;
goto SINGLE_CHARACTER; /* A few lines below */
}
}
}
if (d < c)
{
*errorptr = ERR8;
goto FAILED;
}
for (; c <= d; c++)
{
class[c/8] |= (1 << (c&7));
if ((options & PCRE_CASELESS) != 0)
{
int uc = cd->fcc[c];
/* flip case */
class[uc/8] |= (1 << (uc&7));
}
class_charcount++;
/* in case a one-char range */
class_lastchar = c;
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272

}
continue;
}

Saturday, June 16, 2012 11:29 PM

/* Go get the next char in the class */

/* Handle a lone single character - we can get here for a normal


non-escape char, or after \ that introduces a single character. */
SINGLE_CHARACTER:
class [c/8] |= (1 << (c&7));
if ((options & PCRE_CASELESS) != 0)
{
c = cd->fcc[c];
/* flip case */
class[c/8] |= (1 << (c&7));
}
class_charcount++;
class_lastchar = c;
}
/* Loop until ']' reached; the check for end of string happens inside the
loop. This "while" is the end of the "do" above. */
while ((c = *(++ptr)) != ']');
/* If class_charcount is 1 and class_lastchar is not negative, we saw
precisely one character. This doesn't need the whole 32-byte bit map.
We turn it into a 1-character OP_CHAR if it's positive, or OP_NOT if
it's negative. */
if (class_charcount == 1 && class_lastchar >= 0)
{
if (negate_class)
{
code[-1] = OP_NOT;
}
else
{
code[-1] = OP_CHARS;
*code++ = 1;
}
*code++ = class_lastchar;
}
/* Otherwise, negate the 32-byte map if necessary, and copy it into
the code vector. */
else
{
if (negate_class)
for (c = 0; c < 32; c++) code[c] = ~class[c];
else
memcpy(code, class, 32);
code += 32;
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325

Saturday, June 16, 2012 11:29 PM

}
break;
/* Various kinds of repeat */
case '{':
if (!is_counted_repeat(ptr+1, cd)) goto NORMAL_CHAR;
ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr, cd);
if (*errorptr != NULL) goto FAILED;
goto REPEAT;
case '*':
repeat_min = 0;
repeat_max = -1;
goto REPEAT;
case '+':
repeat_min = 1;
repeat_max = -1;
goto REPEAT;
case '?':
repeat_min = 0;
repeat_max = 1;
REPEAT:
if (previous == NULL)
{
*errorptr = ERR9;
goto FAILED;
}
/* If the next character is '?' this is a minimizing repeat, by default,
but if PCRE_UNGREEDY is set, it works the other way round. Advance to the
next character. */
if (ptr[1] == '?')
{ repeat_type = greedy_non_default; ptr++; }
else repeat_type = greedy_default;
/* If previous was a string of characters, chop off
as the subject of the repeat. If there was only one
abolish the previous item altogether. A repeat with
out any reqchar setting, backing up to the previous
adjust the countlits value. */
if (*previous == OP_CHARS)
{
int len = previous[1];
if (repeat_min == 0) *reqchar = prevreqchar;
*countlits += repeat_min - 1;

-25-

the last one and use it


character, we can
a zero minimum wipes
value. We must also

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378

if (len == 1)
{
c = previous[2];
code = previous;
}
else
{
c = previous[len+1];
previous[1]--;
code--;
}
op_type = 0;
goto OUTPUT_SINGLE_REPEAT;
}

Saturday, June 16, 2012 11:29 PM

/* Use single-char op codes */


/* Code shared with single character types */

/* If previous was a single negated character ([^a] or similar), we use


one of the special opcodes, replacing it. The code is shared with singlecharacter repeats by adding a suitable offset into repeat_type. */
else if ((int)*previous == OP_NOT)
{
op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */
c = previous[1];
code = previous;
goto OUTPUT_SINGLE_REPEAT;
}
/* If previous was a character type match (\d or similar), abolish it and
create a suitable repeat item. The code is shared with single-character
repeats by adding a suitable offset into repeat_type. */
else if ((int)*previous < OP_EODN || *previous == OP_ANY)
{
op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
c = *previous;
code = previous;
OUTPUT_SINGLE_REPEAT:
/* If the maximum is zero then the minimum must also be zero; Perl allows
this case, so we do too - by simply omitting the item altogether. */
if (repeat_max == 0) goto END_REPEAT;
/* Combine the op_type with the repeat_type */
repeat_type += op_type;
/* A minimum of zero is handled either as the special case * or ?, or as
an UPTO, with the maximum given. */
if (repeat_min == 0)
{
-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431

Saturday, June 16, 2012 11:29 PM

if (repeat_max == -1) *code++ = OP_STAR + repeat_type;


else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
else
{
*code++ = OP_UPTO + repeat_type;
*code++ = repeat_max >> 8;
*code++ = (repeat_max & 255);
}
}
/* The case {1,} is handled as the special case + */
else if (repeat_min == 1 && repeat_max == -1)
*code++ = OP_PLUS + repeat_type;
/* The case {n,n} is just an EXACT, while the general case {n,m} is
handled as an EXACT followed by an UPTO. An EXACT of 1 is optimized. */
else
{
if (repeat_min != 1)
{
*code++ = OP_EXACT + op_type;
*code++ = repeat_min >> 8;
*code++ = (repeat_min & 255);
}

/* NB EXACT doesn't have repeat_type */

/* If the mininum is 1 and the previous item was a character string,


we either have to put back the item that got cancelled if the string
length was 1, or add the character back onto the end of a longer
string. For a character type nothing need be done; it will just get
put back naturally. Note that the final character is always going to
get added below. */
else if (*previous == OP_CHARS)
{
if (code == previous) code += 2; else previous[1]++;
}
/* For a single negated character we also have to put back the
item that got cancelled. */
else if (*previous == OP_NOT) code++;
/* If the maximum is unlimited, insert an OP_STAR. */
if (repeat_max < 0)
{
*code++ = c;
*code++ = OP_STAR + repeat_type;
}
/* Else insert an UPTO if the max is greater than the min. */
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

Saturday, June 16, 2012 11:29 PM

else if (repeat_max != repeat_min)


{
*code++ = c;
repeat_max -= repeat_min;
*code++ = OP_UPTO + repeat_type;
*code++ = repeat_max >> 8;
*code++ = (repeat_max & 255);
}
}
/* The character or character type itself comes last in all cases. */
*code++ = c;
}
/* If previous was a character class or a back reference, we put the repeat
stuff after it, but just skip the item if the repeat was {0,0}. */
else if (*previous == OP_CLASS || *previous == OP_REF)
{
if (repeat_max == 0)
{
code = previous;
goto END_REPEAT;
}
if (repeat_min == 0 && repeat_max == -1)
*code++ = OP_CRSTAR + repeat_type;
else if (repeat_min == 1 && repeat_max == -1)
*code++ = OP_CRPLUS + repeat_type;
else if (repeat_min == 0 && repeat_max == 1)
*code++ = OP_CRQUERY + repeat_type;
else
{
*code++ = OP_CRRANGE + repeat_type;
*code++ = repeat_min >> 8;
*code++ = repeat_min & 255;
if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */
*code++ = repeat_max >> 8;
*code++ = repeat_max & 255;
}
}
/* If previous was a bracket group, we may have to replicate it in certain
cases. */
else if ((int)*previous >= OP_BRA || (int)*previous == OP_ONCE ||
(int)*previous == OP_COND)
{
register int i;
int ketoffset = 0;
int len = code - previous;
uschar *bralink = NULL;
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537

Saturday, June 16, 2012 11:29 PM

/* If the maximum repeat count is unlimited, find the end of the bracket
by scanning through from the start, and compute the offset back to it
from the current code pointer. There may be an OP_OPT setting following
the final KET, so we can't find the end just by going back from the code
pointer. */
if (repeat_max == -1)
{
register uschar *ket = previous;
do ket += (ket[1] << 8) + ket[2]; while (*ket != OP_KET);
ketoffset = code - ket;
}
/* The case of a zero minimum is special because of the need to stick
OP_BRAZERO in front of it, and because the group appears once in the
data, whereas in other cases it appears the minimum number of times. For
this reason, it is simplest to treat this case separately, as otherwise
the code gets far too messy. There are several special subcases when the
minimum is zero. */
if (repeat_min == 0)
{
/* If we set up a required char from the bracket, we must back off
to the previous value and reset the countlits value too. */
if (subcountlits > 0)
{
*reqchar = prevreqchar;
*countlits -= subcountlits;
}
/* If the maximum is also zero, we just omit the group from the output
altogether. */
if (repeat_max == 0)
{
code = previous;
goto END_REPEAT;
}
/* If the maximum is 1 or unlimited, we just have to stick in the
BRAZERO and do no more at this point. */
if (repeat_max <= 1)
{
memmove(previous+1, previous, len);
code++;
*previous++ = OP_BRAZERO + repeat_type;
}
/* If the maximum is greater than 1 and limited, we have to replicate
in a nested fashion, sticking OP_BRAZERO before each set of brackets.
-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590

Saturday, June 16, 2012 11:29 PM

The first one has to be handled carefully because it's the original
copy, which has to be moved up. The remainder can be handled by code
that is common with the non-zero minimum case below. We just have to
adjust the value or repeat_max, since one less copy is required. */
else
{
int offset;
memmove(previous+4, previous, len);
code += 4;
*previous++ = OP_BRAZERO + repeat_type;
*previous++ = OP_BRA;
/* We chain together the bracket offset fields that have to be
filled in later when the ends of the brackets are reached. */
offset = (bralink == NULL)? 0 : previous - bralink;
bralink = previous;
*previous++ = offset >> 8;
*previous++ = offset & 255;
}
repeat_max--;
}
/* If the minimum is greater than zero, replicate the group as many
times as necessary, and adjust the maximum to the number of subsequent
copies that we need. */
else
{
for (i = 1; i < repeat_min; i++)
{
memcpy(code, previous, len);
code += len;
}
if (repeat_max > 0) repeat_max -= repeat_min;
}
/* This code is common to both the zero and non-zero minimum cases. If
the maximum is limited, it replicates the group in a nested fashion,
remembering the bracket starts on a stack. In the case of a zero minimum,
the first one was set up above. In all cases the repeat_max now specifies
the number of additional copies needed. */
if (repeat_max >= 0)
{
for (i = repeat_max - 1; i >= 0; i--)
{
*code++ = OP_BRAZERO + repeat_type;
/* All but the final copy start a new nesting, maintaining the
chain of brackets outstanding. */
-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643

Saturday, June 16, 2012 11:29 PM

if (i != 0)
{
int offset;
*code++ = OP_BRA;
offset = (bralink == NULL)? 0 : code - bralink;
bralink = code;
*code++ = offset >> 8;
*code++ = offset & 255;
}
memcpy(code, previous, len);
code += len;
}
/* Now chain through the pending brackets, and fill in their length
fields (which are holding the chain links pro tem). */
while (bralink != NULL)
{
int oldlinkoffset;
int offset = code - bralink + 1;
uschar *bra = code - offset;
oldlinkoffset = (bra[1] << 8) + bra[2];
bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
*code++ = OP_KET;
*code++ = bra[1] = offset >> 8;
*code++ = bra[2] = (offset & 255);
}
}
/* If the maximum is unlimited, set a repeater in the final copy. We
can't just offset backwards from the current code point, because we
don't know if there's been an options resetting after the ket. The
correct offset was computed above. */
else code[-ketoffset] = OP_KETRMAX + repeat_type;
}
/* Else there's some kind of shambles */
else
{
*errorptr = ERR11;
goto FAILED;
}
/* In all case we no longer have a previous item. */
END_REPEAT:
previous = NULL;
break;

-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696

Saturday, June 16, 2012 11:29 PM

/* Start of nested bracket sub-expression, or comment or lookahead or


lookbehind or option setting or condition. First deal with special things
that can come after a bracket; all are introduced by ?, and the appearance
of any of them means that this is not a referencing group. They were
checked for validity in the first pass over the string, so we don't have to
check for syntax errors here. */
case '(':
newoptions = options;
skipbytes = 0;
if (*(++ptr) == '?')
{
int set, unset;
int *optset;
switch (*(++ptr))
{
case '#':
/* Comment; skip to ket */
ptr++;
while (*ptr != ')') ptr++;
continue;
case ':':
bravalue = OP_BRA;
ptr++;
break;

/* Non-extracting bracket */

case '(':
bravalue = OP_COND;
/* Conditional group */
if ((cd->ctypes[*(++ptr)] & ctype_digit) != 0)
{
int condref = *ptr - '0';
while (*(++ptr) != ')') condref = condref*10 + *ptr - '0';
if (condref == 0)
{
*errorptr = ERR35;
goto FAILED;
}
ptr++;
code[3] = OP_CREF;
code[4] = condref >> 8;
code[5] = condref & 255;
skipbytes = 3;
}
else ptr--;
break;
case '=':
bravalue = OP_ASSERT;
ptr++;
break;

/* Positive lookahead */

-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

Saturday, June 16, 2012 11:29 PM

case '!':
/* Negative lookahead */
bravalue = OP_ASSERT_NOT;
ptr++;
break;
case '<':
/* Lookbehinds */
switch (*(++ptr))
{
case '=':
/* Positive lookbehind */
bravalue = OP_ASSERTBACK;
ptr++;
break;
case '!':
/* Negative lookbehind */
bravalue = OP_ASSERTBACK_NOT;
ptr++;
break;
default:
*errorptr = ERR24;
goto FAILED;
}
break;

/* Syntax error */

case '>':
bravalue = OP_ONCE;
ptr++;
break;

/* One-time brackets */

case 'R':
*code++ = OP_RECURSE;
ptr++;
continue;

/* Pattern recursion */

default:
set = unset = 0;
optset = &set;

/* Option setting */

while (*ptr != ')' && *ptr != ':')


{
switch (*ptr++)
{
case '-': optset = &unset; break;
case
case
case
case
case
case

'i':
'm':
's':
'x':
'U':
'X':

*optset
*optset
*optset
*optset
*optset
*optset

|=
|=
|=
|=
|=
|=

PCRE_CASELESS; break;
PCRE_MULTILINE; break;
PCRE_DOTALL; break;
PCRE_EXTENDED; break;
PCRE_UNGREEDY; break;
PCRE_EXTRA; break;

default:
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

Saturday, June 16, 2012 11:29 PM

*errorptr = ERR12;
goto FAILED;
}

/* Set up the changed option bits, but don't change anything yet. */
newoptions = (options | set) & (~unset);
/* If the options ended with ')' this is not the start of a nested
group with option changes, so the options change at this level. At top
level there is nothing else to be done (the options will in fact have
been set from the start of compiling as a result of the first pass) but
at an inner level we must compile code to change the ims options if
necessary, and pass the new setting back so that it can be put at the
start of any following branches, and when this group ends, a resetting
item can be compiled. */
if (*ptr == ')')
{
if ((options & PCRE_INGROUP) != 0 &&
(options & PCRE_IMS) != (newoptions & PCRE_IMS))
{
*code++ = OP_OPT;
*code++ = *optchanged = newoptions & PCRE_IMS;
}
options = newoptions; /* Change options at this level */
previous = NULL;
/* This item can't be repeated */
continue;
/* It is complete */
}
/* If the options ended with ':' we are heading into a nested group
with possible change of options. Such groups are non-capturing and are
not assertions of any kind. All we need to do is skip over the ':';
the newoptions value is handled below. */

bravalue = OP_BRA;
ptr++;
}

/* Else we have a referencing group; adjust the opcode. If the bracket


number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and
arrange for the true number to follow later, in an OP_BRANUMBER item. */
else
{
if (++(*brackets) > EXTRACT_BASIC_MAX)
{
bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1;
code[3] = OP_BRANUMBER;
code[4] = *brackets >> 8;
code[5] = *brackets & 255;
-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

Saturday, June 16, 2012 11:29 PM

skipbytes = 3;
}
else bravalue = OP_BRA + *brackets;
}
/* Process nested bracketed re. Assertions may not be repeated, but other
kinds can be. We copy code into a non-register variable in order to be able
to pass its address because some compilers complain otherwise. Pass in a
new setting for the ims options if they have changed. */
previous = (bravalue >= OP_ONCE)? code : NULL;
*code = bravalue;
tempcode = code;
if (!compile_regex(
options | PCRE_INGROUP,
/* Set for all nested groups */
((options & PCRE_IMS) != (newoptions & PCRE_IMS))?
newoptions & PCRE_IMS : -1, /* Pass ims options if changed */
brackets,
/* Extracting bracket count */
&tempcode,
/* Where to put code (updated) */
&ptr,
/* Input pointer (updated) */
errorptr,
/* Where to put an error message */
(bravalue == OP_ASSERTBACK ||
bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
skipbytes,
/* Skip over OP_COND/OP_BRANUMBER */
&subreqchar,
/* For possible last char */
&subcountlits,
/* For literal count */
cd))
/* Tables block */
goto FAILED;
/* At the end of compiling, code is still pointing to the start of the
group, while tempcode has been updated to point past the end of the group
and any option resetting that may follow it. The pattern pointer (ptr)
is on the bracket. */
/* If this is a conditional bracket, check that there are no more than
two branches in the group. */
else if (bravalue == OP_COND)
{
uschar *tc = code;
condcount = 0;
do {
condcount++;
tc += (tc[1] << 8) | tc[2];
}
while (*tc != OP_KET);
if (condcount > 2)
{
*errorptr = ERR27;
goto FAILED;
-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908

Saturday, June 16, 2012 11:29 PM

/* Handle updating of the required character. If the subpattern didn't


set one, leave it as it was. Otherwise, update it for normal brackets of
all kinds, forward assertions, and conditions with two branches. Don't
update the literal count for forward assertions, however. If the bracket
is followed by a quantifier with zero repeat, we have to back off. Hence
the definition of prevreqchar and subcountlits outside the main loop so
that they can be accessed for the back off. */
if (subreqchar > 0 &&
(bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_ASSERT ||
(bravalue == OP_COND && condcount == 2)))
{
prevreqchar = *reqchar;
*reqchar = subreqchar;
if (bravalue != OP_ASSERT) *countlits += subcountlits;
}
/* Now update the main code pointer to the end of the group. */
code = tempcode;
/* Error if hit end of pattern */
if (*ptr != ')')
{
*errorptr = ERR14;
goto FAILED;
}
break;
/* Check \ for being a real metacharacter; if not, fall through and handle
it as a data character at the start of a string. Escape items are checked
for validity in the pre-compiling pass. */
case '\\':
tempptr = ptr;
c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
/* Handle metacharacters introduced by \. For ones like \d, the ESC_ values
are arranged to be the negation of the corresponding OP_values. For the
back references, the values are ESC_REF plus the reference number. Only
back references and those types that consume a character may be repeated.
We can test for values between ESC_b and ESC_Z for the latter; this may
have to change if any new ones are ever created. */
if (c < 0)
{
if (-c >= ESC_REF)
{
int number = -c - ESC_REF;
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961

Saturday, June 16, 2012 11:29 PM

previous = code;
*code++ = OP_REF;
*code++ = number >> 8;
*code++ = number & 255;
}
else
{
previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
*code++ = -c;
}
continue;
}
/* Data character: reset and fall through */
ptr = tempptr;
c = '\\';
/* Handle a run of data characters until a metacharacter is encountered.
The first character is guaranteed not to be whitespace or # when the
extended flag is set. */
NORMAL_CHAR:
default:
previous = code;
*code = OP_CHARS;
code += 2;
length = 0;
do

{
if ((options & PCRE_EXTENDED) != 0)
{
if ((cd->ctypes[c] & ctype_space) != 0) continue;
if (c == '#')
{
/* The space before the ; is to avoid a warning on a silly compiler
on the Macintosh. */
while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
if (c == 0) break;
continue;
}
}

/* Backslash may introduce a data char or a metacharacter. Escaped items


are checked for validity in the pre-compiling pass. Stop the string
before a metaitem. */
if (c == '\\')
{
tempptr = ptr;
c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
if (c < 0) { ptr = tempptr; break; }
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014

Saturday, June 16, 2012 11:29 PM

/* If a character is > 127 in UTF-8 mode, we have to turn it into


two or more characters in the UTF-8 encoding. */
}
/* Ordinary character or single-char escape */
*code++ = c;
length++;
}
/* This "while" is the end of the "do" above. */
while (length < MAXLIT && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0);
/* Update the last character and the count of literals */
prevreqchar = (length > 1)? code[-2] : *reqchar;
*reqchar = code[-1];
*countlits += length;
/* Compute the length and set it in the data vector, and advance to
the next state. */
previous[1] = length;
if (length < MAXLIT) ptr--;
break;
}
}
/* end of big loop */
/* Control never reaches here by falling through, only by a goto for all the
error states. Pass back the position in the pattern so that it can be displayed
to the user for diagnosing the error. */
FAILED:
*ptrptr = ptr;
return FALSE;
}

/*************************************************
*
Compile sequence of alternatives
*
*************************************************/
/* On entry, ptr is pointing past the bracket character, but on return
it points to the closing bracket, or vertical bar, or end of string.
The code variable is pointing at the byte into which the BRA operator has been
stored. If the ims options are changed at the start (for a (?ims: group) or
during any branch, we need to insert an OP_OPT item at the start of every
following branch to ensure they get set correctly at run time, and also pass
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067

Saturday, June 16, 2012 11:29 PM

the new options into every subsequent branch compile.


Argument:
options
optchanged
brackets
codeptr
ptrptr
errorptr
lookbehind
skipbytes
reqchar
countlits
cd
Returns:
*/

the option bits


new ims options to set as if (?ims) were at the start, or -1
for no change
-> int containing the number of extracting brackets used
-> the address of the current code pointer
-> the address of the current pattern pointer
-> pointer to error message
TRUE if this is a lookbehind assertion
skip this many bytes at start (for OP_COND, OP_BRANUMBER)
-> place to put the last required character, or a negative number
-> place to put the shortest literal count of any branch
points to the data block with tables pointers
TRUE on success

static BOOL compile_regex(options, optchanged, brackets, codeptr, ptrptr,


errorptr, lookbehind, skipbytes, reqchar,
countlits, cd)
int options, optchanged, *brackets;
uschar **codeptr;
const uschar **ptrptr;
const char **errorptr;
BOOL lookbehind;
int skipbytes;
int *reqchar, *countlits;
compile_data *cd;
{
const uschar *ptr = *ptrptr;
uschar *code = *codeptr;
uschar *last_branch = code;
uschar *start_bracket = code;
uschar *reverse_count = NULL;
int oldoptions = options & PCRE_IMS;
int branchreqchar, branchcountlits;
*reqchar = -1;
*countlits = INT_MAX;
code += 3 + skipbytes;
/* Loop for each alternative branch */
for (;;)
{
int length;
/* Handle change of options */
if (optchanged >= 0)
{
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120

Saturday, June 16, 2012 11:29 PM

*code++ = OP_OPT;
*code++ = optchanged;
options = (options & ~PCRE_IMS) | optchanged;
}
/* Set up dummy OP_REVERSE if lookbehind assertion */
if (lookbehind)
{
*code++ = OP_REVERSE;
reverse_count = code;
*code++ = 0;
*code++ = 0;
}
/* Now compile the branch */
if (!compile_branch(options, brackets, &code, &ptr, errorptr, &optchanged,
&branchreqchar, &branchcountlits, cd))
{
*ptrptr = ptr;
return FALSE;
}
/* Fill in the length of the last branch */
length = code - last_branch;
last_branch[1] = length >> 8;
last_branch[2] = length & 255;
/* Save the last required character if all branches have the same; a current
value of -1 means unset, while -2 means "previous branch had no last required
char". */
if (*reqchar != -2)
{
if (branchreqchar >= 0)
{
if (*reqchar == -1) *reqchar = branchreqchar;
else if (*reqchar != branchreqchar) *reqchar = -2;
}
else *reqchar = -2;
}
/* Keep the shortest literal count */
if (branchcountlits < *countlits) *countlits = branchcountlits;
DPRINTF(("literal count = %d min=%d\n" , branchcountlits, *countlits));
/* If lookbehind, check that this branch matches a fixed-length string,
and put the length into the OP_REVERSE item. Temporarily mark the end of
the branch with OP_END. */

-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173

Saturday, June 16, 2012 11:29 PM

if (lookbehind)
{
*code = OP_END;
length = find_fixedlength(last_branch, options);
DPRINTF(("fixed length = %d\n", length));
if (length < 0)
{
*errorptr = ERR25;
*ptrptr = ptr;
return FALSE;
}
reverse_count[0] = (length >> 8);
reverse_count[1] = length & 255;
}
/* Reached end of expression, either ')' or end of pattern. Insert a
terminating ket and the length of the whole bracketed item, and return,
leaving the pointer at the terminating char. If any of the ims options
were changed inside the group, compile a resetting op-code following. */
if (*ptr != '|')
{
length = code - start_bracket;
*code++ = OP_KET;
*code++ = length >> 8;
*code++ = length & 255;
if (optchanged >= 0)
{
*code++ = OP_OPT;
*code++ = oldoptions;
}
*codeptr = code;
*ptrptr = ptr;
return TRUE;
}
/* Another branch follows; insert an "or" node and advance the pointer. */
*code = OP_ALT;
last_branch = code;
code += 3;
ptr++;
}
/* Control never reaches here */
}

/*************************************************
*
Find first significant op code
*
*************************************************/

-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226

Saturday, June 16, 2012 11:29 PM

/* This is called by several functions that scan a compiled expression looking


for a fixed first character, or an anchoring op code etc. It skips over things
that do not influence this. For one application, a change of caseless option is
important.
Arguments:
code
options
optbit
optstop
Returns:
*/

pointer to the start of the group


pointer to external options
the option bit whose changing is significant, or
zero if none are
TRUE to return on option change, otherwise change the options
value and continue
pointer to the first significant opcode

static const uschar *first_significant_code(code, options, optbit, optstop)


const uschar *code;
int *options, optbit;
BOOL optstop;
{
for (;;)
{
switch ((int)*code)
{
case OP_OPT:
if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit))
{
if (optstop) return code;
*options = (int)code[1];
}
code += 2;
break;
case OP_CREF:
case OP_BRANUMBER:
code += 3;
break;
case OP_WORD_BOUNDARY:
case OP_NOT_WORD_BOUNDARY:
code++;
break;
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
do code += (code[1] << 8) + code[2]; while (*code == OP_ALT);
code += 3;
break;
default:
return code;
-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279

Saturday, June 16, 2012 11:29 PM

}
}
/* Control never reaches here */
}

/*************************************************
*
Check for anchored expression
*
*************************************************/
/* Try to find out if this is an anchored regular expression. Consider each
alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket
all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then
it's anchored. However, if this is a multiline pattern, then only OP_SOD
counts, since OP_CIRC can match in the middle.
A branch is also implicitly anchored if it starts with .* and DOTALL is set,
because that will try the rest of the pattern at all possible matching points,
so there is no point trying them again.
Arguments:
code
options
Returns:
*/

points to start of expression (the bracket)


points to the options setting
TRUE or FALSE

static BOOL is_anchored(code, options)


register const uschar *code;
int *options;
{
do {
const uschar *scode = first_significant_code(code + 3, options,
PCRE_MULTILINE, FALSE);
register int op = *scode;
if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
{ if (!is_anchored(scode, options)) return FALSE; }
else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) &&
(*options & PCRE_DOTALL) != 0)
{ if (scode[1] != OP_ANY) return FALSE; }
else if (op != OP_SOD &&
((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC))
return FALSE;
code += (code[1] << 8) + code[2];
}
while (*code == OP_ALT);
return TRUE;
}

-43-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332

Saturday, June 16, 2012 11:29 PM

/*************************************************
*
Check for starting with ^ or .*
*
*************************************************/
/* This is called to find out if every branch starts with ^ or .* so that
"first char" processing can be done to speed things up in multiline
matching and for non-DOTALL patterns that start with .* (which must start at
the beginning or after \n).
Argument:
Returns:
*/

points to start of expression (the bracket)


TRUE or FALSE

static BOOL is_startline(code)


const uschar *code;
{
do {
const uschar *scode = first_significant_code(code + 3, NULL, 0, FALSE);
register int op = *scode;
if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
{ if (!is_startline(scode)) return FALSE; }
else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR)
{ if (scode[1] != OP_ANY) return FALSE; }
else if (op != OP_CIRC) return FALSE;
code += (code[1] << 8) + code[2];
}
while (*code == OP_ALT);
return TRUE;
}

/*************************************************
*
Check for fixed first char
*
*************************************************/
/* Try to find out if there is a fixed first character. This is called for
unanchored expressions, as it speeds up their processing quite considerably.
Consider each alternative branch. If they all start with the same char, or with
a bracket all of whose alternatives start with the same char (recurse ad lib),
then we return that char, otherwise -1.
Arguments:
code
options
Returns:
*/

points to start of expression (the bracket)


pointer to the options (used to check casing changes)
-1 or the fixed first char

static int find_firstchar(code, options)


const uschar *code;
int *options;
{
-44-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

Saturday, June 16, 2012 11:29 PM

register int c = -1;


do {
int d;
const uschar *scode = first_significant_code(code + 3, options,
PCRE_CASELESS, TRUE);
register int op = *scode;
if (op >= OP_BRA) op = OP_BRA;
switch(op)
{
default:
return -1;
case OP_BRA:
case OP_ASSERT:
case OP_ONCE:
case OP_COND:
if ((d = find_firstchar(scode, options)) < 0) return -1;
if (c < 0) c = d; else if (c != d) return -1;
break;
case OP_EXACT:
scode++;

/* Fall through */

case OP_CHARS:
scode++;

/* Fall through */

case OP_PLUS:
case OP_MINPLUS:
if (c < 0) c = scode[1]; else if (c != scode[1]) return -1;
break;
}
code += (code[1] << 8) + code[2];
}
while (*code == OP_ALT);
return c;
}

/*************************************************
*
Compile a Regular Expression
*
*************************************************/
/* This function takes a string and returns a pointer to a block of store
holding a compiled version of the expression.
Arguments:
pattern

the regular expression


-45-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438

options
errorptr
erroroffset
tables
Returns:
*/

Saturday, June 16, 2012 11:29 PM

various option bits


pointer to pointer to error text
ptr offset in pattern where error was detected
pointer to character tables or NULL
pointer to compiled data block, or NULL on error,
with errorptr and erroroffset set

pcre *pcre_compile(pattern, options, errorptr, erroroffset, tables)


const char *pattern;
int options;
const char **errorptr;
int *erroroffset;
const unsigned char *tables;
{
real_pcre *re;
int length = 3;
/* For initial BRA plus length */
int runlength;
int c, reqchar, countlits;
int bracount = 0;
int top_backref = 0;
int branch_extra = 0;
int branch_newextra;
unsigned int brastackptr = 0;
size_t size;
uschar *code;
const uschar *ptr;
compile_data compile_block;
int brastack[BRASTACK_SIZE];
uschar bralenstack[BRASTACK_SIZE];
#ifdef PCRE_DEBUG
uschar *code_base, *code_end;
#endif
/* Can't support UTF8 unless PCRE has been compiled to include the code. */
if ((options & PCRE_UTF8) != 0)
{
*errorptr = ERR32;
return NULL;
}
/* We can't pass back an error message if errorptr is NULL; I guess the best we
can do is just return NULL. */
if (errorptr == NULL) return NULL;
*errorptr = NULL;
/* However, we can give a message for this error */
if (erroroffset == NULL)
-46-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491

Saturday, June 16, 2012 11:29 PM

{
*errorptr = ERR16;
return NULL;
}
*erroroffset = 0;
if ((options & ~PUBLIC_OPTIONS) != 0)
{
*errorptr = ERR17;
return NULL;
}
/* Set up pointers to the individual character tables */
if (tables == NULL) tables = pcre_default_tables;
compile_block.lcc = tables + lcc_offset;
compile_block.fcc = tables + fcc_offset;
compile_block.cbits = tables + cbits_offset;
compile_block.ctypes = tables + ctypes_offset;
/* Reflect pattern for debugging output */
DPRINTF(("------------------------------------------------------------------\n" ));
DPRINTF(("%s\n", pattern));
/* The first thing to do is to make a pass over the pattern to compute the
amount of store required to hold the compiled code. This does not have to be
perfect as long as errors are overestimates. At the same time we can detect any
internal flag settings. Make an attempt to correct for any counted white space
if an "extended" flag setting appears late in the pattern. We can't be so
clever for #-comments. */
ptr =
while
{
int
int
int

(const uschar *)(pattern - 1);


((c = *(++ptr)) != 0)
min, max;
class_charcount;
bracket_length;

if ((options & PCRE_EXTENDED) != 0)


{
if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
if (c == '#')
{
/* The space before the ; is to avoid a warning on a silly compiler
on the Macintosh. */
while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
continue;
}
}
switch(c)
{
-47-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544

Saturday, June 16, 2012 11:29 PM

/* A backslashed item may be an escaped "normal" character or a


character type. For a "normal" character, put the pointers and
character back so that tests for whitespace etc. in the input
are done correctly. */
case '\\':
{
const uschar *save_ptr = ptr;
c = check_escape(&ptr, errorptr, bracount, options, FALSE, &compile_block);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
if (c >= 0)
{
ptr = save_ptr;
c = '\\';
goto NORMAL_CHAR;
}
}
length++;
/* A back reference needs an additional 2 bytes, plus either one or 5
bytes for a repeat. We also need to keep the value of the highest
back reference. */
if (c <= -ESC_REF)
{
int refnum = -c - ESC_REF;
if (refnum > top_backref) top_backref = refnum;
length += 2;
/* For single back reference */
if (ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
{
ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
if ((min == 0 && (max == 1 || max == -1)) ||
(min == 1 && max == -1))
length++;
else length += 5;
if (ptr[1] == '?') ptr++;
}
}
continue;
case '^':
case '.':
case '$':
case '*':
case '+':
case '?':
length++;
continue;

/* These repeats won't be after brackets; */


/* those are handled separately */

/* This covers the cases of repeats after a single char, metachar, class,
or back reference. */

-48-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597

Saturday, June 16, 2012 11:29 PM

case '{':
if (!is_counted_repeat(ptr+1, &compile_block)) goto NORMAL_CHAR;
ptr = read_repeat_counts(ptr+1, &min, &max, errorptr, &compile_block);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
if ((min == 0 && (max == 1 || max == -1)) ||
(min == 1 && max == -1))
length++;
else
{
length--;
/* Uncount the original char or metachar */
if (min == 1) length++; else if (min > 0) length += 4;
if (max > 0) length += 4; else length += 2;
}
if (ptr[1] == '?') ptr++;
continue;
/* An alternation contains an offset to the next branch or ket. If any ims
options changed in the previous branch(es), and/or if we are in a
lookbehind assertion, extra space will be needed at the start of the
branch. This is handled by branch_extra. */
case '|':
length += 3 + branch_extra;
continue;
/* A character class uses 33 characters. Don't worry about character types
that aren't allowed in classes - they'll get picked up during the compile.
A character class that contains only one character uses 2 or 3 bytes,
depending on whether it is negated or not. Notice this where we can. */
case '[':
class_charcount = 0;
if (*(++ptr) == '^') ptr++;
do
{
if (*ptr == '\\')
{
int ch = check_escape(&ptr, errorptr, bracount, options, TRUE,
&compile_block);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
if (-ch == ESC_b) class_charcount++; else class_charcount = 10;
}
else class_charcount++;
ptr++;
}
while (*ptr != 0 && *ptr != ']');
/* Repeats for negated single chars are handled by the general code */
if (class_charcount == 1) length += 3; else
{
length += 33;

-49-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650

Saturday, June 16, 2012 11:29 PM

/* A repeat needs either 1 or 5 bytes. */


if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
{
ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
if ((min == 0 && (max == 1 || max == -1)) ||
(min == 1 && max == -1))
length++;
else length += 5;
if (ptr[1] == '?') ptr++;
}
}
continue;
/* Brackets may be genuine groups or special things */
case '(':
branch_newextra = 0;
bracket_length = 3;
/* Handle special forms of bracket, which all start (? */
if (ptr[1] == '?')
{
int set, unset;
int *optset;
switch (c = ptr[2])
{
/* Skip over comments entirely */
case '#':
ptr += 3;
while (*ptr != 0 && *ptr != ')') ptr++;
if (*ptr == 0)
{
*errorptr = ERR18;
goto PCRE_ERROR_RETURN;
}
continue;
/* Non-referencing groups and lookaheads just move the pointer on, and
then behave like a non-special bracket, except that they don't increment
the count of extracting brackets. Ditto for the "once only" bracket,
which is in Perl from version 5.005. */
case ':':
case '=':
case '!':
case '>':
ptr += 2;
break;

-50-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703

Saturday, June 16, 2012 11:29 PM

/* A recursive call to the regex is an extension, to provide the


facility which can be obtained by $(?p{perl-code}) in Perl 5.6. */
case 'R':
if (ptr[3] != ')')
{
*errorptr = ERR29;
goto PCRE_ERROR_RETURN;
}
ptr += 3;
length += 1;
break;
/* Lookbehinds are in Perl from version 5.005 */
case '<':
if (ptr[3] == '=' || ptr[3] == '!')
{
ptr += 3;
branch_newextra = 3;
length += 3;
/* For the first branch */
break;
}
*errorptr = ERR24;
goto PCRE_ERROR_RETURN;
/* Conditionals are in Perl from version 5.005. The bracket must either
be followed by a number (for bracket reference) or by an assertion
group. */
case '(':
if ((compile_block.ctypes[ptr[3]] & ctype_digit) != 0)
{
ptr += 4;
length += 3;
while ((compile_block.ctypes[*ptr] & ctype_digit) != 0) ptr++;
if (*ptr != ')')
{
*errorptr = ERR26;
goto PCRE_ERROR_RETURN;
}
}
else
/* An assertion must follow */
{
ptr++;
/* Can treat like ':' as far as spacing is concerned */
if (ptr[2] != '?' ||
(ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') )
{
ptr += 2;
/* To get right offset in message */
*errorptr = ERR28;
goto PCRE_ERROR_RETURN;
}
}
-51-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756

Saturday, June 16, 2012 11:29 PM

break;
/* Else loop checking valid options until ) is met. Anything else is an
error. If we are without any brackets, i.e. at top level, the settings
act as if specified in the options, so massage the options immediately.
This is for backward compatibility with Perl 5.004. */
default:
set = unset = 0;
optset = &set;
ptr += 2;
for (;; ptr++)
{
c = *ptr;
switch (c)
{
case 'i':
*optset |= PCRE_CASELESS;
continue;
case 'm':
*optset |= PCRE_MULTILINE;
continue;
case 's':
*optset |= PCRE_DOTALL;
continue;
case 'x':
*optset |= PCRE_EXTENDED;
continue;
case 'X':
*optset |= PCRE_EXTRA;
continue;
case 'U':
*optset |= PCRE_UNGREEDY;
continue;
case '-':
optset = &unset;
continue;
/* A termination by ')' indicates an options-setting-only item;
this is global at top level; otherwise nothing is done here and
it is handled during the compiling process on a per-bracket-group
basis. */
case ')':
if (brastackptr == 0)
{
-52-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809

Saturday, June 16, 2012 11:29 PM

options = (options | set) & (~unset);


set = unset = 0;
/* To save length */
}
/* Fall through */
/* A termination by ':' indicates the start of a nested group with
the given options set. This is again handled at compile time, but
we must allow for compiled space if any of the ims options are
set. We also have to allow for resetting space at the end of
the group, which is why 4 is added to the length and not just 2.
If there are several changes of options within the same group, this
will lead to an over-estimate on the length, but this shouldn't
matter very much. We also have to allow for resetting options at
the start of any alternations, which we do by setting
branch_newextra to 2. Finally, we record whether the case-dependent
flag ever changes within the regex. This is used by the "required
character" code. */
case ':':
if (((set|unset) & PCRE_IMS) != 0)
{
length += 4;
branch_newextra = 2;
if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED;
}
goto END_OPTIONS;
/* Unrecognized option character */

default:
*errorptr = ERR12;
goto PCRE_ERROR_RETURN;
}

/* If we hit a closing bracket, that's it - this is


option-setting. We need to ensure that branch_extra
necessary. The only values branch_newextra can have
If the value is 2, then branch_extra must either be
on whether this is a lookbehind group or not. */

a freestanding
is updated if
here are 0 or 2.
2 or 5, depending

END_OPTIONS:
if (c == ')')
{
if (branch_newextra == 2 && (branch_extra == 0 || branch_extra == 3))
branch_extra += branch_newextra;
continue;
}

/* If options were terminated by ':' control comes here. Fall through


to handle the group below. */
}

-53-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862

Saturday, June 16, 2012 11:29 PM

/* Extracting brackets must be counted so we can process escapes in a


Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to
need an additional 3 bytes of store per extracting bracket. */
else
{
bracount++;
if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3;
}
/* Save length for computing whole length at end if there's a repeat that
requires duplication of the group. Also save the current value of
branch_extra, and start the new group with the new value. If non-zero, this
will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */
if (brastackptr >= sizeof(brastack)/sizeof(int))
{
*errorptr = ERR19;
goto PCRE_ERROR_RETURN;
}
bralenstack[brastackptr] = branch_extra;
branch_extra = branch_newextra;
brastack[brastackptr++] = length;
length += bracket_length;
continue;
/* Handle ket. Look for subsequent max/min; for certain sets of values we
have to replicate this bracket up to that many times. If brastackptr is
0 this is an unmatched bracket which will generate an error, but take care
not to try to access brastack[-1] when computing the length and restoring
the branch_extra value. */
case ')':
length += 3;
{
int minval = 1;
int maxval = 1;
int duplength;
if (brastackptr > 0)
{
duplength = length - brastack[--brastackptr];
branch_extra = bralenstack[brastackptr];
}
else duplength = 0;
/* Leave ptr at the final char; for read_repeat_counts this happens
automatically; for the others we need an increment. */
if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2, &compile_block))
-54-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915

Saturday, June 16, 2012 11:29 PM

{
ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr,
&compile_block);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
}
else if (c == '*') { minval = 0; maxval = -1; ptr++; }
else if (c == '+') { maxval = -1; ptr++; }
else if (c == '?') { minval = 0; ptr++; }
/* If the minimum is zero, we have to allow for an OP_BRAZERO before the
group, and if the maximum is greater than zero, we have to replicate
maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting
bracket set - hence the 7. */
if (minval == 0)
{
length++;
if (maxval > 0) length += (maxval - 1) * (duplength + 7);
}
/* When the minimum is greater than zero, 1 we have to replicate up to
minval-1 times, with no additions required in the copies. Then, if
there is a limited maximum we have to replicate up to maxval-1 times
allowing for a BRAZERO item before each optional copy and nesting
brackets for all but one of the optional copies. */
else
{
length += (minval - 1) * duplength;
if (maxval > minval)
/* Need this test as maxval=-1 means no limit */
length += (maxval - minval) * (duplength + 7) - 6;
}
}
continue;
/* Non-special character. For a run of such characters the length required
is the number of characters + 2, except that the maximum run length is 255.
We won't get a skipped space or a non-data escape or the start of a #
comment as the first character, so the length can't be zero. */
NORMAL_CHAR:
default:
length += 2;
runlength = 0;
do
{
if ((options & PCRE_EXTENDED) != 0)
{
if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
if (c == '#')
{
/* The space before the ; is to avoid a warning on a silly compiler
on the Macintosh. */
-55-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968

Saturday, June 16, 2012 11:29 PM

while ((c = *(++ptr)) != 0 && c != NEWLINE) ;


continue;
}

/* Backslash may introduce a data char or a metacharacter; stop the


string before the latter. */
if (c == '\\')
{
const uschar *saveptr = ptr;
c = check_escape(&ptr, errorptr, bracount, options, FALSE,
&compile_block);
if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
if (c < 0) { ptr = saveptr; break; }
}
/* Ordinary character or single-char escape */
runlength++;
}
/* This "while" is the end of the "do" above. */
while (runlength < MAXLIT &&
(compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0);

ptr--;
length += runlength;
continue;
}

length += 4;

/* For final KET and END */

if (length > 65539)


{
*errorptr = ERR20;
return NULL;
}
/* Compute the size of data block needed and get it, either from malloc or
externally provided function. We specify "code[0]" in the offsetof() expression
rather than just "code", because it has been reported that one broken compiler
fails on "code" because it is also an independent variable. It should make no
difference to the value of the offsetof(). */
size = length + offsetof(real_pcre, code[0]);
re = (real_pcre *)pcre_malloc(size);
if (re == NULL)
{
*errorptr = ERR21;
-56-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021

Saturday, June 16, 2012 11:29 PM

return NULL;
}
/* Put in the magic number, and save the size, options, and table pointer */
re->magic_number = MAGIC_NUMBER;
re->size = size;
re->options = options;
re->tables = tables;
/* Set up a starting, non-extracting bracket, then compile the expression. On
error, *errorptr will be set non-NULL, so we don't need to look at the result
of the function here. */
ptr = (const uschar *)pattern;
code = re->code;
*code = OP_BRA;
bracount = 0;
(void)compile_regex(options, -1, &bracount, &code, &ptr, errorptr, FALSE, 0,
&reqchar, &countlits, &compile_block);
re->top_bracket = bracount;
re->top_backref = top_backref;
/* If not reached end of pattern on success, there's an excess bracket. */
if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22;
/* Fill in the terminating state and check for disastrous overflow, but
if debugging, leave the test till after things are printed out. */
*code++ = OP_END;
#ifndef PCRE_DEBUG
if (code - re->code > length) *errorptr = ERR23;
#endif
/* Give an error if there's back reference to a non-existent capturing
subpattern. */
if (top_backref > re->top_bracket) *errorptr = ERR15;
/* Failed to compile */
if (*errorptr != NULL)
{
pcre_free(re);
PCRE_ERROR_RETURN:
*erroroffset = ptr - (const uschar *)pattern;
return NULL;
}
/* If the anchored option was not passed, set flag if we can determine that the
pattern is anchored by virtue of ^ characters or \A or anything else (such as
-57-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074

Saturday, June 16, 2012 11:29 PM

starting with .* when DOTALL is set).


Otherwise, see if we can determine what the first character has to be, because
that speeds up unanchored matches no end. If not, see if we can set the
PCRE_STARTLINE flag. This is helpful for multiline matches when all branches
start with ^. and also when all branches start with .* for non-DOTALL matches.
*/
if ((options & PCRE_ANCHORED) == 0)
{
int temp_options = options;
if (is_anchored(re->code, &temp_options))
re->options |= PCRE_ANCHORED;
else
{
int ch = find_firstchar(re->code, &temp_options);
if (ch >= 0)
{
re->first_char = ch;
re->options |= PCRE_FIRSTSET;
}
else if (is_startline(re->code))
re->options |= PCRE_STARTLINE;
}
}
/* Save the last required character if there are at least two literal
characters on all paths, or if there is no first character setting. */
if (reqchar >= 0 && (countlits > 1 || (re->options & PCRE_FIRSTSET) == 0))
{
re->req_char = reqchar;
re->options |= PCRE_REQCHSET;
}
/* Print out the compiled data for debugging */
#ifdef PCRE_DEBUG
printf("Length = %d top_bracket = %d top_backref = %d\n" ,
length, re->top_bracket, re->top_backref);
if (re->options != 0)
{
printf("%s%s%s%s%s%s%s%s%s\n",
((re->options & PCRE_ANCHORED) != 0)? "anchored " : "",
((re->options & PCRE_CASELESS) != 0)? "caseless " : "",
((re->options & PCRE_ICHANGED) != 0)? "case state changed " : "",
((re->options & PCRE_EXTENDED) != 0)? "extended " : "",
((re->options & PCRE_MULTILINE) != 0)? "multiline " : "",
((re->options & PCRE_DOTALL) != 0)? "dotall " : "",
((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "",
((re->options & PCRE_EXTRA) != 0)? "extra " : "",
-58-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127

Saturday, June 16, 2012 11:29 PM

((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : "");

if ((re->options & PCRE_FIRSTSET) != 0)


{
if (isprint(re->first_char)) printf("First char = %c\n", re->first_char);
else printf("First char = \\x%02x\n", re->first_char);
}
if ((re->options & PCRE_REQCHSET) != 0)
{
if (isprint(re->req_char)) printf("Req char = %c\n", re->req_char);
else printf("Req char = \\x%02x\n", re->req_char);
}
code_end = code;
code_base = code = re->code;
while (code < code_end)
{
int charlength;
printf("%3d ", code - code_base);
if (*code >= OP_BRA)
{
if (*code - OP_BRA > EXTRACT_BASIC_MAX)
printf("%3d Bra extra", (code[1] << 8) + code[2]);
else
printf("%3d Bra %d", (code[1] << 8) + code[2], *code - OP_BRA);
code += 2;
}
else switch(*code)
{
case OP_OPT:
printf(" %.2x %s", code[1], OP_names[*code]);
code++;
break;
case OP_CHARS:
charlength = *(++code);
printf("%3d ", charlength);
while (charlength-- > 0)
if (isprint(c = *(++code))) printf("%c", c); else printf("\\x%02x", c);
break;
case
case
case
case
case
case

OP_KETRMAX:
OP_KETRMIN:
OP_ALT:
OP_KET:
OP_ASSERT:
OP_ASSERT_NOT:
-59-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180

Saturday, June 16, 2012 11:29 PM

case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ONCE:
case OP_REVERSE:
case OP_BRANUMBER:
case OP_COND:
case OP_CREF:
printf("%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
code += 2;
break;
case OP_STAR:
case OP_MINSTAR:
case OP_PLUS:
case OP_MINPLUS:
case OP_QUERY:
case OP_MINQUERY:
case OP_TYPESTAR:
case OP_TYPEMINSTAR:
case OP_TYPEPLUS:
case OP_TYPEMINPLUS:
case OP_TYPEQUERY:
case OP_TYPEMINQUERY:
if (*code >= OP_TYPESTAR)
printf("
%s", OP_names[code[1]]);
else if (isprint(c = code[1])) printf("
else printf("
\\x%02x", c);
printf("%s", OP_names[*code++]);
break;

%c", c);

case OP_EXACT:
case OP_UPTO:
case OP_MINUPTO:
if (isprint(c = code[3])) printf("
%c{", c);
else printf("
\\x%02x{", c);
if (*code != OP_EXACT) printf("0,");
printf("%d}", (code[1] << 8) + code[2]);
if (*code == OP_MINUPTO) printf("?");
code += 3;
break;
case OP_TYPEEXACT:
case OP_TYPEUPTO:
case OP_TYPEMINUPTO:
printf("
%s{", OP_names[code[3]]);
if (*code != OP_TYPEEXACT) printf(",");
printf("%d}", (code[1] << 8) + code[2]);
if (*code == OP_TYPEMINUPTO) printf("?");
code += 3;
break;
case OP_NOT:
if (isprint(c = *(++code))) printf("
-60-

[^%c]", c);

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233

else printf("
break;

Saturday, June 16, 2012 11:29 PM

[^\\x%02x]", c);

case OP_NOTSTAR:
case OP_NOTMINSTAR:
case OP_NOTPLUS:
case OP_NOTMINPLUS:
case OP_NOTQUERY:
case OP_NOTMINQUERY:
if (isprint(c = code[1])) printf("
else printf("
[^\\x%02x]", c);
printf("%s", OP_names[*code++]);
break;

[^%c]", c);

case OP_NOTEXACT:
case OP_NOTUPTO:
case OP_NOTMINUPTO:
if (isprint(c = code[3])) printf("
[^%c]{", c);
else printf("
[^\\x%02x]{", c);
if (*code != OP_NOTEXACT) printf(",");
printf("%d}", (code[1] << 8) + code[2]);
if (*code == OP_NOTMINUPTO) printf("?");
code += 3;
break;
case OP_REF:
printf("
\\%d", (code[1] << 8) | code[2]);
code += 3;
goto CLASS_REF_REPEAT;
case OP_CLASS:
{
int i, min, max;
code++;
printf("
[");
for (i = 0; i < 256; i++)
{
if ((code[i/8] & (1 << (i&7))) != 0)
{
int j;
for (j = i+1; j < 256; j++)
if ((code[j/8] & (1 << (j&7))) == 0) break;
if (i == '-' || i == ']') printf("\\");
if (isprint(i)) printf("%c", i); else printf("\\x%02x", i);
if (--j > i)
{
printf("-");
if (j == '-' || j == ']') printf("\\");
if (isprint(j)) printf("%c", j); else printf("\\x%02x", j);
}
i = j;
}
-61-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286

Saturday, June 16, 2012 11:29 PM

}
printf("]");
code += 32;
CLASS_REF_REPEAT:
switch(*code)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRQUERY:
case OP_CRMINQUERY:
printf("%s", OP_names[*code]);
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
min = (code[1] << 8) + code[2];
max = (code[3] << 8) + code[4];
if (max == 0) printf("{%d,}", min);
else printf("{%d,%d}", min, max);
if (*code == OP_CRMINRANGE) printf("?");
code += 4;
break;
default:
code--;
}

}
break;

/* Anything else is just a one-node item */


default:
printf("
break;
}

%s", OP_names[*code]);

code++;
printf("\n");
}
printf("------------------------------------------------------------------\n" );
/* This check is done here in the debugging case so that the code that
was compiled can be seen. */
if (code - re->code > length)
{
*errorptr = ERR23;
pcre_free(re);
*erroroffset = ptr - (uschar *)pattern;
-62-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339

Saturday, June 16, 2012 11:29 PM

return NULL;
}
#endif
return (pcre *)re;
}

/*************************************************
*
Match a back-reference
*
*************************************************/
/* If a back reference hasn't been set, the length that is passed is greater
than the number of characters left in the string, so the match fails.
Arguments:
offset
eptr
length
md
ims
Returns:
*/

index into the offset vector


points into the subject
length to be matched
points to match data block
the ims flags
TRUE if matched

static BOOL match_ref(offset, eptr, length, md, ims)


int offset;
register const uschar *eptr;
int length;
match_data *md;
unsigned long int ims;
{
const uschar *p = md->start_subject + md->offset_vector[offset];
#ifdef PCRE_DEBUG
if (eptr >= md->end_subject)
printf("matching subject <null>");
else
{
printf("matching subject ");
pchars(eptr, length, TRUE, md);
}
printf(" against backref ");
pchars(p, length, FALSE, md);
printf("\n");
#endif
/* Always fail if not enough characters left */
if (length > md->end_subject - eptr) return FALSE;
/* Separate the caseless case for speed */
-63-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392

Saturday, June 16, 2012 11:29 PM

if ((ims & PCRE_CASELESS) != 0)


{
while (length-- > 0)
if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
}
else
{ while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
return TRUE;
}

/*************************************************
*
Match from current position
*
*************************************************/
/* On entry ecode points to the first opcode, and eptr to the first character
in the subject string, while eptrb holds the value of eptr at the start of the
last bracketed group - used for breaking infinite loops matching zero-length
strings.
Arguments:
eptr
ecode
offset_top
md
ims
eptrb
flags

Returns:
*/

pointer in subject
position in code
current top pointer
pointer to "static" info for the match
current /i, /m, and /s options
pointer to chain of blocks containing eptr at start of
brackets - for testing for empty matches
can contain
match_condassert - this is an assertion condition
match_isgroup - this is the start of a bracketed group
TRUE if matched

static BOOL match(eptr, ecode, offset_top, md, ims, eptrb, flags)


register const uschar *eptr;
register const uschar *ecode;
int offset_top;
match_data *md;
unsigned long int ims;
eptrblock *eptrb;
int flags;
{
unsigned long int original_ims = ims;
/* Save for resetting on ')' */
eptrblock newptrb;
int mstat;
/* TM3 modification */
if (mudstate.wild_times_lev > mudconf.wild_times_lim)
return PCRE_ERROR_BACKTRACK_LIMIT;
-64-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445

Saturday, June 16, 2012 11:29 PM

mudstate.wild_times_lev++;
/* At the start of a bracketed group, add the current subject pointer to the
stack of such pointers, to be re-instated at the end of the group when we hit
the closing ket. When match() is called in other circumstances, we don't add to
the stack. */
if ((flags & match_isgroup) != 0)
{
newptrb.prev = eptrb;
newptrb.saved_eptr = eptr;
eptrb = &newptrb;
}
/* Now start processing the operations. */
for (;;)
{
int op = (int)*ecode;
int min, max, ctype;
register int i;
register int c;
BOOL minimize = FALSE;
/* Opening capturing bracket. If there is space in the offset vector, save
the current subject position in the working slot at the top of the vector. We
mustn't change the current values of the data slot, because they may be set
from a previous iteration of this group, and be referred to by a reference
inside the group.
If the bracket fails to match, we need to restore this value and also the
values of the final offsets, in case they were set by a previous iteration of
the same bracket.
If there isn't enough space in the offset vector, treat this as if it were a
non-capturing bracket. Don't worry about setting the flag for the error case
here; that is handled in the code for KET. */
if (op > OP_BRA)
{
int offset;
int number = op - OP_BRA;
/* For extended extraction brackets (large number), we have to fish out the
number from a dummy opcode at the start. */
if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5];
offset = number << 1;
#ifdef PCRE_DEBUG
printf("start bracket %d subject=", number);
pchars(eptr, 16, TRUE, md);
printf("\n");
-65-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498

Saturday, June 16, 2012 11:29 PM

#endif
if (offset < md->offset_max)
{
int save_offset1 = md->offset_vector[offset];
int save_offset2 = md->offset_vector[offset+1];
int save_offset3 = md->offset_vector[md->offset_end - number];
DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
do

{
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, eptrb,
match_isgroup)) != FALSE)
return mstat;
ecode += (ecode[1] << 8) + ecode[2];
}
while (*ecode == OP_ALT);
DPRINTF(("bracket %d failed\n", number));
md->offset_vector[offset] = save_offset1;
md->offset_vector[offset+1] = save_offset2;
md->offset_vector[md->offset_end - number] = save_offset3;
return FALSE;
}
/* Insufficient room for saving captured contents */
else op = OP_BRA;
}
/* Other types of node can be handled by a switch */
switch(op)
{
case OP_BRA:
/* Non-capturing bracket: optimized */
DPRINTF(("start bracket 0\n"));
do
{
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, eptrb,
match_isgroup)) != FALSE)
return mstat;
ecode += (ecode[1] << 8) + ecode[2];
}
while (*ecode == OP_ALT);
DPRINTF(("bracket 0 failed\n"));
return FALSE;
/* Conditional group: compilation checked that there are no more than
two branches. If the condition is false, skipping the first branch takes us
-66-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551

Saturday, June 16, 2012 11:29 PM

past the end if there is only one branch, but that's OK because that is
exactly what going to the ket would do. */
case OP_COND:
if (ecode[3] == OP_CREF)
/* Condition is extraction test */
{
int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled ref number */
return match(eptr,
ecode + ((offset < offset_top && md->offset_vector[offset] >= 0)?
6 : 3 + (ecode[1] << 8) + ecode[2]),
offset_top, md, ims, eptrb, match_isgroup);
}
/* The condition is an assertion. Call match() to evaluate it - setting
the final argument TRUE causes it to stop at the end of an assertion. */
else
{
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, NULL,
match_condassert | match_isgroup)) < 0)
return mstat;
if (mstat)
{
ecode += 3 + (ecode[4] << 8) + ecode[5];
while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
}
else ecode += (ecode[1] << 8) + ecode[2];
return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
}
/* Control never reaches here */
/* Skip over conditional reference or large extraction number data if
encountered. */
case OP_CREF:
case OP_BRANUMBER:
ecode += 3;
break;
/* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched
an empty string - recursion will then try other alternatives, if any. */
case OP_END:
if (md->notempty && eptr == md->start_match) return FALSE;
md->end_match_ptr = eptr;
/* Record where we ended */
md->end_offset_top = offset_top;
/* and how many extracts were taken */
return TRUE;
/* Change option settings */
case OP_OPT:
ims = ecode[1];
ecode += 2;
-67-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604

Saturday, June 16, 2012 11:29 PM

DPRINTF(("ims set to %02lx\n", ims));


break;
/* Assertion brackets. Check the alternative branches in turn - the
matching won't pass the KET for an assertion. If any one branch matches,
the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
start of each branch to move the current point backwards, so the code at
this level is identical to the lookahead case. */
case OP_ASSERT:
case OP_ASSERTBACK:
do
{
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, NULL,
match_isgroup)) < 0)
return mstat;
if (mstat)
break;
ecode += (ecode[1] << 8) + ecode[2];
}
while (*ecode == OP_ALT);
if (*ecode == OP_KET) return FALSE;
/* If checking an assertion for a condition, return TRUE. */
if ((flags & match_condassert) != 0) return TRUE;
/* Continue from after the assertion, updating the offsets high water
mark, since extracts may have been taken during the assertion. */
do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
ecode += 3;
offset_top = md->end_offset_top;
continue;
/* Negative assertion: all branches must fail to match */
case OP_ASSERT_NOT:
case OP_ASSERTBACK_NOT:
do
{
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, NULL,
match_isgroup)) < 0)
return mstat;
if (mstat)
return FALSE;
ecode += (ecode[1] << 8) + ecode[2];
}
while (*ecode == OP_ALT);
if ((flags & match_condassert) != 0) return TRUE;
ecode += 3;
-68-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657

Saturday, June 16, 2012 11:29 PM

continue;
/* Move the subject pointer back. This occurs only at the start of
each branch of a lookbehind assertion. If we are too close to the start to
move back, this match function fails. When working with UTF-8 we move
back a number of characters, not bytes. */
case OP_REVERSE:
eptr -= (ecode[1] << 8) + ecode[2];
if (eptr < md->start_subject) return FALSE;
ecode += 3;
break;
/* Recursion matches the current regex, nested. If there are any capturing
brackets started but not finished, we have to save their starting points
and reinstate them after the recursion. However, we don't know how many
such there are (offset_top records the completed total) so we just have
to save all the potential data. There may be up to 99 such values, which
is a bit large to put on the stack, but using malloc for small numbers
seems expensive. As a compromise, the stack is used when there are fewer
than 16 values to store; otherwise malloc is used. A problem is what to do
if the malloc fails ... there is no way of returning to the top level with
an error. Save the top 15 values on the stack, and accept that the rest
may be wrong. */
case OP_RECURSE:
{
BOOL rc;
int *save;
int stacksave[15];
c = md->offset_max;
if (c < 16) save = stacksave; else
{
save = (int *)pcre_malloc((c+1) * sizeof(int));
if (save == NULL)
{
save = stacksave;
c = 15;
}
}
for (i = 1; i <= c; i++)
save[i] = md->offset_vector[md->offset_end - i];
rc = match(eptr, md->start_pattern, offset_top, md, ims, eptrb,
match_isgroup);
for (i = 1; i <= c; i++)
md->offset_vector[md->offset_end - i] = save[i];
if (save != stacksave) pcre_free(save);
if (rc != TRUE) return rc; /* TM3 modification */

-69-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710

Saturday, June 16, 2012 11:29 PM

/* In case the recursion has set more capturing values, save the final
number, then move along the subject till after the recursive match,
and advance one byte in the pattern code. */
offset_top = md->end_offset_top;
eptr = md->end_match_ptr;
ecode++;
}
break;
/* "Once" brackets are like assertion brackets except that after a match,
the point in the subject string is not moved back. Thus there can never be
a move back into the brackets. Check the alternative branches in turn - the
matching won't pass the KET for this kind of subpattern. If any one branch
matches, we carry on as at the end of a normal bracket, leaving the subject
pointer. */
case OP_ONCE:
{
const uschar *prev = ecode;
const uschar *saved_eptr = eptr;
do

{
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, eptrb,
match_isgroup)) < 0)
return mstat;
if (mstat)
break;
ecode += (ecode[1] << 8) + ecode[2];
}
while (*ecode == OP_ALT);
/* If hit the end of the group (which could be repeated), fail */
if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
/* Continue as from after the assertion, updating the offsets high water
mark, since extracts may have been taken. */
do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
offset_top = md->end_offset_top;
eptr = md->end_match_ptr;
/* For a non-repeating ket, just continue at this level. This also
happens for a repeating ket if no characters were matched in the group.
This is the forcible breaking of infinite loops as implemented in Perl
5.005. If there is an options reset, it will get obeyed in the normal
course of events. */
if (*ecode == OP_KET || eptr == saved_eptr)
{
-70-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763

Saturday, June 16, 2012 11:29 PM

ecode += 3;
break;
}
/* The repeating kets try the rest of the pattern or restart from the
preceding bracket, in the appropriate order. We need to reset any options
that changed within the bracket before re-running it, so check the next
opcode. */
if (ecode[3] == OP_OPT)
{
ims = (ims & ~PCRE_IMS) | ecode[4];
DPRINTF(("ims set to %02lx at group repeat\n" , ims));
}
if (*ecode == OP_KETRMIN)
{
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
if ((mstat = match(eptr, prev, offset_top, md, ims, eptrb,
match_isgroup)) != 0)
return mstat;
}
else /* OP_KETRMAX */
{
if ((mstat = match(eptr, prev, offset_top, md, ims, eptrb,
match_isgroup)) != 0)
return mstat;
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
}
}
return FALSE;
/* An alternation is the end of a branch; scan along to find the end of the
bracketed group and go to there. */
case OP_ALT:
do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
break;
/* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
that it may occur zero times. It may repeat infinitely, or not at all i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
repeat limits are compiled as a number of copies, with the optional ones
preceded by BRAZERO or BRAMINZERO. */
case OP_BRAZERO:
{
const uschar *next = ecode+1;
if ((mstat = match(eptr, next, offset_top, md, ims, eptrb,
match_isgroup)) != 0)
return mstat;
-71-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816

Saturday, June 16, 2012 11:29 PM

do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);


ecode = next + 3;
}
break;
case OP_BRAMINZERO:
{
const uschar *next = ecode+1;
do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
if ((mstat = match(eptr, next+3, offset_top, md, ims, eptrb,
match_isgroup)) != 0)
return mstat;
ecode++;
}
break;
/* End of a group, repeated or non-repeating. If we are at the end of
an assertion "group", stop matching and return TRUE, but record the
current high water mark for use by positive assertions. Do this also
for the "once" (not-backup up) groups. */
case OP_KET:
case OP_KETRMIN:
case OP_KETRMAX:
{
const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
const uschar *saved_eptr = eptrb->saved_eptr;
eptrb = eptrb->prev;

/* Back up the stack of bracket start pointers */

if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||


*prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
*prev == OP_ONCE)
{
md->end_match_ptr = eptr;
/* For ONCE */
md->end_offset_top = offset_top;
return TRUE;
}
/* In all other cases except a conditional group we have to check the
group number back at the start and if necessary complete handling an
extraction by setting the offsets and bumping the high water mark. */
if (*prev != OP_COND)
{
int offset;
int number = *prev - OP_BRA;
/* For extended extraction brackets (large number), we have to fish out
the number from a dummy opcode at the start. */
if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5];
offset = number << 1;
-72-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869

Saturday, June 16, 2012 11:29 PM

#ifdef PCRE_DEBUG
printf("end bracket %d", number);
printf("\n");
#endif
if (number > 0)
{
if (offset >= md->offset_max) md->offset_overflow = TRUE; else
{
md->offset_vector[offset] =
md->offset_vector[md->offset_end - number];
md->offset_vector[offset+1] = eptr - md->start_subject;
if (offset_top <= offset) offset_top = offset + 2;
}
}
}
/* Reset the value of the ims flags, in case they got changed during
the group. */
ims = original_ims;
DPRINTF(("ims reset to %02lx\n", ims));
/* For a non-repeating ket, just continue at this level. This also
happens for a repeating ket if no characters were matched in the group.
This is the forcible breaking of infinite loops as implemented in Perl
5.005. If there is an options reset, it will get obeyed in the normal
course of events. */
if (*ecode == OP_KET || eptr == saved_eptr)
{
ecode += 3;
break;
}
/* The repeating kets try the rest of the pattern or restart from the
preceding bracket, in the appropriate order. */
if (*ecode == OP_KETRMIN)
{
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
if ((mstat = match(eptr, prev, offset_top, md, ims, eptrb,
match_isgroup)) != 0)
return mstat;
}
else /* OP_KETRMAX */
{
if ((mstat = match(eptr, prev, offset_top, md, ims, eptrb,
match_isgroup)) != 0)
return mstat;
if ((mstat = match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) != 0)
-73-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922

Saturday, June 16, 2012 11:29 PM

return mstat;
}

}
return FALSE;

/* Start of subject unless notbol, or after internal newline if multiline */


case OP_CIRC:
if (md->notbol && eptr == md->start_subject) return FALSE;
if ((ims & PCRE_MULTILINE) != 0)
{
if (eptr != md->start_subject && eptr[-1] != NEWLINE) return FALSE;
ecode++;
break;
}
/* ... else fall through */
/* Start of subject assertion */
case OP_SOD:
if (eptr != md->start_subject) return FALSE;
ecode++;
break;
/* Assert before internal newline if multiline, or before a terminating
newline unless endonly is set, else end of subject unless noteol is set. */
case OP_DOLL:
if ((ims & PCRE_MULTILINE) != 0)
{
if (eptr < md->end_subject) { if (*eptr != NEWLINE) return FALSE; }
else { if (md->noteol) return FALSE; }
ecode++;
break;
}
else
{
if (md->noteol) return FALSE;
if (!md->endonly)
{
if (eptr < md->end_subject - 1 ||
(eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
ecode++;
break;
}

}
/* ... else fall through */
/* End of subject assertion (\z) */
case OP_EOD:
if (eptr < md->end_subject) return FALSE;
-74-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975

Saturday, June 16, 2012 11:29 PM

ecode++;
break;
/* End of subject or ending \n assertion (\Z) */
case OP_EODN:
if (eptr < md->end_subject - 1 ||
(eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
ecode++;
break;
/* Word boundary assertions */
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
{
BOOL prev_is_word = (eptr != md->start_subject) &&
((md->ctypes[eptr[-1]] & ctype_word) != 0);
BOOL cur_is_word = (eptr < md->end_subject) &&
((md->ctypes[*eptr] & ctype_word) != 0);
if ((*ecode++ == OP_WORD_BOUNDARY)?
cur_is_word == prev_is_word : cur_is_word != prev_is_word)
return FALSE;
}
break;
/* Match a single character type; inline for speed */
case OP_ANY:
if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE)
return FALSE;
if (eptr++ >= md->end_subject) return FALSE;
ecode++;
break;
case OP_NOT_DIGIT:
if (eptr >= md->end_subject ||
(md->ctypes[*eptr++] & ctype_digit) != 0)
return FALSE;
ecode++;
break;
case OP_DIGIT:
if (eptr >= md->end_subject ||
(md->ctypes[*eptr++] & ctype_digit) == 0)
return FALSE;
ecode++;
break;
case OP_NOT_WHITESPACE:
if (eptr >= md->end_subject ||
(md->ctypes[*eptr++] & ctype_space) != 0)
return FALSE;
-75-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028

Saturday, June 16, 2012 11:29 PM

ecode++;
break;
case OP_WHITESPACE:
if (eptr >= md->end_subject ||
(md->ctypes[*eptr++] & ctype_space) == 0)
return FALSE;
ecode++;
break;
case OP_NOT_WORDCHAR:
if (eptr >= md->end_subject ||
(md->ctypes[*eptr++] & ctype_word) != 0)
return FALSE;
ecode++;
break;
case OP_WORDCHAR:
if (eptr >= md->end_subject ||
(md->ctypes[*eptr++] & ctype_word) == 0)
return FALSE;
ecode++;
break;
/* Match a back reference, possibly repeatedly. Look past the end of the
item to see if there is repeat information following. The code is similar
to that for character classes, but repeated for efficiency. Then obey
similar code to character type repeats - written out again for speed.
However, if the referenced string is the empty string, always treat
it as matched, any number of times (otherwise there could be infinite
loops). */
case OP_REF:
{
int length;
int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */
ecode += 3;
/* Advance past item */
/* If the reference is unset, set the length to be longer than the amount
of subject left; this ensures that every attempt at a match fails. We
can't just fail here, because of the possibility of quantifiers with zero
minima. */
length = (offset >= offset_top || md->offset_vector[offset] < 0)?
md->end_subject - eptr + 1 :
md->offset_vector[offset+1] - md->offset_vector[offset];
/* Set up for repetition, or handle the non-repeated case */
switch (*ecode)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
-76-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081

Saturday, June 16, 2012 11:29 PM

case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRQUERY:
case OP_CRMINQUERY:
c = *ecode++ - OP_CRSTAR;
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;
break;

/* Pick up values from tables; */


/* zero for max => infinity */

case OP_CRRANGE:
case OP_CRMINRANGE:
minimize = (*ecode == OP_CRMINRANGE);
min = (ecode[1] << 8) + ecode[2];
max = (ecode[3] << 8) + ecode[4];
if (max == 0) max = INT_MAX;
ecode += 5;
break;
default:
/* No repeat follows */
if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
eptr += length;
continue;
/* With the main loop */
}
/* If the length of the reference is zero, just continue with the
main loop. */
if (length == 0) continue;
/* First, ensure the minimum number of matches are present. We get back
the length of the reference string explicitly rather than passing the
address of eptr, so that eptr can be a register variable. */
for (i = 1; i <= min; i++)
{
if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
eptr += length;
}
/* If min = max, continue at the same level without recursion.
They are not both allowed to be zero. */
if (min == max) continue;
/* If minimizing, keep trying and advancing the pointer */
if (minimize)
{
for (i = min;; i++)
{
if ((mstat = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != 0)
-77-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134

Saturday, June 16, 2012 11:29 PM

return mstat;
if (i >= max || !match_ref(offset, eptr, length, md, ims))
return FALSE;
eptr += length;
}
/* Control never gets here */
}
/* If maximizing, find the longest string and work backwards */
else
{
const uschar *pp = eptr;
for (i = min; i < max; i++)
{
if (!match_ref(offset, eptr, length, md, ims)) break;
eptr += length;
}
while (eptr >= pp)
{
if ((mstat = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
eptr -= length;
}
return FALSE;
}
}
/* Control never gets here */

/* Match a character class, possibly repeatedly. Look past the end of the
item to see if there is repeat information following. Then obey similar
code to character type repeats - written out again for speed. */
case OP_CLASS:
{
const uschar *data = ecode + 1;
ecode += 33;

/* Save for matching */


/* Advance past the item */

switch (*ecode)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRQUERY:
case OP_CRMINQUERY:
c = *ecode++ - OP_CRSTAR;
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;

/* Pick up values from tables; */


/* zero for max => infinity */

-78-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187

Saturday, June 16, 2012 11:29 PM

break;
case OP_CRRANGE:
case OP_CRMINRANGE:
minimize = (*ecode == OP_CRMINRANGE);
min = (ecode[1] << 8) + ecode[2];
max = (ecode[3] << 8) + ecode[4];
if (max == 0) max = INT_MAX;
ecode += 5;
break;
default:
min = max = 1;
break;
}

/* No repeat follows */

/* First, ensure the minimum number of matches are present. */


for (i = 1; i <= min; i++)
{
if (eptr >= md->end_subject) return FALSE;
GETCHARINC(c, eptr)
/* Get character; increment eptr */
if ((data[c/8] & (1 << (c&7))) != 0) continue;
return FALSE;
}
/* If max == min we can continue with the main loop without the
need to recurse. */
if (min == max) continue;
/* If minimizing, keep testing the rest of the expression and advancing
the pointer while it matches the class. */
if (minimize)
{
for (i = min;; i++)
{
if ((mstat = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
if (i >= max || eptr >= md->end_subject) return FALSE;
GETCHARINC(c, eptr)
/* Get character; increment eptr */
if ((data[c/8] & (1 << (c&7))) != 0) continue;
return FALSE;
}
/* Control never gets here */
}
/* If maximizing, find the longest possible run, then work backwards. */
else
-79-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240

Saturday, June 16, 2012 11:29 PM

{
const uschar *pp = eptr;
int len = 1;
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject) break;
GETCHARLEN(c, eptr, len) /* Get character, set length if UTF-8 */
if ((data[c/8] & (1 << (c&7))) == 0) break;
eptr += len;
}
while (eptr >= pp)
{
if ((mstat = match(eptr--, ecode, offset_top, md, ims,
eptrb, 0)) != 0)
return mstat;
}
return FALSE;
}

}
/* Control never gets here */

/* Match a run of characters */


case OP_CHARS:
{
register int length = ecode[1];
ecode += 2;
#ifdef PCRE_DEBUG
/* Sigh. Some compilers never learn. */
if (eptr >= md->end_subject)
printf("matching subject <null> against pattern " );
else
{
printf("matching subject ");
pchars(eptr, length, TRUE, md);
printf(" against pattern ");
}
pchars(ecode, length, FALSE, md);
printf("\n");
#endif
if (length > md->end_subject - eptr) return FALSE;
if ((ims & PCRE_CASELESS) != 0)
{
while (length-- > 0)
if (md->lcc[*ecode++] != md->lcc[*eptr++])
return FALSE;
}
else
{
while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
-80-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293

Saturday, June 16, 2012 11:29 PM

}
}
break;
/* Match a single character repeatedly; different opcodes share code. */
case OP_EXACT:
min = max = (ecode[1] << 8) + ecode[2];
ecode += 3;
goto REPEATCHAR;
case OP_UPTO:
case OP_MINUPTO:
min = 0;
max = (ecode[1] << 8) + ecode[2];
minimize = *ecode == OP_MINUPTO;
ecode += 3;
goto REPEATCHAR;
case OP_STAR:
case OP_MINSTAR:
case OP_PLUS:
case OP_MINPLUS:
case OP_QUERY:
case OP_MINQUERY:
c = *ecode++ - OP_STAR;
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;

/* Pick up values from tables; */


/* zero for max => infinity */

/* Common code for all repeated single-character matches. We can give


up quickly if there are fewer than the minimum number of characters left in
the subject. */
REPEATCHAR:
if (min > md->end_subject - eptr) return FALSE;
c = *ecode++;
/* The code is duplicated for the caseless and caseful cases, for speed,
since matching characters is likely to be quite common. First, ensure the
minimum number of matches are present. If min = max, continue at the same
level without recursing. Otherwise, if minimizing, keep trying the rest of
the expression and advancing one matching character if failing, up to the
maximum. Alternatively, if maximizing, find the maximum number of
characters and work backwards. */
DPRINTF(("matching %c{%d,%d} against subject %.*s\n" , c, min, max,
max, eptr));
if ((ims & PCRE_CASELESS) != 0)
{
c = md->lcc[c];
-81-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346

Saturday, June 16, 2012 11:29 PM

for (i = 1; i <= min; i++)


if (c != md->lcc[*eptr++]) return FALSE;
if (min == max) continue;
if (minimize)
{
for (i = min;; i++)
{
if ((mstat = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
if (i >= max || eptr >= md->end_subject ||
c != md->lcc[*eptr++])
return FALSE;
}
/* Control never gets here */
}
else
{
const uschar *pp = eptr;
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
eptr++;
}
while (eptr >= pp)
if ((mstat = match(eptr--, ecode, offset_top, md, ims,
eptrb, 0)) != 0)
return mstat;
return FALSE;
}
/* Control never gets here */
}
/* Caseful comparisons */
else
{
for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
if (min == max) continue;
if (minimize)
{
for (i = min;; i++)
{
if ((mstat = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
}
/* Control never gets here */
}
else
{
const uschar *pp = eptr;
for (i = min; i < max; i++)
{
-82-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399

Saturday, June 16, 2012 11:29 PM

if (eptr >= md->end_subject || c != *eptr) break;


eptr++;
}
while (eptr >= pp)
if ((mstat = match(eptr--, ecode, offset_top, md, ims,
eptrb, 0)) != 0)
return mstat;
return FALSE;
}

}
/* Control never gets here */

/* Match a negated single character */


case OP_NOT:
if (eptr >= md->end_subject) return FALSE;
ecode++;
if ((ims & PCRE_CASELESS) != 0)
{
if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
}
else
{
if (*ecode++ == *eptr++) return FALSE;
}
break;
/* Match a negated single character repeatedly. This is almost a repeat of
the code for a repeated single character, but I haven't found a nice way of
commoning these up that doesn't require a test of the positive/negative
option for each character match. Maybe that wouldn't add very much to the
time taken, but character matching *is* what this is all about... */
case OP_NOTEXACT:
min = max = (ecode[1] << 8) + ecode[2];
ecode += 3;
goto REPEATNOTCHAR;
case OP_NOTUPTO:
case OP_NOTMINUPTO:
min = 0;
max = (ecode[1] << 8) + ecode[2];
minimize = *ecode == OP_NOTMINUPTO;
ecode += 3;
goto REPEATNOTCHAR;
case OP_NOTSTAR:
case OP_NOTMINSTAR:
case OP_NOTPLUS:
case OP_NOTMINPLUS:
case OP_NOTQUERY:
case OP_NOTMINQUERY:
c = *ecode++ - OP_NOTSTAR;
-83-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452

minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;

Saturday, June 16, 2012 11:29 PM

/* Pick up values from tables; */


/* zero for max => infinity */

/* Common code for all repeated single-character matches. We can give


up quickly if there are fewer than the minimum number of characters left in
the subject. */
REPEATNOTCHAR:
if (min > md->end_subject - eptr) return FALSE;
c = *ecode++;
/* The code is duplicated for the caseless and caseful cases, for speed,
since matching characters is likely to be quite common. First, ensure the
minimum number of matches are present. If min = max, continue at the same
level without recursing. Otherwise, if minimizing, keep trying the rest of
the expression and advancing one matching character if failing, up to the
maximum. Alternatively, if maximizing, find the maximum number of
characters and work backwards. */
DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n" , c, min, max,
max, eptr));
if ((ims & PCRE_CASELESS) != 0)
{
c = md->lcc[c];
for (i = 1; i <= min; i++)
if (c == md->lcc[*eptr++]) return FALSE;
if (min == max) continue;
if (minimize)
{
for (i = min;; i++)
{
if ((mstat = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
if (i >= max || eptr >= md->end_subject ||
c == md->lcc[*eptr++])
return FALSE;
}
/* Control never gets here */
}
else
{
const uschar *pp = eptr;
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
eptr++;
}
while (eptr >= pp)
if ((mstat = match(eptr--, ecode, offset_top, md, ims,
eptrb, 0)) != 0)
-84-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505

Saturday, June 16, 2012 11:29 PM

return mstat;
return FALSE;
}
/* Control never gets here */
}
/* Caseful comparisons */
else
{
for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
if (min == max) continue;
if (minimize)
{
for (i = min;; i++)
{
if ((mstat = match(eptr, ecode, offset_top, md, ims,
eptrb, 0)) != 0)
return mstat;
if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
}
/* Control never gets here */
}
else
{
const uschar *pp = eptr;
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || c == *eptr) break;
eptr++;
}
while (eptr >= pp)
if ((mstat = match(eptr--, ecode, offset_top, md, ims,
eptrb, 0)) != 0)
return mstat;
return FALSE;
}
}
/* Control never gets here */
/* Match a single character type repeatedly; several different opcodes
share code. This is very similar to the code for single characters, but we
repeat it in the interests of efficiency. */
case OP_TYPEEXACT:
min = max = (ecode[1] << 8) + ecode[2];
minimize = TRUE;
ecode += 3;
goto REPEATTYPE;
case OP_TYPEUPTO:
case OP_TYPEMINUPTO:
min = 0;
-85-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558

Saturday, June 16, 2012 11:29 PM

max = (ecode[1] << 8) + ecode[2];


minimize = *ecode == OP_TYPEMINUPTO;
ecode += 3;
goto REPEATTYPE;
case OP_TYPESTAR:
case OP_TYPEMINSTAR:
case OP_TYPEPLUS:
case OP_TYPEMINPLUS:
case OP_TYPEQUERY:
case OP_TYPEMINQUERY:
c = *ecode++ - OP_TYPESTAR;
minimize = (c & 1) != 0;
min = rep_min[c];
max = rep_max[c];
if (max == 0) max = INT_MAX;

/* Pick up values from tables; */


/* zero for max => infinity */

/* Common code for all repeated single character type matches */


REPEATTYPE:
ctype = *ecode++;

/* Code for the character type */

/* First, ensure the minimum number of matches are present. Use inline
code for maximizing the speed, and do the type test once at the start
(i.e. keep it out of the loop). Also we can test that there are at least
the minimum number of bytes before we start, except when doing '.' in
UTF8 mode. Leave the test in in all cases; in the special case we have
to test after each character. */
if (min > md->end_subject - eptr) return FALSE;
if (min > 0) switch(ctype)
{
case OP_ANY:
/* Non-UTF8 can be faster */
if ((ims & PCRE_DOTALL) == 0)
{ for (i = 1; i <= min; i++) if (*eptr++ == NEWLINE) return FALSE; }
else eptr += min;
break;
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
break;
case OP_DIGIT:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
break;
case OP_NOT_WHITESPACE:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
break;
-86-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611

Saturday, June 16, 2012 11:29 PM

case OP_WHITESPACE:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
break;
case OP_NOT_WORDCHAR:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_word) != 0)
return FALSE;
break;
case OP_WORDCHAR:
for (i = 1; i <= min; i++)
if ((md->ctypes[*eptr++] & ctype_word) == 0)
return FALSE;
break;
}
/* If min = max, continue at the same level without recursing */
if (min == max) continue;
/* If minimizing, we have to test the rest of the pattern before each
subsequent match. */
if (minimize)
{
for (i = min;; i++)
{
if ((mstat = match(eptr, ecode, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
if (i >= max || eptr >= md->end_subject) return FALSE;
c = *eptr++;
switch(ctype)
{
case OP_ANY:
if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return FALSE;
break;
case OP_NOT_DIGIT:
if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
break;
case OP_DIGIT:
if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
break;
case OP_NOT_WHITESPACE:
if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
break;

-87-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664

Saturday, June 16, 2012 11:29 PM

case OP_WHITESPACE:
if ((md->ctypes[c] & ctype_space) == 0) return FALSE;
break;
case OP_NOT_WORDCHAR:
if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
break;
case OP_WORDCHAR:
if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
break;
}

}
/* Control never gets here */
}

/* If maximizing it is worth using inline code for speed, doing the type
test once at the start (i.e. keep it out of the loop). */
else
{
const uschar *pp = eptr;
switch(ctype)
{
case OP_ANY:
/* Special code is required for UTF8, but when the maximum is unlimited
we don't need it. */
/* Non-UTF8 can be faster */
if ((ims & PCRE_DOTALL) == 0)
{
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || *eptr == NEWLINE) break;
eptr++;
}
}
else
{
c = max - min;
if (c > md->end_subject - eptr) c = md->end_subject - eptr;
eptr += c;
}
break;
case OP_NOT_DIGIT:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
break;
eptr++;
}
-88-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717

Saturday, June 16, 2012 11:29 PM

break;
case OP_DIGIT:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
break;
eptr++;
}
break;
case OP_NOT_WHITESPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
break;
eptr++;
}
break;
case OP_WHITESPACE:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
break;
eptr++;
}
break;
case OP_NOT_WORDCHAR:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
break;
eptr++;
}
break;
case OP_WORDCHAR:
for (i = min; i < max; i++)
{
if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
break;
eptr++;
}
break;
}
while (eptr >= pp)
{
if ((mstat = match(eptr--, ecode, offset_top, md, ims, eptrb, 0)) != 0)
return mstat;
}
-89-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770

Saturday, June 16, 2012 11:29 PM

return FALSE;
}
/* Control never gets here */
/* There's been some horrible disaster. */
default:
DPRINTF(("Unknown opcode %d\n", *ecode));
md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
return FALSE;
}
/* Do not stick any code in here without much thought; it is assumed
that "continue" in the code above comes out to here to repeat the main
loop. */
}
/* End of main loop */
/* Control never reaches here */
}

/*************************************************
*
Execute a Regular Expression
*
*************************************************/
/* This function applies a compiled re to a subject string and picks out
portions of the string if it matches. Two elements in the vector are set for
each substring: the offsets to the start and end of the substring.
Arguments:
external_re
external_extra
subject
length
start_offset
options
offsets
offsetcount
Returns:

*/

points to the compiled expression


points to "hints" from pcre_study() or is NULL
points to the subject string
length of subject string (may contain binary zeros)
where to start in the subject string
option bits
points to a vector of ints to be filled in with offsets
the number of elements in the vector
> 0 =>
= 0 =>
-1 =>
< -1 =>

success; value is the number of elements filled in


success, but offsets is not big enough
failed to match
some kind of unexpected problem

int pcre_exec(external_re, external_extra, subject, length, start_offset,


options, offsets, offsetcount)
const pcre *external_re;
const pcre_extra *external_extra;
const char *subject;
int length, start_offset, options, *offsets, offsetcount;
-90-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823

Saturday, June 16, 2012 11:29 PM

{
int resetcount, ocount;
int first_char = -1;
int req_char = -1;
int req_char2 = -1;
unsigned long int ims = 0;
match_data match_block;
const uschar *start_bits = NULL;
const uschar *start_match = (const uschar *)subject + start_offset;
const uschar *end_subject;
const uschar *req_char_ptr = start_match - 1;
const real_pcre *re = (const real_pcre *)external_re;
const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
BOOL using_temporary_offsets = FALSE;
BOOL anchored;
BOOL startline;
int mstat;
/* TM3 modification */
if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
if (re == NULL || subject == NULL ||
(offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
mudstate.wild_times_lev = 0;

/* TM3 modification */

anchored = ((re->options | options) & PCRE_ANCHORED) != 0;


startline = (re->options & PCRE_STARTLINE) != 0;
match_block.start_pattern = re->code;
match_block.start_subject = (const uschar *)subject;
match_block.end_subject = match_block.start_subject + length;
end_subject = match_block.end_subject;
match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
match_block.utf8 = (re->options & PCRE_UTF8) != 0;
match_block.notbol = (options & PCRE_NOTBOL) != 0;
match_block.noteol = (options & PCRE_NOTEOL) != 0;
match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
match_block.errorcode = PCRE_ERROR_NOMATCH;

/* Default error */

match_block.lcc = re->tables + lcc_offset;


match_block.ctypes = re->tables + ctypes_offset;
/* The ims options can vary during the matching as a result of the presence
of (?ims) items in the pattern. They are kept in a local variable so that
restoring at the exit of a group is easy. */
ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
/* If the expression has got more back references than the offsets supplied can
-91-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876

Saturday, June 16, 2012 11:29 PM

hold, we get a temporary bit of working store to use during the matching.
Otherwise, we can use the vector supplied, rounding down its size to a multiple
of 3. */
ocount = offsetcount - (offsetcount % 3);
if (re->top_backref > 0 && re->top_backref >= ocount/3)
{
ocount = re->top_backref * 3 + 3;
match_block.offset_vector = (int *)pcre_malloc(ocount * sizeof(int));
if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
using_temporary_offsets = TRUE;
DPRINTF(("Got memory to hold back references\n" ));
}
else match_block.offset_vector = offsets;
match_block.offset_end = ocount;
match_block.offset_max = (2*ocount)/3;
match_block.offset_overflow = FALSE;
/* Compute the minimum number of offsets that we need to reset each time. Doing
this makes a huge difference to execution time when there aren't many brackets
in the pattern. */
resetcount = 2 + re->top_bracket * 2;
if (resetcount > offsetcount) resetcount = ocount;
/* Reset the working variable associated with each extraction. These should
never be used unless previously set, but they get saved and restored, and so we
initialize them to avoid reading uninitialized locations. */
if (match_block.offset_vector != NULL)
{
register int *iptr = match_block.offset_vector + ocount;
register int *iend = iptr - resetcount/2 + 1;
while (--iptr >= iend) *iptr = -1;
}
/* Set up the first character to match, if available. The first_char value is
never set for an anchored regular expression, but the anchoring may be forced
at run time, so we have to test for anchoring. The first char may be unset for
an unanchored pattern, of course. If there's no first char and the pattern was
studied, there may be a bitmap of possible first characters. */
if (!anchored)
{
if ((re->options & PCRE_FIRSTSET) != 0)
{
first_char = re->first_char;
if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
}
else
if (!startline && extra != NULL &&
-92-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929

Saturday, June 16, 2012 11:29 PM

(extra->options & PCRE_STUDY_MAPPED) != 0)


start_bits = extra->start_bits;

/* For anchored or unanchored matches, there may be a "last known required


character" set. If the PCRE_CASELESS is set, implying that the match starts
caselessly, or if there are any changes of this flag within the regex, set up
both cases of the character. Otherwise set the two values the same, which will
avoid duplicate testing (which takes significant time). This covers the vast
majority of cases. It will be suboptimal when the case flag changes in a regex
and the required character in fact is caseful. */
if ((re->options & PCRE_REQCHSET) != 0)
{
req_char = re->req_char;
req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0)?
(re->tables + fcc_offset)[req_char] : req_char;
}
/* Loop for handling unanchored repeated matching attempts; for anchored regexs
the loop runs just once. */
do

{
int rc;
register int *iptr = match_block.offset_vector;
register int *iend = iptr + resetcount;
/* Reset the maximum number of extractions we might see. */
while (iptr < iend) *iptr++ = -1;
/* Advance to a unique first char if possible */
if (first_char >= 0)
{
if ((ims & PCRE_CASELESS) != 0)
while (start_match < end_subject &&
match_block.lcc[*start_match] != first_char)
start_match++;
else
while (start_match < end_subject && *start_match != first_char)
start_match++;
}
/* Or to just after \n for a multiline match if possible */
else if (startline)
{
if (start_match > match_block.start_subject + start_offset)
{
while (start_match < end_subject && start_match[-1] != NEWLINE)
start_match++;
-93-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982

Saturday, June 16, 2012 11:29 PM

/* Or to a non-unique first char after study */


else if (start_bits != NULL)
{
while (start_match < end_subject)
{
register int c = *start_match;
if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
}
}
#ifdef PCRE_DEBUG /* Sigh. Some compilers never learn. */
printf(">>>> Match against: ");
pchars(start_match, end_subject - start_match, TRUE, &match_block);
printf("\n");
#endif
/* If req_char is set, we know that that character must appear in the subject
for the match to succeed. If the first character is set, req_char must be
later in the subject; otherwise the test starts at the match point. This
optimization can save a huge amount of backtracking in patterns with nested
unlimited repeats that aren't going to match. We don't know what the state of
case matching may be when this character is hit, so test for it in both its
cases if necessary. However, the different cased versions will not be set up
unless PCRE_CASELESS was given or the casing state changes within the regex.
Writing separate code makes it go faster, as does using an autoincrement and
backing off on a match. */
if (req_char >= 0)
{
register const uschar *p = start_match + ((first_char >= 0)? 1 : 0);
/* We don't need to repeat the search if we haven't yet reached the
place we found it at last time. */
if (p > req_char_ptr)
{
/* Do a single test if no case difference is set up */
if (req_char == req_char2)
{
while (p < end_subject)
{
if (*p++ == req_char) { p--; break; }
}
}
/* Otherwise test for either case */
else
-94-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035

Saturday, June 16, 2012 11:29 PM

{
while (p < end_subject)
{
register int pp = *p++;
if (pp == req_char || pp == req_char2) { p--; break; }
}
}
/* If we can't find the required character, break the matching loop */
if (p >= end_subject) break;
/* If we have found the required character, save the point where we
found it, so that we don't search again next time round the loop if
the start hasn't passed this character yet. */

req_char_ptr = p;
}

/* When a match occurs, substrings will be set for all internal extractions;
we just need to set up the whole thing as substring 0 before returning. If
there were too many extractions, set the return code to zero. In the case
where we had to get some local store to hold offsets for backreferences, copy
those back references that we can. In this case there need not be overflow
if certain parts of the pattern were not used. */
match_block.start_match = start_match;
mstat = match(start_match, re->code, 2, &match_block, ims, NULL,
match_isgroup);
if (mstat < 0)
match_block.errorcode = mstat;
if (mstat != TRUE)
continue;
/* Copy the offset information from temporary store if necessary */
if (using_temporary_offsets)
{
if (offsetcount >= 4)
{
memcpy(offsets + 2, match_block.offset_vector + 2,
(offsetcount - 2) * sizeof(int));
DPRINTF(("Copied offsets from temporary memory\n" ));
}
if (match_block.end_offset_top > offsetcount)
match_block.offset_overflow = TRUE;
DPRINTF(("Freeing temporary memory\n"));
pcre_free(match_block.offset_vector);
}
rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
-95-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088

Saturday, June 16, 2012 11:29 PM

if (offsetcount < 2) rc = 0; else


{
offsets[0] = start_match - match_block.start_subject;
offsets[1] = match_block.end_match_ptr - match_block.start_subject;
}
DPRINTF((">>>> returning %d\n", rc));
return rc;
}
/* This "while" is the end of the "do" above */
while (!anchored &&
match_block.errorcode == PCRE_ERROR_NOMATCH &&
start_match++ < end_subject);
if (using_temporary_offsets)
{
DPRINTF(("Freeing temporary memory\n"));
pcre_free(match_block.offset_vector);
}
DPRINTF((">>>> returning %d\n", match_block.errorcode));
return match_block.errorcode;
}
/* End of original pcre.c */
/* Beginning of study.c */
/*************************************************
*
Set a bit and maybe its alternate case
*
*************************************************/
/* Given a character, set its bit in the table, and also the bit for the other
version of a letter if we are caseless.
Arguments:
start_bits
c
caseless
cd
Returns:
*/

points to the bit map


is the character
the caseless flag
the block with char table pointers
nothing

static void set_bit(start_bits, c, caseless, cd)


uschar *start_bits;
int c;
BOOL caseless;
-96-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141

Saturday, June 16, 2012 11:29 PM

compile_data *cd;
{
start_bits[c/8] |= (1 << (c&7));
if (caseless && (cd->ctypes[c] & ctype_letter) != 0)
start_bits[cd->fcc[c]/8] |= (1 << (cd->fcc[c]&7));
}

/*************************************************
*
Create bitmap of starting chars
*
*************************************************/
/* This function scans a compiled unanchored expression and attempts to build a
bitmap of the set of initial characters. If it can't, it returns FALSE. As time
goes by, we may be able to get more clever at doing this.
Arguments:
code
start_bits
caseless
cd
Returns:
*/

points to an expression
points to a 32-byte table, initialized to 0
the current state of the caseless flag
the block with char table pointers
TRUE if table built, FALSE otherwise

static BOOL set_start_bits(code, start_bits, caseless, cd)


const uschar *code;
uschar *start_bits;
BOOL caseless;
compile_data *cd;
{
register int c;
/* This next statement and the later reference to dummy are here in order to
trick the optimizer of the IBM C compiler for OS/2 into generating correct
code. Apparently IBM isn't going to fix the problem, and we would rather not
disable optimization (in this module it actually makes a big difference, and
the pcre module can use all the optimization it can get). */
volatile int dummy;
do

{
const uschar *tcode = code + 3;
BOOL try_next = TRUE;
while (try_next)
{
/* If a branch starts with a bracket or a positive lookahead assertion,
recurse to set bits from within them. That's all for this branch. */
if ((int)*tcode >= OP_BRA || *tcode == OP_ASSERT)
-97-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194

Saturday, June 16, 2012 11:29 PM

{
if (!set_start_bits(tcode, start_bits, caseless, cd))
return FALSE;
try_next = FALSE;
}
else switch(*tcode)
{
default:
return FALSE;
/* Skip over extended extraction bracket number */
case OP_BRANUMBER:
tcode += 3;
break;
/* Skip over lookbehind and negative lookahead assertions */
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
do tcode += (tcode[1] << 8) + tcode[2]; while (*tcode == OP_ALT);
tcode += 3;
break;
/* Skip over an option setting, changing the caseless flag */
case OP_OPT:
caseless = (tcode[1] & PCRE_CASELESS) != 0;
tcode += 2;
break;
/* BRAZERO does the bracket, but carries on. */
case OP_BRAZERO:
case OP_BRAMINZERO:
if (!set_start_bits(++tcode, start_bits, caseless, cd))
return FALSE;
dummy = 1;
do tcode += (tcode[1] << 8) + tcode[2]; while (*tcode == OP_ALT);
tcode += 3;
break;
/* Single-char * or ? sets the bit and tries the next item */
case OP_STAR:
case OP_MINSTAR:
case OP_QUERY:
case OP_MINQUERY:
set_bit(start_bits, tcode[1], caseless, cd);
tcode += 2;
break;
-98-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247

Saturday, June 16, 2012 11:29 PM

/* Single-char upto sets the bit and tries the next */


case OP_UPTO:
case OP_MINUPTO:
set_bit(start_bits, tcode[3], caseless, cd);
tcode += 4;
break;
/* At least one single char sets the bit and stops */
case OP_EXACT:
tcode++;

/* Fall through */

case OP_CHARS:
tcode++;

/* Fall through */

case OP_PLUS:
case OP_MINPLUS:
set_bit(start_bits, tcode[1], caseless, cd);
try_next = FALSE;
break;
/* Single character type sets the bits and stops */
case OP_NOT_DIGIT:
for (c = 0; c < 32; c++)
start_bits[c] |= ~cd->cbits[c+cbit_digit];
try_next = FALSE;
break;
case OP_DIGIT:
for (c = 0; c < 32; c++)
start_bits[c] |= cd->cbits[c+cbit_digit];
try_next = FALSE;
break;
case OP_NOT_WHITESPACE:
for (c = 0; c < 32; c++)
start_bits[c] |= ~cd->cbits[c+cbit_space];
try_next = FALSE;
break;
case OP_WHITESPACE:
for (c = 0; c < 32; c++)
start_bits[c] |= cd->cbits[c+cbit_space];
try_next = FALSE;
break;
case OP_NOT_WORDCHAR:
for (c = 0; c < 32; c++)
start_bits[c] |= ~cd->cbits[c+cbit_word];
try_next = FALSE;
-99-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300

Saturday, June 16, 2012 11:29 PM

break;
case OP_WORDCHAR:
for (c = 0; c < 32; c++)
start_bits[c] |= cd->cbits[c+cbit_word];
try_next = FALSE;
break;
/* One or more character type fudges the pointer and restarts, knowing
it will hit a single character type and stop there. */
case OP_TYPEPLUS:
case OP_TYPEMINPLUS:
tcode++;
break;
case OP_TYPEEXACT:
tcode += 3;
break;
/* Zero or more repeats of character types set the bits and then
try again. */
case OP_TYPEUPTO:
case OP_TYPEMINUPTO:
tcode += 2;

/* Fall through */

case OP_TYPESTAR:
case OP_TYPEMINSTAR:
case OP_TYPEQUERY:
case OP_TYPEMINQUERY:
switch(tcode[1])
{
case OP_NOT_DIGIT:
for (c = 0; c < 32; c++)
start_bits[c] |= ~cd->cbits[c+cbit_digit];
break;
case OP_DIGIT:
for (c = 0; c < 32; c++)
start_bits[c] |= cd->cbits[c+cbit_digit];
break;
case OP_NOT_WHITESPACE:
for (c = 0; c < 32; c++)
start_bits[c] |= ~cd->cbits[c+cbit_space];
break;
case OP_WHITESPACE:
for (c = 0; c < 32; c++)
start_bits[c] |= cd->cbits[c+cbit_space];
break;

-100-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353

Saturday, June 16, 2012 11:29 PM

case OP_NOT_WORDCHAR:
for (c = 0; c < 32; c++)
start_bits[c] |= ~cd->cbits[c+cbit_word];
break;
case OP_WORDCHAR:
for (c = 0; c < 32; c++)
start_bits[c] |= cd->cbits[c+cbit_word];
break;
}
tcode += 2;
break;
/* Character class: set the bits and either carry on or not,
according to the repeat count. */
case OP_CLASS:
{
tcode++;
for (c = 0; c < 32; c++) start_bits[c] |= tcode[c];
tcode += 32;
switch (*tcode)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRQUERY:
case OP_CRMINQUERY:
tcode++;
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
if (((tcode[1] << 8) + tcode[2]) == 0) tcode += 5;
else try_next = FALSE;
break;
default:
try_next = FALSE;
break;
}

}
break; /* End of class handling */
}

/* End of switch */
/* End of try_next loop */

code += (code[1] << 8) + code[2];


}
while (*code == OP_ALT);
return TRUE;
}

/* Advance to next branch */

-101-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406

Saturday, June 16, 2012 11:29 PM

/*************************************************
*
Study a compiled expression
*
*************************************************/
/* This function is handed a compiled expression that it must study to produce
information that will speed up the matching. It returns a pcre_extra block
which then gets handed back to pcre_exec().
Arguments:
re
options
errorptr
Returns:
*/

points to the compiled expression


contains option bits
points to where to place error messages;
set NULL unless error
pointer to a pcre_extra block,
NULL on error or if no optimization possible

pcre_extra *pcre_study(external_re, options, errorptr)


const pcre *external_re;
int options;
const char **errorptr;
{
uschar start_bits[32];
real_pcre_extra *extra;
const real_pcre *re = (const real_pcre *)external_re;
compile_data compile_block;
*errorptr = NULL;
if (re == NULL || re->magic_number != MAGIC_NUMBER)
{
*errorptr = "argument is not a compiled regular expression" ;
return NULL;
}
if ((options & ~PUBLIC_STUDY_OPTIONS) != 0)
{
*errorptr = "unknown or incorrect option bit(s) set" ;
return NULL;
}
/* For an anchored pattern, or an unanchored pattern that has a first
char, or a multiline pattern that matches only at "line starts", no
further processing at present. */
if ((re->options & (PCRE_ANCHORED|PCRE_FIRSTSET|PCRE_STARTLINE)) != 0)
return NULL;
/* Set the character tables in the block which is passed around */

-102-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459

Saturday, June 16, 2012 11:29 PM

compile_block.lcc = re->tables + lcc_offset;


compile_block.fcc = re->tables + fcc_offset;
compile_block.cbits = re->tables + cbits_offset;
compile_block.ctypes = re->tables + ctypes_offset;
/* See if we can find a fixed set of initial characters for the pattern. */
memset(start_bits, 0, 32 * sizeof(uschar));
if (!set_start_bits(re->code, start_bits, (re->options & PCRE_CASELESS) != 0,
&compile_block)) return NULL;
/* Get an "extra" block and put the information therein. */
extra = (real_pcre_extra *)pcre_malloc(sizeof(real_pcre_extra));
if (extra == NULL)
{
*errorptr = "failed to get memory";
return NULL;
}
extra->options = PCRE_STUDY_MAPPED;
memcpy(extra->start_bits, start_bits, sizeof(start_bits));
return (pcre_extra *)extra;
}
/* End of study.c */
/* Beginning of get.c */
/* This module contains some convenience functions for extracting substrings
from the subject string after a regex match has succeeded. The original idea
for these functions came from Scott Wimer <scottw@cgibuilder.com>. */
/* TM3 modification: Removed everything but pcre_copy_substring(). */
/*************************************************
*
Copy captured string to given buffer
*
*************************************************/
/* This function copies a single captured substring into a given buffer.
Note that we use memcpy() rather than strncpy() in case there are binary zeros
in the string.
Arguments:
subject
ovector
stringcount

the subject string that was matched


pointer to the offsets table
the number of substrings that were captured
(i.e. the yield of the pcre_exec call, unless
that was zero, in which case it should be 1/3
of the offset table size)
-103-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512

stringnumber
buffer
size
Returns:

*/

Saturday, June 16, 2012 11:29 PM

the number of the required substring


where to put the substring
the size of the buffer
if successful:
the length of the copied string, not including the zero
that is put on the end; can be zero
if not successful:
PCRE_ERROR_NOMEMORY (-6) buffer too small
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring

int pcre_copy_substring(subject, ovector, stringcount, stringnumber,


buffer, size)
const char *subject;
int *ovector, stringcount, stringnumber;
char *buffer;
int size;
{
int yield;
if (stringnumber < 0 || stringnumber >= stringcount)
return PCRE_ERROR_NOSUBSTRING;
stringnumber *= 2;
yield = ovector[stringnumber+1] - ovector[stringnumber];
if (size < yield + 1) return PCRE_ERROR_NOMEMORY;
memcpy(buffer, subject + ovector[stringnumber], yield);
buffer[yield] = 0;
return yield;
}
/* End of get.c */
/* Beginning of maketables.c */
/*************************************************
*
Create PCRE character tables
*
*************************************************/
/* This function builds a set of character tables for use by PCRE and returns
a pointer to them. They are build using the ctype functions, and consequently
their contents will depend upon the current locale setting. When compiled as
part of the library, the store is obtained via pcre_malloc(), but when compiled
inside dftables, use malloc().
Arguments:
Returns:
*/

none
pointer to the contiguous block of data

const unsigned char *pcre_maketables()


{
unsigned char *yield, *p;
int i;

-104-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565

Saturday, June 16, 2012 11:29 PM

#ifndef DFTABLES
yield = (unsigned char*)pcre_malloc(tables_length);
#else
yield = (unsigned char*)malloc(tables_length);
#endif
if (yield == NULL) return NULL;
p = yield;
/* First comes the lower casing table */
for (i = 0; i < 256; i++) *p++ = tolower(i);
/* Next the case-flipping table */
for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i);
/* Then the character class tables. Don't try to be clever and save effort
on exclusive ones - in some locales things may be different. */
memset(p, 0, cbit_length);
for (i = 0; i < 256; i++)
{
if (isdigit(i))
{
p[cbit_digit + i/8] |= 1 << (i&7);
p[cbit_word
+ i/8] |= 1 << (i&7);
}
if (isupper(i))
{
p[cbit_upper + i/8] |= 1 << (i&7);
p[cbit_word
+ i/8] |= 1 << (i&7);
}
if (islower(i))
{
p[cbit_lower + i/8] |= 1 << (i&7);
p[cbit_word
+ i/8] |= 1 << (i&7);
}
if (i == '_')
p[cbit_word
+ i/8] |=
if (isspace(i)) p[cbit_space + i/8] |=
if (isxdigit(i))p[cbit_xdigit + i/8] |=
if (isgraph(i)) p[cbit_graph + i/8] |=
if (isprint(i)) p[cbit_print + i/8] |=
if (ispunct(i)) p[cbit_punct + i/8] |=
if (iscntrl(i)) p[cbit_cntrl + i/8] |=
}
p += cbit_length;

1
1
1
1
1
1
1

/* Finally, the character type table */


for (i = 0; i < 256; i++)
{
int x = 0;
-105-

<<
<<
<<
<<
<<
<<
<<

(i&7);
(i&7);
(i&7);
(i&7);
(i&7);
(i&7);
(i&7);

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.c

5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581

Saturday, June 16, 2012 11:29 PM

if (isspace(i)) x += ctype_space;
if (isalpha(i)) x += ctype_letter;
if (isdigit(i)) x += ctype_digit;
if (isxdigit(i)) x += ctype_xdigit;
if (isalnum(i) || i == '_') x += ctype_word;
if (strchr("*+?{^.$|()[", i) != 0) x += ctype_meta;
*p++ = x;
}
return yield;
}
/* End of maketables.c */
/* -- End of TinyMUSH 3 version of pcre.c */

-106-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:05 PM

/*************************************************
*
Perl-Compatible Regular Expressions
*
*************************************************/
/* Copyright (c) 1997-2001 University of Cambridge */
/* This file has been modified for inclusion in TinyMUSH 3.
* Changes include:
*
Alteration of function declarations to conform with TM3 standard.
*
Inclusion of internals.h as part of this file.
*/
#ifndef _PCRE_H
#define _PCRE_H
/* The file pcre.h is build by "configure". Do not edit it; instead
make changes to pcre.in. */
#define PCRE_MAJOR
#define PCRE_MINOR
#define PCRE_DATE

3
9
02-Jan-2002

/* TM3 modification: We need this. */


#define PCRE_MAX_OFFSETS 99
/* TM3 modification: This would have been defined in config.h */
#define NEWLINE '\n'
/* Win32 uses DLL by default */
#ifdef _WIN32
# ifdef STATIC
# define PCRE_DL_IMPORT
# else
# define PCRE_DL_IMPORT __declspec(dllimport)
# endif
#else
# define PCRE_DL_IMPORT
#endif
/* Allow for C++ users */
#ifdef __cplusplus
extern "C" {
#endif
/* Options */
#define PCRE_CASELESS
#define PCRE_MULTILINE
#define PCRE_DOTALL

0x0001
0x0002
0x0004
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

#define
#define
#define
#define
#define
#define
#define
#define
#define

PCRE_EXTENDED
PCRE_ANCHORED
PCRE_DOLLAR_ENDONLY
PCRE_EXTRA
PCRE_NOTBOL
PCRE_NOTEOL
PCRE_UNGREEDY
PCRE_NOTEMPTY
PCRE_UTF8

Saturday, June 16, 2012 11:05 PM

0x0008
0x0010
0x0020
0x0040
0x0080
0x0100
0x0200
0x0400
0x0800

/* Exec-time and get-time error codes */


#define
#define
#define
#define
#define
#define
#define

PCRE_ERROR_NOMATCH
PCRE_ERROR_NULL
PCRE_ERROR_BADOPTION
PCRE_ERROR_BADMAGIC
PCRE_ERROR_UNKNOWN_NODE
PCRE_ERROR_NOMEMORY
PCRE_ERROR_NOSUBSTRING

(-1)
(-2)
(-3)
(-4)
(-5)
(-6)
(-7)

/* TM3 modification: Limits exceeded. */


#define PCRE_ERROR_BACKTRACK_LIMIT (-100)
/* Request types for pcre_fullinfo() */
#define
#define
#define
#define
#define
#define
#define

PCRE_INFO_OPTIONS
PCRE_INFO_SIZE
PCRE_INFO_CAPTURECOUNT
PCRE_INFO_BACKREFMAX
PCRE_INFO_FIRSTCHAR
PCRE_INFO_FIRSTTABLE
PCRE_INFO_LASTLITERAL

0
1
2
3
4
5
6

/* Types */
struct real_pcre;
struct real_pcre_extra;

/* declaration; the definition is private */


/* declaration; the definition is private */

typedef struct real_pcre pcre;


typedef struct real_pcre_extra pcre_extra;
/* TM3 modification: Replace with #defines calling XMALLOC and XFREE. */
#define pcre_malloc(x)
#define pcre_free(x)

XMALLOC((x), "pcre")
XFREE((x), "pcre")

/* Functions */
extern pcre * FDECL(pcre_compile, (const char *, int, const char **, int *,
const unsigned char *));
extern int FDECL(pcre_copy_substring, (const char *, int *, int, int, char *, int));
extern int FDECL(pcre_exec, (const pcre *, const pcre_extra *, const char *,
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:05 PM

int, int, int, int *, int));


extern const unsigned char * NDECL(pcre_maketables);
extern pcre_extra * FDECL(pcre_study, (const pcre *, int, const char **));
#ifdef __cplusplus
} /* extern "C" */
#endif
/* End of original pcre.h, beginning of internal.h */
/* This header contains definitions that are shared between the different
modules, but which are not relevant to the outside. */
/* In case there is no definition of offsetof() provided - though any proper
Standard C system should have one. */
#ifndef offsetof
#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
#endif
/* These are the public options that can change during matching. */
#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
/* Private options flags start at the most significant end of the four bytes,
but skip the top bit so we can use ints for convenience without getting tangled
with negative values. The public options defined in pcre.h start at the least
significant end. Make sure they don't overlap, though now that we have expanded
to four bytes there is plenty of space. */
#define
#define
#define
#define
#define

PCRE_FIRSTSET
PCRE_REQCHSET
PCRE_STARTLINE
PCRE_INGROUP
PCRE_ICHANGED

0x40000000
0x20000000
0x10000000
0x08000000
0x04000000

/*
/*
/*
/*
/*

first_char is set */
req_char is set */
start after \n for multiline */
compiling inside a group */
i option changes within regex */

/* Options for the "extra" block produced by pcre_study(). */


#define PCRE_STUDY_MAPPED

0x01

/* a map of starting chars exists */

/* Masks for identifying the public options which are permitted at compile
time, run time or study time, respectively. */
#define PUBLIC_OPTIONS \
(PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \
PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8)
#define PUBLIC_EXEC_OPTIONS \
(PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
#define PUBLIC_STUDY_OPTIONS 0

/* None defined */

/* Magic number to provide a small check against being handed junk. */


-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

#define MAGIC_NUMBER

0x50435245UL

Saturday, June 16, 2012 11:05 PM

/* 'PCRE' */

/* Miscellaneous definitions */
typedef int BOOL;
#define FALSE
#define TRUE

0
1

/* Escape items that are just an encoding of a particular data value. Note that
ESC_N is defined as yet another macro, which is set in config.h to either \n
(the default) or \r (which some people want). */
#ifndef ESC_E
#define ESC_E 27
#endif
#ifndef ESC_F
#define ESC_F '\f'
#endif
#ifndef ESC_N
#define ESC_N NEWLINE
#endif
#ifndef ESC_R
#define ESC_R '\r'
#endif
#ifndef ESC_T
#define ESC_T '\t'
#endif
/* These are escaped items that aren't just an encoding of a particular data
value such as \n. They must have non-zero values, as check_escape() returns
their negation. Also, they must appear in the same order as in the opcode
definitions below, up to ESC_z. The final one must be ESC_REF as subsequent
values are used for \1, \2, \3, etc. There is a test in the code for an escape
greater than ESC_b and less than ESC_Z to detect the types that may be
repeated. If any new escapes are put in-between that don't consume a character,
that code will have to change. */
enum { ESC_A = 1, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w,
ESC_Z, ESC_z, ESC_REF };
/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
OP_EOD must correspond in order to the list of escapes immediately above. */
enum {
OP_END,

/* End of pattern */

-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:05 PM

/* Values corresponding to backslashed metacharacters */


OP_SOD,
/* Start of data: \A */
OP_NOT_WORD_BOUNDARY, /* \B */
OP_WORD_BOUNDARY,
/* \b */
OP_NOT_DIGIT,
/* \D */
OP_DIGIT,
/* \d */
OP_NOT_WHITESPACE,
/* \S */
OP_WHITESPACE,
/* \s */
OP_NOT_WORDCHAR,
/* \W */
OP_WORDCHAR,
/* \w */
OP_EODN,
/* End of data or \n at end of data: \Z. */
OP_EOD,
/* End of data: \z */
OP_OPT,
OP_CIRC,
OP_DOLL,
OP_ANY,
OP_CHARS,
OP_NOT,

/*
/*
/*
/*
/*
/*

Set runtime options */


Start of line - varies with multiline switch */
End of line - varies with multiline switch */
Match any character */
Match string of characters */
Match anything but the following char */

OP_STAR,
OP_MINSTAR,
OP_PLUS,
OP_MINPLUS,
OP_QUERY,
OP_MINQUERY,
OP_UPTO,
OP_MINUPTO,
OP_EXACT,

/*
/*
/*
/*

The maximizing and minimizing versions of */


all these opcodes must come in pairs, with */
the minimizing one second. */
This first set applies to single characters */

OP_NOTSTAR,
OP_NOTMINSTAR,
OP_NOTPLUS,
OP_NOTMINPLUS,
OP_NOTQUERY,
OP_NOTMINQUERY,
OP_NOTUPTO,
OP_NOTMINUPTO,
OP_NOTEXACT,

/*
/*
/*
/*

OP_TYPESTAR,
OP_TYPEMINSTAR,
OP_TYPEPLUS,
OP_TYPEMINPLUS,
OP_TYPEQUERY,
OP_TYPEMINQUERY,
OP_TYPEUPTO,
OP_TYPEMINUPTO,
OP_TYPEEXACT,

/*
/*
/*
/*
/*

OP_CRSTAR,
OP_CRMINSTAR,

/* The maximizing and minimizing versions of */


/* all these opcodes must come in pairs, with */

/* From 0 to n matches */
/* Exactly n matches */
The maximizing and minimizing versions of */
all these opcodes must come in pairs, with */
the minimizing one second. */
This first set applies to "not" single characters */

/* From 0 to n matches */
/* Exactly n matches */
The maximizing and minimizing versions of */
all these opcodes must come in pairs, with */
the minimizing one second. These codes must */
be in exactly the same order as those above. */
This set applies to character types such as \d */

/* From 0 to n matches */
/* Exactly n matches */

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:05 PM

OP_CRPLUS,
OP_CRMINPLUS,
OP_CRQUERY,
OP_CRMINQUERY,
OP_CRRANGE,
OP_CRMINRANGE,

/* the minimizing one second. These codes must */


/* be in exactly the same order as those above. */
/* These are for character classes and back refs */

OP_CLASS,
OP_REF,
OP_RECURSE,

/* Match a character class */


/* Match a back reference */
/* Match this pattern recursively */

OP_ALT,
OP_KET,
OP_KETRMAX,
OP_KETRMIN,

/*
/*
/*
/*

/* These are different to the three seta above. */

Start of alternation */
End of group that doesn't have an unbounded repeat */
These two must remain together and in this */
order. They are for groups the repeat for ever. */

/* The assertions must come before ONCE and COND */


OP_ASSERT,
OP_ASSERT_NOT,
OP_ASSERTBACK,
OP_ASSERTBACK_NOT,
OP_REVERSE,

/*
/*
/*
/*
/*

Positive lookahead */
Negative lookahead */
Positive lookbehind */
Negative lookbehind */
Move pointer back - used in lookbehind assertions */

/* ONCE and COND must come after the assertions, with ONCE first, as there's
a test for >= ONCE for a subpattern that isn't an assertion. */

};

OP_ONCE,
OP_COND,
OP_CREF,

/* Once matched, don't back up into the subpattern */


/* Conditional group */
/* Used to hold an extraction string number (cond ref) */

OP_BRAZERO,
OP_BRAMINZERO,

/* These two must remain together and in this */


/* order. */

OP_BRANUMBER,

/* Used for extracting brackets whose number is greater


than can fit into an opcode. */

OP_BRA

/* This and greater values are used for brackets that


extract substrings up to a basic limit. After that,
use is made of OP_BRANUMBER. */

/* The highest extraction number before we have to start using additional


bytes. (Originally PCRE didn't have support for extraction counts higher than
this number.) The value is limited by the number of opcodes left after OP_BRA,
i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional
opcodes. */
#define EXTRACT_BASIC_MAX

150

/* The texts of compile-time error messages are defined as macros here so that
they can be accessed by the POSIX wrapper and converted into error codes. Yes,
I could have used error codes in the first place, but didn't feel like changing
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:05 PM

just to accommodate the POSIX wrapper. */


#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

ERR1
ERR2
ERR3
ERR4
ERR5
ERR6
ERR7
ERR8
ERR9
ERR10
ERR11
ERR12
ERR13
ERR14
ERR15
ERR16
ERR17
ERR18
ERR19
ERR20
ERR21
ERR22
ERR23
ERR24
ERR25
ERR26
ERR27
ERR28
ERR29
ERR30
ERR31
ERR32
ERR33
ERR34
ERR35

"\\ at end of pattern"


"\\c at end of pattern"
"unrecognized character follows \\"
"numbers out of order in {} quantifier"
"number too big in {} quantifier"
"missing terminating ] for character class"
"invalid escape sequence in character class"
"range out of order in character class"
"nothing to repeat"
"operand of unlimited repeat could match the empty string"
"internal error: unexpected repeat"
"unrecognized character after (?"
"unused error"
"missing )"
"back reference to non-existent subpattern"
"erroffset passed as NULL"
"unknown option bit(s) set"
"missing ) after comment"
"parentheses nested too deeply"
"regular expression too large"
"failed to get memory"
"unmatched parentheses"
"internal error: code overflow"
"unrecognized character after (?<"
"lookbehind assertion is not fixed length"
"malformed number after (?("
"conditional group contains more than two branches"
"assertion expected after (?("
"(?p must be followed by )"
"unknown POSIX class name"
"POSIX collating elements are not supported"
"this version of PCRE is not compiled with PCRE_UTF8 support"
"characters with values > 255 are not yet supported in classes"
"character value in \\x{...} sequence is too large"
"invalid condition (?(0)"

/* All character handling must be done as unsigned characters. Otherwise there


are problems with top-bit-set characters and functions such as isspace().
However, we leave the interface to the outside world as char *, because that
should make things easier for callers. We define a short type for unsigned char
to save lots of typing. I tried "uchar", but it causes problems on Digital
Unix, where it is defined in sys/types, so use "uschar" instead. */
typedef unsigned char uschar;
/* The real format of the start of the pcre block; the actual code vector
runs on as long as necessary after the end. */
typedef struct real_pcre {
unsigned long int magic_number;
size_t size;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:05 PM

const unsigned char *tables;


unsigned long int options;
unsigned short int top_bracket;
unsigned short int top_backref;
uschar first_char;
uschar req_char;
uschar code[1];
} real_pcre;
/* The real format of the extra block returned by pcre_study(). */
typedef struct real_pcre_extra {
uschar options;
uschar start_bits[32];
} real_pcre_extra;
/* Structure for passing "static" information around between the functions
doing the compiling, so that they are thread-safe. */
typedef struct compile_data {
const uschar *lcc;
const uschar *fcc;
const uschar *cbits;
const uschar *ctypes;
} compile_data;

/*
/*
/*
/*

Points
Points
Points
Points

to
to
to
to

lower casing table */


case-flipping table */
character type table */
table of type maps */

/* Structure for passing "static" information around between the functions


doing the matching, so that they are thread-safe. */
typedef struct match_data {
int
errorcode;
int
*offset_vector;
int
offset_end;
int
offset_max;
const uschar *lcc;
const uschar *ctypes;
BOOL
offset_overflow;
BOOL
notbol;
BOOL
noteol;
BOOL
utf8;
BOOL
endonly;
BOOL
notempty;
const uschar *start_pattern;
const uschar *start_subject;
const uschar *end_subject;
const uschar *start_match;
const uschar *end_match_ptr;
int
end_offset_top;
} match_data;

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

As it says */
Offset vector */
One past the end */
The maximum usable for return data */
Points to lower casing table */
Points to table of type maps */
Set if too many extractions */
NOTBOL flag */
NOTEOL flag */
UTF8 flag */
Dollar not before final \n */
Empty string match not wanted */
For use when recursing */
Start of the subject string */
End of the subject string */
Start of this match attempt */
Subject position at end match */
Highwater mark at end of match */

/* Bit definitions for entries in the pcre_ctypes table. */

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\pcre.h

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459

#define
#define
#define
#define
#define
#define

ctype_space
ctype_letter
ctype_digit
ctype_xdigit
ctype_word
ctype_meta

0x01
0x02
0x04
0x08
0x10
0x80

Saturday, June 16, 2012 11:05 PM

/* alphameric or '_' */
/* regexp meta char or zero (end pattern) */

/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
of bits for a class map. Some classes are built by combining these tables. */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

cbit_space
cbit_xdigit
cbit_digit
cbit_upper
cbit_lower
cbit_word
cbit_graph
cbit_print
cbit_punct
cbit_cntrl
cbit_length

0
32
64
96
128
160
192
224
256
288
320

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

[:space:] or \s */
[:xdigit:] */
[:digit:] or \d */
[:upper:] */
[:lower:] */
[:word:] or \w */
[:graph:] */
[:print:] */
[:punct:] */
[:cntrl:] */
Length of the cbits table */

/* Offsets of the various tables from the base tables pointer, and
total length. */
#define
#define
#define
#define
#define

lcc_offset
fcc_offset
cbits_offset
ctypes_offset
tables_length

0
256
512
(cbits_offset + cbit_length)
(ctypes_offset + 256)

/* End of internal.h */
#endif /* End of pcre.h */

-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:29 PM

/* player.c */
/* $Id: player.c,v 1.32 2008/01/08 23:35:24 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include "attrs.h" /* required by code */
#include "powers.h" /* required by code */
#include "match.h" /* required by code */
#define NUM_GOOD
#define NUM_BAD

4
3

/* # of successful logins to save data for */


/* # of failed logins to save data for */

typedef struct hostdtm HOSTDTM;


struct hostdtm {
char *host;
char *dtm;
};
typedef struct logindata LDATA;
struct logindata {
HOSTDTM good[NUM_GOOD];
HOSTDTM bad[NUM_BAD];
int tot_good;
int tot_bad;
int new_bad;
};
extern int FDECL(can_set_home, (dbref, dbref, dbref));
extern dbref FDECL(clone_home, (dbref, dbref));
/* --------------------------------------------------------------------------* decrypt_logindata, encrypt_logindata: Decode and encode login info.
*/
static void decrypt_logindata(atrbuf, info)
char *atrbuf;
LDATA *info;
{
int i;
info->tot_good = 0;
info->tot_bad = 0;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:29 PM

info->new_bad = 0;
for (i = 0; i < NUM_GOOD; i++) {
info->good[i].host = NULL;
info->good[i].dtm = NULL;
}
for (i = 0; i < NUM_BAD; i++) {
info->bad[i].host = NULL;
info->bad[i].dtm = NULL;
}

if (*atrbuf == '#') {
atrbuf++;
info->tot_good = atoi(grabto(&atrbuf, ';'));
for (i = 0; i < NUM_GOOD; i++) {
info->good[i].host = grabto(&atrbuf, ';');
info->good[i].dtm = grabto(&atrbuf, ';');
}
info->new_bad = atoi(grabto(&atrbuf, ';'));
info->tot_bad = atoi(grabto(&atrbuf, ';'));
for (i = 0; i < NUM_BAD; i++) {
info->bad[i].host = grabto(&atrbuf, ';');
info->bad[i].dtm = grabto(&atrbuf, ';');
}
}

static void encrypt_logindata(atrbuf, info)


char *atrbuf;
LDATA *info;
{
char *bp, nullc;
int i;
/* Make sure the SPRINTF call tracks NUM_GOOD and NUM_BAD for the
* number of host/dtm pairs of each type.
*/
nullc = '\0';
for (i = 0; i < NUM_GOOD; i++) {
if (!info->good[i].host)
info->good[i].host = &nullc;
if (!info->good[i].dtm)
info->good[i].dtm = &nullc;
}
for (i = 0; i < NUM_BAD; i++) {
if (!info->bad[i].host)
info->bad[i].host = &nullc;
if (!info->bad[i].dtm)
info->bad[i].dtm = &nullc;
}
bp = alloc_lbuf("encrypt_logindata");
sprintf(bp, "#%d;%s;%s;%s;%s;%s;%s;%s;%s;%d;%d;%s;%s;%s;%s;%s;%s;" ,
info->tot_good,
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

Saturday, June 16, 2012 11:29 PM

info->good[0].host, info->good[0].dtm,
info->good[1].host, info->good[1].dtm,
info->good[2].host, info->good[2].dtm,
info->good[3].host, info->good[3].dtm,
info->new_bad, info->tot_bad,
info->bad[0].host, info->bad[0].dtm,
info->bad[1].host, info->bad[1].dtm,
info->bad[2].host, info->bad[2].dtm);
strcpy(atrbuf, bp);
free_lbuf(bp);

/* --------------------------------------------------------------------------* record_login: Record successful or failed login attempt.


* If successful, report last successful login and number of failures since
* last successful login.
*/
void record_login(player, isgood, ldate, lhost, lusername)
dbref player;
int isgood;
char *ldate, *lhost, *lusername;
{
LDATA login_info;
char *atrbuf;
dbref aowner;
int aflags, alen, i;
atrbuf = atr_get(player, A_LOGINDATA, &aowner, &aflags, &alen);
decrypt_logindata(atrbuf, &login_info);
if (isgood) {
if (login_info.new_bad > 0) {
notify(player, "");
notify(player,
tprintf("**** %d failed connect%s since your last successful
connect. ****",
login_info.new_bad,
(login_info.new_bad == 1 ? "" : "s")));
notify(player,
tprintf("Most recent attempt was from %s on %s." ,
login_info.bad[0].host,
login_info.bad[0].dtm));
notify(player, "");
login_info.new_bad = 0;
}
if (login_info.good[0].host && *login_info.good[0].host &&
login_info.good[0].dtm && *login_info.good[0].dtm) {
notify(player,
tprintf("Last connect was from %s on %s." ,
login_info.good[0].host,
login_info.good[0].dtm));
}

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

Saturday, June 16, 2012 11:29 PM

for (i = NUM_GOOD - 1; i > 0; i--) {


login_info.good[i].dtm = login_info.good[i - 1].dtm;
login_info.good[i].host = login_info.good[i - 1].host;
}
login_info.good[0].dtm = ldate;
login_info.good[0].host = lhost;
login_info.tot_good++;
if (*lusername)
atr_add_raw(player, A_LASTSITE, tprintf("%s@%s", lusername, lhost));
else
atr_add_raw(player, A_LASTSITE, lhost);
} else {
for (i = NUM_BAD - 1; i > 0; i--) {
login_info.bad[i].dtm = login_info.bad[i - 1].dtm;
login_info.bad[i].host = login_info.bad[i - 1].host;
}
login_info.bad[0].dtm = ldate;
login_info.bad[0].host = lhost;
login_info.tot_bad++;
login_info.new_bad++;
}
encrypt_logindata(atrbuf, &login_info);
atr_add_raw(player, A_LOGINDATA, atrbuf);
free_lbuf(atrbuf);

/* --------------------------------------------------------------------------* check_pass: Test a password to see if it is correct.


*/
int check_pass(player, password)
dbref player;
const char *password;
{
dbref aowner;
int aflags, alen;
char *target;
target = atr_get(player, A_PASS, &aowner, &aflags, &alen);
if (*target && strcmp(target, password) &&
strcmp(crypt(password, "XX"), target)) {
free_lbuf(target);
return 0;
}
free_lbuf(target);
/* This is needed to prevent entering the raw encrypted password from
* working. Do it better if you like, but it's needed.
*/
if ((strlen(password) == 13) &&
(password[0] == 'X') && (password[1] == 'X'))
return 0;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

Saturday, June 16, 2012 11:29 PM

return 1;

/* --------------------------------------------------------------------------* connect_player: Try to connect to an existing player.


*/
dbref connect_player(name, password, host, username, ip_addr)
char *name, *password, *host, *username, *ip_addr;
{
dbref player, aowner;
int aflags, alen;
time_t tt;
char *time_str, *player_last, *allowance;
time(&tt);
time_str = ctime(&tt);
time_str[strlen(time_str) - 1] = '\0';
if ((player = lookup_player(NOTHING, name, 0)) == NOTHING)
return NOTHING;
if (!check_pass(player, password)) {
record_login(player, 0, time_str, host, username);
return NOTHING;
}
time(&tt);
time_str = ctime(&tt);
time_str[strlen(time_str) - 1] = '\0';

/* compare to last connect see if player gets salary */


player_last = atr_get(player, A_LAST, &aowner, &aflags, &alen);
if (strncmp(player_last, time_str, 10) != 0) {
if (Pennies(player) < mudconf.paylimit) {
/* Don't heap coins on players who already have lots of money. */
allowance = atr_pget(player, A_ALLOWANCE, &aowner, &aflags, &alen);
if (*allowance == '\0')
giveto(player, mudconf.paycheck);
else
giveto(player, atoi(allowance));
free_lbuf(allowance);
}
}
atr_add_raw(player, A_LAST, time_str);
free_lbuf(player_last);
if (ip_addr && *ip_addr)
atr_add_raw(player, A_LASTIP, ip_addr);
return player;

/* --------------------------------------------------------------------------* create_player: Create a new player.


*/
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

Saturday, June 16, 2012 11:29 PM

dbref create_player(name, password, creator, isrobot, isguest)


char *name, *password;
dbref creator;
int isrobot, isguest;
{
dbref player;
char *pbuf;
/* Make sure the password is OK.

Name is checked in create_obj */

pbuf = trim_spaces(password);
if (!isguest && !ok_password(pbuf, creator)) {
free_lbuf(pbuf);
return NOTHING;
}
/* If so, go create him */
player = create_obj(creator, TYPE_PLAYER, name, isrobot);
if (player == NOTHING) {
free_lbuf(pbuf);
return NOTHING;
}
/* initialize everything */

CALL_ALL_MODULES(create_player, (creator, player, isrobot, isguest));


s_Pass(player, crypt(pbuf, "XX"));
s_Home(player, (Good_home(mudconf.start_home) ? mudconf.start_home :
(Good_home(mudconf.start_room) ? mudconf.start_room :
0)));
free_lbuf(pbuf);
return player;

/* --------------------------------------------------------------------------* do_password: Change the password for a player


*/
void do_password(player, cause, key, oldpass, newpass)
dbref player, cause;
int key;
char *oldpass, *newpass;
{
dbref aowner;
int aflags, alen;
char *target;
target = atr_get(player, A_PASS, &aowner, &aflags, &alen);
if (!*target || !check_pass(player, oldpass)) {
notify(player, "Sorry.");
} else if (!ok_password(newpass, player)) {
/* Do nothing, notification is handled by ok_password() */
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

Saturday, June 16, 2012 11:29 PM

} else {
atr_add_raw(player, A_PASS, crypt(newpass, "XX"));
notify(player, "Password changed.");
}
free_lbuf(target);

/* --------------------------------------------------------------------------* do_last Display login history data.


*/
static void disp_from_on(player, dtm_str, host_str)
dbref player;
char *dtm_str, *host_str;
{
if (dtm_str && *dtm_str && host_str && *host_str) {
notify(player,
tprintf("
From: %s
On: %s", dtm_str, host_str));
}
}
void do_last(player, cause, key, who)
dbref player, cause;
int key;
char *who;
{
dbref target, aowner;
LDATA login_info;
char *atrbuf;
int i, aflags, alen;
if (!who || !*who) {
target = Owner(player);
} else if (!(string_compare(who, "me"))) {
target = Owner(player);
} else {
target = lookup_player(player, who, 1);
}
if (target == NOTHING) {
notify(player, "I couldn't find that player." );
} else if (!Controls(player, target)) {
notify(player, NOPERM_MESSAGE);
} else {
atrbuf = atr_get(target, A_LOGINDATA, &aowner, &aflags, &alen);
decrypt_logindata(atrbuf, &login_info);
notify(player, tprintf("Total successful connects: %d" ,
login_info.tot_good));
for (i = 0; i < NUM_GOOD; i++) {
disp_from_on(player,
login_info.good[i].host,
login_info.good[i].dtm);
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

Saturday, June 16, 2012 11:29 PM

}
notify(player, tprintf("Total failed connects: %d",
login_info.tot_bad));
for (i = 0; i < NUM_BAD; i++) {
disp_from_on(player,
login_info.bad[i].host,
login_info.bad[i].dtm);
}
free_lbuf(atrbuf);

/* --------------------------------------------------------------------------* add_player_name, delete_player_name, lookup_player:


* Manage playername->dbref mapping
*/
int add_player_name(player, name)
dbref player;
char *name;
{
int stat;
dbref *p;
char *temp, *tp;
/* Convert to all lowercase */
tp = temp = alloc_lbuf("add_player_name");
safe_str(name, temp, &tp);
for (tp = temp; *tp; tp++)
*tp = tolower(*tp);
p = (int *)hashfind(temp, &mudstate.player_htab);
if (p) {
/* Entry found in the hashtable. If a player, succeed if the
* numbers match (already correctly in the hash table),
* fail if they don't.
*/
if (Good_obj(*p) && isPlayer(*p)) {
free_lbuf(temp);
if (*p == player) {
return 1;
} else {
return 0;
}
}
/* It's an alias (or an incorrect entry). Clobber it */
XFREE(p, "add_player_name");
p = (dbref *) XMALLOC(sizeof(dbref), "add_player_name");
*p = player;
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

Saturday, June 16, 2012 11:29 PM

stat = hashrepl(temp, p, &mudstate.player_htab);


free_lbuf(temp);
} else {
p = (dbref *) XMALLOC(sizeof(dbref), "add_player_name.2");
*p = player;
stat = hashadd(temp, p, &mudstate.player_htab, 0);
free_lbuf(temp);
stat = (stat < 0) ? 0 : 1;

}
return stat;

int delete_player_name(player, name)


dbref player;
char *name;
{
dbref *p;
char *temp, *tp;

tp = temp = alloc_lbuf("delete_player_name");
safe_str(name, temp, &tp);
for (tp = temp; *tp; tp++)
*tp = tolower(*tp);
p = (int *)hashfind(temp, &mudstate.player_htab);
if (!p || (*p == NOTHING) || ((player != NOTHING) && (*p != player))) {
free_lbuf(temp);
return 0;
}
XFREE(p, "delete_player_name");
hashdelete(temp, &mudstate.player_htab);
free_lbuf(temp);
return 1;

dbref lookup_player(doer, name, check_who)


dbref doer;
char *name;
int check_who;
{
dbref *p, thing;
char *temp, *tp;
if (!string_compare(name, "me"))
return doer;
if (*name == LOOKUP_TOKEN) {
do {
name++;
} while (isspace(*name));
}
if (*name == NUMBER_TOKEN) {
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

Saturday, June 16, 2012 11:29 PM

name++;
if (!is_number(name))
return NOTHING;
thing = atoi(name);
if (!Good_obj(thing))
return NOTHING;
if (!((Typeof(thing) == TYPE_PLAYER) || God(doer)))
thing = NOTHING;
return thing;

tp = temp = alloc_lbuf("lookup_player");
safe_str(name, temp, &tp);
for (tp = temp; *tp; tp++)
*tp = tolower(*tp);
p = (int *)hashfind(temp, &mudstate.player_htab);
free_lbuf(temp);
if (!p) {
if (check_who) {
thing = find_connected_name(doer, name);
if (Hidden(thing) && !See_Hidden(doer))
thing = NOTHING;
} else
thing = NOTHING;
} else if (!Good_obj(*p)) {
thing = NOTHING;
} else
thing = *p;
}

return thing;

void NDECL(load_player_names)
{
dbref i, aowner;
int aflags, alen;
char *alias, *p, *tokp;
DO_WHOLE_DB(i) {
if (Typeof(i) == TYPE_PLAYER) {
add_player_name(i, Name(i));
}
}
alias = alloc_lbuf("load_player_names");
DO_WHOLE_DB(i) {
if (Typeof(i) == TYPE_PLAYER) {
alias = atr_get_str(alias, i, A_ALIAS,
&aowner, &aflags, &alen);
if (*alias) {
for (p = strtok_r(alias, ";", &tokp); p;
p = strtok_r(NULL, ";", &tokp)) {
add_player_name(i, p);
}
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582

Saturday, June 16, 2012 11:29 PM

}
free_lbuf(alias);

/* --------------------------------------------------------------------------* badname_add, badname_check, badname_list: Add/look for/display bad names.


*/
void badname_add(bad_name)
char *bad_name;
{
BADNAME *bp;
/* Make a new node and link it in at the top */

bp = (BADNAME *) XMALLOC(sizeof(BADNAME), "badname.struc");


bp->name = XSTRDUP(bad_name, "badname.name");
bp->next = mudstate.badname_head;
mudstate.badname_head = bp;

void badname_remove(bad_name)
char *bad_name;
{
BADNAME *bp, *backp;
/* Look for an exact match on the bad name and remove if found */

backp = NULL;
for (bp = mudstate.badname_head; bp; backp = bp, bp = bp->next) {
if (!string_compare(bad_name, bp->name)) {
if (backp)
backp->next = bp->next;
else
mudstate.badname_head = bp->next;
XFREE(bp->name, "badname.name");
XFREE(bp, "badname.struc");
return;
}
}

int badname_check(bad_name)
char *bad_name;
{
BADNAME *bp;
/* Walk the badname list, doing wildcard matching. If we get a hit
* then return false. If no matches in the list, return true.
*/

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player.c

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

Saturday, June 16, 2012 11:29 PM

for (bp = mudstate.badname_head; bp; bp = bp->next) {


if (quick_wild(bp->name, bad_name))
return 0;
}
return 1;

void badname_list(player, prefix)


dbref player;
const char *prefix;
{
BADNAME *bp;
char *buff, *bufp;
/* Construct an lbuf with all the names separated by spaces */
buff = bufp = alloc_lbuf("badname_list");
safe_str((char *)prefix, buff, &bufp);
for (bp = mudstate.badname_head; bp; bp = bp->next) {
safe_chr(' ', buff, &bufp);
safe_str(bp->name, buff, &bufp);
}
/* Now display it */

notify(player, buff);
free_lbuf(buff);

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player_c.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:28 PM

/* player_c.c - Player cache routines */


/* $Id: player_c.c,v 1.9 2005/10/30 02:02:54 alierak Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "attrs.h"

/* required by code */

typedef struct player_cache {


dbref player;
int money;
int queue;
int qmax;
int cflags;
struct player_cache *next;
} PCACHE;
NHSHTAB pcache_htab;
PCACHE *pcache_head;
#define
#define
#define
#define

PF_DEAD
PF_REF
PF_MONEY_CH
PF_QMAX_CH

0x0001
0x0002
0x0004
0x0008

void NDECL(pcache_init)
{
pool_init(POOL_PCACHE, sizeof(PCACHE));
nhashinit(&pcache_htab, 15 * HASH_FACTOR);
pcache_head = NULL;
}
static void pcache_reload1(player, pp)
dbref player;
PCACHE *pp;
{
char *cp;
cp = atr_get_raw(player, A_MONEY);
if (cp && *cp)
pp->money = atoi(cp);
else
pp->money = 0;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player_c.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:28 PM

cp = atr_get_raw(player, A_QUEUEMAX);
if (cp && *cp)
pp->qmax = atoi(cp);
else if (!Wizard(player))
pp->qmax = mudconf.queuemax;
else
pp->qmax = -1;

PCACHE *pcache_find(player)
dbref player;
{
PCACHE *pp;
pp = (PCACHE *) nhashfind(player, &pcache_htab);
if (pp) {
pp->cflags |= PF_REF;
return pp;
}

pp = alloc_pcache("pcache_find");
pp->queue = 0;
pp->cflags = PF_REF;
pp->player = player;
pcache_reload1(player, pp);
pp->next = pcache_head;
pcache_head = pp;
nhashadd(player, (int *)pp, &pcache_htab);
return pp;

void pcache_reload(player)
dbref player;
{
PCACHE *pp;

if (Good_owner(player)) {
pp = pcache_find(player);
pcache_reload1(player, pp);
}

static void pcache_save(pp)


PCACHE *pp;
{
IBUF tbuf;
if (pp->cflags & PF_DEAD)
return;
if (pp->cflags & PF_MONEY_CH) {
ltos(tbuf, pp->money);
atr_add_raw(pp->player, A_MONEY, tbuf);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player_c.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:28 PM

}
if (pp->cflags & PF_QMAX_CH) {
sprintf(tbuf, "%d", pp->qmax);
atr_add_raw(pp->player, A_QUEUEMAX, tbuf);
}
pp->cflags &= ~(PF_MONEY_CH | PF_QMAX_CH);

void NDECL(pcache_trim)
{
PCACHE *pp, *pplast, *ppnext;

pp = pcache_head;
pplast = NULL;
while (pp) {
if (!(pp->cflags & PF_DEAD) &&
(pp->queue || (pp->cflags & PF_REF))) {
pp->cflags &= ~PF_REF;
pplast = pp;
pp = pp->next;
} else {
ppnext = pp->next;
if (pplast)
pplast->next = ppnext;
else
pcache_head = ppnext;
if (!(pp->cflags & PF_DEAD)) {
pcache_save(pp);
nhashdelete(pp->player, &pcache_htab);
}
free_pcache(pp);
pp = ppnext;
}
}

void NDECL(pcache_sync)
{
PCACHE *pp;

pp = pcache_head;
while (pp) {
pcache_save(pp);
pp = pp->next;
}

int a_Queue(player, adj)


dbref player;
int adj;
{
PCACHE *pp;

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player_c.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:28 PM

if (Good_owner(player)) {
pp = pcache_find(player);
pp->queue += adj;
return pp->queue;
} else {
return 0;
}

void s_Queue(player, val)


dbref player;
int val;
{
PCACHE *pp;

if (Good_owner(player)) {
pp = pcache_find(player);
pp->queue = val;
}

int QueueMax(player)
dbref player;
{
PCACHE *pp;
int m;

m = 0;
if (Good_owner(player)) {
pp = pcache_find(player);
if (pp->qmax >= 0) {
m = pp->qmax;
} else {
m = mudstate.db_top + 1;
if (m < mudconf.queuemax)
m = mudconf.queuemax;
}
}
return m;

int Pennies(obj)
dbref obj;
{
PCACHE *pp;
char *cp;
if (!mudstate.standalone && Good_owner(obj)) {
pp = pcache_find(obj);
return pp->money;
}
cp = atr_get_raw(obj, A_MONEY);
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\player_c.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232

Saturday, June 16, 2012 11:28 PM

return (safe_atoi(cp));

void s_Pennies(obj, howfew)


dbref obj;
int howfew;
{
PCACHE *pp;
IBUF tbuf;
if (!mudstate.standalone && Good_owner(obj)) {
pp = pcache_find(obj);
pp->money = howfew;
pp->cflags |= PF_MONEY_CH;
}

ltos(tbuf, howfew);
atr_add_raw(obj, A_MONEY, tbuf);

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:28 PM

/* powers.c - power manipulation routines */


/* $Id: powers.c,v 1.29 2002/05/11 16:34:40 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"command.h"
/* required by code */
"powers.h" /* required by code */
"match.h" /* required by code */
"ansi.h"
/* required by code */

/*
* --------------------------------------------------------------------------* * ph_any: set or clear indicated bit, no security checking
*/
int ph_any(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (fpowers & POWER_EXT) {
if (reset) {
s_Powers2(target, Powers2(target) & ~power);
} else {
s_Powers2(target, Powers2(target) | power);
}
} else {
if (reset) {
s_Powers(target, Powers(target) & ~power);
} else {
s_Powers(target, Powers(target) | power);
}
}
return 1;
}
/*
* --------------------------------------------------------------------------* * ph_god: only GOD may set or clear the bit
*/
int ph_god(target, player, power, fpowers, reset)
dbref target, player;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:28 PM

POWER power;
int fpowers, reset;
{
if (!God(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/*
* --------------------------------------------------------------------------* * ph_wiz: only WIZARDS (or GOD) may set or clear the bit
*/
int ph_wiz(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!Wizard(player) & !God(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/*
* --------------------------------------------------------------------------* * ph_wizroy: only WIZARDS, ROYALTY, (or GOD) may set or clear the bit
*/
int ph_wizroy(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!WizRoy(player) & !God(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/* --------------------------------------------------------------------------* ph_restrict_player: Only Wizards can set this on players, but
* ordinary players can set it on other types of objects.
*/
int ph_restrict_player(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (isPlayer(target) && !Wizard(player) && !God(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:28 PM

/* --------------------------------------------------------------------------* ph_privileged: You can set this power on a non-player object, if you
* yourself have this power and are a player who owns themselves (i.e.,
* no robots). Only God can set this on a player.
*/
int ph_privileged(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!God(player)) {
if (!isPlayer(player) || (player != Owner(player)))
return 0;
if (isPlayer(target))
return 0;
if (Powers(player) & power)
return (ph_any(target, player, power, fpowers, reset));
else
return 0;
}
}

return (ph_any(target, player, power, fpowers, reset));

/*
* --------------------------------------------------------------------------* * ph_inherit: only players may set or clear this bit.
*/
int ph_inherit(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!Inherits(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/* *INDENT-OFF* */
/* All power names must be in lowercase! */
POWERENT gen_powers[] =
{
{(char *)"announce",
POW_ANNOUNCE,
0, 0,
ph_wiz},
{(char *)"attr_read",
POW_MDARK_ATTR, 0, 0,
ph_wiz},
{(char *)"attr_write",
POW_WIZ_ATTR,
0, 0,
ph_wiz},
{(char *)"boot",
POW_BOOT,
0, 0,
ph_wiz},
{(char *)"builder",
POW_BUILDER,
POWER_EXT, 0,
ph_wiz},
{(char *)"chown_anything", POW_CHOWN_ANY, 0, 0,
ph_wiz},
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{(char
{NULL,

Saturday, June 16, 2012 11:28 PM

*)"cloak",
POW_CLOAK, POWER_EXT, 0,
ph_god},
*)"comm_all",
POW_COMM_ALL,
0, 0,
ph_wiz},
*)"control_all",
POW_CONTROL_ALL,0, 0,
ph_god},
*)"expanded_who",
POW_WIZARD_WHO, 0, 0,
ph_wiz},
*)"find_unfindable", POW_FIND_UNFIND,0, 0,
ph_wiz},
*)"free_money",
POW_FREE_MONEY, 0, 0,
ph_wiz},
*)"free_quota",
POW_FREE_QUOTA, 0, 0,
ph_wiz},
*)"guest",
POW_GUEST, 0, 0,
ph_god},
*)"halt",
POW_HALT,
0, 0,
ph_wiz},
*)"hide",
POW_HIDE,
0, 0,
ph_wiz},
*)"idle",
POW_IDLE,
0, 0,
ph_wiz},
*)"link_any_home",
POW_LINKHOME,
POWER_EXT, 0,
ph_wiz},
*)"link_to_anything",
POW_LINKTOANY, POWER_EXT, 0,
ph_wiz},
*)"link_variable",
POW_LINKVAR,
POWER_EXT, 0,
ph_wiz},
*)"long_fingers",
POW_LONGFINGERS,0, 0,
ph_wiz},
*)"no_destroy",
POW_NO_DESTROY, 0, 0,
ph_wiz},
*)"open_anywhere",
POW_OPENANYLOC, POWER_EXT, 0,
ph_wiz},
*)"pass_locks",
POW_PASS_LOCKS, 0, 0,
ph_wiz},
*)"poll",
POW_POLL,
0, 0,
ph_wiz},
*)"prog",
POW_PROG,
0, 0,
ph_wiz},
*)"quota",
POW_CHG_QUOTAS, 0, 0,
ph_wiz},
*)"search",
POW_SEARCH, 0, 0,
ph_wiz},
*)"see_all",
POW_EXAM_ALL,
0, 0,
ph_wiz},
*)"see_queue",
POW_SEE_QUEUE, 0, 0,
ph_wiz},
*)"see_hidden",
POW_SEE_HIDDEN, 0, 0,
ph_wiz},
*)"stat_any",
POW_STAT_ANY,
0, 0,
ph_wiz},
*)"steal_money",
POW_STEAL, 0, 0,
ph_wiz},
*)"tel_anywhere",
POW_TEL_ANYWHR, 0, 0,
ph_wiz},
*)"tel_anything",
POW_TEL_UNRST, 0, 0,
ph_wiz},
*)"unkillable",
POW_UNKILLABLE, 0, 0,
ph_wiz},
*)"use_sql",
POW_USE_SQL,
POWER_EXT, 0,
ph_god},
*)"watch_logins",
POW_WATCH, 0, 0,
ph_wiz},
0,
POWER_EXT, 0,
0}};

/* *INDENT-ON* */

/*
* --------------------------------------------------------------------------* * init_powertab: initialize power hash tables.
*/
void NDECL(init_powertab)
{
POWERENT *fp;
hashinit(&mudstate.powers_htab, 25 * HASH_FACTOR, HT_STR|HT_KEYREF);
for (fp = gen_powers; fp->powername; fp++) {
hashadd((char *)fp->powername, (int *)fp, &mudstate.powers_htab, 0);
}
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:28 PM

}
/*
* --------------------------------------------------------------------------* * display_powers: display available powers.
*/
void display_powertab(player)
dbref player;
{
char *buf, *bp;
POWERENT *fp;

bp = buf = alloc_lbuf("display_powertab");
safe_str((char *)"Powers:", buf, &bp);
for (fp = gen_powers; fp->powername; fp++) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
continue;
if ((fp->listperm & CA_GOD) && !God(player))
continue;
safe_chr(' ', buf, &bp);
safe_str((char *)fp->powername, buf, &bp);
}
*bp = '\0';
notify(player, buf);
free_lbuf(buf);

POWERENT *find_power(thing, powername)


dbref thing;
char *powername;
{
char *cp;
/* Make sure the power name is valid */

for (cp = powername; *cp; cp++)


*cp = tolower(*cp);
return (POWERENT *) hashfind(powername, &mudstate.powers_htab);

int decode_power(player, powername, pset)


dbref player;
char *powername;
POWERSET *pset;
{
POWERENT *pent;
pset->word1 = 0;
pset->word2 = 0;
pent = (POWERENT *) hashfind(powername, &mudstate.powers_htab);
if (!pent) {
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:28 PM

notify(player, tprintf("%s: Power not found.", powername));


return 0;

}
if (pent->powerpower & POWER_EXT)
pset->word2 = pent->powervalue;
else
pset->word1 = pent->powervalue;
}

return 1;

/*
* --------------------------------------------------------------------------* * power_set: Set or clear a specified power on an object.
*/
void power_set(target, player, power, key)
dbref target, player;
char *power;
int key;
{
POWERENT *fp;
int negate, result;
/*
* Trim spaces, and handle the negation character
*/
negate = 0;
while (*power && isspace(*power))
power++;
if (*power == '!') {
negate = 1;
power++;
}
while (*power && isspace(*power))
power++;
/*
* Make sure a power name was specified
*/
if (*power == '\0') {
if (negate)
notify(player, "You must specify a power to clear." );
else
notify(player, "You must specify a power to set." );
return;
}
fp = find_power(target, power);
if (fp == NULL) {
notify(player, "I don't understand that power." );
return;
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:28 PM

}
/*
* Invoke the power handler, and print feedback
*/

result = fp->handler(target, player, fp->powervalue,


fp->powerpower, negate);
if (!result)
notify(player, NOPERM_MESSAGE);
else if (!(key & SET_QUIET) && !Quiet(player)) {
notify(player, (negate ? "Cleared." : "Set."));
s_Modified(target);
}
return;

/*
* --------------------------------------------------------------------------* * has_power: does object have power visible to player?
*/
int has_power(player, it, powername)
dbref player, it;
char *powername;
{
POWERENT *fp;
POWER fv;
fp = find_power(it, powername);
if (fp == NULL)
return 0;
if (fp->powerpower & POWER_EXT)
fv = Powers2(it);
else
fv = Powers(it);

if (fv & fp->powervalue) {


if ((fp->listperm & CA_WIZARD) && !Wizard(player))
return 0;
if ((fp->listperm & CA_GOD) && !God(player))
return 0;
return 1;
}
return 0;

/*
* --------------------------------------------------------------------------* * power_description: Return an mbuf containing the type and powers on thing.
*/

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:28 PM

char *power_description(player, target)


dbref player, target;
{
char *buff, *bp;
POWERENT *fp;
int otype;
POWER fv;
/*
* Allocate the return buffer
*/
otype = Typeof(target);
bp = buff = alloc_mbuf("power_description");
/*
* Store the header strings and object type
*/
safe_mb_str((char *)"Powers:", buff, &bp);
for (fp = gen_powers; fp->powername; fp++) {
if (fp->powerpower & POWER_EXT)
fv = Powers2(target);
else
fv = Powers(target);
if (fv & fp->powervalue) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
continue;
if ((fp->listperm & CA_GOD) && !God(player))
continue;
safe_mb_chr(' ', buff, &bp);
safe_mb_str((char *)fp->powername, buff, &bp);
}
}
/*
* Terminate the string, and return the buffer to the caller
*/

*bp = '\0';
return buff;

/*
* --------------------------------------------------------------------------* * decompile_powers: Produce commands to set powers on target.
*/
void decompile_powers(player, thing, thingname)
dbref player, thing;
char *thingname;
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:28 PM

POWER f1, f2;


POWERENT *fp;
/*
* Report generic powers
*/
f1 = Powers(thing);
f2 = Powers2(thing);
for (fp = gen_powers; fp->powername; fp++) {
/*
* Skip if we shouldn't decompile this power
*/
if (fp->listperm & CA_NO_DECOMP)
continue;
/*
* Skip if this power is not set
*/
if (fp->powerpower & POWER_EXT) {
if (!(f2 & fp->powervalue))
continue;
} else {
if (!(f1 & fp->powervalue))
continue;
}
/*
* Skip if we can't see this power
*/
if (!check_access(player, fp->listperm))
continue;
/*
* We made it this far, report this power
*/

notify(player, tprintf("@power %s=%s", strip_ansi(thingname), fp->powername));

/* --------------------------------------------------------------------------* cf_power_access: Modify who can set a power. Basically like


* cf_flag_access.
*/
CF_HAND(cf_power_access)
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527

Saturday, June 16, 2012 11:28 PM

char *fstr, *permstr, *tokst;


POWERENT *fp;
fstr = strtok_r(str, " \t=,", &tokst);
permstr = strtok_r(NULL, " \t=,", &tokst);
if (!fstr || !*fstr) {
return -1;
}
if ((fp = find_power(GOD, fstr)) == NULL) {
cf_log_notfound(player, cmd, "No such power", fstr);
return -1;
}
/* Don't change the handlers on special things. */
if ((fp->handler != ph_any) &&
(fp->handler != ph_wizroy) &&
(fp->handler != ph_wiz) &&
(fp->handler != ph_god) &&
(fp->handler != ph_restrict_player) &&
(fp->handler != ph_privileged)) {
STARTLOG(LOG_CONFIGMODS, "CFG", "PERM")
log_printf("Cannot change access for power: %s" , fp->powername);
ENDLOG
return -1;
}

if (!strcmp(permstr, (char *) "any")) {


fp->handler = ph_any;
} else if (!strcmp(permstr, (char *) "royalty")) {
fp->handler = ph_wizroy;
} else if (!strcmp(permstr, (char *) "wizard")) {
fp->handler = ph_wiz;
} else if (!strcmp(permstr, (char *) "god")) {
fp->handler = ph_god;
} else if (!strcmp(permstr, (char *) "restrict_player")) {
fp->handler = ph_restrict_player;
} else if (!strcmp(permstr, (char *) "privileged")) {
fp->handler = ph_privileged;
} else {
cf_log_notfound(player, cmd, "Power access", permstr);
return -1;
}
return 0;

-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:05 PM

/* powers.h - object powers */


/* $Id: powers.h,v 1.14 2002/08/02 20:48:47 lwl Exp $ */
#include "copyright.h"
#ifndef __POWERS_H
#define __POWERS_H
#define POWER_EXT

0x1 /* Lives in extended powers word */

/* First word of powers */


#define POW_CHG_QUOTAS 0x00000001
#define POW_CHOWN_ANY
0x00000002
#define POW_ANNOUNCE
0x00000004
#define POW_BOOT
0x00000008 /*
#define POW_HALT
0x00000010 /*
#define POW_CONTROL_ALL 0x00000020
#define POW_WIZARD_WHO 0x00000040
#define POW_EXAM_ALL
0x00000080
#define POW_FIND_UNFIND 0x00000100
#define POW_FREE_MONEY 0x00000200
#define POW_FREE_QUOTA 0x00000400
#define POW_HIDE
0x00000800 /*
#define POW_IDLE
0x00001000 /*
#define POW_SEARCH 0x00002000 /*
#define POW_LONGFINGERS 0x00004000
#define POW_PROG
0x00008000 /*
#define POW_MDARK_ATTR 0x00010000
#define POW_WIZ_ATTR
0x00020000

/* May change and see quotas */


/* Can @chown anything or to anyone */
/* May use @wall */
May use @boot */
May @halt on other's objects */
/* I control everything */
/* See extra WHO information */
/* I can examine everything */
/* Can find unfindable players */
/* I have infinite money */
/* I have infinite quota */
Can set themselves DARK */
No idle limit */
Can @search anyone */
/* Can get/whisper/etc from a distance */
Can use the @prog command */
/* Can read AF_MDARK attrs */
/* Can write AF_WIZARD attrs */

/* FREE FREE FREE FREE */


#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

POW_COMM_ALL
0x00080000
POW_SEE_QUEUE
0x00100000
POW_SEE_HIDDEN 0x00200000
POW_WATCH
0x00400000 /*
POW_POLL
0x00800000 /*
POW_NO_DESTROY 0x01000000
POW_GUEST
0x02000000 /*
POW_PASS_LOCKS 0x04000000
POW_STAT_ANY
0x08000000
POW_STEAL
0x10000000 /*
POW_TEL_ANYWHR 0x20000000
POW_TEL_UNRST
0x40000000
POW_UNKILLABLE 0x80000000

/* Channel wiz */
/* Player can see the entire queue */
/* Player can see hidden players on WHO list */
Player can set or clear WATCHER */
Player can set the doing poll */
/* Cannot be destroyed */
Player is a guest */
/* Player can pass any lock */
/* Can @stat anyone */
Can give negative money */
/* Teleport anywhere */
/* Teleport anything */
/* Can't be killed */

/* Second word of powers */


#define POW_BUILDER 0x00000001 /* Can build */
#define POW_LINKVAR 0x00000002 /* Can link an exit to "variable" */
#define POW_LINKTOANY
0x00000004 /* Can link to any object */
#define POW_OPENANYLOC 0x00000008 /* Can open from anywhere */
#define POW_USE_SQL 0x00000010 /* Can use SQL queries directly */
#define POW_LINKHOME
0x00000020 /* Can link object to any home */
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

#define POW_CLOAK

0x00000040

Saturday, June 16, 2012 11:05 PM

/* Can vanish from sight via DARK */

/* --------------------------------------------------------------------------* POWERENT: Information about object powers.


*/
typedef struct power_entry {
const char *powername; /* Name of the flag */
int powervalue; /* Which bit in the object is the flag */
int powerpower; /* Ctrl flags for this power (recursive? :-) */
int listperm;
/* Who sees this flag when set */
int (*handler)();
/* Handler for setting/clearing this flag */
} POWERENT;
typedef struct powerset {
POWER
word1;
POWER
word2;
} POWERSET;
extern
extern
extern
extern
extern
extern
extern
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

void NDECL(init_powertab);
void FDECL(display_powertab, (dbref));
void FDECL(power_set, (dbref, dbref, char *, int));
char *
FDECL(power_description, (dbref, dbref));
POWERENT *FDECL(find_power, (dbref, char *));
int FDECL(has_power, (dbref, dbref, char *));
void FDECL(decompile_powers, (dbref, dbref, char *));
s_Change_Quotas(c) s_Powers((c), Powers(c) | POW_CHG_QUOTAS)
s_Chown_Any(c)
s_Powers((c), Powers(c) | POW_CHOWN_ANY)
s_Announce(c)
s_Powers((c), Powers(c) | POW_ANNOUNCE)
s_Can_Boot(c)
s_Powers((c), Powers(c) | POW_BOOT)
s_Can_Halt(c)
s_Powers((c), Powers(c) | POW_HALT)
s_Control_All(c)
s_Powers((c), Powers(c) | POW_CONTROL_ALL)
s_Wizard_Who(c)
s_Powers((c), Powers(c) | POW_WIZARD_WHO)
s_See_All(c)
s_Powers((c), Powers(c) | POW_EXAM_ALL)
s_Find_Unfindable(c)
s_Powers((c), Powers(c) | POW_FIND_UNFIND)
s_Free_Money(c)
s_Powers((c), Powers(c) | POW_FREE_MONEY)
s_Free_Quota(c)
s_Powers((c), Powers(c) | POW_FREE_QUOTA)
s_Can_Hide(c)
s_Powers((c), Powers(c) | POW_HIDE)
s_Can_Idle(c)
s_Powers((c), Powers(c) | POW_IDLE)
s_Search(c)
s_Powers((c), Powers(c) | POW_SEARCH)
s_Long_Fingers(c)
s_Powers((c), Powers(c) | POW_LONGFINGERS)
s_Prog(c)
s_Powers((c), Powers(c) | POW_PROG)
s_Comm_All(c)
s_Powers((c), Powers(c) | POW_COMM_ALL)
s_See_Queue(c)
s_Powers((c), Powers(c) | POW_SEE_QUEUE)
s_See_Hidden(c)
s_Powers((c), Powers(c) | POW_SEE_HIDDEN)
s_Can_Watch(c)
s_Powers((c), Powers(c) | POW_WATCH)
s_Can_Poll(c)
s_Powers((c), Powers(c) | POW_POLL)
s_No_Destroy(c)
s_Powers((c), Powers(c) | POW_NO_DESTROY)
s_Guest(c)
s_Powers((c), Powers(c) | POW_GUEST)
s_Set_Maint_Flags(c)
s_Powers((c), Powers(c) | POW_SET_MFLAGS)
s_Stat_Any(c)
s_Powers((c), Powers(c) | POW_STAT_ANY)
s_Steal(c)
s_Powers((c), Powers(c) | POW_STEAL)
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\powers.h

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

Saturday, June 16, 2012 11:05 PM

#define
#define
#define
#define

s_Tel_Anywhere(c)
s_Tel_Anything(c)
s_Unkillable(c)
s_Builder(c)

s_Powers((c), Powers(c) |
s_Powers((c), Powers(c) |
s_Powers((c), Powers(c) |
s_Powers2((c), Powers2(c)

#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

Can_Set_Quota(c)
(((Powers(c) & POW_CHG_QUOTAS) != 0) || Wizard(c))
Chown_Any(c)
(((Powers(c) & POW_CHOWN_ANY) != 0) || Wizard(c))
Announce(c)
(((Powers(c) & POW_ANNOUNCE) != 0) || Wizard(c))
Can_Boot(c)
(((Powers(c) & POW_BOOT) != 0) || Wizard(c))
Can_Halt(c)
(((Powers(c) & POW_HALT) != 0) || Wizard(c))
Control_All(c)
(((Powers(c) & POW_CONTROL_ALL) != 0) || Wizard(c))
Wizard_Who(c)
(((Powers(c) & POW_WIZARD_WHO) != 0) || WizRoy(c))
See_All(c)
(((Powers(c) & POW_EXAM_ALL) != 0) || WizRoy(c))
Find_Unfindable(c) ((Powers(c) & POW_FIND_UNFIND) != 0)
Free_Money(c)
(((Powers(c) & POW_FREE_MONEY) != 0) || Immortal(c))
Free_Quota(c)
(((Powers(c) & POW_FREE_QUOTA) != 0) || Wizard(c))
Can_Hide(c)
(((Powers(c) & POW_HIDE) != 0) || Wizard(c))
Can_Idle(c)
(((Powers(c) & POW_IDLE) != 0) || Wizard(c))
Search(c)
(((Powers(c) & POW_SEARCH) != 0) || WizRoy(c))
Long_Fingers(c)
(((Powers(c) & POW_LONGFINGERS) != 0) || Wizard(c))
Comm_All(c)
(((Powers(c) & POW_COMM_ALL) != 0) || Wizard(c))
See_Queue(c)
(((Powers(c) & POW_SEE_QUEUE) != 0) || WizRoy(c))
See_Hidden(c)
(((Powers(c) & POW_SEE_HIDDEN) != 0) || WizRoy(c))
Can_Watch(c)
(((Powers(c) & POW_WATCH) != 0) || Wizard(c))
Can_Poll(c)
(((Powers(c) & POW_POLL) != 0) || Wizard(c))
No_Destroy(c)
(((Powers(c) & POW_NO_DESTROY) != 0) || Wizard(c))
Guest(c)
((Powers(c) & POW_GUEST) != 0)
Set_Maint_Flags(c) ((Powers(c) & POW_SET_MFLAGS) != 0)
Stat_Any(c)
((Powers(c) & POW_STAT_ANY) != 0)
Steal(c)
(((Powers(c) & POW_STEAL) != 0) || Wizard(c))
Tel_Anywhere(c)
(((Powers(c) & POW_TEL_ANYWHR) != 0) || Tel_Anything(c))
Tel_Anything(c)
(((Powers(c) & POW_TEL_UNRST) != 0) || WizRoy(c))
Unkillable(c)
(((Powers(c) & POW_UNKILLABLE) != 0) || Immortal(c))
Prog(c)
(((Powers(c) & POW_PROG) != 0) || Wizard(c))
Sees_Hidden_Attrs(c)
(((Powers(c) & POW_MDARK_ATTR) != 0) || WizRoy(c))
Sets_Wiz_Attrs(c)
(((Powers(c) & POW_WIZ_ATTR) != 0) || Wizard(c))
Pass_Locks(c)
((Powers(c) & POW_PASS_LOCKS) != 0)
Builder(c)
(((Powers2(c) & POW_BUILDER) != 0) || WizRoy(c))
LinkVariable(c)
(((Powers2(c) & POW_LINKVAR) != 0) || Wizard(c))
LinkToAny(c)
(((Powers2(c) & POW_LINKTOANY) != 0) || Wizard(c))
LinkAnyHome(c)
(((Powers2(c) & POW_LINKHOME) != 0) || Wizard(c))
Open_Anywhere(c)
((Powers2(c) & POW_OPENANYLOC) != 0)
Can_Cloak(c)
((Powers2(c) & POW_CLOAK) != 0)
Can_Use_SQL(c)
((Powers2(c) & POW_USE_SQL) != 0)

#endif /* __POWERS_H */

-3-

POW_TEL_ANYWHR)
POW_TEL_UNRST)
POW_UNKILLABLE)
| POW_BUILDER)

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:27 PM

/* predicates.c */
/* $Id: predicates.c,v 1.134 2008/02/22 15:19:33 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include <signal.h>
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include
#include
#include
#include
extern
extern
extern
extern
extern
extern
extern
extern
static
static

"match.h" /*
"command.h"
"attrs.h" /*
"powers.h" /*
"ansi.h"
/*
"functions.h"
"db_sql.h" /*

required by code */
/* required by code */
required by code */
required by code */
required by code */
/* required by code */
required by code */

int FDECL(do_command, (DESC *, char *, int));


void NDECL(dump_database);
LOGFILETAB logfds_table[];
volatile int slave_pid;
volatile int slave_socket;
void FDECL(load_quota, (int *, dbref, int));
void FDECL(save_quota, (int *, dbref, int));
int FDECL(get_gender, (dbref));
int FDECL(type_quota, (int));
int FDECL(pay_quota, (dbref, int, int));

extern INLINE void FDECL(queue_rawstring, (DESC *, const char *));


#ifdef HAVE_VSNPRINTF
static char tprintf_buff[LBUF_SIZE];
#else
static char tprintf_buff[20000];
#endif
#if defined(__STDC__) && defined(STDC_HEADERS)
char *tprintf(const char *format,...)
#else
char *tprintf(va_alist)
va_dcl
#endif

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:27 PM

va_list ap;

#if defined(__STDC__) && defined(STDC_HEADERS)


va_start(ap, format);
#else
char *format;
va_start(ap);
format = va_arg(ap, char *);
#endif
#ifdef HAVE_VSNPRINTF
vsnprintf(tprintf_buff, LBUF_SIZE, format, ap);
#else
vsprintf(tprintf_buff, format, ap);
#endif
va_end(ap);
tprintf_buff[LBUF_SIZE - 1] = '\0';
return tprintf_buff;
}
char *tvprintf(format, ap)
const char *format;
va_list ap;
{
#ifdef HAVE_VSNPRINTF
vsnprintf(tprintf_buff, LBUF_SIZE, format, ap);
#else
vsprintf(tprintf_buff, format, ap);
#endif
tprintf_buff[LBUF_SIZE - 1] = '\0';
return tprintf_buff;
}
#if defined(__STDC__) && defined(STDC_HEADERS)
void safe_tprintf_str(char *str, char **bp, const char *format,...)
#else
void safe_tprintf_str(va_alist)
va_dcl
#endif
{
#ifdef HAVE_VSNPRINTF
int len, n;
#else
static char buff[20000];
#endif
va_list ap;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:27 PM

#if defined(__STDC__) && defined(STDC_HEADERS)


va_start(ap, format);
#else
char *str;
char **bp;
char *format;
va_start(ap);
str = va_arg(ap, char *);
bp = va_arg(ap, char **);
format = va_arg(ap, char *);
#endif
/* Sigh, don't we wish _all_ vsprintf's returned int... */
#ifdef HAVE_VSNPRINTF
n = LBUF_SIZE - (*bp - str);
if (n <= 0) {
**bp = '\0';
return;
}
vsnprintf(*bp, n, format, ap);
va_end(ap);
len = strlen(*bp);
n = ((len < n) ? len : n);
*bp += n;
**bp = '\0';
#else
vsprintf(buff, format, ap);
va_end(ap);
buff[LBUF_SIZE - 1] = '\0';
safe_str(buff, str, bp);
**bp = '\0';
#endif
}
/* --------------------------------------------------------------------------* insert_first, remove_first: Insert or remove objects from lists.
*/
dbref insert_first(head, thing)
dbref head, thing;
{
s_Next(thing, head);
return thing;
}
dbref remove_first(head, thing)
dbref head, thing;
{
dbref prev;

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:27 PM

if (head == thing)
return (Next(thing));

DOLIST(prev, head) {
if (Next(prev) == thing) {
s_Next(prev, Next(thing));
return head;
}
}
return head;

/* --------------------------------------------------------------------------* reverse_list: Reverse the order of members in a list.


*/
dbref reverse_list(list)
dbref list;
{
dbref newlist, rest;

newlist = NOTHING;
while (list != NOTHING) {
rest = Next(list);
s_Next(list, newlist);
newlist = list;
list = rest;
}
return newlist;

/* --------------------------------------------------------------------------* member - indicate if thing is in list


*/
int member(thing, list)
dbref thing, list;
{
DOLIST(list, list) {
if (list == thing)
return 1;
}
return 0;
}
/* --------------------------------------------------------------------------* is_integer, is_number: see if string contains just a number.
*/
int is_integer(str)
char *str;
{
while (*str && isspace(*str))
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:27 PM

str++;
/* Leading spaces */
if ((*str == '-') || (*str == '+')) {
/* Leading minus or plus */
str++;
if (!*str)
return 0;
/* but not if just a minus or plus*/
}
if (!isdigit(*str)) /* Need at least 1 integer */
return 0;
while (*str && isdigit(*str))
str++;
/* The number (int) */
while (*str && isspace(*str))
str++;
/* Trailing spaces */
return (*str ? 0 : 1);

int is_number(str)
char *str;
{
int got_one;

while (*str && isspace(*str))


str++;
/* Leading spaces */
if ((*str == '-') || (*str == '+')) {
/* Leading minus or plus */
str++;
if (!*str)
return 0;
/* but not if just a minus or plus */
}
got_one = 0;
if (isdigit(*str))
got_one = 1;
/* Need at least one digit */
while (*str && isdigit(*str))
str++;
/* The number (int) */
if (*str == '.')
str++;
/* decimal point */
if (isdigit(*str))
got_one = 1;
/* Need at least one digit */
while (*str && isdigit(*str))
str++;
/* The number (fract) */
while (*str && isspace(*str))
str++;
/* Trailing spaces */
return ((*str || !got_one) ? 0 : 1);

int could_doit(player, thing, locknum)


dbref player, thing;
int locknum;
{
char *key;
dbref aowner;
int aflags, alen, doit;
/* no if nonplayer tries to get key */

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:27 PM

if (!isPlayer(player) && Key(thing)) {


return 0;
}
if (Pass_Locks(player))
return 1;

key = atr_get(thing, locknum, &aowner, &aflags, &alen);


doit = eval_boolexp_atr(player, thing, thing, key);
free_lbuf(key);
return doit;

static int canpayquota(player, who, cost, objtype)


dbref player, who;
int cost, objtype;
{
register int quota;
int q_list[5];
/* If no cost, succeed */
if (cost <= 0)
return 1;
/* determine basic quota */
load_quota(q_list, Owner(who), A_RQUOTA);
quota = q_list[QTYPE_ALL];
/* enough to build?

Wizards always have enough. */

quota -= cost;
if ((quota < 0) && !Free_Quota(who) && !Free_Quota(Owner(who)))
return 0;
if (mudconf.typed_quotas) {
quota = q_list[type_quota(objtype)];
if ((quota <= 0) &&
!Free_Quota(player) && !Free_Quota(Owner(player)))
return 0;
}
}

return 1;

static int pay_quota(who, cost, objtype)


dbref who;
int cost, objtype;
{
/* If no cost, succeed. Negative costs /must/ be managed, however */
if (cost == 0)
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:27 PM

return 1;
add_quota(who, -cost, type_quota(objtype));
}

return 1;

int canpayfees(player, who, pennies, quota, objtype)


dbref player, who;
int pennies, quota, objtype;
{
if (!Wizard(who) && !Wizard(Owner(who)) &&
!Free_Money(who) && !Free_Money(Owner(who)) &&
(Pennies(Owner(who)) < pennies)) {
if (player == who) {
notify(player,
tprintf("Sorry, you don't have enough %s." ,
mudconf.many_coins));
} else {
notify(player,
tprintf("Sorry, that player doesn't have enough %s." ,
mudconf.many_coins));
}
return 0;
}
if (mudconf.quotas) {
if (!canpayquota(player, who, quota, objtype)) {
if (player == who) {
notify(player,
"Sorry, your building contract has run out." );
} else {
notify(player,
"Sorry, that player's building contract has run out." );
}
return 0;
}
}
return 1;
}
static int type_quota(objtype)
int objtype;
{
int qtype;
/* determine typed quota */
switch (objtype) {
case TYPE_ROOM:
qtype = QTYPE_ROOM;
break;
case TYPE_EXIT:
qtype = QTYPE_EXIT;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:27 PM

break;
case TYPE_PLAYER:
qtype = QTYPE_PLAYER;
break;
default:
qtype = QTYPE_THING;
}
return (qtype);

int payfor(who, cost)


dbref who;
int cost;
{
dbref tmp;

if (Wizard(who) || Wizard(Owner(who)) ||
Free_Money(who) || Free_Money(Owner(who)) ||
Immortal(who) || Immortal(Owner(who))) {
return 1;
}
who = Owner(who);
if ((tmp = Pennies(who)) >= cost) {
s_Pennies(who, tmp - cost);
return 1;
}
return 0;

int payfees(who, pennies, quota, objtype)


dbref who;
int pennies, quota, objtype;
{
/* You /must/ have called canpayfees() first. If not, your
* database will be eaten by rabid squirrels. */
if (mudconf.quotas)
pay_quota(who, quota, objtype);
return payfor(who, pennies);
}
void add_quota(who, payment, type)
dbref who;
int payment, type;
{
int q_list[5];
load_quota(q_list, Owner(who), A_RQUOTA);
q_list[QTYPE_ALL] += payment;
if (mudconf.typed_quotas)
q_list[type] += payment;
save_quota(q_list, Owner(who), A_RQUOTA);
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:27 PM

}
void giveto(who, pennies)
dbref who;
int pennies;
{
if (Wizard(who) || Wizard(Owner(who)) ||
Free_Money(who) || Free_Money(Owner(who)) ||
Immortal(who) || Immortal(Owner(who))) {
return;
}
who = Owner(who);
s_Pennies(who, Pennies(who) + pennies);
}
int ok_name(name)
const char *name;
{
const char *cp;
char *purename = strip_ansi(name);
/* Disallow pure ANSI names */
if (strlen(purename) == 0)
return 0;
/* Disallow leading spaces */
if (isspace(*purename))
return 0;
/* Only printable characters outside of escape codes */
for (cp = purename; *cp; ++cp) {
if (!isprint(*cp))
return 0;
}
/* Disallow trailing spaces */
cp--;
if (isspace(*cp))
return 0;
/* Exclude names that start with or contain certain magic cookies */
return (*purename != LOOKUP_TOKEN &&
*purename != NUMBER_TOKEN &&
*purename != NOT_TOKEN &&
!strchr(name, ARG_DELIMITER) &&
!strchr(name, AND_TOKEN) &&
!strchr(name, OR_TOKEN) &&
string_compare(purename, "me") &&
string_compare(purename, "home") &&
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:27 PM

string_compare(purename, "here"));

int ok_player_name(name)
const char *name;
{
const char *cp, *good_chars;
/* Not too long and a good name for a thing */
if (!ok_name(name) || (strlen(name) >= PLAYER_NAME_LIMIT))
return 0;
if (mudconf.name_spaces || mudstate.standalone)
good_chars = " `$_-.,'";
else
good_chars = "`$_-.,'";
/* Make sure name only contains legal characters */

for (cp = name; cp && *cp; cp++) {


if (isalnum(*cp))
continue;
if (!strchr(good_chars, *cp))
return 0;
}
return 1;

int ok_attr_name(attrname)
const char *attrname;
{
const char *scan;

if (!isalpha(*attrname) && (*attrname != '_'))


return 0;
for (scan = attrname; *scan; scan++) {
if (isalnum(*scan))
continue;
if (!strchr("'?!`/-_.@#$^&~=+<>()%", *scan))
return 0;
}
return 1;

int ok_password(password, player)


const char *password;
dbref player;
{
const char *scan;
int num_upper = 0;
int num_special = 0;
int num_lower = 0;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582

Saturday, June 16, 2012 11:27 PM

if (*password == '\0') {
if (!mudstate.standalone)
notify_quiet(player, "Null passwords are not allowed." );
return 0;
}
for (scan = password; *scan; scan++) {
if (!(isprint(*scan) && !isspace(*scan))) {
if (!mudstate.standalone)
notify_quiet(player, "Illegal character in password." );
return 0;
}
if (isupper(*scan))
num_upper++;
else if (islower(*scan))
num_lower++;
else if ((*scan != '\'') && (*scan != '-'))
num_special++;
}
/* Needed. Change it if you like, but be sure yours is the same. */
if ((strlen(password) == 13) &&
(password[0] == 'X') &&
(password[1] == 'X')) {
if (!mudstate.standalone)
notify_quiet(player, "Please choose another password." );
return 0;
}
if (!mudstate.standalone && mudconf.safer_passwords) {
if (num_upper < 1) {
notify_quiet(player,
"The password must contain at least one capital letter." );
return 0;
}
if (num_lower < 1) {
notify_quiet(player,
"The password must contain at least one lowercase letter." );
return 0;
}
if (num_special < 1) {
notify_quiet(player,
"The password must contain at least one number or a symbol other than
the apostrophe or dash.");
return 0;
}
}
}

return 1;

/* ---------------------------------------------------------------------------11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

Saturday, June 16, 2012 11:27 PM

* handle_ears: Generate the 'grows ears' and 'loses ears' messages.


*/
void handle_ears(thing, could_hear, can_hear)
dbref thing;
int could_hear, can_hear;
{
char *buff, *bp;
int gender;

if (could_hear != can_hear) {
bp = buff = alloc_lbuf("handle_ears");
if (isExit(thing))
safe_exit_name(thing, buff, &bp);
else
safe_name(thing, buff, &bp);
gender = get_gender(thing);
notify_check(thing, thing,
tprintf("%s %s %s listening.",
buff,
((gender == 4) ? "are" : "is"),
(can_hear ? "now" : "no longer")),
(MSG_ME | MSG_NBR | MSG_LOC | MSG_INV));
free_lbuf(buff);
}

/* for lack of better place the @switch code is here */


void do_switch(player, cause, key, expr, args, nargs, cargs, ncargs)
dbref player, cause;
int key, nargs, ncargs;
char *expr, *args[], *cargs[];
{
int a, any, now;
char *buff, *tbuf, *bp, *str;
if (!expr || (nargs <= 0))
return;
now = key & SWITCH_NOW;
key &= ~SWITCH_NOW;
if (key == SWITCH_DEFAULT) {
if (mudconf.switch_df_all)
key = SWITCH_ANY;
else
key = SWITCH_ONE;
}
/* now try a wild card match of buff with stuff in args */
any = 0;
buff = bp = alloc_lbuf("do_switch");
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

Saturday, June 16, 2012 11:27 PM

for (a = 0; (a < (nargs - 1)) && args[a] && args[a + 1]; a += 2) {


bp = buff;
str = args[a];
exec(buff, &bp, player, cause, cause,
EV_FCHECK | EV_EVAL | EV_TOP, &str, cargs, ncargs);
if (wild_match(buff, expr)) {
tbuf = replace_string(SWITCH_VAR, expr, args[a+1]);
if (now) {
process_cmdline(player, cause, tbuf,
cargs, ncargs, NULL);
} else {
wait_que(player, cause, 0, NOTHING, 0,
tbuf, cargs, ncargs, mudstate.rdata);
}
free_lbuf(tbuf);
if (key == SWITCH_ONE) {
free_lbuf(buff);
return;
}
any = 1;
}
}
free_lbuf(buff);
if ((a < nargs) && !any && args[a]) {
tbuf = replace_string(SWITCH_VAR, expr, args[a]);
if (now) {
process_cmdline(player, cause, tbuf, cargs, ncargs,
NULL);
} else {
wait_que(player, cause, 0, NOTHING, 0, tbuf, cargs,
ncargs, mudstate.rdata);
}
free_lbuf(tbuf);
}

/* --------------------------------------------------------------------------* do_end: Stop processing an action list, based on a conditional.


*/
void do_end(player, cause, key, condstr, cmdstr, args, nargs)
dbref player, cause;
int key, nargs;
char *condstr, *cmdstr, *args[];
{
int k = key & ENDCMD_ASSERT;
int n = xlate(condstr);
if ((!k && n) || (k && !n)) {
mudstate.break_called = 1;
if (cmdstr && *cmdstr) {
wait_que(player, cause, 0, NOTHING, 0, cmdstr,
args, nargs, mudstate.rdata);
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741

Saturday, June 16, 2012 11:27 PM

/* --------------------------------------------------------------------------* Command hooks.


*/
void do_hook(player, cause, key, cmdname, target)
dbref player, cause;
int key;
char *cmdname, *target;
{
CMDENT *cmdp;
char *p;
ATTR *ap;
HOOKENT *hp;
dbref thing, aowner;
int atr, aflags;
for (p = cmdname; p && *p; p++)
*p = tolower(*p);
if (!cmdname ||
((cmdp = (CMDENT *) hashfind(cmdname,
&mudstate.command_htab)) == NULL) ||
(cmdp->callseq & CS_ADDED)) {
notify(player, "That is not a valid built-in command." );
return;
}
if (key == 0) {
/* List hooks only */
if (cmdp->pre_hook) {
ap = atr_num(cmdp->pre_hook->atr);
if (!ap) {
notify(player, "Before Hook contains bad attribute number." );
} else {
notify(player, tprintf("Before Hook: #%d/%s",
cmdp->pre_hook->thing, ap->name));
}
} else {
notify(player, "Before Hook: none");
}
if (cmdp->post_hook) {
ap = atr_num(cmdp->post_hook->atr);
if (!ap) {
notify(player, "After Hook contains bad attribute number." );
} else {
notify(player, tprintf("After Hook: #%d/%s",
cmdp->post_hook->thing, ap->name));
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794

Saturday, June 16, 2012 11:27 PM

}
} else {
notify(player, "After Hook: none");
}
if (cmdp->userperms) {
ap = atr_num(cmdp->userperms->atr);
if (!ap) {
notify(player,
"User Permissions contains bad attribute number." );
} else {
notify(player, tprintf("User Permissions: #%d/%s",
cmdp->userperms->thing, ap->name));
}
} else {
notify(player, "User Permissions: none");
}
return;
}
/* Check for the hook flags. */
if (key & HOOK_PRESERVE) {
cmdp->callseq &= ~CS_PRIVATE;
cmdp->callseq |= CS_PRESERVE;
notify(player,
"Hooks will preserve the state of the global registers." );
return;
}
if (key & HOOK_NOPRESERVE) {
cmdp->callseq &= ~(CS_PRESERVE|CS_PRIVATE);
notify(player,
"Hooks will not preserve the state of the global registers." );
return;
}
if (key & HOOK_PRIVATE) {
cmdp->callseq &= ~CS_PRESERVE;
cmdp->callseq |= CS_PRIVATE;
notify(player,
"Hooks will use private global registers." );
return;
}
/* If we didn't get a target, this is a hook deletion. */
if (!target || !*target) {
if (key & HOOK_BEFORE) {
if (cmdp->pre_hook) {
XFREE(cmdp->pre_hook, "do_hook");
cmdp->pre_hook = NULL;
}
notify(player, "Hook removed.");
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

Saturday, June 16, 2012 11:27 PM

} else if (key & HOOK_AFTER) {


if (cmdp->post_hook) {
XFREE(cmdp->post_hook, "do_hook");
cmdp->post_hook = NULL;
}
notify(player, "Hook removed.");
} else if (key & HOOK_PERMIT) {
if (cmdp->userperms) {
XFREE(cmdp->userperms, "do_hook");
cmdp->userperms = NULL;
}
notify(player, "User-defined permissions removed." );
} else {
notify(player, "Unknown command switch.");
}
return;
}
/* Find target object and attribute. Make sure it can be read, and
* that we control the object.
*/
if (!parse_attrib(player, target, &thing, &atr, 0)) {
notify(player, NOMATCH_MESSAGE);
return;
}
if (!Controls(player, thing)) {
notify(player, NOPERM_MESSAGE);
return;
}
if (atr == NOTHING) {
notify(player, "No such attribute.");
return;
}
ap = atr_num(atr);
if (!ap) {
notify(player, "No such attribute.");
return;
}
atr_get_info(thing, atr, &aowner, &aflags);
if (!See_attr(player, thing, ap, aowner, aflags)) {
notify(player, NOPERM_MESSAGE);
return;
}
/* All right, we have what we need. Go allocate a hook. */
hp = (HOOKENT *) XMALLOC(sizeof(HOOKENT), "do_hook");
hp->thing = thing;
hp->atr = atr;
/* If that kind of hook already existed, get rid of it. Put in the
* new one.
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900

Saturday, June 16, 2012 11:27 PM

*/

if (key & HOOK_BEFORE) {


if (cmdp->pre_hook) {
XFREE(cmdp->pre_hook, "do_hook");
}
cmdp->pre_hook = hp;
notify(player, "Hook added.");
} else if (key & HOOK_AFTER) {
if (cmdp->post_hook) {
XFREE(cmdp->post_hook, "do_hook");
}
cmdp->post_hook = hp;
notify(player, "Hook added.");
} else if (key & HOOK_PERMIT) {
if (cmdp->userperms) {
XFREE(cmdp->userperms, "do_hook");
}
cmdp->userperms = hp;
notify(player, "User-defined permissions will now be checked." );
} else {
XFREE(hp, "do_hook");
notify(player, "Unknown command switch.");
}

/* --------------------------------------------------------------------------* Command overriding and friends.


*/
void do_addcommand(player, cause, key, name, command)
dbref player, cause;
int key;
char *name, *command;
{
CMDENT *old, *cmd;
ADDENT *add, *nextp;
dbref thing;
int atr;
char *s;
/* Sanity-check the command name and make it case-insensitive. */
if (!*name || (name[0] == '_' && name[1] == '_')) {
notify(player, "That is not a valid command name." );
return;
}
for (s = name; *s; s++) {
if (isspace(*s) || (*s == ESC_CHAR)) {
notify(player, "That is not a valid command name." );
return;
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953

Saturday, June 16, 2012 11:27 PM

}
*s = tolower(*s);

if (!parse_attrib(player, command, &thing, &atr, 0) ||


(atr == NOTHING)) {
notify(player, "No such attribute.");
return;
}
old = (CMDENT *)hashfind(name, &mudstate.command_htab);
if (old && (old->callseq & CS_ADDED)) {
/* If it's already found in the hash table, and it's being
added using the same object and attribute... */
for (nextp = (ADDENT *)old->info.added; nextp != NULL; nextp = nextp->next) {
if ((nextp->thing == thing) && (nextp->atr == atr)) {
notify(player, tprintf("%s already added.", name));
return;
}
}
/* else tack it on to the existing entry... */
add = (ADDENT *)XMALLOC(sizeof(ADDENT), "addcommand.add");
add->thing = thing;
add->atr = atr;
add->name = XSTRDUP(name, "addcommand.addname");
add->next = (ADDENT *)old->info.added;
if (key & ADDCMD_PRESERVE)
old->callseq |= CS_ACTOR;
else
old->callseq &= ~CS_ACTOR;
old->info.added = add;
} else {
if (old) {
/* Delete the old built-in */
hashdelete(name, &mudstate.command_htab);
}
cmd = (CMDENT *) XMALLOC(sizeof(CMDENT), "addcommand.cmd");
cmd->cmdname = XSTRDUP(name, "addcommand.cmdname");
cmd->switches = NULL;
cmd->perms = 0;
cmd->extra = 0;
cmd->pre_hook = NULL;
cmd->post_hook = NULL;
cmd->userperms = NULL;
cmd->callseq = CS_ADDED | CS_ONE_ARG |
((old && (old->callseq & CS_LEADIN)) ? CS_LEADIN : 0) |
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

((key & ADDCMD_PRESERVE) ? CS_ACTOR : 0);


add = (ADDENT *)XMALLOC(sizeof(ADDENT), "addcommand.add");
add->thing = thing;
add->atr = atr;
add->name = XSTRDUP(name, "addcommand.addname");
add->next = NULL;
cmd->info.added = add;

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

Saturday, June 16, 2012 11:27 PM

hashadd(cmd->cmdname, (int *)cmd, &mudstate.command_htab, 0);

if (old) {
/* If this command was the canonical form of the
* command (not an alias), point its aliases to
* the added command, while keeping the __ alias.
*/
if (!strcmp(name, old->cmdname)) {
hashdelete(tprintf("__%s", old->cmdname), &mudstate.command_htab);
hashreplall((int *)old, (int *)cmd, &mudstate.command_htab);
hashadd(tprintf("__%s", old->cmdname), (int *)old, &mudstate.
command_htab, 0);
}
}

/* We reset the one letter commands here so you can overload them */

reset_prefix_cmds();
notify(player, tprintf("Command %s added.", name));

void do_listcommands(player, cause, key, name)


dbref player, cause;
int key;
char *name;
{
CMDENT *old;
ADDENT *nextp;
int didit = 0;
char *s, *keyname;
/* Let's make this case insensitive... */
for (s = name; *s; s++) {
*s = tolower(*s);
}
if (*name) {
old = (CMDENT *)hashfind(name, &mudstate.command_htab);
if (old && (old->callseq & CS_ADDED)) {
if (strcmp(name, old->cmdname)) {
notify(player, tprintf("%s: alias for %s", name, old->cmdname));
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1006
1007
1008
1009
1010

return;

for (nextp = (ADDENT *)old->info.added; nextp != NULL; nextp = nextp->next) {


notify(player, tprintf("%s: #%d/%s", nextp->name, nextp->thing, ((ATTR
*)atr_num(nextp->atr))->name));
}
} else {
notify(player, tprintf("%s not found in command table." , name));
}
return;
} else {
for (keyname = hash_firstkey(&mudstate.command_htab); keyname != NULL;
keyname = hash_nextkey(&mudstate.command_htab)) {

1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028

old = (CMDENT *)hashfind(keyname, &mudstate.command_htab);


if (old && (old->callseq & CS_ADDED)) {
if (strcmp(keyname, old->cmdname)) {
notify(player, tprintf("%s: alias for %s", keyname, old->cmdname));
continue;
}

1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055

Saturday, June 16, 2012 11:27 PM

for (nextp = (ADDENT *)old->info.added; nextp != NULL; nextp = nextp->


next) {
notify(player, tprintf("%s: #%d/%s", nextp->name, nextp->thing, ((
ATTR *)atr_num(nextp->atr))->name));
didit = 1;
}

}
if (!didit)
notify(player, "No added commands found in command table." );

void do_delcommand(player, cause, key, name, command)


dbref player, cause;
int key;
char *name, *command;
{
CMDENT *old, *cmd;
ADDENT *prev = NULL, *nextp;
dbref thing;
int atr;
char *s;
if (!*name) {
notify(player, "Sorry.");
return;
}

-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106

Saturday, June 16, 2012 11:27 PM

if (*command) {
if (!parse_attrib(player, command, &thing, &atr, 0) ||
(atr == NOTHING)) {
notify(player, "No such attribute.");
return;
}
}
/* Let's make this case insensitive... */
for (s = name; *s; s++) {
*s = tolower(*s);
}
old = (CMDENT *)hashfind(name, &mudstate.command_htab);
if (old && (old->callseq & CS_ADDED)) {
if (!*command) {
for (prev = (ADDENT *)old->info.added; prev != NULL; prev = nextp) {
nextp = prev->next;
/* Delete it! */
XFREE(prev->name, "delcommand.name");
XFREE(prev, "delcommand.addent");
}
hashdelete(name, &mudstate.command_htab);
if ((cmd = (CMDENT *)hashfind(tprintf("__%s", old->cmdname), &mudstate.
command_htab)) != NULL) {
hashadd(cmd->cmdname, (int *)cmd, &mudstate.command_htab, 0);
/* in case we deleted by alias */
if (strcmp(name, cmd->cmdname)) {
hashadd(name, (int *)cmd, &mudstate.command_htab, HASH_ALIAS);
}
/* the __ alias may have been temporarily
* marked as the original hash entry
*/
hashdelete(tprintf("__%s", cmd->cmdname), &mudstate.command_htab);
hashadd(tprintf("__%s", cmd->cmdname), (int *)cmd, &mudstate.
command_htab, HASH_ALIAS);
hashreplall((int *)old, (int *)cmd, &mudstate.command_htab);
} else {
hashdelall((int *)old, &mudstate.command_htab);
}
XFREE(old->cmdname, "delcommand.cmdname");
XFREE(old, "delcommand.cmdp");
reset_prefix_cmds();
notify(player, "Done.");
return;
} else {
for (nextp = (ADDENT *)old->info.added; nextp != NULL; nextp = nextp->next) {
if ((nextp->thing == thing) && (nextp->atr == atr)) {
/* Delete it! */
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1107
1108
1109
1110
1111

XFREE(nextp->name, "delcommand.name");
if (!prev) {
if (!nextp->next) {
hashdelete(name, &mudstate.command_htab);
if ((cmd = (CMDENT *)hashfind(tprintf("__%s", name), &
mudstate.command_htab)) != NULL) {
hashadd(cmd->cmdname, (int *)cmd, &mudstate.command_htab
, 0);
/* in case we deleted by alias */
if (strcmp(name, cmd->cmdname)) {
hashadd(name, (int *)cmd, &mudstate.command_htab,
HASH_ALIAS);
}

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

/* the __ alias may have been temporarily


* marked as the original hash entry
*/
hashdelete(tprintf("__%s", cmd->cmdname), &mudstate.
command_htab);
hashadd(tprintf("__%s", cmd->cmdname), (int *)cmd, &
mudstate.command_htab, HASH_ALIAS);

1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153

Saturday, June 16, 2012 11:27 PM

hashreplall((int *)old, (int *)cmd, &mudstate.


command_htab);
} else {
hashdelall((int *)old, &mudstate.command_htab);
}
XFREE(old->cmdname, "delcommand.cmdname");
XFREE(old, "delcommand.cmdp");
} else {
old->info.added = nextp->next;
XFREE(nextp, "delcommand.addent");
}
} else {
prev->next = nextp->next;
XFREE(nextp, "delcommand.addent");
}
reset_prefix_cmds();
notify(player, "Done.");
return;

}
prev = nextp;

}
notify(player, "Command not found in command table." );

}
} else {
notify(player, "Command not found in command table." );
}

/* @program 'glues' a user's input to a command. Once executed, the first


* string input from any of the doer's logged in descriptors will be
* substituted in <command> as %0. Commands already queued by the doer
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206

Saturday, June 16, 2012 11:27 PM

* will be processed normally.


*/
void handle_prog(d, message)
DESC *d;
char *message;
{
DESC *all, *dsave;
char *cmd;
dbref aowner;
int aflags, alen;
/* Allow the player to pipe a command while in interactive mode.
* Use telnet protocol's GOAHEAD command to show prompt
*/
if (*message == '|') {
dsave = d;
do_command(d, message + 1, 1);
if (dsave == d) {
/* We MUST check if we still have a descriptor, and it's
* the same one, since we could have piped a LOGOUT or
* QUIT!
*/
/* Use telnet protocol's GOAHEAD command to show prompt, make
sure that we haven't been issues an @quitprogram */
if (d->program_data != NULL) {
queue_rawstring(d, (char *) "> \377\371");
}
return;
}

}
cmd = atr_get(d->player, A_PROGCMD, &aowner, &aflags, &alen);
wait_que(d->program_data->wait_cause, d->player, 0, NOTHING, 0, cmd,
(char **)&message, 1, d->program_data->wait_data);
/* First, set 'all' to a descriptor we find for this player */
all = (DESC *)nhashfind(d->player, &mudstate.desc_htab) ;
Free_RegData(all->program_data->wait_data);
XFREE(all->program_data, "program_data");
/* Set info for all player descriptors to NULL */
DESC_ITER_PLAYER(d->player, all)
all->program_data = NULL;
atr_clr(d->player, A_PROGCMD);
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259

Saturday, June 16, 2012 11:27 PM

free_lbuf(cmd);

static int ok_program(player, doer)


dbref player;
dbref doer;
{
if ((!(Prog(player) || Prog(Owner(player))) && !Controls(player, doer)) ||
(God(doer) && !God(player))) {
notify(player, NOPERM_MESSAGE);
return 0;
}
if (!isPlayer(doer) || !Good_obj(doer)) {
notify(player, "No such player.");
return 0;
}
if (!Connected(doer)) {
notify(player, "Sorry, that player is not connected." );
return 0;
}
return 1;
}
void do_quitprog(player, cause, key, name)
dbref player, cause;
int key;
char *name;
{
DESC *d;
dbref doer;
int isprog = 0;
if (*name) {
doer = match_thing(player, name);
} else {
doer = player;
}
if (!ok_program(player, doer))
return;
DESC_ITER_PLAYER(doer, d) {
if (d->program_data != NULL) {
isprog = 1;
}
}
if (!isprog) {
notify(player, "Player is not in an @program." );
return;
}
d = (DESC *)nhashfind(doer, &mudstate.desc_htab);
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312

Saturday, June 16, 2012 11:27 PM

Free_RegData(d->program_data->wait_data);
XFREE(d->program_data, "program_data");
/* Set info for all player descriptors to NULL */
DESC_ITER_PLAYER(doer, d)
d->program_data = NULL;

atr_clr(doer, A_PROGCMD);
notify(player, "@program cleared.");
notify(doer, "Your @program has been terminated." );

void do_prog(player, cause, key, name, command)


dbref player, cause;
int key;
char *name, *command;
{
DESC *d;
PROG *program;
int atr, aflags, lev, found;
dbref doer, thing, aowner, parent;
ATTR *ap;
char *attrib, *msg;
if (!name || !*name) {
notify(player, "No players specified.");
return;
}
doer = match_thing(player, name);
if (!ok_program(player, doer))
return;
msg = command;
attrib = parse_to(&msg, ':', 1);
if (msg && *msg) {
notify(doer, msg);
}
parse_attrib(player, attrib, &thing, &atr, 0);
if (atr != NOTHING) {
if (!atr_pget_info(thing, atr, &aowner, &aflags)) {
notify(player, "Attribute not present on object." );
return;
}
ap = atr_num(atr);
/* We've got to find this attribute in the object's
* parent chain, somewhere.
*/

-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365

Saturday, June 16, 2012 11:27 PM

found = 0;
ITER_PARENTS(thing, parent, lev) {
if (atr_get_info(parent, atr, &aowner, &aflags)) {
found = 1;
break;
}
}
if (!found) {
notify(player, "Attribute not present on object." );
return;
}
if (God(player) ||
(!God(thing) &&
See_attr(player, thing, ap, aowner, aflags) &&
(Wizard(player) || (aowner == Owner(player))))) {
atr_add_raw(doer, A_PROGCMD, atr_get_raw(parent, atr));
} else {
notify(player, NOPERM_MESSAGE);
return;
}
} else {
notify(player, "No such attribute.");
return;
}
/* Check to see if the cause already has an @prog input pending */
DESC_ITER_PLAYER(doer, d) {
if (d->program_data != NULL) {
notify(player, "Input already pending.");
return;
}
}
program = (PROG *) XMALLOC(sizeof(PROG), "do_prog");
program->wait_cause = player;
if (mudstate.rdata) {
Alloc_RegData("do_prog.gdata", mudstate.rdata, program->wait_data);
Copy_RegData("do_prog.regs", mudstate.rdata, program->wait_data);
} else {
program->wait_data = NULL;
}
/* Now, start waiting. */
DESC_ITER_PLAYER(doer, d) {
d->program_data = program;

/* Use telnet protocol's GOAHEAD command to show prompt */


queue_rawstring(d, (char *) "> \377\371");

-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418

Saturday, June 16, 2012 11:27 PM

}
/* --------------------------------------------------------------------------* do_restart: Restarts the game.
*/
void do_restart(player, cause, key)
dbref player, cause;
int key;
{
LOGFILETAB *lp;
MODULE *mp;
if (mudstate.dumping) {
notify(player, "Dumping. Please try again later." );
return;
}
/* Make sure what follows knows we're restarting. No need to clear
* this, since this process is going away-- this is also set on
* startup when the restart.db is read.
*/
mudstate.restarting = 1;
raw_broadcast(0, "GAME: Restart by %s, please wait." ,
Name(Owner(player)));
STARTLOG(LOG_ALWAYS, "WIZ", "RSTRT")
log_printf("Restart by ");
log_name(player);
ENDLOG;
/* Do a dbck first so we don't end up with an inconsistent state.
* Otherwise, since we don't write out GOING objects, the initial
* dbck at startup won't have valid data to work with in order to
* clean things out.
*/
do_dbck(NOTHING, NOTHING, 0);
/* Dump databases, etc. */
dump_database_internal(DUMP_DB_RESTART);
SYNC;
CLOSE;
sql_shutdown();
if (slave_socket != -1) {
shutdown(slave_socket, 2);
close(slave_socket);
slave_socket = -1;
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471

Saturday, June 16, 2012 11:27 PM

}
if (slave_pid != 0) {
kill(slave_pid, SIGKILL);
}
for (lp = logfds_table; lp->log_flag; lp++) {
if (lp->filename && lp->fileptr) {
fclose(lp->fileptr);
rename(lp->filename,
tprintf("%s.%ld", lp->filename, (long) mudstate.now));
}
}
if (mainlog_fp != stderr) {
fclose(mainlog_fp);
rename(mudconf.mudlogname,
tprintf("%s.%ld", mudconf.mudlogname, (long) mudstate.now));
}
alarm(0);
dump_restart_db();
WALK_ALL_MODULES(mp) {
lt_dlclose(mp->handle);
}

execl(mudconf.exec_path, mudconf.exec_path,
(char *) "-c", mudconf.config_file,
(char *) "-l", mudconf.mudlogname,
(char *) "-p", mudconf.pid_file,
(char *) "-t", mudconf.txthome,
(char *) "-b", mudconf.binhome,
(char *) "-d", mudconf.dbhome,
(char *) "-g", mudconf.gdbm,
(char *) "-k", mudconf.crashdb,
NULL);

/* --------------------------------------------------------------------------* do_comment: Implement the @@ (comment) command. Very cpu-intensive :-)


* do_eval is similar, except it gets passed on arg.
*/
void do_comment(player, cause, key)
dbref player, cause;
int key;
{
}
void do_eval(player, cause, key, str)
dbref player, cause;
int key;
char *str;
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524

Saturday, June 16, 2012 11:27 PM

{
}
/* --------------------------------------------------------------------------*/
static dbref promote_dflt(old, new)
dbref old, new;
{
switch (new) {
case NOPERM:
return NOPERM;
case AMBIGUOUS:
if (old == NOPERM)
return old;
else
return new;
}
if ((old == NOPERM) || (old == AMBIGUOUS))
return old;
}

return NOTHING;

dbref match_possessed(player, thing, target, dflt, check_enter)


dbref player, thing, dflt;
char *target;
int check_enter;
{
dbref result, result1;
int control;
char *buff, *start, *place, *s1, *d1, *temp;
/* First, check normally */
if (Good_obj(dflt))
return dflt;
/* Didn't find it directly.

Recursively do a contents check */

start = target;
while (*target) {
/* Fail if no ' characters */
place = target;
target = strchr(place, '\'');
if ((target == NULL) || !*target)
return dflt;
/* If string started with a ', skip past it */

-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577

Saturday, June 16, 2012 11:27 PM

if (place == target) {
target++;
continue;
}
/* If next character is not an s or a space, skip past */
temp = target++;
if (!*target)
return dflt;
if ((*target != 's') && (*target != 'S') && (*target != ' '))
continue;
/* If character was not a space make sure the following
* character is a space.
*/
if (*target != ' ') {
target++;
if (!*target)
return dflt;
if (*target != ' ')
continue;
}
/* Copy the container name to a new buffer so we can
* terminate it.
*/
buff = alloc_lbuf("match_possessed");
for (s1 = start, d1 = buff; *s1 && (s1 < temp); *d1++ = (*s1++)) ;
*d1 = '\0';
/* Look for the container here and in our inventory.
* past if we can't find it.
*/

Skip

init_match(thing, buff, NOTYPE);


if (player == thing) {
match_neighbor();
match_possession();
} else {
match_possession();
}
result1 = match_result();
free_lbuf(buff);
if (!Good_obj(result1)) {
dflt = promote_dflt(dflt, result1);
continue;
}
/* If we don't control it and it is either dark or opaque,
* skip past.
*/

-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

Saturday, June 16, 2012 11:27 PM

control = Controls(player, result1);


if ((Dark(result1) || Opaque(result1)) && !control) {
dflt = promote_dflt(dflt, NOTHING);
continue;
}
/* Validate object has the ENTER bit set, if requested */
if ((check_enter) && !Enter_ok(result1) && !control) {
dflt = promote_dflt(dflt, NOPERM);
continue;
}
/* Look for the object in the container */
init_match(result1, target, NOTYPE);
match_possession();
result = match_result();
result = match_possessed(player, result1, target, result,
check_enter);
if (Good_obj(result))
return result;
dflt = promote_dflt(dflt, result);

}
return dflt;

/* --------------------------------------------------------------------------* parse_range: break up <what>,<low>,<high> syntax


*/
void parse_range(name, low_bound, high_bound)
char **name;
dbref *low_bound, *high_bound;
{
char *buff1, *buff2;
buff1 = *name;
if (buff1 && *buff1)
*name = parse_to(&buff1, ',', EV_STRIP_TS);
if (buff1 && *buff1) {
buff2 = parse_to(&buff1, ',', EV_STRIP_TS);
if (buff1 && *buff1) {
while (*buff1 && isspace(*buff1))
buff1++;
if (*buff1 == NUMBER_TOKEN)
buff1++;
*high_bound = atoi(buff1);
if (*high_bound >= mudstate.db_top)
*high_bound = mudstate.db_top - 1;
} else {
*high_bound = mudstate.db_top - 1;
}
while (*buff2 && isspace(*buff2))
buff2++;
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683

Saturday, June 16, 2012 11:27 PM

if (*buff2 == NUMBER_TOKEN)
buff2++;
*low_bound = atoi(buff2);
if (*low_bound < 0)
*low_bound = 0;
} else {
*low_bound = 0;
*high_bound = mudstate.db_top - 1;
}

int parse_thing_slash(player, thing, after, it)


dbref player, *it;
char *thing, **after;
{
char *str;
/* get name up to / */
for (str = thing; *str && (*str != '/'); str++) ;
/* If no / in string, return failure */
if (!*str) {
*after = NULL;
*it = NOTHING;
return 0;
}
*str++ = '\0';
*after = str;
/* Look for the object */
init_match(player, thing, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
*it = match_result();
/* Return status of search */
}

return (Good_obj(*it));

extern NAMETAB lock_sw[];


int get_obj_and_lock(player, what, it, attr, errmsg, bufc)
dbref player, *it;
char *what, *errmsg, **bufc;
ATTR **attr;
{
char *str, *tbuf;
int anum;
tbuf = alloc_lbuf("get_obj_and_lock");
strcpy(tbuf, what);
-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736

Saturday, June 16, 2012 11:27 PM

if (parse_thing_slash(player, tbuf, &str, it)) {


/* <obj>/<lock> syntax, use the named lock */
anum = search_nametab(player, lock_sw, str);
if (anum == -1) {
free_lbuf(tbuf);
safe_str("#-1 LOCK NOT FOUND", errmsg, bufc);
return 0;
}
} else {
/* Not <obj>/<lock>, do a normal get of the default lock */

*it = match_thing(player, what);


if (!Good_obj(*it)) {
free_lbuf(tbuf);
safe_str("#-1 NOT FOUND", errmsg, bufc);
return 0;
}
anum = A_LOCK;

/* Get the attribute definition, fail if not found */

free_lbuf(tbuf);
*attr = atr_num(anum);
if (!(*attr)) {
safe_str("#-1 LOCK NOT FOUND", errmsg, bufc);
return 0;
}
return 1;

/* --------------------------------------------------------------------------* where_is: Returns place where obj is linked into a list.


* ie. location for players/things, source for exits, NOTHING for rooms.
*/
dbref where_is(what)
dbref what;
{
dbref loc;
if (!Good_obj(what))
return NOTHING;
switch (Typeof(what)) {
case TYPE_PLAYER:
case TYPE_THING:
case TYPE_ZONE:
loc = Location(what);
break;
-33-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789

Saturday, June 16, 2012 11:27 PM

case TYPE_EXIT:
loc = Exits(what);
break;
default:
loc = NOTHING;
break;
}
return loc;

/* --------------------------------------------------------------------------* where_room: Return room containing player, or NOTHING if no room or


* recursion exceeded. If player is a room, returns itself.
*/
dbref where_room(what)
dbref what;
{
int count;

for (count = mudconf.ntfy_nest_lim; count > 0; count--) {


if (!Good_obj(what))
break;
if (isRoom(what))
return what;
if (!Has_location(what))
break;
what = Location(what);
}
return NOTHING;

int locatable(player, it, cause)


dbref player, it, cause;
{
dbref loc_it, room_it;
int findable_room;
/* No sense if trying to locate a bad object */
if (!Good_obj(it))
return 0;
loc_it = where_is(it);
/* Succeed if we can examine the target, if we are the target, if
* we can examine the location, if a wizard caused the lookup,
* or if the target caused the lookup.
*/
if (Examinable(player, it) ||
Find_Unfindable(player) ||
(loc_it == player) ||
-34-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842

Saturday, June 16, 2012 11:27 PM

((loc_it != NOTHING) &&


(Examinable(player, loc_it) || loc_it == where_is(player))) ||
Wizard(cause) ||
(it == cause))
return 1;
room_it = where_room(it);
if (Good_obj(room_it))
findable_room = !Hideout(room_it);
else
findable_room = 1;
/* Succeed if we control the containing room or if the target is
* findable and the containing room is not unfindable.
*/
if (((room_it != NOTHING) && Examinable(player, room_it)) ||
Find_Unfindable(player) || (Findable(it) && findable_room))
return 1;
/* We can't do it. */
}

return 0;

/* --------------------------------------------------------------------------* nearby: Check if thing is nearby player (in inventory, in same room, or
* IS the room.
*/
int nearby(player, thing)
dbref player, thing;
{
int thing_loc, player_loc;

if (!Good_obj(player) || !Good_obj(thing))
return 0;
thing_loc = where_is(thing);
if (thing_loc == player)
return 1;
player_loc = where_is(player);
if ((thing_loc == player_loc) || (thing == player_loc))
return 1;
return 0;

/* --------------------------------------------------------------------------* master_attr: Get the evaluated text string of a master attribute.


*
Note that this returns an lbuf, which must be freed by
*
the caller.
*/
char *master_attr(player, thing, what, sargs, nsargs, f_ptr)
-35-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895

Saturday, June 16, 2012 11:27 PM

dbref player, thing;


int what;
char **sargs;
int nsargs;
int *f_ptr;
/* If the attribute exists, evaluate it and return pointer to lbuf.
* If not, return NULL.
* Respect global overrides.
* what is assumed to be more than 0.
*/
char *d, *m, *buff, *bp, *str, *tbuf, *tp, *sp, *list, *bb_p, *lp;
int t, aflags, alen, is_ok, lev;
dbref aowner, master, parent, obj;
ATTR *ap;
GDATA *preserve;
if (NoDefault(thing)) {
master = NOTHING;
} else {
switch (Typeof(thing)) {
case TYPE_ROOM:
master = mudconf.room_defobj;
break;
case TYPE_EXIT:
master = mudconf.exit_defobj;
break;
case TYPE_PLAYER:
master = mudconf.player_defobj;
break;
case TYPE_GARBAGE:
return NULL;
break;
/* NOTREACHED */
default:
master = mudconf.thing_defobj;
}
if (master == thing)
master = NOTHING;
}
m = NULL;
d = atr_pget(thing, what, &aowner, &aflags, &alen);
if (Good_obj(master)) {
ap = atr_num(what);
t = (ap && (ap->flags & AF_DEFAULT)) ? 1 : 0;
} else {
t = 0;
}
if (t) {
m = atr_pget(master, what, &aowner, &aflags, &alen);
}
-36-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948

Saturday, June 16, 2012 11:27 PM

if (f_ptr)
*f_ptr = aflags;
if (!(*d || (t && *m))) {
free_lbuf(d);
if (m) {
free_lbuf(m);
}
return NULL;
}
/* Construct any arguments that we're going to pass along on the
* stack.
*/
switch (what) {
case A_LEXITS_FMT:
list = alloc_lbuf("master_attr.list");
bb_p = lp = list;
is_ok = Darkened(player, thing);
ITER_PARENTS(thing, parent, lev) {
if (!Has_exits(parent))
continue;
DOLIST(obj, Exits(parent)) {
if (Can_See_Exit(player, obj, is_ok)) {
if (lp != bb_p) {
safe_chr(' ', list, &lp);
}
safe_dbref(list, &lp, obj);
}
}
}
*lp = '\0';
is_ok = 1;
break;
case A_LCON_FMT:
list = alloc_lbuf("master_attr.list");
bb_p = lp = list;
is_ok = Sees_Always(player, thing);
DOLIST(obj, Contents(thing)) {
if (Can_See(player, obj, is_ok)) {
if (lp != bb_p) {
safe_chr(' ', list, &lp);
}
safe_dbref(list, &lp, obj);
}
}
*lp = '\0';
is_ok = 1;
break;
default:
list = NULL;
is_ok = nsargs;
-37-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000

Saturday, June 16, 2012 11:27 PM

break;

/* Go do it. */

preserve = save_global_regs("master_attr_save");
buff = bp = alloc_lbuf("master_attr.1");
if (t && *m) {
str = m;
if (*d) {
sp = d;
tbuf = tp = alloc_lbuf("master_attr.deval");
exec(tbuf, &tp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&sp, ((list == NULL) ? sargs : &list), is_ok);
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, &tbuf, 1);
free_lbuf(tbuf);
} else {
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, ((list == NULL) ? sargs : &list), is_ok);
}
} else if (*d) {
str = d;
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, ((list == NULL) ? sargs : &list), is_ok);
}
*bp = '\0';
free_lbuf(d);
if (m) {
free_lbuf(m);
}
if (list) {
free_lbuf(list);
}
restore_global_regs("master_attr_restore", preserve);
return buff;

/* --------------------------------------------------------------------------* did_it: Have player do something to/with thing


*/
void did_it(player, thing, what, def, owhat, odef, awhat, ctrl_flags, args, nargs,
msg_key)
dbref player, thing;
int what, owhat, awhat, ctrl_flags, nargs, msg_key;
char *args[];
const char *def, *odef;
{
-38-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053

Saturday, June 16, 2012 11:27 PM

GDATA *preserve;
char *d, *m, *buff, *act, *charges, *bp, *str;
char *tbuf, *tp, *sp;
dbref loc, aowner;
int t, num, aflags, alen, need_pres;
dbref master;
ATTR *ap;
int retval = 0;
/* If we need to call exec() from within this function, we first save
* the state of the global registers, in order to avoid munging them
* inappropriately. Do note that the restoration to their original
* values occurs BEFORE the execution of the @a-attribute. Therefore,
* any changing of setq() values done in the @-attribute and @o-attribute
* will NOT be passed on. This prevents odd behaviors that result from
* odd @verbs and so forth (the idea is to preserve the caller's control
* of the global register values).
*/
need_pres = 0;
if (NoDefault(thing)) {
master = NOTHING;
} else {
switch (Typeof(thing)) {
case TYPE_ROOM:
master = mudconf.room_defobj;
break;
case TYPE_EXIT:
master = mudconf.exit_defobj;
break;
case TYPE_PLAYER:
master = mudconf.player_defobj;
break;
default:
master = mudconf.thing_defobj;
}
if (master == thing || !Good_obj(master))
master = NOTHING;
}
/* Module call. Modules can return a negative number, zero, or a
* positive number.
* Positive: Stop calling modules. Return; do not execute normal did_it().
* Zero: Continue calling modules. Execute normal did_it() if we get
*
to the end of the modules and nothing has returned non-zero.
* Negative: Stop calling modules. Execute normal did_it().
*/
CALL_SOME_MODULES(retval, did_it,
(player, thing, master,
what, def, owhat, def, awhat,
ctrl_flags, args, nargs, msg_key));
if (retval > 0)
-39-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106

Saturday, June 16, 2012 11:27 PM

return;
/* message to player */
m = NULL;
if (what > 0) {
/* Check for global attribute format override. If it exists,
* use that. The actual attribute text we were provided
* will be passed to that as %0. (Note that if a global
* override exists, we never use a supplied server default.)
*
* Otherwise, we just go evaluate what we've got, and
* if that's nothing, we go do the default.
*/
d = atr_pget(thing, what, &aowner, &aflags, &alen);
if (Good_obj(master)) {
ap = atr_num(what);
t = (ap && (ap->flags & AF_DEFAULT)) ? 1 : 0;
} else {
t = 0;
}
if (t) {
m = atr_pget(master, what, &aowner, &aflags, &alen);
}
if (*d || (t && *m)) {
need_pres = 1;
preserve = save_global_regs("did_it_save");
buff = bp = alloc_lbuf("did_it.1");
if (t && *m) {
str = m;
if (*d) {
sp = d;
tbuf = tp = alloc_lbuf("did_it.deval");
exec(tbuf, &tp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&sp, args, nargs);
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, &tbuf, 1);
free_lbuf(tbuf);
} else {
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, (char **) NULL, 0);
}
} else if (*d) {
str = d;
exec(buff, &bp, thing, player, player,
-40-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159

Saturday, June 16, 2012 11:27 PM

EV_EVAL | EV_FIGNORE | EV_TOP,


&str, args, nargs);

}
*bp = '\0';
#ifdef PUEBLO_SUPPORT
if ((aflags & AF_HTML) && Html(player)) {
char *buff_cp = buff + strlen(buff);
safe_crlf(buff, &buff_cp);
notify_html(player, buff);
} else
notify(player, buff);
#else
notify(player, buff);
#endif /* PUEBLO_SUPPORT */
free_lbuf(buff);
} else if (def) {
notify(player, def);
}
free_lbuf(d);
} else if ((what < 0) && def) {
notify(player, def);
}
if (m) {
free_lbuf(m);
}
/* message to neighbors */
m = NULL;
if ((owhat > 0) && Has_location(player) &&
Good_obj(loc = Location(player))) {
d = atr_pget(thing, owhat, &aowner, &aflags, &alen);
if (Good_obj(master)) {
ap = atr_num(owhat);
t = (ap && (ap->flags & AF_DEFAULT)) ? 1 : 0;
} else {
t = 0;
}
if (t) {
m = atr_pget(master, owhat, &aowner, &aflags, &alen);
}
if (*d || (t && *m)) {
if (!need_pres) {
need_pres = 1;
preserve = save_global_regs("did_it_save");
}
buff = bp = alloc_lbuf("did_it.2");
if (t && *m) {
-41-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212

Saturday, June 16, 2012 11:27 PM

str = m;
if (*d) {
sp = d;
tbuf = tp = alloc_lbuf("did_it.deval");
exec(tbuf, &tp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&sp, args, nargs);
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, &tbuf, 1);
free_lbuf(tbuf);
} else if (odef) {
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, (char **) &odef, 1);
} else {
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, (char **) NULL, 0);
}
} else if (*d) {
str = d;
exec(buff, &bp, thing, player, player,
EV_EVAL | EV_FIGNORE | EV_TOP,
&str, args, nargs);
}
*bp = '\0';
if (*buff) {
if (aflags & AF_NONAME) {
notify_except2(loc, player, player, thing, buff, msg_key);
} else {
notify_except2(loc, player, player, thing,
tprintf("%s %s", Name(player), buff),
msg_key);
}
}
free_lbuf(buff);
} else if (odef) {
if (ctrl_flags & VERB_NONAME) {
notify_except2(loc, player, player, thing, odef, msg_key);
} else {
notify_except2(loc, player, player, thing,
tprintf("%s %s", Name(player), odef), msg_key);
}
}
free_lbuf(d);
} else if ((owhat < 0) && odef && Has_location(player) &&
Good_obj(loc = Location(player))) {
if (ctrl_flags & VERB_NONAME) {
notify_except2(loc, player, player, thing, odef, msg_key);
} else {
notify_except2(loc, player, player, thing,
tprintf("%s %s", Name(player), odef), msg_key);
-42-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265

Saturday, June 16, 2012 11:27 PM

}
}
if (m) {
free_lbuf(m);
}
/* If we preserved the state of the global registers, restore them. */
if (need_pres)
restore_global_regs("did_it_restore", preserve);
/* do the action attribute */
if (awhat > 0) {
if (*(act = atr_pget(thing, awhat, &aowner, &aflags, &alen))) {
charges = atr_pget(thing, A_CHARGES, &aowner, &aflags, &alen);
if (*charges) {
num = atoi(charges);
if (num > 0) {
buff = alloc_sbuf("did_it.charges");
sprintf(buff, "%d", num - 1);
atr_add_raw(thing, A_CHARGES, buff);
free_sbuf(buff);
} else if (*(buff = atr_pget(thing, A_RUNOUT,
&aowner, &aflags, &alen))) {
free_lbuf(act);
act = buff;
} else {
free_lbuf(act);
free_lbuf(buff);
free_lbuf(charges);
return;
}
}
free_lbuf(charges);
/* Skip any leading $<command>: or ^<monitor>: pattern.
* If we run off the end of string without finding an unescaped
* ':' (or there's nothing after it), go back to the beginning
* of the string and just use that.
*/
if ((*act == '$') || (*act == '^')) {
for (tp = act + 1;
*tp && ((*tp != ':') || (*(tp - 1) == '\\'));
tp++)
;
if (!*tp) {
tp = act;
} else {
tp++;
/* must advance past the ':' */
}
-43-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318

Saturday, June 16, 2012 11:27 PM

} else {
tp = act;
}
/* Go do it. */
if (ctrl_flags & (VERB_NOW|TRIG_NOW)) {
preserve = save_global_regs("did_it_save2");
process_cmdline(thing, player, tp, args, nargs, NULL);
restore_global_regs("did_it_restore2", preserve);
} else {
wait_que(thing, player, 0, NOTHING, 0, tp,
args, nargs, mudstate.rdata);
}

}
free_lbuf(act);
}

/*
* --------------------------------------------------------------------------* * do_verb: Command interface to did_it.
*/
void do_verb(player, cause, key, victim_str, args, nargs)
dbref player, cause;
int key, nargs;
char *victim_str, *args[];
{
dbref actor, victim, aowner;
int what, owhat, awhat, nxargs, restriction, aflags, i;
ATTR *ap;
const char *whatd, *owhatd;
char *xargs[NUM_ENV_VARS];
/*
* Look for the victim
*/
if (!victim_str || !*victim_str) {
notify(player, "Nothing to do.");
return;
}
/*
* Get the victim
*/
init_match(player, victim_str, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
victim = noisy_match_result();
if (!Good_obj(victim))
return;

-44-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371

/*
* Get the actor.
*/

Saturday, June 16, 2012 11:27 PM

Default is my cause

if ((nargs >= 1) && args[0] && *args[0]) {


init_match(player, args[0], NOTYPE);
match_everything(MAT_EXIT_PARENTS);
actor = noisy_match_result();
if (!Good_obj(actor))
return;
} else {
actor = cause;
}
/*
* Check permissions. There are two possibilities * 1: Player * * *
* controls both victim and actor. In this case victim runs *
his
*
* * * * * * action list. * 2: Player controls actor. In this case
* * victim * does * not run his *
action list and any attributes
* * that * player cannot * read from *
victim are defaulted.
*/
if (!controls(player, actor)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
restriction = !controls(player, victim);
what = -1;
owhat = -1;
awhat = -1;
whatd = NULL;
owhatd = NULL;
nxargs = 0;
/*
* Get invoker message attribute
*/
if (nargs >= 2) {
ap = atr_str(args[1]);
if (ap && (ap->number > 0))
what = ap->number;
}
/*
* Get invoker message default
*/
if ((nargs >= 3) && args[2] && *args[2]) {
whatd = args[2];
}
/*
-45-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424

Saturday, June 16, 2012 11:27 PM

* Get others message attribute


*/
if (nargs >= 4) {
ap = atr_str(args[3]);
if (ap && (ap->number > 0))
owhat = ap->number;
}
/*
* Get others message default
*/
if ((nargs >= 5) && args[4] && *args[4]) {
owhatd = args[4];
}
/*
* Get action attribute
*/
if (nargs >= 6) {
ap = atr_str(args[5]);
if (ap)
awhat = ap->number;
}
/*
* Get arguments
*/
if (nargs >= 7) {
parse_arglist(victim, actor, actor, args[6], '\0',
EV_STRIP_LS | EV_STRIP_TS, xargs, NUM_ENV_VARS,
(char **)NULL, 0);
for (nxargs = 0; (nxargs < NUM_ENV_VARS) && xargs[nxargs];
nxargs++) ;
}
/*
* If player doesn't control both, enforce visibility restrictions.
* Regardless of control we still check if the player can read the
* attribute, since we don't want him getting wiz-readable-only attrs.
*/
atr_get_info(victim, what, &aowner, &aflags);
if (what != -1) {
ap = atr_num(what);
if (!ap || !Read_attr(player, victim, ap, aowner, aflags) ||
(restriction &&
((ap->number == A_DESC) && !mudconf.read_rem_desc &&
!Examinable(player, victim) && !nearby(player, victim))))
what = -1;
}
atr_get_info(victim, owhat, &aowner, &aflags);
if (owhat != -1) {
ap = atr_num(owhat);
-46-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477

Saturday, June 16, 2012 11:27 PM

if (!ap || !Read_attr(player, victim, ap, aowner, aflags) ||


(restriction &&
((ap->number == A_DESC) && !mudconf.read_rem_desc &&
!Examinable(player, victim) && !nearby(player, victim))))
owhat = -1;

}
if (restriction)
awhat = 0;
/*
* Go do it
*/

did_it(actor, victim, what, whatd, owhat, owhatd, awhat,


key & (VERB_NOW | VERB_NONAME), xargs, nxargs,
(((key & VERB_SPEECH) ? MSG_SPEECH : 0) |
((key & VERB_MOVE) ? MSG_MOVE : 0) |
((key & VERB_PRESENT) ? MSG_PRESENCE : 0)));
/*
* Free user args
*/
for (i = 0; i < nxargs; i++)
free_lbuf(xargs[i]);
}
void do_sql_connect(player, cause, key)
dbref player, cause;
int key;
{
if (sql_init() < 0) {
notify(player, "Database connection attempt failed." );
} else {
notify(player, "Database connection succeeded." );
}
}
/* --------------------------------------------------------------------------* do_redirect: Redirect PUPPET, TRACE, VERBOSE output to another player.
*/
void do_redirect(player, cause, key, from_name, to_name)
dbref player, cause;
int key;
char *from_name, *to_name;
{
dbref from_ref, to_ref;
NUMBERTAB *np;
/* Find what object we're redirecting from. We must either control it,
-47-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530

Saturday, June 16, 2012 11:27 PM

* or it must be REDIR_OK.
*/
init_match(player, from_name, NOTYPE);
match_everything(0);
from_ref = noisy_match_result();
if (!Good_obj(from_ref))
return;
/* If we have no second argument, we are un-redirecting something
* which is already redirected. We can get rid of it if we control
* the object being redirected, or we control the target of the
* redirection.
*/
if (!to_name || !*to_name) {
if (!H_Redirect(from_ref)) {
notify(player, "That object is not being redirected." );
return;
}
np = (NUMBERTAB *) nhashfind(from_ref, &mudstate.redir_htab);
if (np) {
/* This should always be true -- if we have the flag the
* hashtable lookup should succeed -- but just in case,
* we check. (We clear the flag upon startup.)
* If we have a weird situation, we don't care whether
* or not the control criteria gets met; we just fix it.
*/
if (!Controls(player, from_ref) && (np->num != player)) {
notify(player, NOPERM_MESSAGE);
return;
}
if (np->num != player) {
notify(np->num,
tprintf("Output from %s(#%d) is no being redirected to you." ,
Name(from_ref), from_ref));
}
XFREE(np, "redir_struct");
nhashdelete(from_ref, &mudstate.redir_htab);
}
s_Flags3(from_ref, Flags3(from_ref) & ~HAS_REDIRECT);
notify(player, "Redirection stopped.");
if (from_ref != player) {
notify(from_ref, "You are no longer being redirected." );
}
return;
}
/* If the object is already being redirected, we cannot do so again. */
if (H_Redirect(from_ref)) {
notify(player, "That object is already being redirected." );
return;
-48-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583

Saturday, June 16, 2012 11:27 PM

}
/* To redirect something, it needs to either be REDIR_OK or we
* need to control it.
*/
if (!Controls(player, from_ref) && !Redir_ok(from_ref)) {
notify(player, NOPERM_MESSAGE);
return;
}
/* Find the player that we're redirecting to. We must control the
* player.
*/
to_ref = lookup_player(player, to_name, 1);
if (!Good_obj(to_ref)) {
notify(player, "No such player.");
return;
}
if (!Controls(player, to_ref)) {
notify(player, NOPERM_MESSAGE);
return;
}
/* Insert it into the hashtable. */
np = (NUMBERTAB *) XMALLOC(sizeof(NUMBERTAB), "redir_struct");
np->num = to_ref;
nhashadd(from_ref, (int *) np, &mudstate.redir_htab);
s_Flags3(from_ref, Flags3(from_ref) | HAS_REDIRECT);

if (from_ref != player) {
notify(from_ref,
tprintf("You have been redirected to %s." , Name(to_ref)));
}
if (to_ref != player) {
notify(to_ref,
tprintf("Output from %s(#%d) has been redirected to you." ,
Name(from_ref), from_ref));
}
notify(player, "Redirected.");

/* --------------------------------------------------------------------------* do_reference: Manipulate nrefs.


*/
void do_reference(player, cause, key, ref_name, obj_name)
dbref player, cause;
int key;
char *ref_name, *obj_name;
{
-49-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636

Saturday, June 16, 2012 11:27 PM

HASHENT *hptr;
HASHTAB *htab;
int i, len, total, is_global;
char tbuf[LBUF_SIZE], outbuf[LBUF_SIZE], *tp, *bp, *buff, *s;
dbref target, *np;
if (key & NREF_LIST) {
htab = &mudstate.nref_htab;
if (!ref_name || !*ref_name) {
/* Global only. */
is_global = 1;
tbuf[0] = '_';
tbuf[1] = '\0';
len = 1;
} else {
is_global = 0;
if (!string_compare(ref_name, "me")) {
target = player;
} else {
target = lookup_player(player, ref_name, 1);
if (target == NOTHING) {
notify(player, "No such player.");
return;
}
if (!Controls(player, target)) {
notify(player, NOPERM_MESSAGE);
return;
}
}
tp = tbuf;
safe_ltos(tbuf, &tp, player);
safe_chr('.', tbuf, &tp);
*tp = '\0';
len = strlen(tbuf);
}
total = 0;
for (i = 0; i < htab->hashsize; i++) {
for (hptr = htab->entry[i]; hptr != NULL; hptr = hptr->next) {
if (!strncmp(tbuf, hptr->target.s, len)) {
total++;
bp = outbuf;
safe_tprintf_str(outbuf, &bp, "%s: ",
((is_global) ? hptr->target.s :
strchr(hptr->target.s, '.') + 1));
buff = unparse_object(player, *(hptr->data), 0);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
if (Owner(player) != Owner(*(hptr->data))) {
safe_str((char *) " [owner: ", outbuf, &bp);
buff = unparse_object(player, Owner(*(hptr->data)), 0);
-50-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689

}
}

Saturday, June 16, 2012 11:27 PM

safe_str(buff, outbuf, &bp);


free_lbuf(buff);
safe_chr(']', outbuf, &bp);
}
*bp = '\0';
notify(player, outbuf);

notify(player, tprintf("Total references: %d", total));


return;
}
/* We can only reference objects that we can examine. */
if (obj_name && *obj_name) {
target = match_thing(player, obj_name);
if (!Good_obj(target))
return;
if (!Examinable(player, target)) {
notify(player, NOPERM_MESSAGE);
return;
}
} else {
target = NOTHING;
/* indicates clear */
}
/* If the reference name starts with an underscore, it's global.
* Only wizards can do that.
*/
tp = tbuf;
if (*ref_name == '_') {
if (!Wizard(player)) {
notify(player, NOPERM_MESSAGE);
return;
}
} else {
safe_ltos(tbuf, &tp, player);
safe_chr('.', tbuf, &tp);
}
for (s = ref_name; *s; s++)
safe_chr(tolower(*s), tbuf, &tp);
*tp = '\0';
/* Does this reference name exist already? */
np = (int *) hashfind(tbuf, &mudstate.nref_htab);
if (np) {
if (target == NOTHING) {
XFREE(np, "nref");
-51-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\predicates.c

2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733

Saturday, June 16, 2012 11:27 PM

hashdelete(tbuf, &mudstate.nref_htab);
notify(player, "Reference cleared.");
} else if (*np == target) {
/* Already got it. */
notify(player, "That reference has already been made." );
} else {
/* Replace it. */
XFREE(np, "nref");
np = (dbref *) XMALLOC(sizeof(dbref), "nref");
*np = target;
hashrepl(tbuf, np, &mudstate.nref_htab);
notify(player, "Reference updated.");
}
return;
}
/* Didn't find it. We've got a new one (or an error if we have no
* target but the reference didn't exist).
*/
if (target == NOTHING) {
notify(player, "No such reference to clear." );
return;
}

np = (dbref *) XMALLOC(sizeof(dbref), "nref");


*np = target;
hashadd(tbuf, np, &mudstate.nref_htab, 0);
notify(player, "Referenced.");

/* --------------------------------------------------------------------------* Miscellaneous stuff below.


*/
void do_sql(player, cause, key, name)
dbref player, cause;
int key;
char *name;
{
sql_query(player, name, NULL, NULL, &SPACE_DELIM, &SPACE_DELIM);
}

-52-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\quota.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:27 PM

/* quota.c - quota management commands */


/* $Id: quota.c,v 1.18 2002/08/02 20:48:47 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "match.h" /* required by code */
#include "attrs.h" /* required by code */
#include "powers.h" /* required by code */
/* --------------------------------------------------------------------------* load_quota: Load a quota into an array. Expects A_QUOTA or A_QUOTA.
*/
void load_quota(q_list, player, qtype)
int q_list[];
dbref player;
int qtype;
{
int i, aowner, aflags, alen;
char *quota_str, *p, *tokst;
quota_str = atr_get(player, qtype, &aowner, &aflags, &alen);
if (!*quota_str) {
for (i = 0; i < 5; i++)
q_list[i] = 0;
free_lbuf(quota_str);
return;
}
for (p = strtok_r(quota_str, " ", &tokst), i = 0;
p && (i < 5);
p = strtok_r(NULL, " ", &tokst), i++) {
q_list[i] = atoi(p);
}
}

free_lbuf(quota_str);

/* --------------------------------------------------------------------------* save_quota: turns a quota array into an attribute.


*/
void save_quota(q_list, player, qtype)
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\quota.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:27 PM

int q_list[];
dbref player;
int qtype;
{
char buf[MBUF_SIZE];

sprintf(buf, "%d %d %d %d %d", q_list[0], q_list[1], q_list[2],


q_list[3], q_list[4]);
atr_add_raw(player, qtype, buf);

/* --------------------------------------------------------------------------* mung_quota, show_quota, do_quota: Manage quotas.


*/
static void count_objquota(player, aq, rq, eq, tq, pq)
dbref player;
int *aq, *rq, *eq, *tq, *pq;
{
register int a, r, e, t, p, i;
a = r = e = t = p = 0;

DO_WHOLE_DB(i) {
if ((Owner(i) != player) || (Going(i) && !isRoom(i)))
continue;
switch (Typeof(i)) {
case TYPE_ROOM:
a += mudconf.room_quota;
r++;
break;
case TYPE_EXIT:
a += mudconf.exit_quota;
e++;
break;
case TYPE_THING:
a += mudconf.thing_quota;
t++;
break;
case TYPE_PLAYER:
a += mudconf.player_quota;
p++;
break;
}
}
*aq = a;
*rq = r;
*eq = e;
*tq = t;
*pq = p;

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\quota.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:27 PM

static void adjust_quota(player, qtype, value, key)


dbref player;
int qtype, value, key;
{
register int aq, rq;
int q_list[5], rq_list[5];
load_quota(q_list, player, A_QUOTA);
load_quota(rq_list, player, A_RQUOTA);
aq = q_list[qtype];
rq = rq_list[qtype];
/* Adjust values */
if (key & QUOTA_REM) {
aq += (value - rq);
rq = value;
} else {
rq += (value - aq);
aq = value;
}
/* Set both abs and relative quota */

q_list[qtype] = aq;
rq_list[qtype] = rq;
save_quota(q_list, player, A_QUOTA);
save_quota(rq_list, player, A_RQUOTA);

static void mung_quotas(player, key, value)


dbref player;
int key, value;
{
int xq, rooms, exits, things, players;
int q_list[5], rq_list[5];
if (key & QUOTA_FIX) {
/* Get value of stuff owned and good value, set other values
* from that. */
count_objquota(player, &xq, &rooms, &exits, &things, &players);
if (key & QUOTA_TOT) {
load_quota(rq_list, player, A_RQUOTA);
rq_list[QTYPE_ALL] += xq;
save_quota(rq_list, player, A_QUOTA);
} else {
load_quota(q_list, player, A_QUOTA);
q_list[QTYPE_ALL] -= xq;
q_list[QTYPE_ROOM] -= rooms;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\quota.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

Saturday, June 16, 2012 11:27 PM

q_list[QTYPE_EXIT] -= exits;
q_list[QTYPE_THING] -= things;
q_list[QTYPE_PLAYER] -= players;
save_quota(q_list, player, A_RQUOTA);

}
}
}
}
}
}

}
else if (key & QUOTA_ROOM) {
adjust_quota(player, QTYPE_ROOM, value, key);
else if (key & QUOTA_EXIT) {
adjust_quota(player, QTYPE_EXIT, value, key);
else if (key & QUOTA_THING) {
adjust_quota(player, QTYPE_THING, value, key);
else if (key & QUOTA_PLAYER) {
adjust_quota(player, QTYPE_PLAYER, value, key);
else {
adjust_quota(player, QTYPE_ALL, value, key);

static void show_quota(player, victim)


dbref player, victim;
{
int q_list[5], rq_list[5], dq_list[5], i;
load_quota(q_list, victim, A_QUOTA);
load_quota(rq_list, victim, A_RQUOTA);
for (i = 0; i < 5; i++)
dq_list[i] = q_list[i] - rq_list[i];
if (Free_Quota(victim)) {
if (mudconf.typed_quotas)
notify_quiet(player,
tprintf("%-16s: %4d - N/A %4d - N/A %4d - N/A
N/A",
Name(victim), dq_list[QTYPE_ALL],
dq_list[QTYPE_ROOM], dq_list[QTYPE_EXIT],
dq_list[QTYPE_THING], dq_list[QTYPE_PLAYER]));
else
notify_quiet(player,
tprintf("%-16s: %4d - N/A", Name(victim),
dq_list[QTYPE_ALL]));
} else {
if (mudconf.typed_quotas)
notify_quiet(player,
tprintf("%-16s: %4d - %3d %4d - %3d %4d - %3d
%3d",
Name(victim),
dq_list[QTYPE_ALL], q_list[QTYPE_ALL],
dq_list[QTYPE_ROOM], q_list[QTYPE_ROOM],
dq_list[QTYPE_EXIT], q_list[QTYPE_EXIT],
dq_list[QTYPE_THING], q_list[QTYPE_THING],
dq_list[QTYPE_PLAYER], q_list[QTYPE_PLAYER]));
else
-4-

%4d - N/A

%4d -

%4d - %3d

%4d -

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\quota.c

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262

Saturday, June 16, 2012 11:27 PM

notify_quiet(player,
tprintf("%-16s: %4d - %3d", Name(victim),
dq_list[QTYPE_ALL], q_list[QTYPE_ALL]));

static void show_quota_header(player)


dbref player;
{
if (mudconf.typed_quotas)
notify_quiet(player, "Name
Thin - Lim Play - Lim");
else
notify_quiet(player, "Name
}

: Quot - Lim

Room - Lim

: Quot - Lim" );

void do_quota(player, cause, key, arg1, arg2)


dbref player, cause;
int key;
char *arg1, *arg2;
{
dbref who;
register int set = 0, value = 0, i;
if (!(mudconf.quotas || Can_Set_Quota(player))) {
notify_quiet(player, "Quotas are not enabled.");
return;
}
if ((key & QUOTA_TOT) && (key & QUOTA_REM)) {
notify_quiet(player, "Illegal combination of switches." );
return;
}
/* Show or set all quotas if requested */
if (key & QUOTA_ALL) {
if (arg1 && *arg1) {
value = atoi(arg1);
set = 1;
if (value < 0) {
notify(player, "Illegal quota value.");
return;
}
} else if (key & (QUOTA_SET | QUOTA_FIX)) {
value = 0;
set = 1;
}
if (set) {
STARTLOG(LOG_WIZARD, "WIZ", "QUOTA")
log_name(player);
log_printf(" changed everyone's quota.");
ENDLOG
}
show_quota_header(player);
-5-

Exit - Lim

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\quota.c

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315

Saturday, June 16, 2012 11:27 PM

DO_WHOLE_DB(i) {
if (isPlayer(i)) {
if (set)
mung_quotas(i, key, value);
show_quota(player, i);
}
}
return;

}
/* Find out whose quota to show or set */

if (!arg1 || *arg1 == '\0') {


who = Owner(player);
} else {
who = lookup_player(player, arg1, 1);
if (!Good_obj(who)) {
notify_quiet(player, "Not found.");
return;
}
}
/* Make sure we have permission to do it */
if (!Can_Set_Quota(player)) {
if (arg2 && *arg2) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
if (Owner(player) != who) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
}
if (arg2 && *arg2) {
set = 1;
value = atoi(arg2);
if (value < 0) {
notify(player, "Illegal quota value.");
return;
}
} else if (key & QUOTA_FIX) {
set = 1;
value = 0;
}
if (set) {
STARTLOG(LOG_WIZARD, "WIZ", "QUOTA")
log_name(player);
log_printf(" changed the quota of ");
log_name(who);
ENDLOG
mung_quotas(who, key, value);
}
show_quota_header(player);
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\quota.c

316
317
318

Saturday, June 16, 2012 11:27 PM

show_quota(player, who);

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\recover.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:27 PM

/*
* A tool to traverse a corrupted GDBM database, look for special tags, and
* rebuild a consistent database
*/
#include
#include
#include
#include
#include
#include
#include

"autoconf.h"
"config.h"
"db.h"
<sys/types.h>
<sys/file.h>
<stdio.h>
<string.h>

#include "gdbm-1.8.0/gdbmdefs.h"
static gdbm_file_info *dbp = NULL;
static void gdbm_panic(mesg)
char *mesg;
{
fprintf(stderr, "GDBM panic: %s\n", mesg);
}
extern char *optarg;
extern int optind;
int main(argc, argv)
int argc;
char *argv[];
{
datum key, dat;
FILE *f;
int numbytes, filesize;
long filepos;
struct stat buf;
bucket_element be;
int c;
char cp;
char *infile, *outfile;
int errflg = 0;
/* Parse options */
infile = outfile = NULL;
while ((c = getopt(argc, argv, "i:o:")) != -1) {
switch (c) {
case 'i':
infile = optarg;
break;
case 'o':
outfile = optarg;
break;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\recover.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:27 PM

default:
errflg++;
}

}
if (errflg || !infile || !outfile) {
fprintf(stderr, "Usage: %s -i input_file -o output_file\n" ,
argv[0]);
exit(1);
}
/* Open files */
if ((dbp = gdbm_open(outfile, 8192, GDBM_WRCREAT, 0600,
gdbm_panic)) == NULL) {
fprintf(stderr, "Fatal error in gdbm_open (%s): %s\n" ,
outfile, strerror(errno));
exit(1);
}
if (stat(infile, &buf)) {
fprintf(stderr, "Fatal error in stat (%s): %s\n" ,
infile, strerror(errno));
exit(1);
}
filesize = buf.st_size;
f = fopen(infile, "r");
while (fread((void *)&cp, 1, 1, f) != 0) {
/* Quick and dirty */
if (cp == 'T') {
filepos = ftell(f);
/* Rewind one byte */
fseek(f, -1, SEEK_CUR);
if (fread((void *)&be, sizeof(bucket_element),
1, f) == 0) {
fprintf(stderr,
"Fatal error at file position %ld.\n" ,
filepos);
exit(1);
}
/* Check the tag to make sure it's correct, and
* make sure the pointer and sizes are sane */
if (!memcmp((void *)(be.start_tag),
(void *)"TM3S", 4) &&
be.data_pointer < filesize &&
be.key_size < filesize &&
be.data_size < filesize) {
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\recover.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:27 PM

filepos = ftell(f);
/* Seek to where the data begins */
fseek(f, be.data_pointer, SEEK_SET);
key.dptr = (char *)malloc(be.key_size);
key.dsize = be.key_size;
dat.dptr = (char *)malloc(be.data_size);
dat.dsize = be.data_size;
if ((numbytes = fread((void *)(key.dptr), 1,
key.dsize, f)) == 0) {
fprintf(stderr,
"Fatal error at file position %ld.\n" ,
filepos);
exit(1);
}
if (fread((void *)(dat.dptr), dat.dsize,
1, f) == 0) {
fprintf(stderr,
"Fatal error at file position %ld.\n" ,
filepos);
exit(1);
}
if (gdbm_store(dbp, key, dat, GDBM_REPLACE)) {
fprintf(stderr,
"Fatal error in gdbm_store (%s): %s\n" ,
outfile, strerror(errno));
exit(1);
}
free(key.dptr);
free(dat.dptr);
/* Seek back to where we left off */
fseek(f, filepos, SEEK_SET);
} else {
/* Seek back to one byte after we started
* and continue */

fseek(f, filepos, SEEK_SET);

fclose(f);
gdbm_close(dbp);
exit(0);

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:26 PM

/* rob.c - Commands dealing with giving/taking/killing things or money */


/* $Id: rob.c,v 1.17 2002/08/07 20:27:17 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "match.h" /* required by code */
#include "attrs.h" /* required by code */
#include "powers.h" /* required by code */
void do_kill(player, cause, key, what, costchar)
dbref player, cause;
int key;
char *what, *costchar;
{
dbref victim;
char *buf1, *buf2, *bp;
int cost;
init_match(player, what, TYPE_PLAYER);
match_neighbor();
match_me();
match_here();
if (Long_Fingers(player)) {
match_player();
match_absolute();
}
victim = match_result();
switch (victim) {
case NOTHING:
notify(player, "I don't see that player here." );
break;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
break;
default:
if ((Typeof(victim) != TYPE_PLAYER) &&
(Typeof(victim) != TYPE_THING)) {
notify(player,
"Sorry, you can only kill players and things." );
break;
}
if ((Haven(Location(victim)) && !Wizard(player)) ||
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:26 PM

(controls(victim, Location(victim)) &&


!controls(player, Location(victim))) ||
Unkillable(victim)) {
notify(player, "Sorry.");
break;

}
/*
* go for it
*/

cost = atoi(costchar);
if (key == KILL_KILL) {
if (cost < mudconf.killmin)
cost = mudconf.killmin;
if (cost > mudconf.killmax)
cost = mudconf.killmax;
/*
* see if it works
*/
if (!payfor(player, cost)) {
notify(player,
tprintf("You don't have enough %s.",
mudconf.many_coins));
return;
}
} else {
cost = 0;
}
if (!((mudconf.killguarantee &&
(Randomize(mudconf.killguarantee) < cost)) ||
(key == KILL_SLAY)) ||
Wizard(victim)) {
/*
* Failure: notify player and victim only
*/
notify(player, "Your murder attempt failed." );
buf1 = alloc_lbuf("do_kill.failed");
bp = buf1;
safe_tprintf_str(buf1, &bp,
"%s tried to kill you!",
Name(player));
notify_with_cause(victim, player, buf1);
if (Suspect(player)) {
StringCopy(buf1, Name(player));
if (player == Owner(player)) {
raw_broadcast(WIZARD,
"[Suspect] %s tried to kill %s(#%d)." ,
buf1, Name(victim), victim);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:26 PM

} else {
buf2 = alloc_lbuf("do_kill.SUSP.failed");
StringCopy(buf2, Name(Owner(player)));
raw_broadcast(WIZARD,
"[Suspect] %s <via %s(#%d)> tried to kill %s(#%d)." ,
buf2, buf1, player,
Name(victim), victim);
free_lbuf(buf2);
}

}
free_lbuf(buf1);
break;

}
/*
* Success!
*/

You killed him

buf1 = alloc_lbuf("do_kill.succ.1");
buf2 = alloc_lbuf("do_kill.succ.2");
if (Suspect(player)) {
StringCopy(buf1, Name(player));
if (player == Owner(player)) {
raw_broadcast(WIZARD,
"[Suspect] %s killed %s(#%d)." ,
buf1, Name(victim), victim);
} else {
StringCopy(buf2, Name(Owner(player)));
raw_broadcast(WIZARD,
"[Suspect] %s <via %s(#%d)> killed %s(#%d)." ,
buf2, buf1, player, Name(victim),
victim);
}
}
bp = buf1;
safe_tprintf_str(buf1, &bp, "You killed %s!", Name(victim));
bp = buf2;
safe_tprintf_str(buf2, &bp, "killed %s!", Name(victim));
if (Typeof(victim) != TYPE_PLAYER)
if (halt_que(NOTHING, victim) > 0)
if (!Quiet(victim))
notify(Owner(victim), "Halted.");
did_it(player, victim, A_KILL, buf1, A_OKILL, buf2, A_AKILL, 0,
(char **)NULL, 0, MSG_PRESENCE);
/*
* notify victim
*/
bp = buf1;
safe_tprintf_str(buf1, &bp, "%s killed you!", Name(player));
notify_with_cause(victim, player, buf1);
/*
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:26 PM

* Pay off the bonus


*/
if (key == KILL_KILL) {
cost /= 2; /*
* victim gets half
*/
if (Pennies(Owner(victim)) < mudconf.paylimit) {
sprintf(buf1,
"Your insurance policy pays %d %s." ,
cost, mudconf.many_coins);
notify(victim, buf1);
giveto(Owner(victim), cost);
} else {
notify(victim,
"Your insurance policy has been revoked." );
}
}
free_lbuf(buf1);
free_lbuf(buf2);
/*
* send him home
*/

move_via_generic(victim, HOME, NOTHING, 0);


divest_object(victim);
break;

/*
* --------------------------------------------------------------------------* * give_thing, give_money, do_give: Give away money or things.
*/
static void give_thing(giver, recipient, key, what)
dbref giver, recipient;
int key;
char *what;
{
dbref thing;
char *str, *sp;
init_match(giver, what, TYPE_THING);
match_possession();
match_me();
thing = match_result();
switch (thing) {
case NOTHING:
notify(giver, "You don't have that!");
return;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:26 PM

case AMBIGUOUS:
notify(giver, "I don't know which you mean!" );
return;
}
if (thing == giver) {
notify(giver, "You can't give yourself away!" );
return;
}
if (((Typeof(thing) != TYPE_THING) &&
(Typeof(thing) != TYPE_PLAYER)) ||
!(Enter_ok(recipient) || controls(giver, recipient))) {
notify(giver, NOPERM_MESSAGE);
return;
}
if (!could_doit(giver, thing, A_LGIVE)) {
sp = str = alloc_lbuf("do_give.gfail");
safe_str((char *)"You can't give ", str, &sp);
safe_name(thing, str, &sp);
safe_str((char *)" away.", str, &sp);
*sp = '\0';
did_it(giver, thing, A_GFAIL, str, A_OGFAIL, NULL,
A_AGFAIL, 0, (char **)NULL, 0, MSG_MOVE);
free_lbuf(str);
return;

}
if (!could_doit(thing, recipient, A_LRECEIVE)) {
sp = str = alloc_lbuf("do_give.rfail");
safe_name(recipient, str, &sp);
safe_str((char *)" doesn't want ", str, &sp);
safe_name(thing, str, &sp);
safe_chr('.', str, &sp);
*sp = '\0';

did_it(giver, recipient, A_RFAIL, str, A_ORFAIL, NULL,


A_ARFAIL, 0, (char **)NULL, 0, MSG_MOVE);
free_lbuf(str);
return;

}
move_via_generic(thing, recipient, giver, 0);
divest_object(thing);
if (!(key & GIVE_QUIET)) {
str = alloc_lbuf("do_give.thing.ok");
StringCopy(str, Name(giver));
notify_with_cause(recipient, giver,
tprintf("%s gave you %s.", str, Name(thing)));
notify(giver, "Given.");
notify_with_cause(thing, giver,
tprintf("%s gave you to %s.", str, Name(recipient)));
free_lbuf(str);
}
did_it(giver, thing, A_DROP, NULL, A_ODROP, NULL, A_ADROP,
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:26 PM

0, (char **)NULL, 0, MSG_MOVE);


did_it(recipient, thing, A_SUCC, NULL, A_OSUCC, NULL, A_ASUCC,
0, (char **)NULL, 0, MSG_MOVE);

static void give_money(giver, recipient, key, amount)


dbref giver, recipient;
int key;
int amount;
{
dbref aowner;
int cost, aflags, alen;
char *str;
/*
* do amount consistency check
*/
if (amount < 0 && !Steal(giver)) {
notify(giver,
tprintf("You look through your pockets. Nope, no negative %s." ,
mudconf.many_coins));
return;
}
if (!amount) {
notify(giver,
tprintf("You must specify a positive number of %s." ,
mudconf.many_coins));
return;
}
if (!Wizard(giver)) {
if ((Typeof(recipient) == TYPE_PLAYER) &&
(Pennies(recipient) + amount > mudconf.paylimit)) {
notify(giver,
tprintf("That player doesn't need that many %s!" ,
mudconf.many_coins));
return;
}
if (!could_doit(giver, recipient, A_LRECEIVE)) {
notify(giver,
tprintf("%s won't take your money.",
Name(recipient)));
return;
}
}
/*
* try to do the give
*/
if (!payfor(giver, amount)) {
notify(giver,
tprintf("You don't have that many %s to give!" ,
mudconf.many_coins));
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:26 PM

return;
}
/*
* Find out cost if an object
*/
if (Typeof(recipient) == TYPE_THING) {
str = atr_pget(recipient, A_COST, &aowner, &aflags, &alen);
cost = atoi(str);
free_lbuf(str);
/*
* Can't afford it?
*/
if (amount < cost) {
notify(giver, "Feeling poor today?");
giveto(giver, amount);
return;
}
/*
* Negative cost
*/
if (cost < 0) {
return;
}
} else {
cost = amount;
}
if (!(key & GIVE_QUIET)) {
if (amount == 1) {
notify(giver,
tprintf("You give a %s to %s.",
mudconf.one_coin, Name(recipient)));
notify_with_cause(recipient, giver,
tprintf("%s gives you a %s.", Name(giver),
mudconf.one_coin));
} else {
notify(giver,
tprintf("You give %d %s to %s.", amount,
mudconf.many_coins, Name(recipient)));
notify_with_cause(recipient, giver,
tprintf("%s gives you %d %s.", Name(giver),
amount, mudconf.many_coins));
}
}
/*
* Report change given
*/
if ((amount - cost) == 1) {
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:26 PM

notify(giver,
tprintf("You get 1 %s in change.", mudconf.one_coin));
giveto(giver, 1);
} else if (amount != cost) {
notify(giver,
tprintf("You get %d %s in change.",
(amount - cost), mudconf.many_coins));
giveto(giver, (amount - cost));
}
/*
* Transfer the money and run PAY attributes
*/

giveto(recipient, cost);
did_it(giver, recipient, A_PAY, NULL, A_OPAY, NULL, A_APAY,
0, (char **)NULL, 0, MSG_PRESENCE);
return;

void do_give(player, cause, key, who, amnt)


dbref player, cause;
int key;
char *who, *amnt;
{
dbref recipient;
/*
* check recipient
*/
init_match(player, who, TYPE_PLAYER);
match_neighbor();
match_possession();
match_me();
if (Long_Fingers(player)) {
match_player();
match_absolute();
}
recipient = match_result();
switch (recipient) {
case NOTHING:
notify(player, "Give to whom?");
return;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
return;
}
if (isExit(recipient)) {
notify(player, "You can't give anything to an exit." );
return;
}

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\rob.c

425
426
427
428
429
430
431
432
433
434
435

Saturday, June 16, 2012 11:26 PM

if (Guest(recipient)) {
notify(player, "You can't give anything to a Guest." );
return;
}
if (is_number(amnt)) {
give_money(player, recipient, key, atoi(amnt));
} else {
give_thing(player, recipient, key, amnt);
}

-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:26 PM

/* set.c - commands which set parameters */


/* $Id: set.c,v 1.50 2004/08/17 21:21:12 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"match.h"
"powers.h"
"attrs.h"
"ansi.h"

/*
/*
/*
/*

required
required
required
required

by
by
by
by

code
code
code
code

*/
*/
*/
*/

extern NAMETAB indiv_attraccess_nametab[];


dbref match_controlled(player, name)
dbref player;
const char *name;
{
dbref mat;

init_match(player, name, NOTYPE);


match_everything(MAT_EXIT_PARENTS);
mat = noisy_match_result();
if (Good_obj(mat) && !Controls(player, mat)) {
notify_quiet(player, NOPERM_MESSAGE);
return NOTHING;
} else {
return (mat);
}

dbref match_controlled_quiet(player, name)


dbref player;
const char *name;
{
dbref mat;
init_match(player, name, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
mat = match_result();
if (Good_obj(mat) && !Controls(player, mat)) {
return NOTHING;
} else {
return (mat);
}
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:26 PM

}
dbref match_affected(player, name)
dbref player;
const char *name;
{
dbref mat;
/* We allow control, as well as having the same owner. */

init_match(player, name, NOTYPE);


match_everything(MAT_EXIT_PARENTS);
mat = noisy_match_result();
if (Good_obj(mat) && (Owner(player) != Owner(mat)) &&
!Controls(player, mat)) {
notify_quiet(player, NOPERM_MESSAGE);
return NOTHING;
} else {
return (mat);
}

void do_chzone(player, cause, key, name, newobj)


dbref player, cause;
int key;
const char *name;
const char *newobj;
{
dbref thing;
dbref zone;
if (!mudconf.have_zones) {
notify(player, "Zones disabled.");
return;
}
init_match(player, name, NOTYPE);
match_everything(0);
if ((thing = noisy_match_result()) == NOTHING)
return;
if (!newobj || !*newobj || !strcasecmp(newobj, "none"))
zone = NOTHING;
else {
init_match(player, newobj, NOTYPE);
match_everything(0);
if ((zone = noisy_match_result()) == NOTHING)
return;

if ((Typeof(zone) != TYPE_THING) && (Typeof(zone) != TYPE_ROOM)) {


notify(player, "Invalid zone object type.");
return;
}

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:26 PM

if (!Wizard(player) && !(Controls(player, thing)) &&


!(check_zone_for_player(player, thing)) &&
!(db[player].owner == db[thing].owner)) {
notify(player, "You don't have the power to shift reality." );
return;
}
/* a player may change an object's zone to NOTHING or to an object he
* owns
*/
if ((zone != NOTHING) && !Wizard(player) &&
!(Controls(player, zone)) &&
!(db[player].owner == db[zone].owner)) {
notify(player, "You cannot move that object to that zone." );
return;
}
/* only rooms may be zoned to other rooms */
if ((zone != NOTHING) &&
(Typeof(zone) == TYPE_ROOM) && Typeof(thing) != TYPE_ROOM) {
notify(player, "Only rooms may have parent rooms." );
return;
}
/* everything is okay, do the change */

s_Zone(thing, zone);
if (Typeof(thing) != TYPE_PLAYER) {
/* We do not strip flags and powers on players, due to the
* inconvenience involved in resetting them. Players will just
* have to be careful when @chzone'ing players with special
* privileges.
* For all other objects, we behave like @chown does.
*/
if (key & CHZONE_NOSTRIP) {
if (!God(player))
s_Flags(thing, Flags(thing) & ~WIZARD);
} else {
s_Flags(thing, Flags(thing) & ~mudconf.stripped_flags.word1);
s_Flags2(thing, Flags2(thing) & ~mudconf.stripped_flags.word2);
s_Flags3(thing, Flags3(thing) & ~mudconf.stripped_flags.word3);
}
if (!(key & CHZONE_NOSTRIP) || !God(player)) {
s_Powers(thing, 0);
s_Powers2(thing, 0);
}
}
notify(player, "Zone changed.");
s_Modified(thing);

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:26 PM

void do_name(player, cause, key, name, newname)


dbref player, cause;
int key;
const char *name;
char *newname;
{
dbref thing;
char *buff;
if ((thing = match_controlled(player, name)) == NOTHING)
return;
/*
* check for bad name
*/
if ((*newname == '\0') || (strip_ansi_len(newname) == 0)) {
notify_quiet(player, "Give it what new name?");
return;
}
/*
* check for renaming a player
*/
if (isPlayer(thing)) {
buff = trim_spaces((char *)newname);
if (!ok_player_name(buff) ||
!badname_check(buff)) {
notify_quiet(player, "You can't use that name.");
free_lbuf(buff);
return;
} else if (string_compare(buff, Name(thing)) &&
(lookup_player(NOTHING, buff, 0) != NOTHING)) {
/*
* string_compare allows changing foo to Foo, etc.
*/
notify_quiet(player, "That name is already in use." );
free_lbuf(buff);
return;

}
/*
* everything ok, notify
*/
STARTLOG(LOG_SECURITY, "SEC", "CNAME")
log_name(thing),
log_printf(" renamed to %s", buff);
ENDLOG
if (Suspect(thing)) {
raw_broadcast(WIZARD,
"[Suspect] %s renamed to %s", Name(thing), buff);
}
delete_player_name(thing, Name(thing));
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:26 PM

s_Name(thing, buff);
add_player_name(thing, Name(thing));
if (!Quiet(player) && !Quiet(thing))
notify_quiet(player, "Name set.");
free_lbuf(buff);
s_Modified(thing);
return;
} else {
if (!ok_name(newname)) {
notify_quiet(player, "That is not a reasonable name." );
return;
}
/*
* everything ok, change the name
*/
s_Name(thing, newname);
if (!Quiet(player) && !Quiet(thing))
notify_quiet(player, "Name set.");
s_Modified(thing);
}

/*
* --------------------------------------------------------------------------* * do_alias: Make an alias for a player or object.
*/
static void set_player_aliases(player, target, oldalias, list, aflags)
dbref player, target;
char *oldalias, *list;
int aflags;
{
int i, j, n_aliases, retcode;
char *p, *tokp;
char alias_buf[LBUF_SIZE], tmp_buf[LBUF_SIZE], *alias_ptrs[LBUF_SIZE / 2];
/* Clear out the original alias, so we can rewrite a new alias
* that uses the same names, if necessary.
*/
Clear_Player_Aliases(target, oldalias);
/* Don't nibble the original buffer. Copy it all into an array, because
* we have to eat leading and trailing spaces.
*/
retcode = 1;
strcpy(tmp_buf, list);
for (n_aliases = 0, p = strtok_r(tmp_buf, ";", &tokp); p;
n_aliases++, p = strtok_r(NULL, ";", &tokp)) {
alias_ptrs[n_aliases] = trim_spaces(p);
}
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:26 PM

/* Enforce a maximum number of aliases. */


if (n_aliases > mudconf.max_player_aliases) {
notify_quiet(player,
tprintf("You cannot have more than %d aliases." ,
mudconf.max_player_aliases));
retcode = 0;
}
/* Enforce player name regulations. */
for (i = 0; retcode && (i < n_aliases); i++) {
if (lookup_player(NOTHING, alias_ptrs[i], 0) != NOTHING) {
notify_quiet(player,
tprintf("The name '%s' is already in use." ,
alias_ptrs[i]));
retcode = 0;
} else if (!(badname_check(alias_ptrs[i]) &&
ok_player_name(alias_ptrs[i]))) {
notify_quiet(player,
tprintf("You cannot use '%s' as an alias." ,
alias_ptrs[i]));
retcode = 0;
} else {
/* Make sure this alias doesn't duplicate another in the list. */

}
}

for (j = i + 1; retcode && (j < n_aliases); j++) {


if (!strcasecmp(alias_ptrs[i], alias_ptrs[j])) {
notify_quiet(player,
tprintf("You have duplicated '%s' in your alias list." ,
alias_ptrs[i]));
retcode = 0;
}
}

/* Construct a new alias list, with spaces removed. */


for (i = 0, p = alias_buf; retcode && (i < n_aliases); i++) {
if (add_player_name(target, alias_ptrs[i])) {
if (p != alias_buf) {
safe_chr(';', alias_buf, &p);
}
safe_str(alias_ptrs[i], alias_buf, &p);
} else {
retcode = 0;
notify_quiet(player,
tprintf("The alias '%s' is already in use or is illegal." ,
alias_ptrs[i]));
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:26 PM

/* Ugh. Now we have to delete aliases we added up 'til now. */

}
}

for (j = 0; j < i; j++)


delete_player_name(target, alias_ptrs[j]);

/* Free memory allocated by trim_spaces(). */


for (i = 0; i < n_aliases; i++) {
free_lbuf(alias_ptrs[i]);
}
/* Twiddle the alias attribute on the object. Note that we have to
* do this regardless of the outcome, since we wiped out the original
* aliases from the player name table earlier.
*/

if (retcode) {
atr_add(target, A_ALIAS, alias_buf, Owner(player), aflags);
if (!Quiet(player)) {
notify_quiet(player, "Alias set.");
}
} else {
atr_clr(target, A_ALIAS);
notify_quiet(player, "Alias cleared due to error." );
}

void do_alias(player, cause, key, name, alias)


dbref player, cause;
int key;
char *name, *alias;
{
dbref thing, aowner;
int aflags, alen;
ATTR *ap;
char *oldalias, *trimalias;
if ((thing = match_controlled(player, name)) == NOTHING)
return;
/*
* check for renaming a player
*/
ap = atr_num(A_ALIAS);
if (isPlayer(thing)) {
/*
* Fetch the old alias
*/
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:26 PM

oldalias = atr_get(thing, A_ALIAS, &aowner, &aflags, &alen);


trimalias = trim_spaces(alias);
if (!Controls(player, thing)) {
/*
* Make sure we have rights to do it. We can't do
* the normal Set_attr check because ALIAS is
* set CONSTANT and we want to keep people from
* doing &ALIAS and bypassing the player name checks.
*/
notify_quiet(player, NOPERM_MESSAGE);
} else if (!*trimalias) {
/*
* New alias is null, just clear it
*/
Clear_Player_Aliases(thing, oldalias);
atr_clr(thing, A_ALIAS);
if (!Quiet(player))
notify_quiet(player, "Alias removed.");
} else {
/*
* Remove the old name and add the new name
*/
set_player_aliases(player, thing, oldalias,
trimalias, aflags);

}
free_lbuf(trimalias);
free_lbuf(oldalias);
} else {
atr_pget_info(thing, A_ALIAS, &aowner, &aflags);
/*
* Make sure we have rights to do it
*/

if (!Set_attr(player, thing, ap, aflags)) {


notify_quiet(player, NOPERM_MESSAGE);
} else {
atr_add(thing, A_ALIAS, alias, Owner(player), aflags);
if (!Quiet(player))
notify_quiet(player, "Set.");
}

/*
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:26 PM

* --------------------------------------------------------------------------* * do_lock: Set a lock on an object or attribute.


*/
void do_lock(player, cause, key, name, keytext)
dbref player, cause;
int key;
char *name, *keytext;
{
dbref thing, aowner;
int atr, aflags;
ATTR *ap;
struct boolexp *okey;
if (parse_attrib(player, name, &thing, &atr, 0)) {
if (atr != NOTHING) {
if (!atr_get_info(thing, atr, &aowner, &aflags)) {
notify_quiet(player,
"Attribute not present on object." );
return;
}
ap = atr_num(atr);

if (ap && Lock_attr(player, thing, ap, aowner)) {


aflags |= AF_LOCK;
atr_set_flags(thing, atr, aflags);
if (!Quiet(player) && !Quiet(thing))
notify_quiet(player,
"Attribute locked.");
} else {
notify_quiet(player, NOPERM_MESSAGE);
}
return;

}
init_match(player, name, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
thing = match_result();
switch (thing) {
case NOTHING:
notify_quiet(player,
"I don't see what you want to lock!" );
return;
case AMBIGUOUS:
notify_quiet(player,
"I don't know which one you want to lock!" );
return;
default:
if (!controls(player, thing)) {
notify_quiet(player, "You can't lock that!");
return;
}
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:26 PM

}
okey = parse_boolexp(player, keytext, 0);
if (okey == TRUE_BOOLEXP) {
notify_quiet(player, "I don't understand that key." );
} else {
/*
* everything ok, do it
*/
if (!key)
key = A_LOCK;
atr_add_raw(thing, key, unparse_boolexp_quiet(player, okey));
if (key == A_LDARK)
s_Has_Darklock(thing);
if (!Quiet(player) && !Quiet(thing))
notify_quiet(player, "Locked.");

}
free_boolexp(okey);

/*
* --------------------------------------------------------------------------* * Remove a lock from an object of attribute.
*/
void do_unlock(player, cause, key, name)
dbref player, cause;
int key;
char *name;
{
dbref thing, aowner;
int atr, aflags;
ATTR *ap;
if (parse_attrib(player, name, &thing, &atr, 0)) {
if (atr != NOTHING) {
if (!atr_get_info(thing, atr, &aowner, &aflags)) {
notify_quiet(player,
"Attribute not present on object." );
return;
}
ap = atr_num(atr);
if (ap && Lock_attr(player, thing, ap, aowner)) {
aflags &= ~AF_LOCK;
atr_set_flags(thing, atr, aflags);
if (Owner(player != Owner(thing)))
if (!Quiet(player) && !Quiet(thing))
notify_quiet(player,
"Attribute unlocked.");
} else {
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:26 PM

notify_quiet(player, NOPERM_MESSAGE);
}
return;

}
}
if (!key)
key = A_LOCK;
if ((thing = match_controlled(player, name)) != NOTHING) {
atr_clr(thing, key);
if (key == A_LDARK)
c_Has_Darklock(thing);
if (!Quiet(player) && !Quiet(thing))
notify_quiet(player, "Unlocked.");
}

/*
* --------------------------------------------------------------------------* * do_unlink: Unlink an exit from its destination or remove a dropto.
*/
void do_unlink(player, cause, key, name)
dbref player, cause;
int key;
char *name;
{
dbref exit;
init_match(player, name, TYPE_EXIT);
match_everything(0);
exit = match_result();
switch (exit) {
case NOTHING:
notify_quiet(player, "Unlink what?");
break;
case AMBIGUOUS:
notify_quiet(player, AMBIGUOUS_MESSAGE);
break;
default:
if (!controls(player, exit)) {
notify_quiet(player, NOPERM_MESSAGE);
} else {
switch (Typeof(exit)) {
case TYPE_EXIT:
s_Location(exit, NOTHING);
if (!Quiet(player))
notify_quiet(player, "Unlinked.");
break;
case TYPE_ROOM:
s_Dropto(exit, NOTHING);
if (!Quiet(player))
notify_quiet(player,
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:26 PM

"Dropto removed.");
break;
default:
notify_quiet(player, "You can't unlink that!");
break;
}

/* --------------------------------------------------------------------------* do_chown: Change ownership of an object or attribute.


*/
void do_chown(player, cause, key, name, newown)
dbref player, cause;
int key;
char *name, *newown;
{
dbref thing, owner, aowner;
int atr, aflags, do_it, cost, quota;
ATTR *ap;
if (parse_attrib(player, name, &thing, &atr, 1)) {
if (atr != NOTHING) {
if (!*newown) {
owner = Owner(thing);
} else if (!(string_compare(newown, "me"))) {
owner = Owner(player);
} else {
owner = lookup_player(player, newown, 1);
}
/*
* You may chown an attr to yourself if you
* own the object and the attr is not locked.
* You may chown an attr to the owner of the
* object if you own the attribute. To do
* anything else you must be a wizard. Only
* #1 can chown attributes on #1.
*/
if (!atr_get_info(thing, atr, &aowner, &aflags)) {
notify_quiet(player,
"Attribute not present on object." );
return;
}
do_it = 0;
if (owner == NOTHING) {
notify_quiet(player,
"I couldn't find that player." );
} else if (God(thing) && !God(player)) {
notify_quiet(player, NOPERM_MESSAGE);
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:26 PM

} else if (Wizard(player)) {
do_it = 1;
} else if (owner == Owner(player)) {
/*
* chown to me: only if I own the obj
* and !locked
*/
if (!Controls(player, thing) ||
(aflags & AF_LOCK)) {
notify_quiet(player,
NOPERM_MESSAGE);
} else {
do_it = 1;
}
} else if (owner == Owner(thing)) {
/*
* chown to obj owner: only if I own attr
* and !locked
*/
if ((Owner(player) != aowner) ||
(aflags & AF_LOCK)) {
notify_quiet(player,
NOPERM_MESSAGE);
} else {
do_it = 1;
}
} else {
notify_quiet(player, NOPERM_MESSAGE);
}
if (!do_it)
return;
ap = atr_num(atr);
if (!ap || !Set_attr(player, player, ap, aflags)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
atr_set_owner(thing, atr, owner);
if (!Quiet(player))
notify_quiet(player,
"Attribute owner changed.");
s_Modified(thing);
return;

}
}
init_match(player, name, TYPE_THING);
match_possession();
match_here();

-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:26 PM

match_exit();
match_me();
if (Chown_Any(player)) {
match_player();
match_absolute();
}
switch (thing = match_result()) {
case NOTHING:
notify_quiet(player, "You don't have that!");
return;
case AMBIGUOUS:
notify_quiet(player, "I don't know which you mean!" );
return;
}
if (!*newown || !(string_compare(newown, "me"))) {
owner = Owner(player);
} else {
owner = lookup_player(player, newown, 1);
}
cost = 1;
quota = 1;
switch (Typeof(thing)) {
case TYPE_ROOM:
cost = mudconf.digcost;
quota = mudconf.room_quota;
break;
case TYPE_THING:
cost = OBJECT_DEPOSIT(Pennies(thing));
quota = mudconf.thing_quota;
break;
case TYPE_EXIT:
cost = mudconf.opencost;
quota = mudconf.exit_quota;
break;
case TYPE_PLAYER:
cost = mudconf.robotcost;
quota = mudconf.player_quota;
}
if (owner == NOTHING) {
notify_quiet(player, "I couldn't find that player." );
} else if (isPlayer(thing) && !God(player)) {
notify_quiet(player, "Players always own themselves." );
} else if (((!controls(player, thing) && !Chown_Any(player) &&
!(Chown_ok(thing) &&
could_doit(player, thing, A_LCHOWN))) ||
(isThing(thing) && (Location(thing) != player) &&
!Chown_Any(player))) ||
(!controls(player, owner) && !Chown_Any(player)) ||
God(thing)) {
notify_quiet(player, NOPERM_MESSAGE);
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:26 PM

} else if (canpayfees(player, owner, cost, quota, Typeof(thing))) {


payfees(owner, cost, quota, Typeof(thing));
payfees(Owner(thing), -cost, -quota, Typeof(thing));
if (God(player)) {
s_Owner(thing, owner);
} else {
s_Owner(thing, Owner(owner));
}
atr_chown(thing);
/* If we're not stripping flags, and we're God, don't strip the
* WIZARD flag. Otherwise, do that, at least.
*/
if (key & CHOWN_NOSTRIP) {
if (God(player)) {
s_Flags(thing, (Flags(thing) & ~CHOWN_OK) | HALT);
} else {
s_Flags(thing,
(Flags(thing) & ~(CHOWN_OK | WIZARD)) | HALT);
}
} else {
s_Flags(thing,
(Flags(thing) &
~(CHOWN_OK | mudconf.stripped_flags.word1)) | HALT);
s_Flags2(thing,
(Flags2(thing) & ~(mudconf.stripped_flags.word2)));
s_Flags3(thing,
(Flags3(thing) & ~(mudconf.stripped_flags.word3)));
}
/* Powers are only preserved by God with nostrip */
if (!(key & CHOWN_NOSTRIP) || !God(player)) {
s_Powers(thing, 0);
s_Powers2(thing, 0);
}

halt_que(NOTHING, thing);
if (!Quiet(player))
notify_quiet(player, "Owner changed.");
s_Modified(thing);

/*
* --------------------------------------------------------------------------* * do_set: Set flags or attributes on objects, or flags on attributes.
*/
void set_attr_internal(player, thing, attrnum, attrtext, key, buff, bufc)
dbref player, thing;
int attrnum, key;
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:26 PM

char *attrtext, *buff, **bufc;


{
dbref aowner;
int aflags, could_hear;
ATTR *attr;

attr = atr_num(attrnum);
atr_pget_info(thing, attrnum, &aowner, &aflags);
if (attr && Set_attr(player, thing, attr, aflags)) {
if ((attr->check != NULL) &&
(!(*attr->check) (0, player, thing, attrnum, attrtext))) {
if (buff) {
safe_noperm(buff, bufc);
}
return;
}
could_hear = Hearer(thing);
atr_add(thing, attrnum, attrtext, Owner(player),
aflags & ~AF_STRUCTURE);
handle_ears(thing, could_hear, Hearer(thing));
if (!(key & SET_QUIET) && !Quiet(player) && !Quiet(thing))
notify_quiet(player, "Set.");
} else {
if (buff) {
safe_noperm(buff, bufc);
} else {
notify_quiet(player, NOPERM_MESSAGE);
}
}

void do_set(player, cause, key, name, flag)


dbref player, cause;
int key;
char *name, *flag;
{
dbref thing, thing2, aowner;
char *p, *buff;
int atr, atr2, aflags, alen, clear, flagvalue, could_hear;
ATTR *attr, *attr2;
/*
* See if we have the <obj>/<attr> form, which is how you set * * *
* attribute * flags.
*/
if (parse_attrib(player, name, &thing, &atr, 1)) {
if (atr != NOTHING) {
/*
* You must specify a flag name
*/

-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:26 PM

if (!flag || !*flag) {
notify_quiet(player,
"I don't know what you want to set!" );
return;
}
/*
* Check for clearing
*/
clear = 0;
if (*flag == NOT_TOKEN) {
flag++;
clear = 1;
}
/*
* Make sure player specified a valid attribute flag
*/
flagvalue = search_nametab(player,
indiv_attraccess_nametab, flag);
if (flagvalue < 0) {
notify_quiet(player, "You can't set that!");
return;
}
/*
* Make sure the object has the attribute present
*/
if (!atr_get_info(thing, atr, &aowner, &aflags)) {
notify_quiet(player,
"Attribute not present on object." );
return;
}
/*
* Make sure we can write to the attribute
*/
attr = atr_num(atr);
if (!attr || !Set_attr(player, thing, attr, aflags)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
/*
* Go do it
*/
if (clear)
aflags &= ~flagvalue;
else
aflags |= flagvalue;
could_hear = Hearer(thing);
atr_set_flags(thing, atr, aflags);

-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

Saturday, June 16, 2012 11:26 PM

/*
* Tell the player about it.
*/
handle_ears(thing, could_hear, Hearer(thing));
if (!(key & SET_QUIET) &&
!Quiet(player) && !Quiet(thing)) {
if (clear)
notify_quiet(player, "Cleared.");
else
notify_quiet(player, "Set.");
}
return;

}
}
/*
* find thing
*/

if ((thing = match_controlled(player, name)) == NOTHING)


return;
/*
* check for attribute set first
*/
for (p = flag; *p && (*p != ':'); p++) ;
if (*p) {
*p++ = 0;
atr = mkattr(flag);
if (atr <= 0) {
notify_quiet(player, "Couldn't create attribute.");
return;
}
attr = atr_num(atr);
if (!attr) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
atr_get_info(thing, atr, &aowner, &aflags);
if (!Set_attr(player, thing, attr, aflags)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
buff = alloc_lbuf("do_set");
/*
* check for _
*/
if (*p == '_') {
StringCopy(buff, p + 1);
if (!parse_attrib(player, p + 1, &thing2, &atr2, 0) ||
(atr2 == NOTHING)) {
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007

Saturday, June 16, 2012 11:26 PM

notify_quiet(player, "No match.");


free_lbuf(buff);
return;

}
attr2 = atr_num(atr2);
p = buff;
atr_pget_str(buff, thing2, atr2, &aowner, &aflags, &alen);
if (!attr2 ||
!See_attr(player, thing2, attr2, aowner, aflags)) {
notify_quiet(player, NOPERM_MESSAGE);
free_lbuf(buff);
return;
}

}
/*
* Go set it
*/

set_attr_internal(player, thing, atr, p, key, NULL, NULL);


free_lbuf(buff);
return;

}
/*
* Set or clear a flag
*/
}

flag_set(thing, player, flag, key);

void do_power(player, cause, key, name, flag)


dbref player, cause;
int key;
char *name, *flag;
{
dbref thing;
if (!flag || !*flag) {
notify_quiet(player,
"I don't know what you want to set!" );
return;
}
/*
* find thing
*/
if ((thing = match_controlled(player, name)) == NOTHING)
return;
}

power_set(thing, player, flag, key);

void do_setattr(player, cause, attrnum, name, attrtext)


-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

Saturday, June 16, 2012 11:26 PM

dbref player, cause;


int attrnum;
char *name, *attrtext;
{
dbref thing;
init_match(player, name, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
thing = noisy_match_result();

if (thing == NOTHING)
return;
set_attr_internal(player, thing, attrnum, attrtext, 0, NULL, NULL);

void do_cpattr(player, cause, key, oldpair, newpair, nargs)


dbref player, cause;
int key, nargs;
char *oldpair;
char *newpair[];
{
int i, ca, got = 0;
dbref oldthing;
char **newthings, **newattrs, *tp;
ATTR *oldattr;
if (!*oldpair || !**newpair || !oldpair || !*newpair)
return;
if (nargs < 1)
return;
/* newpair gets whacked to bits by parse_to(). Do it just once. */
newthings = (char **) XCALLOC(nargs, sizeof(char *), "do_cpattr.dbrefs");
newattrs = (char **) XCALLOC(nargs, sizeof(char *), "do_cpattr.attrs");
for (i = 0; i < nargs; i++) {
tp = newpair[i];
newthings[i] = parse_to(&tp, '/', 1);
newattrs[i] = tp;
}
olist_push();
if (parse_attrib_wild(player,
((strchr(oldpair, '/') == NULL) ?
tprintf("me/%s", oldpair) : oldpair),
&oldthing, 0, 0, 1, 0)) {
for (ca = olist_first(); ca != NOTHING; ca = olist_next()) {
oldattr = atr_num(ca);
if (oldattr) {
got = 1;
for (i = 0; i < nargs; i++) {
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113

}
}

Saturday, June 16, 2012 11:26 PM

do_set(player, cause, 0, newthings[i],


tprintf("%s:_#%d/%s",
(newattrs[i] ? newattrs[i] : oldattr->name),
oldthing, oldattr->name));

}
}
if (!got) {
notify_quiet(player, "No matching attributes found." );
}
olist_pop();
XFREE(newthings, "do_cpattr.dbrefs");
XFREE(newattrs, "do_cpattr.attrs");

void do_mvattr(player, cause, key, what, args, nargs)


dbref player, cause;
int key, nargs;
char *what, *args[];
{
dbref thing, aowner, axowner;
ATTR *in_attr, *out_attr;
int i, anum, in_anum, aflags, alen, axflags, no_delete, num_copied;
char *astr;
/*
* Make sure we have something to do.
*/
if (nargs < 2) {
notify_quiet(player, "Nothing to do.");
return;
}
/*
* Find and make sure we control the target object.
*/
thing = match_controlled(player, what);
if (thing == NOTHING)
return;
/*
* Look up the source attribute. If it either doesn't exist or isn't
* * * * * readable, use an empty string.
*/
in_anum = -1;
astr = alloc_lbuf("do_mvattr");
in_attr = atr_str(args[0]);
if (in_attr == NULL) {
*astr = '\0';
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

Saturday, June 16, 2012 11:26 PM

} else {
atr_get_str(astr, thing, in_attr->number, &aowner, &aflags, &alen);
if (!See_attr(player, thing, in_attr, aowner, aflags)) {
*astr = '\0';
} else {
in_anum = in_attr->number;
}
}
/*
* Copy the attribute to each target in turn.
*/
no_delete = 0;
num_copied = 0;
for (i = 1; i < nargs; i++) {
anum = mkattr(args[i]);
if (anum <= 0) {
notify_quiet(player,
tprintf("%s: That's not a good name for an attribute." ,
args[i]));
continue;
}
out_attr = atr_num(anum);
if (!out_attr) {
notify_quiet(player,
tprintf("%s: Permission denied.", args[i]));
} else if (out_attr->number == in_anum) {
no_delete = 1;
} else {
atr_get_info(thing, out_attr->number, &axowner,
&axflags);
if (!Set_attr(player, thing, out_attr, axflags)) {
notify_quiet(player,
tprintf("%s: Permission denied.",
args[i]));
} else {
atr_add(thing, out_attr->number, astr,
Owner(player), aflags);
num_copied++;
if (!Quiet(player))
notify_quiet(player,
tprintf("%s: Set.",
out_attr->name));
}
}
}
/*
* Remove the source attribute if we can.
*/
if (num_copied < 1) {
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218

Saturday, June 16, 2012 11:26 PM

if (in_attr) {
notify_quiet(player,
tprintf("%s: Not copied anywhere. Not cleared." ,
in_attr->name));
} else {
notify_quiet(player, "Not copied anywhere. Non-existent attribute." );
}
} else if ((in_anum > 0) && !no_delete) {
in_attr = atr_num(in_anum);
if (in_attr && Set_attr(player, thing, in_attr, aflags)) {
atr_clr(thing, in_attr->number);
if (!Quiet(player))
notify_quiet(player,
tprintf("%s: Cleared.",
in_attr->name));
} else {
if (in_attr) {
notify_quiet(player,
tprintf("%s: Could not remove old attribute. Permission denied." ,
in_attr->name));
} else {
notify_quiet(player, "Could not remove old attribute. Non-existent
attribute.");
}
}
}
free_lbuf(astr);

/*
* --------------------------------------------------------------------------* * parse_attrib, parse_attrib_wild: parse <obj>/<attr> tokens.
*/
int parse_attrib(player, str, thing, atr, ok_structs)
dbref player, *thing;
int *atr;
char *str;
int ok_structs;
{
ATTR *attr;
char *buff;
dbref aowner;
int aflags;
if (!str)
return 0;
/*
* Break apart string into obj and attr.
*/
buff = alloc_lbuf("parse_attrib");
-23-

Return on failure

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271

Saturday, June 16, 2012 11:26 PM

StringCopy(buff, str);
if (!parse_thing_slash(player, buff, &str, thing)) {
free_lbuf(buff);
return 0;
}
/*
* Get the named attribute from the object if we can
*/

attr = atr_str(str);
free_lbuf(buff);
if (!attr) {
*atr = NOTHING;
return NOTHING;
} else {
atr_pget_info(*thing, attr->number, &aowner, &aflags);
if (!See_attr_all(player, *thing, attr, aowner, aflags,
ok_structs)) {
*atr = NOTHING;
} else {
*atr = attr->number;
}
}
return 1;

static void find_wild_attrs(player, thing, str, check_exclude, hash_insert,


get_locks, ok_structs)
dbref player, thing;
char *str;
int check_exclude, hash_insert, get_locks, ok_structs;
{
ATTR *attr;
char *as;
dbref aowner;
int ca, ok, aflags;
/*
* Walk the attribute list of the object
*/
atr_push();
for (ca = atr_head(thing, &as); ca; ca = atr_next(&as)) {
attr = atr_num(ca);
/*
* Discard bad attributes and ones we've seen before.
*/
if (!attr)
continue;
if (check_exclude &&
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324

Saturday, June 16, 2012 11:26 PM

((attr->flags & AF_PRIVATE) ||


nhashfind(ca, &mudstate.parent_htab)))
continue;
/*
* If we aren't the top level remember this attr so we * * *
* exclude * it in any parents.
*/
atr_get_info(thing, ca, &aowner, &aflags);
if (check_exclude && (aflags & AF_PRIVATE))
continue;
if (get_locks)
ok = Read_attr_all(player, thing, attr, aowner,
aflags, ok_structs);
else
ok = See_attr_all(player, thing, attr, aowner,
aflags, ok_structs);
/*
* Enforce locality restriction on descriptions
*/
if (ok && (attr->number == A_DESC) && !mudconf.read_rem_desc &&
!Examinable(player, thing) && !nearby(player, thing))
ok = 0;
if (ok && quick_wild(str, (char *)attr->name)) {
olist_add(ca);
if (hash_insert) {
nhashadd(ca, (int *)attr,
&mudstate.parent_htab);
}
}

}
atr_pop();

int parse_attrib_wild(player, str, thing, check_parents, get_locks, df_star,


ok_structs)
dbref player, *thing;
char *str;
int check_parents, get_locks, df_star, ok_structs;
{
char *buff;
dbref parent;
int check_exclude, hash_insert, lev;
if (!str)
return 0;
buff = alloc_lbuf("parse_attrib_wild");
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377

Saturday, June 16, 2012 11:26 PM

StringCopy(buff, str);
/*
* Separate name and attr portions at the first /
*/
if (!parse_thing_slash(player, buff, &str, thing)) {
/*
* Not in obj/attr format, return if not defaulting to *
*/
if (!df_star) {
free_lbuf(buff);
return 0;
}
/*
* Look for the object, return failure if not found
*/
init_match(player, buff, NOTYPE);
match_everything(MAT_EXIT_PARENTS);
*thing = match_result();
if (!Good_obj(*thing)) {
free_lbuf(buff);
return 0;
}
str = (char *)"*";

}
/*
* Check the object (and optionally all parents) for attributes
*/

if (check_parents) {
check_exclude = 0;
hash_insert = check_parents;
nhashflush(&mudstate.parent_htab, 0);
ITER_PARENTS(*thing, parent, lev) {
if (!Good_obj(Parent(parent)))
hash_insert = 0;
find_wild_attrs(player, parent, str, check_exclude,
hash_insert, get_locks, ok_structs);
check_exclude = 1;
}
} else {
find_wild_attrs(player, *thing, str, 0, 0, get_locks,
ok_structs);
}
free_lbuf(buff);
return 1;

-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430

Saturday, June 16, 2012 11:26 PM

/*
* --------------------------------------------------------------------------* edit_string_ansi, do_edit: Modify attributes.
*/
void edit_string_ansi(src, dst, returnstr, from, to)
char *src, **dst, **returnstr, *from, *to;
{
edit_string(src, dst, from, to);

if (mudconf.ansi_colors) {
edit_string(src, returnstr, from,
tprintf("%s%s%s%s", ANSI_HILITE, to, ANSI_NORMAL,
ANSI_NORMAL));
} else {
*returnstr = alloc_lbuf("edit_string_ansi");
StringCopy(*returnstr, *dst);
}

void do_edit(player, cause, key, it, args, nargs)


dbref player, cause;
int key, nargs;
char *it, *args[];
{
dbref thing, aowner;
int attr, got_one, aflags, alen, doit;
int could_hear;
char *from, *to, *result, *returnstr, *atext;
ATTR *ap;
/*
* Make sure we have something to do.
*/
if ((nargs < 1) || !*args[0]) {
notify_quiet(player, "Nothing to do.");
return;
}
from = args[0];
to = (nargs >= 2) ? args[1] : (char *)"";
/*
* Look for the object and get the attribute (possibly wildcarded)
*/
olist_push();
if (!it || !*it ||
!parse_attrib_wild(player, it, &thing, 0, 0, 0, 0)) {
notify_quiet(player, "No match.");
olist_pop();
return;
-27-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483

Saturday, June 16, 2012 11:26 PM

}
/*
* Iterate through matching attributes, performing edit
*/
got_one = 0;
atext = alloc_lbuf("do_edit.atext");
could_hear = Hearer(thing);
for (attr = olist_first(); attr != NOTHING; attr = olist_next()) {
ap = atr_num(attr);
if (ap) {
/*
* Get the attr and make sure we can modify it.
*/
atr_get_str(atext, thing, ap->number,
&aowner, &aflags, &alen);
if (Set_attr(player, thing, ap, aflags)) {
/*
* Do the edit and save the result
*/
got_one = 1;
edit_string_ansi(atext, &result, &returnstr, from, to);
if (ap->check != NULL) {
doit = (*ap->check) (0, player, thing,
ap->number, result);
} else {
doit = 1;
}
if (doit) {
atr_add(thing, ap->number, result,
Owner(player), aflags);
if (!Quiet(player))
notify_quiet(player,
tprintf("Set - %s: %s",
ap->name,
returnstr));
}
free_lbuf(result);
free_lbuf(returnstr);
} else {
/*
* No rights to change the attr
*/
notify_quiet(player,
tprintf("%s: Permission denied.",
ap->name));
-28-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536

Saturday, June 16, 2012 11:26 PM

}
}

/*
* Clean up
*/
free_lbuf(atext);
olist_pop();

if (!got_one) {
notify_quiet(player, "No matching attributes.");
} else {
handle_ears(thing, could_hear, Hearer(thing));
}

void do_wipe(player, cause, key, it)


dbref player, cause;
int key;
char *it;
{
dbref thing, aowner;
int attr, got_one, aflags, alen;
int could_hear;
ATTR *ap;
char *atext;
olist_push();
if (!it || !*it ||
!parse_attrib_wild(player, it, &thing, 0, 0, 1, 1)) {
notify_quiet(player, "No match.");
olist_pop();
return;
}
/*
* Iterate through matching attributes, zapping the writable ones
*/
got_one = 0;
atext = alloc_lbuf("do_wipe.atext");
could_hear = Hearer(thing);
for (attr = olist_first(); attr != NOTHING; attr = olist_next()) {
ap = atr_num(attr);
if (ap) {
/*
* Get the attr and make sure we can modify it.
*/

-29-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589

Saturday, June 16, 2012 11:26 PM

atr_get_str(atext, thing, ap->number,


&aowner, &aflags, &alen);
if (Set_attr(player, thing, ap, aflags)) {
atr_clr(thing, ap->number);
got_one = 1;
}

}
/*
* Clean up
*/
free_lbuf(atext);
olist_pop();

if (!got_one) {
notify_quiet(player, "No matching attributes.");
} else {
handle_ears(thing, could_hear, Hearer(thing));
if (!Quiet(player))
notify_quiet(player, "Wiped.");
}

void do_trigger(player, cause, key, object, argv, nargs)


dbref player, cause;
int key, nargs;
char *object, *argv[];
{
dbref thing;
int attrib;
if (!((parse_attrib(player, object, &thing, &attrib, 0)
&& (attrib != NOTHING)) ||
(parse_attrib(player, tprintf("me/%s", object),
&thing, &attrib, 0)
&& (attrib != NOTHING)))) {
notify_quiet(player, "No match.");
return;
}
if (!controls(player, thing)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
did_it(player, thing, A_NULL, NULL, A_NULL, NULL,
attrib, key & TRIG_NOW, argv, nargs, 0);
/*
* XXX be more descriptive as to what was triggered?
*/
if (!(key & TRIG_QUIET) && !Quiet(player))
notify_quiet(player, "Triggered.");

-30-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

Saturday, June 16, 2012 11:26 PM

}
void do_use(player, cause, key, object)
dbref player, cause;
int key;
char *object;
{
char *df_use, *df_ouse, *temp, *bp;
dbref thing, aowner;
int aflags, alen, doit;
init_match(player, object, NOTYPE);
match_neighbor();
match_possession();
if (Wizard(player)) {
match_absolute();
match_player();
}
match_me();
match_here();
thing = noisy_match_result();
if (thing == NOTHING)
return;
/*
* Make sure player can use it
*/
if (!could_doit(player, thing, A_LUSE)) {
did_it(player, thing, A_UFAIL,
"You can't figure out how to use that." ,
A_OUFAIL, NULL, A_AUFAIL, 0, (char **)NULL, 0,
MSG_PRESENCE);
return;
}
temp = alloc_lbuf("do_use");
doit = 0;
if (*atr_pget_str(temp, thing, A_USE, &aowner, &aflags, &alen))
doit = 1;
else if (*atr_pget_str(temp, thing, A_OUSE, &aowner, &aflags, &alen))
doit = 1;
else if (*atr_pget_str(temp, thing, A_AUSE, &aowner, &aflags, &alen))
doit = 1;
free_lbuf(temp);
if (doit) {
df_use = alloc_lbuf("do_use.use");
df_ouse = alloc_lbuf("do_use.ouse");
bp = df_use;
safe_tprintf_str(df_use, &bp, "You use %s", Name(thing));
bp = df_ouse;
safe_tprintf_str(df_ouse, &bp, "uses %s", Name(thing));
did_it(player, thing, A_USE, df_use, A_OUSE, df_ouse, A_AUSE,
-31-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\set.c

1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685

Saturday, June 16, 2012 11:26 PM

1, (char **)NULL, 0, MSG_PRESENCE);


free_lbuf(df_use);
free_lbuf(df_ouse);
} else {
notify_quiet(player, "You can't figure out how to use that." );
}

/*
* --------------------------------------------------------------------------* * do_setvattr: Set a user-named (or possibly a predefined) attribute.
*/
void do_setvattr(player, cause, key, arg1, arg2)
dbref player, cause;
int key;
char *arg1, *arg2;
{
char *s;
int anum;
arg1++;

/*
* skip the '&'
*/
for (s = arg1; *s && !isspace(*s); s++) ;
/*
* take to the space
*/
if (*s)
*s++ = '\0';
/*
* split it
*/

anum = mkattr(arg1);
/*
* Get or make attribute
*/
if (anum <= 0) {
notify_quiet(player,
"That's not a good name for an attribute." );
return;
}
do_setattr(player, cause, anum, s, arg2);

-32-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\slave.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:25 PM

/* slave.c - does iptoname conversions, and identquery lookups */


/* $Id: slave.c,v 1.18 2003/08/13 23:57:31 rmg Exp $ */
/*
* The philosophy is to keep this program as simple/small as possible.
* It does normal fork()s, so the smaller it is, the faster it goes.
*/
#include "autoconf.h"
#include
#include
#include
#include
#include
#include

<netdb.h>
<netinet/in.h>
<sys/ioctl.h>
<signal.h>
"slave.h"
<arpa/inet.h>

/* Some systems are lame, and inet_addr() returns -1 on failure, despite


* the fact that it returns an unsigned long.
*/
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
#define MAX_STRING 1000
#define MAX_CHILDREN 20
pid_t parent_pid;
volatile pid_t child_pids[MAX_CHILDREN];
char *arg_for_errors;
char *format_inet_addr(dest, addr)
char *dest;
unsigned long addr;
{
sprintf(dest, "%lu.%lu.%lu.%lu",
(addr & 0xFF000000) >> 24,
(addr & 0x00FF0000) >> 16,
(addr & 0x0000FF00) >> 8,
(addr & 0x000000FF));
return (dest + strlen(dest));
}
/*
* copy a string, returning pointer to the null terminator of dest
*/
char *stpcpy(dest, src)
char *dest;
const char *src;
{
while ((*dest = *src)) {
++dest;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\slave.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:25 PM

++src;
}
return (dest);

void child_timeout_signal(sig)
int sig;
{
exit(1);
}
int query(ip, orig_arg)
char *ip;
char *orig_arg;
{
char *comma;
char *port_pair;
struct hostent *hp;
struct sockaddr_in sin;
int s;
FILE *f;
char result[MAX_STRING];
char buf[MAX_STRING * 2];
char buf2[MAX_STRING * 2];
char buf3[MAX_STRING * 4];
char arg[MAX_STRING];
size_t len;
char *p;
unsigned int addr;
addr = inet_addr(ip);
if (addr == INADDR_NONE) {
return (-1);
}
hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
sprintf(buf, "%s %s\n",
ip, ((hp && strlen(hp->h_name) < MAX_STRING) ?
hp->h_name : ip));
arg_for_errors = orig_arg;
strcpy(arg, orig_arg);
comma = (char *)strrchr(arg, ',');
if (comma == NULL) {
return (-1);
}
*comma = 0;
port_pair = (char *)strrchr(arg, ',');
if (port_pair == NULL) {
return (-1);
}
*port_pair++ = 0;
*comma = ',';

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\slave.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:25 PM

hp = gethostbyname(arg);
if (hp == NULL) {
static struct hostent def;
static struct in_addr defaddr;
static char *alist[1];
static char namebuf[MAX_STRING];
defaddr.s_addr = (unsigned int) inet_addr(arg);
if (defaddr.s_addr == INADDR_NONE) {
return (-1);
}
strcpy(namebuf, arg);
def.h_name = namebuf;
def.h_addr_list = alist;
def.h_addr = (char *)&defaddr;
def.h_length = sizeof(struct in_addr);
def.h_addrtype = AF_INET;
def.h_aliases = 0;
hp = &def;

}
sin.sin_family = hp->h_addrtype;
memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length);
sin.sin_port = htons(113); /*
* ident port
*/
s = socket(hp->h_addrtype, SOCK_STREAM, 0);
if (s < 0) {
return (-1);
}
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
if (errno != ECONNREFUSED
&& errno != ETIMEDOUT
&& errno != ENETUNREACH
&& errno != EHOSTUNREACH) {
close(s);
return (-1);
}
buf2[0] = '\0';
} else {
len = strlen(port_pair);
if (write(s, port_pair, len) != (int)len) {
close(s);
return (-1);
}
if (write(s, "\r\n", 2) != 2) {
close(s);
return (-1);
}
f = fdopen(s, "r");
{
int c;

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\slave.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:25 PM

p = result;
while ((c = fgetc(f)) != EOF) {
if (c == '\n')
break;
if (isprint(c)) {
*p++ = c;
if (p - result == MAX_STRING - 1)
break;
}
}
*p = '\0';

}
(void)fclose(f);
p = format_inet_addr(buf2, ntohl(sin.sin_addr.s_addr));
*p++ = ' ';
p = stpcpy(p, result);
*p++ = '\n';
*p++ = '\0';

}
sprintf(buf3, "%s%s", buf, buf2);
write(1, buf3, strlen(buf3));
return (0);

void child_signal(sig)
int sig;
{
pid_t child_pid;
int i;

/* see if any children have exited */


while ((child_pid = WAITOPT(NULL, WNOHANG)) > 0) {
for (i = 0; i < MAX_CHILDREN; i++) {
if (child_pids[i] == child_pid) {
child_pids[i] = -1;
break;
}
}
}
signal(SIGCHLD, (void (*)(int))child_signal);

void alarm_signal(sig)
int sig;
{
struct itimerval itime;
struct timeval interval;
if (getppid() != parent_pid) {
exit(1);
}
signal(SIGALRM, (void (*)(int))alarm_signal);
interval.tv_sec = 120; /*
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\slave.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:25 PM

* 2 minutes
*/
interval.tv_usec = 0;
itime.it_interval = interval;
itime.it_value = interval;
setitimer(ITIMER_REAL, &itime, 0);

int main(argc, argv)


int argc;
char **argv;
{
char arg[MAX_STRING];
char *p;
int i, len;
pid_t child_pid;
parent_pid = getppid();
if (parent_pid == 1) {
exit(1);
}
for (i = 0; i < MAX_CHILDREN; i++) {
child_pids[i] = -1;
}
alarm_signal(SIGALRM);
signal(SIGCHLD, (void (*)(int))child_signal);
signal(SIGPIPE, SIG_DFL);
for (;;) {
/* Find an empty child process slot, or wait until one is
* available. Otherwise there's no point in reading in a
* request yet.
*/
do {
/* see if any children have exited */
while ((child_pid = WAITOPT(NULL, WNOHANG)) > 0) {
for (i = 0; i < MAX_CHILDREN; i++) {
if (child_pids[i] == child_pid) {
child_pids[i] = -1;
break;
}
}
}
/* look for an available child process slot */
for (i = 0; i < MAX_CHILDREN; i++) {
child_pid = child_pids[i];
if (child_pid == -1 ||
kill(child_pid, 0) == -1)
break;
}
if (i < MAX_CHILDREN)
break;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\slave.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:25 PM

/* no slot available, wait for some child to exit */


child_pid = WAITOPT(NULL, 0);
for (i = 0; i < MAX_CHILDREN; i++) {
if (child_pids[i] == child_pid) {
child_pids[i] = -1;
break;
}
}
} while (i == MAX_CHILDREN);
/* ok, now read a request (blocking if no request is waiting,
* and stopping when interrupted by a signal)
*/
len = read(0, arg, MAX_STRING - 1);
if (len == 0)
break;
if (len < 0) {
if (errno == EINTR) {
continue;
}
break;
}
arg[len] = '\0';
p = strchr(arg, '\n');
if (p)
*p = '\0';
child_pid = fork();
switch (child_pid) {
case -1:
exit(1);
case 0: /*
* child
*/
{
/*
* we don't want to try this for more than 5
* minutes
*/
struct itimerval itime;
struct timeval interval;
interval.tv_sec = 300; /*
* 5 minutes
*/
interval.tv_usec = 0;
itime.it_interval = interval;
itime.it_value = interval;
signal(SIGALRM, (void (*)(int))child_timeout_signal);
setitimer(ITIMER_REAL, &itime, 0);

}
exit(query(arg, p + 1) != 0);

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\slave.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338

Saturday, June 16, 2012 11:25 PM

default:
/* parent */
child_pids[i] = child_pid;
break;
}

/* wait for any remaining children */


for (i = 0; i < MAX_CHILDREN; i++) {
child_pid = child_pids[i];
if (child_pid != -1 &&
kill(child_pid, 0) != -1) {
kill(child_pid, SIGKILL);
WAITPID(child_pid, NULL, 0);
}
}
exit(0);

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\slave.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Saturday, June 16, 2012 11:05 PM

/* slave.h */
/* $Id: slave.h,v 1.4 2000/05/29 22:20:55 rmg Exp $ */
#include "copyright.h"
#ifndef __SLAVE_H
#define __SLAVE_H
enum {
SLAVE_IDENTQ = 'i',
SLAVE_IPTONAME = 'h'
};
#endif /* __SLAVE_H */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:25 PM

/* speech.c - Commands which involve speaking */


/* $Id: speech.c,v 1.51 2008/03/09 17:09:03 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"match.h"
"powers.h"
"attrs.h"
"ansi.h"

/*
/*
/*
/*

required
required
required
required

by
by
by
by

code
code
code
code

*/
*/
*/
*/

#define SAY_STRING (mudconf.comma_say ? "say," : "say")


#define SAYS_STRING (mudconf.comma_say ? "says," : "says")
int sp_ok(player)
dbref player;
{
if (Gagged(player) && (!(Wizard(player)))) {
notify(player, "Sorry. Gagged players cannot speak." );
return 0;
}

if (!mudconf.robot_speak) {
if (Robot(player) && !controls(player, Location(player))) {
notify(player, "Sorry robots may not speak in public." );
return 0;
}
}
if (Auditorium(Location(player))) {
if (!could_doit(player, Location(player), A_LSPEECH)) {
notify(player, "Sorry, you may not speak in this place." );
return 0;
}
}
return 1;

static void say_shout(target, prefix, flags, player, message)


int target, flags;
dbref player;
char *message;
const char *prefix;
{
if (flags & SAY_NOTAG)
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

else
}

Saturday, June 16, 2012 11:25 PM

raw_broadcast(target, "%s%s", Name(player), message);


raw_broadcast(target, "%s%s%s", prefix, Name(player), message);

static const char *announce_msg = "Announcement: ";


static const char *broadcast_msg = "Broadcast: ";
static const char *admin_msg = "Admin: ";
void do_think(player, cause, key, message)
dbref player, cause;
int key;
char *message;
{
char *str, *buf, *bp;

buf = bp = alloc_lbuf("do_think");
str = message;
exec(buf, &bp, player, cause, cause,
EV_FCHECK | EV_EVAL | EV_TOP, &str, (char **)NULL, 0);
notify(player, buf);
free_lbuf(buf);

static int check_speechformat(player, speaker, loc, thing, message, key)


dbref player, speaker, loc, thing;
char *message;
int key;
{
char *sargs[2], tokbuf[2], *buff, msgbuf[LBUF_SIZE];
int aflags;
/* We have to make a copy of our arguments, because the exec() we
* pass it through later can nibble those arguments, and we may
* need to call this function more than once on the same message.
*/
strcpy(msgbuf, message);
switch (key) {
case SAY_SAY:
tokbuf[0] = '"';
break;
case SAY_POSE:
tokbuf[0] = ':';
break;
case SAY_POSE_NOSPC:
tokbuf[0] = ';';
break;
default:
tokbuf[0] = '|';
}
tokbuf[1] = '\0';
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:25 PM

sargs[0] = msgbuf;
sargs[1] = tokbuf;
/* Go get it. An empty evaluation is considered equivalent to no
* attribute, unless the attribute has a no_name flag.
*/
buff = master_attr(speaker, thing, A_SPEECHFMT, sargs, 2, &aflags);
if (buff) {
if (*buff) {
notify_all_from_inside_speech (loc, player, buff);
free_lbuf(buff);
return 1;
} else if (aflags & AF_NONAME) {
free_lbuf(buff);
return 1;
}
free_lbuf(buff);
}
}

return 0;

static void format_speech(player, speaker, loc, message, key)


dbref player, speaker, loc;
char *message;
int key;
{
if (H_Speechmod(speaker) &&
check_speechformat(player, speaker, loc, speaker, message, key))
return;
if (H_Speechmod(loc) &&
check_speechformat(player, speaker, loc, loc, message, key))
return;
switch (key) {
case SAY_SAY:
if (mudconf.you_say) {
notify(speaker, tprintf("You %s \"%s\"", SAY_STRING, message));
if (loc != NOTHING) {
notify_except(loc, player, speaker,
tprintf("%s %s \"%s\"", Name(speaker),
SAYS_STRING, message), MSG_SPEECH);
}
} else {
notify_all_from_inside_speech (loc, player,
tprintf("%s %s \"%s\"", Name(speaker),
SAYS_STRING, message));
}
break;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:25 PM

case SAY_POSE:
notify_all_from_inside_speech (loc, player,
tprintf("%s %s", Name(speaker), message));
break;
case SAY_POSE_NOSPC:
notify_all_from_inside_speech (loc, player,
tprintf("%s%s", Name(speaker), message));
break;
default:
/* NOTREACHED */
notify_all_from_inside_speech (loc, player, message);
}

void do_say(player, cause, key, message)


dbref player, cause;
int key;
char *message;
{
dbref loc;
char *buf2, *bp;
int say_flags, depth;
/* Check for shouts. Need to have Announce power. */
if ((key & SAY_SHOUT) && !Announce(player)) {
notify(player, NOPERM_MESSAGE);
return;
}
/*
* Convert prefix-coded messages into the normal type
*/
say_flags = key & (SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
key &= ~(SAY_NOTAG | SAY_HERE | SAY_ROOM | SAY_HTML);
if (key & SAY_PREFIX) {
key &= ~SAY_PREFIX;
switch (key) {
case SAY_POSE:
message++;
if (*message == ' ') {
message++;
key = SAY_POSE_NOSPC;
}
break;
case SAY_SAY:
case SAY_POSE_NOSPC:
message++;
break;
case SAY_EMIT:
/* if they doubled the backslash, remove it. Otherwise
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:25 PM

* it's already been removed by evaluation.


*/
if (*message == '\\')
message++;
break;
default:
return;
}

}
/*
* Make sure speaker is somewhere if speaking in a place
*/
loc = where_is(player);
switch (key) {
case SAY_SAY:
case SAY_POSE:
case SAY_POSE_NOSPC:
case SAY_EMIT:
if (loc == NOTHING)
return;
if (!sp_ok(player))
return;
}
/*
* Send the message on its way
*/
switch (key) {
case SAY_SAY:
format_speech(player, player, loc, message, SAY_SAY);
break;
case SAY_POSE:
format_speech(player, player, loc, message, SAY_POSE);
break;
case SAY_POSE_NOSPC:
format_speech(player, player, loc, message, SAY_POSE_NOSPC);
break;
case SAY_EMIT:
if (!say_flags || (say_flags & SAY_HERE) ||
((say_flags & SAY_HTML) && !(say_flags & SAY_ROOM))) {
if (say_flags & SAY_HTML) {
notify_all_from_inside_html_speech (loc, player,
message);
} else {
notify_all_from_inside_speech (loc, player,
message);
}
}
if (say_flags & SAY_ROOM) {
if ((Typeof(loc) == TYPE_ROOM) &&
(say_flags & SAY_HERE)) {
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:25 PM

return;
}
depth = 0;
while ((Typeof(loc) != TYPE_ROOM) &&
(depth++ < 20)) {
loc = Location(loc);
if ((loc == NOTHING) ||
(loc == Location(loc)))
return;
}
if (Typeof(loc) == TYPE_ROOM) {
if (say_flags & SAY_HTML) {
notify_all_from_inside_html_speech (loc, player,
message);
} else {
notify_all_from_inside_speech (loc, player,
message);
}
}

}
break;
case SAY_SHOUT:
switch (*message) {
case ':':
message[0] = ' ';
say_shout(0, announce_msg, say_flags, player, message);
break;
case ';':
message++;
say_shout(0, announce_msg, say_flags, player, message);
break;
case '"':
message++;
default:
buf2 = alloc_lbuf("do_say.shout");
bp = buf2;
safe_str((char *)" shouts, \"", buf2, &bp);
safe_str(message, buf2, &bp);
safe_chr('"', buf2, &bp);
say_shout(0, announce_msg, say_flags, player, buf2);
free_lbuf(buf2);
}
STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT")
log_name(player);
log_printf(" shouts: '%s'", strip_ansi(message));
ENDLOG
break;
case SAY_WIZSHOUT:
switch (*message) {
case ':':
message[0] = ' ';
say_shout(WIZARD, broadcast_msg, say_flags, player,
message);
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:25 PM

break;
case ';':
message++;
say_shout(WIZARD, broadcast_msg, say_flags, player,
message);
break;
case '"':
message++;
default:
buf2 = alloc_lbuf("do_say.wizshout");
bp = buf2;
safe_str((char *)" says, \"", buf2, &bp);
safe_str(message, buf2, &bp);
safe_chr('"', buf2, &bp);
say_shout(WIZARD, broadcast_msg, say_flags, player,
buf2);
free_lbuf(buf2);
}
STARTLOG(LOG_SHOUTS, "WIZ", "BCAST")
log_name(player);
log_printf(" broadcasts: '%s'", strip_ansi(message));
ENDLOG
break;
case SAY_ADMINSHOUT:
switch (*message) {
case ':':
message[0] = ' ';
say_shout(WIZARD, admin_msg, say_flags, player,
message);
say_shout(ROYALTY, admin_msg, say_flags, player,
message);
break;
case ';':
message++;
say_shout(WIZARD, admin_msg, say_flags, player,
message);
say_shout(ROYALTY, admin_msg, say_flags, player,
message);
break;
case '"':
message++;
default:
buf2 = alloc_lbuf("do_say.adminshout");
bp = buf2;
safe_str((char *)" says, \"", buf2, &bp);
safe_str(message, buf2, &bp);
safe_chr('"', buf2, &bp);
*bp = '\0';
say_shout(WIZARD, admin_msg, say_flags, player,
buf2);
say_shout(ROYALTY, admin_msg, say_flags, player,
buf2);
free_lbuf(buf2);
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:25 PM

}
STARTLOG(LOG_SHOUTS, "WIZ", "ASHOUT")
log_name(player);
log_printf(" yells: '%s'", strip_ansi(message));
ENDLOG
break;
case SAY_WALLPOSE:
if (say_flags & SAY_NOTAG)
raw_broadcast(0, "%s %s", Name(player), message);
else
raw_broadcast(0, "Announcement: %s %s", Name(player),
message);
STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT")
log_name(player);
log_printf(" WALLposes: '%s'", strip_ansi(message));
ENDLOG
break;
case SAY_WIZPOSE:
if (say_flags & SAY_NOTAG)
raw_broadcast(WIZARD, "%s %s", Name(player), message);
else
raw_broadcast(WIZARD, "Broadcast: %s %s", Name(player),
message);
STARTLOG(LOG_SHOUTS, "WIZ", "BCAST")
log_name(player);
log_printf(" WIZposes: '%s'", strip_ansi(message));
ENDLOG
break;
case SAY_WALLEMIT:
if (say_flags & SAY_NOTAG)
raw_broadcast(0, "%s", message);
else
raw_broadcast(0, "Announcement: %s", message);
STARTLOG(LOG_SHOUTS, "WIZ", "SHOUT")
log_name(player);
log_printf(" WALLemits: '%s'", strip_ansi(message));
ENDLOG
break;
case SAY_WIZEMIT:
if (say_flags & SAY_NOTAG)
raw_broadcast(WIZARD, "%s", message);
else
raw_broadcast(WIZARD, "Broadcast: %s", message);
STARTLOG(LOG_SHOUTS, "WIZ", "BCAST")
log_name(player);
log_printf(" WIZemits: '%s'", strip_ansi(message));
ENDLOG
break;
}

/*
* ---------------------------------------------------------------------------8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:25 PM

* * do_page: Handle the page command.


* * Page-pose code from shadow@prelude.cc.purdue.
*/
static void page_return(player, target, tag, anum, dflt)
dbref player, target;
int anum;
const char *tag, *dflt;
{
dbref aowner;
int aflags, alen;
char *str, *str2, *buf, *bp;
struct tm *tp;
time_t t;

str = atr_pget(target, anum, &aowner, &aflags, &alen);


if (*str) {
str2 = bp = alloc_lbuf("page_return");
buf = str;
exec(str2, &bp, target, player, player,
EV_FCHECK | EV_EVAL | EV_TOP | EV_NO_LOCATION, &buf,
(char **)NULL, 0);
if (*str2) {
t = time(NULL);
tp = localtime(&t);
notify_with_cause(player, target,
tprintf("%s message from %s: %s",
tag, Name(target), str2));
notify_with_cause(target, player,
tprintf("[%d:%02d] %s message sent to %s." ,
tp->tm_hour, tp->tm_min, tag, Name(player)));
}
free_lbuf(str2);
} else if (dflt && *dflt) {
notify_with_cause(player, target, dflt);
}
free_lbuf(str);

static int page_check(player, target)


dbref player, target;
{
if (!payfor(player, Guest(player) ? 0 : mudconf.pagecost)) {
notify(player,
tprintf("You don't have enough %s.",
mudconf.many_coins));
} else if (!Connected(target)) {
page_return(player, target, "Away", A_AWAY,
tprintf("Sorry, %s is not connected." ,
Name(target)));
} else if (!could_doit(player, target, A_LPAGE)) {
if (Can_Hide(target) && Hidden(target) && !See_Hidden(player))
page_return(player, target, "Away", A_AWAY,
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

else

Saturday, June 16, 2012 11:25 PM

tprintf("Sorry, %s is not connected." ,


Name(target)));

page_return(player, target, "Reject", A_REJECT,


tprintf("Sorry, %s is not accepting pages." ,
Name(target)));
} else if (!could_doit(target, player, A_LPAGE)) {
if (Wizard(player)) {
notify(player,
tprintf("Warning: %s can't return your page." ,
Name(target)));
return 1;
} else {
notify(player,
tprintf("Sorry, %s can't return your page." ,
Name(target)));
return 0;
}
} else {
return 1;
}
return 0;

void do_page(player, cause, key, tname, message)


dbref player, cause;
int key;
/* 1 if this is a reply page */
char *tname, *message;
{
char *dbref_list, *ddp;
char *clean_tname, *tnp;
char *omessage, *omp, *imessage, *imp;
int count = 0;
int aowner, aflags, alen;
dbref target;
int n_dbrefs, i;
int *dbrefs_array = NULL;
char *str, *tokst;
/* If we have to have an equals sign in the page command, if
* there's no message, it's an error (otherwise tname would
* be null and message would contain text).
* Otherwise we handle repage by swapping args.
* Unfortunately, we have no way of differentiating
* 'page foo=' from 'page foo' -- both result in a valid tname.
*/
if (!key && !*message) {
if (mudconf.page_req_equals) {
notify(player, "No one to page.");
return;
}
tnp = message;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:25 PM

message = tname;
tname = tnp;
}
if (!tname || !*tname) {

/* no recipient list; use lastpaged */

/* Clean junk objects out of their lastpaged dbref list */


if (key)
dbref_list = atr_get(player, A_PAGEGROUP, &aowner, &aflags, &alen);
else
dbref_list = atr_get(player, A_LASTPAGE, &aowner, &aflags, &alen);
/* How many words in the list of targets? */
if (!*dbref_list) {
count = 0;
} else {
for (n_dbrefs = 1, str = dbref_list; ; n_dbrefs++) {
if ((str = strchr(str, ' ')) != NULL)
str++;
else
break;
}
dbrefs_array = (int *) XCALLOC(n_dbrefs, sizeof(int),
"do_page.dbrefs");
/* Convert the list into an array of targets. Validate. */

for (ddp = strtok_r(dbref_list, " ", &tokst);


ddp;
ddp = strtok_r(NULL, " ", &tokst)) {
target = atoi(ddp);
if (!Good_obj(target) || !isPlayer(target)) {
notify(player, tprintf("I don't recognize #%d.", target));
continue;
}
/* Eliminate ourselves from repeat and reply pages */
if (target == player)
continue;
dbrefs_array[count] = target;
count++;
}

free_lbuf(dbref_list);
} else {

/* normal page; build new recipient list */

if ((target = lookup_player(player, tname, 1)) != NOTHING) {


dbrefs_array = (int *) XCALLOC(1, sizeof(int), "do_page.dbrefs");
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:25 PM

dbrefs_array[0] = target;
count++;
} else {
/* How many words in the list of targets? Note that we separate
* with either a comma or a space!
*/
n_dbrefs = 1;
for (str = tname; *str; str++) {
if ((*str == ' ') || (*str == ','))
n_dbrefs++;
}
dbrefs_array = (int *) XCALLOC(n_dbrefs, sizeof(int), "do_page.dbrefs");
/* Go look 'em up */

}
}

for (tnp = strtok_r(tname, ", ", &tokst);


tnp;
tnp = strtok_r(NULL, ", ", &tokst)) {
if ((target = lookup_player(player, tnp, 1)) != NOTHING) {
dbrefs_array[count] = target;
count++;
} else {
notify(player, tprintf("I don't recognize %s.", tnp));
}
}

n_dbrefs = count;
/* Filter out disconnected and pagelocked, if we're actually sending
* a message.
*/
if (*message) {
for (i = 0; i < n_dbrefs; i++) {
if (!page_check(player, dbrefs_array[i])) {
dbrefs_array[i] = NOTHING;
count--;
}
}
}
/* Write back the lastpaged attribute. */
dbref_list = ddp = alloc_lbuf("do_page.lastpage");
for (i = 0; i < n_dbrefs; i++) {
if (dbrefs_array[i] != NOTHING) {
if (ddp != dbref_list)
safe_chr(' ', dbref_list, &ddp);
safe_ltos(dbref_list, &ddp, dbrefs_array[i]);
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

Saturday, June 16, 2012 11:25 PM

}
}
*ddp = '\0';
atr_add_raw(player, A_LASTPAGE, dbref_list);
free_lbuf(dbref_list);
/* Check to make sure we have something. */
if (count == 0) {
if (!*message) {
if (key)
notify(player, "You have not been paged by anyone." );
else
notify(player, "You have not paged anyone.");
} else {
notify(player, "No one to page.");
}
if (dbrefs_array)
XFREE(dbrefs_array, "do_page.dbrefs");
return;
}
/* Each person getting paged is included in the pagegroup, as is the
* person doing the paging. This lets us construct one list rather than
* individual ones for each player. Self-paging is automatically
* eliminated when the pagegroup is used.
*/
dbref_list = ddp = alloc_lbuf("do_page.pagegroup");
safe_ltos(dbref_list, &ddp, player);
for (i = 0; i < n_dbrefs; i++) {
if (dbrefs_array[i] != NOTHING) {
safe_chr(' ', dbref_list, &ddp);
safe_ltos(dbref_list, &ddp, dbrefs_array[i]);
}
}
*ddp = '\0';
for (i = 0; i < n_dbrefs; i++)
if (dbrefs_array[i] != NOTHING)
atr_add_raw(dbrefs_array[i], A_PAGEGROUP, dbref_list);
free_lbuf(dbref_list);
/* Build name list. Even if we only have one name, we have to go
* through the array, because the first entries might be invalid.
*/
clean_tname = tnp = alloc_lbuf("do_page.namelist");
if (count == 1) {
for (i = 0; i < n_dbrefs; i++) {
if (dbrefs_array[i] != NOTHING) {
safe_name(dbrefs_array[i], clean_tname, &tnp);
break;
}
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

Saturday, June 16, 2012 11:25 PM

}
} else {
safe_chr('(', clean_tname, &tnp);
for (i = 0; i < n_dbrefs; i++) {
if (dbrefs_array[i] != NOTHING) {
if (tnp != clean_tname + 1)
safe_known_str(", ", 2, clean_tname, &tnp);
safe_name(dbrefs_array[i], clean_tname, &tnp);
}
}
safe_chr(')', clean_tname, &tnp);
}
*tnp = '\0';
/* Mess with message */
omessage = omp = alloc_lbuf("do_page.omessage");
imessage = imp = alloc_lbuf("do_page.imessage");
switch (*message) {
case '\0':
notify(player, tprintf("You last paged %s.", clean_tname));
free_lbuf(clean_tname);
free_lbuf(omessage);
free_lbuf(imessage);
XFREE(dbrefs_array, "do_page.dbrefs");
return;
case ':':
message++;
safe_str("From afar, ", omessage, &omp);
if (count != 1)
safe_tprintf_str(omessage, &omp, "to %s: ", clean_tname);
safe_tprintf_str(omessage, &omp, "%s %s", Name(player), message);
safe_tprintf_str(imessage, &imp, "Long distance to %s: %s %s",
clean_tname, Name(player), message);
break;
case ';':
message++;
safe_str("From afar, ", omessage, &omp);
if (count != 1)
safe_tprintf_str(omessage, &omp, "to %s: ", clean_tname);
safe_tprintf_str(omessage, &omp, "%s%s", Name(player), message);
safe_tprintf_str(imessage, &imp, "Long distance to %s: %s%s",
clean_tname, Name(player), message);
break;
case '"':
message++;
default:
if (count != 1)
safe_tprintf_str(omessage, &omp, "To %s, ", clean_tname);
safe_tprintf_str(omessage, &omp, "%s pages: %s",
Name(player), message);
safe_tprintf_str(imessage, &imp, "You paged %s with '%s'.",
clean_tname, message);
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

Saturday, June 16, 2012 11:25 PM

}
free_lbuf(clean_tname);
/* Send the message out, checking for idlers */
for (i = 0; i < n_dbrefs; i++) {
if (dbrefs_array[i] != NOTHING) {
notify_with_cause(dbrefs_array[i], player, omessage);
page_return(player, dbrefs_array[i], "Idle", A_IDLE, NULL);
}
}
free_lbuf(omessage);
XFREE(dbrefs_array, "do_page.dbrefs");
/* Tell the sender */

notify(player, imessage);
free_lbuf(imessage);

void do_reply_page(player, cause, key, msg)


dbref player, cause;
int key;
char *msg;
{
do_page(player, cause, 1, NULL, msg);
}
/*
* --------------------------------------------------------------------------* * do_pemit: Messages to specific players, or to all but specific players.
*/
void whisper_pose(player, target, message)
dbref player, target;
char *message;
{
char *buff;

buff = alloc_lbuf("do_pemit.whisper.pose");
StringCopy(buff, Name(player));
notify(player,
tprintf("%s senses \"%s%s\"", Name(target), buff, message));
notify_with_cause(target, player,
tprintf("You sense %s%s", buff, message));
free_lbuf(buff);

void do_pemit_list(player, list, message, do_contents)


dbref player;
char *list;
const char *message;
int do_contents;
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848

Saturday, June 16, 2012 11:25 PM

/*
* Send a message to a list of dbrefs. To avoid repeated generation *
* of the NOSPOOF string, we set it up the first time we
* encounter something Nospoof, and then check for it
* thereafter. The list is destructively modified.
*/
char *p, *tokst;
dbref who, *recips;
int n_recips, r, ok_to_do;
if (!message || !*message || !list || !*list)
return;
n_recips = 1;
for (p = list; *p; ++p) {
if (*p == ' ')
++n_recips;
}
recips = (dbref *) XCALLOC(n_recips, sizeof(dbref),
"do_pemit_list.recips");
n_recips = 0;
for (p = strtok_r(list, " ", &tokst);
p != NULL;
p = strtok_r(NULL, " ", &tokst)) {
init_match(player, p, TYPE_PLAYER);
match_everything(0);
who = match_result();
switch (who) {
case NOTHING:
notify(player, "Emit to whom?");
break;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
break;
default:
if (!Good_obj(who))
continue;
/* avoid pemitting to this dbref if already done */
for (r = 0; r < n_recips; ++r) {
if (recips[r] == who)
break;
}
if (r < n_recips)
continue;
/* see if player can pemit to this dbref */
ok_to_do = mudconf.pemit_any;
if (!ok_to_do &&
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

Saturday, June 16, 2012 11:25 PM

(Long_Fingers(player) || nearby(player, who) ||


Controls(player, who))) {
ok_to_do = 1;

}
if (!ok_to_do && (isPlayer(who))
&& mudconf.pemit_players) {
if (!page_check(player, who))
continue;
ok_to_do = 1;
}
if (do_contents && !mudconf.pemit_any &&
!Controls(player, who)) {
ok_to_do = 0;
}
if (!ok_to_do) {
notify(player, "You cannot do that.");
continue;
}
/* fine, send the message */
if (do_contents && Has_contents(who))
notify_all_from_inside(who, player, message);
else
notify_with_cause(who, player, message);
/* avoid pemitting to this dbref again */
recips[n_recips] = who;
++n_recips;

}
XFREE(recips, "do_pemit_list.recips");

void do_pemit(player, cause, key, recipient, message)


dbref player, cause;
int key;
char *recipient, *message;
{
dbref target, loc;
char *buf2, *bp;
int do_contents, ok_to_do, depth, pemit_flags;
if (key & PEMIT_CONTENTS) {
do_contents = 1;
key &= ~PEMIT_CONTENTS;
} else {
do_contents = 0;
}
if (key & PEMIT_LIST) {
do_pemit_list(player, recipient, message, do_contents);
return;
}
pemit_flags = key & (PEMIT_HERE | PEMIT_ROOM | PEMIT_SPEECH | PEMIT_MOVE |
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

Saturday, June 16, 2012 11:25 PM

PEMIT_HTML | PEMIT_SPOOF);
key &= ~(PEMIT_HERE | PEMIT_ROOM | PEMIT_SPEECH | PEMIT_MOVE | PEMIT_HTML |
PEMIT_SPOOF);
ok_to_do = 0;
switch (key) {
case PEMIT_FSAY:
case PEMIT_FPOSE:
case PEMIT_FPOSE_NS:
case PEMIT_FEMIT:
target = match_affected(player, recipient);
if (target == NOTHING)
return;
ok_to_do = 1;
break;
default:
init_match(player, recipient, TYPE_PLAYER);
match_everything(0);
target = match_result();
}
switch (target) {
case NOTHING:
switch (key) {
case PEMIT_WHISPER:
notify(player, "Whisper to whom?");
break;
case PEMIT_PEMIT:
notify(player, "Emit to whom?");
break;
case PEMIT_OEMIT:
notify(player, "Emit except to whom?");
break;
default:
notify(player, "Sorry.");
}
break;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
break;
default:
/*
* Enforce locality constraints
*/
if (!ok_to_do &&
(nearby(player, target) || Long_Fingers(player)
|| Controls(player, target))) {
ok_to_do = 1;
}
if (!ok_to_do && (key == PEMIT_PEMIT) &&
(Typeof(target) == TYPE_PLAYER) && mudconf.pemit_players) {
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

Saturday, June 16, 2012 11:25 PM

if (!page_check(player, target))
return;
ok_to_do = 1;

}
if (!ok_to_do &&
(!mudconf.pemit_any || (key != PEMIT_PEMIT))) {
notify(player, "You are too far away to do that." );
return;
}
if (do_contents && !Controls(player, target) &&
!mudconf.pemit_any) {
notify(player, NOPERM_MESSAGE);
return;
}
loc = where_is(target);
switch (key) {
case PEMIT_PEMIT:
if (do_contents) {
if (Has_contents(target)) {
if (pemit_flags & PEMIT_SPEECH) {
notify_all_from_inside_speech (target,
player, message);
} else if (pemit_flags & PEMIT_MOVE) {
notify_all_from_inside_move(target,
player, message);
} else {
notify_all_from_inside(target, player,
message);
}
}
} else {
notify_with_cause_extra(target, player,
message,
((pemit_flags & PEMIT_HTML) ? MSG_HTML : 0) |
((pemit_flags & PEMIT_SPEECH) ? MSG_SPEECH : 0));
}
break;
case PEMIT_OEMIT:
notify_except(Location(target), player, target,
message,
((pemit_flags & PEMIT_SPEECH) ? MSG_SPEECH : 0) |
((pemit_flags & PEMIT_MOVE) ? MSG_MOVE : 0));
break;
case PEMIT_WHISPER:
if ((Unreal(player) && !Check_Heard(target, player)) ||
(Unreal(target) && !Check_Hears(player, target))) {
notify(player, CANNOT_HEAR_MSG);
} else {
switch (*message) {
case ':':
message[0] = ' ';
whisper_pose(player, target, message);
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:25 PM

break;
case ';':
message++;
whisper_pose(player, target, message);
break;
case '"':
message++;
default:
notify(player,
tprintf("You whisper \"%s\" to %s.",
message, Name(target)));
notify_with_cause(target, player,
tprintf("%s whispers \"%s\"",
Name(player), message));
}
if ((!mudconf.quiet_whisper) && !Wizard(player)) {
loc = where_is(player);
if (loc != NOTHING) {
buf2 = alloc_lbuf("do_pemit.whisper.buzz");
bp = buf2;
safe_name(player, buf2, &bp);
safe_str((char *)" whispers something to ",
buf2, &bp);
safe_name(target, buf2, &bp);
*bp = '\0';
notify_except2(loc, player, player,
target, buf2,
MSG_SPEECH);
free_lbuf(buf2);
}
}

}
break;
case PEMIT_FSAY:
format_speech(((pemit_flags & PEMIT_SPOOF) ?
target : player),
target, loc, message, SAY_SAY);
break;
case PEMIT_FPOSE:
format_speech(((pemit_flags & PEMIT_SPOOF) ?
target : player),
target, loc, message, SAY_POSE);
break;
case PEMIT_FPOSE_NS:
format_speech(((pemit_flags & PEMIT_SPOOF) ?
target : player),
target, loc, message, SAY_POSE_NOSPC);
break;
case PEMIT_FEMIT:
if ((pemit_flags & PEMIT_HERE) ||
(!(pemit_flags & ~PEMIT_SPOOF)))
notify_all_from_inside_speech (loc,
((pemit_flags & PEMIT_SPOOF) ?
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\speech.c

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084

Saturday, June 16, 2012 11:25 PM

target : player), message);


if (pemit_flags & PEMIT_ROOM) {
if ((Typeof(loc) == TYPE_ROOM) &&
(pemit_flags & PEMIT_HERE)) {
return;
}
depth = 0;
while ((Typeof(loc) != TYPE_ROOM) &&
(depth++ < 20)) {
loc = Location(loc);
if ((loc == NOTHING) ||
(loc == Location(loc)))
return;
}
if (Typeof(loc) == TYPE_ROOM) {
notify_all_from_inside_speech (loc,
((pemit_flags & PEMIT_SPOOF) ?
target : player), message);
}
}
break;

-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\strdup.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Saturday, June 16, 2012 11:24 PM

/* strdup.c - For systems like Ultrix that don't have it. */


/* $Id: strdup.c,v 1.2 2000/05/29 22:20:56 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
char *strdup(const char *s)
{
char *result;

result = (char *)malloc(strlen(s) + 1);


strcpy(result, s);
return result;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:24 PM

/* stringutil.c - string utilities */


/* $Id: stringutil.c,v 1.57 2007/10/08 06:22:43 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "ansi.h"

/* required by code */

/* Provide strtok_r (reentrant strtok) if needed */


#ifndef HAVE_STRTOK_R
char *strtok_r(s, sep, last)
char *s;
const char *sep;
char **last;
{
if (!s)
s = *last;
#ifdef HAVE_STRCSPN
s += strspn(s, sep);
*last = s + strcspn(s, sep);
#else /* HAVE_STRCSPN */
while (strchr(sep, *s) && *s) s++;
*last = s;
while (!strchr(sep, **last) && **last) (*last)++;
#endif /* HAVE_STRCSPN */
if (s == *last)
return NULL;
if (**last)
*((*last)++) = '\0';
return s;
}
#endif /* HAVE_STRTOK_R */
/* --------------------------------------------------------------------------* ANSI character-to-number translation table.
*/
int ansi_nchartab[256] =
{
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
0,
0,
0,
0,

0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
I_ANSI_BBLUE,
0,
-1-

0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
I_ANSI_BCYAN,
I_ANSI_BGREEN,

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

};

0,
0,
0,
0,
I_ANSI_BBLACK,
0,
0,
0,
I_ANSI_HILITE,
0,
0,
0,
I_ANSI_BLACK,
0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,

0,
I_ANSI_BMAGENTA,
0,
0,
I_ANSI_BYELLOW,
0,
0,
0,
I_ANSI_INVERSE,
I_ANSI_MAGENTA,
0,
I_ANSI_UNDER,
I_ANSI_YELLOW,
0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,

Saturday, June 16, 2012 11:24 PM

0,
0,
I_ANSI_BRED,
0,
0,
0,
I_ANSI_BLUE,
I_ANSI_BLINK,
0,
I_ANSI_NORMAL,
I_ANSI_RED,
0,
0,
0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,

0,
0,
0,
I_ANSI_BWHITE,
0,
0,
I_ANSI_CYAN,
I_ANSI_GREEN,
0,
0,
0,
I_ANSI_WHITE,
0,
0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0

/* --------------------------------------------------------------------------* ANSI number-to-character translation table.


*/
char ansi_lettab[I_ANSI_NUM] =
{
'\0',
'h',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'\0',
'g',
'y',
'b',
'm',
'X',
'R',
'G',
'Y',
};

'u',
'\0',
'\0',
'\0',
'c',
'B',

'f',
'\0',
'\0',
'\0',
'w',
'M',

'\0',
'\0',
'\0',
'x',
'\0',
'C',

'i',
'\0',
'\0',
'r',
'\0',
'W'

/* --------------------------------------------------------------------------* ANSI packed state definitions -- number-to-bitmask translation table.


*
* The mask specifies the state bits that are altered by a particular ansi
* code. Bits are laid out as follows:
*
* 0x1000 -- No ansi. Every valid ansi code clears this bit.
* 0x0800 -- inverse
* 0x0400 -- flash
* 0x0200 -- underline
* 0x0100 -- highlight
* 0x0080 -- "use default bg", set by ansi normal, cleared by other bg's
* 0x0070 -- three bits of bg color
* 0x0008 -- "use default fg", set by ansi normal, cleared by other fg's
* 0x0007 -- three bits of fg color
*/
int ansi_mask_bits[I_ANSI_LIM] = {
0x1fff, 0x1100, 0x1100, 0,

0x1200, 0x1400, 0,
-2-

0x1800, 0, 0,

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

};

0,
0,
0x100f,
0x10f0,

0,
0x1100,
0x100f,
0x10f0,

0,
0x1100,
0x100f,
0x10f0,

0,
0,
0x100f,
0x10f0,

Saturday, June 16, 2012 11:24 PM

0,
0x1200,
0x100f,
0x10f0,

0,
0x1400,
0x100f,
0x10f0,

0,
0,
0x100f,
0x10f0,

0,
0x1800,
0x100f,
0x10f0,

0,
0,
0,
0,

0,
0,
0,
0

/* --------------------------------------------------------------------------* ANSI packed state definitions -- number-to-bitvalue translation table.


*/
int ansi_bits[I_ANSI_LIM] =
0x0099, 0x0100, 0x0000,
0,
0,
0,
0,
0x0000, 0x0000,
0x0000, 0x0001, 0x0002,
0x0000, 0x0010, 0x0020,
};

{
0,
0,
0,
0x0003,
0x0030,

0x0200,
0,
0x0000,
0x0004,
0x0040,

0x0400,
0,
0x0000,
0x0005,
0x0050,

0,
0,
0,
0x0006,
0x0060,

0x0800,
0,
0x0000,
0x0007,
0x0070,

0,
0,
0,
0,
0,

0,
0,
0,
0,
0

/* --------------------------------------------------------------------------* strip_ansi -- return a new string with escape codes removed


*/
char *strip_ansi(s)
const char *s;
{
static char buf[LBUF_SIZE];
char *p = buf;
if (s) {
while (*s == ESC_CHAR) {
skip_esccode(s);
}

while (*s) {
*p++ = *s++;
while (*s == ESC_CHAR) {
skip_esccode(s);
}
}

*p = '\0';
return buf;

/* --------------------------------------------------------------------------* strip_ansi_len -- count non-escape-code characters


*/
int strip_ansi_len(s)
const char *s;
{
int n = 0;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:24 PM

if (s) {
while (*s == ESC_CHAR) {
skip_esccode(s);
}

}
}

while (*s) {
++s, ++n;
while (*s == ESC_CHAR) {
skip_esccode(s);
}
}

return n;

/* normal_to_white -- This function implements the NOBLEED flag */


char *normal_to_white(raw)
const char *raw;
{
static char buf[LBUF_SIZE];
char *p = (char *)raw;
char *q = buf;
char *just_after_csi;
char *just_after_esccode = p;
unsigned int param_val;
int has_zero;
while (p && *p) {
if (*p == ESC_CHAR) {
safe_known_str(just_after_esccode, p - just_after_esccode, buf, &q);
if (p[1] == ANSI_CSI) {
safe_chr(*p, buf, &q);
++p;
safe_chr(*p, buf, &q);
++p;
just_after_csi = p;
has_zero = 0;
while ((*p & 0xf0) == 0x30) {
if (*p == '0')
has_zero = 1;
++p;
}
while ((*p & 0xf0) == 0x20) {
++p;
}
if (*p == ANSI_END && has_zero) {
/* it really was an ansi code,
* go back and fix up the zero
*/
p = just_after_csi;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:24 PM

param_val = 0;
while ((*p & 0xf0) == 0x30) {
if (*p < 0x3a) {
param_val <<= 1;
param_val += (param_val << 2) + (*p & 0x0f);
safe_chr(*p, buf, &q);
} else {
if (param_val == 0) {
/* ansi normal */
safe_known_str("m\033[37m\033[", 8, buf, &q);
} else {
/* some other color */
safe_chr(*p, buf, &q);
}
param_val = 0;
}
++p;
}
while ((*p & 0xf0) == 0x20) {
++p;
}
safe_chr(*p, buf, &q);
++p;
if (param_val == 0) {
safe_known_str(ANSI_WHITE, 5, buf, &q);
}
} else {
++p;
safe_known_str(just_after_csi, p - just_after_csi, buf, &q);
}
} else {
safe_copy_esccode(p, buf, &q);
}
just_after_esccode = p;
} else {
++p;
}

}
safe_known_str(just_after_esccode, p - just_after_esccode, buf, &q);
return buf;

char *ansi_transition_esccode(ansi_before, ansi_after)


int ansi_before, ansi_after;
{
int ansi_bits_set, ansi_bits_clr;
char *p;
static char buffer[64];
if (ansi_before == ansi_after)
return "";
buffer[0] = ESC_CHAR;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:24 PM

buffer[1] = ANSI_CSI;
p = buffer + 2;
/* If they turn off any highlight bits, or they change from some color
* to default color, we need to use ansi normal first.
*/
ansi_bits_set = (~ansi_before) & ansi_after;
ansi_bits_clr = ansi_before & (~ansi_after);
if ((ansi_bits_clr & 0xf00) ||
/* highlights off */
(ansi_bits_set & 0x088) ||
/* normal to color */
(ansi_bits_clr == 0x1000)) {
/* explicit normal */
strcpy(p, "0;"); p += 2;
ansi_bits_set = (~ansi_bits[0]) & ansi_after;
ansi_bits_clr = ansi_bits[0] & (~ansi_after);
}
/* Next reproduce the highlight state */
if (ansi_bits_set & 0x100) {
strcpy(p, "1;"); p += 2;
}
if (ansi_bits_set & 0x200) {
strcpy(p, "4;"); p += 2;
}
if (ansi_bits_set & 0x400) {
strcpy(p, "5;"); p += 2;
}
if (ansi_bits_set & 0x800) {
strcpy(p, "7;"); p += 2;
}
/* Foreground color */
if ((ansi_bits_set | ansi_bits_clr) & 0x00f) {
strcpy(p, "30;"); p += 3;
p[-2] |= (ansi_after & 0x00f);
}
/* Background color */
if ((ansi_bits_set | ansi_bits_clr) & 0x0f0) {
strcpy(p, "40;"); p += 3;
p[-2] |= ((ansi_after & 0x0f0) >> 4);
}

/* Terminate */
if (p > buffer + 2) {
p[-1] = ANSI_END;
/* Buffer is already null-terminated by strcpy */
} else {
buffer[0] = '\0';
}
return buffer;

-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:24 PM

char *ansi_transition_mushcode(ansi_before, ansi_after)


int ansi_before, ansi_after;
{
int ansi_bits_set, ansi_bits_clr;
char *p;
static char ansi_mushcode_fg[9] = "xrgybmcw";
static char ansi_mushcode_bg[9] = "XRGYBMCW";
static char buffer[64];
if (ansi_before == ansi_after)
return "";
p = buffer;
/* If they turn off any highlight bits, or they change from some color
* to default color, we need to use ansi normal first.
*/
ansi_bits_set = (~ansi_before) & ansi_after;
ansi_bits_clr = ansi_before & (~ansi_after);
if ((ansi_bits_clr & 0xf00) ||
/* highlights off */
(ansi_bits_set & 0x088) ||
/* normal to color */
(ansi_bits_clr == 0x1000)) {
/* explicit normal */
strcpy(p, "%xn"); p += 3;
ansi_bits_set = (~ansi_bits[0]) & ansi_after;
ansi_bits_clr = ansi_bits[0] & (~ansi_after);
}
/* Next reproduce the highlight state */
if (ansi_bits_set & 0x100)
strcpy(p, "%xh"); p +=
}
if (ansi_bits_set & 0x200)
strcpy(p, "%xu"); p +=
}
if (ansi_bits_set & 0x400)
strcpy(p, "%xf"); p +=
}
if (ansi_bits_set & 0x800)
strcpy(p, "%xi"); p +=
}

{
3;
{
3;
{
3;
{
3;

/* Foreground color */
if ((ansi_bits_set | ansi_bits_clr) & 0x00f) {
strcpy(p, "%xx"); p += 3;
p[-1] = ansi_mushcode_fg[(ansi_after & 0x00f)];
}
/* Background color */
if ((ansi_bits_set | ansi_bits_clr) & 0x0f0) {
strcpy(p, "%xX"); p += 3;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:24 PM

p[-1] = ansi_mushcode_bg[(ansi_after & 0x0f0) >> 4];

/* Terminate */
*p = '\0';
return buffer;

char *ansi_transition_letters(ansi_before, ansi_after)


int ansi_before, ansi_after;
{
int ansi_bits_set, ansi_bits_clr;
char *p;
static char ansi_mushcode_fg[9] = "xrgybmcw";
static char ansi_mushcode_bg[9] = "XRGYBMCW";
static char buffer[64];
if (ansi_before == ansi_after)
return "";
p = buffer;
/* If they turn off any highlight bits, or they change from some color
* to default color, we need to use ansi normal first.
*/
ansi_bits_set = (~ansi_before) & ansi_after;
ansi_bits_clr = ansi_before & (~ansi_after);
if ((ansi_bits_clr & 0xf00) ||
/* highlights off */
(ansi_bits_set & 0x088) ||
/* normal to color */
(ansi_bits_clr == 0x1000)) {
/* explicit normal */
*p++ = 'n';
ansi_bits_set = (~ansi_bits[0]) & ansi_after;
ansi_bits_clr = ansi_bits[0] & (~ansi_after);
}
/* Next reproduce the highlight state */
if (ansi_bits_set
*p++ = 'h';
}
if (ansi_bits_set
*p++ = 'u';
}
if (ansi_bits_set
*p++ = 'f';
}
if (ansi_bits_set
*p++ = 'i';
}

& 0x100) {
& 0x200) {
& 0x400) {
& 0x800) {

/* Foreground color */
if ((ansi_bits_set | ansi_bits_clr) & 0x00f) {
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:24 PM

*p++ = ansi_mushcode_fg[(ansi_after & 0x00f)];

/* Background color */
if ((ansi_bits_set | ansi_bits_clr) & 0x0f0) {
*p++ = ansi_mushcode_bg[(ansi_after & 0x0f0) >> 4];
}

/* Terminate */
*p = '\0';
return buffer;

/* ansi_map_states -- Identify ansi state of every character in a string */


int ansi_map_states(s, m, p)
const char *s;
int **m;
char **p;
{
static int ansi_map[LBUF_SIZE + 1];
static char stripped[LBUF_SIZE + 1];
int n, ansi_state;
n = 0;
ansi_state = ANST_NORMAL;
while (*s) {
if (*s == ESC_CHAR) {
track_esccode(s, ansi_state);
} else {
ansi_map[n] = ansi_state;
stripped[n++] = *s++;
}
}
ansi_map[n] = ANST_NORMAL;
stripped[n] = '\0';

*m = ansi_map;
*p = stripped;
return n;

/* remap_colors -- allow a change of the color sequences */


char *remap_colors(s, cmap)
char *s;
int *cmap;
{
static char new[LBUF_SIZE];
char *bp;
int n;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:24 PM

if (!s || !*s || !cmap)


return s;
bp = new;
do {
while (*s && (*s != ESC_CHAR)) {
safe_chr(*s, new, &bp);
s++;
}
if (*s == ESC_CHAR) {
safe_chr(*s, new, &bp);
s++;
if (*s == ANSI_CSI) {
safe_chr(*s, new, &bp);
s++;
do {
n = atoi(s);
if ((n >= I_ANSI_BLACK) && (n < I_ANSI_NUM) &&
(cmap[n - I_ANSI_BLACK] != 0)) {
safe_ltos(new, &bp, cmap[n - I_ANSI_BLACK]);
while (isdigit(*s))
s++;
} else {
while (isdigit(*s)) {
safe_chr(*s, new, &bp);
s++;
}
}
if (*s == ';') {
safe_chr(*s, new, &bp);
s++;
}
} while (*s && (*s != ANSI_END));
if (*s == ANSI_END) {
safe_chr(*s, new, &bp);
s++;
}
} else if (*s) {
safe_chr(*s, new, &bp);
s++;
}
}
} while (*s);
}

return new;

/* translate_string -- Convert (type = 1) raw character sequences into


* MUSH substitutions or strip them (type = 0).
*/
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582

Saturday, June 16, 2012 11:24 PM

char *translate_string(str, type)


char *str;
int type;
{
static char new[LBUF_SIZE];
char *bp;
bp = new;
if (type) {
int ansi_state = ANST_NORMAL;
int ansi_state_prev = ANST_NORMAL;
while (*str) {
switch (*str) {
case ESC_CHAR:
while (*str == ESC_CHAR) {
track_esccode(str, ansi_state);
}
safe_str(ansi_transition_mushcode(ansi_state_prev, ansi_state), new, &bp
);
ansi_state_prev = ansi_state;
continue;
case ' ':
if (str[1] == ' ') {
safe_known_str("%b", 2, new, &bp);
} else {
safe_chr(' ', new, &bp);
}
break;
case '\\': case '%': case '[': case ']':
case '{': case '}': case '(': case ')':
safe_chr('%', new, &bp);
safe_chr(*str, new, &bp);
break;
case '\r':
break;
case '\n':
safe_known_str("%r", 2, new, &bp);
break;
case '\t':
safe_known_str("%t", 2, new, &bp);
break;
default:
safe_chr(*str, new, &bp);
}
str++;
}
} else {
while (*str) {
switch (*str) {
case ESC_CHAR:
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

Saturday, June 16, 2012 11:24 PM

skip_esccode(str);
continue;
case '\r':
break;
case '\n': case '\t':
safe_chr(' ', new, &bp);
break;
default:
safe_chr(*str, new, &bp);
}
str++;

}
*bp = '\0';
return new;

/*
* capitalizes an entire string
*/
char *upcasestr(s)
char *s;
{
char *p;

for (p = s; p && *p; p++)


*p = toupper(*p);
return s;

/*
* --------------------------------------------------------------------------* munge_space: Compress multiple spaces to one space,
* also remove leading and trailing spaces.
*/
char *munge_space(string)
char *string;
{
char *buffer, *p, *q;
buffer = alloc_lbuf("munge_space");
p = string;
q = buffer;
while (p && *p && isspace(*p))
p++;
/*
* remove initial spaces
*/
while (p && *p) {
while (*p && !isspace(*p))
*q++ = *p++;
while (*p && isspace(*++p)) ;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

Saturday, June 16, 2012 11:24 PM

if (*p)
*q++ = ' ';

}
*q = '\0';

/*
* remove terminal spaces and terminate
* string
*/
return (buffer);

/*
* --------------------------------------------------------------------------* * trim_spaces: Remove leading and trailing spaces.
*/
char *trim_spaces(string)
char *string;
{
char *buffer, *p, *q;

buffer = alloc_lbuf("trim_spaces");
p = string;
q = buffer;
while (p && *p && isspace(*p)) /* remove inital spaces */
p++;
while (p && *p) {
while (*p && !isspace(*p)) /* copy nonspace chars */
*q++ = *p++;
while (*p && isspace(*p))
/* compress spaces */
p++;
if (*p)
*q++ = ' '; /* leave one space */
}
*q = '\0';
/* terminate string */
return (buffer);

/*
* --------------------------------------------------------------------------* grabto: Return portion of a string up to the indicated character. Also
* returns a modified pointer to the string ready for another call.
*/
char *grabto(str, targ)
char **str, targ;
{
char *savec, *cp;
if (!str || !*str || !**str)
return NULL;
savec = cp = *str;
while (*cp && *cp != targ)
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741

Saturday, June 16, 2012 11:24 PM

cp++;
if (*cp)
*cp++ = '\0';
*str = cp;
return savec;

int string_compare(s1, s2)


const char *s1, *s2;
{
if (mudstate.standalone || mudconf.space_compress) {
while (isspace(*s1))
s1++;
while (isspace(*s2))
s2++;
while (*s1 && *s2 && ((tolower(*s1) == tolower(*s2)) ||
(isspace(*s1) && isspace(*s2)))) {
if (isspace(*s1) && isspace(*s2)) { /* skip all
* other spaces
*/
while (isspace(*s1))
s1++;
while (isspace(*s2))
s2++;
} else {
s1++;
s2++;
}
}
if ((*s1) && (*s2))
return (1);
if (isspace(*s1)) {
while (isspace(*s1))
s1++;
return (*s1);
}
if (isspace(*s2)) {
while (isspace(*s2))
s2++;
return (*s2);
}
if ((*s1) || (*s2))
return (1);
return (0);
} else {
while (*s1 && *s2 && tolower(*s1) == tolower(*s2))
s1++, s2++;

return (tolower(*s1) - tolower(*s2));

int string_prefix(string, prefix)


-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794

Saturday, June 16, 2012 11:24 PM

const char *string, *prefix;


{
int count = 0;

while (*string && *prefix && tolower(*string) == tolower(*prefix))


string++, prefix++, count++;
if (*prefix == '\0')
/* Matched all of prefix */
return (count);
else
return (0);

/*
* accepts only nonempty matches starting at the beginning of a word
*/
const char *string_match(src, sub)
const char *src, *sub;
{
if ((*sub != '\0') && (src)) {
while (*src) {
if (string_prefix(src, sub))
return src;
/* else scan to beginning of next word */
while (*src && isalnum(*src))
src++;
while (*src && !isalnum(*src))
src++;
}
}
return 0;
}
/*
* --------------------------------------------------------------------------* replace_string: Returns an lbuf containing string STRING with all occurances
* of OLD replaced by NEW. OLD and NEW may be different lengths.
* (mitch 1 feb 91)
*
* edit_string: Like replace_string, but sensitive about ANSI codes, and
* handles special ^ and $ cases.
*/
char *replace_string(old, new, string)
const char *old, *new, *string;
{
char *result, *r, *s;
int olen;
if (string == NULL)
return NULL;
s = (char *)string;
olen = strlen(old);
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

Saturday, June 16, 2012 11:24 PM

r = result = alloc_lbuf("replace_string");
while (*s) {
/* Copy up to the next occurrence of the first char of OLD */
while (*s && *s != *old) {
safe_chr(*s, result, &r);
s++;
}
/*
* If we are really at an OLD, append NEW to the result and
* bump the input string past the occurrence of
* OLD. Otherwise, copy the char and try again.
*/
if (*s) {
if (!strncmp(old, s, olen)) {
safe_str((char *)new, result, &r);
s += olen;
} else {
safe_chr(*s, result, &r);
s++;
}
}

}
*r = '\0';
return result;

void edit_string(src, dst, from, to)


char *src, **dst, *from, *to;
{
char *cp, *p;
int ansi_state, to_ansi_set, to_ansi_clr, tlen, flen;
/* We may have gotten an ANSI_NORMAL termination to OLD and NEW,
* that the user probably didn't intend to be there. (If the
* user really did want it there, he simply has to put a double
* ANSI_NORMAL in; this is non-intuitive but without it we can't
* let users swap one ANSI code for another using this.) Thus,
* we chop off the terminating ANSI_NORMAL on both, if there is
* one.
*/
p = from + strlen(from) - 4;
if (p >= from && !strcmp(p, ANSI_NORMAL))
*p = '\0';
p = to + strlen(to) - 4;
if (p >= to && !strcmp(p, ANSI_NORMAL))
*p = '\0';

-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900

Saturday, June 16, 2012 11:24 PM

/* Scan the contents of the TO string. Figure out whether we


* have any embedded ANSI codes.
*/
ansi_state = ANST_NONE;
track_all_esccodes(to, p, ansi_state);
to_ansi_set = (~ANST_NONE) & ansi_state;
to_ansi_clr = ANST_NONE & (~ansi_state);
tlen = p - to;
/*
* Do the substitution.
*/

Idea for prefix/suffix from R'nice@TinyTIM

cp = *dst = alloc_lbuf("edit_string");
if (!strcmp(from, "^")) {
/*
* Prepend 'to' to string
*/
safe_known_str(to, tlen, *dst, &cp);
safe_copy_tracking(src, p, ansi_state, *dst, &cp);
} else if (!strcmp(from, "$")) {
/*
* Append 'to' to string
*/
ansi_state = ANST_NONE;
safe_copy_tracking(src, p, ansi_state, *dst, &cp);
ansi_state |= to_ansi_set;
ansi_state &= ~to_ansi_clr;
safe_known_str(to, tlen, *dst, &cp);
} else {
/*
* Replace all occurances of 'from' with 'to'.
* special cases of from = \$ and \^.
*/
if (((from[0] == '\\') || (from[0] == '%')) &&
((from[1] == '$') || (from[1] == '^')) &&
(from[2] == '\0'))
from++;
flen = strlen(from);
ansi_state = ANST_NONE;
while (*src) {

-17-

Handle the

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953

Saturday, June 16, 2012 11:24 PM

/* Copy up to the next occurrence of the first


* char of FROM. */
p = src;
while (*src && (*src != *from)) {
if (*src == ESC_CHAR) {
track_esccode(src, ansi_state);
} else {
++src;
}
}
safe_known_str(p, src - p, *dst, &cp);
/* If we are really at a FROM, append TO to the result
* and bump the input string past the occurrence of
* FROM. Otherwise, copy the char and try again.
*/
if (*src) {
if (!strncmp(from, src, flen)) {
/* Apply whatever ANSI transition
* happens in TO */
ansi_state |= to_ansi_set;
ansi_state &= ~to_ansi_clr;

}
}

safe_known_str(to, tlen, *dst, &cp);


src += flen;
} else {
/* We have to handle the case where
* the first character in FROM is the
* ANSI escape character. In that case
* we move over and copy the entire
* ANSI code. Otherwise we just copy
* the character.
*/
if (*from == ESC_CHAR) {
p = src;
track_esccode(src, ansi_state);
safe_known_str(p, src - p,
*dst, &cp);
} else {
safe_chr(*src, *dst, &cp);
++src;
}
}

safe_str(ansi_transition_esccode(ansi_state, ANST_NONE), *dst, &cp);

int minmatch(str, target, min)


-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006

Saturday, June 16, 2012 11:24 PM

char *str, *target;


int min;
{
while (*str && *target && (tolower(*str) == tolower(*target))) {
str++;
target++;
min--;
}
if (*str)
return 0;
if (!*target)
return 1;
return ((min <= 0) ? 1 : 0);
}
/* --------------------------------------------------------------------------* safe_copy_str, safe_copy_long_str, safe_chr_real_fn - Copy buffers,
* watching for overflows.
*/
INLINE void
safe_copy_str(src, buff, bufp, max)
char *src, *buff, **bufp;
int max;
{
char *tp, *maxtp, *longtp;
int n, len;
tp = *bufp;
if (src == NULL) {
*tp = '\0';
return;
}
maxtp = buff + max;
longtp = tp + 7;
maxtp = (maxtp < longtp) ? maxtp : longtp;
while (*src && (tp < maxtp))
*tp++ = *src++;
if (*src == '\0') { /* copied whole src, and tp is at most maxtp */
*tp = '\0';
*bufp = tp;
return;
}
len = strlen(src);
n = max - (tp - buff); /* tp is either maxtp or longtp */
if (n <= 0) {
*tp = '\0';
*bufp = tp;
return;
}
-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059

Saturday, June 16, 2012 11:24 PM

n = ((len < n) ? len : n);


memcpy(tp, src, n);
tp += n;
*tp = '\0';
*bufp = tp;

INLINE int
safe_copy_str_fn(src, buff, bufp, max)
const char *src;
char *buff, **bufp;
int max;
{
char *tp, *maxtp, *longtp;
int n, len;
tp = *bufp;
if (src == NULL) {
*tp = '\0';
return 0;
}
maxtp = buff + max;
longtp = tp + 7;
maxtp = (maxtp < longtp) ? maxtp : longtp;
while (*src && (tp < maxtp))
*tp++ = *src++;
if (*src == '\0') { /* copied whole src, and tp is at most maxtp */
*tp = '\0';
*bufp = tp;
return 0;
}
len = strlen(src);
n = max - (tp - buff); /* tp is either maxtp or longtp */
if (n <= 0) {
len -= (tp - *bufp);
*tp = '\0';
*bufp = tp;
return (len);
}
n = ((len < n) ? len : n);
memcpy(tp, src, n);
tp += n;
*tp = '\0';
*bufp = tp;
}

return (len - n);

int
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112

Saturday, June 16, 2012 11:24 PM

safe_copy_long_str(src, buff, bufp, max)


char *src, *buff, **bufp;
int max;
{
int len, n;
char *tp;
tp = *bufp;
if (src == NULL) {
*tp = '\0';
return 0;
}
len = strlen(src);
n = max - (tp - buff);
if (n < 0)
n = 0;
strncpy (tp, src, n);
buff[max] = '\0';

if (len <= n) {
*bufp = tp + len;
return (0);
} else {
*bufp = tp + n;
return (len-n);
}

INLINE void safe_known_str(src, known, buff, bufp)


const char *src;
char *buff, **bufp;
int known;
{
int n;
char *tp, *maxtp;
tp = *bufp;
if (!src) {
*tp = '\0';
return;
}
maxtp = buff + LBUF_SIZE - 1;
if (known > 7) {
n = maxtp - tp;
if (n <= 0) {
*tp = '\0';
return;
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

Saturday, June 16, 2012 11:24 PM

}
n = ((known < n) ? known : n);
memcpy(tp, src, n);
tp += n;
*tp = '\0';
*bufp = tp;
return;
}
if (tp + known < maxtp)
maxtp = tp + known;
while (*src && (tp < maxtp))
*(tp)++ = *src++;

*tp = '\0';
*bufp = tp;

INLINE int
safe_chr_real_fn(src, buff, bufp, max)
char src, *buff, **bufp;
int max;
{
char *tp;
int retval = 0;
tp = *bufp;
if ((tp - buff) < max) {
*tp++ = src;
*bufp = tp;
*tp = '\0';
} else {
buff[max] = '\0';
retval = 1;
}
}

return retval;

/* --------------------------------------------------------------------------* More utilities.


*/
int matches_exit_from_list(str, pattern)
char *str, *pattern;
{
char *s;
if (*str == '\0')
return 0;

/* never match empty */

while (*pattern) {
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218

Saturday, June 16, 2012 11:24 PM

for (s = str;
/* check out this one */
(*s && (tolower(*s) == tolower(*pattern)) &&
*pattern && (*pattern != EXIT_DELIMITER));
s++, pattern++) ;
/* Did we match it all? */
if (*s == '\0') {
/* Make sure nothing afterwards */
while (*pattern && isspace(*pattern))
pattern++;
/* Did we get it? */
if (!*pattern || (*pattern == EXIT_DELIMITER))
return 1;

}
/* We didn't get it, find next string to test */

while (*pattern && *pattern++ != EXIT_DELIMITER) ;


while (isspace(*pattern))
pattern++;

}
return 0;

int ltos(s, num)


char *s;
long num;
{
/* Mark Vasoll's long int to string converter. */
char buf[20], *p;
unsigned long anum;
p = buf;
/* absolute value */
anum = (num < 0) ? -num : num;
/* build up the digits backwards by successive division */
while (anum > 9) {
*p++ = '0' + (anum % 10);
anum /= 10;
}
/* put in the sign if needed */
if (num < 0)
*s++ = '-';
/* put in the last digit, this makes very fast single digits numbers */
*s++ = '0' + (char)anum;
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271

Saturday, June 16, 2012 11:24 PM

/* reverse the rest of the digits (if any) into the provided buf */
while (p-- > buf)
*s++ = *p;

/* terminate the resulting string */


*s = '\0';
return 0;

INLINE void safe_ltos(s, bufc, num)


char *s;
char **bufc;
long num;
{
/* Mark Vasoll's long int to string converter. */
char buf[20], *p, *tp, *endp;
unsigned long anum;
p = buf;
tp = *bufc;
/* absolute value */
anum = (num < 0) ? -num : num;
/* build up the digits backwards by successive division */
while (anum > 9) {
*p++ = '0' + (anum % 10);
anum /= 10;
}
if (tp > s + LBUF_SIZE - 21) {
endp = s + LBUF_SIZE - 1;
/* put in the sign if needed */
if (num < 0 && (tp < endp))
*tp++ = '-';
/* put in the last digit, this makes very fast single
* digits numbers
*/
if (tp < endp)
*tp++ = '0' + (char)anum;
/* reverse the rest of the digits (if any) into the
* provided buf
*/
while ((p-- > buf) && (tp < endp))
*tp++ = *p;
} else {
if (num < 0)
*tp++ = '-';
*tp++ = '0' + (char)anum;
while (p-- > buf)
-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\stringutil.c

1272
1273
1274
1275
1276
1277
1278
1279

Saturday, June 16, 2012 11:24 PM

*tp++ = *p;

/* terminate the resulting string */


*tp = '\0';
*bufc = tp;

-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:24 PM

/* timer.c - Subroutines for (system-) timed events */


/* $Id: timer.c,v 1.23 2007/09/29 13:04:31 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include

"match.h" /* required by code */


"command.h"
/* required by code */
"powers.h" /* required by code */
"bitstring.h" /* required by code */

extern void NDECL(pool_reset);


extern unsigned int FDECL(alarm, (unsigned int seconds));
extern void NDECL(pcache_trim);
/* --------------------------------------------------------------------------* Cron-related things. This implementation is somewhat derivative of
* Paul Vixie's cron implementation. See bitstring.h for the copyright
* and other details.
*/
#define FIRST_MINUTE
#define LAST_MINUTE
#define MINUTE_COUNT

0
59
(LAST_MINUTE - FIRST_MINUTE + 1)

#define FIRST_HOUR
#define LAST_HOUR
#define HOUR_COUNT

0
23
(LAST_HOUR - FIRST_HOUR + 1)

#define FIRST_DOM
#define LAST_DOM
#define DOM_COUNT

1
31
(LAST_DOM - FIRST_DOM + 1)

#define FIRST_MONTH
#define LAST_MONTH
#define MONTH_COUNT

1
12
(LAST_MONTH - FIRST_MONTH + 1)

/* Note
#define
#define
#define

on DOW: 0 and 7 are both Sunday, for compatibility reasons. */


FIRST_DOW
0
LAST_DOW
7
DOW_COUNT
(LAST_DOW - FIRST_DOW + 1)

#define DOM_STAR

0x01
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

#define DOW_STAR

Saturday, June 16, 2012 11:24 PM

0x02

typedef struct cron_entry CRONTAB;


struct cron_entry {
dbref obj;
int atr;
char *cronstr;
bitstr_t bit_decl(minute, MINUTE_COUNT);
bitstr_t bit_decl(hour, HOUR_COUNT);
bitstr_t bit_decl(dom, DOM_COUNT);
bitstr_t bit_decl(month, MONTH_COUNT);
bitstr_t bit_decl(dow, DOW_COUNT);
int flags;
CRONTAB *next;
};
CRONTAB *cron_head = NULL;
#define set_cronbits(b,l,h,n) \
if (((n) >= (l)) && ((n) <= (h))) bit_set((b), (n) - (l));
static void NDECL(check_cron)
{
struct tm *ltime;
int minute, hour, dom, month, dow;
CRONTAB *crp;
char *cmd;
dbref aowner;
int aflags, alen;
/* Convert our time to a zero basis, so the elements can be used
* as indices.
*/
ltime = localtime(&mudstate.events_counter);
minute = ltime->tm_min - FIRST_MINUTE;
hour = ltime->tm_hour - FIRST_HOUR;
dom = ltime->tm_mday - FIRST_DOM;
month = ltime->tm_mon + 1 - FIRST_MONTH; /* must convert 0-11 to 1-12 */
dow = ltime->tm_wday - FIRST_DOW;
/* Do it if the minute, hour, and month match, plus a day selection
* matches. We handle stars and the day-of-month vs. day-of-week
* exactly like Unix (Vixie) cron does.
*/
for (crp = cron_head; crp != NULL; crp = crp->next) {
if (bit_test(crp->minute, minute) &&
bit_test(crp->hour, hour) &&
bit_test(crp->month, month) &&
(((crp->flags & DOM_STAR) || (crp->flags & DOW_STAR)) ?
(bit_test(crp->dow, dow) && bit_test(crp->dom, dom)) :
(bit_test(crp->dow, dow) || bit_test(crp->dom, dom)))) {
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

}
}

Saturday, June 16, 2012 11:24 PM

cmd = atr_pget(crp->obj, crp->atr, &aowner, &aflags, &alen);


if (*cmd && Good_obj(crp->obj)) {
wait_que(crp->obj, crp->obj, 0, NOTHING, 0, cmd,
(char **) NULL, 0, NULL);
}
free_lbuf(cmd);

static char *parse_cronlist(player, bits, low, high, bufp)


dbref player;
bitstr_t *bits;
int low, high;
char *bufp;
{
int i, n_begin, n_end, step_size;
bit_nclear(bits, 0, (high - low + 1)); /* Default is all off */
if (!bufp || !*bufp)
return NULL;
if (!*bufp)
return NULL;
/* We assume we're at the beginning of what we needed to parse.
* All leading whitespace-skipping should have been taken care of
* either before this function was called, or at the end of this
* function.
*/
while (*bufp && !isspace(*bufp)) {
if (*bufp == '*') {
n_begin = low;
n_end = high;
bufp++;
} else if (isdigit(*bufp)) {
n_begin = atoi(bufp); /* atoi() ignores trailing non-digits */
while (*bufp && isdigit(*bufp))
bufp++;
if (*bufp != '-') {
/* We have a single number, not a range. */
n_end = n_begin;
} else {
/* Eat the dash, get the range. */
bufp++;
n_end = atoi(bufp);
while (*bufp && isdigit(*bufp))
bufp++;
}
} else {
notify(player, tprintf("Cron parse error at: %s", bufp));
return NULL;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:24 PM

}
/* Check for step size. */
if (*bufp == '/') {
bufp++;
/* eat the slash */
step_size = atoi(bufp);
if (step_size < 1) {
notify(player, "Invalid step size.");
return NULL;
}
while (*bufp && isdigit(*bufp))
bufp++;
} else {
step_size = 1;
}
/* Go set it. */
for (i = n_begin; i <= n_end; i += step_size)
set_cronbits(bits, low, high, i);
/* We've made it through one pass. If the next character isn't
* a comma, we break out of this loop.
*/
if (*bufp == ',')
bufp++;
else
break;
}
/* Skip over trailing garbage. */
while (*bufp && !isspace(*bufp))
bufp++;
/* Initially, bufp pointed to the beginning of what we parsed. We have
* to return it so we know where to start the next bit of parsing.
* Skip spaces as well.
*/
while (isspace(*bufp))
bufp++;
}

return bufp;

int call_cron(player, thing, attrib, timestr)


dbref player, thing;
int attrib;
char *timestr;
{
int errcode;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:24 PM

CRONTAB *crp;
char *bufp;
/* Don't allow duplicate entries. */
for (crp = cron_head; crp != NULL; crp = crp->next) {
if ((crp->obj == thing) && (crp->atr == attrib) &&
!strcmp(crp->cronstr, timestr))
return -1;
}
crp = (CRONTAB *) XMALLOC(sizeof(CRONTAB), "cron_entry");
crp->obj = thing;
crp->atr = attrib;
crp->flags = 0;
crp->cronstr = XSTRDUP(timestr, "cron_entry.time");
/* The time string is: <min> <hour> <day of month> <month> <day of week>
* Legal values also include asterisks, and <x>-<y> (for a range).
* We do NOT support step size.
*/
errcode = 0;
bufp = timestr;
while (isspace(*bufp))
bufp++;
bufp = parse_cronlist(player, crp->minute,
FIRST_MINUTE, LAST_MINUTE, bufp);
if (!bufp || !*bufp) {
errcode = 1;
} else {
bufp = parse_cronlist(player, crp->hour, FIRST_HOUR, LAST_HOUR, bufp);
if (!bufp || !*bufp)
errcode = 1;
}
if (!errcode) {
if (*bufp == '*')
crp->flags |= DOM_STAR;
bufp = parse_cronlist(player, crp->dom, FIRST_DOM, LAST_DOM, bufp);
if (!bufp || !*bufp)
errcode = 1;
}
if (!errcode) {
bufp = parse_cronlist(player, crp->month,
FIRST_MONTH, LAST_MONTH, bufp);
if (!bufp || !*bufp)
errcode = 1;
}
if (!errcode) {
if (*bufp == '*')
crp->flags |= DOW_STAR;
bufp = parse_cronlist(player, crp->dow, FIRST_DOW, LAST_DOW, bufp);
}
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:24 PM

/* Sundays can be either 0 or 7. */


if (bit_test(crp->dow, 0))
bit_set(crp->dow, 7);
if (bit_test(crp->dow, 7))
bit_set(crp->dow, 0);
if (errcode) {
XFREE(crp->cronstr, "cron_entry.time");
XFREE(crp, "cron_entry");
return 0;
}
/* Relink the list, now that we know we have something good. */
crp->next = cron_head;
cron_head = crp;
}

return 1;

void do_cron(player, cause, key, objstr, timestr)


dbref player, cause;
int key;
char *objstr, *timestr;
{
dbref thing;
int attrib, retcode;
if (!timestr || !*timestr) {
notify(player, "No times given.");
return;
}
if (!parse_attrib(player, objstr, &thing, &attrib, 0) ||
(attrib == NOTHING) || !Good_obj(thing)) {
notify(player, "No match.");
return;
}
if (!Controls(player, thing)) {
notify(player, NOPERM_MESSAGE);
return;
}
retcode = call_cron(player, thing, attrib, timestr);
if (retcode == 0)
notify(player, "Syntax errors. No cron entry made." );
else if (retcode == -1)
notify(player, "That cron entry already exists." );
else
notify(player, "Cron entry added.");
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:24 PM

}
int cron_clr(thing, attr)
dbref thing;
int attr;
{
CRONTAB *crp, *next, *prev;
int count;

count = 0;
for (crp = cron_head, prev = NULL; crp != NULL; ) {
if ((crp->obj == thing) &&
((attr == NOTHING) || (crp->atr == attr))) {
count++;
next = crp->next;
XFREE(crp->cronstr, "cron_entry.time");
XFREE(crp, "cron_entry");
if (prev)
prev->next = next;
else
cron_head = next;
crp = next;
} else {
prev = crp;
crp = crp->next;
}
}
return count;

void do_crondel(player, cause, key, objstr)


dbref player, cause;
int key;
char *objstr;
{
dbref thing;
int attr, count;
if (!objstr || !*objstr) {
notify(player, "No match.");
return;
}
attr = NOTHING;
if (!parse_attrib(player, objstr, &thing, &attr, 0) ||
(attr == NOTHING)) {
if ((*objstr != '#') ||
((thing = parse_dbref(objstr + 1)) == NOTHING)) {
notify(player, "No match.");
}
}
if (!Controls(player, thing)) {
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:24 PM

notify(player, NOPERM_MESSAGE);
return;
}

count = cron_clr(thing, attr);


notify(player, tprintf("Removed %d cron entries.", count));

void do_crontab(player, cause, key, objstr)


dbref player, cause;
int key;
char *objstr;
{
dbref thing;
int count;
CRONTAB *crp;
char *bufp;
ATTR *ap;
if (objstr && *objstr) {
thing = match_thing(player, objstr);
if (!Good_obj(thing))
return;
if (!Controls(player, thing)) {
notify(player, NOPERM_MESSAGE);
return;
}
} else {
thing = NOTHING;
}
/* List it if it's the thing we want, or, if we didn't specify a
* thing, list things belonging to us (or everything, if we're
* normally entitled to see the entire queue).
*/
count = 0;
for (crp = cron_head; crp != NULL; crp = crp->next) {
if (((thing == NOTHING) &&
((Owner(crp->obj) == player) || See_Queue(player))) ||
(crp->obj == thing)) {
count++;
bufp = unparse_object(player, crp->obj, 0);
ap = atr_num(crp->atr);
if (!ap) {
notify(player,
tprintf("%s has a cron entry that contains bad attribute number %d." ,
bufp, crp->atr));
} else {
notify(player, tprintf("%s/%s: %s", bufp, ap->name,
crp->cronstr));
}
free_lbuf(bufp);
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:24 PM

}
}

notify(player, tprintf("Matched %d cron %s.",


count, (count == 1) ? "entry" : "entries"));

/* --------------------------------------------------------------------------* General timer things.


*/
void NDECL(init_timer)
{
mudstate.now = time(NULL);
mudstate.dump_counter = ((mudconf.dump_offset == 0) ?
mudconf.dump_interval : mudconf.dump_offset) + mudstate.now;
mudstate.check_counter = ((mudconf.check_offset == 0) ?
mudconf.check_interval : mudconf.check_offset) + mudstate.now;
mudstate.idle_counter = mudconf.idle_interval + mudstate.now;
mudstate.mstats_counter = 15 + mudstate.now;
/* The events counter is the next time divisible by sixty (i.e.,
* that puts us at the beginning of a minute).
*/
mudstate.events_counter = mudstate.now + (60 - (mudstate.now % 60));
}

alarm(1);

void NDECL(dispatch)
{
char *cmdsave;
cmdsave = mudstate.debug_cmd;
mudstate.debug_cmd = (char *)"< dispatch >";
/* This routine can be used to poll from interface.c */
if (!mudstate.alarm_triggered)
return;
mudstate.alarm_triggered = 0;
mudstate.now = time(NULL);
do_second();
/* Module API hook */
CALL_ALL_MODULES(do_second, ());
/* Free list reconstruction */
if ((mudconf.control_flags & CF_DBCHECK) &&
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:24 PM

(mudstate.check_counter <= mudstate.now)) {


mudstate.check_counter = mudconf.check_interval + mudstate.now;
mudstate.debug_cmd = (char *)"< dbck >";
do_dbck(NOTHING, NOTHING, 0);
SYNC;
pcache_trim();
pool_reset();

/* Database dump routines */


if ((mudconf.control_flags & CF_CHECKPOINT) &&
(mudstate.dump_counter <= mudstate.now)) {
mudstate.dump_counter = mudconf.dump_interval + mudstate.now;
mudstate.debug_cmd = (char *)"< dump >";
fork_and_dump(0);
}
/* Idle user check */
if ((mudconf.control_flags & CF_IDLECHECK) &&
(mudstate.idle_counter <= mudstate.now)) {
mudstate.idle_counter = mudconf.idle_interval + mudstate.now;
mudstate.debug_cmd = (char *)"< idlecheck >";
check_idle();
}
/* Check for execution of attribute events */
if (mudconf.control_flags & CF_EVENTCHECK) {
if (mudstate.now >= mudstate.events_counter) {
mudstate.debug_cmd = (char *) "< croncheck >";
check_cron();
mudstate.events_counter += 60;
}
}
#if defined(HAVE_GETRUSAGE) && defined(STRUCT_RUSAGE_COMPLETE)
/* Memory use stats */
if (mudstate.mstats_counter <= mudstate.now) {
int curr;
mudstate.mstats_counter = 15 + mudstate.now;
curr = mudstate.mstat_curr;
if (mudstate.now > mudstate.mstat_secs[curr]) {
struct rusage usage;
curr = 1 - curr;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\timer.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574

}
#endif

Saturday, June 16, 2012 11:24 PM

getrusage(RUSAGE_SELF, &usage);
mudstate.mstat_ixrss[curr] = usage.ru_ixrss;
mudstate.mstat_idrss[curr] = usage.ru_idrss;
mudstate.mstat_isrss[curr] = usage.ru_isrss;
mudstate.mstat_secs[curr] = mudstate.now;
mudstate.mstat_curr = curr;

/* reset alarm */

alarm(1);
mudstate.debug_cmd = cmdsave;

/*
* --------------------------------------------------------------------------* * do_timewarp: Adjust various internal timers.
*/
void do_timewarp(player, cause, key, arg)
dbref player, cause;
int key;
char *arg;
{
int secs;
secs = atoi(arg);

if ((key == 0) || (key & TWARP_QUEUE)) /*


* Sem/Wait queues
*/
do_queue(player, cause, QUEUE_WARP, arg);
if (key & TWARP_DUMP)
mudstate.dump_counter -= secs;
if (key & TWARP_CLEAN)
mudstate.check_counter -= secs;
if (key & TWARP_IDLE)
mudstate.idle_counter -= secs;
if (key & TWARP_EVENTS)
mudstate.events_counter -= secs;

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:04 PM

/* udb.h */
/* $Id: udb.h,v 1.25 2003/05/12 00:32:23 dpassmor Exp $ */
#include "copyright.h"
#ifndef __UDB_H
#define __UDB_H
/** Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Margo Seltzer.
*
*
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* Define the number of objects we may be reading/writing to at one time */
#define NUM_OBJPIPES

64

/* For MUSH, an int works great as an object ID


* And attributes are zero terminated strings, so we heave the size out.
* We hand around attribute identifiers in the last things.
*/
typedef char
typedef unsigned int

Attr;
Objname;

typedef struct Aname {


unsigned int
object;
unsigned int
attrnum;
} Aname;
/* In general, we want binary attributes, so we do this. */
typedef struct Attrib {
int attrnum;
/* MUSH specific identifier */
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb.h

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:04 PM

int size;
char
*data;
} Attrib;
/* An object is a name, an attribute count, and a vector of attributes */
/* which Attr's are stowed in a contiguous array pointed at by atrs.
*/
typedef struct Obj {
Objname name;
time_t counter;
int dirty;
int at_count;
Attrib *atrs;
} Obj;
typedef struct cache {
void *keydata;
int keylen;
void *data;
int datalen;
unsigned int type;
unsigned int flags;
struct cache *nxt;
struct cache *prvfree;
struct cache *nxtfree;
} Cache;
typedef struct {
Cache *head;
Cache *tail;
} Chain;
typedef struct {
void *dptr;
int dsize;
} DBData;
/* Cache flags */
#define CACHE_DIRTY 0x00000001
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

int FDECL(cache_init, (int));


void
NDECL(cache_reset);
int NDECL(cache_sync);
DBData
FDECL(db_get, (DBData, unsigned int));
int FDECL(db_put, (DBData, DBData, unsigned int));
int FDECL(db_del, (DBData, unsigned int));
void NDECL(db_lock);
void NDECL(db_unlock);
DBData
FDECL(cache_get, (DBData, unsigned int));
int FDECL(cache_put, (DBData, DBData, unsigned int));
void FDECL(cache_del, (DBData, unsigned int));
void NDECL(attrib_sync);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb.h

107
108
109
110
111
112
113

extern
extern
extern
extern

char
void
void
int

Saturday, June 16, 2012 11:04 PM

*FDECL(pipe_get_attrib, (int, int));


FDECL(pipe_set_attrib, (int, int, char *));
FDECL(pipe_del_attrib, (int, int));
FDECL(obj_siz, (Obj *));

#endif /* __UDB_H */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_defs.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Saturday, June 16, 2012 11:04 PM

/* udb_defs.h - Header file for the UnterMud DB layer, in TinyMUSH 3.0 */


/* $Id: udb_defs.h,v 1.17 2001/08/23 21:44:53 dpassmor Exp $ */
/*
*/

Andrew Molitor, amolitor@eagle.wesleyan.edu


1991

#include "copyright.h"
#ifndef __UDB_DEFS_H
#define __UDB_DEFS_H
/* If your malloc() returns void or char pointers... */
/* typedef void
*mall_t; */
typedef char
*mall_t;
/* default (runtime-resettable) cache parameters */
#define CACHE_SIZE 1000000
#define CACHE_WIDTH 200

/* 1 million bytes */

/* Datatypes that we have in cache and on disk */


#define
#define
#define
#define
#define
#define
#define

DBTYPE_EMPTY
DBTYPE_ATTRIBUTE
DBTYPE_DBINFO
DBTYPE_OBJECT
DBTYPE_ATRNUM
DBTYPE_MODULETYPE
DBTYPE_RESERVED

#define DBTYPE_END

0
/* This entry is empty */
1
/* This is an attribute */
2
/* Various DB paramaters */
3
/* Object structure */
4
/* Attribute number to name map */
5
/* DBTYPE to module name map */
0x0000FFFF /* Numbers >= are free for
* use by user code (modules) */
0xFFFFFFFF /* Highest type */

#endif /* __UDB_DEFS_H */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_misc.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:23 PM

/* udb_misc.c - Misc support routines for unter style error management. */


/* $Id: udb_misc.c,v 1.14 2006/11/10 20:53:20 tyrspace Exp $ */
/*
* Stolen from mjr.
*
* Andrew Molitor, amolitor@eagle.wesleyan.edu
*/
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
/*
* Log database errors
*/
void log_db_err(obj, attr, txt)
int obj, attr;
const char *txt;
{
if (!mudstate.standalone) {
STARTLOG(LOG_ALWAYS, "DBM", "ERROR")
log_printf("Could not %s object #%d", txt, obj);
if (attr != NOTHING) {
log_printf(" attr #%d", attr);
}
ENDLOG
} else {
fprintf(mainlog_fp, "Could not %s object #%d", txt, obj);
if (attr != NOTHING) {
fprintf(mainlog_fp, " attr #%d", attr);
}
fprintf(mainlog_fp, "\n");
}
}
/*
* print a series of warnings - do not exit
*/
/*
* VARARGS
*/
#if defined(__STDC__) && defined(STDC_HEADERS)
void warning(char *p,...)
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_misc.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:23 PM

#else
void warning(va_alist)
va_dcl
#endif
{

va_list ap;

#if defined(__STDC__) && defined(STDC_HEADERS)


va_start(ap, p);
#else
char *p;
va_start(ap);
p = va_arg(ap, char *);
#endif
while (1) {
if (p == (char *)0)
break;
if (p == (char *)-1)
p = (char *) strerror(errno);
(void)fprintf(mainlog_fp, "%s", p);
p = va_arg(ap, char *);

}
va_end(ap);

/*
* print a series of warnings - exit
*/
/*
* VARARGS
*/
#if defined(__STDC__) && defined(STDC_HEADERS)
void fatal(char *p,...)
#else
void fatal(va_alist)
va_dcl
#endif
{
va_list ap;
#if defined(__STDC__) && defined(STDC_HEADERS)
va_start(ap, p);
#else
char *p;
va_start(ap);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_misc.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

Saturday, June 16, 2012 11:23 PM

p = va_arg(ap, char *);


#endif
while (1) {
if (p == (char *)0)
break;
if (p == (char *)-1)
p = (char *) strerror(errno);
(void)fprintf(mainlog_fp, "%s", p);
p = va_arg(ap, char *);

}
va_end(ap);
exit(1);

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:23 PM

/* udb_obj.c - Binary object handling gear. */


/* $Id: udb_obj.c,v 1.22 2002/03/31 06:07:26 dpassmor Exp $ */
/* Originally written by Andrew Molitor, amolitor@nmsu.edu 1992 */
/*
*
*
*
*
*
*
*

Why not just write the attributes individually to disk? Well, when you're
running on a platform that does synchronous writes with a large database,
thousands of I/O operations tend to be expensive. When you 'coalesce'
many attribute writes onto a single object and do only one I/O operation,
you can get an order of magnitude speed difference, especially on
loading/unloading to flatfile. It also has the side effect of
pre-fetching on reads, since you often have sequential attribute reads
off of the same object. */

#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h"
"flags.h"
"htab.h"
"mudconf.h"

/*
/*
/*
/*

required
required
required
required

by
by
by
by

mudconf */
mudconf */
mudconf */
code */

#include "db.h"
#include "externs.h"

/* required by externs */
/* required by code */

#include "udb.h"

/* required by code */

/* Sizes, on disk, of Object and (within the object) Attribute headers */


#define OBJ_HEADER_SIZE
#define ATTR_HEADER_SIZE

(sizeof(Objname) + sizeof(int))
(sizeof(int) * 2)

/* Take a chunk of data which contains an object, and parse it into an


* object structure. */
Obj *unroll_obj(data)
char *data;
{
int i, j;
Obj *o;
Attrib *a;
char *dptr;
dptr = data;
/* Get a new Obj struct */
if ((o = (Obj *) XMALLOC(sizeof(Obj), "unroll_obj.o")) == NULL)
return (NULL);
/* Read in the header */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:23 PM

if (memcpy((void *)&(o->name), (void *)dptr, sizeof(Objname)) == NULL) {


XFREE(o, "unroll_obj.o");
return (NULL);
}
dptr += sizeof(Objname);
if (memcpy((void *)&i, (void *)dptr, sizeof(int)) == NULL) {
XFREE(o, "unroll_obj.o");
return (NULL);
}
dptr += sizeof(int);
o->at_count = i;
/* Now get an array of Attrs */
a = o->atrs = (Attrib *) XMALLOC(i * sizeof(Attrib), "unroll_obj.a");
if (!o->atrs) {
XFREE(o, "unroll_obj.o");
return (NULL);
}
/* Now go get the attrs, one at a time. */
for (j = 0; j < i;) {
/* Attribute size */
if (memcpy((void *)&(a[j].size), (void *)dptr, sizeof(int)) == NULL)
goto bail;
dptr += sizeof(int);
/* Attribute number */
if (memcpy((void *)&(a[j].attrnum), (void *)dptr, sizeof(int)) == NULL)
goto bail;
dptr += sizeof(int);
/* get some memory for the data */
if ((a[j].data = (char *)XMALLOC(a[j].size, "unroll_obj.data")) == NULL)
goto bail;
/* Preincrement j, so we know how many to free if this next
* bit fails. */
j++;
/* Now get the data */
if (memcpy((void *)a[j - 1].data, (void *)dptr, a[j - 1].size) == NULL)
goto bail;
dptr += a[j - 1].size;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:23 PM

}
/* Should be all done... */
o->dirty = 0;
return (o);
/* Oh shit. We gotta free up all these little bits of memory. */
bail:
/* j points one attribute *beyond* what we need to free up */
for (i = 0; i < j; i++)
XFREE(a[i].data, "unroll_obj.data");
XFREE(a, "unroll_obj.a");
XFREE(o, "unroll_obj.o");
}

return (NULL);

/* Rollup an object structure into a single buffer for a write to disk. */


char *rollup_obj(o)
Obj *o;
{
int i;
Attrib *a;
char *dptr, *data;
dptr = data = (char *)XMALLOC(obj_siz(o), "rollup_obj.data");
/* Mark the object as clean */
o->dirty = 0;
/* Write out the object header */
if (memcpy((void *)dptr, (void *)&(o->name), sizeof(Objname)) == NULL)
return NULL;
dptr += sizeof(Objname);
if (memcpy((void *)dptr, (void *)&(o->at_count), sizeof(int)) == NULL)
return NULL;
dptr += sizeof(int);
/* Now do the attributes, one at a time. */
a = o->atrs;
for (i = 0; i < o->at_count; i++) {
/* Attribute size. */

-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:23 PM

if (memcpy((void *)dptr, (void *)&(a[i].size), sizeof(int)) == NULL)


return NULL;
dptr += sizeof(int);
/* Attribute number */
if (memcpy((void *)dptr, (void *)&(a[i].attrnum), sizeof(int)) == NULL)
return NULL;
dptr += sizeof(int);
/* Attribute data */

if (memcpy((void *)dptr, (void *)a[i].data, a[i].size) == NULL)


return NULL;
dptr += a[i].size;

/* That's all she wrote. */


}

return data;

/* Return the size, on disk, the thing is going to take up.*/


int obj_siz(o)
Obj *o;
{
int i;
int siz;
siz = OBJ_HEADER_SIZE;
for (i = 0; i < o->at_count; i++)
siz += (((o->atrs)[i]).size + ATTR_HEADER_SIZE);
}

return (siz);

/* And something to free all the goo on an Obj, as well as the Obj.*/
static void objfree(o)
Obj *o;
{
int i;
Attrib *a;
if (!o->atrs) {
XFREE(o, "objfree.o");
return;
}
a = o->atrs;
for (i = 0; i < o->at_count; i++) {
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:23 PM

XFREE(a[i].data, "objfree.data");

XFREE(a, "objfree.a");
XFREE(o, "objfree.o");

/* Routines to manipulate attributes within the object structure */


char *obj_get_attrib(anam, obj)
int anam;
Obj *obj;
{
int lo, mid, hi;
Attrib *a;
/* Binary search for the attribute */

lo = 0;
hi = obj->at_count - 1;
a = obj->atrs;
while (lo <= hi) {
mid = ((hi - lo) >> 1) + lo;
if (a[mid].attrnum == anam) {
return (char *) a[mid].data;
break;
} else if (a[mid].attrnum > anam) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return (NULL);

void obj_set_attrib(anam, obj, value)


int anam;
Obj *obj;
char *value;
{
int hi, lo, mid;
Attrib *a;
/* Demands made elsewhere insist that we cope with the case of an
* empty object. */
if (obj->atrs == NULL) {
a = (Attrib *) XMALLOC(sizeof(Attrib), "obj_set_attrib.a");
obj->atrs = a;
obj->at_count = 1;
a[0].attrnum = anam;
a[0].data = (char *)value;
a[0].size = strlen(value) + 1;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:23 PM

return;

/* Binary search for the attribute. */


lo = 0;
hi = obj->at_count - 1;
a = obj->atrs;
while (lo <= hi) {
mid = ((hi - lo) >> 1) + lo;
if (a[mid].attrnum == anam) {
XFREE(a[mid].data, "obj_set_attrib");
a[mid].data = (char *)value;
a[mid].size = strlen(value) + 1;
return;
} else if (a[mid].attrnum > anam) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
/* If we got here, we didn't find it, so lo = hi + 1, and the
* attribute should be inserted between them. */
a = (Attrib *) XREALLOC(obj->atrs,
(obj->at_count + 1) * sizeof(Attrib), "obj_set_attrib.a");
/* Move the stuff upwards one slot. */
if (lo < obj->at_count)
memmove((void *)(a + lo + 1), (void *)(a + lo),
(obj->at_count - lo) * sizeof(Attrib));

a[lo].data = value;
a[lo].attrnum = anam;
a[lo].size = strlen(value) + 1;
obj->at_count++;
obj->atrs = a;

void obj_del_attrib(anam, obj)


int anam;
Obj *obj;
{
int hi, lo, mid;
Attrib *a;
if (!obj->at_count || !obj->atrs)
return;
if (obj->at_count < 0)
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:23 PM

abort();
/* Binary search for the attribute. */
lo = 0;
hi = obj->at_count - 1;
a = obj->atrs;
while (lo <= hi) {
mid = ((hi - lo) >> 1) + lo;
if (a[mid].attrnum == anam) {
XFREE(a[mid].data, "obj_del_attrib.data");
obj->at_count--;
if (mid != obj->at_count)
memcpy((void *)(a + mid), (void *)(a + mid + 1),
(obj->at_count - mid) * sizeof(Attrib));

}
/*
*
*
*

if (obj->at_count == 0) {
XFREE(obj->atrs, "del_attrib.atrs");
obj->atrs = NULL;
}
return;
} else if (a[mid].attrnum > anam) {
hi = mid - 1;
} else {
lo = mid + 1;
}

Now let's define the functions that the cache actually uses. These
'pipeline' attribute writes using a pair of object structures. When
the object which is being read or written to changes, we have to
dump the current object, and bring in the new one. */

/* get_free_objpipe: return an object pipeline */


Obj *get_free_objpipe(obj)
int obj;
{
DBData key, data;
int i, j = 0;
/* Try to see if it's already in a pipeline first */
for (i = 0; i < NUM_OBJPIPES; i++) {
if (mudstate.objpipes[i] &&
mudstate.objpipes[i]->name == obj) {
mudstate.objpipes[i]->counter = mudstate.objc;
mudstate.objc++;
return mudstate.objpipes[i];
}
}

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:23 PM

/* Look for an empty pipeline */


for (i = 0; i < NUM_OBJPIPES; i++) {
if (!mudstate.objpipes[i]) {
/* If there's no object there, read one in */
key.dptr = &obj;
key.dsize = sizeof(int);
data = db_get(key, DBTYPE_ATTRIBUTE);
if (data.dptr) {
mudstate.objpipes[i] = unroll_obj(data.dptr);
XFREE(data.dptr, "get_free_objpipe");
} else {
/* New object */
if ((mudstate.objpipes[i] = (Obj *) XMALLOC(sizeof(Obj),
"unroll_obj.o")) == NULL)
return (NULL);
mudstate.objpipes[i]->name = obj;
mudstate.objpipes[i]->at_count = 0;
mudstate.objpipes[i]->dirty = 0;
mudstate.objpipes[i]->atrs = NULL;
}
mudstate.objpipes[i]->counter = mudstate.objc;
mudstate.objc++;
return mudstate.objpipes[i];

}
if (mudstate.objpipes[i]->counter <
mudstate.objpipes[j]->counter) {
j = i;
}
}

/* We got here, so we have to push the oldest object out. If it's


* dirty, write it first */
if (mudstate.objpipes[j]->dirty) {
data.dptr = rollup_obj(mudstate.objpipes[j]);
data.dsize = obj_siz(mudstate.objpipes[j]);
key.dptr = &mudstate.objpipes[j]->name;
key.dsize = sizeof(int);
db_lock();
db_put(key, data, DBTYPE_ATTRIBUTE);
db_unlock();
XFREE(data.dptr, "get_free_objpipe.2");
}
objfree(mudstate.objpipes[j]);
/* Bring in the object from disk if it exists there */
key.dptr = &obj;
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:23 PM

key.dsize = sizeof(int);
data = db_get(key, DBTYPE_ATTRIBUTE);
if (data.dptr) {
mudstate.objpipes[j] = unroll_obj(data.dptr);
XFREE(data.dptr, "get_free_objpipe.3");
if (mudstate.objpipes[j] == NULL) {
STARTLOG(LOG_PROBLEMS, "ERR", "CACHE")
log_printf("Null returned on unroll of object #%d" , j);
ENDLOG
return (NULL);
}
} else {
/* New object */
if ((mudstate.objpipes[j] = (Obj *) XMALLOC(sizeof(Obj),
"unroll_obj.o")) == NULL)
return (NULL);
mudstate.objpipes[j]->name = obj;
mudstate.objpipes[j]->at_count = 0;
mudstate.objpipes[j]->dirty = 0;
mudstate.objpipes[j]->atrs = NULL;
}

mudstate.objpipes[j]->counter = mudstate.objc;
mudstate.objc++;
return mudstate.objpipes[j];

char *pipe_get_attrib(anum, obj)


int anum;
int obj;
{
Obj *object;
char *value, *tmp;

object = get_free_objpipe(obj);
value = obj_get_attrib(anum, object);
if (value) {
tmp = XSTRDUP(value, "pipe_get_attrib");
return tmp;
} else {
return NULL;
}

void pipe_set_attrib(anum, obj, value)


int anum;
int obj;
char *value;
{
Obj *object;
char *newvalue;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_obj.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522

Saturday, June 16, 2012 11:23 PM

/* Write the damn thing */

object = get_free_objpipe(obj);
object->dirty = 1;
newvalue = XSTRDUP(value, "pipe_set_attrib");
obj_set_attrib(anum, object, newvalue);
return;

void pipe_del_attrib(anum, obj)


int anum;
int obj;
{
Obj *object;
/* Write the damn thing */

object = get_free_objpipe(obj);
object->dirty = 1;
obj_del_attrib(anum, object);
return;

void attrib_sync()
{
DBData key, data;
int i;
/* Make sure dirty objects are written to disk */

for (i = 0; i < NUM_OBJPIPES; i++) {


if (mudstate.objpipes[i] &&
mudstate.objpipes[i]->dirty) {
data.dptr = rollup_obj(mudstate.objpipes[i]);
data.dsize = obj_siz(mudstate.objpipes[i]);
key.dptr = &mudstate.objpipes[i]->name;
key.dsize = sizeof(int);
db_put(key, data, DBTYPE_ATTRIBUTE);
XFREE(data.dptr, "attrib_sync.1");
mudstate.objpipes[i]->dirty = 0;
}
}

-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:23 PM

/* udb_ocache.c - LRU caching */


/* $Id: udb_ocache.c,v 1.81 2006/11/10 20:53:20 tyrspace Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include
#include
#include
#include

"db.h"
/* required by externs */
"externs.h"
/* required by code */
"udb_defs.h"
/* required by code */
"ansi.h"
/* required by code */

extern
extern
extern
extern

void
void
void
void

VDECL(warning, (char *, ...));


VDECL(fatal, (char *, ...));
FDECL(log_db_err, (int, int, const char *));
FDECL(dddb_setsync, (int));

extern void FDECL(raw_notify, (dbref, const char *));


#define NAMECMP(a,b,c,d,e)

((d == e) && !memcmp(a,b,c))

#define DEQUEUE(q, e)
if(e->nxt == (Cache *)0) { \
if (prv != (Cache *)0) { \
prv->nxt = (Cache *)0; \
} \
q->tail = prv; \
} \
if(prv == (Cache *)0) { \
q->head = e->nxt; \
} else \
prv->nxt = e->nxt;
#define INSHEAD(q, e)
if (q->head == (Cache *)0) { \
q->tail = e; \
e->nxt = (Cache *)0; \
} else { \
e->nxt = q->head; \
} \
q->head = e;
#define INSTAIL(q, e)
if (q->head == (Cache *)0) { \
q->head = e; \
} else { \
q->tail->nxt = e; \
} \
q->tail = e; \
e->nxt = (Cache *)0;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:23 PM

#define F_DEQUEUE(q, e) if(e->nxtfree == (Cache *)0) { \


if (e->prvfree != (Cache *)0) { \
e->prvfree->nxtfree = (Cache *)0; \
} \
q->tail = e->prvfree; \
} \
if(e->prvfree == (Cache *)0) { \
q->head = e->nxtfree; \
if (e->nxtfree) \
e->nxtfree->prvfree = (Cache *) 0; \
} else { \
e->prvfree->nxtfree = e->nxtfree; \
if (e->nxtfree) \
e->nxtfree->prvfree = e->prvfree; \
}
#define F_INSHEAD(q, e) if (q->head == (Cache *)0) { \
q->tail = e; \
e->nxtfree = (Cache *)0; \
} else { \
e->nxtfree = q->head; \
e->nxtfree->prvfree = e; \
} \
e->prvfree = (Cache *)0; \
q->head = e;
#define F_INSTAIL(q, e) if (q->head == (Cache *)0) { \
q->head = e; \
} else { \
q->tail->nxtfree = e; \
} \
e->prvfree = q->tail; \
q->tail = e; \
e->nxtfree = (Cache *)0;
static Cache * FDECL(get_free_entry, (int));
static int
FDECL(cache_write, (Cache *));
/* initial settings for cache sizes */
static int cwidth = CACHE_WIDTH;
/* sys_c points to all cache lists */
Chain *sys_c;
/* freelist points to an alternate linked list kept in LRU order */
Chain *freelist;
static int cache_initted = 0;
static int cache_frozen = 0;

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:23 PM

/* cache stats */
time_t cs_ltime;
int cs_writes = 0;
int cs_reads = 0;
int cs_dbreads = 0;
int cs_dbwrites = 0;
int cs_dels = 0;
int cs_checks = 0;
int cs_rhits = 0;
int cs_ahits = 0;
int cs_whits = 0;
int cs_fails = 0;
int cs_syncs = 0;
int cs_size = 0;

/* total writes */
/* total reads */
/* total read-throughs */
/* total write-throughs */
/* total deletes */
/* total checks */
/* total reads filled from cache */
/* total reads filled active cache */
/* total writes to dirty cache */
/* attempts to grab nonexistent */
/* total cache syncs */
/* total cache size */

int cachehash(keydata, keylen, type)


void *keydata;
int keylen;
unsigned int type;
{
unsigned int hash = 0;
char *sp;

if (keydata == NULL)
return 0;
for (sp = (char *)keydata; (sp - (char *)keydata) < keylen; sp++)
hash = (hash << 5) + hash + *sp;
return ((hash + type) % cwidth);

void cache_repl(cp, new, len, type, flags)


Cache *cp;
void *new;
int len;
unsigned int type;
unsigned int flags;
{
cs_size -= cp->datalen;
if (cp->data != NULL)
RAW_FREE(cp->data, "cache_repl");
cp->data = new;
cp->datalen = len;
cp->type = type;
cp->flags = flags;
cs_size += cp->datalen;
}
int cache_init(width)
int width;
{
int x;
Chain *sp;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:23 PM

static char *ncmsg = "cache_init: cannot allocate cache: " ;


if (cache_initted || sys_c != (Chain *) 0)
return (0);
/* If width is specified as non-zero, change it to that,
* otherwise use default. */
if (width)
cwidth = width;
sp = sys_c = (Chain *) RAW_MALLOC((unsigned)cwidth * sizeof(Chain), "cache_init");
if (sys_c == (Chain *) 0) {
warning(ncmsg, (char *)-1, "\n", (char *)0);
return (-1);
}
freelist = (Chain *) RAW_MALLOC(sizeof(Chain), "cache_init");
/* Allocate the initial cache entries */
for (x = 0; x < cwidth; x++, sp++) {
sp->head = (Cache *) 0;
sp->tail = (Cache *) 0;
}
/* Init the LRU freelist */
freelist->head = (Cache *) 0;
freelist->tail = (Cache *) 0;
/* Initialize the object pipelines */
for (x = 0; x < NUM_OBJPIPES; x++) {
mudstate.objpipes[x] = NULL;
}
/* Initialize the object access counter */
mudstate.objc = 0;
/* mark caching system live */
cache_initted++;
cs_ltime = time(NULL);
}

return (0);

void cache_reset()
{
int x;
Cache *cp, *nxt;
Chain *sp;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:23 PM

DBData key, data;


/* Clear the cache after startup and reset stats */
db_lock();
for (x = 0; x < cwidth; x++, sp++) {
sp = &sys_c[x];
/* traverse the chain */
for (cp = sp->head; cp != NULL; cp = nxt) {
nxt = cp->nxt;
if (cp->flags & CACHE_DIRTY) {
if (cp->data == NULL) {
switch(cp->type) {
case DBTYPE_ATTRIBUTE:
pipe_del_attrib(((Aname *)cp->keydata)->attrnum,
((Aname *)cp->keydata)->object);
break;
default:
key.dptr = cp->keydata;
key.dsize = cp->keylen;
db_del(key, cp->type);
}
cs_dels++;
} else {
switch(cp->type) {
case DBTYPE_ATTRIBUTE:
pipe_set_attrib(((Aname *)cp->keydata)->attrnum,
((Aname *)cp->keydata)->object,
(char *)cp->data);
break;
default:
key.dptr = cp->keydata;
key.dsize = cp->keylen;
data.dptr = cp->data;
data.dsize = cp->datalen;
db_put(key, data, cp->type);
}
cs_dbwrites++;
}
}

cache_repl(cp, NULL, 0, DBTYPE_EMPTY, 0);


RAW_FREE(cp->keydata, "cache_get");
RAW_FREE(cp, "get_free_entry");

sp->head = (Cache *) 0;
sp->tail = (Cache *) 0;

}
freelist->head = (Cache *) 0;
freelist->tail = (Cache *) 0;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:23 PM

db_unlock();
/* Clear the counters after startup, or they'll be skewed */

cs_writes = 0;
cs_reads = 0;
cs_dbreads = 0;
cs_dbwrites = 0;
cs_dels = 0;
cs_checks = 0;
cs_rhits = 0;
cs_ahits = 0;
cs_whits = 0;
cs_fails = 0;
cs_syncs = 0;
cs_size = 0;

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

total writes */
total reads */
total read-throughs */
total write-throughs */
total deletes */
total checks */
total reads filled from cache */
total reads filled active cache */
total writes to dirty cache */
attempts to grab nonexistent */
total cache syncs */
size of cache in bytes */

/* list dbrefs of objects in the cache. */


void list_cached_objs(player)
dbref player;
{
Chain *sp;
Cache *cp;
int x;
int aco, maco, asize, msize, oco, moco;
int *count_array, *size_array;
aco = maco = asize = msize = oco = moco = 0;
count_array = (int *) XCALLOC(mudstate.db_top, sizeof(int),
"list_cached_objs.count");
size_array = (int *) XCALLOC(mudstate.db_top, sizeof(int),
"list_cached_objs.size");
for (x = 0, sp = sys_c; x < cwidth; x++, sp++) {
for (cp = sp->head; cp != NULL; cp = cp->nxt) {
if (cp->data && (cp->type == DBTYPE_ATTRIBUTE) &&
!(cp->flags & CACHE_DIRTY)) {
aco++;
asize += cp->datalen;
count_array[((Aname *)cp->keydata)->object] += 1;
size_array[((Aname *)cp->keydata)->object] += cp->datalen;
}
}
}
raw_notify(player, "Active Cache:");
raw_notify(player,
"Name
-6-

Dbref

Attrs

Size" );

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

Saturday, June 16, 2012 11:23 PM

raw_notify(player,
"========================================================" );
for (x = 0; x < mudstate.db_top; x++) {
if (count_array[x] > 0) {
raw_notify(player,
tprintf("%-30.30s #%-6d %5d %8d",
strip_ansi(Name(x)), x, count_array[x], size_array[x]));
oco++;
count_array[x] = 0;
size_array[x] = 0;
}
}
raw_notify(player, "\nModified Active Cache:");
raw_notify(player,
"Name
Dbref
Attrs
Size" );
raw_notify(player,
"========================================================" );
for (x = 0, sp = sys_c; x < cwidth; x++, sp++) {
for (cp = sp->head; cp != NULL; cp = cp->nxt) {
if (cp->data && (cp->type == DBTYPE_ATTRIBUTE) &&
(cp->flags & CACHE_DIRTY)) {
maco++;
msize += cp->datalen;
count_array[((Aname *)cp->keydata)->object] += 1;
size_array[((Aname *)cp->keydata)->object] += cp->datalen;
}
}
}
for (x = 0; x < mudstate.db_top; x++) {
if (count_array[x] > 0) {
raw_notify(player,
tprintf("%-30.30s #%-6d %5d %8d",
strip_ansi(Name(x)), x, count_array[x], size_array[x]));
moco++;
}
}
raw_notify(player,
tprintf("\nTotals: active %d (%d attrs), modified active %d (%d attrs),
total attrs %d", oco, aco, moco, maco, aco + maco));
raw_notify(player,
tprintf("Size: active %d bytes, modified active %d bytes" , asize, msize));

XFREE(count_array, "list_cached_objs.count");
XFREE(size_array, "list_cached_objs.size");

void list_cached_attrs(player)
dbref player;
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417

Saturday, June 16, 2012 11:23 PM

Chain *sp;
Cache *cp;
int x;
int aco, maco, asize, msize;
ATTR *atr;
aco = maco = asize = msize = 0;
raw_notify(player, "Active Cache:");
raw_notify(player, "Name
Attribute
Size");
raw_notify(player,
"====================================================================" );

Dbref

for (x = 0, sp = sys_c; x < cwidth; x++, sp++) {


for (cp = sp->head; cp != NULL; cp = cp->nxt) {
if (cp->data && (cp->type == DBTYPE_ATTRIBUTE) &&
!(cp->flags & CACHE_DIRTY)) {
aco++;
asize += cp->datalen;
atr = atr_num(((Aname *)cp->keydata)->attrnum);
raw_notify(player,
tprintf("%-23.23s %-31.31s #%-6d %6d" , PureName(((Aname *)cp->keydata)->
object),
(atr ? atr->name : "(Unknown)"), ((Aname *)cp->keydata)->object,
cp->datalen));
}
}
}
raw_notify(player, "\nModified Active Cache:");
raw_notify(player, "Name
Attribute
Size");
raw_notify(player,
"====================================================================" );

Dbref

for (x = 0, sp = sys_c; x < cwidth; x++, sp++) {


for (cp = sp->head; cp != NULL; cp = cp->nxt) {
if (cp->data && (cp->type == DBTYPE_ATTRIBUTE) &&
(cp->flags & CACHE_DIRTY)) {
maco++;
msize += cp->datalen;
atr = atr_num(((Aname *)cp->keydata)->attrnum);
raw_notify(player,
tprintf("%-23.23s %-31.31s #%-6d %6d" , PureName(((Aname *)cp->keydata)->
object),
(atr ? atr->name : "(Unknown)"), ((Aname *)cp->keydata)->object,
cp->datalen));
}
}
}

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

Saturday, June 16, 2012 11:23 PM

raw_notify(player,
tprintf("\nTotals: active %d, modified active %d, total attributes %d" ,
aco, maco, aco + maco));
raw_notify(player,
tprintf("Size: active %d bytes, modified active %d bytes" , asize, msize));

/* Search the cache for an entry of a specific type, if found, copy the data
* and length into pointers provided by the caller, if not, fetch from DB.
* You do not need to free data returned by this call. */
DBData cache_get(key, type)
DBData key;
unsigned int type;
{
Cache *cp;
Chain *sp;
int hv = 0;
DBData data;
#ifdef MEMORY_BASED
char *cdata;
#endif
if (!key.dptr || !cache_initted) {
data.dptr = NULL;
data.dsize = 0;
return data;
}
/*
*
*
*

If we're dumping, ignore stats - activity during a dump skews the


working set. We make sure in get_free_entry that any activity
resulting from a dump does not push out entries that are already
in the cache */

#ifndef MEMORY_BASED
if (!mudstate.standalone && !mudstate.dumping)
cs_reads++;
#endif
#ifdef MEMORY_BASED
if (type == DBTYPE_ATTRIBUTE)
goto skipcacheget;
#endif
hv = cachehash(key.dptr, key.dsize, type);
sp = &sys_c[hv];
for (cp = sp->head; cp != NULL; cp = cp->nxt) {
if (NAMECMP(key.dptr, cp->keydata, key.dsize, type, cp->type)) {
if (!mudstate.standalone && !mudstate.dumping) {
cs_rhits++;
cs_ahits++;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522

Saturday, June 16, 2012 11:23 PM

}
F_DEQUEUE(freelist, cp);
F_INSTAIL(freelist, cp);
data.dptr = cp->data;
data.dsize = cp->datalen;

return data;

#ifdef MEMORY_BASED
skipcacheget:
#endif
/* DARN IT - at this point we have a certified, type-A cache miss */
/* Grab the data from wherever */
switch(type) {
case DBTYPE_ATTRIBUTE:
#ifdef MEMORY_BASED
cdata = obj_get_attrib(((Aname *)key.dptr)->attrnum,
&(db[((Aname *)key.dptr)->object].attrtext));
if (cdata) {
data.dptr = cdata;
data.dsize = strlen(cdata) + 1;
return data;
}
#endif
data.dptr = (void *)pipe_get_attrib(((Aname *)key.dptr)->attrnum,
((Aname *)key.dptr)->object);
if (data.dptr == NULL) {
data.dsize = 0;
} else {
data.dsize = strlen(data.dptr) + 1;
}
#ifdef MEMORY_BASED
if (!mudstate.standalone && !mudstate.dumping)
cs_dbreads++;
if (data.dptr) {
data.dsize = strlen(data.dptr) + 1;
cdata = XMALLOC(data.dsize, "cache_get.membased");
memcpy((void *)cdata, (void *)data.dptr, data.dsize);
obj_set_attrib(((Aname *)key.dptr)->attrnum,
&(db[((Aname *)key.dptr)->object].attrtext),
cdata);
data.dptr = cdata;
return data;
} else {
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575

#endif

Saturday, June 16, 2012 11:23 PM

data.dptr = NULL;
data.dsize = 0;
return data;

break;
default:
data = db_get(key, type);
}
if (!mudstate.standalone && !mudstate.dumping)
cs_dbreads++;
if (data.dptr == NULL) {
return data;
}
if ((cp = get_free_entry(data.dsize)) == NULL) {
return data;
}
cp->keydata = (void *)RAW_MALLOC(key.dsize, "cache_get");
memcpy(cp->keydata, key.dptr, key.dsize);
cp->keylen = key.dsize;
cp->data = data.dptr;
cp->datalen = data.dsize;
cp->type = type;
cp->flags = 0;
/* If we're dumping, we'll put everything we fetch that is not
already in cache at the end of the chain and set its last
referenced time to zero. This will ensure that we won't blow away
what's already in cache, since get_free_entry will just reuse
these entries. */
cs_size += cp->datalen;
if (mudstate.dumping) {
/* Link at head of chain */
INSHEAD(sp, cp);
/* Link at head of LRU freelist */
F_INSHEAD(freelist, cp);
} else {
/* Link at tail of chain */
INSTAIL(sp, cp);
/* Link at tail of LRU freelist */
F_INSTAIL(freelist, cp);
}

return data;

-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628

Saturday, June 16, 2012 11:23 PM

/*
* put an attribute back into the cache. this is complicated by the
* fact that when a function calls this with an object, the object
* is *already* in the cache, since calling functions operate on
* pointers to the cached objects, and may or may not be actively
* modifying them. in other words, by the time the object is handed
* to cache_put, it has probably already been modified, and the cached
* version probably already reflects those modifications!
*
* so - we do a couple of things: we make sure that the cached object is
* actually there, and move it to the modified chain. if we can't find it * either we have a (major) programming error, or the
* *name* of the object has been changed, or the object is a totally
* new creation someone made and is inserting into the world.
*
* in the case of totally new creations, we simply accept the pointer
* to the object and add it into our environment. freeing it becomes
* the responsibility of the cache code. DO NOT HAND A POINTER TO
* CACHE_PUT AND THEN FREE IT YOURSELF!!!!
*
*/
int cache_put(key, data, type)
DBData key;
DBData data;
unsigned int type;
{
Cache *cp;
Chain *sp;
int hv = 0;
#ifdef MEMORY_BASED
char *cdata;
#endif
if (!key.dptr || !data.dptr || !cache_initted) {
return (1);
}
/* Call module API hook */
CALL_ALL_MODULES(cache_put_notify, (key, type))
#ifndef MEMORY_BASED
if (mudstate.standalone) {
#endif
/* Bypass the cache when standalone or memory based for writes */
if (data.dptr == NULL) {
switch(type) {
case DBTYPE_ATTRIBUTE:
pipe_del_attrib(((Aname *)key.dptr)->attrnum,
((Aname *)key.dptr)->object);
#ifdef MEMORY_BASED
obj_del_attrib(((Aname *)key.dptr)->attrnum,
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

Saturday, June 16, 2012 11:23 PM

&(db[((Aname *)key.dptr)->object].attrtext));

#endif

break;
default:
db_lock();
db_del(key, type);
db_unlock();
}
} else {
switch(type) {
case DBTYPE_ATTRIBUTE:
pipe_set_attrib(((Aname *)key.dptr)->attrnum,
((Aname *)key.dptr)->object,
(char *)data.dptr);
#ifdef MEMORY_BASED
cdata = XMALLOC(data.dsize, "cache_get.membased");
memcpy((void *)cdata, (void *)data.dptr, data.dsize);
obj_set_attrib(((Aname *)key.dptr)->attrnum,
&(db[((Aname *)key.dptr)->object].attrtext),
cdata);

#endif

/* Don't forget to free data.dptr when standalone */


XFREE(data.dptr, "cache_put");
break;
default:
db_lock();
db_put(key, data, type);
db_unlock();
}

}
return(0);
#ifndef MEMORY_BASED
}
#endif
cs_writes++;

/* generate hash */
hv = cachehash(key.dptr, key.dsize, type);
sp = &sys_c[hv];
/* step one, search chain, and if we find the obj, dirty it */
for (cp = sp->head; cp != NULL; cp = cp->nxt) {
if (NAMECMP(key.dptr, cp->keydata, key.dsize, type, cp->type)) {
if (!mudstate.dumping) {
cs_whits++;
}
if(cp->data != data.dptr) {
cache_repl(cp, data.dptr, data.dsize, type, CACHE_DIRTY);
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734

Saturday, June 16, 2012 11:23 PM

}
F_DEQUEUE(freelist, cp);
F_INSTAIL(freelist, cp);

return (0);

/* Add a new entry to the cache */


if ((cp = get_free_entry(data.dsize)) == NULL)
return (1);
cp->keydata = (void *)RAW_MALLOC(key.dsize, "cache_put");
memcpy(cp->keydata, key.dptr, key.dsize);
cp->keylen = key.dsize;
cp->data = data.dptr;
cp->datalen = data.dsize;
cp->type = type;
cp->flags = CACHE_DIRTY;
cs_size += cp->datalen;
/* link at tail of chain */
INSTAIL(sp, cp);
/* link at tail of LRU freelist */
F_INSTAIL(freelist, cp);
}

return (0);

static Cache *get_free_entry(atrsize)


int atrsize;
{
DBData key, data;
Chain *sp;
Cache *cp, *p, *prv;
int hv;
/*
*
*
*
*

Flush entries from the cache until there's enough room for
this one. The max size can be dynamically changed-- if it is too
small, the MUSH will flush entries until the cache fits within
this size and if it is too large, we'll fill it up before we
start flushing */

while ((cs_size + atrsize) >


(mudconf.cache_size ? mudconf.cache_size : CACHE_SIZE)) {

-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787

Saturday, June 16, 2012 11:23 PM

cp = freelist->head;
if (cp) {
F_DEQUEUE(freelist, cp);
}
if (cp && (cp->flags & CACHE_DIRTY)) {
/* Flush the modified attributes to disk */

if (cp->data == NULL) {
switch(cp->type) {
case DBTYPE_ATTRIBUTE:
pipe_del_attrib(((Aname *)cp->keydata)->attrnum,
((Aname *)cp->keydata)->object);
break;
default:
key.dptr = cp->keydata;
key.dsize = cp->keylen;
db_lock();
db_del(key, cp->type);
db_unlock();
}
cs_dels++;
} else {
switch(cp->type) {
case DBTYPE_ATTRIBUTE:
pipe_set_attrib(((Aname *)cp->keydata)->attrnum,
((Aname *)cp->keydata)->object,
(char *)cp->data);
break;
default:
key.dptr = cp->keydata;
key.dsize = cp->keylen;
data.dptr = cp->data;
data.dsize = cp->datalen;
db_lock();
db_put(key, data, cp->type);
db_unlock();
}
cs_dbwrites++;
}

/* Take the attribute off of its chain and nuke the


attribute's memory */
if (cp) {
/* Find the cache entry inside the real cache */
hv = cachehash(cp->keydata, cp->keylen, cp->type);
sp = &sys_c[hv];
prv = NULL;
for (p = sp->head; p != NULL; p = p->nxt) {
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840

Saturday, June 16, 2012 11:23 PM

if (cp == p) {
break;
}
prv = p;

/* Remove the cache entry */


DEQUEUE(sp, cp);
cache_repl(cp, NULL, 0, DBTYPE_EMPTY, 0);
RAW_FREE(cp->keydata, "cache_reset.actkey");
RAW_FREE(cp, "get_free_entry");

}
cp = NULL;

/* No valid cache entries to flush, allocate a new one */


if ((cp = (Cache *) RAW_MALLOC(sizeof(Cache), "get_free_entry")) == NULL)
fatal("cache get_free_entry: malloc failed" , (char *)-1, (char *)0);

cp->keydata = NULL;
cp->keylen = 0;
cp->data = NULL;
cp->datalen = 0;
cp->type = DBTYPE_EMPTY;
cp->flags = 0;
return (cp);

static int cache_write(cp)


Cache *cp;
{
DBData key, data;
/* Write a single cache chain to disk */
while (cp != NULL) {
if (!(cp->flags & CACHE_DIRTY)) {
cp = cp->nxt;
continue;
}
if (cp->data == NULL) {
switch(cp->type) {
case DBTYPE_ATTRIBUTE:
pipe_del_attrib(((Aname *)cp->keydata)->attrnum,
((Aname *)cp->keydata)->object);
break;
default:
key.dptr = cp->keydata;
key.dsize = cp->keylen;
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893

}
}

Saturday, June 16, 2012 11:23 PM

db_del(key, cp->type);
}
cs_dels++;
} else {
switch(cp->type) {
case DBTYPE_ATTRIBUTE:
pipe_set_attrib(((Aname *)cp->keydata)->attrnum,
((Aname *)cp->keydata)->object,
(char *)cp->data);
break;
default:
key.dptr = cp->keydata;
key.dsize = cp->keylen;
data.dptr = cp->data;
data.dsize = cp->datalen;
db_put(key, data, cp->type);
}
cs_dbwrites++;
}
cp->flags = 0;
cp = cp->nxt;

return (0);

int NDECL(cache_sync)
{
int x;
Chain *sp;
cs_syncs++;
if (!cache_initted)
return (1);
if (cache_frozen)
return (0);
if (mudstate.standalone || mudstate.restarting) {
/* If we're restarting or standalone, having DBM wait for
* each write is a performance no-no; run asynchronously */
}

dddb_setsync(0);

/* Lock the database */


db_lock();
for (x = 0, sp = sys_c; x < cwidth; x++, sp++) {
if (cache_write(sp->head))
return (1);
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946

Saturday, June 16, 2012 11:23 PM

}
/* Also sync the read and write object structures if they're dirty */
attrib_sync();
/* Unlock the database */
db_unlock();
if (mudstate.standalone || mudstate.restarting) {
dddb_setsync(1);
}
}

return (0);

void cache_del(key, type)


DBData key;
unsigned int type;
{
Cache *cp;
Chain *sp;
int hv = 0;
if (!key.dptr || !cache_initted)
return;
/* Call module API hook */
CALL_ALL_MODULES(cache_del_notify, (key, type))
#ifdef MEMORY_BASED
if (type == DBTYPE_ATTRIBUTE) {
pipe_del_attrib(((Aname *)key.dptr)->attrnum,
((Aname *)key.dptr)->object);
obj_del_attrib(((Aname *)key.dptr)->attrnum,
&(db[((Aname *)key.dptr)->object].attrtext));
return;
}
#endif
cs_dels++;
hv = cachehash(key.dptr, key.dsize, type);
sp = &sys_c[hv];
/* mark dead in cache */
for (cp = sp->head; cp != NULL; cp = cp->nxt) {
if (NAMECMP(key.dptr, cp->keydata, key.dsize, type, cp->type)) {
F_DEQUEUE(freelist, cp);
F_INSHEAD(freelist, cp);
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ocache.c

947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965

Saturday, June 16, 2012 11:23 PM

cache_repl(cp, NULL, 0, type, CACHE_DIRTY);


return;

if ((cp = get_free_entry(0)) == NULL)


return;
cp->keydata = (void *)RAW_MALLOC(key.dsize, "cache_del");
memcpy(cp->keydata, key.dptr, key.dsize);
cp->keylen = key.dsize;
cp->type = type;
cp->flags = CACHE_DIRTY;

INSHEAD(sp, cp);
F_INSHEAD(freelist, cp);
return;

-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ochunk.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Saturday, June 16, 2012 11:22 PM

/* udb_ochunk.c */
/* $Id: udb_ochunk.c,v 1.54 2006/11/10 20:53:20 tyrspace Exp $ */
/*
* Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "gdbm.h"
#include "udb.h"

/* required by code */
/* required by code */

#define DEFAULT_DBMCHUNKFILE "mudDB"


static char *dbfile = DEFAULT_DBMCHUNKFILE;
static int db_initted = 0;
static GDBM_FILE dbp = (GDBM_FILE) 0;
static datum dat;
static datum key;
static struct flock fl;
extern void VDECL(fatal, (char *, ...));
extern void VDECL(warning, (char *, ...));
extern void FDECL(log_db_err, (int, int, const char *));
void dddb_setsync(flag)
int flag;
{
char *gdbm_error;

if (gdbm_setopt(dbp, GDBM_SYNCMODE, &flag, sizeof(int)) == -1) {


gdbm_error = (char *)gdbm_strerror(gdbm_errno);
warning("setsync: cannot toggle sync flag" , dbfile, " ", (char *)-1, "\n",
gdbm_error, "\n", (char *)0);
}

static void dbm_error(msg)


char *msg;
{
STARTLOG(LOG_ALWAYS, "DB", "ERROR")
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ochunk.c

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

Saturday, June 16, 2012 11:22 PM

log_printf("Database error: %s\n", msg);


ENDLOG

/* gdbm_reorganize compresses unused space in the db */


int dddb_optimize()
{
int i;

i = gdbm_reorganize(dbp);
return i;

int dddb_init()
{
static char *copen = "db_init cannot open ";
char tmpfile[256];
char *gdbm_error;
int i;
if (!mudstate.standalone)
sprintf(tmpfile, "%s/%s", mudconf.dbhome, dbfile);
else
strcpy(tmpfile, dbfile);
if ((dbp = gdbm_open(tmpfile, mudstate.db_block_size, GDBM_WRCREAT|GDBM_SYNC|
GDBM_NOLOCK, 0600, dbm_error)) == (GDBM_FILE) 0) {
gdbm_error = (char *)gdbm_strerror(gdbm_errno);
warning(copen, tmpfile, " ", (char *)-1, "\n", gdbm_error, "\n", (char *)0);
return (1);
}
if (mudstate.standalone) {
/* Set the cache size to be 400 hash buckets for GDBM. */
i = 400;
if (gdbm_setopt(dbp, GDBM_CACHESIZE, &i, sizeof(int)) == -1) {
gdbm_error = (char *)gdbm_strerror(gdbm_errno);
warning(copen, dbfile, " ", (char *)-1, "\n", gdbm_error, "\n", (char *)0);
return (1);
}
} else {
/* This would set the cache size to be 2 hash buckets
* for GDBM, except that the library imposes a minimum
* of 10.
*/
i = 2;
if (gdbm_setopt(dbp, GDBM_CACHESIZE, &i, sizeof(int)) == -1) {
gdbm_error = (char *)gdbm_strerror(gdbm_errno);
warning(copen, dbfile, " ", (char *)-1, "\n", gdbm_error, "\n", (char *)0);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ochunk.c

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

Saturday, June 16, 2012 11:22 PM

return (1);

/* Set GDBM to manage a global free space table. */


i = 1;
if (gdbm_setopt(dbp, GDBM_CENTFREE, &i, sizeof(int)) == -1) {
gdbm_error = (char *)gdbm_strerror(gdbm_errno);
warning(copen, dbfile, " ", (char *)-1, "\n", gdbm_error, "\n", (char *)0);
return (1);
}
/* Set GDBM to coalesce free blocks. */
i = 1;
if (gdbm_setopt(dbp, GDBM_COALESCEBLKS, &i, sizeof(int)) == -1) {
gdbm_error = (char *)gdbm_strerror(gdbm_errno);
warning(copen, dbfile, " ", (char *)-1, "\n", gdbm_error, "\n", (char *)0);
return (1);
}
/* If we're standalone, having GDBM wait for each write is a
* performance no-no; run non-synchronous */
if (mudstate.standalone)
dddb_setsync(0);
/* Grab the file descriptor for locking */
mudstate.dbm_fd = gdbm_fdesc(dbp);

db_initted = 1;
return (0);

int dddb_setfile(fil)
char *fil;
{
char *xp;
if (db_initted)
return (1);

/* KNOWN memory leak. can't help it. it's small */


xp = XSTRDUP(fil, "dddb_setfile");
if (xp == (char *)0)
return (1);
dbfile = xp;
return (0);

int dddb_close()
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ochunk.c

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

Saturday, June 16, 2012 11:22 PM

if (dbp != (GDBM_FILE) 0) {
gdbm_close(dbp);
dbp = (GDBM_FILE) 0;
}
db_initted = 0;
return (0);

/* Pass db_get a key, and it returns data. Type is used as part of the GDBM
* key to guard against namespace conflicts in different MUSH subsystems.
* It is the caller's responsibility to free the data returned by db_get */
DBData db_get(gamekey, type)
DBData gamekey;
unsigned int type;
{
DBData gamedata;
char *s;
#ifdef TEST_MALLOC
char *newdat;
#endif
if (!db_initted) {
gamedata.dptr = NULL;
gamedata.dsize = 0;
return gamedata;
}
/* Construct a key (GDBM likes first 4 bytes to be unique) */
s = key.dptr = (char *)RAW_MALLOC(sizeof(int) + gamekey.dsize, "db_get");
memcpy((void *)s, gamekey.dptr, gamekey.dsize);
s += gamekey.dsize;
memcpy((void *)s, (void *)&type, sizeof(unsigned int));
key.dsize = sizeof(int) + gamekey.dsize;
dat = gdbm_fetch(dbp, key);
#ifdef TEST_MALLOC
/* We must XMALLOC() our own memory */
if (dat.dptr != NULL) {
newdat = (char *)XMALLOC(dat.dsize, "db_get.newdat");
memcpy(newdat, dat.dptr, dat.dsize);
free(dat.dptr);
dat.dptr = newdat;
}
#endif
gamedata.dptr = dat.dptr;
gamedata.dsize = dat.dsize;
RAW_FREE(key.dptr, "db_get");
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ochunk.c

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

Saturday, June 16, 2012 11:22 PM

return gamedata;

/* Pass db_put a key, data and the type of entry you are storing */
int db_put(gamekey, gamedata, type)
DBData gamekey;
DBData gamedata;
unsigned int type;
{
char *s;
if (!db_initted)
return (1);
/* Construct a key (GDBM likes first 4 bytes to be unique) */
s = key.dptr = (char *)RAW_MALLOC(sizeof(int) + gamekey.dsize, "db_put");
memcpy((void *)s, gamekey.dptr, gamekey.dsize);
s += gamekey.dsize;
memcpy((void *)s, (void *)&type, sizeof(unsigned int));
key.dsize = sizeof(int) + gamekey.dsize;
/* make table entry */
dat.dptr = gamedata.dptr;
dat.dsize = gamedata.dsize;
if (gdbm_store(dbp, key, dat, GDBM_REPLACE)) {
warning("db_put: can't gdbm_store ", " ", (char *)-1, "\n", (char *)0);
RAW_FREE(dat.dptr, "db_put.dat");
RAW_FREE(key.dptr, "db_put");
return (1);
}
RAW_FREE(key.dptr, "db_put");
}

return (0);

/* Pass db_del a key and the type of entry you are deleting */
int db_del(gamekey, type)
DBData gamekey;
unsigned int type;
{
char *s;
if (!db_initted) {
return (-1);
}
/* Construct a key (GDBM likes first 4 bytes to be unique) */

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ochunk.c

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

Saturday, June 16, 2012 11:22 PM

s = key.dptr = (char *)RAW_MALLOC(sizeof(int) + gamekey.dsize, "db_del");


memcpy((void *)s, gamekey.dptr, gamekey.dsize);
s += gamekey.dsize;
memcpy((void *)s, (void *)&type, sizeof(unsigned int));
key.dsize = sizeof(int) + gamekey.dsize;
dat = gdbm_fetch(dbp, key);
/* not there? */
if (dat.dptr == NULL) {
RAW_FREE(key.dptr, "db_del.key");
return (0);
}
#ifdef TEST_MALLOC
free(dat.dptr);
#else
RAW_FREE(dat.dptr, "db_del.dat");
#endif

/* drop key from db */


if (gdbm_delete(dbp, key)) {
warning("db_del: can't delete key\n", (char *)NULL);
RAW_FREE(key.dptr, "db_del.key");
return (1);
}
RAW_FREE(key.dptr, "db_del.key");
return (0);

void db_lock()
{
/* Attempt to lock the DBM file. Block until the lock is cleared,
then set it. */
if (mudstate.dbm_fd == -1)
return;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();

if (fcntl(mudstate.dbm_fd, F_SETLKW, &fl) == -1) {


log_perror("DMP", "LOCK", NULL, "fcntl()");
return;
}

void db_unlock()
{
if (mudstate.dbm_fd == -1)
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\udb_ochunk.c

317
318
319
320
321
322
323
324
325
326

Saturday, June 16, 2012 11:22 PM

return;
fl.l_type = F_UNLCK;

if (fcntl(mudstate.dbm_fd, F_SETLK, &fl) == -1) {


log_perror("DMP", "LOCK", NULL, "fcntl()");
return;
}

-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\unparse.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:22 PM

/* unparse.c - convert boolexps to printable form */


/* $Id: unparse.c,v 1.12 2003/02/04 05:06:33 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
/*
* Boolexp decompile formats
*/
#define F_EXAMINE

1
/*
* Normal
*/
#define F_QUIET
2
/*
* Binary for db dumps
*/
#define F_DECOMPILE 3
/*
* @decompile output
*/
#define F_FUNCTION 4
/*
* [lock()] output
*/
/*
* Take a dbref (loc) and generate a string. -1, -3, or (#loc) Note, this
* will give players object numbers of stuff they don't control, but it's
* only internal currently, so it's not a problem.
*/
static char *unparse_object_quiet(player, loc)
dbref player, loc;
{
static char buf[SBUF_SIZE];

switch (loc) {
case NOTHING:
return (char *)"-1";
case HOME:
return (char *)"-3";
default:
sprintf(buf, "(#%d)", loc);
return buf;
}

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\unparse.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:22 PM

static char boolexp_buf[LBUF_SIZE];


static char *buftop;
static void unparse_boolexp1(player, b, outer_type, format)
dbref player;
BOOLEXP *b;
char outer_type;
int format;
{
ATTR *ap;
char sep_ch;
char *buff;
if ((b == TRUE_BOOLEXP)) {
if (format == F_EXAMINE) {
safe_str((char *)"*UNLOCKED*", boolexp_buf, &buftop);
}
return;
}
switch (b->type) {
case BOOLEXP_AND:
if (outer_type == BOOLEXP_NOT) {
safe_chr('(', boolexp_buf, &buftop);
}
unparse_boolexp1(player, b->sub1, b->type, format);
safe_chr(AND_TOKEN, boolexp_buf, &buftop);
unparse_boolexp1(player, b->sub2, b->type, format);
if (outer_type == BOOLEXP_NOT) {
safe_chr(')', boolexp_buf, &buftop);
}
break;
case BOOLEXP_OR:
if (outer_type == BOOLEXP_NOT || outer_type == BOOLEXP_AND) {
safe_chr('(', boolexp_buf, &buftop);
}
unparse_boolexp1(player, b->sub1, b->type, format);
safe_chr(OR_TOKEN, boolexp_buf, &buftop);
unparse_boolexp1(player, b->sub2, b->type, format);
if (outer_type == BOOLEXP_NOT || outer_type == BOOLEXP_AND) {
safe_chr(')', boolexp_buf, &buftop);
}
break;
case BOOLEXP_NOT:
safe_chr('!', boolexp_buf, &buftop);
unparse_boolexp1(player, b->sub1, b->type, format);
break;
case BOOLEXP_INDIR:
safe_chr(INDIR_TOKEN, boolexp_buf, &buftop);
unparse_boolexp1(player, b->sub1, b->type, format);
break;
case BOOLEXP_IS:
safe_chr(IS_TOKEN, boolexp_buf, &buftop);
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\unparse.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:22 PM

unparse_boolexp1(player, b->sub1, b->type, format);


break;
case BOOLEXP_CARRY:
safe_chr(CARRY_TOKEN, boolexp_buf, &buftop);
unparse_boolexp1(player, b->sub1, b->type, format);
break;
case BOOLEXP_OWNER:
safe_chr(OWNER_TOKEN, boolexp_buf, &buftop);
unparse_boolexp1(player, b->sub1, b->type, format);
break;
case BOOLEXP_CONST:
if (!mudstate.standalone) {
switch (format) {
case F_QUIET:
/*
* Quiet output - for dumps and internal use.
* Always #Num
*/
safe_str((char *)unparse_object_quiet(player, b->thing),
boolexp_buf, &buftop);
break;
case F_EXAMINE:
/*
* Examine output - informative. *
* Name(#Num) or Name
*/
buff = unparse_object(player, b->thing, 0);
safe_str(buff, boolexp_buf, &buftop);
free_lbuf(buff);
break;
case F_DECOMPILE:
/*
* Decompile output - should be usable on
* other MUSHes. *Name if player, Name if
* thing, else #Num
*/
switch (Typeof(b->thing)) {
case TYPE_PLAYER:
safe_chr('*', boolexp_buf, &buftop);
case TYPE_THING:
safe_name(b->thing, boolexp_buf, &buftop);
break;
default:
safe_dbref(boolexp_buf, &buftop, b->thing);
break;
}
break;
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\unparse.c

case F_FUNCTION:

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

Saturday, June 16, 2012 11:22 PM

/*
* Function output - must be usable by @lock
* cmd. *Name if player, else #Num
*/
switch (Typeof(b->thing)) {
case TYPE_PLAYER:
safe_chr('*', boolexp_buf, &buftop);
safe_name(b->thing, boolexp_buf, &buftop);
break;
default:
safe_dbref(boolexp_buf, &buftop, b->thing);
break;
}

}
} else {
safe_str((char *)unparse_object_quiet(player, b->thing),
boolexp_buf, &buftop);
}
break;
case BOOLEXP_ATR:
case BOOLEXP_EVAL:
if (b->type == BOOLEXP_EVAL)
sep_ch = '/';
else
sep_ch = ':';
ap = atr_num(b->thing);
if (ap && ap->number) {
safe_str((char *)ap->name, boolexp_buf, &buftop);
} else {
safe_ltos(boolexp_buf, &buftop, b->thing);
}
safe_chr(sep_ch, boolexp_buf, &buftop);
safe_str((char *)b->sub1, boolexp_buf, &buftop);
break;
default:
fprintf(mainlog_fp, "ABORT! unparse.c, bad boolexp type in
unparse_boolexp1().\n");
abort();
break;
}

char *unparse_boolexp_quiet(player, b)
dbref player;
BOOLEXP *b;
{
buftop = boolexp_buf;
unparse_boolexp1(player, b, BOOLEXP_CONST, F_QUIET);
*buftop = '\0';
return boolexp_buf;
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\unparse.c

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

Saturday, June 16, 2012 11:22 PM

}
char *unparse_boolexp(player, b)
dbref player;
BOOLEXP *b;
{
buftop = boolexp_buf;
unparse_boolexp1(player, b, BOOLEXP_CONST, F_EXAMINE);
*buftop = '\0';
return boolexp_buf;
}
char *unparse_boolexp_decompile(player, b)
dbref player;
BOOLEXP *b;
{
buftop = boolexp_buf;
unparse_boolexp1(player, b, BOOLEXP_CONST, F_DECOMPILE);
*buftop = '\0';
return boolexp_buf;
}
char *unparse_boolexp_function(player, b)
dbref player;
BOOLEXP *b;
{
buftop = boolexp_buf;
unparse_boolexp1(player, b, BOOLEXP_CONST, F_FUNCTION);
*buftop = '\0';
return boolexp_buf;
}

-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\unsplit.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

Saturday, June 16, 2012 11:22 PM

/* unsplit.c - filter for re-combining continuation lines */


/* $Id: unsplit.c,v 1.6 2001/01/18 08:07:04 dpassmor Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include <stdio.h>
#include <ctype.h>
int main(argc, argv)
int argc;
char **argv;
{
int c, numcr;

while ((c = getchar()) != EOF) {


if (c == '\\') {
numcr = 0;
do {
c = getchar();
if (c == '\n')
numcr++;
} while ((c != EOF) && isspace(c));
if (numcr > 1)
putchar('\n');
ungetc(c, stdin);
} else {
putchar(c);
}
}
fflush(stdout);
exit(0);

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:21 PM

/* vattr.c - Manages the user-defined attributes. */


/* $Id: vattr.c,v 1.30 2002/06/19 23:38:23 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"vattr.h" /* required by code */


"attrs.h" /* required by code */
"functions.h" /* required by code */
"command.h"
/* required by code */

static void FDECL(fixcase, (char *));


static char FDECL(*store_string, (char *));
extern int anum_alc_top;
/*
* Allocate space for strings in lumps this big.
*/
#define STRINGBLOCK 1000
/*
* Current block we're putting stuff in
*/
static char *stringblock = (char *)0;
/*
* High water mark.
*/
static int stringblock_hwm = 0;
void NDECL(vattr_init)
{
hashinit(&mudstate.vattr_name_htab, VATTR_HASH_SIZE, HT_STR|HT_KEYREF);
}
VATTR *vattr_find(name)
char *name;
{
return (VATTR *)hashfind(name, &mudstate.vattr_name_htab);
}

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:21 PM

VATTR *vattr_alloc(name, flags)


char *name;
int flags;
{
int number;

if (((number = mudstate.attr_next++) & 0x7f) == 0)


number = mudstate.attr_next++;
anum_extend(number);
flags |= AF_DIRTY;
return (vattr_define(name, number, flags));

VATTR *vattr_define(name, number, flags)


char *name;
int number, flags;
{
VATTR *vp;
/* Be ruthless. */
if (strlen(name) >= VNAME_SIZE)
name[VNAME_SIZE - 1] = '\0';
fixcase(name);
if (!ok_attr_name(name))
return (NULL);
if ((vp = vattr_find(name)) != NULL)
return (vp);
vp = (VATTR *) XMALLOC(sizeof(VATTR), "vattr_define");
vp->name = store_string(name);
vp->flags = flags;
vp->number = number;
hashadd(vp->name, (int *) vp, &mudstate.vattr_name_htab, 0);

anum_extend(vp->number);
anum_set(vp->number, (ATTR *) vp);
return (vp);

#ifdef NEVER
void do_dbclean(player, cause, key)
dbref player, cause;
int key;
{
VATTR *vp, *vpx;
dbref i, end;
int ca, n_oldtotal, n_oldtop, n_deleted, n_renumbered, n_objt, n_atrt, got;
char *as, *str;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:21 PM

int *used_table;
ATTR **new_table;
UFUN *ufp;
CMDENT *cmdp;
ADDENT *addp;
raw_broadcast(0,
"GAME: Cleaning database. Game may freeze for a few minutes." );
used_table = (int *) XCALLOC(mudstate.attr_next, sizeof(int),
"dbclean.used_table");
n_oldtotal = mudstate.attr_next;
n_oldtop = anum_alc_top;
n_deleted = n_renumbered = n_objt = n_atrt = 0;
/* Non-user-defined attributes are always considered used. */
for (i = 0; i < A_USER_START; i++)
used_table[i] = i;
/* Walk the database. Mark all the attribute numbers in use. */
atr_push();
DO_WHOLE_DB(i) {
for (ca = atr_head(i, &as); ca; ca = atr_next(&as)) {
used_table[ca] = ca;
}
}
atr_pop();
/* Walk the vattr table. If a number isn't in use, zorch it. */
vp = vattr_first();
while (vp) {
vpx = vp;
vp = vattr_next(vp);
if (used_table[vpx->number] == 0) {
anum_set(vpx->number, NULL);
hashdelete(vpx->name, &mudstate.vattr_name_htab);
XFREE(vpx, "dbclean.vpx");
n_deleted++;
}
}
/* The user-defined function, added command, and hook structures embed
* attribute numbers. Clean out the ones we've deleted, resetting them
* to the *Invalid (A_TEMP) attr.
*/
for (ufp = (UFUN *) hash_firstentry(&mudstate.ufunc_htab);
ufp != NULL;
ufp = (UFUN *) hash_nextentry(&mudstate.ufunc_htab)) {
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:21 PM

if (used_table[ufp->atr] == 0)
ufp->atr = A_TEMP;
}
for (cmdp = (CMDENT *) hash_firstentry(&mudstate.command_htab);
cmdp != NULL;
cmdp = (CMDENT *) hash_nextentry(&mudstate.command_htab)) {
if (cmdp->pre_hook) {
if (used_table[cmdp->pre_hook->atr] == 0)
cmdp->pre_hook->atr = A_TEMP;
}
if (cmdp->post_hook) {
if (used_table[cmdp->post_hook->atr] == 0)
cmdp->post_hook->atr = A_TEMP;
}
if (cmdp->userperms) {
if (used_table[cmdp->userperms->atr] == 0)
cmdp->userperms->atr = A_TEMP;
}
if (cmdp->callseq & CS_ADDED) {
for (addp = (ADDENT *) cmdp->info.added;
addp != NULL;
addp = addp->next) {
if (used_table[addp->atr] == 0)
addp->atr = A_TEMP;
}
}
}
/* Walk the table we've created of used statuses. When we find free
* slots, walk backwards to the first used slot at the end of the
* table. Write the number of the free slot into that used slot.
*/
for (i = A_USER_START, end = mudstate.attr_next - 1;
(i < mudstate.attr_next) && (i < end); i++) {
if (used_table[i] == 0) {
while ((end > i) && (used_table[end] == 0)) {
end--;
}
if (end > i) {
used_table[end] = used_table[i] = i;
end--;
}
}
}
/* Renumber the necessary attributes in the vattr tables. */
for (i = A_USER_START; i < mudstate.attr_next; i++) {
if (used_table[i] != i) {
vp = (VATTR *) anum_get(i);
if (vp) {
vp->number = used_table[i];
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

}
}

Saturday, June 16, 2012 11:21 PM

vp->flags |= AF_DIRTY;
anum_set(used_table[i], (ATTR *) vp);
anum_set(i, NULL);
n_renumbered++;
}

/* Now we walk the database. For every object, if we have an attribute


* we're renumbering (the slot number is not equal to the array value
* at that slot), we delete the old attribute and add the new one.
*/
atr_push();
DO_WHOLE_DB(i) {
got = 0;
for (ca = atr_head(i, &as); ca; ca = atr_next(&as)) {
if (used_table[ca] != ca) {
str = atr_get_raw(i, ca);
atr_add_raw(i, used_table[ca], str);
atr_clr(i, ca);
n_atrt++;
got = 1;
}
}
if (got)
n_objt++;
}
atr_pop();
/* The new end of the attribute table is the first thing we've
* renumbered.
*/
for (end = A_USER_START;
((end == used_table[end]) && (end < mudstate.attr_next));
end++)
;
mudstate.attr_next = end;
/* We might be able to shrink the size of the attribute table.
* If the current size of the table is less than the initial
* size, shrink it back down to the initial size.
* Otherwise, shrink it down so it's the current top plus the
* initial size, as if we'd just called anum_extend() for it.
*/
if (anum_alc_top > mudconf.init_size + A_USER_START) {
if (mudstate.attr_next < mudconf.init_size + A_USER_START) {
end = mudconf.init_size + A_USER_START;
} else {
end = mudstate.attr_next + mudconf.init_size;
}
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:21 PM

if (end < anum_alc_top) {


new_table = (ATTR **) XCALLOC(end + 1, sizeof(ATTR *),
"dbclean.new_table");
for (i = 0; i < mudstate.attr_next; i++)
new_table[i] = anum_table[i];
XFREE(anum_table, "dbclean.anum_table");
anum_table = new_table;
anum_alc_top = end;
}
}
/* Go through the function and added command tables again, and
* take care of the attributes that got renumbered.
*/
for (ufp = (UFUN *) hash_firstentry(&mudstate.ufunc_htab);
ufp != NULL;
ufp = (UFUN *) hash_nextentry(&mudstate.ufunc_htab)) {
if (used_table[ufp->atr] != ufp->atr)
ufp->atr = used_table[ufp->atr];
}
for (cmdp = (CMDENT *) hash_firstentry(&mudstate.command_htab);
cmdp != NULL;
cmdp = (CMDENT *) hash_nextentry(&mudstate.command_htab)) {
if (cmdp->pre_hook) {
if (used_table[cmdp->pre_hook->atr] != cmdp->pre_hook->atr)
cmdp->pre_hook->atr = used_table[cmdp->pre_hook->atr];
}
if (cmdp->post_hook) {
if (used_table[cmdp->post_hook->atr] != cmdp->post_hook->atr)
cmdp->post_hook->atr = used_table[cmdp->post_hook->atr];
}
if (cmdp->userperms) {
if (used_table[cmdp->userperms->atr] != cmdp->userperms->atr)
cmdp->userperms->atr = used_table[cmdp->userperms->atr];
}
if (cmdp->callseq & CS_ADDED) {
for (addp = (ADDENT *) cmdp->info.added;
addp != NULL;
addp = addp->next) {
if (used_table[addp->atr] != addp->atr)
addp->atr = used_table[addp->atr];
}
}
}
/* Clean up. */
XFREE(used_table, "dbclean.used_table");
if (anum_alc_top != n_oldtop) {
notify(player,
tprintf("Cleaned %d user attribute slots (reduced to %d): %d deleted, %d
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

renumbered (%d objects and %d individual attrs touched). Table size reduced
from %d to %d.",
n_oldtotal - A_USER_START,
mudstate.attr_next - A_USER_START,
n_deleted, n_renumbered,
n_objt, n_atrt, n_oldtop, anum_alc_top));
} else {
notify(player,
tprintf("Cleaned %d attributes (now %d): %d deleted, %d renumbered (%d
objects and %d individual attrs touched)." ,
n_oldtotal, mudstate.attr_next, n_deleted, n_renumbered,
n_objt, n_atrt));
}

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

Saturday, June 16, 2012 11:21 PM

raw_broadcast(0, "GAME: Database cleaning complete." );


}
#endif /* NEVER */
void vattr_delete(name)
char *name;
{
VATTR *vp;
int number;
fixcase(name);
if (!ok_attr_name(name))
return;
number = 0;
vp = (VATTR *)hashfind(name, &mudstate.vattr_name_htab);
if (vp) {
number = vp->number;
anum_set(number, NULL);
hashdelete(name, &mudstate.vattr_name_htab);
XFREE(vp, "vattr_delete");
}
}

return;

VATTR *vattr_rename(name, newname)


char *name, *newname;
{
VATTR *vp;
fixcase(name);
if (!ok_attr_name(name))
return (NULL);
/*
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

Saturday, June 16, 2012 11:21 PM

* Be ruthless.
*/
if (strlen(newname) >= VNAME_SIZE)
newname[VNAME_SIZE - 1] = '\0';
fixcase(newname);
if (!ok_attr_name(newname))
return (NULL);
/* We must explicitly delete and add the name to the hashtable,
* since we are changing the data.
*/
vp = (VATTR *)hashfind(name, &mudstate.vattr_name_htab);
if (vp) {
vp->name = store_string(newname);
hashdelete(name, &mudstate.vattr_name_htab);
hashadd(newname, (int *) vp, &mudstate.vattr_name_htab, 0);
}
}

return (vp);

VATTR *NDECL(vattr_first)
{
return (VATTR *)hash_firstentry(&mudstate.vattr_name_htab);
}
VATTR *vattr_next(vp)
VATTR *vp;
{
if (vp == NULL)
return (vattr_first());
}

return ((VATTR *)hash_nextentry(&mudstate.vattr_name_htab));

static void fixcase(name)


char *name;
{
char *cp = name;
while (*cp) {
*cp = toupper(*cp);
cp++;
}
}

return;

-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.c

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

Saturday, June 16, 2012 11:21 PM

/*
* Some goop for efficiently storing strings we expect to
* keep forever. There is no freeing mechanism.
*/
static char *store_string(str)
char *str;
{
int len;
char *ret;
len = strlen(str);
/*
* If we have no block, or there's not enough room left in the
* current one, get a new one.
*/

if (!stringblock || (STRINGBLOCK - stringblock_hwm) < (len + 1)) {


stringblock = (char *)XMALLOC(STRINGBLOCK, "store_string");
if (!stringblock)
return ((char *)0);
stringblock_hwm = 0;
}
ret = stringblock + stringblock_hwm;
StringCopy(ret, str);
stringblock_hwm += (len + 1);
return (ret);

-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\vattr.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Saturday, June 16, 2012 11:04 PM

/* vattr.h - Definitions for user-defined attributes */


/* $Id: vattr.h,v 1.7 2002/08/28 15:24:09 rmg Exp $ */
#include "copyright.h"
#ifndef __VATTR_H
#define __VATTR_H
#ifndef VATTR_HASH_SIZE
/* must be a power of two */
#define VATTR_HASH_SIZE 8192
#endif
#define VNAME_SIZE

32

typedef struct user_attribute VATTR;


struct user_attribute {
char
*name; /* Name of user attribute */
int number;
/* Assigned attribute number */
int flags;
/* Attribute flags */
};
extern
extern
extern
extern
extern
extern
extern
extern

void NDECL(vattr_init);
VATTR * FDECL(vattr_rename, (char *, char *));
VATTR * FDECL(vattr_find, (char *));
VATTR * FDECL(vattr_alloc, (char *, int));
VATTR * FDECL(vattr_define, (char *, int, int));
void FDECL(vattr_delete, (char *));
VATTR * NDECL(vattr_first);
VATTR * FDECL(vattr_next, (VATTR *));

#endif /* __VATTR_H */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\version.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:21 PM

/* version.c - version information */


/* $Id: version.c,v 1.15 2000/12/02 23:24:21 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include "patchlevel.h" /* required by code */
/*
* TinyMUSH 3.0
*/
/*
* 2.0
* All known bugs fixed with disk-based. Played with gdbm, it
* sucked. Now using bsd 4.4 hash stuff.
*/
/*
* 1.12
* * All known bugs fixed after several days of debugging 1.10/1.11.
* * Much string-handling braindeath patched, but needs a big overhaul,
* * really.
GAC 2/10/91
*/
/*
* 1.11
* * Fixes for 1.10. (@name didn't call do_name, etc.)
* * Added dexamine (debugging examine, dumps the struct, lots of info.)
*/
/*
* 1.10
* * Finally got db2newdb working well enough to run from the big (30000
* * object) db with ATR_KEY and ATR_NAME defined.
GAC 2/3/91
*/
/*
* TinyMUSH version.c file. Add a comment here any time you've made a
* * big enough revision to increment the TinyMUSH version #.
*/
void do_version(player, cause, extra)
dbref player, cause;
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\version.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:21 PM

int extra;
{
notify(player, mudstate.version);
notify(player, tprintf("Build date: %s", MUSH_BUILD_DATE));
if (Wizard(player)) {
notify(player, tprintf("Build info: %s", mudstate.buildinfo));
}
if (mudstate.modloaded[0]) {
notify(player, tprintf("Modules loaded: %s", mudstate.modloaded));
}
}
void NDECL(init_version)
{
#if PATCHLEVEL > 0
mudstate.version =
XSTRDUP(tprintf("TinyMUSH version %s %s %d #%s [%s]" ,
MUSH_VERSION,
((MUSH_RELEASE_STATUS == 0) ? "patchlevel" :
((MUSH_RELEASE_STATUS == 1) ? "beta" : "alpha")),
PATCHLEVEL, MUSH_BUILD_NUM, MUSH_RELEASE_DATE),
"init_version");
mudstate.short_ver =
XSTRDUP(tprintf("TinyMUSH %s.%c%d",
MUSH_VERSION,
((MUSH_RELEASE_STATUS == 0) ? 'p' :
((MUSH_RELEASE_STATUS == 1) ? 'b' : 'a')),
PATCHLEVEL), "init_version");
#else
mudstate.version =
XSTRDUP(tprintf("TinyMUSH version %s #%s [%s]" ,
MUSH_VERSION, MUSH_BUILD_NUM, MUSH_RELEASE_DATE),
"init_version");
mudstate.short_ver =
XSTRDUP(tprintf("TinyMUSH %s", MUSH_VERSION), "init_version");
#endif /* PATCHLEVEL > 0 */

mudstate.buildinfo =
XSTRDUP(tprintf("%s\n
%s %s",
MUSH_CONFIGURE_CMD,
MUSH_BUILD_COMPILER, MUSH_BUILD_CFLAGS),
"init_version");
STARTLOG(LOG_ALWAYS, "INI", "START")
log_printf("Starting: %s", mudstate.version);
ENDLOG
STARTLOG(LOG_ALWAYS, "INI", "START")
log_printf("Build date: %s", MUSH_BUILD_DATE);
ENDLOG
STARTLOG(LOG_ALWAYS, "INI", "START")
log_printf("Build info: %s", mudstate.buildinfo);
ENDLOG

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:20 PM

/* walkdb.c - Support for commands that walk the entire db */


/* $Id: walkdb.c,v 1.35 2004/02/23 04:35:14 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
#include
#include
#include
#include

"match.h"
"powers.h"
"walkdb.h"
"attrs.h"

/*
/*
/*
/*

required
required
required
required

by
by
by
by

code
code
code
code

*/
*/
*/
*/

#ifdef MCHECK
#include "malloc.h"
#endif
extern int FDECL(decode_power, (dbref, char *, POWERSET *));
/*
* Bind occurances of the universal var in ACTION to ARG, then run ACTION.
* * Cmds run in low-prio Q after a 1 sec delay for the first one.
*/
static void bind_and_queue(player, cause, action, argstr, cargs, ncargs, number, now)
dbref player, cause;
int ncargs, number, now;
char *action, *argstr, *cargs[];
{
char *command, *command2;
/*
* allocated by replace_string
*/

command = replace_string(BOUND_VAR, argstr, action);


command2 = replace_string(LISTPLACE_VAR, tprintf("%d", number),
command);
if (now)
process_cmdline(player, cause, command2, cargs, ncargs, NULL);
else
wait_que(player, cause, 0, NOTHING, 0, command2, cargs, ncargs,
mudstate.rdata);
free_lbuf(command);
free_lbuf(command2);

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:20 PM

/*
* New @dolist. i.e.:
* * @dolist #12 #34 #45 #123 #34644=@emit [name(##)]
* *
* * New switches added 12/92, /space (default) delimits list using spaces,
* * and /delimit allows specification of a delimiter.
*/
void do_dolist(player, cause, key, list, command, cargs, ncargs)
dbref player, cause;
int key, ncargs;
char *list, *command, *cargs[];
{
char *tbuf, *curr, *objstring, delimiter = ' ';
int number = 0, now;
if (!list || *list == '\0') {
notify(player,
"That's terrific, but what should I do with the list?" );
return;
}
curr = list;
now = key & DOLIST_NOW;
if (key & DOLIST_DELIMIT) {
char *tempstr;
if (strlen((tempstr = parse_to(&curr, ' ', EV_STRIP))) > 1) {
notify(player, "The delimiter must be a single character!" );
return;
}
delimiter = *tempstr;

}
while (curr && *curr) {
while (*curr == delimiter)
curr++;
if (*curr) {
number++;
objstring = parse_to(&curr, delimiter, EV_STRIP);
bind_and_queue(player, cause, command, objstring,
cargs, ncargs, number, now);
}
}
if (key & DOLIST_NOTIFY) {
tbuf = alloc_lbuf("dolist.notify_cmd");
strcpy(tbuf, (char *) "@notify me");
wait_que(player, cause, 0, NOTHING, A_SEMAPHORE, tbuf,
cargs, ncargs, mudstate.rdata);
free_lbuf(tbuf);
}

-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:20 PM

/*
* Regular @find command
*/
void do_find(player, cause, key, name)
dbref player, cause;
int key;
char *name;
{
dbref i, low_bound, high_bound;
char *buff;

if (!payfor(player, mudconf.searchcost)) {
notify_quiet(player,
tprintf("You don't have enough %s.",
mudconf.many_coins));
return;
}
parse_range(&name, &low_bound, &high_bound);
for (i = low_bound; i <= high_bound; i++) {
if ((Typeof(i) != TYPE_EXIT) &&
controls(player, i) &&
(!*name || string_match(PureName(i), name))) {
buff = unparse_object(player, i, 0);
notify(player, buff);
free_lbuf(buff);
}
}
notify(player, "***End of List***");

/*
* --------------------------------------------------------------------------* * get_stats, do_stats: Get counts of items in the db.
*/
int get_stats(player, who, info)
dbref player, who;
STATS *info;
{
dbref i;
info->s_total = 0;
info->s_rooms = 0;
info->s_exits = 0;
info->s_things = 0;
info->s_players = 0;
info->s_going = 0;
info->s_garbage = 0;
info->s_unknown = 0;
/*
* Do we have permission?
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:20 PM

*/
if (Good_obj(who) && !Controls(player, who) && !Stat_Any(player)) {
notify(player, NOPERM_MESSAGE);
return 0;
}
/*
* Can we afford it?
*/

if (!payfor(player, mudconf.searchcost)) {
notify(player, tprintf("You don't have enough %s.",
mudconf.many_coins));
return 0;
}
DO_WHOLE_DB(i) {
if ((who == NOTHING) || (who == Owner(i))) {
info->s_total++;
if (Going(i) && (Typeof(i) < GOODTYPE)) {
info->s_going++;
continue;
}
switch (Typeof(i)) {
case TYPE_ROOM:
info->s_rooms++;
break;
case TYPE_EXIT:
info->s_exits++;
break;
case TYPE_THING:
info->s_things++;
break;
case TYPE_PLAYER:
info->s_players++;
break;
case TYPE_GARBAGE:
info->s_garbage++;
break;
default:
info->s_unknown++;
}
}
}
return 1;

void do_stats(player, cause, key, name)


dbref player, cause;
int key;
char *name;
/*
* reworked by R'nice
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

Saturday, June 16, 2012 11:20 PM

*/
{

dbref owner;
STATS statinfo;
switch (key) {
case STAT_ALL:
owner = NOTHING;
break;
case STAT_ME:
owner = Owner(player);
break;
case STAT_PLAYER:
if (!(name && *name)) {
notify(player,
tprintf("The universe contains %d objects (next free is #%d)." ,
mudstate.db_top,
((mudstate.freelist == NOTHING) ?
mudstate.db_top : mudstate.freelist)));
return;
}
owner = lookup_player(player, name, 1);
if (owner == NOTHING) {
notify(player, "Not found.");
return;
}
break;
default:
notify(player, "Illegal combination of switches." );
return;
}
if (!get_stats(player, owner, &statinfo))
return;
notify(player,
tprintf("%d objects = %d rooms, %d exits, %d things, %d players. (%d
unknown, %d going, %d garbage)" ,
statinfo.s_total, statinfo.s_rooms, statinfo.s_exits,
statinfo.s_things, statinfo.s_players,
statinfo.s_unknown, statinfo.s_going,
statinfo.s_garbage));

#ifdef TEST_MALLOC
if (Wizard(player))
notify(player, tprintf("Malloc count = %d.", malloc_count));
if (Wizard(player))
notify(player, tprintf("Malloc bytes = %d.", malloc_bytes));
#endif /*
* TEST_MALLOC
*/
#ifdef MCHECK
if (Wizard(player)) {
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316

Saturday, June 16, 2012 11:20 PM

struct mstats mval;


mval = mstats();
notify(player, tprintf("Total size of the heap: %d",
mval.bytes_total));
notify(player, tprintf("Chunks allocated: %d -- Total size of allocated chunks:
%d",
mval.chunks_used, mval.bytes_used));
notify(player, tprintf("Chunks free: %d -- Total size of free chunks: %d" ,
mval.chunks_free, mval.bytes_free));

}
#endif /*
* MCHECK
*/
}

int chown_all(from_player, to_player, acting_player, key)


dbref from_player, to_player, acting_player;
int key;
{
register int i, count = 0, q_t = 0, q_p = 0, q_r = 0, q_e = 0;
int fword1, fword2, fword3, strip_powers;
if (!isPlayer(from_player))
from_player = Owner(from_player);
if (!isPlayer(to_player))
to_player = Owner(to_player);
if (God(from_player) && !God(to_player)) {
notify(acting_player, NOPERM_MESSAGE);
return 0;
}
strip_powers = 1;
if (key & CHOWN_NOSTRIP) {
if (God(acting_player)) {
fword1 = CHOWN_OK;
strip_powers = 0;
} else {
fword1 = CHOWN_OK | WIZARD;
}
fword2 = 0;
fword3 = 0;
} else {
fword1 = CHOWN_OK | mudconf.stripped_flags.word1;
fword2 = mudconf.stripped_flags.word2;
fword3 = mudconf.stripped_flags.word3;
}
DO_WHOLE_DB(i) {
if ((Owner(i) == from_player) && (Owner(i) != i)) {
switch (Typeof(i)) {
case TYPE_PLAYER:
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

Saturday, June 16, 2012 11:20 PM

s_Owner(i, i);
q_p += mudconf.player_quota;
break;
case TYPE_THING:
if (Going(i))
break;
s_Owner(i, to_player);
q_t += mudconf.thing_quota;
break;
case TYPE_ROOM:
s_Owner(i, to_player);
q_r += mudconf.room_quota;
break;
case TYPE_EXIT:
s_Owner(i, to_player);
q_e += mudconf.exit_quota;
break;
default:
s_Owner(i, to_player);
}
s_Flags(i, (Flags(i) & ~fword1) | HALT);
s_Flags2(i, Flags2(i) & ~fword2);
s_Flags3(i, Flags3(i) & ~fword3);
if (strip_powers) {
s_Powers(i, 0);
s_Powers2(i, 0);
}
count++;

}
payfees(to_player, 0, q_p, TYPE_PLAYER);
payfees(from_player, 0, -q_p, TYPE_PLAYER);
payfees(to_player, 0, q_r, TYPE_ROOM);
payfees(from_player, 0, -q_r, TYPE_ROOM);
payfees(to_player, 0, q_e, TYPE_EXIT);
payfees(from_player, 0, -q_e, TYPE_EXIT);
payfees(to_player, 0, q_t, TYPE_THING);
payfees(from_player, 0, -q_t, TYPE_THING);
return count;

void do_chownall(player, cause, key, from, to)


dbref player, cause;
int key;
char *from, *to;
{
int count;
dbref victim, recipient;
init_match(player, from, TYPE_PLAYER);
match_neighbor();
match_absolute();
match_player();
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

Saturday, June 16, 2012 11:20 PM

if ((victim = noisy_match_result()) == NOTHING)


return;
if ((to != NULL) && *to) {
init_match(player, to, TYPE_PLAYER);
match_neighbor();
match_absolute();
match_player();
if ((recipient = noisy_match_result()) == NOTHING)
return;
} else {
recipient = player;
}

count = chown_all(victim, recipient, player, key);


if (!Quiet(player)) {
notify(player, tprintf("%d objects @chowned.", count));
}

#define ANY_OWNER -2
void er_mark_disabled(player)
dbref player;
{
notify(player,
"The mark commands are not allowed while DB cleaning is enabled." );
notify(player,
"Use the '@disable cleaning' command to disable automatic cleaning." );
notify(player,
"Remember to '@unmark_all' before re-enabling automatic cleaning." );
}
/*
* --------------------------------------------------------------------------* * do_search: Walk the db reporting various things (or setting/clearing
* * mark bits)
*/
int search_setup(player, searchfor, parm)
dbref player;
char *searchfor;
SEARCH *parm;
{
char *pname, *searchtype, *t;
int err;
dbref thing, aowner;
int attrib, aflags, alen;
ATTR *attr;
/*
* Crack arg into <pname> <type>=<targ>,<low>,<high>
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

Saturday, June 16, 2012 11:20 PM

*/
pname = parse_to(&searchfor, '=', EV_STRIP_TS);
if (!pname || !*pname) {
pname = (char *)"me";
} else
for (t = pname; *t; t++) {
if (isupper(*t))
*t = tolower(*t);
}
if (searchfor && *searchfor) {
searchtype = strrchr(pname, ' ');
if (searchtype) {
*searchtype++ = '\0';
} else {
searchtype = pname;
pname = (char *)"";
}
} else {
searchtype = (char *)"";
}
/*
* If the player name is quoted, strip the quotes
*/
if (*pname == '\"') {
err = strlen(pname) - 1;
if (pname[err] == '"') {
pname[err] = '\0';
pname++;
}
}
/*
* Strip any range arguments
*/
parse_range(&searchfor, &parm->low_bound, &parm->high_bound);
/*
* set limits on who we search
*/
parm->s_owner = Owner(player);
parm->s_wizard = Search(player);
parm->s_rst_owner = NOTHING;
if (!*pname) {
parm->s_rst_owner = parm->s_wizard ? ANY_OWNER : player;
} else if (pname[0] == '#') {
parm->s_rst_owner = atoi(&pname[1]);
if (!Good_obj(parm->s_rst_owner))
parm->s_rst_owner = NOTHING;
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

Saturday, June 16, 2012 11:20 PM

else if (Typeof(parm->s_rst_owner) != TYPE_PLAYER)


parm->s_rst_owner = NOTHING;
} else if (strcmp(pname, "me") == 0) {
parm->s_rst_owner = player;
} else {
parm->s_rst_owner = lookup_player(player, pname, 1);
}
if (parm->s_rst_owner == NOTHING) {
notify(player, tprintf("%s: No such player", pname));
return 0;
}
/*
* set limits on what we search for
*/
err = 0;
parm->s_rst_name = NULL;
parm->s_rst_eval = NULL;
parm->s_rst_ufuntxt = NULL;
parm->s_rst_type = NOTYPE;
parm->s_parent = NOTHING;
parm->s_zone = NOTHING;
parm->s_fset.word1 = 0;
parm->s_fset.word2 = 0;
parm->s_fset.word3 = 0;
parm->s_pset.word1 = 0;
parm->s_pset.word2 = 0;
switch (searchtype[0]) {
case '\0':
/*
* the no class requested class :)
*/
break;
case 'e':
if (string_prefix("exits", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_EXIT;
} else if (string_prefix("evaluate", searchtype)) {
parm->s_rst_eval = searchfor;
} else if (string_prefix("eplayer", searchtype)) {
parm->s_rst_type = TYPE_PLAYER;
parm->s_rst_eval = searchfor;
} else if (string_prefix("eroom", searchtype)) {
parm->s_rst_type = TYPE_ROOM;
parm->s_rst_eval = searchfor;
} else if (string_prefix("eobject", searchtype)) {
parm->s_rst_type = TYPE_THING;
parm->s_rst_eval = searchfor;
} else if (string_prefix("ething", searchtype)) {
parm->s_rst_type = TYPE_THING;
parm->s_rst_eval = searchfor;
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

Saturday, June 16, 2012 11:20 PM

} else if (string_prefix("eexit", searchtype)) {


parm->s_rst_type = TYPE_EXIT;
parm->s_rst_eval = searchfor;
} else {
err = 1;
}
break;
case 'f':
if (string_prefix("flags", searchtype)) {
/*
* convert_flags ignores previous values of flag_mask
* * * * * and s_rst_type while setting them
*/
if (!convert_flags(player, searchfor, &parm->s_fset,
&parm->s_rst_type))
return 0;
} else {
err = 1;
}
break;
case 'n':
if (string_prefix("name", searchtype)) {
parm->s_rst_name = searchfor;
} else {
err = 1;
}
break;
case 'o':
if (string_prefix("objects", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_THING;
} else {
err = 1;
}
break;
case 'p':
if (string_prefix("players", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_PLAYER;
if (!*pname)
parm->s_rst_owner = ANY_OWNER;
} else if (string_prefix("parent", searchtype)) {
parm->s_parent = match_controlled(player, searchfor);
if (!Good_obj(parm->s_parent))
return 0;
if (!*pname)
parm->s_rst_owner = ANY_OWNER;
} else if (string_prefix("power", searchtype)) {
if (!decode_power(player, searchfor, &parm->s_pset))
return 0;
} else {
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

Saturday, June 16, 2012 11:20 PM

err = 1;
}
break;
case 'r':
if (string_prefix("rooms", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_ROOM;
} else {
err = 1;
}
break;
case 't':
if (string_prefix("type", searchtype)) {
if (searchfor[0] == '\0')
break;
if (string_prefix("rooms", searchfor))
parm->s_rst_type = TYPE_ROOM;
else if (string_prefix("exits", searchfor))
parm->s_rst_type = TYPE_EXIT;
else if (string_prefix("objects", searchfor))
parm->s_rst_type = TYPE_THING;
else if (string_prefix("things", searchfor))
parm->s_rst_type = TYPE_THING;
else if (string_prefix("garbage", searchfor))
parm->s_rst_type = TYPE_GARBAGE;
else if (string_prefix("players", searchfor)) {
parm->s_rst_type = TYPE_PLAYER;
if (!*pname)
parm->s_rst_owner = ANY_OWNER;
} else {
notify(player,
tprintf("%s: unknown type",
searchfor));
return 0;
}
} else if (string_prefix("things", searchtype)) {
parm->s_rst_name = searchfor;
parm->s_rst_type = TYPE_THING;
} else {
err = 1;
}
break;
case 'u':
t = NULL;
if (string_prefix("ueval", searchtype)) {
t = searchfor;
} else if (string_prefix("uplayer", searchtype)) {
parm->s_rst_type = TYPE_PLAYER;
t = searchfor;
} else if (string_prefix("uroom", searchtype)) {
parm->s_rst_type = TYPE_ROOM;
t = searchfor;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687

Saturday, June 16, 2012 11:20 PM

} else if (string_prefix("uobject", searchtype)) {


parm->s_rst_type = TYPE_THING;
t = searchfor;
} else if (string_prefix("uthing", searchtype)) {
parm->s_rst_type = TYPE_THING;
t = searchfor;
} else if (string_prefix("uexit", searchtype)) {
parm->s_rst_type = TYPE_EXIT;
t = searchfor;
} else {
err = 1;
}
if (t) {
if (!parse_attrib(player, t, &thing, &attrib, 0) ||
(attrib == NOTHING)) {
notify(player, "No match for u-function.");
return 0;
}
attr = atr_num(attrib);
if (!attr) {
notify(player, "No match for u-function.");
return 0;
}
t = atr_pget(thing, attrib, &aowner, &aflags, &alen);
if (!*t) {
free_lbuf(t);
notify(player, "No match for u-function.");
return 0;
}
parm->s_rst_ufuntxt = t;
}
break;
case 'z':
if (string_prefix("zone", searchtype)) {
parm->s_zone = match_controlled(player, searchfor);
if (!Good_obj(parm->s_zone))
return 0;
if (!*pname)
parm->s_rst_owner = ANY_OWNER;
} else {
err = 1;
}
break;
default:
err = 1;
}
if (err) {
notify(player, tprintf("%s: unknown class", searchtype));
return 0;
}
/*
-13-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

Saturday, June 16, 2012 11:20 PM

* Make sure player is authorized to do the search


*/
if (!parm->s_wizard &&
(parm->s_rst_type != TYPE_PLAYER) &&
(parm->s_rst_owner != player) &&
(parm->s_rst_owner != ANY_OWNER)) {
notify(player, "You need a search warrant to do that!" );
return 0;
}
/*
* make sure player has money to do the search
*/

if (!payfor(player, mudconf.searchcost)) {
notify(player,
tprintf("You don't have enough %s to search. (You need %d)" ,
mudconf.many_coins, mudconf.searchcost));
return 0;
}
return 1;

void search_perform(player, cause, parm)


dbref player, cause;
SEARCH *parm;
{
FLAG thing1flags, thing2flags, thing3flags;
POWER thing1powers, thing2powers;
dbref thing;
char *buff, *buff2, *atext, *result, *bp, *str;
int save_invk_ctr;
buff = alloc_sbuf("search_perform.num");
save_invk_ctr = mudstate.func_invk_ctr;
if (parm->s_rst_ufuntxt)
atext = alloc_lbuf("search_perform.atext");
else
atext = NULL;
for (thing = parm->low_bound; thing <= parm->high_bound; thing++) {
mudstate.func_invk_ctr = save_invk_ctr;
/*
* Check for matching type
*/
if ((parm->s_rst_type != NOTYPE) &&
(parm->s_rst_type != Typeof(thing)))
continue;
/*
-14-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

Saturday, June 16, 2012 11:20 PM

* Check for matching owner


*/
if ((parm->s_rst_owner != ANY_OWNER) &&
(parm->s_rst_owner != Owner(thing)))
continue;
/*
* Check for matching parent
*/
if ((parm->s_parent != NOTHING) &&
(parm->s_parent != Parent(thing)))
continue;
/*
* Check for matching zone
*/
if ((parm->s_zone != NOTHING) &&
(parm->s_zone != Zone(thing)))
continue;
/*
* Check for matching flags
*/
thing3flags = Flags3(thing);
thing2flags = Flags2(thing);
thing1flags = Flags(thing);
if ((thing1flags & parm->s_fset.word1) != parm->s_fset.word1)
continue;
if ((thing2flags & parm->s_fset.word2) != parm->s_fset.word2)
continue;
if ((thing3flags & parm->s_fset.word3) != parm->s_fset.word3)
continue;
/*
* Check for matching power
*/
thing1powers = Powers(thing);
thing2powers = Powers2(thing);
if ((thing1powers & parm->s_pset.word1) != parm->s_pset.word1)
continue;
if ((thing2powers & parm->s_pset.word2) != parm->s_pset.word2)
continue;
/*
* Check for matching name
*/
if (parm->s_rst_name != NULL) {
-15-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

Saturday, June 16, 2012 11:20 PM

if (!string_prefix((char *)PureName(thing),
parm->s_rst_name))
continue;

}
/*
* Check for successful evaluation
*/

if (parm->s_rst_eval != NULL) {
if (isGarbage(thing))
continue;
sprintf(buff, "#%d", thing);
buff2 = replace_string(BOUND_VAR, buff,
parm->s_rst_eval);
result = bp = alloc_lbuf("search_perform");
str = buff2;
exec(result, &bp, player, cause, cause,
EV_FCHECK | EV_EVAL | EV_NOTRACE, &str,
(char **)NULL, 0);
free_lbuf(buff2);
if (!*result || !xlate(result)) {
free_lbuf(result);
continue;
}
free_lbuf(result);
}
if (parm->s_rst_ufuntxt != NULL) {
if (isGarbage(thing))
continue;
sprintf(buff, "#%d", thing);
result = bp = alloc_lbuf("search_perform.result");
strcpy(atext, parm->s_rst_ufuntxt);
str = atext;
exec(result, &bp, player, cause, cause,
EV_FCHECK | EV_EVAL | EV_NOTRACE, &str,
&buff, 1);
if (!*result || !xlate(result)) {
free_lbuf(result);
continue;
}
free_lbuf(result);
}
/*
* It passed everything.
*/

Amazing.

olist_add(thing);
}
free_sbuf(buff);
if (atext)
free_lbuf(atext);
-16-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899

Saturday, June 16, 2012 11:20 PM

if (parm->s_rst_ufuntxt)
free_lbuf(parm->s_rst_ufuntxt);
mudstate.func_invk_ctr = save_invk_ctr;

static void search_mark(player, key)


dbref player;
int key;
{
dbref thing;
int nchanged, is_marked;
nchanged = 0;
for (thing = olist_first(); thing != NOTHING; thing = olist_next()) {
is_marked = Marked(thing);
/*
* Don't bother checking if marking and already marked * (or
* * * * if unmarking and not marked)
*/
if (((key == SRCH_MARK) && is_marked) ||
((key == SRCH_UNMARK) && !is_marked))
continue;
/*
* Toggle the mark bit and update the counters
*/
if (key == SRCH_MARK) {
Mark(thing);
nchanged++;
} else {
Unmark(thing);
nchanged++;
}

}
notify(player,
tprintf("%d objects %smarked",
nchanged, ((key == SRCH_MARK) ? "" : "un")));
return;

void do_search(player, cause, key, arg)


dbref player, cause;
int key;
char *arg;
{
int flag, destitute;
int rcount, ecount, tcount, pcount, gcount;
char *buff, *outbuf, *bp;
dbref thing, from, to;
SEARCH searchparm;
if ((key != SRCH_SEARCH) && (mudconf.control_flags & CF_DBCHECK)) {
-17-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

Saturday, June 16, 2012 11:20 PM

er_mark_disabled(player);
return;

}
if (!search_setup(player, arg, &searchparm))
return;
olist_push();
search_perform(player, cause, &searchparm);
destitute = 1;
/*
* If we are doing a @mark command, handle that here.
*/
if (key != SRCH_SEARCH) {
search_mark(player, key);
olist_pop();
return;
}
outbuf = alloc_lbuf("do_search.outbuf");
rcount = ecount = tcount = pcount = gcount = 0;
/*
* room search
*/
if (searchparm.s_rst_type == TYPE_ROOM ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing = olist_first(); thing != NOTHING; thing = olist_next()) {
if (Typeof(thing) != TYPE_ROOM)
continue;
if (flag) {
flag = 0;
destitute = 0;
notify(player, "\nROOMS:");
}
buff = unparse_object(player, thing, 0);
notify(player, buff);
free_lbuf(buff);
rcount++;
}
}
/*
* exit search
*/
if (searchparm.s_rst_type == TYPE_EXIT ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing = olist_first(); thing != NOTHING; thing = olist_next()) {
if (Typeof(thing) != TYPE_EXIT)
continue;
if (flag) {
flag = 0;
-18-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

Saturday, June 16, 2012 11:20 PM

destitute = 0;
notify(player, "\nEXITS:");

}
from = Exits(thing);
to = Location(thing);

bp = outbuf;
buff = unparse_object(player, thing, 0);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_str((char *)" [from ", outbuf, &bp);
buff = unparse_object(player, from, 0);
safe_str(((from == NOTHING) ? "NOWHERE" : buff),
outbuf, &bp);
free_lbuf(buff);
safe_str((char *)" to ", outbuf, &bp);
buff = unparse_object(player, to, 0);
safe_str(((to == NOTHING) ? "NOWHERE" : buff),
outbuf, &bp);
free_lbuf(buff);
safe_chr(']', outbuf, &bp);
*bp = '\0';
notify(player, outbuf);
ecount++;

}
}
/*
* object search
*/
if (searchparm.s_rst_type == TYPE_THING ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing = olist_first(); thing != NOTHING; thing = olist_next()) {
if (Typeof(thing) != TYPE_THING)
continue;
if (flag) {
flag = 0;
destitute = 0;
notify(player, "\nOBJECTS:");
}
bp = outbuf;
buff = unparse_object(player, thing, 0);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_str((char *)" [owner: ", outbuf, &bp);
buff = unparse_object(player, Owner(thing), 0);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);

-19-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058

Saturday, June 16, 2012 11:20 PM

safe_chr(']', outbuf, &bp);


*bp = '\0';
notify(player, outbuf);
tcount++;

}
/*
* garbage search
*/
if (searchparm.s_rst_type == TYPE_GARBAGE ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing = olist_first(); thing != NOTHING; thing = olist_next()) {
if (Typeof(thing) != TYPE_GARBAGE)
continue;
if (flag) {
flag = 0;
destitute = 0;
notify(player, "\nGARBAGE:");
}
bp = outbuf;
buff = unparse_object(player, thing, 0);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_str((char *)" [owner: ", outbuf, &bp);
buff = unparse_object(player, Owner(thing), 0);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_chr(']', outbuf, &bp);
*bp = '\0';
notify(player, outbuf);
gcount++;

}
}
/*
* player search
*/
if (searchparm.s_rst_type == TYPE_PLAYER ||
searchparm.s_rst_type == NOTYPE) {
flag = 1;
for (thing = olist_first(); thing != NOTHING; thing = olist_next()) {
if (Typeof(thing) != TYPE_PLAYER)
continue;
if (flag) {
flag = 0;
destitute = 0;
notify(player, "\nPLAYERS:");
}
bp = outbuf;
buff = unparse_object(player, thing, 0);
safe_str(buff, outbuf, &bp);
-20-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

Saturday, June 16, 2012 11:20 PM

free_lbuf(buff);
if (searchparm.s_wizard) {
safe_str((char *)" [location: ",
outbuf, &bp);
buff = unparse_object(player,
Location(thing), 0);
safe_str(buff, outbuf, &bp);
free_lbuf(buff);
safe_chr(']', outbuf, &bp);
}
*bp = '\0';
notify(player, outbuf);
pcount++;

}
}
/*
* if nothing found matching search criteria
*/

if (destitute) {
notify(player, "Nothing found.");
} else {
sprintf(outbuf,
"\nFound: Rooms...%d Exits...%d Objects...%d
rcount, ecount, tcount, pcount, gcount);
notify(player, outbuf);
}
free_lbuf(outbuf);
olist_pop();

Players...%d

Garbage...%d" ,

/* --------------------------------------------------------------------------* do_floaters: Report floating rooms.


*/
static void mark_place(loc)
dbref loc;
{
dbref exit;
/* If already marked, exit.

Otherwise set marked. */

if (!Good_obj(loc))
return;
if (Marked(loc))
return;
Mark(loc);
/* Visit all places you can get to via exits from here. */
for (exit = Exits(loc); exit != NOTHING; exit = Next(exit)) {
if (Good_obj(Location(exit)))
mark_place(Location(exit));
-21-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

Saturday, June 16, 2012 11:20 PM

void do_floaters(player, cause, key, name)


dbref player, cause;
int key;
char *name;
{
dbref owner, i, total;
char *buff;
/* Figure out who we're going to search. */
if (key & FLOATERS_ALL) {
if (!Search(player)) {
notify(player, NOPERM_MESSAGE);
return;
}
owner = NOTHING;
} else {
if (!name || !*name) {
owner = Owner(player);
} else {
owner = lookup_player(player, name, 1);
if (!Good_obj(owner)) {
notify(player, "Not found.");
return;
}
if (!Controls(player, owner) && !Search(player)) {
notify(player, NOPERM_MESSAGE);
return;
}
}
}
/* We're walking the db, so this costs as much as a search. */
if (!payfor(player, mudconf.searchcost)) {
notify(player, tprintf("You don't have enough %s.",
mudconf.many_coins));
return;
}
/* Mark everyplace you can get to via exits from the starting room */
Unmark_all(i);
if (Good_loc(mudconf.guest_start_room))
mark_place(mudconf.guest_start_room);
mark_place(Good_loc(mudconf.start_room) ? mudconf.start_room : 0);
/* Report rooms that aren't marked */
total = 0;
-22-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217

Saturday, June 16, 2012 11:20 PM

DO_WHOLE_DB(i) {
if (isRoom(i) && !Going(i) && !Marked(i)) {
if ((owner == NOTHING) || (Owner(i) == owner)) {
total++;
buff = unparse_object(player, i, 0);
notify(player, buff);
free_lbuf(buff);
}
}
}

notify(player, tprintf("%d floating %s found.",


total, (total == 1) ? "room" : "rooms"));

/*
* --------------------------------------------------------------------------* * do_markall: set or clear the mark bits of all objects in the db.
*/
void do_markall(player, cause, key)
dbref player, cause;
int key;
{
int i;

if (mudconf.control_flags & CF_DBCHECK) {


er_mark_disabled(player);
return;
}
if (key == MARK_SET)
Mark_all(i);
else if (key == MARK_CLEAR)
Unmark_all(i);
if (!Quiet(player))
notify(player, "Done.");

/*
* --------------------------------------------------------------------------* * do_apply_marked: Perform a command for each marked obj in the db.
*/
void do_apply_marked(player, cause, key, command, cargs, ncargs)
dbref player, cause;
int key, ncargs;
char *command, *cargs[];
{
char *buff;
int i;
int number = 0;
if (mudconf.control_flags & CF_DBCHECK) {
-23-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

Saturday, June 16, 2012 11:20 PM

er_mark_disabled(player);
return;

}
buff = alloc_sbuf("do_apply_marked");
DO_WHOLE_DB(i) {
if (Marked(i)) {
sprintf(buff, "#%d", i);
number++;
bind_and_queue(player, cause, command, buff,
cargs, ncargs, number, 0);
}
}
free_sbuf(buff);
if (!Quiet(player))
notify(player, "Done.");

/*
* --------------------------------------------------------------------------* * Object list management routines:
* * olist_push, olist_pop, olist_add, olist_first, olist_next
*/
/*
* olist_push: Create a new object list at the top of the object list stack
*/
void NDECL(olist_push)
{
OLSTK *ol;
ol = (OLSTK *)XMALLOC(sizeof(OLSTK), "olist_push");
ol->next = mudstate.olist;
mudstate.olist = ol;

ol->head = NULL;
ol->tail = NULL;
ol->cblock = NULL;
ol->count = 0;
ol->citm = 0;

/*
* olist_pop: Pop one entire list off the object list stack
*/
void NDECL(olist_pop)
{
OLSTK *ol;
OBLOCK *op, *onext;
ol = mudstate.olist->next;

-24-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

Saturday, June 16, 2012 11:20 PM

for (op = mudstate.olist->head; op != NULL; op = onext) {


onext = op->next;
free_lbuf(op);
}
XFREE(mudstate.olist, "olist_push");
mudstate.olist = ol;

/*
* olist_add: Add an entry to the object list
*/
void olist_add(item)
dbref item;
{
OBLOCK *op;

if (!mudstate.olist->head) {
op = (OBLOCK *) alloc_lbuf("olist_add.first");
mudstate.olist->head = mudstate.olist->tail = op;
mudstate.olist->count = 0;
op->next = NULL;
} else if (mudstate.olist->count >= OBLOCK_SIZE) {
op = (OBLOCK *) alloc_lbuf("olist_add.next");
mudstate.olist->tail->next = op;
mudstate.olist->tail = op;
mudstate.olist->count = 0;
op->next = NULL;
} else {
op = mudstate.olist->tail;
}
op->data[mudstate.olist->count++] = item;

/*
* olist_first: Return the first entry in the object list
*/
dbref NDECL(olist_first)
{
if (!mudstate.olist->head)
return NOTHING;
if ((mudstate.olist->head == mudstate.olist->tail) &&
(mudstate.olist->count == 0))
return NOTHING;
mudstate.olist->cblock = mudstate.olist->head;
mudstate.olist->citm = 0;
return mudstate.olist->cblock->data[mudstate.olist->citm++];
}
dbref NDECL(olist_next)
{
dbref thing;
-25-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.c

1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337

Saturday, June 16, 2012 11:20 PM

if (!mudstate.olist->cblock)
return NOTHING;
if ((mudstate.olist->cblock == mudstate.olist->tail) &&
(mudstate.olist->citm >= mudstate.olist->count))
return NOTHING;
thing = mudstate.olist->cblock->data[mudstate.olist->citm++];
if (mudstate.olist->citm >= OBLOCK_SIZE) {
mudstate.olist->cblock = mudstate.olist->cblock->next;
mudstate.olist->citm = 0;
}
return thing;

-26-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\walkdb.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

Saturday, June 16, 2012 11:04 PM

/* walkdb.h - structures used in commands that walk the entire db */


/* $Id: walkdb.h,v 1.2 2002/07/25 15:47:28 lwl Exp $ */
#include "copyright.h"
#ifndef __WALKDB_H
#define __WALKDB_H
/* Search structure, used by @search and search(). */
typedef struct search_type SEARCH;
struct search_type {
int s_wizard;
dbref
s_owner;
dbref
s_rst_owner;
int s_rst_type;
FLAGSET s_fset;
POWERSET s_pset;
dbref
s_parent;
dbref
s_zone;
char
*s_rst_name;
char
*s_rst_eval;
char
*s_rst_ufuntxt;
int low_bound;
int high_bound;
};
/* Stats structure, used by @stats and stats(). */
typedef struct stats_type STATS;
struct stats_type {
int s_total;
int s_rooms;
int s_exits;
int s_things;
int s_players;
int s_going;
int s_garbage;
int s_unknown;
};
extern int FDECL(search_setup, (dbref, char *, SEARCH *));
extern void FDECL(search_perform, (dbref, dbref, SEARCH *));
extern int FDECL(get_stats, (dbref, dbref, STATS *));
#endif /* __WALKDB_H */

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:20 PM

/* wild.c - wildcard routines */


/* $Id: wild.c,v 1.19 2002/08/28 15:24:09 rmg Exp $ */
/*
* Written by T. Alexander Popiel, 24 June 1993
* Last modified by T. Alexander Popiel, 19 August 1993
*
* Thanks go to Andrew Molitor for debugging
* Thanks also go to Rich $alz for code to benchmark against
*
* Copyright (c) 1993 by T. Alexander Popiel
* This code is hereby placed under GNU copyleft,
* see copyright.h for details.
*/
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by code */
extern int FDECL(set_register, (const char *, char *, char *)); /* funvars.c */
#define FIXCASE(a) (tolower(a))
#define EQUAL(a,b) ((a == b) || (FIXCASE(a) == FIXCASE(b)))
#define NOTEQUAL(a,b) ((a != b) && (FIXCASE(a) != FIXCASE(b)))
static char **arglist;
static int numargs;

/* argument return space */


/* argument return size */

/* --------------------------------------------------------------------------* check_literals: All literals in a wildcard pattern must appear in the


*
data string, or no match is possible.
*/
static int check_literals(tstr, dstr)
char *tstr, *dstr;
{
char pattern[LBUF_SIZE], data[LBUF_SIZE], *p, *dp, *ep, *xp;
int len;
/* Fast match the beginning of the string. */
while ((*tstr != '*') && (*tstr != '?')) {
if (*tstr == '\\')
tstr++;
if (NOTEQUAL(*dstr, *tstr))
-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:20 PM

return 0;
if (!*dstr)
return 1;
tstr++;
dstr++;
}
/* Make a lower-case copy of the data. */
ep = data;
while (*dstr) {
*ep = FIXCASE(*dstr);
ep++;
dstr++;
}
*ep = '\0';
/* Fast match the end of the string.
* When we're done with this, we'll also have established a better
* end point for the remainder of the literals match.
* ep will point to the null terminator at the end of the data string
* we need to worry about (i.e., that which has not already been
* taken care of by our backwards match).
* xp will point to the last character of the pattern string we need
* to worry about.
*/
ep--;
xp = tstr + strlen(tstr) - 1;
while ((ep >= dstr) && (xp >= tstr) && (*xp != '*') && (*xp != '?')) {
if ((*xp != '\\') && NOTEQUAL(*ep, *xp))
return 0;
ep--;
xp--;
}
ep++;
*ep = '\0';
/* Walk the pattern string. Use the wildcard characters as delimiters,
* to extract the literal strings that we need to match sequentially.
*/
dp = data;
while (*tstr && (tstr <= xp)) {
while ((*tstr == '*') || (*tstr == '?'))
tstr++;
if (!*tstr || (tstr > xp))
return 1;
p = pattern;
len = 0;
while (*tstr && (*tstr != '*') && (*tstr != '?') && (tstr <= xp)) {
if (*tstr == '\\')
tstr++;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:20 PM

*p = FIXCASE(*tstr);
p++;
tstr++;
len++;

}
*p = '\0';
if (len) {
if ((dp = strstr(dp, pattern)) == NULL)
return 0;
dp += len;
}
if (dp >= ep)
return 1;
}
}

return 1;

/* --------------------------------------------------------------------------* quick_wild: do a wildcard match, without remembering the wild data.


*
* This routine will cause crashes if fed NULLs instead of strings.
*/
static int real_quick_wild(tstr, dstr)
char *tstr, *dstr;
{
int st;
if (mudstate.wild_times_lev > mudconf.wild_times_lim)
return -1;
mudstate.wild_times_lev++;
while (*tstr != '*') {
switch (*tstr) {
case '?':
/* Single character match. Return false if at end
* of data.
*/
if (!*dstr)
return 0;
break;
case '\\':
/* Escape character. Move up, and force literal
* match of next character.
*/
tstr++;
/*
* FALL THROUGH
*/
default:
/* Literal character. Check for a match. If
* matching end of data, return true.
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:20 PM

*/
if (NOTEQUAL(*dstr, *tstr))
return 0;
if (!*dstr)
return 1;

}
tstr++;
dstr++;

/* Skip over '*'. */


tstr++;
/* Return true on trailing '*'. */
if (!*tstr)
return 1;
/* Skip over wildcards. */
while ((*tstr == '?') || (*tstr == '*')) {
if (*tstr == '?') {
if (!*dstr)
return 0;
dstr++;
}
tstr++;
}
/* Skip over a backslash in the pattern string if it is there. */
if (*tstr == '\\')
tstr++;
/* Return true on trailing '*'. */
if (!*tstr)
return 1;
/* Scan for possible matches. */

while (*dstr) {
if (EQUAL(*dstr, *tstr)) {
if ((st = real_quick_wild(tstr + 1, dstr + 1)) != 0)
return st;
}
dstr++;
}
return 0;

int quick_wild(tstr, dstr)


-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:20 PM

char *tstr, *dstr;


int st;
if (!check_literals(tstr, dstr))
return 0;
mudstate.wild_times_lev = 0;

st = real_quick_wild(tstr, dstr);
if ((st < 0) && (mudstate.wild_times_lev > mudconf.wild_times_lim))
return 0;
return st;

/* --------------------------------------------------------------------------* wild1: INTERNAL: do a wildcard match, remembering the wild data.


*
* DO NOT CALL THIS FUNCTION DIRECTLY - DOING SO MAY RESULT IN
* SERVER CRASHES AND IMPROPER ARGUMENT RETURN.
*
* Side Effect: this routine modifies the 'arglist' static global
* variable.
*/
static int real_wild1(tstr, dstr, arg)
char *tstr, *dstr;
int arg;
{
char *datapos;
int argpos, numextra, st;
if (mudstate.wild_times_lev > mudconf.wild_times_lim)
return -1;
mudstate.wild_times_lev++;
while (*tstr != '*') {
switch (*tstr) {
case '?':
/* Single character match.
* of data.
*/
if (!*dstr)
return 0;
arglist[arg][0] = *dstr;
arglist[arg][1] = '\0';
arg++;

Return false if at end

/* Jump to the fast routine if we can. */


if (arg >= numargs)
return real_quick_wild(tstr + 1, dstr + 1);
break;
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:20 PM

case '\\':
/* Escape character. Move up, and force literal
* match of next character.
*/
tstr++;
/*
* FALL THROUGH
*/
default:
/* Literal character. Check for a match. If
* matching end of data, return true.
*/
if (NOTEQUAL(*dstr, *tstr))
return 0;
if (!*dstr)
return 1;
}
tstr++;
dstr++;

/* If at end of pattern, slurp the rest, and leave. */


if (!tstr[1]) {
StringCopyTrunc(arglist[arg], dstr, LBUF_SIZE - 1);
arglist[arg][LBUF_SIZE - 1] = '\0';
return 1;
}
/* Remember current position for filling in the '*' return. */
datapos = dstr;
argpos = arg;
/* Scan forward until we find a non-wildcard. */
do {

if (argpos < arg) {


/* Fill in arguments if someone put another '*'
* before a fixed string.
*/
arglist[argpos][0] = '\0';
argpos++;
/* Jump to the fast routine if we can. */
if (argpos >= numargs)
return real_quick_wild(tstr, dstr);
/* Fill in any intervening '?'s */
while (argpos < arg) {
arglist[argpos][0] = *datapos;
arglist[argpos][1] = '\0';
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:20 PM

datapos++;
argpos++;
/* Jump to the fast routine if we can. */
if (argpos >= numargs)
return real_quick_wild(tstr, dstr);

}
}
/* Skip over the '*' for now... */
tstr++;
arg++;
/* Skip over '?'s for now... */
numextra = 0;
while (*tstr == '?') {
if (!*dstr)
return 0;
tstr++;
dstr++;
arg++;
numextra++;
}
} while (*tstr == '*');

/* Skip over a backslash in the pattern string if it is there. */


if (*tstr == '\\')
tstr++;
/* Check for possible matches. This loop terminates either at end
* of data (resulting in failure), or at a successful match.
*/
while (1) {
/* Scan forward until first character matches. */
if (*tstr)
while (NOTEQUAL(*dstr, *tstr)) {
if (!*dstr)
return 0;
dstr++;
} else
while (*dstr)
dstr++;
/* The first character matches, now. Check if the rest
* does, using the fastest method, as usual.
*/
if (*dstr) {
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:20 PM

st = (arg < numargs) ?


real_wild1(tstr + 1, dstr + 1, arg) :
real_quick_wild(tstr + 1, dstr + 1);
if (st < 0)
return st;
} else {
st = 0;
}
if (!*dstr || st) {
/* Found a match! Fill in all remaining arguments.
* First do the '*'...
*/
StringCopyTrunc(arglist[argpos], datapos,
(dstr - datapos) - numextra);
arglist[argpos][(dstr - datapos) - numextra] = '\0';
datapos = dstr - numextra;
argpos++;
/* Fill in any trailing '?'s that are left. */
while (numextra) {
if (argpos >= numargs)
return 1;
arglist[argpos][0] = *datapos;
arglist[argpos][1] = '\0';
datapos++;
argpos++;
numextra--;
}
/* It's done! */

return 1;
} else {
dstr++;
}

int wild1(tstr, dstr, arg)


char *tstr, *dstr;
int arg;
{
int st;
if (!check_literals(tstr, dstr))
return 0;
mudstate.wild_times_lev = 0;
st = real_wild1(tstr, dstr, arg);
if ((st < 0) && (mudstate.wild_times_lev > mudconf.wild_times_lim))
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:20 PM

return 0;
return st;

/* --------------------------------------------------------------------------* wild: do a wildcard match, remembering the wild data.


*
* This routine will cause crashes if fed NULLs instead of strings.
*
* This function may crash if alloc_lbuf() fails.
*
* Side Effect: this routine modifies the 'arglist' and 'numargs'
* static global variables.
*/
int wild(tstr, dstr, args, nargs)
char *tstr, *dstr, *args[];
int nargs;
{
int i, value;
char *scan;
/* Initialize the return array. */
for (i = 0; i < nargs; i++)
args[i] = NULL;
/* Do fast match. */
while ((*tstr != '*') && (*tstr != '?')) {
if (*tstr == '\\')
tstr++;
if (NOTEQUAL(*dstr, *tstr))
return 0;
if (!*dstr)
return 1;
tstr++;
dstr++;
}
/* Allocate space for the return args. */
i = 0;
scan = tstr;
while (*scan && (i < nargs)) {
switch (*scan) {
case '?':
args[i] = alloc_lbuf("wild.?");
i++;
break;
case '*':
args[i] = alloc_lbuf("wild.*");
i++;
}
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:20 PM

scan++;

/* Put stuff in globals for quick recursion. */


arglist = args;
numargs = nargs;
/* Do the match. */
value = nargs ? wild1(tstr, dstr, 0) : quick_wild(tstr, dstr);
/* Clean out any fake match data left by wild1. */

for (i = 0; i < nargs; i++)


if ((args[i] != NULL) && (!*args[i] || !value)) {
free_lbuf(args[i]);
args[i] = NULL;
}
return value;

/* --------------------------------------------------------------------------* wild_match: do either an order comparison or a wildcard match,


* remembering the wild data, if wildcard match is done.
*
* This routine will cause crashes if fed NULLs instead of strings.
*/
int wild_match(tstr, dstr)
char *tstr, *dstr;
{
switch (*tstr) {
case '>':
tstr++;
if (isdigit(*tstr) || (*tstr == '-'))
return (atoi(tstr) < atoi(dstr));
else
return (strcmp(tstr, dstr) < 0);
case '<':
tstr++;
if (isdigit(*tstr) || (*tstr == '-'))
return (atoi(tstr) > atoi(dstr));
else
return (strcmp(tstr, dstr) > 0);
}
}

return quick_wild(tstr, dstr);

/* ---------------------------------------------------------------------* register_match: Do a wildcard match, setting the wild data into the
* global registers.
*/
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:20 PM

int register_match(tstr, dstr, args, nargs)


char *tstr, *dstr, *args[];
int nargs;
{
int i, value;
char *buff, *scan, *p, *end, *q_names[NUM_ENV_VARS];
/* Initialize return array. */
for (i = 0; i < nargs; i++)
args[i] = q_names[i] = NULL;
/* Do fast match. */
while ((*tstr != '*') && (*tstr != '?')) {
if (*tstr == '\\')
tstr++;
if (NOTEQUAL(*dstr, *tstr))
return 0;
if (!*dstr)
return 1;
tstr++;
dstr++;
}
/* Convert string, allocate space for the return args. */
i = 0;
scan = tstr;
buff = alloc_lbuf("rmatch.buff");
p = buff;
while (*scan) {
*p++ = *scan;
switch (*scan) {
case '?':
/* FALLTHRU */
case '*':
args[i] = alloc_lbuf("xvars_match.wild");
scan++;
if (*scan == '{') {
if ((end = strchr(scan + 1, '}')) != NULL) {
*end = '\0';
if (*(scan + 1)) {
q_names[i] = XSTRDUP(scan + 1,
"rmatch.name");
}
scan = end + 1;
}
}
i++;
break;
default:
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wild.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

Saturday, June 16, 2012 11:20 PM

scan++;
}
}
*p = '\0';
/* Go do it. */
arglist = args;
numargs = nargs;
value = nargs ? wild1(buff, dstr, 0) : quick_wild(buff, dstr);
/* Copy things into registers. Clean fake match data from wild1(). */
for (i = 0; i < nargs; i++) {
if ((args[i] != NULL) && (!*args[i] || !value)) {
free_lbuf(args[i]);
args[i] = NULL;
}
if (args[i] && q_names[i])
set_register("rmatch", q_names[i], args[i]);
if (q_names[i]) {
XFREE(q_names[i], "rmatch.name");
}
}
free_lbuf(buff);
}

return value;

-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

Saturday, June 16, 2012 11:19 PM

/* wiz.c - Wizard-only commands */


/* $Id: wiz.c,v 1.34 2003/07/14 18:55:22 lwl Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include
#include
#include
#include

"alloc.h" /* required by mudconf */


"flags.h" /* required by mudconf */
"htab.h"
/* required by mudconf */
"mudconf.h"
/* required by code */

#include "db.h"
/* required by externs */
#include "externs.h"
/* required by interface */
#include "interface.h" /* required by code */
#include
#include
#include
#include
#include

"file_c.h" /*
"match.h" /*
"command.h"
"attrs.h" /*
"powers.h" /*

required by code */
required by code */
/* required by code */
required by code */
required by code */

void do_teleport(player, cause, key, arg1, arg2)


dbref player, cause;
int key;
char *arg1, *arg2;
{
dbref victim, destination, loc, exitloc;
char *to;
int hush = 0;
if (((Fixed(player)) || (Fixed(Owner(player)))) &&
!(Tel_Anywhere(player))) {
notify(player, mudconf.fixed_tel_msg);
return;
}
/* get victim */
if (*arg2 == '\0') {
victim = player;
to = arg1;
} else {
init_match(player, arg1, NOTYPE);
match_everything(0);
victim = noisy_match_result();

if (victim == NOTHING)
return;
to = arg2;

-1-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

Saturday, June 16, 2012 11:19 PM

/* Validate type of victim */


if (!Has_location(victim) && !isExit(victim)) {
notify_quiet(player, "You can't teleport that.");
return;
}
/* If this is an exit, we need to control it, or it must be
* unlinked. (Same permissions as @link.) Or, we can control
* the room. (Same permissions as get.)
* Otherwise, fail if we're not Tel_Anything, and we don't control
* the victim or the victim's location.
*/
if (isExit(victim)) {
if ((Location(victim) != NOTHING) && !Controls(player, victim) &&
!Controls(player, Exits(victim))) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
} else if (!Controls(player, victim) &&
!Controls(player, Location(victim)) &&
!Tel_Anything(player)) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
/*
* Check for teleporting home. Exits don't have homes.
*/
if (!string_compare(to, "home")) {
if (isExit(victim))
notify_quiet(player, NOPERM_MESSAGE);
else
move_via_teleport(victim, HOME, cause, 0);
return;
}
/*
* Find out where to send the victim
*/
init_match(player, to, NOTYPE);
match_everything(0);
destination = match_result();
switch (destination) {
case NOTHING:
notify_quiet(player, "No match.");
return;
case AMBIGUOUS:
notify_quiet(player,
"I don't know which destination you mean!" );
return;
-2-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

Saturday, June 16, 2012 11:19 PM

default:
if ((victim == destination) || Going(destination)) {
notify_quiet(player, "Bad destination.");
return;
}
}
/*
* If fascist teleport is on, you must control the victim's ultimate
* location (after LEAVEing any objects) or it must be JUMP_OK.
*/
if (mudconf.fascist_tport) {
loc = where_room(victim);
if (!Good_obj(loc) || !isRoom(loc) ||
!(Controls(player, loc) || Jump_ok(loc) ||
Tel_Anywhere(player))) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
}
/* If this is an exit, the same privs involved as @open apply. */
if (isExit(victim)) {
if (!Has_exits(destination) ||
(!Controls(player, destination) && !Open_Anywhere(player))) {
notify_quiet(player, NOPERM_MESSAGE);
return;
}
exitloc = Exits(victim);
s_Exits(exitloc, remove_first(Exits(exitloc), victim));
s_Exits(destination, insert_first(Exits(destination), victim));
s_Exits(victim, destination);
s_Modified(victim);
notify_quiet(player, "Teleported.");
return;
}
if (Has_contents(destination)) {
/*
* You must control the destination, or it must be a JUMP_OK
* room where the victim passes its TELEPORT lock, or you
* must be Tel_Anywhere.
*/
if (!(Controls(player, destination) ||
(Jump_ok(destination) &&
could_doit(victim, destination, A_LTPORT)) ||
Tel_Anywhere(player))) {
/*
-3-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

Saturday, June 16, 2012 11:19 PM

* Nope, report failure


*/
if (player != victim)
notify_quiet(player, NOPERM_MESSAGE);
did_it(victim, destination,
A_TFAIL, "You can't teleport there!",
A_OTFAIL, NULL, A_ATFAIL, 0, (char **)NULL, 0,
MSG_MOVE);
return;

}
/*
* We're OK, do the teleport
*/

if (key & TELEPORT_QUIET)


hush = HUSH_ENTER | HUSH_LEAVE;

if (move_via_teleport(victim, destination, cause, hush)) {


if (player != victim) {
if (!Quiet(player))
notify_quiet(player, "Teleported.");
}
}
} else if (isExit(destination)) {
if (Exits(destination) == Location(victim)) {
move_exit(victim, destination, 0,
"You can't go that way.", 0);
} else {
notify_quiet(player, "I can't find that exit.");
}
}

/*
* --------------------------------------------------------------------------* do_force_prefixed: Interlude to do_force for the # command
*/
void do_force_prefixed(player, cause, key, command, args, nargs)
dbref player, cause;
int key, nargs;
char *command, *args[];
{
char *cp;
cp = parse_to(&command, ' ', 0);
if (!command)
return;
while (*command && isspace(*command))
command++;
if (*command)
do_force(player, cause, key, cp, command, args, nargs);
-4-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

Saturday, June 16, 2012 11:19 PM

}
/*
* --------------------------------------------------------------------------* do_force: Force an object to do something.
*/
void do_force(player, cause, key, what, command, args, nargs)
dbref player, cause;
int key, nargs;
char *what, *command, *args[];
{
dbref victim;
if ((victim = match_controlled(player, what)) == NOTHING)
return;
/*
* force victim to do command
*/

if (key & FRC_NOW)


process_cmdline(victim, player, command, args, nargs, NULL);
else
wait_que(victim, player, 0, NOTHING, 0, command, args, nargs,
mudstate.rdata);

/*
* --------------------------------------------------------------------------* do_toad: Turn a player into an object.
*/
void do_toad(player, cause, key, toad, newowner)
dbref player, cause;
int key;
char *toad, *newowner;
{
dbref victim, recipient, loc, aowner;
char *buf;
int count, aflags, alen;
init_match(player, toad, TYPE_PLAYER);
match_neighbor();
match_absolute();
match_player();
if ((victim = noisy_match_result()) == NOTHING)
return;
if (!isPlayer(victim)) {
notify_quiet(player, "Try @destroy instead.");
return;
}
-5-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

Saturday, June 16, 2012 11:19 PM

if (No_Destroy(victim)) {
notify_quiet(player, "You can't toad that player." );
return;
}
if ((newowner != NULL) && *newowner) {
init_match(player, newowner, TYPE_PLAYER);
match_neighbor();
match_absolute();
match_player();
if ((recipient = noisy_match_result()) == NOTHING)
return;
} else {
recipient = player;
}
STARTLOG(LOG_WIZARD, "WIZ", "TOAD")
log_name_and_loc(victim);
log_printf(" was @toaded by ");
log_name(player);
ENDLOG
/*
* Clear everything out
*/
if (key & TOAD_NO_CHOWN) {
count = -1;
} else {
count = chown_all(victim, recipient, player, 0);
s_Owner(victim, recipient); /*
* you get it
*/
}
s_Flags(victim, TYPE_THING | HALT);
s_Flags2(victim, 0);
s_Flags3(victim, 0);
s_Pennies(victim, 1);
/*
* notify people
*/
loc = Location(victim);
buf = alloc_mbuf("do_toad");
sprintf(buf, "%s has been turned into a slimy toad!" , Name(victim));
notify_except2(loc, player, victim, player, buf, 0);
sprintf(buf, "You toaded %s! (%d objects @chowned)" , Name(victim),
count + 1);
notify_quiet(player, buf);
/*
* Zap the name from the name hash table
*/
-6-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

Saturday, June 16, 2012 11:19 PM

delete_player_name(victim, Name(victim));
sprintf(buf, "a slimy toad named %s", Name(victim));
s_Name(victim, buf);
free_mbuf(buf);
/*
* Zap the alias too
*/
buf = atr_pget(victim, A_ALIAS, &aowner, &aflags, &alen);
delete_player_name(victim, buf);
free_lbuf(buf);

count = boot_off(victim,
(char *)"You have been turned into a slimy toad!" );
notify_quiet(player, tprintf("%d connection%s closed.",
count, (count == 1 ? "" : "s")));

void do_newpassword(player, cause, key, name, password)


dbref player, cause;
int key;
char *name, *password;
{
dbref victim;
char *buf, *bp;
if ((victim = lookup_player(player, name, 0)) == NOTHING) {
notify_quiet(player, "No such player.");
return;
}
if (*password != '\0' && !ok_password(password, player)) {
/* Can set null passwords, but not bad passwords.
* Notification of reason done by ok_password().
*/
return;
}
if (God(victim)) {
notify_quiet(player, "You cannot change that player's password." );
return;
}
STARTLOG(LOG_WIZARD, "WIZ", "PASS")
log_name(player);
log_printf(" changed the password of ");
log_name(victim);
ENDLOG
/*
* it's ok, do it
*/
s_Pass(victim, crypt((const char *)password, "XX"));
-7-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

Saturday, June 16, 2012 11:19 PM

notify_quiet(player, "Password changed.");


buf = alloc_lbuf("do_newpassword");
bp = buf;
safe_tprintf_str(buf, &bp,
"Your password has been changed by %s." ,
Name(player));
notify_quiet(victim, buf);
free_lbuf(buf);

void do_boot(player, cause, key, name)


dbref player, cause;
int key;
char *name;
{
dbref victim;
char *buf, *bp;
int count;
if (!(Can_Boot(player))) {
notify(player, NOPERM_MESSAGE);
return;
}
if (key & BOOT_PORT) {
if (is_number(name)) {
victim = atoi(name);
} else {
notify_quiet(player, "That's not a number!");
return;
}
STARTLOG(LOG_WIZARD, "WIZ", "BOOT")
log_printf("Port %d was @booted by ", victim);
log_name(player);
ENDLOG
} else {
init_match(player, name, TYPE_PLAYER);
match_neighbor();
match_absolute();
match_player();
if ((victim = noisy_match_result()) == NOTHING)
return;
if (God(victim)) {
notify_quiet(player, "You cannot boot that player!" );
return;
}
if ((!isPlayer(victim) && !God(player)) ||
(player == victim)) {
notify_quiet(player, "You can only boot off other players!" );
return;
}
STARTLOG(LOG_WIZARD, "WIZ", "BOOT")
log_name_and_loc(victim);
-8-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

Saturday, June 16, 2012 11:19 PM

log_printf(" was @booted by ");


log_name(player);
ENDLOG
notify_quiet(player, tprintf("You booted %s off!", Name(victim)));

}
if (key & BOOT_QUIET) {
buf = NULL;
} else {
bp = buf = alloc_lbuf("do_boot.msg");
safe_name(player, buf, &bp);
safe_str((char *)" gently shows you the door." , buf, &bp);
*bp = '\0';
}

if (key & BOOT_PORT)


count = boot_by_port(victim, !God(player), buf);
else
count = boot_off(victim, buf);
notify_quiet(player, tprintf("%d connection%s closed.",
count, (count == 1 ? "" : "s")));
if (buf)
free_lbuf(buf);

/*
* --------------------------------------------------------------------------do_poor: Reduce the wealth of anyone over a specified amount.
*/
void do_poor(player, cause, key, arg1)
dbref player, cause;
int key;
char *arg1;
{
dbref a;
int amt, curamt;

if (!is_number(arg1))
return;
amt = atoi(arg1);
DO_WHOLE_DB(a) {
if (isPlayer(a)) {
curamt = Pennies(a);
if (amt < curamt)
s_Pennies(a, amt);
}
}

/*
* --------------------------------------------------------------------------* do_cut: Chop off a contents or exits chain after the named item.
*/
-9-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

Saturday, June 16, 2012 11:19 PM

void do_cut(player, cause, key, thing)


dbref player, cause;
int key;
char *thing;
{
dbref object;

object = match_controlled(player, thing);


switch (object) {
case NOTHING:
notify_quiet(player, "No match.");
break;
case AMBIGUOUS:
notify_quiet(player, "I don't know which one");
break;
default:
s_Next(object, NOTHING);
notify_quiet(player, "Cut.");
}

/* -------------------------------------------------------------------------* do_motd: Wizard-settable message of the day (displayed on connect)


*/
void do_motd(player, cause, key, message)
dbref player, cause;
int key;
char *message;
{
int is_brief;
is_brief = 0;
if (key & MOTD_BRIEF) {
is_brief = 1;
key = key & ~MOTD_BRIEF;
if (key == MOTD_ALL)
key = MOTD_LIST;
else if (key != MOTD_LIST)
key |= MOTD_BRIEF;
}
message[GBUF_SIZE - 1] = '\0';
switch (key) {
case MOTD_ALL:
if (mudconf.motd_msg) {
XFREE(mudconf.motd_msg, "do_motd.motd");
}
mudconf.motd_msg = XSTRDUP(message, "do_motd.motd");
if (!Quiet(player))
notify_quiet(player, "Set: MOTD.");
break;
case MOTD_WIZ:
-10-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

Saturday, June 16, 2012 11:19 PM

if (mudconf.wizmotd_msg) {
XFREE(mudconf.wizmotd_msg, "do_motd.wizmotd");
}
mudconf.wizmotd_msg = XSTRDUP(message, "do_motd.wizmotd");
if (!Quiet(player))
notify_quiet(player, "Set: Wizard MOTD.");
break;
case MOTD_DOWN:
if (mudconf.downmotd_msg) {
XFREE(mudconf.downmotd_msg, "do_motd.downmotd");
}
mudconf.downmotd_msg = XSTRDUP(message, "do_motd.downmotd");
if (!Quiet(player))
notify_quiet(player, "Set: Down MOTD.");
break;
case MOTD_FULL:
if (mudconf.fullmotd_msg) {
XFREE(mudconf.fullmotd_msg, "do_motd.fullmotd");
}
mudconf.fullmotd_msg = XSTRDUP(message, "do_motd.fullmotd");
if (!Quiet(player))
notify_quiet(player, "Set: Full MOTD.");
break;
case MOTD_LIST:
if (Wizard(player)) {
if (!is_brief) {
notify_quiet(player,
"----- motd file -----");
fcache_send(player, FC_MOTD);
notify_quiet(player,
"----- wizmotd file -----");
fcache_send(player, FC_WIZMOTD);
notify_quiet(player,
"----- motd messages -----");
}
if (mudconf.motd_msg && *mudconf.motd_msg) {
notify_quiet(player,
tprintf("MOTD: %s",
mudconf.motd_msg));
} else {
notify_quiet(player, "No MOTD.");
}
if (mudconf.wizmotd_msg && *mudconf.wizmotd_msg) {
notify_quiet(player,
tprintf("Wizard MOTD: %s",
mudconf.wizmotd_msg));
} else {
notify_quiet(player, "No Wizard MOTD.");
}
if (mudconf.downmotd_msg && *mudconf.downmotd_msg) {
notify_quiet(player,
tprintf("Down MOTD: %s",
mudconf.downmotd_msg));
-11-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

Saturday, June 16, 2012 11:19 PM

} else {
notify_quiet(player, "No Down MOTD.");
}
if (mudconf.fullmotd_msg && *mudconf.fullmotd_msg) {
notify_quiet(player,
tprintf("Full MOTD: %s",
mudconf.fullmotd_msg));
} else {
notify_quiet(player, "No Full MOTD.");
}
} else {
if (Guest(player))
fcache_send(player, FC_CONN_GUEST);
else
fcache_send(player, FC_MOTD);
if (mudconf.motd_msg && *mudconf.motd_msg) {
notify_quiet(player, mudconf.motd_msg);
} else {
notify_quiet(player, "No MOTD.");
}
}
break;
default:
notify_quiet(player, "Illegal combination of switches." );
}

/* --------------------------------------------------------------------------* do_global: enable or disable global control flags


*/
/* *INDENT-OFF* */
NAMETAB enable_names[] = {
{(char *)"building",
{(char *)"checkpointing",
{(char *)"cleaning",
{(char *)"dequeueing",
{(char *)"god_monitoring",
{(char *)"idlechecking",
{(char *)"interpret",
{(char *)"logins",
3,
{(char *)"eventchecking",
{ NULL,
0, 0,

1, CA_PUBLIC, CF_BUILD},
2, CA_PUBLIC, CF_CHECKPOINT},
2, CA_PUBLIC, CF_DBCHECK},
1, CA_PUBLIC, CF_DEQUEUE},
1, CA_PUBLIC, CF_GODMONITOR},
2, CA_PUBLIC, CF_IDLECHECK},
2, CA_PUBLIC, CF_INTERP},
CA_PUBLIC, CF_LOGIN},
2, CA_PUBLIC, CF_EVENTCHECK},
0}};

/* *INDENT-ON* */
void do_global(player, cause, key, flag)
dbref player, cause;
int key;
char *flag;
{
int flagvalue;
-12-

C:\Users\Richard\Downloads\tm31p6.tar\tm31p6\tinymush-3.1p6\src\wiz.c

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665

Saturday, June 16, 2012 11:19 PM

/*
* Set or clear the indicated flag
*/

flagvalue = search_nametab(player, enable_names, flag);


if (flagvalue < 0) {
notify_quiet(player, "I don't know about that flag." );
} else if (key == GLOB_ENABLE) {
mudconf.control_flags |= flagvalue;
STARTLOG(LOG_CONFIGMODS, "CFG", "GLOBAL")
log_name(player);
log_printf(" enabled: %s", flag);
ENDLOG
if (!Quiet(player))
notify_quiet(player, "Enabled.");
} else if (key == GLOB_DISABLE) {
mudconf.control_flags &= ~flagvalue;
STARTLOG(LOG_CONFIGMODS, "CFG", "GLOBAL")
log_name(player);
log_printf(" disabled: %s", flag);
ENDLOG
if (!Quiet(player))
notify_quiet(player, "Disabled.");
} else {
notify_quiet(player, "Illegal combination of switches." );
}

-13-

Das könnte Ihnen auch gefallen