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/mbtask/taskchat.c
2003-03-24 19:44:38 +00:00

338 lines
8.7 KiB
C

/*****************************************************************************
*
* $Id$
* Purpose ...............: mbtask - chat server
*
*****************************************************************************
* Copyright (C) 1997-2003
*
* 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, 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************/
#include "../config.h"
#include "libs.h"
#include "../lib/structs.h"
#include "taskutil.h"
#include "taskregs.h"
#include "taskchat.h"
#define MAXCHANNELS 100 /* Maximum chat channels */
#define MAXMESSAGES 100 /* Maximum ringbuffer for messages */
typedef enum {CH_FREE, CH_PRIVATE, CH_PUBLIC} CHANNELTYPE;
/*
* Users connected to the chatserver.
*/
typedef struct _ch_user_rec {
pid_t pid; /* User's pid */
char name[36]; /* His name used (may become nick) */
time_t connected; /* Time connected */
int channel; /* Connected channel or -1 */
int pointer; /* Message pointer */
unsigned chatting : 1; /* Is chatting in a channel */
unsigned chanop : 1; /* Is a chanop */
} _chat_users;
/*
* Buffer for messages, this is the structure of a ringbuffer which will
* hold all messages, private public etc. There is one global input pointer
* which points to the current head of the ringbuffer. When a user connects
* to a channel, he will get the latest messages in the channel if they
* are present.
*/
typedef struct _chatmsg {
pid_t topid; /* Destination pid of message */
char fromname[36]; /* Message from user */
char message[81]; /* The message to display */
time_t posted; /* Timestamp for posted message */
} _chat_messages;
/*
* List of banned users from a channel. This is a dynamic list.
*/
typedef struct _banned {
int channel; /* Channel the user is banned from */
char user[36]; /* The user who is banned */
} banned_users;
/*
* The buffers
*/
_chat_messages chat_messages[MAXMESSAGES];
_chat_users chat_users[MAXCLIENT];
int buffer_head = 0; /* Messages buffer head */
extern struct sysconfig CFG; /* System configuration */
/*
* Put a system message into the chatbuffer
*/
void system_msg(pid_t, char *);
void system_msg(pid_t pid, char *msg)
{
if (buffer_head < MAXMESSAGES)
buffer_head++;
else
buffer_head = 0;
Syslog('-', "system_msg(%d, %s) ptr=%d", pid, msg, buffer_head);
memset(&chat_messages[buffer_head], 0, sizeof(_chat_messages));
chat_messages[buffer_head].topid = pid;
sprintf(chat_messages[buffer_head].fromname, "Server");
strncpy(chat_messages[buffer_head].message, msg, 80);
chat_messages[buffer_head].posted = time(NULL);
}
/*
* Show help
*/
void chat_help(pid_t);
void chat_help(pid_t pid)
{
system_msg(pid, (char *)"Topics available:");
system_msg(pid, (char *)"");
system_msg(pid, (char *)" EXIT HELP");
}
void chat_init(void)
{
memset(&chat_users, 0, sizeof(chat_users));
memset(&chat_messages, 0, sizeof(chat_messages));
}
/*
* Connect a session to the chatserver.
*/
char *chat_connect(char *data)
{
char *pid, *usr;
static char buf[200];
int i, j, count = 0;
Syslog('-', "CCON:%s", data);
memset(&buf, 0, sizeof(buf));
/*
* Search free userslot
*/
for (i = 0; i < MAXCLIENT; i++) {
if (chat_users[i].pid == 0) {
/*
* Oke, found
*/
pid = strtok(data, ","); /* Should be 2 */
pid = strtok(NULL, ","); /* The pid */
usr = strtok(NULL, ";"); /* Username */
chat_users[i].pid = atoi(pid);
strncpy(chat_users[i].name, usr, 36);
chat_users[i].connected = time(NULL);
chat_users[i].pointer = buffer_head;
chat_users[i].channel = -1;
Syslog('-', "Connected user %s (%s) with chatserver, slot %d", usr, pid, i);
/*
* Now put welcome message into the ringbuffer and report success.
*/
sprintf(buf, "MBSE BBS v%s chat server; type /help for help", VERSION);
system_msg(chat_users[i].pid, buf);
sprintf(buf, "Welcome to the %s chat network", CFG.bbs_name);
system_msg(chat_users[i].pid, buf);
for (j = 0; j < MAXCLIENT; j++)
if (chat_users[j].pid)
count++;
sprintf(buf, "There %s %d user%s connected", (count != 1)?"are":"is", count, (count != 1)?"s":"");
system_msg(chat_users[i].pid, buf);
sprintf(buf, "100:0;");
return buf;
}
}
sprintf(buf, "100:1,Too many users connected;");
return buf;
}
char *chat_close(char *data)
{
static char buf[200];
char *pid;
int i;
Syslog('-', "CCLO:%s", data);
memset(&buf, 0, sizeof(buf));
pid = strtok(data, ",");
pid = strtok(NULL, ";");
for (i = 0; i < MAXCLIENT; i++) {
if (chat_users[i].pid == atoi(pid)) {
Syslog('-', "Closing chat for pid %s, slot %d", pid, i);
memset(&chat_users[i], 0, sizeof(_chat_users));
sprintf(buf, "100:0;");
return buf;
}
}
Syslog('-', "Pid %s was not connected to chatserver");
sprintf(buf, "100:1,ERROR - Not connected to server;");
return buf;
}
char *chat_put(char *data)
{
static char buf[200];
char *pid, *msg, *cmd;
int i;
Syslog('-', "CPUT:%s", data);
memset(&buf, 0, sizeof(buf));
pid = strtok(data, ",");
pid = strtok(NULL, ",");
msg = strtok(NULL, "\0");
msg[strlen(msg)-1] = '\0';
for (i = 0; i < MAXCLIENT; i++) {
if (chat_users[i].pid == atoi(pid)) {
/*
* We are connected and known, first send the input back to ourself.
*/
system_msg(chat_users[i].pid, msg);
if (msg[0] == '/') {
/*
* A command, process this
*/
if (strncasecmp(msg, "/help", 5) == 0) {
chat_help(atoi(pid));
sprintf(buf, "100:0;");
return buf;
}
if (strncasecmp(msg, "/exit", 5) == 0) {
/*
* Just send messages, the client should later do a
* real disconnect.
*/
sprintf(buf, "Goodbye");
system_msg(chat_users[i].pid, buf);
sprintf(buf, "100:0;");
return buf;
}
if (strncasecmp(msg, "/join", 5) == 0) {
cmd = strtok(msg, " \0");
Syslog('-', "\"%s\"", cmd);
cmd = strtok(NULL, "\0");
Syslog('-', "\"%s\"", cmd);
if ((cmd == NULL) || (cmd[0] != '#') || (strcmp(cmd, "#") == 0)) {
sprintf(buf, "Try /join #channel");
system_msg(chat_users[i].pid, buf);
} else {
Syslog('-', "Trying to join channel %s", cmd);
}
sprintf(buf, "100:0;");
return buf;
}
/*
* If still here, the command was not recognized.
*/
cmd = strtok(msg, " \t\r\n\0");
sprintf(buf, "%s :Unknown command", cmd+1);
system_msg(chat_users[i].pid, buf);
sprintf(buf, "100:0;");
return buf;
}
if (chat_users[i].channel == -1) {
/*
* Trying messages while not in a channel
*/
sprintf(buf, "No channel joined. Try /join #channel");
system_msg(chat_users[i].pid, buf);
sprintf(buf, "100:0;");
return buf;
}
sprintf(buf, "100:0;");
return buf;
}
}
Syslog('-', "Pid %s was not connected to chatserver");
sprintf(buf, "100:1,ERROR - Not connected to server;");
return buf;
}
char *chat_get(char *data)
{
static char buf[200];
char *pid;
int i;
Syslog('-', "CGET:%s", data);
memset(&buf, 0, sizeof(buf));
pid = strtok(data, ",");
pid = strtok(NULL, ";");
for (i = 0; i < MAXCLIENT; i++) {
if (atoi(pid) == chat_users[i].pid) {
while (chat_users[i].pointer != buffer_head) {
if (chat_users[i].pointer < MAXMESSAGES)
chat_users[i].pointer++;
else
chat_users[i].pointer = 0;
if (chat_users[i].pid == chat_messages[chat_users[i].pointer].topid) {
/*
* Message is for us.
*/
sprintf(buf, "100:1,%s;", chat_messages[chat_users[i].pointer].message);
Syslog('-', "%s", buf);
return buf;
}
}
sprintf(buf, "100:0;");
return buf;
}
}
sprintf(buf, "100:1,ERROR - Not connected to server;");
return buf;
}