17 #include <sys/select.h>
19 #include "serv_chat.h"
20 #include "sysdep_decls.h"
21 #include "citserver.h"
25 struct ChatLine *ChatQueue = NULL;
29 void allwrite(char *cmdbuf, int flag, char *roomname, char *username)
34 struct ChatLine *clptr, *clnew;
37 if (CC->fake_username[0])
38 un = CC->fake_username;
40 un = CC->usersupp.fullname;
43 sprintf(bcast,":|<%s %s>",un,cmdbuf);
48 sprintf(bcast,"%s|%s",un,cmdbuf);
53 sprintf(bcast,":|<%s whispers %s>", un, cmdbuf);
55 if ((strcasecmp(cmdbuf,"NOOP")) && (flag !=2)) {
56 fp = fopen(CHATLOG,"a");
57 fprintf(fp,"%s\n",bcast);
61 clnew = (struct ChatLine *) malloc(sizeof(struct ChatLine));
62 bzero(clnew, sizeof(struct ChatLine));
64 fprintf(stderr, "citserver: cannot alloc chat line: %s\n",
71 clnew->chat_time = now;
72 strncpy(clnew->chat_room, roomname, 19);
74 strncpy(clnew->chat_username, username, 31);
76 clnew->chat_username[0] = '\0';
77 strcpy(clnew->chat_text, bcast);
79 /* Here's the critical section.
80 * First, add the new message to the queue...
82 begin_critical_section(S_CHATQUEUE);
84 clnew->chat_seq = ChatLastMsg;
85 if (ChatQueue == NULL) {
89 for (clptr=ChatQueue; clptr->next != NULL; clptr=clptr->next) ;;
93 /* Then, before releasing the lock, free the expired messages */
95 if (ChatQueue == NULL) goto DONE_FREEING;
96 if ( (now - ChatQueue->chat_time) < 120L ) goto DONE_FREEING;
98 ChatQueue = ChatQueue->next;
101 DONE_FREEING: end_critical_section(S_CHATQUEUE);
105 t_context *find_context(char **unstr)
107 t_context *t_cc, *found_cc = NULL;
110 if ((!*unstr) || (!unstr))
113 begin_critical_section(S_SESSION_TABLE);
114 for (t_cc = ContextList; ((t_cc) && (!found_cc)); t_cc = t_cc->next)
116 if (t_cc->fake_username[0])
117 name = t_cc->fake_username;
119 name = t_cc->curr_user;
121 if ((!strncasecmp(name, tptr, strlen(name))) && (tptr[strlen(name)] == ' '))
124 *unstr = &(tptr[strlen(name)+1]);
127 end_critical_section(S_SESSION_TABLE);
133 * List users in chat. Setting allflag to 1 also lists users elsewhere.
137 void do_chat_listing(int allflag)
139 struct CitContext *ccptr;
141 cprintf(":|\n:| Users currently in chat:\n");
142 begin_critical_section(S_SESSION_TABLE);
143 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) {
144 if ( (!strcasecmp(ccptr->cs_room, "<chat>"))
145 && ((ccptr->cs_flags & CS_STEALTH) == 0)) {
146 cprintf(":| %-25s <%s>\n", (ccptr->fake_username[0]) ? ccptr->fake_username : ccptr->curr_user, ccptr->chat_room);
152 cprintf(":|\n:| Users not in chat:\n");
153 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next)
155 if ( (strcasecmp(ccptr->cs_room, "<chat>"))
156 && ((ccptr->cs_flags & CS_STEALTH) == 0))
158 cprintf(":| %-25s <%s>:\n", (ccptr->fake_username[0]) ? ccptr->fake_username : ccptr->curr_user, (ccptr->fake_roomname[0]) ? ccptr->fake_roomname : ccptr->cs_room);
163 end_critical_section(S_SESSION_TABLE);
168 void cmd_chat(char *argbuf)
173 char hold_cs_room[20];
174 int MyLastMsg, ThisLastMsg;
175 struct ChatLine *clptr;
176 struct CitContext *t_context;
179 if (!(CC->logged_in)) {
180 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
184 strcpy(CC->chat_room, "Main room");
186 strcpy(hold_cs_room,CC->cs_room);
187 CC->cs_flags = CC->cs_flags | CS_CHAT;
188 set_wtmpsupp("<chat>");
189 cprintf("%d Entering chat mode (type '/help' for available commands)\n",
192 MyLastMsg = ChatLastMsg;
194 if ((CC->cs_flags & CS_STEALTH) == 0) {
195 allwrite("<entering chat>",0, CC->chat_room, NULL);
204 cmdbuf[strlen(cmdbuf) + 1] = 0;
205 retval = client_read_to(&cmdbuf[strlen(cmdbuf)], 1, 2);
207 /* if we have a complete line, do send processing */
208 if (strlen(cmdbuf) > 0) if (cmdbuf[strlen(cmdbuf)-1] == 10) {
209 cmdbuf[strlen(cmdbuf) - 1] = 0;
213 if ( (!strcasecmp(cmdbuf,"exit"))
214 ||(!strcasecmp(cmdbuf,"/exit"))
215 ||(!strcasecmp(cmdbuf,"quit"))
216 ||(!strcasecmp(cmdbuf,"logout"))
217 ||(!strcasecmp(cmdbuf,"logoff"))
218 ||(!strcasecmp(cmdbuf,"/q"))
219 ||(!strcasecmp(cmdbuf,".q"))
220 ||(!strcasecmp(cmdbuf,"/quit"))
221 ) strcpy(cmdbuf,"000");
223 if (!strcmp(cmdbuf,"000")) {
224 if ((CC->cs_flags & CS_STEALTH) == 0) {
225 allwrite("<exiting chat>",0, CC->chat_room, NULL);
229 CC->cs_flags = CC->cs_flags - CS_CHAT;
230 set_wtmpsupp(hold_cs_room);
234 if ((!strcasecmp(cmdbuf,"/help"))
235 ||(!strcasecmp(cmdbuf,"help"))
236 ||(!strcasecmp(cmdbuf,"/?"))
237 ||(!strcasecmp(cmdbuf,"?"))) {
239 cprintf(":|Available commands: \n");
240 cprintf(":|/help (prints this message) \n");
241 cprintf(":|/who (list users currently in chat) \n");
242 cprintf(":|/whobbs (list users in chat -and- elsewhere) \n");
243 cprintf(":|/me ('action' line, ala irc) \n");
244 cprintf(":|/msg (send private message, ala irc) \n");
245 cprintf(":|/join (join new room) \n");
246 cprintf(":|/quit (return to the BBS) \n");
250 if (!strcasecmp(cmdbuf,"/who")) {
254 if (!strcasecmp(cmdbuf,"/whobbs")) {
258 if (!strncasecmp(cmdbuf,"/me ",4)) {
259 allwrite(&cmdbuf[4],1, CC->chat_room, NULL);
263 if (!strncasecmp(cmdbuf,"/msg ", 5))
266 strptr1 = &cmdbuf[5];
267 if ((t_context = find_context(&strptr1)))
269 allwrite(strptr1, 2, "", CC->curr_user);
270 if (strcasecmp(CC->curr_user, t_context->curr_user))
271 allwrite(strptr1, 2, "", t_context->curr_user);
274 cprintf(":|User not found.\n", cmdbuf);
278 if (!strncasecmp(cmdbuf,"/join ", 6))
281 allwrite("<changing rooms>",0, CC->chat_room, NULL);
283 strcpy(CC->chat_room, "Main room");
286 strncpy(CC->chat_room, &cmdbuf[6], 20);
288 allwrite("<joining room>",0, CC->chat_room, NULL);
291 if ((cmdbuf[0]!='/')&&(strlen(cmdbuf)>0)) {
293 allwrite(cmdbuf,0, CC->chat_room, NULL);
297 cprintf(":|Command %s is not understood.\n", cmdbuf);
303 /* now check the queue for new incoming stuff */
305 if (CC->fake_username[0])
306 un = CC->fake_username;
309 if (ChatLastMsg > MyLastMsg) {
310 ThisLastMsg = ChatLastMsg;
311 for (clptr=ChatQueue; clptr!=NULL; clptr=clptr->next)
313 if ((clptr->chat_seq > MyLastMsg) && ((!clptr->chat_username[0]) || (!strncasecmp(un, clptr->chat_username, 32))))
315 if ((!clptr->chat_room[0]) || (!strncasecmp(CC->chat_room, clptr->chat_room, 20)))
317 cprintf("%s\n", clptr->chat_text);
321 MyLastMsg = ThisLastMsg;
329 * poll for express messages
331 void cmd_pexp(void) {
332 struct ExpressMessage *emptr;
334 if (CC->FirstExpressMessage == NULL) {
335 cprintf("%d No express messages waiting.\n",ERROR);
339 cprintf("%d Express msgs:\n",LISTING_FOLLOWS);
341 while (CC->FirstExpressMessage != NULL) {
342 cprintf("%s", CC->FirstExpressMessage->em_text);
343 begin_critical_section(S_SESSION_TABLE);
344 emptr = CC->FirstExpressMessage;
345 CC->FirstExpressMessage = CC->FirstExpressMessage->next;
347 end_critical_section(S_SESSION_TABLE);
353 * returns an asterisk if there are any express messages waiting,
356 char check_express(void) {
357 if (CC->FirstExpressMessage == NULL) {
367 * send express messages <bc>
369 void cmd_sexp(char *argbuf)
373 int message_sent = 0;
374 struct CitContext *ccptr;
375 struct ExpressMessage *emptr, *emnew;
376 char *lun; /* <bc> */
378 if (!(CC->logged_in)) {
379 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
383 if (num_parms(argbuf)!=2) {
384 cprintf("%d usage error\n",ERROR);
388 if (CC->fake_username[0])
389 lun = CC->fake_username;
391 lun = CC->usersupp.fullname;
393 extract(x_user,argbuf,0);
395 if (!strcmp(x_user, "."))
397 strcpy(x_user, CC->last_pager);
399 extract(x_msg,argbuf,1);
403 cprintf("%d You were not previously paged.\n", ERROR);
407 if ( (!strcasecmp(x_user, "broadcast")) && (CC->usersupp.axlevel < 6) ) {
408 cprintf("%d Higher access required to send a broadcast.\n",
409 ERROR+HIGHER_ACCESS_REQUIRED);
413 /* find the target user's context and append the message */
414 begin_critical_section(S_SESSION_TABLE);
415 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) {
418 if (ccptr->fake_username[0]) /* <bc> */
419 un = ccptr->fake_username;
421 un = ccptr->usersupp.fullname;
423 if ( (!strcasecmp(un, x_user))
424 || (!strcasecmp(x_user, "broadcast")) ) {
425 strcpy(ccptr->last_pager, CC->curr_user);
426 emnew = (struct ExpressMessage *)
427 malloc(sizeof(struct ExpressMessage));
429 sprintf(emnew->em_text, "%s from %s:\n %s\n",
430 ( (!strcasecmp(x_user, "broadcast")) ? "Broadcast message" : "Message" ),
433 if (ccptr->FirstExpressMessage == NULL) {
434 ccptr->FirstExpressMessage = emnew;
437 emptr = ccptr->FirstExpressMessage;
438 while (emptr->next != NULL) {
447 end_critical_section(S_SESSION_TABLE);
449 if (message_sent > 0) {
450 cprintf("%d Message sent.\n",OK);
453 cprintf("%d No user '%s' logged in.\n",ERROR,x_user);