2009-05-15 20:01:56 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
|
|
|
* Purpose ...............: mbtask - chat server
|
|
|
|
*
|
|
|
|
*****************************************************************************
|
2011-01-26 22:37:48 +00:00
|
|
|
* Copyright (C) 1997-2011
|
2009-05-15 20:01:56 +00:00
|
|
|
*
|
|
|
|
* 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 "../lib/mbselib.h"
|
|
|
|
#include "taskutil.h"
|
|
|
|
#include "taskregs.h"
|
|
|
|
#include "taskchat.h"
|
|
|
|
#include "taskibc.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define MAXMESSAGES 100 /* Maximum ringbuffer for messages */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The buffers
|
|
|
|
*/
|
|
|
|
_chat_messages chat_messages[MAXMESSAGES];
|
|
|
|
|
|
|
|
|
|
|
|
int buffer_head = 0; /* Messages buffer head */
|
|
|
|
extern struct sysconfig CFG; /* System configuration */
|
|
|
|
extern int s_bbsopen; /* The BBS open status */
|
|
|
|
extern int usrchg;
|
|
|
|
extern int chnchg;
|
|
|
|
extern int srvchg;
|
|
|
|
extern int Run_IBC;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prototypes
|
|
|
|
*/
|
|
|
|
void Chatlog(char *, char *, char *);
|
|
|
|
void chat_dump(void);
|
|
|
|
void system_msg(pid_t, char *);
|
|
|
|
void chat_help(pid_t, int);
|
|
|
|
int join(pid_t, char *, int);
|
|
|
|
int part(pid_t, char*);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Chatlog(char *level, char *channel, char *msg)
|
|
|
|
{
|
|
|
|
char *logm;
|
|
|
|
|
|
|
|
if (CFG.iAutoLog && strlen(CFG.chat_log)) {
|
|
|
|
logm = calloc(PATH_MAX, sizeof(char));
|
|
|
|
snprintf(logm, PATH_MAX, "%s/log/%s", getenv("MBSE_ROOT"), CFG.chat_log);
|
|
|
|
ulog(logm, level, channel, (char *)"-1", msg);
|
|
|
|
free(logm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void chat_dump(void)
|
|
|
|
{
|
|
|
|
int i, first;
|
|
|
|
|
|
|
|
first = TRUE;
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if (usr_list[i].pid) {
|
|
|
|
if (first) {
|
|
|
|
Syslog('c', " pid username nick channel sysop");
|
|
|
|
Syslog('c', "----- ------------------------------------ --------- -------------------- -----");
|
|
|
|
first = FALSE;
|
|
|
|
}
|
|
|
|
Syslog('c', "%5d %-36s %-9s %-20s %s", usr_list[i].pid, usr_list[i].realname, usr_list[i].nick,
|
|
|
|
usr_list[i].channel, usr_list[i].sysop?"True ":"False");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Put a system message into the chatbuffer
|
|
|
|
*/
|
|
|
|
void system_msg(pid_t pid, char *msg)
|
|
|
|
{
|
|
|
|
if (buffer_head < MAXMESSAGES)
|
|
|
|
buffer_head++;
|
|
|
|
else
|
|
|
|
buffer_head = 0;
|
|
|
|
|
|
|
|
memset(&chat_messages[buffer_head], 0, sizeof(_chat_messages));
|
|
|
|
chat_messages[buffer_head].topid = pid;
|
|
|
|
strncpy(chat_messages[buffer_head].fromname, "Server", 36);
|
|
|
|
strncpy(chat_messages[buffer_head].message, msg, 80);
|
|
|
|
chat_messages[buffer_head].posted = time(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Shout a message to all users
|
|
|
|
*/
|
|
|
|
void system_shout(const char *format, ...)
|
|
|
|
{
|
|
|
|
char *buf;
|
|
|
|
va_list va_ptr;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
buf = calloc(512, sizeof(char));
|
|
|
|
va_start(va_ptr, format);
|
|
|
|
vsnprintf(buf, 512, format, va_ptr);
|
|
|
|
va_end(va_ptr);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if (usr_list[i].pid) {
|
|
|
|
system_msg(usr_list[i].pid, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Chatlog((char *)"-", (char *)" ", buf);
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Show help
|
|
|
|
*/
|
|
|
|
void chat_help(pid_t pid, int owner)
|
|
|
|
{
|
|
|
|
system_msg(pid, (char *)" Help topics available:");
|
|
|
|
system_msg(pid, (char *)"");
|
|
|
|
system_msg(pid, (char *)" /BYE - Exit from chatserver");
|
|
|
|
system_msg(pid, (char *)" /ECHO <message> - Echo message to yourself");
|
|
|
|
system_msg(pid, (char *)" /EXIT - Exit from chatserver");
|
|
|
|
system_msg(pid, (char *)" /JOIN #channel - Join or create a channel");
|
|
|
|
system_msg(pid, (char *)" /J #channel - Join or create a channel");
|
|
|
|
// system_msg(pid, (char *)" /KICK <nick> - Kick nick out of the channel");
|
|
|
|
system_msg(pid, (char *)" /LIST - List active channels");
|
|
|
|
system_msg(pid, (char *)" /NAMES - List nicks in current channel");
|
|
|
|
system_msg(pid, (char *)" /NICK <name> - Set new nickname");
|
|
|
|
system_msg(pid, (char *)" /PART - Leave current channel");
|
|
|
|
system_msg(pid, (char *)" /QUIT - Exit from chatserver");
|
|
|
|
if (owner)
|
|
|
|
system_msg(pid, (char *)" /TOPIC <topic> - Set topic for current channel");
|
|
|
|
system_msg(pid, (char *)"");
|
|
|
|
system_msg(pid, (char *)" All other input (without a starting /) is sent to the channel.");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Join a channel
|
|
|
|
*/
|
|
|
|
int join(pid_t pid, char *channel, int sysop)
|
|
|
|
{
|
|
|
|
char buf[81];
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
Syslog('c', "Join pid %d to channel %s", pid, channel);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXIBC_CHN; i++) {
|
|
|
|
if (strcmp(chn_list[i].name, channel) == 0) {
|
|
|
|
for (j = 0; j < MAXIBC_USR; j++) {
|
|
|
|
if (usr_list[j].pid == pid) {
|
|
|
|
|
|
|
|
strncpy(usr_list[j].channel, channel, 20);
|
|
|
|
chn_list[i].users++;
|
|
|
|
Syslog('+', "IBC: user %s has joined channel %s", usr_list[j].nick, channel);
|
|
|
|
usrchg = TRUE;
|
|
|
|
srvchg = TRUE;
|
|
|
|
chnchg = TRUE;
|
|
|
|
|
|
|
|
chat_dump();
|
|
|
|
snprintf(buf, 81, "%s has joined channel %s, now %d users", usr_list[j].nick, channel, chn_list[i].users);
|
|
|
|
chat_msg(channel, NULL, buf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The sysop channel is private to the system, no broadcast
|
|
|
|
*/
|
|
|
|
if (strcasecmp(channel, "#sysop"))
|
|
|
|
send_at((char *)"JOIN", usr_list[j].nick, channel);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A new channel must be created, but only the sysop may create the "sysop" channel
|
|
|
|
*/
|
|
|
|
if (!sysop && (strcasecmp(channel, "#sysop") == 0)) {
|
|
|
|
snprintf(buf, 81, "*** Only the sysop may create channel \"%s\"", channel);
|
|
|
|
system_msg(pid, buf);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No matching channel found, add a new channel.
|
|
|
|
*/
|
|
|
|
for (j = 0; j < MAXIBC_USR; j++) {
|
|
|
|
if (usr_list[j].pid == pid) {
|
|
|
|
if (add_channel(channel, usr_list[j].nick, CFG.myfqdn) == 0) {
|
|
|
|
|
|
|
|
strncpy(usr_list[j].channel, channel, 20);
|
|
|
|
Syslog('+', "IBC: user %s created and joined channel %s", usr_list[j].nick, channel);
|
|
|
|
usrchg = TRUE;
|
|
|
|
chnchg = TRUE;
|
|
|
|
srvchg = TRUE;
|
|
|
|
|
|
|
|
snprintf(buf, 81, "* Created channel %s", channel);
|
|
|
|
chat_msg(channel, NULL, buf);
|
|
|
|
chat_dump();
|
|
|
|
if (strcasecmp(channel, "#sysop"))
|
|
|
|
send_at((char *)"JOIN", usr_list[j].nick, channel);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No matching or free channels
|
|
|
|
*/
|
|
|
|
snprintf(buf, 81, "*** Cannot create chat channel %s, no free channels", channel);
|
|
|
|
system_msg(pid, buf);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Part from a channel
|
|
|
|
*/
|
|
|
|
int part(pid_t pid, char *reason)
|
|
|
|
{
|
|
|
|
char buf[81], *p;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
if (strlen(reason) > 54)
|
|
|
|
reason[54] = '\0';
|
|
|
|
|
|
|
|
Syslog('c', "Part pid %d from channel, reason %s", pid, reason);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if ((usr_list[i].pid == pid) && strlen(usr_list[i].channel)) {
|
|
|
|
for (j = 0; j < MAXIBC_CHN; j++) {
|
|
|
|
if (strcmp(chn_list[j].name, usr_list[i].channel) == 0) {
|
|
|
|
/*
|
|
|
|
* Inform other users
|
|
|
|
*/
|
|
|
|
if (reason != NULL) {
|
|
|
|
chat_msg(usr_list[i].channel, usr_list[i].nick, reason);
|
|
|
|
}
|
|
|
|
snprintf(buf, 81, "%s has left channel %s, %d users left",
|
|
|
|
usr_list[i].nick, chn_list[j].name, chn_list[j].users -1);
|
|
|
|
chat_msg(usr_list[i].channel, NULL, buf);
|
|
|
|
if (strcasecmp(chn_list[j].name, (char *)"#sysop")) {
|
|
|
|
p = xstrcpy(chn_list[j].name);
|
|
|
|
if (reason && strlen(reason)) {
|
|
|
|
p = xstrcat(p, (char *)" ");
|
|
|
|
p = xstrcat(p, reason);
|
|
|
|
}
|
|
|
|
send_at((char *)"PART", usr_list[i].nick, p);
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clean channel
|
|
|
|
*/
|
|
|
|
if (chn_list[j].users > 0)
|
|
|
|
chn_list[j].users--;
|
|
|
|
Syslog('+', "IBC: nick %s leaves channel %s, %d user left",
|
|
|
|
usr_list[i].nick, chn_list[j].name, chn_list[j].users);
|
|
|
|
if (chn_list[j].users == 0) {
|
|
|
|
/*
|
|
|
|
* Last user in channel, remove channel
|
|
|
|
*/
|
|
|
|
snprintf(buf, 81, "* Removed channel %s", chn_list[j].name);
|
|
|
|
system_msg(pid, buf);
|
|
|
|
Syslog('+', "IBC: removed channel %s, no more users left", chn_list[j].name);
|
|
|
|
del_channel(chn_list[j].name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update user data
|
|
|
|
*/
|
|
|
|
usr_list[i].channel[0] = '\0';
|
|
|
|
usrchg = TRUE;
|
|
|
|
chnchg = TRUE;
|
|
|
|
srvchg = TRUE;
|
|
|
|
|
|
|
|
chat_dump();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void chat_init(void)
|
|
|
|
{
|
|
|
|
memset(&chat_messages, 0, sizeof(chat_messages));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void chat_cleanuser(pid_t pid)
|
|
|
|
{
|
|
|
|
part(pid, (char *)"I'm hanging up!");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send message into channel
|
|
|
|
*/
|
|
|
|
void chat_msg(char *channel, char *nick, char *msg)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (nick == NULL)
|
|
|
|
p = xstrcpy(msg);
|
|
|
|
else {
|
|
|
|
p = xstrcpy((char *)"<");
|
|
|
|
p = xstrcat(p, nick);
|
|
|
|
p = xstrcat(p, (char *)"> ");
|
|
|
|
p = xstrcat(p, msg);
|
|
|
|
}
|
|
|
|
Chatlog((char *)"+", channel, p);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if (strlen(usr_list[i].channel) && (strcmp(usr_list[i].channel, channel) == 0)) {
|
|
|
|
system_msg(usr_list[i].pid, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Connect a session to the chatserver.
|
|
|
|
*/
|
|
|
|
void chat_connect_r(char *data, char *buf)
|
|
|
|
{
|
|
|
|
char *realname, *nick, *temp;
|
|
|
|
int i, j, rc, count = 0, sys = FALSE;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
Syslog('c', "CCON:%s", data);
|
|
|
|
|
|
|
|
if (! Run_IBC) {
|
|
|
|
snprintf(buf, 200, "100:1,*** Chatserver not configured;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsSema((char *)"upsalarm")) {
|
|
|
|
snprintf(buf, 200, "100:1,*** Power failure, running on UPS;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s_bbsopen == FALSE) {
|
|
|
|
snprintf(buf, 200, "100:1,*** The BBS is closed now;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Register with IBC
|
|
|
|
*/
|
|
|
|
strtok(data, ","); /* Should be 3 */
|
|
|
|
pid = (pid_t)atoi(strtok(NULL, ",")); /* The pid */
|
|
|
|
realname = xstrcpy(cldecode(strtok(NULL, ",")));/* Username */
|
|
|
|
nick = xstrcpy(cldecode(strtok(NULL, ","))); /* Nickname */
|
|
|
|
sys = atoi(strtok(NULL, ";")); /* Sysop flag */
|
|
|
|
|
|
|
|
rc = add_user(CFG.myfqdn, nick, realname);
|
|
|
|
if (rc == 1) {
|
|
|
|
free(realname);
|
|
|
|
free(nick);
|
|
|
|
snprintf(buf, 200, "100:1,Already registered;");
|
|
|
|
return;
|
|
|
|
} else if (rc == 2) {
|
|
|
|
free(realname);
|
|
|
|
free(nick);
|
|
|
|
snprintf(buf, 200, "100:1,Too many users connected;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
send_at((char *)"USER", nick, realname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now search the added entry to update the data
|
|
|
|
*/
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if ((strcmp(usr_list[i].server, CFG.myfqdn) == 0) &&
|
|
|
|
(strcmp(usr_list[i].name, nick) == 0) && (strcmp(usr_list[i].realname, realname) == 0)) {
|
|
|
|
/*
|
|
|
|
* Oke, found
|
|
|
|
*/
|
|
|
|
usr_list[i].pid = pid;
|
|
|
|
usr_list[i].pointer = buffer_head;
|
|
|
|
usr_list[i].sysop = sys;
|
|
|
|
usrchg = TRUE;
|
|
|
|
srvchg = TRUE;
|
|
|
|
Syslog('c', "Connected user %s (%d) with chatserver, sysop %s", realname, (int)pid, sys ? "True":"False");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now put welcome message into the ringbuffer and report success.
|
|
|
|
*/
|
|
|
|
temp = calloc(81, sizeof(char));
|
2011-01-26 22:37:48 +00:00
|
|
|
snprintf(temp, 80, "MBSE BBS v%s chat server; type /help for help", VERSION);
|
2009-05-15 20:01:56 +00:00
|
|
|
system_msg(usr_list[i].pid, temp);
|
2011-01-26 22:37:48 +00:00
|
|
|
snprintf(temp, 80, "Welcome to the Internet BBS Chat Network");
|
2009-05-15 20:01:56 +00:00
|
|
|
system_msg(usr_list[i].pid, temp);
|
2011-01-26 22:37:48 +00:00
|
|
|
snprintf(temp, 80, "Current connected servers:");
|
2009-05-15 20:01:56 +00:00
|
|
|
system_msg(usr_list[i].pid, temp);
|
|
|
|
for (j = 0; j < MAXIBC_SRV; j++) {
|
|
|
|
if (strlen(srv_list[j].server)) {
|
2011-01-26 22:37:48 +00:00
|
|
|
snprintf(temp, 80, " %d user%s at '%s'",
|
2009-05-15 20:01:56 +00:00
|
|
|
srv_list[j].users, (srv_list[j].users == 1) ? " ":"s", srv_list[j].fullname);
|
|
|
|
system_msg(usr_list[i].pid, temp);
|
|
|
|
count += srv_list[j].users;
|
|
|
|
}
|
|
|
|
}
|
2011-01-26 22:37:48 +00:00
|
|
|
snprintf(temp, 80, "There %s %d user%s connected", (count != 1)?"are":"is", count, (count != 1)?"s":"");
|
2009-05-15 20:01:56 +00:00
|
|
|
system_msg(usr_list[i].pid, temp);
|
2011-01-26 22:37:48 +00:00
|
|
|
snprintf(buf, 80, "100:0;");
|
2009-05-15 20:01:56 +00:00
|
|
|
free(realname);
|
|
|
|
free(nick);
|
|
|
|
free(temp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void chat_close_r(char *data, char *buf)
|
|
|
|
{
|
|
|
|
pid_t pid;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
Syslog('c', "CCLO:%s", data);
|
|
|
|
strtok(data, ",");
|
|
|
|
pid = (pid_t)atoi(strtok(NULL, ";"));
|
|
|
|
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if (usr_list[i].pid == pid) {
|
|
|
|
/*
|
|
|
|
* Remove from IBC network
|
|
|
|
*/
|
|
|
|
send_at((char *)"QUIT", usr_list[i].name, (char *)"Leaving chat");
|
|
|
|
del_user(CFG.myfqdn, usr_list[i].name);
|
|
|
|
Syslog('c', "Closing chat for pid %d", (int)pid);
|
|
|
|
snprintf(buf, 81, "100:0;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Syslog('c', "Pid %d was not connected to chatserver", (int)pid);
|
|
|
|
snprintf(buf, 81, "100:1,*** ERROR - Not connected to server;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void chat_put_r(char *data, char *buf)
|
|
|
|
{
|
|
|
|
char *p, *q, *msg, *cmd, *mbuf, *flags, temp[81];
|
|
|
|
int i, j, k, first, count, owner = FALSE, found;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
if (IsSema((char *)"upsalarm")) {
|
|
|
|
snprintf(buf, 81, "100:2,1,*** Power alarm, running on UPS;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s_bbsopen == FALSE) {
|
|
|
|
snprintf(buf, 81, "100:2,1,*** The BBS is closed now;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
strtok(data, ",");
|
|
|
|
pid = (pid_t)atoi(strtok(NULL, ","));
|
|
|
|
msg = xstrcpy(cldecode(strtok(NULL, ";")));
|
|
|
|
mbuf = calloc(200, sizeof(char));
|
|
|
|
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if (usr_list[i].pid == pid) {
|
|
|
|
if (msg[0] == '/') {
|
|
|
|
/*
|
|
|
|
* A command, process this but first see if we are in a channel
|
|
|
|
* and own the channel. This gives us more power.
|
|
|
|
*/
|
|
|
|
if (strlen(usr_list[i].channel)) {
|
|
|
|
for (j = 0; j < MAXIBC_CHN; j++) {
|
|
|
|
if (((strcmp(usr_list[i].nick, chn_list[j].owner) == 0) ||
|
|
|
|
(strcmp(usr_list[i].name, chn_list[j].owner) == 0)) &&
|
|
|
|
(strcmp(usr_list[i].server, chn_list[j].server) == 0)) {
|
|
|
|
owner = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (strncasecmp(msg, "/help", 5) == 0) {
|
|
|
|
chat_help(pid, owner);
|
|
|
|
goto ack;
|
|
|
|
} else if (strncasecmp(msg, "/echo", 5) == 0) {
|
|
|
|
snprintf(mbuf, 200, "%s", msg);
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
goto ack;
|
|
|
|
} else if ((strncasecmp(msg, "/exit", 5) == 0) ||
|
|
|
|
(strncasecmp(msg, "/quit", 5) == 0) ||
|
|
|
|
(strncasecmp(msg, "/bye", 4) == 0)) {
|
|
|
|
if (strlen(usr_list[i].channel)) {
|
|
|
|
/*
|
|
|
|
* If in a channel, leave channel first
|
|
|
|
*/
|
|
|
|
part(usr_list[i].pid, (char *)"Quitting");
|
|
|
|
snprintf(mbuf, 81, "Goodbye");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
}
|
|
|
|
goto hangup;
|
|
|
|
} else if ((strncasecmp(msg, "/join", 5) == 0) ||
|
|
|
|
(strncasecmp(msg, "/j ", 3) == 0)) {
|
|
|
|
cmd = strtok(msg, " \0");
|
|
|
|
cmd = strtok(NULL, "\0");
|
|
|
|
if ((cmd == NULL) || (cmd[0] != '#') || (strcmp(cmd, "#") == 0)) {
|
|
|
|
snprintf(mbuf, 200, "** Try /join #channel");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
} else if (strlen(usr_list[i].channel)) {
|
|
|
|
snprintf(mbuf, 200, "** Cannot join while in a channel");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
} else {
|
|
|
|
join(usr_list[i].pid, cmd, usr_list[i].sysop);
|
|
|
|
}
|
|
|
|
chat_dump();
|
|
|
|
goto ack;
|
|
|
|
} else if (strncasecmp(msg, "/list", 5) == 0) {
|
|
|
|
first = TRUE;
|
|
|
|
for (j = 0; j < MAXIBC_CHN; j++) {
|
|
|
|
if (strlen(chn_list[j].server)) {
|
|
|
|
if (first) {
|
|
|
|
snprintf(mbuf, 200, "Cnt Channel name Channel topic");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
snprintf(mbuf, 200, "--- -------------------- ------------------------------------------------------");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
}
|
|
|
|
first = FALSE;
|
|
|
|
q = calloc(81, sizeof(char));
|
|
|
|
snprintf(q, 81, "%3d %-20s ", chn_list[j].users, chn_list[j].name);
|
|
|
|
p = xstrcpy(q);
|
|
|
|
p = xstrcat(p, chn_list[j].topic);
|
|
|
|
system_msg(usr_list[i].pid, p);
|
|
|
|
free(p);
|
|
|
|
free(q);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (first) {
|
|
|
|
snprintf(mbuf, 200, "No active channels to list");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
}
|
|
|
|
goto ack;
|
|
|
|
} else if (strncasecmp(msg, "/names", 6) == 0) {
|
|
|
|
if (strlen(usr_list[i].channel)) {
|
|
|
|
snprintf(mbuf, 200, "Present in channel %s:", usr_list[i].channel);
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
snprintf(mbuf, 200, "Nick Real name Flags");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
snprintf(mbuf, 200, "---------------------------------------- ------------------------------ -----");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
count = 0;
|
|
|
|
for (j = 0; j < MAXIBC_USR; j++) {
|
|
|
|
if (strcmp(usr_list[j].channel, usr_list[i].channel) == 0) {
|
|
|
|
/*
|
|
|
|
* Get channel flags
|
|
|
|
*/
|
|
|
|
flags = xstrcpy((char *)"--");
|
|
|
|
for (k = 0; k < MAXIBC_CHN; k++) {
|
|
|
|
if (strcmp(chn_list[k].name, usr_list[i].channel) == 0) {
|
|
|
|
if (((strcmp(chn_list[k].owner, usr_list[j].nick) == 0) ||
|
|
|
|
(strcmp(chn_list[k].owner, usr_list[j].name) == 0)) &&
|
|
|
|
(strcmp(chn_list[k].server, usr_list[j].server) == 0)) {
|
|
|
|
flags[0] = 'O';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (usr_list[j].sysop)
|
|
|
|
flags[1] = 'S';
|
|
|
|
|
|
|
|
snprintf(temp, 81, "%s@%s", usr_list[j].nick, usr_list[j].server);
|
|
|
|
snprintf(mbuf, 200, "%-40s %-30s %s", temp, usr_list[j].realname, flags);
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
count++;
|
|
|
|
free(flags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
snprintf(mbuf, 200, "%d user%s in this channel", count, (count == 1) ?"":"s");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
} else {
|
|
|
|
snprintf(mbuf, 200, "** Not in a channel");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
}
|
|
|
|
goto ack;
|
|
|
|
} else if (strncasecmp(msg, "/nick", 5) == 0) {
|
|
|
|
cmd = strtok(msg, " \0");
|
|
|
|
cmd = strtok(NULL, "\0");
|
|
|
|
if ((cmd == NULL) || (strlen(cmd) == 0) || (strlen(cmd) > 9)) {
|
|
|
|
snprintf(mbuf, 200, "** Nickname must be between 1 and 9 characters");
|
|
|
|
} else {
|
|
|
|
found = FALSE;
|
|
|
|
for (j = 0; j < MAXIBC_USR; j++) {
|
|
|
|
if ((strcmp(usr_list[j].name, cmd) == 0) || (strcmp(usr_list[j].nick, cmd) == 0)) {
|
|
|
|
found = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found ) {
|
|
|
|
strncpy(usr_list[i].nick, cmd, 9);
|
|
|
|
snprintf(mbuf, 200, "Nick set to \"%s\"", cmd);
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
send_nick(usr_list[i].nick, usr_list[i].name, usr_list[i].realname);
|
|
|
|
usrchg = TRUE;
|
|
|
|
chat_dump();
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
snprintf(mbuf, 200, "Can't set nick");
|
|
|
|
}
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
chat_dump();
|
|
|
|
goto ack;
|
|
|
|
} else if (strncasecmp(msg, "/part", 5) == 0) {
|
|
|
|
cmd = strtok(msg, " \0");
|
|
|
|
Syslog('c', "\"%s\"", cmd);
|
|
|
|
cmd = strtok(NULL, "\0");
|
|
|
|
Syslog('c', "\"%s\"", printable(cmd, 0));
|
|
|
|
if (part(usr_list[i].pid, cmd ? cmd : (char *)"Quitting") == FALSE) {
|
|
|
|
snprintf(mbuf, 200, "** Not in a channel");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
}
|
|
|
|
chat_dump();
|
|
|
|
goto ack;
|
|
|
|
} else if (strncasecmp(msg, "/topic", 6) == 0) {
|
|
|
|
if (strlen(usr_list[i].channel)) {
|
|
|
|
snprintf(mbuf, 200, "** Internal system error");
|
|
|
|
for (j = 0; j < MAXIBC_CHN; j++) {
|
|
|
|
if (strcmp(usr_list[i].channel, chn_list[j].name) == 0) {
|
|
|
|
if (owner) {
|
|
|
|
cmd = strtok(msg, " \0");
|
|
|
|
cmd = strtok(NULL, "\0");
|
|
|
|
if ((cmd == NULL) || (strlen(cmd) == 0) || (strlen(cmd) > 54)) {
|
|
|
|
snprintf(mbuf, 200, "** Topic must be between 1 and 54 characters");
|
|
|
|
} else {
|
|
|
|
strncpy(chn_list[j].topic, cmd, 54);
|
|
|
|
snprintf(mbuf, 200, "Topic set to \"%s\"", cmd);
|
|
|
|
p = xstrcpy((char *)"TOPIC ");
|
|
|
|
p = xstrcat(p, chn_list[j].name);
|
|
|
|
p = xstrcat(p, (char *)" ");
|
|
|
|
p = xstrcat(p, chn_list[j].topic);
|
|
|
|
p = xstrcat(p, (char *)"\r\n");
|
|
|
|
send_all(p);
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snprintf(mbuf, 200, "** You are not the channel owner");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snprintf(mbuf, 200, "** Not in a channel");
|
|
|
|
}
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
chat_dump();
|
|
|
|
goto ack;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If still here, the command was not recognized.
|
|
|
|
*/
|
|
|
|
cmd = strtok(msg, " \t\r\n\0");
|
|
|
|
snprintf(mbuf, 200, "*** \"%s\" :Unknown command", cmd+1);
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (strlen(usr_list[i].channel) == 0) {
|
|
|
|
/*
|
|
|
|
* Trying messages while not in a channel
|
|
|
|
*/
|
|
|
|
snprintf(mbuf, 200, "** No channel joined. Try /join #channel");
|
|
|
|
system_msg(usr_list[i].pid, mbuf);
|
|
|
|
goto ack;
|
|
|
|
} else {
|
|
|
|
chat_msg(usr_list[i].channel, usr_list[i].nick, msg);
|
|
|
|
/*
|
|
|
|
* Send message to all links but not the #sysop channel
|
|
|
|
*/
|
|
|
|
if (strcmp(usr_list[i].channel, "#sysop")) {
|
|
|
|
p = xstrcpy((char *)"PRIVMSG ");
|
|
|
|
p = xstrcat(p, usr_list[i].channel);
|
|
|
|
p = xstrcat(p, (char *)" <");
|
|
|
|
p = xstrcat(p, usr_list[i].nick);
|
|
|
|
p = xstrcat(p, (char *)"> ");
|
|
|
|
p = xstrcat(p, msg);
|
|
|
|
p = xstrcat(p, (char *)"\r\n");
|
|
|
|
send_all(p);
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Syslog('+', "Pid %s was not connected to chatserver", pid);
|
|
|
|
snprintf(buf, 200, "100:2,1,*** ERROR - Not connected to server;");
|
|
|
|
free(msg);
|
|
|
|
free(mbuf);
|
|
|
|
return;
|
|
|
|
|
|
|
|
ack:
|
|
|
|
snprintf(buf, 200, "100:0;");
|
|
|
|
free(msg);
|
|
|
|
free(mbuf);
|
|
|
|
return;
|
|
|
|
|
|
|
|
hangup:
|
|
|
|
snprintf(buf, 200, "100:2,1,Disconnecting;");
|
|
|
|
free(msg);
|
|
|
|
free(mbuf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for a message for the user. Return the message or signal that
|
|
|
|
* nothing is there to display.
|
|
|
|
*/
|
|
|
|
void chat_get_r(char *data, char *buf)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
pid_t pid;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (IsSema((char *)"upsalarm")) {
|
|
|
|
snprintf(buf, 200, "100:2,1,*** Power failure, running on UPS;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s_bbsopen == FALSE) {
|
|
|
|
snprintf(buf, 200, "100:2,1,*** The BBS is closed now;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
strtok(data, ",");
|
|
|
|
pid = (pid_t)atoi(strtok(NULL, ";"));
|
|
|
|
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if (pid == usr_list[i].pid) {
|
|
|
|
while (usr_list[i].pointer != buffer_head) {
|
|
|
|
if (usr_list[i].pointer < MAXMESSAGES)
|
|
|
|
usr_list[i].pointer++;
|
|
|
|
else
|
|
|
|
usr_list[i].pointer = 0;
|
|
|
|
if (usr_list[i].pid == chat_messages[usr_list[i].pointer].topid) {
|
|
|
|
/*
|
|
|
|
* Message is for us
|
|
|
|
*/
|
|
|
|
p = xstrcpy((char *)"100:2,0,");
|
|
|
|
p = xstrcat(p, clencode(chat_messages[usr_list[i].pointer].message));
|
|
|
|
p = xstrcat(p, (char *)";");
|
|
|
|
strncpy(buf, p, 200);
|
|
|
|
free(p);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
snprintf(buf, 200, "100:0;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
snprintf(buf, 200, "100:2,1,*** ERROR - Not connected to server;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for sysop present for forced chat
|
|
|
|
*/
|
|
|
|
void chat_checksysop_r(char *data, char *buf)
|
|
|
|
{
|
|
|
|
pid_t pid;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
strtok(data, ",");
|
|
|
|
pid = (pid_t)atoi(strtok(NULL, ";"));
|
|
|
|
|
|
|
|
if (reg_ispaging(pid)) {
|
|
|
|
Syslog('c', "Check sysopchat for pid %d, user has paged", pid);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now check if sysop is present in the sysop channel
|
|
|
|
*/
|
|
|
|
for (i = 0; i < MAXIBC_USR; i++) {
|
|
|
|
if (pid != usr_list[i].pid) {
|
|
|
|
if (strlen(usr_list[i].channel) && (strcasecmp(usr_list[i].channel, "#sysop") == 0) && usr_list[i].sysop) {
|
|
|
|
Syslog('c', "Sending ACK on check");
|
|
|
|
snprintf(buf, 20, "100:1,1;");
|
|
|
|
reg_sysoptalk(pid);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, 20, "100:1,0;");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|