]> code.citadel.org Git - citadel.git/blob - citadel/room_ops.c
* Implemented the function CtdlRoomAccess() to handle *all* of the
[citadel.git] / citadel / room_ops.c
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <sys/stat.h>
5 #include <string.h>
6 #include <pthread.h>
7 #include <time.h>
8 #include "citadel.h"
9 #include "server.h"
10 #include "database.h"
11 #include "config.h"
12 #include "room_ops.h"
13 #include "sysdep_decls.h"
14 #include "support.h"
15 #include "user_ops.h"
16 #include "msgbase.h"
17 #include "serv_chat.h"
18 #include "citserver.h"
19
20 /*
21  * Generic routine for determining user access to rooms
22  */
23 int CtdlRoomAccess(struct quickroom *roombuf, struct usersupp *userbuf) {
24         int retval = 0;
25         struct visit vbuf;
26
27         /* Make sure we're dealing with a real, existing room */
28         if (roombuf->QRflags & QR_INUSE) {
29                 retval = retval | UA_INUSE;
30                 }
31         else {
32                 return(0);
33                 }
34
35         /* for internal programs, always do everything */
36         if (((CC->internal_pgm))&&(roombuf->QRflags & QR_INUSE)) {
37                 return(UA_INUSE | UA_KNOWN | UA_GOTOALLOWED);
38                 }
39
40         /* Locate any applicable user/room relationships */
41         CtdlGetRelationship(&vbuf, userbuf, roombuf);
42
43         /* If this is a public room, it's accessible... */
44         if ((roombuf->QRflags & QR_PRIVATE) == 0) {
45                 retval = retval | UA_KNOWN | UA_GOTOALLOWED;
46                 }
47
48         /* If this is a preferred users only room, check access level */
49         if (roombuf->QRflags & QR_PREFONLY) {
50                 if (userbuf->axlevel < 5) {
51                         retval = retval & ~UA_KNOWN & ~UA_GOTOALLOWED;
52                         }
53                 }
54
55         /* For private rooms, check the generation number matchups */
56         if (roombuf->QRflags & QR_PRIVATE) {
57
58                 /* An explicit match means the user belongs in this room */
59                 if (vbuf.v_flags & V_ACCESS) {
60                         retval = retval | UA_KNOWN | UA_GOTOALLOWED;
61                         }
62                 /* Otherwise, check if this is a guess-name or passworded
63                  * room.  If it is, a goto may at least be attempted
64                  */
65                 else if ((roombuf->QRflags & QR_PRIVATE)
66                      ||(roombuf->QRflags & QR_PASSWORDED)) {
67                         retval = retval & ~UA_KNOWN;
68                         retval = retval | UA_GOTOALLOWED;
69                         }
70                 }
71
72         /* Check to see if the user has forgotten this room */
73         if (vbuf.v_flags & V_FORGET) {
74                 retval = retval & ~UA_KNOWN;
75                 retval = retval | UA_ZAPPED;
76                 }
77
78         /* If user is explicitly locked out of this room, deny everything */
79         if (vbuf.v_flags & V_LOCKOUT) {
80                 retval = retval & ~UA_KNOWN & ~UA_GOTOALLOWED;
81                 }
82
83         /* Aides get access to everything */
84         if (userbuf->axlevel >= 6) {
85                 retval = retval | UA_INUSE | UA_KNOWN | UA_GOTOALLOWED;
86                 retval = retval & ~UA_ZAPPED;
87                 }
88
89         /* By the way, we also check for the presence of new messages */
90         if ( (roombuf->QRhighest) > (vbuf.v_lastseen) ) {
91                 retval = retval | UA_HASNEWMSGS;
92                 }
93
94         return(retval);
95         }
96
97
98 /*
99  * getroom()  -  retrieve room data from disk
100  */
101 void getroom(struct quickroom *qrbuf, int room_num)
102 {
103         struct cdbdata *cdbqr;
104         int a;
105
106         bzero(qrbuf, sizeof(struct quickroom));
107         cdbqr = cdb_fetch(CDB_QUICKROOM, &room_num, sizeof(int));
108         if (cdbqr != NULL) {
109                 memcpy(qrbuf, cdbqr->ptr,
110                         ( (cdbqr->len > sizeof(struct quickroom)) ?
111                         sizeof(struct quickroom) : cdbqr->len) );
112                 cdb_free(cdbqr);
113                 }
114         else {
115                 if (room_num < 3) {
116                         qrbuf->QRflags = QR_INUSE;
117                         time(&qrbuf->QRgen);
118                         switch(room_num) {
119                                 case 0: strcpy(qrbuf->QRname, "Lobby");
120                                         break;
121                                 case 1: strcpy(qrbuf->QRname, "Mail");
122                                         break;
123                                 case 2: strcpy(qrbuf->QRname, "Aide");
124                                         break;
125                                 }
126                         }
127                 }
128
129
130         /** FIX **   VILE SLEAZY HACK ALERT!!  
131          * This is a temporary fix until we can track down where room names
132          * are getting corrupted on some systems.
133          */
134         for (a=0; a<20; ++a) if (qrbuf->QRname[a] < 32) qrbuf->QRname[a] = 0;
135         qrbuf->QRname[19] = 0;
136         }
137
138 /*
139  * lgetroom()  -  same as getroom() but locks the record (if supported)
140  */
141 void lgetroom(struct quickroom *qrbuf, int room_num)
142 {
143         begin_critical_section(S_QUICKROOM);
144         getroom(qrbuf,room_num);
145         }
146
147
148 /*
149  * putroom()  -  store room data on disk
150  */
151 void putroom(struct quickroom *qrbuf, int room_num)
152 {
153         time(&qrbuf->QRmtime);
154         cdb_store(CDB_QUICKROOM, &room_num, sizeof(int),
155                 qrbuf, sizeof(struct quickroom));
156         }
157
158
159 /*
160  * lputroom()  -  same as putroom() but unlocks the record (if supported)
161  */
162 void lputroom(struct quickroom *qrbuf, int room_num)
163 {
164
165         putroom(qrbuf,room_num);
166         end_critical_section(S_QUICKROOM);
167
168         }
169
170
171 /*
172  * getfloor()  -  retrieve floor data from disk
173  */
174 void getfloor(struct floor *flbuf, int floor_num)
175 {
176         struct cdbdata *cdbfl;
177
178         bzero(flbuf, sizeof(struct floor));
179         cdbfl = cdb_fetch(CDB_FLOORTAB, &floor_num, sizeof(int));
180         if (cdbfl != NULL) {
181                 memcpy(flbuf, cdbfl->ptr,
182                         ( (cdbfl->len > sizeof(struct floor)) ?
183                         sizeof(struct floor) : cdbfl->len) );
184                 cdb_free(cdbfl);
185                 }
186         else {
187                 if (floor_num == 0) {
188                         strcpy(flbuf->f_name, "Main Floor");
189                         flbuf->f_flags = F_INUSE;
190                         flbuf->f_ref_count = 3;
191                         }
192                 }
193
194         }
195
196 /*
197  * lgetfloor()  -  same as getfloor() but locks the record (if supported)
198  */
199 void lgetfloor(struct floor *flbuf, int floor_num)
200 {
201
202         begin_critical_section(S_FLOORTAB);
203         getfloor(flbuf,floor_num);
204         }
205
206
207 /*
208  * putfloor()  -  store floor data on disk
209  */
210 void putfloor(struct floor *flbuf, int floor_num)
211 {
212         cdb_store(CDB_FLOORTAB, &floor_num, sizeof(int),
213                 flbuf, sizeof(struct floor));
214         }
215
216
217 /*
218  * lputfloor()  -  same as putfloor() but unlocks the record (if supported)
219  */
220 void lputfloor(struct floor *flbuf, int floor_num)
221 {
222
223         putfloor(flbuf,floor_num);
224         end_critical_section(S_FLOORTAB);
225
226         }
227
228
229
230 /*
231  * get_msglist()  -  retrieve room message pointers
232  */
233 void get_msglist(int room_num)
234 {
235         struct cdbdata *cdbfr;
236
237         if (CC->msglist != NULL) {
238                 free(CC->msglist);
239                 }
240         CC->msglist = NULL;
241         CC->num_msgs = 0;
242
243         if (room_num != 1) {
244                 cdbfr = cdb_fetch(CDB_MSGLISTS, &room_num, sizeof(int));
245                 }
246         else {
247                 cdbfr = cdb_fetch(CDB_MAILBOXES, &CC->usersupp.usernum,
248                                         sizeof(long));
249                 }
250
251         if (cdbfr == NULL) {
252                 return;
253                 }
254
255         CC->msglist = malloc(cdbfr->len);
256         memcpy(CC->msglist, cdbfr->ptr, cdbfr->len);
257         CC->num_msgs = cdbfr->len / sizeof(long);
258         cdb_free(cdbfr);
259         }
260
261
262 /*
263  * put_msglist()  -  retrieve room message pointers
264  */
265 void put_msglist(int room_num)
266 {
267
268         if (room_num != 1) {
269                 cdb_store(CDB_MSGLISTS, &room_num, sizeof(int),
270                         CC->msglist, (CC->num_msgs * sizeof(long)) );
271                 }
272         else {
273                 cdb_store(CDB_MAILBOXES, &CC->usersupp.usernum, sizeof(long),
274                         CC->msglist, (CC->num_msgs * sizeof(long)) );
275                 }
276         }
277
278
279 /*
280  * MessageFromList()  -  get a message number from the list currently in memory
281  */
282 long MessageFromList(int whichpos) {
283
284         /* Return zero if the position is invalid */
285         if (whichpos >= CC->num_msgs) return 0L;
286
287         return(CC->msglist[whichpos]);
288         }
289
290 /* 
291  * SetMessageInList()  -  set a message number in the list currently in memory
292  */
293 void SetMessageInList(int whichpos, long newmsgnum) {
294
295         /* Return zero if the position is invalid */
296         if (whichpos >= CC->num_msgs) return;
297
298         CC->msglist[whichpos] = newmsgnum;
299         }
300
301
302
303 /*
304  * sort message pointers
305  * (returns new msg count)
306  */
307 int sort_msglist(long listptrs[], int oldcount)
308 {
309         int a,b;
310         long hold1, hold2;
311         int numitems;
312
313         numitems = oldcount;
314         if (numitems < 2) return(oldcount);
315
316         /* do the sort */
317         for (a=numitems-2; a>=0; --a) {
318                 for (b=0; b<=a; ++b) {
319                         if (listptrs[b] > (listptrs[b+1])) {
320                                 hold1 = listptrs[b];
321                                 hold2 = listptrs[b+1];
322                                 listptrs[b] = hold2;
323                                 listptrs[b+1] = hold1;
324                                 }
325                         }
326                 }
327
328         /* and yank any nulls */
329         while ( (numitems > 0) && (listptrs[0] == 0L) ) {
330                 memcpy(&listptrs[0], &listptrs[1],
331                         (sizeof(long) * (CC->num_msgs - 1)) );
332                 --numitems;
333                 }
334
335         return(numitems);
336         }
337
338  
339
340
341 /* 
342  * cmd_lrms()   -  List all accessible rooms, known or forgotten
343  */
344 void cmd_lrms(char *argbuf)
345 {
346         int a;
347         int target_floor = (-1);
348         struct quickroom qrbuf;
349
350         if (strlen(argbuf)>0) target_floor = extract_int(argbuf,0);
351
352         if (!(CC->logged_in)) {
353                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
354                 return;
355                 }
356
357         if (getuser(&CC->usersupp,CC->curr_user)) {
358                 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
359                 return;
360                 }
361
362         cprintf("%d Accessible rooms:\n",LISTING_FOLLOWS);
363         
364         for (a=0; a<MAXROOMS; ++a) {
365                 getroom(&qrbuf,a);
366                 if ( ((CtdlRoomAccess(&qrbuf, &CC->usersupp)
367                      & (UA_KNOWN | UA_ZAPPED)))
368                 && ((qrbuf.QRfloor == target_floor)||(target_floor<0)) ) 
369                         cprintf("%s|%u|%d\n",
370                                 qrbuf.QRname,qrbuf.QRflags,qrbuf.QRfloor);
371                 }
372         cprintf("000\n");
373         }
374
375 /* 
376  * cmd_lkra()   -  List all known rooms
377  */
378 void cmd_lkra(char *argbuf)
379 {
380         int a, ra;
381         struct quickroom qrbuf;
382         int target_floor = (-1);
383
384         if (strlen(argbuf)>0) target_floor = extract_int(argbuf,0);
385
386         if ((!(CC->logged_in))&&(!(CC->internal_pgm))) {
387                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
388                 return;
389                 }
390
391         if (!(CC->internal_pgm)) if (getuser(&CC->usersupp,CC->curr_user)) {
392                 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
393                 return;
394                 }
395
396         cprintf("%d Known rooms:\n",LISTING_FOLLOWS);
397         
398         for (a=0; a<MAXROOMS; ++a) {
399                 getroom(&qrbuf,a);
400                 ra = CtdlRoomAccess(&qrbuf, &CC->usersupp);
401                 if ( (ra & UA_KNOWN)
402                    && ((qrbuf.QRfloor == target_floor)||(target_floor<0)) )
403                         cprintf("%s|%u|%d\n",
404                                 qrbuf.QRname,qrbuf.QRflags,qrbuf.QRfloor);
405                 }
406         cprintf("000\n");
407         }
408
409 /* 
410  * cmd_lkrn()   -  List Known Rooms with New messages
411  */
412 void cmd_lkrn(char *argbuf)
413 {
414         int a, ra;
415         struct quickroom qrbuf;
416         int target_floor = (-1);
417
418         if (strlen(argbuf)>0) target_floor = extract_int(argbuf,0);
419
420         if (!(CC->logged_in)) {
421                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
422                 return;
423                 }
424
425         if (getuser(&CC->usersupp,CC->curr_user)) {
426                 cprintf("%d can't locate user\n",ERROR+INTERNAL_ERROR);
427                 return;
428                 }
429
430         cprintf("%d list of rms w/ new msgs\n",LISTING_FOLLOWS);
431         
432         for (a=0; a<MAXROOMS; ++a) {
433                 getroom(&qrbuf,a);
434                 ra = CtdlRoomAccess(&qrbuf, &CC->usersupp);
435                 if ( (ra & UA_KNOWN)
436                    && (ra & UA_HASNEWMSGS)
437                    && ((qrbuf.QRfloor == target_floor)||(target_floor<0)) )
438                         cprintf("%s|%u|%d\n",
439                                 qrbuf.QRname,qrbuf.QRflags,qrbuf.QRfloor);
440                 }
441         cprintf("000\n");
442         }
443
444 /* 
445  * cmd_lkro()   -  List Known Rooms with Old (no new) messages
446  */
447 void cmd_lkro(char *argbuf)
448 {
449         int a, ra;
450         struct quickroom qrbuf;
451         int target_floor = (-1);
452
453         if (strlen(argbuf)>0) target_floor = extract_int(argbuf,0);
454
455         if (!(CC->logged_in)) {
456                 cprintf("%d not logged in\n",ERROR+NOT_LOGGED_IN);
457                 return;
458                 }
459
460         if (getuser(&CC->usersupp,CC->curr_user)) {
461                 cprintf("%d can't locate user\n",ERROR+INTERNAL_ERROR);
462                 return;
463                 }
464
465         cprintf("%d list of rms w/o new msgs\n",LISTING_FOLLOWS);
466         
467         for (a=0; a<MAXROOMS; ++a) {
468                 getroom(&qrbuf,a);
469                 ra = CtdlRoomAccess(&qrbuf, &CC->usersupp);
470                    if ((ra & UA_KNOWN)
471                    && ((ra & UA_HASNEWMSGS) == 0)
472                    && ((qrbuf.QRfloor == target_floor)||(target_floor<0)) ) {
473                         if (!strcmp(qrbuf.QRname,"000")) cprintf(">");
474                         cprintf("%s|%u|%d\n",
475                                 qrbuf.QRname,qrbuf.QRflags,qrbuf.QRfloor);
476                         }
477                 }
478         cprintf("000\n");
479         }
480
481 /* 
482  * cmd_lzrm()   -  List Zapped RooMs
483  */
484 void cmd_lzrm(char *argbuf)
485 {
486         int a, ra;
487         struct quickroom qrbuf;
488         int target_floor = (-1);
489
490         if (strlen(argbuf)>0) target_floor = extract_int(argbuf,0);
491
492         if (!(CC->logged_in)) {
493                 cprintf("%d not logged in\n",ERROR+NOT_LOGGED_IN);
494                 return;
495                 }
496
497         if (getuser(&CC->usersupp,CC->curr_user)) {
498                 cprintf("%d can't locate user\n",ERROR+INTERNAL_ERROR);
499                 return;
500                 }
501
502         cprintf("%d list of forgotten rms\n",LISTING_FOLLOWS);
503         
504         for (a=0; a<MAXROOMS; ++a) {
505                 getroom(&qrbuf,a);
506                 ra = CtdlRoomAccess(&qrbuf, &CC->usersupp);
507                 if ( (ra & UA_GOTOALLOWED)
508                    && (ra & UA_ZAPPED)
509                    && ((qrbuf.QRfloor == target_floor)||(target_floor<0)) ) {
510                         if (!strcmp(qrbuf.QRname,"000")) cprintf(">");
511                         cprintf("%s|%u|%d\n",
512                                 qrbuf.QRname,qrbuf.QRflags,qrbuf.QRfloor);
513                         }
514                 }
515         cprintf("000\n");
516         }
517
518
519
520 void usergoto(int where, int display_result)
521 {
522         int a,b,c;
523         int info = 0;
524         int rmailflag;
525         int raideflag;
526         int newmailcount = 0;
527         struct visit vbuf;
528
529         CC->curr_rm=where;
530         getroom(&CC->quickroom,CC->curr_rm);
531         lgetuser(&CC->usersupp,CC->curr_user);
532         CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
533
534         /* old method - remove when we're ready */
535         CC->usersupp.forget[CC->curr_rm]=(-1);
536         CC->usersupp.generation[CC->curr_rm]=CC->quickroom.QRgen;
537
538         /* new method */
539         vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
540         vbuf.v_flags = vbuf.v_flags | V_ACCESS;
541
542         CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
543         lputuser(&CC->usersupp,CC->curr_user);
544
545         /* check for new mail */
546         newmailcount = NewMailCount();
547
548         /* set info to 1 if the user needs to read the room's info file */
549         if (CC->quickroom.QRinfo > CC->usersupp.lastseen[CC->curr_rm]) info = 1;
550
551         b=0; c=0;
552         get_mm();
553         get_msglist(CC->curr_rm);
554         for (a=0; a<CC->num_msgs; ++a) {
555                 if (MessageFromList(a)>0L) {
556                         ++b;
557                         if (MessageFromList(a)
558                            > CC->usersupp.lastseen[CC->curr_rm]) ++c;
559                         }
560                 }
561
562
563         if (CC->curr_rm == 1) rmailflag = 1;
564         else rmailflag = 0;
565
566         if ( (CC->quickroom.QRroomaide == CC->usersupp.usernum)
567            || (CC->usersupp.axlevel>=6) )  raideflag = 1;
568         else raideflag = 0;
569
570         if (display_result) cprintf("%d%c%s|%d|%d|%d|%d|%ld|%ld|%d|%d|%d|%d\n",
571                 OK,check_express(),
572                 CC->quickroom.QRname,c,b,info,CC->quickroom.QRflags,
573                 CC->quickroom.QRhighest,CC->usersupp.lastseen[CC->curr_rm],
574                 rmailflag,raideflag,newmailcount,CC->quickroom.QRfloor);
575         if (CC->quickroom.QRflags & QR_PRIVATE) {
576                 set_wtmpsupp("<private room>");
577                 }
578         else {
579                 set_wtmpsupp(CC->quickroom.QRname);
580                 }
581         }
582
583
584 /* 
585  * cmd_goto()  -  goto a new room
586  */
587 void cmd_goto(char *gargs)
588 {
589         struct quickroom QRscratch;
590         int a,c;
591         int ok;
592         char bbb[20],towhere[32],password[20];
593
594         if ((!(CC->logged_in)) && (!(CC->internal_pgm))) {
595                 cprintf("%d not logged in\n",ERROR+NOT_LOGGED_IN);
596                 return;
597                 }
598
599         extract(towhere,gargs,0);
600         extract(password,gargs,1);
601
602         c=0;
603         getuser(&CC->usersupp,CC->curr_user);
604         for (a=0; a<MAXROOMS; ++a) {
605                 getroom(&QRscratch,a);
606                 if ((a==0)&&(!strcasecmp(towhere,"_BASEROOM_"))) {
607                         strncpy(towhere,QRscratch.QRname,31);
608                         }
609                 if ((a==1)&&(!strcasecmp(towhere,"_MAIL_"))) {
610                         strncpy(towhere,QRscratch.QRname,31);
611                         }
612                 if ((!strcasecmp(QRscratch.QRname,config.c_twitroom))
613                    &&(!strcasecmp(towhere,"_BITBUCKET_"))) {
614                         strncpy(towhere,QRscratch.QRname,31);
615                         }
616                 strcpy(bbb,QRscratch.QRname);
617                 ok = 0;
618
619                 /* let internal programs go directly to any room */
620                 if (((CC->internal_pgm))&&(!strcasecmp(bbb,towhere))) {
621                         usergoto(a,1);
622                         return;
623                         }
624
625                 /* normal clients have to pass through security */
626                 if ( 
627                         (strcasecmp(bbb,towhere)==0)
628                         &&      ((QRscratch.QRflags&QR_INUSE)!=0)
629
630                         && (    ((QRscratch.QRflags&QR_PREFONLY)==0)
631                         ||      (CC->usersupp.axlevel>=5)
632                         )
633
634                         && (    (a!=2) || (CC->usersupp.axlevel>=6) )
635
636                         && (    ((QRscratch.QRflags&QR_PRIVATE)==0)
637                         || (QRscratch.QRflags&QR_GUESSNAME)
638                         || (CC->usersupp.axlevel>=6)
639                         || (QRscratch.QRflags&QR_PASSWORDED)
640                         ||      (QRscratch.QRgen==CC->usersupp.generation[a])
641                         )
642         
643                         ) ok = 1;
644
645
646                 if (ok==1) {
647
648                         if (  (QRscratch.QRflags&QR_PASSWORDED) &&
649                                 (CC->usersupp.axlevel<6) &&
650                                 (QRscratch.QRgen!=CC->usersupp.generation[a]) &&
651                                 (strcasecmp(QRscratch.QRpasswd,password))
652                                 ) {
653                                         cprintf("%d wrong or missing passwd\n",
654                                                 ERROR+PASSWORD_REQUIRED);
655                                         return;
656                                         }
657
658                         usergoto(a,1);
659                         return;
660                         }
661
662                 }
663         cprintf("%d room '%s' not found\n",ERROR+ROOM_NOT_FOUND,towhere);
664         }
665
666
667 void cmd_whok(void) {
668         struct usersupp temp;
669         struct cdbdata *cdbus;
670
671         if ((!(CC->logged_in))&&(!(CC->internal_pgm))) {
672                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
673                 return;
674                 }
675         getuser(&CC->usersupp,CC->curr_user);
676
677         if ((!is_room_aide()) && (!(CC->internal_pgm)) ) {
678                 cprintf("%d Higher access required.\n",
679                         ERROR+HIGHER_ACCESS_REQUIRED);
680                 return;
681                 }
682
683         cprintf("%d Who knows room:\n",LISTING_FOLLOWS);
684         cdb_rewind(CDB_USERSUPP);
685         while(cdbus = cdb_next_item(CDB_USERSUPP), cdbus != NULL) {
686                 bzero(&temp, sizeof(struct usersupp));
687                 memcpy(&temp, cdbus->ptr, cdbus->len);
688                 cdb_free(cdbus);
689                 if ((CC->quickroom.QRflags & QR_INUSE)
690                         && ( (CC->curr_rm!=2) || (temp.axlevel>=6) )
691                         && (CC->quickroom.QRgen != (temp.forget[CC->curr_rm]) )
692
693                         && (    ((CC->quickroom.QRflags&QR_PREFONLY)==0)
694                         ||      (temp.axlevel>=5)
695                         )
696
697                         && (    ((CC->quickroom.QRflags&QR_PRIVATE)==0)
698                         ||      (temp.axlevel>=6)
699                         ||      (CC->quickroom.QRgen==(temp.generation[CC->curr_rm]))
700                         )
701
702                         && (strncmp(temp.fullname,"000",3))
703
704                 ) cprintf("%s\n",temp.fullname);
705                 }
706         cprintf("000\n");
707         }
708
709
710 /*
711  * RDIR command for room directory
712  */
713 void cmd_rdir(void) {
714         char buf[256];
715         char flnm[256];
716         char comment[256];
717         FILE *ls,*fd;
718         struct stat statbuf;
719
720         if (!(CC->logged_in)) {
721                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
722                 return;
723                 }
724
725         getroom(&CC->quickroom,CC->curr_rm);
726         getuser(&CC->usersupp,CC->curr_user);
727
728         if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
729                 cprintf("%d not here.\n",ERROR+NOT_HERE);
730                 return;
731                 }
732
733         if (((CC->quickroom.QRflags & QR_VISDIR) == 0)
734            && (CC->usersupp.axlevel<6)
735            && (CC->usersupp.usernum != CC->quickroom.QRroomaide)) {
736                 cprintf("%d not here.\n",ERROR+HIGHER_ACCESS_REQUIRED);
737                 return;
738                 }
739
740         cprintf("%d %s|%s/files/%s\n",
741                 LISTING_FOLLOWS,config.c_fqdn,BBSDIR,CC->quickroom.QRdirname);
742
743         sprintf(buf,"cd %s/files/%s; ls >%s 2>/dev/null",
744                 BBSDIR,CC->quickroom.QRdirname,CC->temp);
745         system(buf);
746
747         sprintf(buf,"%s/files/%s/filedir",BBSDIR,CC->quickroom.QRdirname);
748         fd = fopen(buf,"r");
749         if (fd==NULL) fd=fopen("/dev/null","r");
750
751         ls = fopen(CC->temp,"r");
752         while (fgets(flnm,256,ls)!=NULL) {
753                 flnm[strlen(flnm)-1]=0;
754                 if (strcasecmp(flnm,"filedir")) {
755                         sprintf(buf,"%s/files/%s/%s",
756                                 BBSDIR,CC->quickroom.QRdirname,flnm);
757                         stat(buf,&statbuf);
758                         strcpy(comment,"");
759                         fseek(fd,0L,0);
760                         while ((fgets(buf,256,fd)!=NULL)
761                             &&(strlen(comment)==0)) {
762                                 buf[strlen(buf)-1] = 0;
763                                 if ((!strncasecmp(buf,flnm,strlen(flnm)))
764                                    && (buf[strlen(flnm)]==' ')) 
765                                         strncpy(comment,
766                                                 &buf[strlen(flnm)+1],255);
767                                 }
768                         cprintf("%s|%ld|%s\n",flnm,statbuf.st_size,comment);
769                         }
770                 }
771         fclose(ls);
772         fclose(fd);
773         unlink(CC->temp);
774
775         cprintf("000\n");
776         }
777
778 /*
779  * get room parameters (aide or room aide command)
780  */
781 void cmd_getr(void) {
782         if ((!(CC->logged_in))&&(!(CC->internal_pgm))) {
783                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
784                 return;
785                 }
786
787         if ( (!is_room_aide()) && (!(CC->internal_pgm)) ) {
788                 cprintf("%d Higher access required.\n",
789                         ERROR+HIGHER_ACCESS_REQUIRED);
790                 return;
791                 }
792
793         if (CC->curr_rm < 3) {
794                 cprintf("%d Can't edit this room.\n",ERROR+NOT_HERE);
795                 return;
796                 }
797
798         getroom(&CC->quickroom,CC->curr_rm);
799         cprintf("%d%c%s|%s|%s|%d|%d\n",
800                 OK,check_express(),
801                 CC->quickroom.QRname,
802                 ((CC->quickroom.QRflags & QR_PASSWORDED) ? CC->quickroom.QRpasswd : ""),
803                 ((CC->quickroom.QRflags & QR_DIRECTORY) ? CC->quickroom.QRdirname : ""),
804                 CC->quickroom.QRflags,
805                 (int)CC->quickroom.QRfloor);
806         }
807
808
809 /*
810  * set room parameters (aide or room aide command)
811  */
812 void cmd_setr(char *args) {
813         char buf[256];
814         struct floor flbuf;
815         int old_floor;
816
817         if (!(CC->logged_in)) {
818                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
819                 return;
820                 }
821
822         if (!is_room_aide()) {
823                 cprintf("%d Higher access required.\n",
824                         ERROR+HIGHER_ACCESS_REQUIRED);
825                 return;
826                 }
827
828         if (CC->curr_rm < 3) {
829                 cprintf("%d Can't edit this room.\n",ERROR+NOT_HERE);
830                 return;
831                 }
832
833         if (num_parms(args)>=6) {
834                 getfloor(&flbuf,extract_int(args,5));
835                 if ((flbuf.f_flags & F_INUSE) == 0) {
836                         cprintf("%d Invalid floor number.\n",
837                                 ERROR+INVALID_FLOOR_OPERATION);
838                         return;
839                         }
840                 }
841
842         lgetroom(&CC->quickroom,CC->curr_rm);
843         extract(buf,args,0); buf[20]=0;
844         strncpy(CC->quickroom.QRname,buf,19);
845         extract(buf,args,1); buf[10]=0;
846         strncpy(CC->quickroom.QRpasswd,buf,9);
847         extract(buf,args,2); buf[15]=0;
848         strncpy(CC->quickroom.QRdirname,buf,19);
849         CC->quickroom.QRflags = ( extract_int(args,3) | QR_INUSE);
850
851         /* Clean up a client boo-boo: if the client set the room to
852          * guess-name or passworded, ensure that the private flag is
853          * also set.
854          */
855         if ((CC->quickroom.QRflags & QR_GUESSNAME)
856            ||(CC->quickroom.QRflags & QR_PASSWORDED))
857                 CC->quickroom.QRflags |= QR_PRIVATE;
858
859         /* Kick everyone out if the client requested it (by changing the
860          * room's generation number)
861          */
862         if (extract_int(args,4)) {
863                 time(&CC->quickroom.QRgen);
864                 }
865
866         old_floor = CC->quickroom.QRfloor;
867         if (num_parms(args)>=6) {
868                 CC->quickroom.QRfloor = extract_int(args,5);
869                 }
870
871         lputroom(&CC->quickroom,CC->curr_rm);
872
873         /* adjust the floor reference counts */
874         lgetfloor(&flbuf,old_floor);
875         --flbuf.f_ref_count;
876         lputfloor(&flbuf,old_floor);
877         lgetfloor(&flbuf,CC->quickroom.QRfloor);
878         ++flbuf.f_ref_count;
879         lputfloor(&flbuf,CC->quickroom.QRfloor);
880
881         /* create a room directory if necessary */
882         if (CC->quickroom.QRflags & QR_DIRECTORY) {
883                 sprintf(buf,
884                         "mkdir ./files/%s </dev/null >/dev/null 2>/dev/null",
885                 CC->quickroom.QRdirname);
886                 system(buf);
887                 }
888
889         sprintf(buf,"%s> edited by %s",CC->quickroom.QRname,CC->curr_user);
890         aide_message(buf);
891         cprintf("%d Ok\n",OK);
892         }
893
894
895
896 /* 
897  * get the name of the room aide for this room
898  */
899 void cmd_geta(void) {
900         struct usersupp usbuf;
901
902         if ((!(CC->logged_in))&&(!(CC->internal_pgm))) {
903                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
904                 return;
905                 }
906
907         if (CC->curr_rm < 0) {
908                 cprintf("%d No current room.\n",ERROR);
909                 return;
910                 }
911
912         if (getuserbynumber(&usbuf,CC->quickroom.QRroomaide)==0) {
913                 cprintf("%d %s\n",OK,usbuf.fullname);
914                 }
915         else {
916                 cprintf("%d \n",OK);
917                 }
918         }
919
920
921 /* 
922  * set the room aide for this room
923  */
924 void cmd_seta(char *new_ra)
925 {
926         struct usersupp usbuf;
927         long newu;
928         char buf[256];
929         int post_notice;
930         
931         if (!(CC->logged_in)) {
932                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
933                 return;
934                 }
935
936         if (!is_room_aide()) {
937                 cprintf("%d Higher access required.\n",
938                         ERROR+HIGHER_ACCESS_REQUIRED);
939                 return;
940                 }
941
942         if (CC->curr_rm < 3) {
943                 cprintf("%d Can't edit this room.\n",ERROR+NOT_HERE);
944                 return;
945                 }
946
947         if (getuser(&usbuf,new_ra)!=0) {
948                 newu = (-1L);
949                 }
950         else {
951                 newu = usbuf.usernum;
952                 }
953
954         lgetroom(&CC->quickroom,CC->curr_rm);
955         post_notice = 0;
956         if (CC->quickroom.QRroomaide != newu) {
957                 post_notice = 1;
958                 }
959         CC->quickroom.QRroomaide = newu;
960         lputroom(&CC->quickroom,CC->curr_rm);
961
962         /*
963          * We have to post the change notice _after_ writing changes to 
964          * the room table, otherwise it would deadlock!
965          */
966         if (post_notice == 1) {
967                 sprintf(buf,"%s is now room aide for %s>",
968                         usbuf.fullname,CC->quickroom.QRname);
969                 aide_message(buf);
970                 }
971         cprintf("%d Ok\n",OK);
972         }
973
974
975 /* 
976  * retrieve info file for this room
977  */
978 void cmd_rinf(void) {
979         char filename[64];
980         char buf[256];
981         FILE *info_fp;
982         
983         sprintf(filename,"./info/%d",CC->curr_rm);
984         info_fp = fopen(filename,"r");
985
986         if (info_fp==NULL) {
987                 cprintf("%d No info file.\n",ERROR);
988                 return;
989                 }
990
991         cprintf("%d Info:\n",LISTING_FOLLOWS);  
992         while (fgets(buf, 256, info_fp) != NULL) {
993                 if (strlen(buf) > 0) buf[strlen(buf)-1] = 0;
994                 cprintf("%s\n", buf);
995                 }
996         cprintf("000\n");
997         fclose(info_fp);
998         }
999
1000 /*
1001  * aide command: kill the current room
1002  */
1003 void cmd_kill(char *argbuf)
1004 {
1005         char aaa[100];
1006         int a;
1007         int kill_ok;
1008         struct floor flbuf;
1009         long MsgToDelete;
1010         
1011         kill_ok = extract_int(argbuf,0);
1012
1013         if (!(CC->logged_in)) {
1014                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1015                 return;
1016                 }
1017
1018         if (!is_room_aide()) {
1019                 cprintf("%d Higher access required.\n",
1020                         ERROR+HIGHER_ACCESS_REQUIRED);
1021                 return;
1022                 }
1023
1024         if (CC->curr_rm < 3) {
1025                 cprintf("%d Can't kill this room.\n",ERROR+NOT_HERE);
1026                 return;
1027                 }
1028
1029         if (kill_ok) {
1030
1031                 /* first flag the room record as not in use */
1032                 lgetroom(&CC->quickroom,CC->curr_rm);
1033                 CC->quickroom.QRflags=0;
1034
1035                 /* then delete the messages in the room */
1036                 get_msglist(CC->curr_rm);
1037                 if (CC->num_msgs > 0) for (a=0; a < CC->num_msgs; ++a) {
1038                         MsgToDelete = MessageFromList(a);
1039                         cdb_delete(CDB_MSGMAIN, &MsgToDelete, sizeof(long));
1040                         }
1041                 put_msglist(CC->curr_rm);
1042                 free(CC->msglist);
1043                 CC->num_msgs = 0;
1044                 cdb_delete(CDB_MSGLISTS, &CC->curr_rm, sizeof(int));
1045
1046                 lputroom(&CC->quickroom,CC->curr_rm);
1047
1048
1049                 /* then decrement the reference count for the floor */
1050                 lgetfloor(&flbuf,(int)CC->quickroom.QRfloor);
1051                 flbuf.f_ref_count = flbuf.f_ref_count - 1;
1052                 lputfloor(&flbuf,(int)CC->quickroom.QRfloor);
1053
1054                 /* tell the world what we did */
1055                 sprintf(aaa,"%s> killed by %s",CC->quickroom.QRname,CC->curr_user);
1056                 aide_message(aaa);
1057                 CC->curr_rm=(-1);
1058                 cprintf("%d '%s' deleted.\n",OK,CC->quickroom.QRname);
1059                 }
1060         else {
1061                 cprintf("%d ok to delete.\n",OK);
1062                 }
1063         }
1064
1065
1066 /*
1067  * Find a free slot to create a new room in, or return -1 for error.
1068  * search_dir is the direction to search in.  1 causes this function to
1069  * return the first available slot, -1 gets the last available slot.
1070  */
1071 int get_free_room_slot(int search_dir)
1072 {
1073         int a,st;
1074         struct quickroom qrbuf;
1075
1076         st = ((search_dir>0) ? 3 : (MAXROOMS-1));
1077
1078         for (a=st; ((a<MAXROOMS)&&(a>=3)); a=a+search_dir) {
1079                 getroom(&qrbuf,a);
1080                 if ((qrbuf.QRflags & QR_INUSE)==0) return(a);
1081                 }
1082         return(-1);
1083         }
1084
1085
1086 /*
1087  * internal code to create a new room (returns room flags)
1088  */
1089 unsigned create_room(int free_slot, char *new_room_name, int new_room_type, char *new_room_pass, int new_room_floor)
1090 {
1091         struct quickroom qrbuf;
1092         struct floor flbuf;
1093         struct visit vbuf;
1094
1095         lgetroom(&qrbuf,free_slot);
1096         strncpy(qrbuf.QRname,new_room_name,19);
1097         strncpy(qrbuf.QRpasswd,new_room_pass,9);
1098         qrbuf.QRflags = QR_INUSE;
1099         if (new_room_type > 0) qrbuf.QRflags=(qrbuf.QRflags|QR_PRIVATE);
1100         if (new_room_type == 1) qrbuf.QRflags=(qrbuf.QRflags|QR_GUESSNAME);
1101         if (new_room_type == 2) qrbuf.QRflags=(qrbuf.QRflags|QR_PASSWORDED);
1102         qrbuf.QRroomaide = (-1L);
1103         if ((new_room_type > 0)&&(CREATAIDE==1))
1104                 qrbuf.QRroomaide=CC->usersupp.usernum;
1105         qrbuf.QRhighest = 0L;
1106         time(&qrbuf.QRgen);
1107         qrbuf.QRfloor = new_room_floor;
1108
1109         /* save what we just did... */
1110         lputroom(&qrbuf,free_slot);
1111
1112         /* bump the reference count on whatever floor the room is on */
1113         lgetfloor(&flbuf,(int)qrbuf.QRfloor);
1114         flbuf.f_ref_count = flbuf.f_ref_count + 1;
1115         lputfloor(&flbuf,(int)qrbuf.QRfloor);
1116
1117         /* be sure not to kick the creator out of the room! */
1118         lgetuser(&CC->usersupp,CC->curr_user);
1119         CtdlGetRelationship(&vbuf, &CC->usersupp, &qrbuf);
1120         /* (old method) */
1121         CC->usersupp.generation[free_slot] = qrbuf.QRgen;
1122         CC->usersupp.forget[free_slot] = (-1);
1123         /* (new method) */
1124         vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
1125         vbuf.v_flags = vbuf.v_flags | V_ACCESS;
1126         CtdlSetRelationship(&vbuf, &CC->usersupp, &qrbuf);
1127         lputuser(&CC->usersupp,CC->curr_user);
1128
1129         /* resume our happy day */
1130         return(qrbuf.QRflags);
1131         }
1132
1133
1134 /*
1135  * create a new room
1136  */
1137 void cmd_cre8(char *args)
1138 {
1139         int cre8_ok;
1140         int free_slot;
1141         int a;
1142         char new_room_name[256];
1143         int new_room_type;
1144         char new_room_pass[256];
1145         int new_room_floor;
1146         char aaa[256];
1147         unsigned newflags;
1148         struct quickroom qrbuf;
1149         struct floor flbuf;
1150
1151         cre8_ok = extract_int(args,0);
1152         extract(new_room_name,args,1);
1153         new_room_name[19] = 0;
1154         new_room_type = extract_int(args,2);
1155         extract(new_room_pass,args,3);
1156         new_room_pass[9] = 0;
1157         new_room_floor = 0;
1158
1159         if ((strlen(new_room_name)==0) && (cre8_ok==1)) {
1160                 cprintf("%d Invalid room name.\n",ERROR);
1161                 return;
1162                 }
1163
1164         if (num_parms(args)>=5) {
1165                 getfloor(&flbuf,extract_int(args,4));
1166                 if ((flbuf.f_flags & F_INUSE) == 0) {
1167                         cprintf("%d Invalid floor number.\n",
1168                                 ERROR+INVALID_FLOOR_OPERATION);
1169                         return;
1170                         }
1171                 else {
1172                         new_room_floor = extract_int(args,4);
1173                         }
1174                 }
1175
1176         if (!(CC->logged_in)) {
1177                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1178                 return;
1179                 }
1180
1181         if (CC->usersupp.axlevel<3) {
1182                 cprintf("%d You need higher access to create rooms.\n",
1183                         ERROR+HIGHER_ACCESS_REQUIRED);
1184                 return;
1185                 }
1186
1187         free_slot = get_free_room_slot(1);
1188         if (free_slot<0) {
1189                 cprintf("%d There is no space available for a new room.\n",
1190                         ERROR);
1191                 return;
1192                 }
1193
1194         if (cre8_ok==0) {
1195                 cprintf("%d ok to create...\n",OK);
1196                 return;
1197                 }
1198
1199         for (a=0; a<MAXROOMS; ++a) {
1200                 getroom(&qrbuf,a);
1201                 if ( (!strcasecmp(qrbuf.QRname,new_room_name))
1202                    && (qrbuf.QRflags & QR_INUSE) ) {
1203                         cprintf("%d '%s' already exists.\n",
1204                                 ERROR,qrbuf.QRname);
1205                         return;
1206                         }
1207                 }
1208
1209         if ((new_room_type < 0) || (new_room_type > 3)) {
1210                 cprintf("%d Invalid room type.\n",ERROR);
1211                 return;
1212                 }
1213
1214         newflags = create_room(free_slot,new_room_name,
1215                         new_room_type,new_room_pass,new_room_floor);
1216
1217         /* post a message in Aide> describing the new room */
1218         strncpy(aaa,new_room_name,255);
1219         strcat(aaa,"> created by ");
1220         strcat(aaa,CC->usersupp.fullname);
1221         if (newflags&QR_PRIVATE) strcat(aaa," [private]");
1222         if (newflags&QR_GUESSNAME) strcat(aaa,"[guessname] ");
1223         if (newflags&QR_PASSWORDED) {
1224                 strcat(aaa,"\n Password: ");
1225                 strcat(aaa,new_room_pass);
1226                 }
1227         aide_message(aaa); 
1228
1229         sprintf(aaa,"./info/%d",free_slot);     /* delete old info file */
1230         unlink(aaa);    
1231         sprintf(aaa,"./images/room.%d.gif",free_slot);  /* and picture */
1232         unlink(aaa);    
1233
1234         cprintf("%d '%s' has been created.\n",OK,qrbuf.QRname);
1235         }
1236
1237
1238
1239 void cmd_einf(char *ok)
1240 {       /* enter info file for current room */
1241         FILE *fp;
1242         char infofilename[32];
1243         char buf[256];
1244
1245         if (!(CC->logged_in)) {
1246                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1247                 return;
1248                 }
1249
1250         if (!is_room_aide()) {
1251                 cprintf("%d Higher access required.\n",
1252                         ERROR+HIGHER_ACCESS_REQUIRED);
1253                 return;
1254                 }
1255
1256         if (atoi(ok)==0) {
1257                 cprintf("%d Ok.\n",OK);
1258                 return;
1259                 }
1260
1261         cprintf("%d Send info...\n",SEND_LISTING);
1262
1263         sprintf(infofilename,"./info/%d",CC->curr_rm);
1264
1265         fp=fopen(infofilename,"w");
1266         do {
1267                 client_gets(buf);
1268                 if (strcmp(buf,"000")) fprintf(fp,"%s\n",buf);
1269                 } while(strcmp(buf,"000"));
1270         fclose(fp);
1271
1272         /* now update the room index so people will see our new info */
1273         lgetroom(&CC->quickroom,CC->curr_rm);   /* lock so no one steps on us */
1274         CC->quickroom.QRinfo = CC->quickroom.QRhighest + 1L;
1275         lputroom(&CC->quickroom,CC->curr_rm);
1276         }
1277
1278
1279 /* 
1280  * cmd_lflr()   -  List all known floors
1281  */
1282 void cmd_lflr(void) {
1283         int a;
1284         struct floor flbuf;
1285
1286         if (!(CC->logged_in)) {
1287                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1288                 return;
1289                 }
1290
1291         /* if (getuser(&CC->usersupp,CC->curr_user)) {
1292                 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
1293                 return;
1294                 }
1295         */
1296
1297         cprintf("%d Known floors:\n",LISTING_FOLLOWS);
1298         
1299         for (a=0; a<MAXFLOORS; ++a) {
1300                 getfloor(&flbuf,a);
1301                 if (flbuf.f_flags & F_INUSE) {
1302                         cprintf("%d|%s|%d\n",
1303                                 a,
1304                                 flbuf.f_name,
1305                                 flbuf.f_ref_count);
1306                         }
1307                 }
1308         cprintf("000\n");
1309         }
1310
1311
1312
1313 /*
1314  * create a new floor
1315  */
1316 void cmd_cflr(char *argbuf)
1317 {
1318         char new_floor_name[256];
1319         struct floor flbuf;
1320         int cflr_ok;
1321         int free_slot = (-1);
1322         int a;
1323
1324         extract(new_floor_name,argbuf,0);
1325         cflr_ok = extract_int(argbuf,1);
1326
1327         
1328         if (!(CC->logged_in)) {
1329                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1330                 return;
1331                 }
1332
1333         if (CC->usersupp.axlevel<6) {
1334                 cprintf("%d You need higher access to create rooms.\n",
1335                         ERROR+HIGHER_ACCESS_REQUIRED);
1336                 return;
1337                 }
1338
1339         for (a=0; a<MAXFLOORS; ++a) {
1340                 getfloor(&flbuf,a);
1341
1342                 /* note any free slots while we're scanning... */
1343                 if ( ((flbuf.f_flags & F_INUSE)==0) 
1344                      && (free_slot < 0) )  free_slot = a;
1345
1346                 /* check to see if it already exists */
1347                 if ( (!strcasecmp(flbuf.f_name,new_floor_name))
1348                      && (flbuf.f_flags & F_INUSE) ) {
1349                         cprintf("%d Floor '%s' already exists.\n",
1350                                 ERROR+ALREADY_EXISTS,
1351                                 flbuf.f_name);
1352                         return;
1353                         }
1354
1355                 }
1356
1357         if (free_slot<0) {
1358                 cprintf("%d There is no space available for a new floor.\n",
1359                         ERROR+INVALID_FLOOR_OPERATION);
1360                 return;
1361                 }
1362
1363         if (cflr_ok==0) {
1364                 cprintf("%d ok to create...\n",OK);
1365                 return;
1366                 }
1367
1368         lgetfloor(&flbuf,free_slot);
1369         flbuf.f_flags = F_INUSE;
1370         flbuf.f_ref_count = 0;
1371         strncpy(flbuf.f_name,new_floor_name,255);
1372         lputfloor(&flbuf,free_slot);
1373         cprintf("%d %d\n",OK,free_slot);
1374         }
1375
1376
1377
1378 /*
1379  * delete a floor
1380  */
1381 void cmd_kflr(char *argbuf)
1382 {
1383         struct floor flbuf;
1384         int floor_to_delete;
1385         int kflr_ok;
1386         int delete_ok;
1387
1388         floor_to_delete = extract_int(argbuf,0);
1389         kflr_ok = extract_int(argbuf,1);
1390
1391         
1392         if (!(CC->logged_in)) {
1393                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1394                 return;
1395                 }
1396
1397         if (CC->usersupp.axlevel<6) {
1398                 cprintf("%d You need higher access to delete floors.\n",
1399                         ERROR+HIGHER_ACCESS_REQUIRED);
1400                 return;
1401                 }
1402
1403         lgetfloor(&flbuf,floor_to_delete);
1404
1405         delete_ok = 1;  
1406         if ((flbuf.f_flags & F_INUSE) == 0) {
1407                 cprintf("%d Floor %d not in use.\n",
1408                         ERROR+INVALID_FLOOR_OPERATION,floor_to_delete);
1409                 delete_ok = 0;
1410                 }
1411
1412         else {
1413                 if (flbuf.f_ref_count != 0) {
1414                         cprintf("%d Cannot delete; floor contains %d rooms.\n",
1415                                 ERROR+INVALID_FLOOR_OPERATION,
1416                                 flbuf.f_ref_count);
1417                         delete_ok = 0;
1418                         }
1419
1420                 else {
1421                         if (kflr_ok == 1) {
1422                                 cprintf("%d Ok\n",OK);
1423                                 }
1424                         else {
1425                                 cprintf("%d Ok to delete...\n",OK);
1426                                 }
1427
1428                         }
1429
1430                 }
1431
1432         if ( (delete_ok == 1) && (kflr_ok == 1) ) flbuf.f_flags = 0;
1433         lputfloor(&flbuf,floor_to_delete);
1434         }
1435
1436 /*
1437  * edit a floor
1438  */
1439 void cmd_eflr(char *argbuf)
1440 {
1441         struct floor flbuf;
1442         int floor_num;
1443         int np;
1444
1445         np = num_parms(argbuf);
1446         if (np < 1) {
1447                 cprintf("%d Usage error.\n",ERROR);
1448                 return;
1449                 }
1450         
1451         if (!(CC->logged_in)) {
1452                 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1453                 return;
1454                 }
1455
1456         if (CC->usersupp.axlevel<6) {
1457                 cprintf("%d You need higher access to edit floors.\n",
1458                         ERROR+HIGHER_ACCESS_REQUIRED);
1459                 return;
1460                 }
1461
1462         floor_num = extract_int(argbuf,0);
1463         lgetfloor(&flbuf,floor_num);
1464         if ( (flbuf.f_flags & F_INUSE) == 0) {
1465                 lputfloor(&flbuf,floor_num);
1466                 cprintf("%d Floor %d is not in use.\n",
1467                         ERROR+INVALID_FLOOR_OPERATION,floor_num);
1468                 return;
1469                 }
1470         if (np >= 2) extract(flbuf.f_name,argbuf,1);
1471         lputfloor(&flbuf,floor_num);
1472         
1473         cprintf("%d Ok\n",OK);
1474         }