14 #include "sysdep_decls.h"
18 #include "serv_chat.h"
19 #include "citserver.h"
22 * Generic routine for determining user access to rooms
24 int CtdlRoomAccess(struct quickroom *roombuf, struct usersupp *userbuf) {
28 /* Make sure we're dealing with a real, existing room */
29 if (roombuf->QRflags & QR_INUSE) {
30 retval = retval | UA_INUSE;
36 /* for internal programs, always do everything */
37 if (((CC->internal_pgm))&&(roombuf->QRflags & QR_INUSE)) {
38 return(UA_INUSE | UA_KNOWN | UA_GOTOALLOWED);
41 /* Locate any applicable user/room relationships */
42 CtdlGetRelationship(&vbuf, userbuf, roombuf);
44 /* If this is a public room, it's accessible... */
45 if ((roombuf->QRflags & QR_PRIVATE) == 0) {
46 retval = retval | UA_KNOWN | UA_GOTOALLOWED;
49 /* If this is a preferred users only room, check access level */
50 if (roombuf->QRflags & QR_PREFONLY) {
51 if (userbuf->axlevel < 5) {
52 retval = retval & ~UA_KNOWN & ~UA_GOTOALLOWED;
56 /* For private rooms, check the generation number matchups */
57 if (roombuf->QRflags & QR_PRIVATE) {
59 /* An explicit match means the user belongs in this room */
60 if (vbuf.v_flags & V_ACCESS) {
61 retval = retval | UA_KNOWN | UA_GOTOALLOWED;
63 /* Otherwise, check if this is a guess-name or passworded
64 * room. If it is, a goto may at least be attempted
66 else if ((roombuf->QRflags & QR_PRIVATE)
67 ||(roombuf->QRflags & QR_PASSWORDED)) {
68 retval = retval & ~UA_KNOWN;
69 retval = retval | UA_GOTOALLOWED;
73 /* Check to see if the user has forgotten this room */
74 if (vbuf.v_flags & V_FORGET) {
75 retval = retval & ~UA_KNOWN;
76 retval = retval | UA_ZAPPED;
79 /* If user is explicitly locked out of this room, deny everything */
80 if (vbuf.v_flags & V_LOCKOUT) {
81 retval = retval & ~UA_KNOWN & ~UA_GOTOALLOWED;
84 /* Aides get access to everything */
85 if (userbuf->axlevel >= 6) {
86 retval = retval | UA_INUSE | UA_KNOWN | UA_GOTOALLOWED;
87 retval = retval & ~UA_ZAPPED;
90 /* By the way, we also check for the presence of new messages */
91 if ( (roombuf->QRhighest) > (vbuf.v_lastseen) ) {
92 retval = retval | UA_HASNEWMSGS;
99 * getroom() - retrieve room data from disk
101 int getroom(struct quickroom *qrbuf, char *room_name)
103 struct cdbdata *cdbqr;
104 char lowercase_name[ROOMNAMELEN];
107 for (a=0; a<=strlen(room_name); ++a) {
108 lowercase_name[a] = tolower(room_name[a]);
111 memset(qrbuf, 0, sizeof(struct quickroom));
112 cdbqr = cdb_fetch(CDB_QUICKROOM,
113 lowercase_name, strlen(lowercase_name));
115 memcpy(qrbuf, cdbqr->ptr,
116 ( (cdbqr->len > sizeof(struct quickroom)) ?
117 sizeof(struct quickroom) : cdbqr->len) );
127 * lgetroom() - same as getroom() but locks the record (if supported)
129 int lgetroom(struct quickroom *qrbuf, char *room_name)
131 begin_critical_section(S_QUICKROOM);
132 return(getroom(qrbuf, room_name));
137 * putroom() - store room data on disk
138 * (if the supplied buffer is NULL, delete the room record)
140 void putroom(struct quickroom *qrbuf, char *room_name)
142 char lowercase_name[ROOMNAMELEN];
145 for (a=0; a<=strlen(room_name); ++a) {
146 lowercase_name[a] = tolower(room_name[a]);
150 cdb_delete(CDB_QUICKROOM,
151 lowercase_name, strlen(lowercase_name));
154 time(&qrbuf->QRmtime);
155 cdb_store(CDB_QUICKROOM,
156 lowercase_name, strlen(lowercase_name),
157 qrbuf, sizeof(struct quickroom));
163 * lputroom() - same as putroom() but unlocks the record (if supported)
165 void lputroom(struct quickroom *qrbuf, char *room_name)
168 putroom(qrbuf, room_name);
169 end_critical_section(S_QUICKROOM);
173 /****************************************************************************/
176 * getfloor() - retrieve floor data from disk
178 void getfloor(struct floor *flbuf, int floor_num)
180 struct cdbdata *cdbfl;
182 memset(flbuf, 0, sizeof(struct floor));
183 cdbfl = cdb_fetch(CDB_FLOORTAB, &floor_num, sizeof(int));
185 memcpy(flbuf, cdbfl->ptr,
186 ( (cdbfl->len > sizeof(struct floor)) ?
187 sizeof(struct floor) : cdbfl->len) );
191 if (floor_num == 0) {
192 strcpy(flbuf->f_name, "Main Floor");
193 flbuf->f_flags = F_INUSE;
194 flbuf->f_ref_count = 3;
201 * lgetfloor() - same as getfloor() but locks the record (if supported)
203 void lgetfloor(struct floor *flbuf, int floor_num)
206 begin_critical_section(S_FLOORTAB);
207 getfloor(flbuf,floor_num);
212 * putfloor() - store floor data on disk
214 void putfloor(struct floor *flbuf, int floor_num)
216 cdb_store(CDB_FLOORTAB, &floor_num, sizeof(int),
217 flbuf, sizeof(struct floor));
222 * lputfloor() - same as putfloor() but unlocks the record (if supported)
224 void lputfloor(struct floor *flbuf, int floor_num)
227 putfloor(flbuf,floor_num);
228 end_critical_section(S_FLOORTAB);
234 * Traverse the room file...
236 void ForEachRoom(void (*CallBack)(struct quickroom *EachRoom)) {
237 struct quickroom qrbuf;
238 struct cdbdata *cdbqr;
240 cdb_rewind(CDB_QUICKROOM);
242 while(cdbqr = cdb_next_item(CDB_QUICKROOM), cdbqr != NULL) {
243 memset(&qrbuf, 0, sizeof(struct quickroom));
244 memcpy(&qrbuf, cdbqr->ptr,
245 ( (cdbqr->len > sizeof(struct quickroom)) ?
246 sizeof(struct quickroom) : cdbqr->len) );
248 if (qrbuf.QRflags & QR_INUSE) (*CallBack)(&qrbuf);
255 * get_msglist() - retrieve room message pointers
257 void get_msglist(struct quickroom *whichroom) {
258 struct cdbdata *cdbfr;
262 lprintf(9, "get_msglist() called for <%s>\n", whichroom->QRname);
263 sprintf(dbkey, "%s%ld", whichroom->QRname, whichroom->QRgen);
264 for (a=0; a<strlen(dbkey); ++a) dbkey[a]=tolower(dbkey[a]);
265 lprintf(9, "database key is <%s>\n", dbkey);
267 lprintf(9, "Freeing existing message list\n");
268 if (CC->msglist != NULL) {
274 lprintf(9, "calling cdb_fetch\n");
275 cdbfr = cdb_fetch(CDB_MSGLISTS, dbkey, strlen(dbkey));
276 lprintf(9, "done\n");
282 CC->msglist = malloc(cdbfr->len);
283 memcpy(CC->msglist, cdbfr->ptr, cdbfr->len);
284 CC->num_msgs = cdbfr->len / sizeof(long);
286 lprintf(9, "Leaving get_msglist()\n");
291 * put_msglist() - retrieve room message pointers
293 void put_msglist(struct quickroom *whichroom) {
297 sprintf(dbkey, "%s%ld", whichroom->QRname, whichroom->QRgen);
298 for (a=0; a<strlen(dbkey); ++a) dbkey[a]=tolower(dbkey[a]);
300 cdb_store(CDB_MSGLISTS, dbkey, strlen(dbkey),
301 CC->msglist, CC->num_msgs * sizeof(long));
306 * delete_msglist() - delete room message pointers
308 void delete_msglist(struct quickroom *whichroom) {
312 sprintf(dbkey, "%s%ld", whichroom->QRname, whichroom->QRgen);
313 for (a=0; a<strlen(dbkey); ++a) dbkey[a]=tolower(dbkey[a]);
315 cdb_delete(CDB_MSGLISTS, dbkey, strlen(dbkey));
320 * MessageFromList() - get a message number from the list currently in memory
322 long MessageFromList(int whichpos) {
324 /* Return zero if the position is invalid */
325 if (whichpos >= CC->num_msgs) return 0L;
327 return(CC->msglist[whichpos]);
331 * SetMessageInList() - set a message number in the list currently in memory
333 void SetMessageInList(int whichpos, long newmsgnum) {
335 /* Return zero if the position is invalid */
336 if (whichpos >= CC->num_msgs) return;
338 CC->msglist[whichpos] = newmsgnum;
344 * sort message pointers
345 * (returns new msg count)
347 int sort_msglist(long listptrs[], int oldcount)
354 if (numitems < 2) return(oldcount);
357 for (a=numitems-2; a>=0; --a) {
358 for (b=0; b<=a; ++b) {
359 if (listptrs[b] > (listptrs[b+1])) {
361 hold2 = listptrs[b+1];
363 listptrs[b+1] = hold1;
368 /* and yank any nulls */
369 while ( (numitems > 0) && (listptrs[0] == 0L) ) {
370 memcpy(&listptrs[0], &listptrs[1],
371 (sizeof(long) * (CC->num_msgs - 1)) );
381 * Determine whether a given room is one of the base non-editable rooms
383 int is_noneditable(struct quickroom *qrbuf) {
384 if (!strcasecmp(qrbuf->QRname, BASEROOM)) return(0);
385 else if (!strcasecmp(qrbuf->QRname, AIDEROOM)) return(0);
390 * cmd_lrms() - List all accessible rooms, known or forgotten
392 void cmd_lrms_backend(struct quickroom *qrbuf) {
393 if ( ((CtdlRoomAccess(qrbuf, &CC->usersupp)
394 & (UA_KNOWN | UA_ZAPPED)))
395 && ((qrbuf->QRfloor == (CC->FloorBeingSearched))
396 ||((CC->FloorBeingSearched)<0)) )
397 cprintf("%s|%u|%d\n",
398 qrbuf->QRname,qrbuf->QRflags,qrbuf->QRfloor);
401 void cmd_lrms(char *argbuf)
403 CC->FloorBeingSearched = (-1);
404 if (strlen(argbuf)>0) CC->FloorBeingSearched = extract_int(argbuf,0);
406 if (!(CC->logged_in)) {
407 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
411 if (getuser(&CC->usersupp,CC->curr_user)) {
412 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
416 cprintf("%d Accessible rooms:\n",LISTING_FOLLOWS);
418 ForEachRoom(cmd_lrms_backend);
425 * cmd_lkra() - List all known rooms
427 void cmd_lkra_backend(struct quickroom *qrbuf) {
428 if ( ((CtdlRoomAccess(qrbuf, &CC->usersupp)
430 && ((qrbuf->QRfloor == (CC->FloorBeingSearched))
431 ||((CC->FloorBeingSearched)<0)) )
432 cprintf("%s|%u|%d\n",
433 qrbuf->QRname,qrbuf->QRflags,qrbuf->QRfloor);
436 void cmd_lkra(char *argbuf)
438 CC->FloorBeingSearched = (-1);
439 if (strlen(argbuf)>0) CC->FloorBeingSearched = extract_int(argbuf,0);
441 if (!(CC->logged_in)) {
442 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
446 if (getuser(&CC->usersupp,CC->curr_user)) {
447 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
451 cprintf("%d Known rooms:\n",LISTING_FOLLOWS);
453 ForEachRoom(cmd_lkra_backend);
460 * cmd_lkrn() - List all known rooms with new messages
462 void cmd_lkrn_backend(struct quickroom *qrbuf) {
465 ra = CtdlRoomAccess(qrbuf, &CC->usersupp);
467 && (ra & UA_HASNEWMSGS)
468 && ((qrbuf->QRfloor == (CC->FloorBeingSearched))
469 ||((CC->FloorBeingSearched)<0)) )
470 cprintf("%s|%u|%d\n",
471 qrbuf->QRname,qrbuf->QRflags,qrbuf->QRfloor);
474 void cmd_lkrn(char *argbuf)
476 CC->FloorBeingSearched = (-1);
477 if (strlen(argbuf)>0) CC->FloorBeingSearched = extract_int(argbuf,0);
479 if (!(CC->logged_in)) {
480 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
484 if (getuser(&CC->usersupp,CC->curr_user)) {
485 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
489 cprintf("%d Rooms w/ new msgs:\n",LISTING_FOLLOWS);
491 ForEachRoom(cmd_lkrn_backend);
498 * cmd_lkro() - List all known rooms
500 void cmd_lkro_backend(struct quickroom *qrbuf) {
503 ra = CtdlRoomAccess(qrbuf, &CC->usersupp);
505 && ((ra & UA_HASNEWMSGS)==0)
506 && ((qrbuf->QRfloor == (CC->FloorBeingSearched))
507 ||((CC->FloorBeingSearched)<0)) )
508 cprintf("%s|%u|%d\n",
509 qrbuf->QRname,qrbuf->QRflags,qrbuf->QRfloor);
512 void cmd_lkro(char *argbuf)
514 CC->FloorBeingSearched = (-1);
515 if (strlen(argbuf)>0) CC->FloorBeingSearched = extract_int(argbuf,0);
517 if (!(CC->logged_in)) {
518 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
522 if (getuser(&CC->usersupp,CC->curr_user)) {
523 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
527 cprintf("%d Rooms w/o new msgs:\n",LISTING_FOLLOWS);
529 ForEachRoom(cmd_lkro_backend);
536 * cmd_lzrm() - List all forgotten rooms
538 void cmd_lzrm_backend(struct quickroom *qrbuf) {
541 ra = CtdlRoomAccess(qrbuf, &CC->usersupp);
542 if ( (ra & UA_GOTOALLOWED)
544 && ((qrbuf->QRfloor == (CC->FloorBeingSearched))
545 ||((CC->FloorBeingSearched)<0)) )
546 cprintf("%s|%u|%d\n",
547 qrbuf->QRname,qrbuf->QRflags,qrbuf->QRfloor);
550 void cmd_lzrm(char *argbuf)
552 CC->FloorBeingSearched = (-1);
553 if (strlen(argbuf)>0) CC->FloorBeingSearched = extract_int(argbuf,0);
555 if (!(CC->logged_in)) {
556 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
560 if (getuser(&CC->usersupp,CC->curr_user)) {
561 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
565 cprintf("%d Zapped rooms:\n",LISTING_FOLLOWS);
567 ForEachRoom(cmd_lzrm_backend);
573 void usergoto(char *where, int display_result)
576 int new_messages = 0;
577 int total_messages = 0;
581 int newmailcount = 0;
584 strcpy(CC->quickroom.QRname, where);
585 lprintf(9, "usergoto() fetching room record\n");
586 getroom(&CC->quickroom, where);
587 lprintf(9, "usergoto() fetching user record\n");
588 lgetuser(&CC->usersupp,CC->curr_user);
589 lprintf(9, "usergoto() fetching relationships\n");
590 CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
592 vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
593 vbuf.v_flags = vbuf.v_flags | V_ACCESS;
595 CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
596 lputuser(&CC->usersupp,CC->curr_user);
598 lprintf(9, "usergoto() about to check for new mail\n");
599 /* check for new mail */
600 newmailcount = NewMailCount();
602 /* set info to 1 if the user needs to read the room's info file */
603 if (CC->quickroom.QRinfo > vbuf.v_lastseen) info = 1;
606 lprintf(9, "Fetching message list for counting...\n");
607 get_msglist(&CC->quickroom);
608 for (a=0; a<CC->num_msgs; ++a) {
609 if (MessageFromList(a)>0L) {
611 if (MessageFromList(a) > vbuf.v_lastseen) {
616 lprintf(9, "...done counting\n");
618 if (CC->quickroom.QRflags & QR_MAILBOX) rmailflag = 1;
621 if ( (CC->quickroom.QRroomaide == CC->usersupp.usernum)
622 || (CC->usersupp.axlevel>=6) ) raideflag = 1;
625 if (display_result) cprintf("%d%c%s|%d|%d|%d|%d|%ld|%ld|%d|%d|%d|%d\n",
627 CC->quickroom.QRname,
628 new_messages, total_messages,
629 info,CC->quickroom.QRflags,
630 CC->quickroom.QRhighest,
632 rmailflag,raideflag,newmailcount,CC->quickroom.QRfloor);
634 if (CC->quickroom.QRflags & QR_PRIVATE) {
635 set_wtmpsupp("<private room>");
638 set_wtmpsupp(CC->quickroom.QRname);
644 * cmd_goto() - goto a new room
646 void cmd_goto(char *gargs)
648 struct quickroom QRscratch;
652 char bbb[ROOMNAMELEN],towhere[32],password[20];
654 if ((!(CC->logged_in)) && (!(CC->internal_pgm))) {
655 cprintf("%d not logged in\n",ERROR+NOT_LOGGED_IN);
659 extract(towhere,gargs,0);
660 extract(password,gargs,1);
663 getuser(&CC->usersupp,CC->curr_user);
665 if (!strcasecmp(towhere, "_BASEROOM_"))
666 strcpy(towhere, BASEROOM);
668 if (!strcasecmp(towhere, "_MAIL_"))
669 strcpy(towhere, MAILROOM);
671 if (!strcasecmp(towhere, "_BITBUCKET_"))
672 strcpy(towhere, config.c_twitroom);
675 /* let internal programs go directly to any room */
676 if (((CC->internal_pgm))&&(!strcasecmp(bbb,towhere))) {
677 usergoto(towhere, 1);
681 if (getroom(&QRscratch, towhere) == 0) {
683 /* See if there is an existing user/room relationship */
684 ra = CtdlRoomAccess(&QRscratch, &CC->usersupp);
686 /* normal clients have to pass through security */
687 if (ra & UA_GOTOALLOWED) ok = 1;
690 if ( (QRscratch.QRflags&QR_PASSWORDED) &&
691 ((ra & UA_KNOWN) == 0) &&
692 (strcasecmp(QRscratch.QRpasswd,password))
694 cprintf("%d wrong or missing passwd\n",
695 ERROR+PASSWORD_REQUIRED);
699 usergoto(towhere, 1);
705 cprintf("%d room '%s' not found\n",ERROR+ROOM_NOT_FOUND,towhere);
709 void cmd_whok(void) {
710 struct usersupp temp;
711 struct cdbdata *cdbus;
713 if ((!(CC->logged_in))&&(!(CC->internal_pgm))) {
714 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
717 getuser(&CC->usersupp,CC->curr_user);
719 if ((!is_room_aide()) && (!(CC->internal_pgm)) ) {
720 cprintf("%d Higher access required.\n",
721 ERROR+HIGHER_ACCESS_REQUIRED);
725 cprintf("%d Who knows room:\n",LISTING_FOLLOWS);
726 cdb_rewind(CDB_USERSUPP);
727 while(cdbus = cdb_next_item(CDB_USERSUPP), cdbus != NULL) {
728 memset(&temp, 0, sizeof(struct usersupp));
729 memcpy(&temp, cdbus->ptr, cdbus->len);
732 if ( (CC->quickroom.QRflags & QR_INUSE)
733 && (CtdlRoomAccess(&CC->quickroom, &temp) & UA_KNOWN)
734 ) cprintf("%s\n",temp.fullname);
741 * RDIR command for room directory
743 void cmd_rdir(void) {
750 if (!(CC->logged_in)) {
751 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
755 getroom(&CC->quickroom, CC->quickroom.QRname);
756 getuser(&CC->usersupp, CC->curr_user);
758 if ((CC->quickroom.QRflags & QR_DIRECTORY) == 0) {
759 cprintf("%d not here.\n",ERROR+NOT_HERE);
763 if (((CC->quickroom.QRflags & QR_VISDIR) == 0)
764 && (CC->usersupp.axlevel<6)
765 && (CC->usersupp.usernum != CC->quickroom.QRroomaide)) {
766 cprintf("%d not here.\n",ERROR+HIGHER_ACCESS_REQUIRED);
770 cprintf("%d %s|%s/files/%s\n",
771 LISTING_FOLLOWS,config.c_fqdn,BBSDIR,CC->quickroom.QRdirname);
773 sprintf(buf,"cd %s/files/%s; ls >%s 2>/dev/null",
774 BBSDIR,CC->quickroom.QRdirname,CC->temp);
777 sprintf(buf,"%s/files/%s/filedir",BBSDIR,CC->quickroom.QRdirname);
779 if (fd==NULL) fd=fopen("/dev/null","r");
781 ls = fopen(CC->temp,"r");
782 while (fgets(flnm,256,ls)!=NULL) {
783 flnm[strlen(flnm)-1]=0;
784 if (strcasecmp(flnm,"filedir")) {
785 sprintf(buf,"%s/files/%s/%s",
786 BBSDIR,CC->quickroom.QRdirname,flnm);
790 while ((fgets(buf,256,fd)!=NULL)
791 &&(strlen(comment)==0)) {
792 buf[strlen(buf)-1] = 0;
793 if ((!strncasecmp(buf,flnm,strlen(flnm)))
794 && (buf[strlen(flnm)]==' '))
796 &buf[strlen(flnm)+1],255);
798 cprintf("%s|%ld|%s\n",flnm,statbuf.st_size,comment);
809 * get room parameters (aide or room aide command)
811 void cmd_getr(void) {
812 if ((!(CC->logged_in))&&(!(CC->internal_pgm))) {
813 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
817 if ( (!is_room_aide()) && (!(CC->internal_pgm)) ) {
818 cprintf("%d Higher access required.\n",
819 ERROR+HIGHER_ACCESS_REQUIRED);
823 if (is_noneditable(&CC->quickroom)) {
824 cprintf("%d Can't edit this room.\n",ERROR+NOT_HERE);
828 getroom(&CC->quickroom, CC->quickroom.QRname);
829 cprintf("%d%c%s|%s|%s|%d|%d\n",
831 CC->quickroom.QRname,
832 ((CC->quickroom.QRflags & QR_PASSWORDED) ? CC->quickroom.QRpasswd : ""),
833 ((CC->quickroom.QRflags & QR_DIRECTORY) ? CC->quickroom.QRdirname : ""),
834 CC->quickroom.QRflags,
835 (int)CC->quickroom.QRfloor);
840 * set room parameters (aide or room aide command)
842 void cmd_setr(char *args) {
847 if (!(CC->logged_in)) {
848 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
852 if (!is_room_aide()) {
853 cprintf("%d Higher access required.\n",
854 ERROR+HIGHER_ACCESS_REQUIRED);
858 if (is_noneditable(&CC->quickroom)) {
859 cprintf("%d Can't edit this room.\n",ERROR+NOT_HERE);
863 if (num_parms(args)>=6) {
864 getfloor(&flbuf,extract_int(args,5));
865 if ((flbuf.f_flags & F_INUSE) == 0) {
866 cprintf("%d Invalid floor number.\n",
867 ERROR+INVALID_FLOOR_OPERATION);
872 lgetroom(&CC->quickroom, CC->quickroom.QRname);
873 extract(buf,args,0); buf[ROOMNAMELEN]=0;
874 strncpy(CC->quickroom.QRname,buf,ROOMNAMELEN-1);
875 extract(buf,args,1); buf[10]=0;
876 strncpy(CC->quickroom.QRpasswd,buf,9);
877 extract(buf,args,2); buf[15]=0;
878 strncpy(CC->quickroom.QRdirname,buf,19);
879 CC->quickroom.QRflags = ( extract_int(args,3) | QR_INUSE);
881 /* Clean up a client boo-boo: if the client set the room to
882 * guess-name or passworded, ensure that the private flag is
885 if ((CC->quickroom.QRflags & QR_GUESSNAME)
886 ||(CC->quickroom.QRflags & QR_PASSWORDED))
887 CC->quickroom.QRflags |= QR_PRIVATE;
889 /* Kick everyone out if the client requested it (by changing the
890 * room's generation number)
892 if (extract_int(args,4)) {
893 time(&CC->quickroom.QRgen);
896 old_floor = CC->quickroom.QRfloor;
897 if (num_parms(args)>=6) {
898 CC->quickroom.QRfloor = extract_int(args,5);
901 lputroom(&CC->quickroom, CC->quickroom.QRname);
903 /* adjust the floor reference counts */
904 lgetfloor(&flbuf,old_floor);
906 lputfloor(&flbuf,old_floor);
907 lgetfloor(&flbuf,CC->quickroom.QRfloor);
909 lputfloor(&flbuf,CC->quickroom.QRfloor);
911 /* create a room directory if necessary */
912 if (CC->quickroom.QRflags & QR_DIRECTORY) {
914 "mkdir ./files/%s </dev/null >/dev/null 2>/dev/null",
915 CC->quickroom.QRdirname);
919 sprintf(buf,"%s> edited by %s",CC->quickroom.QRname,CC->curr_user);
921 cprintf("%d Ok\n",OK);
927 * get the name of the room aide for this room
929 void cmd_geta(void) {
930 struct usersupp usbuf;
932 if ((!(CC->logged_in))&&(!(CC->internal_pgm))) {
933 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
937 if (is_noneditable(&CC->quickroom)) {
938 cprintf("%d Can't edit this room.\n",ERROR+NOT_HERE);
942 if (getuserbynumber(&usbuf,CC->quickroom.QRroomaide)==0) {
943 cprintf("%d %s\n",OK,usbuf.fullname);
952 * set the room aide for this room
954 void cmd_seta(char *new_ra)
956 struct usersupp usbuf;
961 if (!(CC->logged_in)) {
962 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
966 if (!is_room_aide()) {
967 cprintf("%d Higher access required.\n",
968 ERROR+HIGHER_ACCESS_REQUIRED);
972 if (getuser(&usbuf,new_ra)!=0) {
976 newu = usbuf.usernum;
979 lgetroom(&CC->quickroom, CC->quickroom.QRname);
981 if (CC->quickroom.QRroomaide != newu) {
984 CC->quickroom.QRroomaide = newu;
985 lputroom(&CC->quickroom, CC->quickroom.QRname);
988 * We have to post the change notice _after_ writing changes to
989 * the room table, otherwise it would deadlock!
991 if (post_notice == 1) {
992 sprintf(buf,"%s is now room aide for %s>",
993 usbuf.fullname,CC->quickroom.QRname);
996 cprintf("%d Ok\n",OK);
1000 * Generate an associated file name for a room
1002 void assoc_file_name(char *buf, struct quickroom *qrbuf, char *prefix) {
1005 sprintf(buf, "./prefix/%s.%ld", qrbuf->QRname, qrbuf->QRgen);
1006 for (a=0; a<strlen(buf); ++a) {
1007 if (buf[a]==32) buf[a]='.';
1012 * retrieve info file for this room
1014 void cmd_rinf(void) {
1019 assoc_file_name(filename, &CC->quickroom, "info");
1020 info_fp = fopen(filename,"r");
1022 if (info_fp==NULL) {
1023 cprintf("%d No info file.\n",ERROR);
1027 cprintf("%d Info:\n",LISTING_FOLLOWS);
1028 while (fgets(buf, 256, info_fp) != NULL) {
1029 if (strlen(buf) > 0) buf[strlen(buf)-1] = 0;
1030 cprintf("%s\n", buf);
1037 * Back end processing to delete a room and everything associated with it
1039 void delete_room(struct quickroom *qrbuf) {
1045 /* Delete the info file */
1046 assoc_file_name(aaa, qrbuf, "info");
1049 /* Delete the image file */
1050 assoc_file_name(aaa, qrbuf, "images");
1053 /* first flag the room record as not in use */
1054 lgetroom(qrbuf, qrbuf->QRname);
1057 /* then delete the messages in the room */
1058 lprintf(9, "calling get_msglist()\n");
1060 if (CC->num_msgs > 0) for (a=0; a < CC->num_msgs; ++a) {
1061 MsgToDelete = MessageFromList(a);
1062 lprintf(9, "Deleting message %ld\n", MsgToDelete);
1063 cdb_delete(CDB_MSGMAIN, &MsgToDelete, sizeof(long));
1065 lprintf(9, "calling put_msglist()\n");
1070 lprintf(9, "calling delete_msglist()\n");
1071 delete_msglist(qrbuf);
1072 lputroom(qrbuf, qrbuf->QRname);
1074 /* then decrement the reference count for the floor */
1075 lgetfloor(&flbuf,(int)(qrbuf->QRfloor));
1076 flbuf.f_ref_count = flbuf.f_ref_count - 1;
1077 lputfloor(&flbuf,(int)(qrbuf->QRfloor));
1079 /* Delete the room record from the database! */
1080 putroom(NULL, qrbuf->QRname);
1081 lprintf(9, "finished with delete_room()\n");
1086 * aide command: kill the current room
1088 void cmd_kill(char *argbuf) {
1090 char deleted_room_name[ROOMNAMELEN];
1093 kill_ok = extract_int(argbuf,0);
1095 if (!(CC->logged_in)) {
1096 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1100 if (!is_room_aide()) {
1101 cprintf("%d Higher access required.\n",
1102 ERROR+HIGHER_ACCESS_REQUIRED);
1106 if (is_noneditable(&CC->quickroom)) {
1107 cprintf("%d Can't edit this room.\n",ERROR+NOT_HERE);
1112 strcpy(deleted_room_name, CC->quickroom.QRname);
1113 delete_room(&CC->quickroom); /* Do the dirty work */
1114 lprintf(9, "Calling usergoto()\n");
1115 usergoto(BASEROOM, 0); /* Return to the Lobby */
1117 lprintf(9, "Composing notice\n");
1118 /* tell the world what we did */
1119 sprintf(aaa,"%s> killed by %s",
1120 deleted_room_name, CC->curr_user);
1121 lprintf(9, "Posting notice\n");
1123 lprintf(9, "done posting notice\n");
1124 cprintf("%d '%s' deleted.\n", OK, deleted_room_name);
1127 cprintf("%d ok to delete.\n",OK);
1133 * Internal code to create a new room (returns room flags)
1135 * Room types: 0=public, 1=guessname, 2=passworded, 3=inv-only, 4=mailbox
1137 unsigned create_room(char *new_room_name,
1139 char *new_room_pass,
1140 int new_room_floor) {
1142 struct quickroom qrbuf;
1146 if (getroom(&qrbuf, new_room_name)==0) return(0); /* already exists */
1148 memset(&qrbuf, 0, sizeof(struct quickroom));
1149 strncpy(qrbuf.QRname,new_room_name,ROOMNAMELEN);
1150 strncpy(qrbuf.QRpasswd,new_room_pass,9);
1151 qrbuf.QRflags = QR_INUSE;
1152 if (new_room_type > 0) qrbuf.QRflags=(qrbuf.QRflags|QR_PRIVATE);
1153 if (new_room_type == 1) qrbuf.QRflags=(qrbuf.QRflags|QR_GUESSNAME);
1154 if (new_room_type == 2) qrbuf.QRflags=(qrbuf.QRflags|QR_PASSWORDED);
1155 if (new_room_type == 4) qrbuf.QRflags=(qrbuf.QRflags|QR_MAILBOX);
1157 /* If the room is private, and the system administrator has elected
1158 * to automatically grant room aide privileges, do so now; otherwise,
1159 * set the room aide to undefined.
1161 if ( (qrbuf.QRflags & QR_PRIVATE) && (CREATAIDE==1) ) {
1162 qrbuf.QRroomaide=CC->usersupp.usernum;
1165 qrbuf.QRroomaide = (-1L);
1168 qrbuf.QRhighest = 0L; /* No messages in this room yet */
1169 time(&qrbuf.QRgen); /* Use a timestamp as the generation number */
1170 qrbuf.QRfloor = new_room_floor;
1172 /* save what we just did... */
1173 putroom(&qrbuf, qrbuf.QRname);
1175 /* bump the reference count on whatever floor the room is on */
1176 lgetfloor(&flbuf,(int)qrbuf.QRfloor);
1177 flbuf.f_ref_count = flbuf.f_ref_count + 1;
1178 lputfloor(&flbuf,(int)qrbuf.QRfloor);
1180 /* be sure not to kick the creator out of the room! */
1181 lgetuser(&CC->usersupp,CC->curr_user);
1182 CtdlGetRelationship(&vbuf, &CC->usersupp, &qrbuf);
1183 vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
1184 vbuf.v_flags = vbuf.v_flags | V_ACCESS;
1185 CtdlSetRelationship(&vbuf, &CC->usersupp, &qrbuf);
1186 lputuser(&CC->usersupp,CC->curr_user);
1188 /* resume our happy day */
1189 return(qrbuf.QRflags);
1196 void cmd_cre8(char *args)
1199 char new_room_name[256];
1201 char new_room_pass[256];
1205 struct quickroom qrbuf;
1208 cre8_ok = extract_int(args,0);
1209 extract(new_room_name,args,1);
1210 new_room_name[ROOMNAMELEN-1] = 0;
1211 new_room_type = extract_int(args,2);
1212 extract(new_room_pass,args,3);
1213 new_room_pass[9] = 0;
1216 if ((strlen(new_room_name)==0) && (cre8_ok==1)) {
1217 cprintf("%d Invalid room name.\n",ERROR);
1221 if (num_parms(args)>=5) {
1222 getfloor(&flbuf,extract_int(args,4));
1223 if ((flbuf.f_flags & F_INUSE) == 0) {
1224 cprintf("%d Invalid floor number.\n",
1225 ERROR+INVALID_FLOOR_OPERATION);
1229 new_room_floor = extract_int(args,4);
1233 if (!(CC->logged_in)) {
1234 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1238 if (CC->usersupp.axlevel<3) {
1239 cprintf("%d You need higher access to create rooms.\n",
1240 ERROR+HIGHER_ACCESS_REQUIRED);
1244 if ((strlen(new_room_name)==0) && (cre8_ok==0)) {
1245 cprintf("%d Ok to create rooms.\n", OK);
1249 /* Check to make sure the requested room name doesn't already exist */
1250 if (getroom(&qrbuf, new_room_name)==0) {
1251 cprintf("%d '%s' already exists.\n",
1252 ERROR,qrbuf.QRname);
1256 if ((new_room_type < 0) || (new_room_type > 3)) {
1257 cprintf("%d Invalid room type.\n",ERROR);
1262 cprintf("%d OK to create '%s'\n", OK, new_room_name);
1266 newflags = create_room(new_room_name,
1267 new_room_type,new_room_pass,new_room_floor);
1269 /* post a message in Aide> describing the new room */
1270 strncpy(aaa,new_room_name,255);
1271 strcat(aaa,"> created by ");
1272 strcat(aaa,CC->usersupp.fullname);
1273 if (newflags&QR_PRIVATE) strcat(aaa," [private]");
1274 if (newflags&QR_GUESSNAME) strcat(aaa,"[guessname] ");
1275 if (newflags&QR_PASSWORDED) {
1276 strcat(aaa,"\n Password: ");
1277 strcat(aaa,new_room_pass);
1281 cprintf("%d '%s' has been created.\n",OK,qrbuf.QRname);
1286 void cmd_einf(char *ok)
1287 { /* enter info file for current room */
1289 char infofilename[64];
1292 if (!(CC->logged_in)) {
1293 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1297 if (!is_room_aide()) {
1298 cprintf("%d Higher access required.\n",
1299 ERROR+HIGHER_ACCESS_REQUIRED);
1304 cprintf("%d Ok.\n",OK);
1308 cprintf("%d Send info...\n",SEND_LISTING);
1310 assoc_file_name(infofilename, &CC->quickroom, "info");
1312 fp=fopen(infofilename,"w");
1315 if (strcmp(buf,"000")) fprintf(fp,"%s\n",buf);
1316 } while(strcmp(buf,"000"));
1319 /* now update the room index so people will see our new info */
1320 lgetroom(&CC->quickroom,CC->quickroom.QRname); /* lock so no one steps on us */
1321 CC->quickroom.QRinfo = CC->quickroom.QRhighest + 1L;
1322 lputroom(&CC->quickroom,CC->quickroom.QRname);
1327 * cmd_lflr() - List all known floors
1329 void cmd_lflr(void) {
1333 if (!(CC->logged_in)) {
1334 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1338 /* if (getuser(&CC->usersupp,CC->curr_user)) {
1339 cprintf("%d Can't locate user!\n",ERROR+INTERNAL_ERROR);
1344 cprintf("%d Known floors:\n",LISTING_FOLLOWS);
1346 for (a=0; a<MAXFLOORS; ++a) {
1348 if (flbuf.f_flags & F_INUSE) {
1349 cprintf("%d|%s|%d\n",
1361 * create a new floor
1363 void cmd_cflr(char *argbuf)
1365 char new_floor_name[256];
1368 int free_slot = (-1);
1371 extract(new_floor_name,argbuf,0);
1372 cflr_ok = extract_int(argbuf,1);
1375 if (!(CC->logged_in)) {
1376 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1380 if (CC->usersupp.axlevel<6) {
1381 cprintf("%d You need higher access to create rooms.\n",
1382 ERROR+HIGHER_ACCESS_REQUIRED);
1386 for (a=0; a<MAXFLOORS; ++a) {
1389 /* note any free slots while we're scanning... */
1390 if ( ((flbuf.f_flags & F_INUSE)==0)
1391 && (free_slot < 0) ) free_slot = a;
1393 /* check to see if it already exists */
1394 if ( (!strcasecmp(flbuf.f_name,new_floor_name))
1395 && (flbuf.f_flags & F_INUSE) ) {
1396 cprintf("%d Floor '%s' already exists.\n",
1397 ERROR+ALREADY_EXISTS,
1405 cprintf("%d There is no space available for a new floor.\n",
1406 ERROR+INVALID_FLOOR_OPERATION);
1411 cprintf("%d ok to create...\n",OK);
1415 lgetfloor(&flbuf,free_slot);
1416 flbuf.f_flags = F_INUSE;
1417 flbuf.f_ref_count = 0;
1418 strncpy(flbuf.f_name,new_floor_name,255);
1419 lputfloor(&flbuf,free_slot);
1420 cprintf("%d %d\n",OK,free_slot);
1428 void cmd_kflr(char *argbuf)
1431 int floor_to_delete;
1435 floor_to_delete = extract_int(argbuf,0);
1436 kflr_ok = extract_int(argbuf,1);
1439 if (!(CC->logged_in)) {
1440 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1444 if (CC->usersupp.axlevel<6) {
1445 cprintf("%d You need higher access to delete floors.\n",
1446 ERROR+HIGHER_ACCESS_REQUIRED);
1450 lgetfloor(&flbuf,floor_to_delete);
1453 if ((flbuf.f_flags & F_INUSE) == 0) {
1454 cprintf("%d Floor %d not in use.\n",
1455 ERROR+INVALID_FLOOR_OPERATION,floor_to_delete);
1460 if (flbuf.f_ref_count != 0) {
1461 cprintf("%d Cannot delete; floor contains %d rooms.\n",
1462 ERROR+INVALID_FLOOR_OPERATION,
1469 cprintf("%d Ok\n",OK);
1472 cprintf("%d Ok to delete...\n",OK);
1479 if ( (delete_ok == 1) && (kflr_ok == 1) ) flbuf.f_flags = 0;
1480 lputfloor(&flbuf,floor_to_delete);
1486 void cmd_eflr(char *argbuf)
1492 np = num_parms(argbuf);
1494 cprintf("%d Usage error.\n",ERROR);
1498 if (!(CC->logged_in)) {
1499 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1503 if (CC->usersupp.axlevel<6) {
1504 cprintf("%d You need higher access to edit floors.\n",
1505 ERROR+HIGHER_ACCESS_REQUIRED);
1509 floor_num = extract_int(argbuf,0);
1510 lgetfloor(&flbuf,floor_num);
1511 if ( (flbuf.f_flags & F_INUSE) == 0) {
1512 lputfloor(&flbuf,floor_num);
1513 cprintf("%d Floor %d is not in use.\n",
1514 ERROR+INVALID_FLOOR_OPERATION,floor_num);
1517 if (np >= 2) extract(flbuf.f_name,argbuf,1);
1518 lputfloor(&flbuf,floor_num);
1520 cprintf("%d Ok\n",OK);