17 #include <sys/select.h>
21 extern struct config config;
22 extern struct CitContext *ContextList;
24 struct ChatLine *ChatQueue = NULL;
28 void allwrite(char *cmdbuf, int flag, char *roomname, char *username)
33 struct ChatLine *clptr, *clnew;
36 if (CC->fake_username[0])
37 un = CC->fake_username;
39 un = CC->usersupp.fullname;
42 sprintf(bcast,":|<%s %s>",un,cmdbuf);
47 sprintf(bcast,"%s|%s",un,cmdbuf);
52 sprintf(bcast,":|<%s whispers %s>", un, cmdbuf);
54 if (strucmp(cmdbuf,"NOOP")) {
55 fp = fopen(CHATLOG,"a");
56 fprintf(fp,"%s\n",bcast);
60 clnew = (struct ChatLine *) malloc(sizeof(struct ChatLine));
61 bzero(clnew, sizeof(struct ChatLine));
63 fprintf(stderr, "citserver: cannot alloc chat line: %s\n",
70 clnew->chat_time = now;
71 strncpy(clnew->chat_room, roomname, 19);
73 strncpy(clnew->chat_username, username, 31);
75 clnew->chat_username[0] = '\0';
76 strcpy(clnew->chat_text, bcast);
78 /* Here's the critical section.
79 * First, add the new message to the queue...
81 begin_critical_section(S_CHATQUEUE);
83 clnew->chat_seq = ChatLastMsg;
84 if (ChatQueue == NULL) {
88 for (clptr=ChatQueue; clptr->next != NULL; clptr=clptr->next) ;;
92 /* Then, before releasing the lock, free the expired messages */
94 if (ChatQueue == NULL) goto DONE_FREEING;
95 if ( (now - ChatQueue->chat_time) < 120L ) goto DONE_FREEING;
97 ChatQueue = ChatQueue->next;
100 DONE_FREEING: end_critical_section(S_CHATQUEUE);
104 * List users in chat. Setting allflag to 1 also lists users elsewhere.
106 void do_chat_listing(int allflag)
108 struct CitContext *ccptr;
110 cprintf(":|\n:| Users currently in chat:\n");
111 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) {
112 if ( (!strucmp(ccptr->cs_room, "<chat>"))
113 && ((ccptr->cs_flags & CS_STEALTH) == 0)) {
114 cprintf(":| %-25s <%s>\n", (ccptr->fake_username[0]) ? ccptr->fake_username : ccptr->curr_user, ccptr->chat_room);
120 cprintf(":|\n:| Users not in chat:\n");
121 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next)
123 if ( (strucmp(ccptr->cs_room, "<chat>"))
124 && ((ccptr->cs_flags & CS_STEALTH) == 0))
126 cprintf(":| %-25s <%s>:\n", (ccptr->fake_username[0]) ? ccptr->fake_username : ccptr->curr_user, ccptr->cs_room);
135 void cmd_chat(char *argbuf)
140 char hold_cs_room[20];
141 int MyLastMsg, ThisLastMsg;
142 struct ChatLine *clptr;
145 if (!(CC->logged_in)) {
146 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
150 strcpy(CC->chat_room, "Main room");
152 strcpy(hold_cs_room,CC->cs_room);
153 CC->cs_flags = CC->cs_flags | CS_CHAT;
154 set_wtmpsupp("<chat>");
155 cprintf("%d Entering chat mode (type '/help' for available commands)\n",
158 MyLastMsg = ChatLastMsg;
160 if ((CC->cs_flags & CS_STEALTH) == 0) {
161 allwrite("<entering chat>",0, CC->chat_room, NULL);
167 cmdbuf[strlen(cmdbuf) + 1] = 0;
168 retval = client_read_to(&cmdbuf[strlen(cmdbuf)], 1, 2);
170 /* if we have a complete line, do send processing */
171 if (strlen(cmdbuf) > 0) if (cmdbuf[strlen(cmdbuf)-1] == 10) {
172 cmdbuf[strlen(cmdbuf) - 1] = 0;
176 if ( (!strucmp(cmdbuf,"exit"))
177 ||(!strucmp(cmdbuf,"/exit"))
178 ||(!strucmp(cmdbuf,"quit"))
179 ||(!strucmp(cmdbuf,"logout"))
180 ||(!strucmp(cmdbuf,"logoff"))
181 ||(!strucmp(cmdbuf,"/q"))
182 ||(!strucmp(cmdbuf,".q"))
183 ||(!strucmp(cmdbuf,"/quit"))
184 ) strcpy(cmdbuf,"000");
186 if (!strcmp(cmdbuf,"000")) {
187 if ((CC->cs_flags & CS_STEALTH) == 0) {
188 allwrite("<exiting chat>",0, CC->chat_room, NULL);
192 CC->cs_flags = CC->cs_flags - CS_CHAT;
193 set_wtmpsupp(hold_cs_room);
197 if ((!strucmp(cmdbuf,"/help"))
198 ||(!strucmp(cmdbuf,"help"))
199 ||(!strucmp(cmdbuf,"/?"))
200 ||(!strucmp(cmdbuf,"?"))) {
202 cprintf(":|Available commands: \n");
203 cprintf(":|/help (prints this message) \n");
204 cprintf(":|/who (list users currently in chat) \n");
205 cprintf(":|/whobbs (list users in chat -and- elsewhere) \n");
206 cprintf(":|/me ('action' line, ala irc) \n");
207 cprintf(":|/msg (send private message, ala irc) \n");
208 cprintf(":|/join (join new room) \n");
209 cprintf(":|/quit (return to the BBS) \n");
212 if (!strucmp(cmdbuf,"/who")) {
215 if (!strucmp(cmdbuf,"/whobbs")) {
218 if (!struncmp(cmdbuf,"/me ",4)) {
219 allwrite(&cmdbuf[4],1, CC->chat_room, NULL);
222 if (!struncmp(cmdbuf,"/msg ", 5))
224 strptr1 = strtok(cmdbuf, " ");
227 strptr1 = strtok(NULL, " ");
230 allwrite(&strptr1[strlen(strptr1)+1], 2, CC->chat_room, CC->curr_user);
231 if (struncmp(CC->curr_user, strptr1, strlen(CC->curr_user)))
232 allwrite(&strptr1[strlen(strptr1)+1], 2, CC->chat_room, strptr1);
238 if (!struncmp(cmdbuf,"/join ", 6))
240 allwrite("<changing rooms>",0, CC->chat_room, NULL);
242 strcpy(CC->chat_room, "Main room");
245 strncpy(CC->chat_room, &cmdbuf[6], 20);
247 allwrite("<joining room>",0, CC->chat_room, NULL);
251 if ((cmdbuf[0]!='/')&&(strlen(cmdbuf)>0)) {
252 allwrite(cmdbuf,0, CC->chat_room, NULL);
259 /* now check the queue for new incoming stuff */
261 if (CC->fake_username[0])
262 un = CC->fake_username;
265 if (ChatLastMsg > MyLastMsg) {
266 ThisLastMsg = ChatLastMsg;
267 for (clptr=ChatQueue; clptr!=NULL; clptr=clptr->next)
270 (clptr->chat_seq > MyLastMsg) &&
271 (!struncmp(CC->chat_room, clptr->chat_room, 20)) &&
272 ((!clptr->chat_username[0]) || (!struncmp(un, clptr->chat_username, 32)))
275 cprintf("%s\n", clptr->chat_text);
278 MyLastMsg = ThisLastMsg;
286 * poll for express messages
288 void cmd_pexp(void) {
289 struct ExpressMessage *emptr;
291 if (CC->FirstExpressMessage == NULL) {
292 cprintf("%d No express messages waiting.\n",ERROR);
296 cprintf("%d Express msgs:\n",LISTING_FOLLOWS);
298 while (CC->FirstExpressMessage != NULL) {
299 cprintf("%s", CC->FirstExpressMessage->em_text);
300 begin_critical_section(S_SESSION_TABLE);
301 emptr = CC->FirstExpressMessage;
302 CC->FirstExpressMessage = CC->FirstExpressMessage->next;
304 end_critical_section(S_SESSION_TABLE);
310 * returns an asterisk if there are any express messages waiting,
313 char check_express(void) {
314 if (CC->FirstExpressMessage == NULL) {
324 * send express messages <bc>
326 void cmd_sexp(char *argbuf)
330 int message_sent = 0;
331 struct CitContext *ccptr;
332 struct ExpressMessage *emptr, *emnew;
333 char *lun; /* <bc> */
335 if (!(CC->logged_in)) {
336 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
340 if (num_parms(argbuf)!=2) {
341 cprintf("%d usage error\n",ERROR);
345 if (CC->fake_username[0])
346 lun = CC->fake_username;
348 lun = CC->usersupp.fullname;
350 extract(x_user,argbuf,0);
352 if (!strcmp(x_user, "."))
354 strcpy(x_user, CC->last_pager);
356 extract(x_msg,argbuf,1);
360 cprintf("%d You were not previously paged.\n", ERROR);
364 if ( (!strucmp(x_user, "broadcast")) && (CC->usersupp.axlevel < 6) ) {
365 cprintf("%d Higher access required to send a broadcast.\n",
366 ERROR+HIGHER_ACCESS_REQUIRED);
370 /* find the target user's context and append the message */
371 begin_critical_section(S_SESSION_TABLE);
372 for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) {
375 if (ccptr->fake_username[0]) /* <bc> */
376 un = ccptr->fake_username;
378 un = ccptr->usersupp.fullname;
380 if ( (!strucmp(un, x_user))
381 || (!strucmp(x_user, "broadcast")) ) {
382 strcpy(ccptr->last_pager, CC->curr_user);
383 emnew = (struct ExpressMessage *)
384 malloc(sizeof(struct ExpressMessage));
386 sprintf(emnew->em_text, "%s from %s:\n %s\n",
387 ( (!strucmp(x_user, "broadcast")) ? "Broadcast message" : "Message" ),
390 if (ccptr->FirstExpressMessage == NULL) {
391 ccptr->FirstExpressMessage = emnew;
394 emptr = ccptr->FirstExpressMessage;
395 while (emptr->next != NULL) {
404 end_critical_section(S_SESSION_TABLE);
406 if (message_sent > 0) {
407 cprintf("%d Message sent.\n",OK);
410 cprintf("%d No user '%s' logged in.\n",ERROR,x_user);