#ifdef RCS
static char rcsid[]="$Id: servfunc.c,v 1.1.1.1 2000/11/13 02:42:48 holsta Exp $";
#endif
/******************************************************************************
* Internetting Cooperating Programmers
* ----------------------------------------------------------------------------
*
* ____ PROJECT
* | _ \ __ _ _ __ ___ ___ _ __
* | | | |/ _` | '_ \ / __/ _ \ '__|
* | |_| | (_| | | | | (_| __/ |
* |____/ \__,_|_| |_|\___\___|_| the IRC bot
*
* All files in this archive are subject to the GNU General Public License.
*
* $Source: /cvsroot/dancer/dancer/src/servfunc.c,v $
* $Revision: 1.1.1.1 $
* $Date: 2000/11/13 02:42:48 $
* $Author: holsta $
* $State: Exp $
* $Locker: $
*
* ---------------------------------------------------------------------------
*****************************************************************************/
#include "dancer.h"
#include "trio.h"
#include "strio.h"
#include "list.h"
#include "function.h"
#include "servfunc.h"
#include "fplrun.h"
/* --- Global ----------------------------------------------------- */
extern time_t now;
extern char servername[];
extern char servfile[];
extern char *errfrom;
extern itemserv *currentserv;
itemserv *servHead;
static int servid = 1;
/* --- FindServ --------------------------------------------------- */
itemserv *FindServ(char *name, long port)
{
int id;
itemserv *s;
snapshot;
id = atoi(name);
for (s = First(servHead); s; s = Next(s)) {
if ((id && (id == s->s.id)) ||
(StrEqual(name, s->s.name) && (port == s->s.port))) {
return s;
}
}
return NULL;
}
/* --- NextServ --------------------------------------------------- */
itemserv *NextServ(void)
{
itemserv *afterthis;
itemserv *s;
snapshot;
afterthis = currentserv;
for (s = First(servHead); s; s = Next(s)) {
if (s->s.flags & SERV_DISABLED)
continue;
if (NULL == afterthis)
return s;
else if (s == afterthis)
afterthis = NULL; /* get the next */
}
return First(servHead); /* if nothing matched, return the first */
}
int AddServ(struct ServerSub *sub)
{
int retcode = TRUE;
itemserv *s;
snapshot;
s = FindServ(sub->name, sub->port);
if (NULL == s) {
s = NewEntry(itemserv);
if (s) {
InsertLast(servHead, s);
s->s = *sub;
s->s.id = servid++;
return FALSE;
}
}
else if (s->s.flags & SERV_DISABLED &&
!(sub->flags & SERV_DISABLED) &&
!(sub->flags & SERV_INCONFIG)) {
/*
* The existing one is marked disabled. The new one is not, and it is
* not from the .config file.
* .config file entries are not allowed to undo disabled ones.
*/
/*
* The added one already exists, so we should return successful
* but we should free the resources of this new struct since we
* are reusing an old one.
*/
s->s.flags &= ~SERV_DISABLED;
retcode = FALSE;
}
else if (sub->flags & SERV_INCONFIG) {
s->s.flags |= SERV_INCONFIG; /* this exist in .config we know now */
}
/* Free the resources */
if (sub->name)
StrFree(sub->name);
if (sub->passwd)
StrFree(sub->passwd);
if (sub->adder)
StrFree(sub->adder);
if (sub->message)
StrFree(sub->message);
return retcode;
}
int ManAddServ(char *name, long port, char *passwd, char *who, long flags)
{
struct ServerSub sub;
snapshot;
memset(&sub, 0, sizeof(struct ServerSub));
sub.name = StrDuplicate(name);
sub.port = port ? port : IRCPORT;
sub.passwd = passwd ? StrDuplicate(passwd) : NULL;
sub.adder = who ? StrDuplicate(who) : NULL;
sub.addtime = now;
sub.flags = flags;
return AddServ(&sub);
}
void ListServ(char *from, char *line)
{
char match[MIDBUFFER] = "*";
itemserv *s;
snapshot;
StrScan(line, "%"MIDBUFFERTXT"s", match);
for (s = First(servHead); s; s = Next(s)) {
if (Match(s->s.name, match)) {
Sendf(from, "%d - %s %d%s%s", s->s.id, s->s.name, s->s.port,
s->s.passwd ? " <password>" : "",
(s->s.flags & SERV_DISABLED) ? " [DISABLED]" : "");
}
}
}
/* --- SaveServ --------------------------------------------------- */
int SaveServ(void)
{
char tempfile[BIGBUFFER];
bool ok = TRUE;
itemserv *s;
FILE *f;
snapshot;
if (NIL == servfile[0])
return TRUE;
StrFormatMax(tempfile, sizeof(tempfile), "%s~", servfile);
f = fopen(tempfile, "w");
if (f) {
if (0 > fprintf(f, "# Dancer serverlist version: " VERSIONMSG "\n")) {
ok = FALSE;
}
else {
for (s = First(servHead); s; s = Next(s)) {
if (0 > fprintf(f, "%s:%d:%s\n" ":%s\n" "-%s\n" "!%d %d %d %d %d %d\n",
s->s.name, s->s.port, s->s.passwd ? s->s.passwd : "",
s->s.message ? s->s.message : "",
s->s.adder ? s->s.adder : "",
s->s.connect, s->s.disconnect, s->s.average,
s->s.numconnects, s->s.flags, s->s.addtime)) {
ok = FALSE;
break;
}
}
}
fclose(f);
if (ok)
rename(tempfile, servfile);
}
else
return TRUE;
return FALSE;
}
/* --- LoadServ --------------------------------------------------- */
int LoadServ(void)
{
char buffer[MAXLINE];
char name1[BIGBUFFER];
char name2[BIGBUFFER];
int number[6];
struct ServerSub sub;
FILE *f;
snapshot;
f = fopen(servfile, "r");
if (f) {
memset(&sub, 0, sizeof(struct ServerSub));
while (fgets(buffer, sizeof(buffer), f)) {
switch(buffer[0]) {
case '#':
case '\n':
break;
case ':':
if (1 == StrScan(buffer, ":%[^\n]", name1)) {
sub.message = StrDuplicate(name1);
}
break;
case '-':
if (1 == StrScan(buffer, "-%[^\n]", name1)) {
sub.adder = StrDuplicate(name1);
}
break;
case '!':
if (6 == StrScan(buffer, "!%d %d %d %d %d %d",
&number[0], &number[1], &number[2],
&number[3], &number[4], &number[5])) {
sub.connect = number[0];
sub.disconnect = number[1];
sub.average = number[2];
sub.numconnects = number[3];
sub.flags = number[4] & ~SERV_INCONFIG;
sub.addtime = number[5];
}
AddServ(&sub);
memset(&sub, 0, sizeof(struct ServerSub));
break;
default:
name2[0] = (char)0;
number[0] = IRCPORT;
if (1 <= StrScan(buffer, "%[^:]:%d:%[^\n]",
name1, &number[0], name2)) {
sub.name = StrDuplicate(name1);
sub.port = number[0];
if (name2[0])
sub.passwd = StrDuplicate(name2);
}
break;
}
}
fclose(f);
}
else
return TRUE;
return FALSE;
}
void FreeServ(void *v)
{
itemserv *s;
snapshot;
s = (itemserv *)v;
if (s) {
if (s->s.name)
StrFree(s->s.name);
if (s->s.passwd)
StrFree(s->s.passwd);
if (s->s.message)
StrFree(s->s.message);
if (s->s.adder)
StrFree(s->s.adder);
}
}
void ServInit(void)
{
extern itemlist *serverHead;
char servername[BIGBUFFER], serverpasswd[BIGBUFFER];
int serverport;
itemlist *p;
snapshot;
servHead = NewList(itemserv);
if (servHead) {
/* First, we get the servers from the .serv file */
LoadServ();
/* Now, we convert the old-style serverlist */
for (p = First(serverHead); p; p = Next(p)) {
serverpasswd[0] = (char)0;
serverport = IRCPORT;
StrScan((char *)p->pointer, "%[a-zA-Z0-9.-]%*[ :]%d%*[ :]%[^\n]",
servername, &serverport, serverpasswd);
ManAddServ(servername, serverport, serverpasswd[0] ? serverpasswd : NULL,
NULL, SERV_INCONFIG);
}
}
}
void ServCleanup(void)
{
snapshot;
SaveServ();
DeleteList(servHead, FreeServ);
}
int DelServ(char *name, long port)
{
itemserv *s;
snapshot;
s = FindServ(name, port);
if (s) {
if (s->s.flags & SERV_INCONFIG) {
/*
* This is entered in the .config file and therefore we cannot
* remove this for real, just mark it disabled
*/
s->s.flags |= SERV_DISABLED;
}
else {
DeleteEntry(servHead, s, FreeServ); /* remove */
}
return FALSE;
}
return TRUE;
}
int ManDelServ(char *from, char *line)
{
char server[SEMIBUFFER];
long port = IRCPORT;
snapshot;
if (StrScan(line, "%"SEMIBUFFERTXT"s %d", server, &port)) {
if (currentserv &&
StrEqual(server, currentserv->s.name) &&
(port == currentserv->s.port)) {
Send(errfrom, GetText(msg_cant_delete_current_server));
return TRUE;
}
if (DelServ(server, port)) {
Sendf(errfrom, GetText(msg_could_not_find_server), server, port);
return TRUE;
}
Sendf(from, GetText(msg_server_removed), server, port);
SaveServ();
}
else
return TRUE;
return FALSE;
}
void StatServ(char *from, int options, char *server, long port)
{
itemserv *s;
snapshot;
if (NIL == server[0]) {
s = currentserv;
if (NULL == s) {
Sendf(errfrom, GetText(msg_server_not_in_list), servername);
return;
}
}
else {
s = FindServ(server, port);
if (NULL == s) {
Sendf(errfrom, GetText(msg_could_not_find_server), server, port);
return;
}
}
/*
* The switch makes duplicate flags get ignored, only one of them set
* will make a change
*/
switch(options) {
case SERV_ENABLED:
s->s.flags &= ~SERV_DISABLED;
break;
case SERV_DISABLED:
s->s.flags |= SERV_DISABLED;
break;
}
Sendf(from, "%s port %d %s", s->s.name, s->s.port,
s->s.passwd ? "<passwd>" : "");
Sendf(from, "%s last connect %s ago", (currentserv == s) ? "<current>" : "",
s->s.connect ? TimeAgo(s->s.connect) : "ages");
Sendf(from, "last disconnect %s ago, average connect time %s",
s->s.disconnect ? TimeAgo(s->s.disconnect) : "ages",
SecsToString(s->s.average));
Sendf(from, "number of connects: %d", s->s.numconnects);
Sendf(from, "State:%s",
(s->s.flags & SERV_DISABLED) ? " [DISABLED]" : " normal");
}
void ConnectServ(itemserv *serv)
{
snapshot;
currentserv = serv;
if (serv) {
#ifdef HAVE_LIBFPL
if (runfpl(RUN_CONNECT, serv->s.name, FPLRUN_PRE))
return;
#endif
serv->s.connect = now;
serv->s.numconnects++;
SaveServ();
runfpl(RUN_CONNECT, serv->s.name, FPLRUN_POST);
}
}
void DisconnectServ(char *fmt, ...)
{
char buf[BIGBUFFER];
va_list args;
snapshot;
va_start(args, fmt);
trio_vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
#ifdef HAVE_LIBFPL
if (runfpl(RUN_DISCONNECT, buf, FPLRUN_PRE))
return;
#endif
if (currentserv) {
if (currentserv->s.message)
StrFree(currentserv->s.message);
currentserv->s.message = StrDuplicate(buf);
currentserv->s.disconnect = now;
/* calculate the new average connect time */
currentserv->s.average = ((currentserv->s.average *
(currentserv->s.numconnects - 1)) +
(currentserv->s.disconnect -
currentserv->s.connect)) /
currentserv->s.numconnects;
}
runfpl(RUN_DISCONNECT, buf, FPLRUN_POST);
}
syntax highlighted by Code2HTML, v. 0.9.1