This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbsebbs/chat.c

419 lines
10 KiB
C

/*****************************************************************************
*
* $Id: chat.c,v 1.32 2008/02/12 19:59:45 mbse Exp $
* Purpose ...............: Sysop to user chat utility
*
*****************************************************************************
* Copyright (C) 1997-2008
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "../lib/mbselib.h"
#include "../lib/mbse.h"
#include "../lib/users.h"
#include "chat.h"
#include "funcs.h"
#include "input.h"
#include "language.h"
#include "misc.h"
#include "whoson.h"
#include "term.h"
#include "ttyio.h"
#include "timeout.h"
#define RBUFLEN 81
int chat_with_sysop = FALSE; /* Global sysop chat flag */
int chatting = FALSE; /* Global chatting flag */
char rbuf[50][RBUFLEN]; /* Chat receive buffer */ /* FIXME: must be a dynamic buffer */
int rpointer = 0; /* Chat receive pointer */
int rsize = 5; /* Chat receive size */
extern pid_t mypid;
extern int cols;
extern int rows;
extern unsigned int mib_chats;
extern unsigned int mib_chatminutes;
void Showline(int, int, char *);
void DispMsg(char *);
void clrtoeol(void);
unsigned char testkey(int, int);
unsigned char testkey(int y, int x)
{
int rc;
unsigned char ch = 0;
Nopper();
locate(y, x);
rc = Waitchar(&ch, 50);
if (rc == 1) {
if (ch == KEY_ESCAPE)
rc = Escapechar(&ch);
}
if (rc == 1)
return ch;
else
return '\0';
}
/*
* Colorize the chat window
*/
void Showline(int y, int x, char *msg)
{
int i, done = FALSE;
if (strlen(msg)) {
if (msg[0] == '<') {
locate(y, x);
colour(LIGHTCYAN, BLACK);
PUTCHAR('<');
colour(LIGHTBLUE, BLACK);
for (i = 1; i < strlen(msg); i++) {
if ((msg[i] == '>') && (! done)) {
colour(LIGHTCYAN, BLACK);
PUTCHAR(msg[i]);
colour(CYAN, BLACK);
done = TRUE;
} else {
PUTCHAR(msg[i]);
}
}
} else if (msg[0] == '*') {
if (msg[1] == '*') {
if (msg[2] == '*')
mbse_colour(YELLOW, BLACK);
else
colour(LIGHTRED, BLACK);
} else {
colour(LIGHTMAGENTA, BLACK);
}
mvprintw(y, x, msg);
} else {
colour(GREEN, BLACK);
mvprintw(y, x, msg);
}
}
}
/*
* Display received chat message in the chat window.
*/
void DispMsg(char *msg)
{
int i;
/*
* Beep on minor system messages
*/
if ((msg[0] == '*') && (msg[1] != '*'))
putchar('\007');
strncpy(rbuf[rpointer], msg, RBUFLEN);
Showline(2 + rpointer, 1, rbuf[rpointer]);
if (rpointer == rsize) {
/*
* Scroll buffer
*/
for (i = 0; i <= rsize; i++) {
locate(i + 2, 1);
clrtoeol();
snprintf(rbuf[i], RBUFLEN, "%s", rbuf[i+1]);
Showline(i + 2, 1, rbuf[i]);
}
} else {
rpointer++;
}
}
/*
* Clear to End Of Line
*/
void clrtoeol(void)
{
PUTSTR((char *)ANSI_CLREOL);
}
/*
* Chat, if the parameters are not NULL, a connection with the named
* channel is made with the give username which will be forced to the
* used nick name. This mode is used for forced sysop chat.
* If the parameters are NULL, then it's up to the user what happens.
*/
void Chat(char *username, char *channel)
{
int width, curpos = 0, stop = FALSE, data, rc;
unsigned char ch;
char sbuf[81], resp[128], *name, *mname;
static char buf[200];
time_t c_start, c_end;
WhosDoingWhat(SYSOPCHAT, NULL);
clear();
rsize = rows - 5;
rpointer = 0;
if (SYSOP == TRUE) {
/*
* Forbid the sysop to chat, the sysop MUST use mbmon.
*/
Syslog('+', "The Sysop attempted to chat");
pout(LIGHTRED, BLACK, (char *) Language(29));
Enter(1);
Pause();
return;
}
if (username && channel) {
colour(LIGHTGREEN, BLACK);
PUTCHAR('\007');
/* *** Sysop is starting chat *** */
pout(LIGHTGREEN, BLACK, (char *) Language(59));
Enter(1);
sleep(1);
PUTCHAR('\007');
sleep(1);
PUTCHAR('\007');
Syslog('+', "Sysop chat started");
chat_with_sysop = TRUE;
} else {
Syslog('+', "User started chatting");
}
/*
* Setup the screen, this is only possible in ANSI mode.
*/
clear();
locate(1, 1);
colour(WHITE, BLUE);
snprintf(buf, 200, "%-*s", cols, " MBSE BBS Chat Server");
mvprintw(1, 1, buf);
mname = xstrcpy(clencode(exitinfo.sUserName));
name = xstrcpy(clencode(exitinfo.Name));
width = cols - (strlen(name) + 3);
snprintf(buf, 200, "CCON,4,%d,%s,%s,0;", mypid, mname, name);
free(mname);
free(name);
if (socket_send(buf) == 0) {
strncpy(buf, socket_receive(), sizeof(buf)-1);
if (strncmp(buf, "200:1,", 6) == 0) {
Syslog('!', "Chat server is not available");
colour(LIGHTRED, BLACK);
mvprintw(4, 1, (char *) Language(30));
Enter(2);
Pause();
chat_with_sysop = FALSE;
return;
}
}
locate(rows - 2, 1);
colour(WHITE, BLUE);
snprintf(buf, 200, "%-*s", cols, " Type \"/EXIT\" to exit or \"/HELP\" for help.");
mvprintw(rows - 2, 1, buf);
colour(WHITE, BLACK);
mvprintw(rows - 1, 1, ">");
mvprintw(rows - 1, width + 2, "<");
memset(&sbuf, 0, sizeof(sbuf));
memset(&rbuf, 0, sizeof(rbuf));
colour(LIGHTGRAY, BLACK);
/*
* If username and channelname are given, send the /nick and /join
* commands to the chatserver.
*/
if (username && channel) {
snprintf(buf, 200, "CPUT:2,%d,/nick %s;", mypid, clencode(username));
if (socket_send(buf) == 0)
strcpy(buf, socket_receive());
snprintf(buf, 200, "CPUT:2,%d,/join %s;", mypid, clencode(channel));
if (socket_send(buf) == 0)
strcpy(buf, socket_receive());
}
chatting = TRUE;
c_start = time(NULL);
while (stop == FALSE) {
/*
* Check for new message, loop fast until no more data available.
*/
data = TRUE;
while (data) {
snprintf(buf, 200, "CGET:1,%d;", mypid);
if (socket_send(buf) == 0) {
strncpy(buf, socket_receive(), sizeof(buf)-1);
if (strncmp(buf, "100:2,", 6) == 0) {
strncpy(resp, strtok(buf, ":"), 10); /* Should be 100 */
strncpy(resp, strtok(NULL, ","), 5); /* Should be 2 */
strncpy(resp, strtok(NULL, ","), 5); /* 1= fatal, chat ended */
rc = atoi(resp);
memset(&resp, 0, sizeof(resp));
strncpy(resp, cldecode(strtok(NULL, ";")), 80); /* The message */
DispMsg(resp);
if (rc == 1) {
Syslog('+', "Chat server error: %s", resp);
stop = TRUE;
data = FALSE;
}
} else {
data = FALSE;
}
}
}
if (stop)
break;
/*
* Check for a pressed key, if so then process it.
* Allow hi-ascii for multi-language.
*/
ch = testkey(rows -1, curpos + 2);
if ((ch == KEY_BACKSPACE) || (ch == KEY_RUBOUT) || (ch == KEY_DEL)) {
alarm_on();
if (curpos) {
curpos--;
sbuf[curpos] = '\0';
BackErase();
} else {
PUTCHAR(7);
}
/* if KEY_DEL isprint, do no output again */
} else if (isprint(ch) || traduce((char *)&ch)) {
alarm_on();
if (curpos < width) {
PUTCHAR(ch);
sbuf[curpos] = ch;
curpos++;
} else {
PUTCHAR(7);
}
} else if ((ch == '\r') && curpos) {
alarm_on();
snprintf(buf, 200, "CPUT:2,%d,%s;", mypid, clencode(sbuf));
if (socket_send(buf) == 0) {
strcpy(buf, socket_receive());
if (strncmp(buf, "100:2,", 6) == 0) {
strncpy(resp, strtok(buf, ":"), 10); /* Should be 100 */
strncpy(resp, strtok(NULL, ","), 5); /* Should be 2 */
strncpy(resp, strtok(NULL, ","), 5); /* 1= fatal, chat ended */
rc = atoi(resp);
strncpy(resp, cldecode(strtok(NULL, ";")), 80); /* The message */
DispMsg(resp);
if (rc == 1) {
Syslog('+', "Chat server error: %s", resp);
stop = TRUE;
}
}
}
curpos = 0;
memset(&sbuf, 0, sizeof(sbuf));
locate(rows - 1, 2);
clrtoeol();
colour(WHITE, BLACK);
mvprintw(rows - 1, 1, ">");
mvprintw(rows - 1, width + 2, "<");
colour(LIGHTGRAY, BLACK);
}
}
chatting = FALSE;
c_end = time(NULL);
mib_chats++;
mib_chatminutes += (unsigned int) ((c_end - c_start) / 60);
/*
* Before sending the close command, purge all outstanding messages.
*/
data = TRUE;
while (data) {
snprintf(buf, 200, "CGET:1,%d;", mypid);
if (socket_send(buf) == 0) {
strncpy(buf, socket_receive(), sizeof(buf)-1);
if (strncmp(buf, "100:2,", 6) == 0) {
strncpy(resp, strtok(buf, ":"), 10); /* Should be 100 */
strncpy(resp, strtok(NULL, ","), 5); /* Should be 2 */
strncpy(resp, strtok(NULL, ","), 5); /* 1= fatal error */
rc = atoi(resp);
memset(&resp, 0, sizeof(resp));
strncpy(resp, cldecode(strtok(NULL, ";")), 80); /* The message */
DispMsg(resp);
if (rc == 1) {
Syslog('+', "Chat server error: %s", resp);
data = FALSE; /* Even if there is more, prevent a loop */
}
} else {
data = FALSE;
}
}
}
if (username && channel) {
/*
* Disjoin sysop channel
*/
/* *** Sysop has terminated chat *** */
snprintf(buf, 200, "%s", (char *) Language(60));
DispMsg(buf);
Syslog('+', "Sysop chat ended");
chat_with_sysop = FALSE;
} else {
Syslog('+', "User chat ended");
}
/*
* Close server connection
*/
snprintf(buf, 200, "CCLO,1,%d;", mypid);
if (socket_send(buf) == 0) {
strcpy(buf, socket_receive());
}
sleep(2);
clear();
}