/*
* comsys.c
*/
/*
* $Id: comsys.c,v 1.6 2005/08/08 09:43:05 murrayma Exp $
*/
#include <ctype.h>
#include <sys/types.h>
#include "copyright.h"
#include "config.h"
#include "db.h"
#include "interface.h"
#include "attrs.h"
#include "match.h"
#include "config.h"
#include "externs.h"
#include "flags.h"
#include "powers.h"
#include "comsys.h"
#include "p.comsys.h"
#include "p.functions.h"
#include "create.h"
/* Static functions */
static void do_save_com(chmsg *);
static void do_show_com(chmsg *);
static void do_comlast(dbref, struct channel *);
static void do_comsend(struct channel *, char *);
static void do_joinchannel(dbref, struct channel *);
static void do_leavechannel(dbref, struct channel *);
static void do_comwho(dbref, struct channel *);
static void do_setnewtitle(dbref, struct channel *, char *);
static void sort_users(struct channel *);
static int do_test_access(dbref, long, struct channel *);
/*
* This is the hash table for channel names
*/
void init_chantab(void) {
hashinit(&mudstate.channel_htab, 30 * HASH_FACTOR);
}
void send_channel(char *chan, const char *format, ...) {
struct channel *ch;
char buf[LBUF_SIZE];
char data[LBUF_SIZE];
char *newline;
va_list ap;
if (!(ch = select_channel(chan)))
return;
va_start(ap, format);
vsnprintf(data, LBUF_SIZE, format, ap);
va_end(ap);
snprintf(buf, LBUF_SIZE, "[%s] %s", chan, data);
while ((newline = strchr(buf, '\n')))
*newline = ' ';
do_comsend(ch, buf);
}
char *get_channel_from_alias(dbref player, char *alias) {
struct commac *c;
int first, last, current = 0;
int dir;
c = get_commac(player);
first = 0;
last = c->numchannels - 1;
dir = 1;
while (dir && (first <= last)) {
current = (first + last) / 2;
dir = strcasecmp(alias, c->alias + 6 * current);
if (dir < 0)
last = current - 1;
else
first = current + 1;
}
if (!dir)
return c->channels[current];
else
return "";
}
void load_comsystem(FILE * fp) {
int i, j, k, dummy;
int nc, new = 0;
struct channel *ch;
struct comuser *user;
char temp[LBUF_SIZE];
char buf[8];
num_channels = 0;
fgets(buf, sizeof(buf), fp);
if (!strncmp(buf, "+V2", 3)) {
new = 2;
fscanf(fp, "%d\n", &nc);
} else if (!strncmp(buf, "+V1", 3)) {
new = 1;
fscanf(fp, "%d\n", &nc);
} else
nc = atoi(buf);
num_channels = nc;
for (i = 0; i < nc; i++) {
ch = (struct channel *) malloc(sizeof(struct channel));
fscanf(fp, "%[^\n]\n", temp);
strncpy(ch->name, temp, CHAN_NAME_LEN);
ch->name[CHAN_NAME_LEN-1] = '\0';
ch->on_users = NULL;
hashadd(ch->name, (int *) ch, &mudstate.channel_htab);
#ifdef CHANNEL_HISTORY
ch->last_messages = NULL;
#endif
if (new) { /* V1 or higher */
if (fscanf(fp,
new ==
1 ? "%d %d %d %d %d %d %d %d\n" :
"%d %d %d %d %d %d %d %d %d\n", &(ch->type),
&(ch->temp1), &(ch->temp2), &(ch->charge),
&(ch->charge_who), &(ch->amount_col),
&(ch->num_messages), &(ch->chan_obj), &dummy) >= 9 &&
new > 1) {
/* Do things with 'dummy' */
if (dummy > 0) {
for (j = 0; j < dummy; j++) {
#ifdef CHANNEL_HISTORY
chmsg *c;
#endif
fscanf(fp, "%d %[^\n]\n", &k, temp);
#ifdef CHANNEL_HISTORY
Create(c, chmsg, 1);
c->msg = strdup(temp);
c->time = k;
myfifo_push(&ch->last_messages, c);
#endif
}
}
}
} else {
fscanf(fp, "%d %d %d %d %d %d %d %d %d %d\n", &(ch->type),
&(dummy), &(ch->temp1), &(ch->temp2), &(dummy),
&(ch->charge), &(ch->charge_who), &(ch->amount_col),
&(ch->num_messages), &(ch->chan_obj));
}
fscanf(fp, "%d\n", &(ch->num_users));
ch->max_users = ch->num_users;
if (ch->num_users > 0) {
ch->users = (struct comuser **)
calloc(ch->max_users, sizeof(struct comuser *));
for (j = 0; j < ch->num_users; j++) {
user = (struct comuser *) malloc(sizeof(struct comuser));
ch->users[j] = user;
if (new) {
fscanf(fp, "%d %d\n", &(user->who), &(user->on));
} else {
fscanf(fp, "%d %d %d", &(user->who), &(dummy),
&(dummy));
fscanf(fp, "%d\n", &(user->on));
}
fscanf(fp, "%[^\n]\n", temp);
user->title = strdup(temp + 2);
if (!(isPlayer(user->who)) && !(Going(user->who) &&
(God(Owner(user->who))))) {
do_joinchannel(user->who, ch);
user->on_next = ch->on_users;
ch->on_users = user;
} else {
user->on_next = ch->on_users;
ch->on_users = user;
}
}
sort_users(ch);
} else
ch->users = NULL;
}
}
static FILE *temp_file;
static void do_save_com(chmsg * d) {
fprintf(temp_file, "%d %s\n", (int) d->time, d->msg);
}
void save_comsystem(FILE * fp) {
struct channel *ch;
struct comuser *user;
int j, k, player_users;
fprintf(fp, "+V2\n");
fprintf(fp, "%d\n", num_channels);
for (ch = (struct channel *) hash_firstentry(&mudstate.channel_htab);
ch;
ch = (struct channel *) hash_nextentry(&mudstate.channel_htab)) {
fprintf(fp, "%s\n", ch->name);
k = myfifo_length(&ch->last_messages);
/* 1 2 3 4 5 6 7 8 9 */
fprintf(fp, "%d %d %d %d %d %d %d %d %d\n", ch->type, ch->temp1,
ch->temp2, ch->charge, ch->charge_who, ch->amount_col,
ch->num_messages, ch->chan_obj, k);
if (k) {
temp_file = fp;
myfifo_trav_r(&ch->last_messages, do_save_com);
}
player_users = 0;
for (j = 0; j < ch->num_users; j++)
if (isPlayer(ch->users[j]->who) || isRobot(ch->users[j]->who))
player_users++;
fprintf(fp, "%d\n", player_users);
for (j = 0; j < ch->num_users; j++) {
user = ch->users[j];
if (!isPlayer(user->who) && !isRobot(user->who))
continue;
fprintf(fp, "%d %d\n", user->who, user->on);
if (strlen(user->title))
fprintf(fp, "t:%s\n", user->title);
else
fprintf(fp, "t:\n");
}
}
}
static dbref cheat_player;
static void do_show_com(chmsg * d) {
struct tm *t;
int day;
char buf[LBUF_SIZE];
t = localtime(&mudstate.now);
day = t->tm_mday;
t = localtime(&d->time);
if (day == t->tm_mday) {
sprintf(buf, "[%02d:%02d] %s", t->tm_hour, t->tm_min, d->msg);
} else
sprintf(buf, "[%02d.%02d / %02d:%02d] %s", t->tm_mon + 1,
t->tm_mday, t->tm_hour, t->tm_min, d->msg);
notify(cheat_player, buf);
}
static void do_comlast(dbref player, struct channel *ch) {
#ifdef CHANNEL_HISTORY
if (!myfifo_length(&ch->last_messages)) {
notify_printf(player, "There haven't been any messages on %s.",
ch->name);
return;
}
cheat_player = player;
myfifo_trav_r(&ch->last_messages, do_show_com);
#endif
}
void do_processcom(dbref player, char *arg1, char *arg2) {
char mess[LBUF_SIZE];
struct channel *ch;
struct comuser *user;
if ((strlen(arg1) + strlen(arg2)) > LBUF_SIZE / 2) {
arg2[LBUF_SIZE / 2 - strlen(arg1)] = '\0';
}
if (!*arg2) {
raw_notify(player, "No message.");
return;
}
if (!Wizard(player) && In_IC_Loc(player)) {
raw_notify(player, "Permission denied.");
return;
}
if (!(ch = select_channel(arg1))) {
notify_printf(player, "Unknown channel %s.", arg1);
return;
}
if (!(user = select_user(ch, player))) {
raw_notify(player,
"You are not listed as on that channel. Delete this alias and re-add.");
return;
}
if (!strcasecmp(arg2, "on")) {
do_joinchannel(player, ch);
} else if (!strcasecmp(arg2, "off")) {
do_leavechannel(player, ch);
} else if (!user->on && !Wizard(player) && !mudconf.allow_chanlurking) {
notify_printf(player, "You must be on %s to do that.", arg1);
return;
} else if (!strcasecmp(arg2, "who")) {
do_comwho(player, ch);
} else if (!strcasecmp(arg2, "last")) {
do_comlast(player, ch);
} else if (!user->on) {
notify_printf(player, "You must be on %s to do that.", arg1);
return;
} else if (!do_test_access(player, CHANNEL_TRANSMIT, ch)) {
raw_notify(player, "That channel type cannot be transmitted on.");
return;
} else {
if (!payfor(player, Guest(player) ? 0 : ch->charge)) {
notify_printf(player, "You don't have enough %s.", mudconf.many_coins);
return;
} else {
ch->amount_col += ch->charge;
giveto(ch->charge_who, ch->charge);
}
if ((*arg2) == ':')
snprintf(mess, LBUF_SIZE, "[%s] %s %s", arg1, Name(player),
arg2 + 1);
else if ((*arg2) == ';')
snprintf(mess, LBUF_SIZE, "[%s] %s%s", arg1, Name(player),
arg2 + 1);
else if (strlen(user->title))
snprintf(mess, LBUF_SIZE, "[%s] %s: <%s> %s", arg1,
Name(player), user->title, arg2);
else
snprintf(mess, LBUF_SIZE, "[%s] %s: %s", arg1, Name(player),
arg2);
do_comsend(ch, mess);
}
}
static void do_comsend(struct channel *ch, char *mess) {
struct comuser *user;
chmsg *c;
ch->num_messages++;
for (user = ch->on_users; user; user = user->on_next) {
if (user->on && do_test_access(user->who, CHANNEL_RECIEVE, ch) &&
(Wizard(user->who) || !In_IC_Loc(user->who))) {
if (Typeof(user->who) == TYPE_PLAYER && Connected(user->who))
raw_notify(user->who, mess);
else
notify(user->who, mess);
}
}
/* Also, add it to the history of channel */
#ifdef CHANNEL_HISTORY
if (myfifo_length(&ch->last_messages) >= CHANNEL_HISTORY_LEN) {
c = myfifo_pop(&ch->last_messages);
free((void *) c->msg);
} else
Create(c, chmsg, 1);
c->msg = strdup(mess);
c->time = mudstate.now;
myfifo_push(&ch->last_messages, c);
#endif
}
static void do_joinchannel(dbref player, struct channel *ch) {
struct comuser *user;
int i;
user = select_user(ch, player);
if (!user) {
ch->num_users++;
if (ch->num_users >= ch->max_users) {
ch->max_users += 10;
ch->users = realloc(ch->users, sizeof(struct comuser *) *
ch->max_users);
}
user = (struct comuser *) malloc(sizeof(struct comuser));
for (i = ch->num_users - 1;
i > 0 && ch->users[i - 1]->who > player; i--)
ch->users[i] = ch->users[i - 1];
ch->users[i] = user;
user->who = player;
user->on = 1;
user->title = strdup("");
if UNDEAD(player) {
user->on_next = ch->on_users;
ch->on_users = user;
}
} else if (!user->on) {
user->on = 1;
} else {
notify_printf(player, "You are already on channel %s.",
ch->name);
return;
}
if (!Dark(player)) {
do_comsend(ch, tprintf("[%s] %s has joined this channel.",
ch->name, Name(player)));
}
}
static void do_leavechannel(dbref player, struct channel *ch) {
struct comuser *user;
user = select_user(ch, player);
if (!user)
return;
notify_printf(player, "You have left channel %s.", ch->name);
if ((user->on) && (!Dark(player))) {
char *c = Name(player);
if (c && *c) {
do_comsend(ch, tprintf("[%s] %s has left this channel.",
ch->name, c));
}
}
user->on = 0;
}
static void do_comwho(dbref player, struct channel *ch) {
struct comuser *user;
char *buff;
raw_notify(player, "-- Players --");
for (user = ch->on_users; user; user = user->on_next) {
if (Typeof(user->who) == TYPE_PLAYER && user->on &&
Connected(user->who) && (!Hidden(user->who) ||
((ch->type & CHANNEL_TRANSPARENT) && !Dark(user->who)) ||
Wizard_Who(player))
&& (!In_IC_Loc(user->who) || Wizard(user->who))) {
int i = fetch_idle(user->who);
buff = unparse_object(player, user->who, 0);
if (i > 30) {
char *c = get_uptime_to_string(i);
notify_printf(player, "%s [idle %s]", buff, c);
free_sbuf(c);
} else
notify_printf(player, "%s", buff);
free_lbuf(buff);
}
}
raw_notify(player, "-- Objects --");
for (user = ch->on_users; user; user = user->on_next) {
if (Typeof(user->who) != TYPE_PLAYER && user->on &&
!(Going(user->who) && God(Owner(user->who)))) {
buff = unparse_object(player, user->who, 0);
notify_printf(player, "%s", buff);
free_lbuf(buff);
}
}
notify_printf(player, "-- %s --", ch->name);
}
struct channel *select_channel(char *channel) {
return (struct channel *) hashfind(channel, &mudstate.channel_htab);
}
struct comuser *select_user(struct channel *ch, dbref player) {
int last, current;
int dir = 1, first = 0;
if (!ch)
return NULL;
last = ch->num_users - 1;
current = (first + last) / 2;
while (dir && (first <= last)) {
current = (first + last) / 2;
if (ch->users[current] == NULL) {
last--;
continue;
}
if (ch->users[current]->who == player)
dir = 0;
else if (ch->users[current]->who < player) {
dir = 1;
first = current + 1;
} else {
dir = -1;
last = current - 1;
}
}
if (!dir)
return ch->users[current];
else
return NULL;
}
void do_addcom(dbref player, dbref cause, int key, char *arg1, char *arg2) {
char channel[200];
char title[100];
struct channel *ch;
char *s;
int where;
struct commac *c;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
if (!*arg1) {
raw_notify(player, "You need to specify an alias.");
return;
}
if (!*arg2) {
raw_notify(player, "You need to specify a channel.");
return;
}
s = strchr(arg2, ',');
if (s) {
/* channelname,title */
if (s >= arg2 + 200) {
raw_notify(player, "Channel name too long.");
return;
}
strncpy(channel, arg2, s - arg2);
channel[s - arg2] = '\0';
strncpy(title, s + 1, 100);
title[99] = '\0';
} else {
/* just channelname */
if (strlen(arg2) >= 200) {
raw_notify(player, "Channel name too long.");
return;
}
strcpy(channel, arg2);
title[0] = '\0';
}
if (strchr(channel, ' ')) {
raw_notify(player, "Channel name cannot contain spaces.");
return;
}
if (!(ch = select_channel(channel))) {
notify_printf(player, "Channel %s does not exist yet.", channel);
return;
}
if (!do_test_access(player, CHANNEL_JOIN, ch)) {
raw_notify(player,
"Sorry, this channel type does not allow you to join.");
return;
}
if (select_user(ch, player)) {
raw_notify(player,
"Warning: you are already listed on that channel.");
}
c = get_commac(player);
for (where = 0; where < c->numchannels &&
(strcasecmp(arg1, c->alias + where * 6) > 0); where++);
if (where < c->numchannels && !strcasecmp(arg1, c->alias + where * 6)) {
notify_printf(player, "That alias is already in use for channel %s.",
c->channels[where]);
return;
}
if (c->numchannels >= c->maxchannels) {
c->maxchannels += 10;
c->alias = realloc(c->alias, sizeof(char) * 6 * c->maxchannels);
c->channels =
realloc(c->channels, sizeof(char *) * c->maxchannels);
}
if (where < c->numchannels) {
memmove(c->alias + 6 * (where + 1), c->alias + 6 * where,
6 * (c->numchannels - where));
memmove(c->channels + where + 1, c->channels + where,
sizeof(c->channels) * (c->numchannels - where));
}
c->numchannels++;
strncpy(c->alias + 6 * where, arg1, 5);
c->alias[where * 6 + 5] = '\0';
c->channels[where] = strdup(channel);
do_joinchannel(player, ch);
do_setnewtitle(player, ch, title);
if (title[0])
notify_printf(player, "Channel %s added with alias %s and title %s.",
channel, arg1, title);
else
notify_printf(player, "Channel %s added with alias %s.",
channel, arg1);
}
static void do_setnewtitle(dbref player, struct channel *ch, char *title) {
struct comuser *user;
char *new;
user = select_user(ch, player);
/* Make sure there can be no embedded newlines from %r */
if (!ch || !user)
return;
new = replace_string("\r\n", "", title);
if (user->title)
free(user->title);
user->title = strdup(new); /* strdup so we can free() safely */
free_lbuf(new);
}
void do_delcom(dbref player, dbref cause, int key, char *arg1) {
int i;
struct commac *c;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
if (!arg1) {
raw_notify(player, "Need an alias to delete.");
return;
}
c = get_commac(player);
for (i = 0; i < c->numchannels; i++) {
if (!strcasecmp(arg1, c->alias + i * 6)) {
do_delcomchannel(player, c->channels[i]);
notify_printf(player, "Channel %s deleted.",
c->channels[i]);
free(c->channels[i]);
c->numchannels--;
if (i < c->numchannels) {
memmove(c->alias + 6 * i, c->alias + 6 * (i + 1),
6 * (c->numchannels - i));
memmove(c->channels + i, c->channels + i + 1,
sizeof(c->channels) * (c->numchannels - i));
}
return;
}
}
raw_notify(player, "Unable to find that alias.");
}
void do_delcomchannel(dbref player, char *channel) {
struct channel *ch;
struct comuser *user;
int i;
if (!(ch = select_channel(channel))) {
notify_printf(player, "Unknown channel %s.", channel);
} else {
for (i = 0; i < ch->num_users; i++) {
user = ch->users[i];
if (user->who == player) {
do_comdisconnectchannel(player, channel);
if (user->on && !Dark(player)) {
char *c = Name(player);
if (c && *c)
do_comsend(ch,
tprintf("[%s] %s has left this channel.",
channel, c));
}
notify_printf(player, "You have left channel %s.", channel);
if (user->title)
free(user->title);
free(user);
ch->num_users--;
if (i < ch->num_users)
memmove(ch->users + i, ch->users + i + 1,
sizeof(ch->users) * (ch->num_users - i));
}
}
}
}
void do_createchannel(dbref player, dbref cause, int key, char *channel) {
struct channel *newchannel;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
if (select_channel(channel)) {
notify_printf(player, "Channel %s already exists.", channel);
return;
}
if (!*channel) {
raw_notify(player, "You must specify a channel to create.");
return;
}
if (!(Comm_All(player))) {
raw_notify(player, "You do not have permission to do that.");
return;
}
newchannel = (struct channel *) malloc(sizeof(struct channel));
strncpy(newchannel->name, channel, CHAN_NAME_LEN - 1);
newchannel->name[CHAN_NAME_LEN - 1] = '\0';
#ifdef CHANNEL_HISTORY
newchannel->last_messages = NULL;
#endif
newchannel->type = 127;
newchannel->temp1 = 0;
newchannel->temp2 = 0;
newchannel->charge = 0;
newchannel->charge_who = player;
newchannel->amount_col = 0;
newchannel->num_users = 0;
newchannel->max_users = 0;
newchannel->users = NULL;
newchannel->on_users = NULL;
newchannel->chan_obj = NOTHING;
newchannel->num_messages = 0;
num_channels++;
hashadd(newchannel->name, (int *) newchannel, &mudstate.channel_htab);
notify_printf(player, "Channel %s created.", channel);
}
void do_destroychannel(dbref player, dbref cause, int key, char *channel) {
struct channel *ch;
int j;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
ch = (struct channel *) hashfind(channel, &mudstate.channel_htab);
if (!ch) {
notify_printf(player, "Could not find channel %s.", channel);
return;
} else if (!(Comm_All(player)) && (player != ch->charge_who)) {
raw_notify(player, "You do not have permission to do that. ");
return;
}
num_channels--;
hashdelete(channel, &mudstate.channel_htab);
for (j = 0; j < ch->num_users; j++) {
free(ch->users[j]);
}
free(ch->users);
free(ch);
notify_printf(player, "Channel %s destroyed.", channel);
}
void do_listchannels(dbref player) {
struct channel *ch;
int perm;
if (!(perm = Comm_All(player))) {
raw_notify(player,
"Warning: Only public channels and your channels will be shown.");
}
raw_notify(player,
"** Channel --Flags-- Obj Own Charge Balance Users Messages");
for (ch = (struct channel *) hash_firstentry(&mudstate.channel_htab);
ch; ch = (struct channel *) hash_nextentry(&mudstate.channel_htab))
if (perm || (ch->type & CHANNEL_PUBLIC)
|| ch->charge_who == player) {
notify_printf(player,
"%c%c %-20.20s %c%c%c/%c%c%c %5d %5d %8d %8d %6d %10d",
(ch->type & (CHANNEL_PUBLIC)) ? 'P' : '-',
(ch->type & (CHANNEL_LOUD)) ? 'L' : '-', ch->name,
(ch->type & (CHANNEL_PL_MULT *
CHANNEL_JOIN)) ? 'J' : '-',
(ch->type & (CHANNEL_PL_MULT *
CHANNEL_TRANSMIT)) ? 'X' : '-',
(ch->type & (CHANNEL_PL_MULT *
CHANNEL_RECIEVE)) ? 'R' : '-',
(ch->type & (CHANNEL_OBJ_MULT *
CHANNEL_JOIN)) ? 'j' : '-',
(ch->type & (CHANNEL_OBJ_MULT *
CHANNEL_TRANSMIT)) ? 'x' : '-',
(ch->type & (CHANNEL_OBJ_MULT *
CHANNEL_RECIEVE)) ? 'r' : '-',
(ch->chan_obj != NOTHING) ? ch->chan_obj : -1,
ch->charge_who, ch->charge, ch->amount_col,
ch->num_users, ch->num_messages);
}
raw_notify(player, "-- End of list of Channels --");
}
void do_comtitle(dbref player, dbref cause, int key, char *arg1, char *arg2) {
struct channel *ch;
char channel[100];
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
if (!*arg1) {
raw_notify(player, "Need an alias to do comtitle.");
return;
}
strncpy(channel, get_channel_from_alias(player, arg1), 100);
channel[99] = '\0';
if (!*channel) {
raw_notify(player, "Unknown alias");
return;
}
if ((ch = select_channel(channel)) && select_user(ch, player)) {
notify_printf(player, "Title set to '%s' on channel %s.",
arg2, channel);
do_setnewtitle(player, ch, arg2);
}
if (!ch) {
raw_notify(player, "Invalid comsys alias, please delete.");
return;
}
}
void do_comlist(dbref player, dbref cause, int key) {
struct comuser *user;
struct commac *c;
int i;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
c = get_commac(player);
raw_notify(player,
"Alias Channel Title Status");
for (i = 0; i < c->numchannels; i++) {
if ((user = select_user(select_channel(c->channels[i]), player))) {
notify_printf(player, "%-9.9s %-19.19s %-39.39s %s",
c->alias + i * 6, c->channels[i],
user->title, (user->on ? "on" : "off"));
} else {
notify_printf(player, "Bad Comsys Alias: %s for Channel: %s",
c->alias + i * 6, c->channels[i]);
}
}
raw_notify(player, "-- End of comlist --");
}
void do_channelnuke(dbref player) {
struct channel *ch;
int j;
for (ch = (struct channel *) hash_firstentry(&mudstate.channel_htab);
ch;
ch = (struct channel *) hash_nextentry(&mudstate.channel_htab)) {
if (ch->charge_who == player) {
num_channels--;
hashdelete(ch->name, &mudstate.channel_htab);
for (j = 0; j < ch->num_users; j++)
free(ch->users[j]);
free(ch->users);
free(ch);
}
}
}
void do_clearcom(dbref player, dbref cause, int key) {
int i;
struct commac *c;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
c = get_commac(player);
for (i = (c->numchannels) - 1; i > -1; --i) {
do_delcom(player, player, 0, c->alias + i * 6);
}
}
void do_allcom(dbref player, dbref cause, int key, char *arg1) {
int i;
struct commac *c;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
c = get_commac(player);
if ((strcasecmp(arg1, "who") != 0) && (strcasecmp(arg1, "on") != 0) &&
(strcasecmp(arg1, "off") != 0)) {
raw_notify(player, "Only options available are: on, off and who.");
return;
}
for (i = 0; i < c->numchannels; i++) {
do_processcom(player, c->channels[i], arg1);
if (strcasecmp(arg1, "who") == 0)
raw_notify(player, "");
}
}
static void sort_users(struct channel *ch) {
int i;
int nu;
int done;
struct comuser *user;
nu = ch->num_users;
done = 0;
while (!done) {
done = 1;
for (i = 0; i < (nu - 1); i++) {
if (ch->users[i]->who > ch->users[i + 1]->who) {
user = ch->users[i];
ch->users[i] = ch->users[i + 1];
ch->users[i + 1] = user;
done = 0;
}
}
}
}
void do_channelwho(dbref player, dbref cause, int key, char *arg1) {
struct channel *ch;
struct comuser *user;
char channel[100];
int flag = 0;
char *cp;
int i;
char ansibuffer[LBUF_SIZE];
char outputbuffer[LBUF_SIZE];
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
cp = strchr(arg1, '/');
if (!cp) {
strncpy(channel, arg1, 100);
channel[99] = '\0';
} else {
/* channelname/all */
if (cp - arg1 >= 100) {
raw_notify(player, "Channel name too long.");
return;
}
strncpy(channel, arg1, cp - arg1);
channel[cp - arg1] = '\0';
if (*++cp == 'a')
flag = 1;
}
if (!(ch = select_channel(channel))) {
notify_printf(player, "Unknown channel \"%s\".", channel);
return;
}
if (!((Comm_All(player)) || (player == ch->charge_who))) {
raw_notify(player, "You do not have permission to do that.");
return;
}
notify_printf(player, "-- %s --", ch->name);
notify_printf(player, "%-29.29s %-6.6s %-6.6s", "Name", "Status", "Player");
for (i = 0; i < ch->num_users; i++) {
user = ch->users[i];
if ((flag || UNDEAD(user->who)) && (!Hidden(user->who) ||
((ch->type & CHANNEL_TRANSPARENT) && !Dark(user->who)) ||
Wizard_Who(player))) {
cp = unparse_object(player, user->who, 0);
strip_ansi_r(ansibuffer, cp, LBUF_SIZE);
notify_printf(player, "%-29.29s %-6.6s %-6.6s", ansibuffer,
((user->on) ? "on " : "off"),
(Typeof(user->who) == TYPE_PLAYER) ? "yes" : "no ");
free_lbuf(cp);
}
}
notify_printf(player, "-- %s --", ch->name);
}
void do_comdisconnectraw_notify(dbref player, char *chan) {
struct channel *ch;
struct comuser *cu;
if (!(ch = select_channel(chan)))
return;
if (!(cu = select_user(ch, player)))
return;
if ((ch->type & CHANNEL_LOUD) && (cu->on) && (!Dark(player))) {
do_comsend(ch, tprintf("[%s] %s has disconnected.",
ch->name, Name(player)));
}
}
void do_comconnectraw_notify(dbref player, char *chan) {
struct channel *ch;
struct comuser *cu;
if (!(ch = select_channel(chan)))
return;
if (!(cu = select_user(ch, player)))
return;
if ((ch->type & CHANNEL_LOUD) && (cu->on) && (!Dark(player))) {
do_comsend(ch, tprintf("[%s] %s has connected.",
ch->name, Name(player)));
}
}
void do_comconnectchannel(dbref player, char *channel, char *alias, int i) {
struct channel *ch;
struct comuser *user;
if ((ch = select_channel(channel))) {
for (user = ch->on_users; user && user->who != player;
user = user->on_next);
if (!user) {
if ((user = select_user(ch, player))) {
user->on_next = ch->on_users;
ch->on_users = user;
} else
notify_printf(player,"Bad Comsys Alias: %s for Channel: %s",
alias + i * 6, channel);
}
} else
notify_printf(player, "Bad Comsys Alias: %s for Channel: %s",
alias + i * 6, channel);
}
void do_comdisconnect(dbref player) {
int i;
struct commac *c;
c = get_commac(player);
for (i = 0; i < c->numchannels; i++) {
do_comdisconnectchannel(player, c->channels[i]);
#ifdef CHANNEL_LOUD
do_comdisconnectraw_notify(player, c->channels[i]);
#endif
}
send_channel("MUXConnections", tprintf("* %s has disconnected *",
Name(player)));
}
void do_comconnect(dbref player, DESC * d) {
struct commac *c;
int i;
char *lsite;
c = get_commac(player);
for (i = 0; i < c->numchannels; i++) {
do_comconnectchannel(player, c->channels[i], c->alias, i);
do_comconnectraw_notify(player, c->channels[i]);
}
lsite = d->addr;
if (lsite && *lsite)
send_channel("MUXConnections",
tprintf("* %s has connected from %s *", Name(player), lsite));
else
send_channel("MUXConnections",
tprintf("* %s has connected from somewhere *", Name(player)));
}
void do_comdisconnectchannel(dbref player, char *channel) {
struct comuser *user, *prevuser = NULL;
struct channel *ch;
if (!(ch = select_channel(channel)))
return;
for (user = ch->on_users; user;) {
if (user->who == player) {
if (prevuser)
prevuser->on_next = user->on_next;
else
ch->on_users = user->on_next;
return;
} else {
prevuser = user;
user = user->on_next;
}
}
}
void do_editchannel(dbref player, dbref cause, int flag, char *arg1, char *arg2) {
char *s;
struct channel *ch;
int add_remove = 1;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
if (!(ch = select_channel(arg1))) {
notify_printf(player, "Unknown channel %s.", arg1);
return;
}
if (!((Comm_All(player)) || (player == ch->charge_who))) {
raw_notify(player, "Permission denied.");
return;
}
s = arg2;
if (*s == '!') {
add_remove = 0;
s++;
}
switch (flag) {
case 0:
if (lookup_player(player, arg2, 1) != NOTHING) {
ch->charge_who = lookup_player(player, arg2, 1);
raw_notify(player, "Set.");
return;
} else {
raw_notify(player, "Invalid player.");
return;
}
case 1:
ch->charge = atoi(arg2);
raw_notify(player, "Set.");
return;
case 3:
if (strcasecmp(s, "join") == 0) {
add_remove ? (ch->type |=
(CHANNEL_PL_MULT * CHANNEL_JOIN)) : (ch->type &=
~(CHANNEL_PL_MULT * CHANNEL_JOIN));
raw_notify(player,
(add_remove) ? "@cpflags: Set." : "@cpflags: Cleared.");
return;
}
if (strcasecmp(s, "receive") == 0) {
add_remove ? (ch->type |=
(CHANNEL_PL_MULT * CHANNEL_RECIEVE)) : (ch->type &=
~(CHANNEL_PL_MULT * CHANNEL_RECIEVE));
raw_notify(player,
(add_remove) ? "@cpflags: Set." : "@cpflags: Cleared.");
return;
}
if (strcasecmp(s, "transmit") == 0) {
add_remove ? (ch->type |=
(CHANNEL_PL_MULT * CHANNEL_TRANSMIT)) : (ch->type &=
~(CHANNEL_PL_MULT * CHANNEL_TRANSMIT));
raw_notify(player,
(add_remove) ? "@cpflags: Set." : "@cpflags: Cleared.");
return;
}
raw_notify(player, "@cpflags: Unknown Flag.");
break;
case 4:
if (strcasecmp(s, "join") == 0) {
add_remove ? (ch->type |=
(CHANNEL_OBJ_MULT * CHANNEL_JOIN)) : (ch->type &=
~(CHANNEL_OBJ_MULT * CHANNEL_JOIN));
raw_notify(player,
(add_remove) ? "@coflags: Set." : "@coflags: Cleared.");
return;
}
if (strcasecmp(s, "receive") == 0) {
add_remove ? (ch->type |=
(CHANNEL_OBJ_MULT * CHANNEL_RECIEVE)) : (ch->type &=
~(CHANNEL_OBJ_MULT * CHANNEL_RECIEVE));
raw_notify(player,
(add_remove) ? "@coflags: Set." : "@coflags: Cleared.");
return;
}
if (strcasecmp(s, "transmit") == 0) {
add_remove ? (ch->type |=
(CHANNEL_OBJ_MULT * CHANNEL_TRANSMIT)) : (ch->type &=
~(CHANNEL_OBJ_MULT * CHANNEL_TRANSMIT));
raw_notify(player,
(add_remove) ? "@coflags: Set." : "@coflags: Cleared.");
return;
}
raw_notify(player, "@coflags: Unknown Flag.");
break;
}
return;
}
static int do_test_access(dbref player, long access, struct channel *chan) {
long flag_value = access;
if (Comm_All(player))
return (1);
/*
* Channel objects allow custom locks for channels. The normal
* lock is used to see if they can join that channel. The
* enterlock is checked to see if they can receive messages on
* it. The Uselock is checked to see if they can transmit on
* it. Note: These checks do not supercede the normal channel
* flags. If a channel is set JOIN for players, ALL players can
* join the channel, whether or not they pass the lock. Same for
* all channel object locks.
*/
if ((flag_value & CHANNEL_JOIN) && !((chan->chan_obj == NOTHING) ||
(chan->chan_obj == 0))) {
if (could_doit(player, chan->chan_obj, A_LOCK))
return (1);
}
if ((flag_value & CHANNEL_TRANSMIT) && !((chan->chan_obj == NOTHING) ||
(chan->chan_obj == 0))) {
if (could_doit(player, chan->chan_obj, A_LUSE))
return (1);
}
if ((flag_value & CHANNEL_RECIEVE) && !((chan->chan_obj == NOTHING) ||
(chan->chan_obj == 0))) {
if (could_doit(player, chan->chan_obj, A_LENTER))
return (1);
}
if (Typeof(player) == TYPE_PLAYER)
flag_value *= CHANNEL_PL_MULT;
else
flag_value *= CHANNEL_OBJ_MULT;
flag_value &= 0xFF; /*
* Mask out CHANNEL_PUBLIC and CHANNEL_LOUD
* just to be paranoid.
*/
return (((long) chan->type & flag_value));
}
int do_comsystem(dbref who, char *cmd) {
char *t;
char *ch;
char *alias;
char *s;
alias = alloc_lbuf("do_comsystem");
s = alias;
for (t = cmd; *t && *t != ' '; *s++ = *t++)
/* nothing */ ;
*s = '\0';
if (*t)
t++;
ch = get_channel_from_alias(who, alias);
if (ch && *ch) {
do_processcom(who, ch, t);
free_lbuf(alias);
return 0;
}
free_lbuf(alias);
return 1;
}
void do_chclose(dbref player, char *chan) {
struct channel *ch;
if (!(ch = select_channel(chan))) {
notify_printf(player, "@cset: Channel %s does not exist.", chan);
return;
}
if ((player != ch->charge_who) && (!Comm_All(player))) {
raw_notify(player, "@cset: Permission denied.");
return;
}
ch->type &= (~(CHANNEL_PUBLIC));
notify_printf(player,
"@cset: Channel %s taken off the public listings.", chan);
return;
}
void do_cemit(dbref player, dbref cause, int key, char *chan, char *text) {
struct channel *ch;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
if (!(ch = select_channel(chan))) {
notify_printf(player, "Channel %s does not exist.", chan);
return;
}
if ((player != ch->charge_who) && (!Comm_All(player))) {
raw_notify(player, "Permission denied.");
return;
}
if (key == CEMIT_NOHEADER)
do_comsend(ch, text);
else
do_comsend(ch, tprintf("[%s] %s", chan, text));
}
void do_chopen(dbref player, dbref cause, int key, char *chan, char *object) {
struct channel *ch;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
switch (key) {
case CSET_PRIVATE:
do_chclose(player, chan);
return;
case CSET_LOUD:
do_chloud(player, chan);
return;
case CSET_QUIET:
do_chsquelch(player, chan);
return;
case CSET_LIST:
do_chanlist(player, NOTHING, 1);
return;
case CSET_OBJECT:
do_chanobj(player, chan, object);
return;
case CSET_STATUS:
do_chanstatus(player, NOTHING, 1, chan);
return;
case CSET_TRANSPARENT:
do_chtransparent(player, chan);
return;
case CSET_OPAQUE:
do_chopaque(player, chan);
return;
}
if (!(ch = select_channel(chan))) {
notify_printf(player, "@cset: Channel %s does not exist.",
chan);
return;
}
if ((player != ch->charge_who) && (!Comm_All(player))) {
raw_notify(player, "@cset: Permission denied.");
return;
}
ch->type |= (CHANNEL_PUBLIC);
notify_printf(player, "@cset: Channel %s placed on the public listings.",
chan);
return;
}
void do_chloud(dbref player, char *chan) {
struct channel *ch;
if (!(ch = select_channel(chan))) {
notify_printf(player, "@cset: Channel %s does not exist.",
chan);
return;
}
if ((player != ch->charge_who) && (!Comm_All(player))) {
raw_notify(player, "@cset: Permission denied.");
return;
}
ch->type |= (CHANNEL_LOUD);
notify_printf(player,
"@cset: Channel %s now sends connect/disconnect msgs.",
chan);
return;
}
void do_chsquelch(dbref player, char *chan) {
struct channel *ch;
if (!(ch = select_channel(chan))) {
notify_printf(player, "@cset: Channel %s does not exist.",
chan);
return;
}
if ((player != ch->charge_who) && (!Comm_All(player))) {
raw_notify(player, "@cset: Permission denied.");
return;
}
ch->type &= ~(CHANNEL_LOUD);
notify_printf(player,
"@cset: Channel %s connect/disconnect msgs muted.", chan);
return;
}
void do_chtransparent(dbref player, char *chan) {
struct channel *ch;
if (!(ch = select_channel(chan))) {
notify_printf(player, "@cset: Channel %s does not exist.",
chan);
return;
}
if ((player != ch->charge_who) && (!Comm_All(player))) {
raw_notify(player, "@cset: Permission denied.");
return;
}
ch->type |= CHANNEL_TRANSPARENT;
notify_printf(player,
"@cset: Channel %s now shows all listeners to everyone.",
chan);
return;
}
void do_chopaque(dbref player, char *chan) {
struct channel *ch;
if (!(ch = select_channel(chan))) {
notify_printf(player, "@cset: Channel %s does not exist.",
chan);
return;
}
if ((player != ch->charge_who) && (!Comm_All(player))) {
raw_notify(player, "@cset: Permission denied.");
return;
}
ch->type &= ~CHANNEL_TRANSPARENT;
notify_printf(player,
"@cset: Channel %s now does not show all listeners to everyone.",
chan);
return;
}
void do_chboot(dbref player, dbref cause, int key, char *channel, char *victim) {
struct comuser *user;
struct channel *ch;
struct comuser *vu;
dbref thing;
/*
* * I sure hope it's not going to be that *
* * * * * * * * long.
*/
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
if (!(ch = select_channel(channel))) {
raw_notify(player, "@cboot: Unknown channel.");
return;
}
if (!(user = select_user(ch, player))) {
raw_notify(player, "@cboot: You are not on that channel.");
return;
}
if (!((ch->charge_who == player) || Comm_All(player))) {
raw_notify(player, "Permission denied.");
return;
}
thing = match_thing(player, victim);
if (thing == NOTHING) {
return;
}
if (!(vu = select_user(ch, thing))) {
notify_printf(player, "@cboot: %s in not on the channel.",
Name(thing));
return;
}
/*
* We should be in the clear now. :)
*/
do_comsend(ch, tprintf("[%s] %s boots %s off the channel.", ch->name,
Name(player), Name(thing)));
do_delcomchannel(thing, channel);
}
void do_chanobj(dbref player, char *channel, char *object) {
struct channel *ch;
dbref thing;
char *buff;
init_match(player, object, NOTYPE);
match_everything(0);
thing = match_result();
if (!(ch = select_channel(channel))) {
raw_notify(player, "That channel does not exist.");
return;
}
if (thing == NOTHING) {
ch->chan_obj = NOTHING;
raw_notify(player, "Set.");
return;
}
if (!(ch->charge_who == player) && !Comm_All(player)) {
raw_notify(player, "Permission denied.");
return;
}
ch->chan_obj = thing;
buff = unparse_object(player, thing, 0);
notify_printf(player,
"Channel %s is now using %s as channel object.", ch->name,
buff);
free_lbuf(buff);
}
void do_chanlist(dbref player, dbref cause, int key) {
dbref owner;
struct channel *ch;
int flags;
char *temp;
char *buf;
char *atrstr;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
flags = (int) NULL;
if (key & CLIST_FULL) {
do_listchannels(player);
return;
}
temp = alloc_mbuf("do_chanlist_temp");
buf = alloc_mbuf("do_chanlist_buf");
raw_notify(player, "** Channel Owner Description");
for (ch = (struct channel *) hash_firstentry(&mudstate.channel_htab);
ch;
ch = (struct channel *) hash_nextentry(&mudstate.channel_htab)) {
if (Comm_All(player) || (ch->type & CHANNEL_PUBLIC) ||
ch->charge_who == player) {
atrstr = atr_pget(ch->chan_obj, A_DESC, &owner, &flags);
if ((ch->chan_obj == NOTHING) || !*atrstr)
sprintf(buf, "%s", "No description.");
else
sprintf(buf, "%-54.54s", atrstr);
free_lbuf(atrstr);
sprintf(temp, "%c%c %-13.13s %-15.15s %-45.45s",
(ch->type & (CHANNEL_PUBLIC)) ? 'P' : '-',
(ch->type & (CHANNEL_LOUD)) ? 'L' : '-', ch->name,
Name(ch->charge_who), buf);
raw_notify(player, temp);
}
}
free_mbuf(temp);
free_mbuf(buf);
raw_notify(player, "-- End of list of Channels --");
}
void do_chanstatus(dbref player, dbref cause, int key, char *chan) {
dbref owner;
struct channel *ch;
int flags;
char *temp;
char *buf;
char *atrstr;
if (!mudconf.have_comsys) {
raw_notify(player, "Comsys disabled.");
return;
}
if (key & CSTATUS_FULL) {
struct channel *ch;
int perm;
if (!(perm = Comm_All(player))) {
raw_notify(player,
"Warning: Only public channels and your channels will be shown.");
}
raw_notify(player,
"** Channel --Flags-- Obj Own Charge Balance Users Messages");
if (!(ch = select_channel(chan))) {
notify_printf(player,
"@cstatus: Channel %s does not exist.", chan);
return;
}
if (perm || (ch->type & CHANNEL_PUBLIC) ||
ch->charge_who == player) {
notify_printf(player, "%c%c %-20.20s %c%c%c/%c%c%c %5d %5d %8d %8d %6d %10d",
(ch->type & (CHANNEL_PUBLIC)) ? 'P' : '-',
(ch->type & (CHANNEL_LOUD)) ? 'L' : '-', ch->name,
(ch->type & (CHANNEL_PL_MULT *
CHANNEL_JOIN)) ? 'J' : '-',
(ch->type & (CHANNEL_PL_MULT *
CHANNEL_TRANSMIT)) ? 'X' : '-',
(ch->type & (CHANNEL_PL_MULT *
CHANNEL_RECIEVE)) ? 'R' : '-',
(ch->type & (CHANNEL_OBJ_MULT *
CHANNEL_JOIN)) ? 'j' : '-',
(ch->type & (CHANNEL_OBJ_MULT *
CHANNEL_TRANSMIT)) ? 'x' : '-',
(ch->type & (CHANNEL_OBJ_MULT *
CHANNEL_RECIEVE)) ? 'r' : '-',
(ch->chan_obj != NOTHING) ? ch->chan_obj : -1,
ch->charge_who, ch->charge, ch->amount_col,
ch->num_users, ch->num_messages);
}
raw_notify(player, "-- End of list of Channels --");
return;
}
temp = alloc_mbuf("do_chanstatus_temp");
buf = alloc_mbuf("do_chanstatus_buf");
raw_notify(player, "** Channel Owner Description");
if (!(ch = select_channel(chan))) {
notify_printf(player, "@cstatus: Channel %s does not exist.",
chan);
return;
}
if (Comm_All(player) || (ch->type & CHANNEL_PUBLIC) ||
ch->charge_who == player) {
atrstr = atr_pget(ch->chan_obj, A_DESC, &owner, &flags);
if ((ch->chan_obj == NOTHING) || !*atrstr)
sprintf(buf, "%s", "No description.");
else
sprintf(buf, "%-54.54s", atrstr);
free_lbuf(atrstr);
snprintf(temp, MBUF_SIZE, "%c%c %-13.13s %-15.15s %-45.45s",
(ch->type & (CHANNEL_PUBLIC)) ? 'P' : '-',
(ch->type & (CHANNEL_LOUD)) ? 'L' : '-', ch->name,
Name(ch->charge_who), buf);
raw_notify(player, temp);
}
free_mbuf(temp);
free_mbuf(buf);
raw_notify(player, "-- End of list of Channels --");
}
void fun_cemit(char *buff, char **bufc, dbref player, dbref cause, char *fargs[], char *nfargs[], int cargs, int ncargs) {
struct channel *ch;
static char smbuf[LBUF_SIZE];
if (!(ch = select_channel(fargs[0]))) {
safe_str("#-1 CHANNEL NOT FOUND", buff, bufc);
return;
}
if (!mudconf.have_comsys || (!Comm_All(player) && (player != ch->charge_who))) {
safe_str("#-1 NO PERMISSION TO USE", buff, bufc);
return;
}
snprintf(smbuf, LBUF_SIZE-1, "[%s] %s", fargs[0], fargs[1]);
do_comsend(ch, smbuf);
*buff = '\0';
}