boolexp hidelock; /**< Who may hide from view */
struct channel *next; /**< Next channel in linked list */
BUFFERQ *bufferq; /**< Pointer to channel recall buffer queue */
+ FILE *logfile; /**< File to log channel in */
};
/** A list of channels on an object.
#define CHANNEL_NOCEMIT 0x400 /* Disallow @cemit */
#define CHANNEL_COBJ 0x800 /* Channel with a channel object */
#define CHANNEL_INTERACT 0x1000 /* Filter channel output through interactions */
+#define CHANNEL_LOG 0x2000 /* Log the channel to a file */
#define CHANNEL_DEFAULT_FLAGS (CHANNEL_PLAYER)
#define CL_JOIN 0x1
#define CL_SPEAK 0x2
#define ChanSeeLock(c) ((c)->seelock)
#define ChanHideLock(c) ((c)->hidelock)
#define ChanBufferQ(c) ((c)->bufferq)
+#define ChanLogFile(c) ((c)->logfile)
#define Channel_Quiet(c) (ChanType(c) & CHANNEL_QUIET)
#define Channel_Open(c) (ChanType(c) & CHANNEL_OPEN)
#define Channel_Object(c) (ChanType(c) & CHANNEL_OBJECT)
#define Channel_NoNames(c) (ChanType(c) & CHANNEL_NONAMES)
#define Channel_NoCemit(c) (ChanType(c) & CHANNEL_NOCEMIT)
#define Channel_Interact(c) (ChanType(c) & CHANNEL_INTERACT)
+#define Channel_Log(c) (ChanType(c) & CHANNEL_LOG)
#define Chan_Ok_Type(c,o) \
((ChanObj(c) == o) || (IsPlayer(o) && Channel_Player(c)) || \
(IsThing(o) && Channel_Object(c)))
#include <sys/types.h>
#endif
#include <stdarg.h>
+#include <sys/stat.h>
+#include <errno.h>
#include "conf.h"
#include "externs.h"
#include "attrib.h"
const char *extra);
static void list_partial_matches(dbref player, const char *name,
enum chan_match_type type);
+static void begin_chat_log(CHAN *chan);
+static void end_chat_log(CHAN *chan);
+static void write_chat_log(CHAN *chan, char *buf);
const char *chan_speak_lock = "ChanSpeakLock"; /**< Name of speak lock */
const char *chan_join_lock = "ChanJoinLock"; /**< Name of join lock */
{"NoCemit", 'C', CHANNEL_NOCEMIT, CHANNEL_NOCEMIT},
{"Interact", 'I', CHANNEL_INTERACT, CHANNEL_INTERACT},
{"ChanObj", 'Z', CHANNEL_COBJ, CHANNEL_COBJ},
+ {"LogChannel", 'L', CHANNEL_LOG, CHANNEL_LOG},
{NULL, '\0', 0, 0}
};
return 0;
}
insert_channel(&ch);
+ if(Channel_Log(ch))
+ begin_chat_log(ch);
}
num_channels = i;
return 0;
}
insert_channel(&ch);
+ if(Channel_Log(ch))
+ begin_chat_log(ch);
}
num_channels = i;
ChanMaxUsers(ch) = 0;
ChanUsers(ch) = NULL;
ChanBufferQ(ch) = NULL;
+ ch->logfile = NULL;
return ch;
}
CHANUSER *u, *unext;
if (!c)
return;
+ if(c->logfile)
+ fclose(c->logfile);
free_boolexp(ChanJoinLock(c));
free_boolexp(ChanSpeakLock(c));
free_boolexp(ChanHideLock(c));
ChanCreator(chan) = Owner(player);
strcpy(ChanName(chan), name);
insert_channel(&chan);
+ if(Channel_Log(chan))
+ begin_chat_log(chan);
notify_format(player, T("CHAT: Channel <%s> created."), ChanName(chan));
break;
case 1:
notify(player, T("Permission denied."));
return;
}
+ if(Channel_Log(chan))
+ end_chat_log(chan);
/* remove everyone from the channel */
channel_wipe(player, chan);
/* refund the owner's money */
}
/* When we rename a channel, we actually remove it and re-insert it */
strcpy(old, ChanName(chan));
+ if(Channel_Log(chan))
+ end_chat_log(chan);
remove_channel(chan);
strcpy(ChanName(chan), perms);
insert_channel(&chan);
+ if(Channel_Log(chan))
+ begin_chat_log(chan);
channel_broadcast(chan, player, 0,
"<%s> %s has renamed channel %s to %s.",
ChanName(chan), Name(player), old, ChanName(chan));
("Invalid or same permissions on channel <%s>. No changes made."),
ChanName(chan));
} else {
+ if(Channel_Log(chan) && !(type & CHANNEL_LOG))
+ end_chat_log(chan);
+ else if(!Channel_Log(chan) && (type & CHANNEL_LOG))
+ begin_chat_log(chan);
ChanType(chan) = type;
notify_format(player,
T("Permissions on channel <%s> changed."), ChanName(chan));
if (ChanBufferQ(channel))
add_to_bufferq(ChanBufferQ(channel), 0,
(flags & CB_NOSPOOF) ? player : NOTHING, tbuf1);
+ if(Channel_Log(channel))
+ write_chat_log(channel, tbuf1);
}
channel_broadcast(chan, victim, flags, msg, ChanObjName(chan), Name(victim));
}
+static void
+begin_chat_log(CHAN *chan)
+{
+ struct stat st;
+ char filename[512];
+ int i, j;
+
+ if(!*CHATLOGDIR)
+ return;
+
+ if(stat(CHATLOGDIR, &st)) {
+ do_rawlog(LT_ERR, T("Unable to stat() chatlog_dir: %s"), strerror(errno));
+ return;
+ }
+
+ if(!S_ISDIR(st.st_mode)) {
+ do_rawlog(LT_ERR, T("chatlog_dir is not a directory"));
+ return;
+ }
+
+ strcpy(filename, CHATLOGDIR); /* N.B.: CHATLOGDIR is at most 256 bytes */
+ i = strlen(filename);
+ if(filename[i-1] != '/') {
+ filename[i] = '/';
+ i++;
+ }
+
+ j = strlen(ChanName(chan));
+ if((i + j) > 507) {
+ do_rawlog(LT_ERR,
+ T("Buffer length exceeded for chat log filename for channel %s"),
+ ChanName(chan));
+ return;
+ }
+
+ strcpy(filename + i, ChanName(chan));
+ i += j;
+
+ strcpy(filename + i, ".log");
+ filename[511] = '\0';
+
+ ChanLogFile(chan) = fopen(filename, "a");
+ if(!ChanLogFile(chan)) {
+ do_rawlog(LT_ERR, T("Unable to open log file for channel %s: %s"),
+ ChanName(chan), strerror(errno));
+ return;
+ }
+
+ write_chat_log(chan, "Beginning of log.");
+}
+
+static void
+end_chat_log(CHAN *chan)
+{
+ if(!ChanLogFile(chan))
+ return;
+
+ write_chat_log(chan, "End of log.");
+ fclose(ChanLogFile(chan));
+ ChanLogFile(chan) = NULL;
+}
+
+static void
+write_chat_log(CHAN *chan, char *buf)
+{
+ char tbuf[BUFFER_LEN];
+ struct tm *when;
+ char *clean;
+
+ if(!ChanLogFile(chan))
+ return;
+
+ when = localtime(&mudtime);
+ strftime(tbuf, sizeof tbuf, "[%m/%d %H:%M:%S] ", when);
+ fputs(tbuf, ChanLogFile(chan));
+
+ clean = remove_markup(buf, NULL);
+ fputs(clean, ChanLogFile(chan));
+ fputc('\n', ChanLogFile(chan));
+ fflush(ChanLogFile(chan));
+}
static void
do_reset_cobj(player, name)