17 #include <sys/select.h>
21 extern struct config config;
23 typedef struct CitContext t_context;
25 extern struct CitContext *ContextList;
27 struct ChatLine *ChatQueue = NULL;
31 void allwrite(char *cmdbuf, int flag, char *roomname, char *username)
36 struct ChatLine *clptr, *clnew;
39 if (CC->fake_username[0])
40 un = CC->fake_username;
42 un = CC->usersupp.fullname;
45 sprintf(bcast,":|<%s %s>",un,cmdbuf);
50 sprintf(bcast,"%s|%s",un,cmdbuf);
55 sprintf(bcast,":|<%s whispers %s>", un, cmdbuf);
57 if ((strcasecmp(cmdbuf,"NOOP")) && (flag !=2)) {
58 fp = fopen(CHATLOG,"a");
59 fprintf(fp,"%s\n",bcast);
63 clnew = (struct ChatLine *) malloc(sizeof(struct ChatLine));
64 bzero(clnew, sizeof(struct ChatLine));
66 fprintf(stderr, "citserver: cannot alloc chat line: %s\n",
73 clnew->chat_time = now;
74 strncpy(clnew->chat_room, roomname, 19);
76 strncpy(clnew->chat_username, username, 31);
78 clnew->chat_username[0] = '\0';
79 strcpy(clnew->chat_text, bcast);
81 /* Here's the critical section.
82 * First, add the new message to the queue...
84 begin_critical_section(S_CHATQUEUE);
86 clnew->chat_seq = ChatLastMsg;
87 if (ChatQueue == NULL) {
91 for (clptr=ChatQueue; clptr->next != NULL; clptr=clptr->next) ;;
95 /* Then, before releasing the lock, free the expired messages */
97 if (ChatQueue == NULL) goto DONE_FREEING;
98 if ( (now - ChatQueue->chat_time) < 120L ) goto DONE_FREEING;
100 ChatQueue = ChatQueue->next;
103 DONE_FREEING: end_critical_section(S_CHATQUEUE);
107 t_context *find_context(char **unstr)
109 t_context *t_cc, *found_cc = NULL;
112 if ((!*unstr) || (!unstr))
115 begin_critical_section(S_SESSION_TABLE);
116 for (t_cc = ContextList; ((t_cc) && (!found_cc)); t_cc = t_cc->next)
118 if (t_cc->fake_username[0])
119 name = t_cc->fake_username;
121 name = t_cc->curr_user;
123 if ((!strncasecmp(name, tptr, strlen(name))) && (tptr[strlen(name)] == ' '))
126 *unstr = &(tptr[strlen(name)+1]);
129 end_critical_section(S_SESSION_TABLE);
135 * List users in chat. Setting allflag to 1 also lists users elsewhere.
139 void do_chat_listing(int allflag)
141 struct CitContext *ccptr;
143 cprintf(":|\n:| Users currently in chat:\n");
144 begin_critical_section(S_SESSION_TABLE);
145 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) {
146 if ( (!strcasecmp(ccptr->cs_room, "<chat>"))
147 && ((ccptr->cs_flags & CS_STEALTH) == 0)) {
148 cprintf(":| %-25s <%s>\n", (ccptr->fake_username[0]) ? ccptr->fake_username : ccptr->curr_user, ccptr->chat_room);
154 cprintf(":|\n:| Users not in chat:\n");
155 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next)
157 if ( (strcasecmp(ccptr->cs_room, "<chat>"))
158 && ((ccptr->cs_flags & CS_STEALTH) == 0))
160 cprintf(":| %-25s <%s>:\n", (ccptr->fake_username[0]) ? ccptr->fake_username : ccptr->curr_user, (ccptr->fake_roomname[0]) ? ccptr->fake_roomname : ccptr->cs_room);
165 end_critical_section(S_SESSION_TABLE);
170 void cmd_chat(char *argbuf)
175 char hold_cs_room[20];
176 int MyLastMsg, ThisLastMsg;
177 struct ChatLine *clptr;
178 struct CitContext *t_context;
181 if (!(CC->logged_in)) {
182 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
186 strcpy(CC->chat_room, "Main room");
188 strcpy(hold_cs_room,CC->cs_room);
189 CC->cs_flags = CC->cs_flags | CS_CHAT;
190 set_wtmpsupp("<chat>");
191 cprintf("%d Entering chat mode (type '/help' for available commands)\n",
194 MyLastMsg = ChatLastMsg;
196 if ((CC->cs_flags & CS_STEALTH) == 0) {
197 allwrite("<entering chat>",0, CC->chat_room, NULL);
206 cmdbuf[strlen(cmdbuf) + 1] = 0;
207 retval = client_read_to(&cmdbuf[strlen(cmdbuf)], 1, 2);
209 /* if we have a complete line, do send processing */
210 if (strlen(cmdbuf) > 0) if (cmdbuf[strlen(cmdbuf)-1] == 10) {
211 cmdbuf[strlen(cmdbuf) - 1] = 0;
215 if ( (!strcasecmp(cmdbuf,"exit"))
216 ||(!strcasecmp(cmdbuf,"/exit"))
217 ||(!strcasecmp(cmdbuf,"quit"))
218 ||(!strcasecmp(cmdbuf,"logout"))
219 ||(!strcasecmp(cmdbuf,"logoff"))
220 ||(!strcasecmp(cmdbuf,"/q"))
221 ||(!strcasecmp(cmdbuf,".q"))
222 ||(!strcasecmp(cmdbuf,"/quit"))
223 ) strcpy(cmdbuf,"000");
225 if (!strcmp(cmdbuf,"000")) {
226 if ((CC->cs_flags & CS_STEALTH) == 0) {
227 allwrite("<exiting chat>",0, CC->chat_room, NULL);
231 CC->cs_flags = CC->cs_flags - CS_CHAT;
232 set_wtmpsupp(hold_cs_room);
236 if ((!strcasecmp(cmdbuf,"/help"))
237 ||(!strcasecmp(cmdbuf,"help"))
238 ||(!strcasecmp(cmdbuf,"/?"))
239 ||(!strcasecmp(cmdbuf,"?"))) {
241 cprintf(":|Available commands: \n");
242 cprintf(":|/help (prints this message) \n");
243 cprintf(":|/who (list users currently in chat) \n");
244 cprintf(":|/whobbs (list users in chat -and- elsewhere) \n");
245 cprintf(":|/me ('action' line, ala irc) \n");
246 cprintf(":|/msg (send private message, ala irc) \n");
247 cprintf(":|/join (join new room) \n");
248 cprintf(":|/quit (return to the BBS) \n");
252 if (!strcasecmp(cmdbuf,"/who")) {
256 if (!strcasecmp(cmdbuf,"/whobbs")) {
260 if (!strncasecmp(cmdbuf,"/me ",4)) {
261 allwrite(&cmdbuf[4],1, CC->chat_room, NULL);
265 if (!strncasecmp(cmdbuf,"/msg ", 5))
268 strptr1 = &cmdbuf[5];
269 if ((t_context = find_context(&strptr1)))
271 allwrite(strptr1, 2, "", CC->curr_user);
272 if (strcasecmp(CC->curr_user, t_context->curr_user))
273 allwrite(strptr1, 2, "", t_context->curr_user);
276 cprintf(":|User not found.\n", cmdbuf);
280 if (!strncasecmp(cmdbuf,"/join ", 6))
283 allwrite("<changing rooms>",0, CC->chat_room, NULL);
285 strcpy(CC->chat_room, "Main room");
288 strncpy(CC->chat_room, &cmdbuf[6], 20);
290 allwrite("<joining room>",0, CC->chat_room, NULL);
293 if ((cmdbuf[0]!='/')&&(strlen(cmdbuf)>0)) {
295 allwrite(cmdbuf,0, CC->chat_room, NULL);
299 cprintf(":|Command %s is not understood.\n", cmdbuf);
305 /* now check the queue for new incoming stuff */
307 if (CC->fake_username[0])
308 un = CC->fake_username;
311 if (ChatLastMsg > MyLastMsg) {
312 ThisLastMsg = ChatLastMsg;
313 for (clptr=ChatQueue; clptr!=NULL; clptr=clptr->next)
315 if ((clptr->chat_seq > MyLastMsg) && ((!clptr->chat_username[0]) || (!strncasecmp(un, clptr->chat_username, 32))))
317 if ((!clptr->chat_room[0]) || (!strncasecmp(CC->chat_room, clptr->chat_room, 20)))
319 cprintf("%s\n", clptr->chat_text);
323 MyLastMsg = ThisLastMsg;
331 * poll for express messages
333 void cmd_pexp(void) {
334 struct ExpressMessage *emptr;
336 if (CC->FirstExpressMessage == NULL) {
337 cprintf("%d No express messages waiting.\n",ERROR);
341 cprintf("%d Express msgs:\n",LISTING_FOLLOWS);
343 while (CC->FirstExpressMessage != NULL) {
344 cprintf("%s", CC->FirstExpressMessage->em_text);
345 begin_critical_section(S_SESSION_TABLE);
346 emptr = CC->FirstExpressMessage;
347 CC->FirstExpressMessage = CC->FirstExpressMessage->next;
349 end_critical_section(S_SESSION_TABLE);
355 * returns an asterisk if there are any express messages waiting,
358 char check_express(void) {
359 if (CC->FirstExpressMessage == NULL) {
369 * send express messages <bc>
371 void cmd_sexp(char *argbuf)
375 int message_sent = 0;
376 struct CitContext *ccptr;
377 struct ExpressMessage *emptr, *emnew;
378 char *lun; /* <bc> */
380 if (!(CC->logged_in)) {
381 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
385 if (num_parms(argbuf)!=2) {
386 cprintf("%d usage error\n",ERROR);
390 if (CC->fake_username[0])
391 lun = CC->fake_username;
393 lun = CC->usersupp.fullname;
395 extract(x_user,argbuf,0);
397 if (!strcmp(x_user, "."))
399 strcpy(x_user, CC->last_pager);
401 extract(x_msg,argbuf,1);
405 cprintf("%d You were not previously paged.\n", ERROR);
409 if ( (!strcasecmp(x_user, "broadcast")) && (CC->usersupp.axlevel < 6) ) {
410 cprintf("%d Higher access required to send a broadcast.\n",
411 ERROR+HIGHER_ACCESS_REQUIRED);
415 /* find the target user's context and append the message */
416 begin_critical_section(S_SESSION_TABLE);
417 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) {
420 if (ccptr->fake_username[0]) /* <bc> */
421 un = ccptr->fake_username;
423 un = ccptr->usersupp.fullname;
425 if ( (!strcasecmp(un, x_user))
426 || (!strcasecmp(x_user, "broadcast")) ) {
427 strcpy(ccptr->last_pager, CC->curr_user);
428 emnew = (struct ExpressMessage *)
429 malloc(sizeof(struct ExpressMessage));
431 sprintf(emnew->em_text, "%s from %s:\n %s\n",
432 ( (!strcasecmp(x_user, "broadcast")) ? "Broadcast message" : "Message" ),
435 if (ccptr->FirstExpressMessage == NULL) {
436 ccptr->FirstExpressMessage = emnew;
439 emptr = ccptr->FirstExpressMessage;
440 while (emptr->next != NULL) {
449 end_critical_section(S_SESSION_TABLE);
451 if (message_sent > 0) {
452 cprintf("%d Message sent.\n",OK);
455 cprintf("%d No user '%s' logged in.\n",ERROR,x_user);