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