Initial commit of code released on 2002-07-15

This commit is contained in:
Brian Cline
2015-01-25 18:26:44 -06:00
commit feca086612
102 changed files with 22822 additions and 0 deletions

27
Sources/Makefile Normal file
View File

@@ -0,0 +1,27 @@
# Undernet Channel Service (X)
# Copyright (C) 1995-2002 Robin Thellend
#
# This program 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 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# The author can be contact by email at <csfeedback@robin.pfft.net>
#
# Please note that this software is unsupported and mostly
# obsolete. It was replaced by GNUworld/CMaster. See
# http://gnuworld.sourceforge.net/ for more information.
#
all:
@cd ..; make; cd Sources;

72
Sources/Sources.mak Normal file
View File

@@ -0,0 +1,72 @@
# Undernet Channel Service (X)
# Copyright (C) 1995-2002 Robin Thellend
#
# This program 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 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# The author can be contact by email at <csfeedback@robin.pfft.net>
#
# Please note that this software is unsupported and mostly
# obsolete. It was replaced by GNUworld/CMaster. See
# http://gnuworld.sourceforge.net/ for more information.
all: ../cs
.c.o:
${CC} ${CFLAGS} ${DEFINES} -c $<
../cs: ver ${OBJECTS} cksum.o cksum
${CC} ${CFLAGS} ${DEFINES} ${LIBS} -o ../cs main.c cksum.o ${OBJECTS} -DBINCKSUM1=0 -DBINCKSUM2=0
${CC} ${CFLAGS} ${DEFINES} ${LIBS} -o ../cs main.c cksum.o ${OBJECTS} `./cksum ../cs`
ver:
@chmod +x version.SH
@./version.SH
cksum: cksum.c
${CC} ${CFLAGS} -o cksum cksum.c -DMAIN
list: ../list
../list: list.c
${CC} -o ../list list.c
listall: ../listall
../listall: listall.c
${CC} -o ../listall listall.c
fixdb: match.o
${CC} fixdb.c match.o -DMAIN -o ../fixdb
showdb: match.o
${CC} -Wall showdb.c match.o -DMAIN -o ../showdb
show_old_managers: match.o
${CC} -Wall -o ../show_old_managers show_old_managers.c match.o -DMAIN
clean:
$(RM) -f *.o *.bak
depend:
-gcc -MM ${CFLAGS} ${SOURCES} > make.dep
backup: ${SOURCES} list.c listall.c
-cd ..; backups/backup
love:
-@echo "With you?? dream on! :P"
include make.dep

427
Sources/bans.c Normal file
View File

@@ -0,0 +1,427 @@
/* @(#)$Id: bans.c,v 1.12 1999/04/04 17:00:03 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
void ban(char *source, char *chan, char *nicklist)
{
char buffer[300];
char OneNick[NICK_LENGTH];
char channel[CHANNELNAME_LENGTH];
register auser *user;
register aluser *luser;
register achannel *ch;
register int i = 0;
if (*nicklist == '#')
{
GetWord(0, nicklist, channel);
nicklist = ToWord(1, nicklist);
}
else
{
strcpy(channel, chan);
GuessChannel(source, channel);
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: ban <channel> <nick1|addr1> [nick2|addr2] [...]");
return;
}
#ifdef DEBUG
printf("BAN REQUEST FOR %s\nON CHANNEL %s\nBY %s (%d)\n",
nicklist, channel, source, Access(channel, source));
#endif
if (*source && Access(channel, source) < BAN_LEVEL)
{
notice(source, "Your Access on this channel is too low");
return;
}
ch = ToChannel(channel);
/* I'm not on this channel.. so screw it! */
if (ch == NULL || !ch->on)
{
notice(source, "I'm NOT on that channel!");
return;
}
if (!ch->AmChanOp)
{
notice(source, "I'm not channel operator!");
return;
}
if (!*nicklist)
{
notice(source, "SYNTAX: ban <channel> <nick1|addr1> [nick2|addr2] [...]");
return;
}
GetWord(0, nicklist, OneNick);
while (*OneNick)
{
luser = ToLuser(OneNick);
if (luser)
sprintf(buffer, "%s!%s@%s", luser->nick,
luser->username, luser->site);
if (luser)
{
sprintf(buffer, "I BAN %s!%s@%s ON %s", luser->nick,
luser->username, luser->site, channel);
log(buffer);
user = ToUser(channel, OneNick);
if (user && user->chanop)
{
changemode(channel, "-o", user->N->nick, 0);
}
MakeBanMask(luser, buffer);
changemode(channel, "+b", buffer, 0);
}
GetWord(++i, nicklist, OneNick);
}
flushmode(channel);
}
void mban(char *source, char *ch, char *args)
{
char buffer[200];
char channel[80];
register int found = 0;
register achannel *chan;
register auser *user;
if (*args == '#')
{
GetWord(0, args, channel);
args = ToWord(1, args);
}
else
{
strcpy(channel, ch);
GuessChannel(source, channel);
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: mban <channel> <nick!username@hostname>");
return;
}
if ((chan = ToChannel(channel)) == NULL || !chan->on)
{
if (*source)
notice(source, "I'm NOT on that channel!");
return;
}
if (!chan->AmChanOp)
{
if (*source)
notice(source, "I am NOT channel operator!");
return;
}
if (*source && Access(channel, source) < MASS_BAN_LEVEL)
{
notice(source, "Your Access on this channel is too low!");
return;
}
if (!*args)
{
notice(source, "SYNTAX: mban <channel> <nick!username@hostname>");
return;
}
user = chan->users;
while (user)
{
sprintf(buffer, "%s!%s@%s",
user->N->nick, user->N->username, user->N->site);
if (match(buffer, args))
{
sprintf(buffer, "I BAN %s!%s@%s on %s (%s)", user->N->nick,
user->N->username, user->N->site, channel, args);
log(buffer);
if (user->chanop)
{
changemode(channel, "-o", user->N->nick, 0);
user->chanop = 0;
}
/*MakeBanMask(user->N,buffer); */
if (!found)
changemode(channel, "+b", args, 0);
found = 1;
}
user = user->next;
}
if (found)
flushmode(channel);
else if (*source)
{
notice(source, "No match.");
}
}
void unban(char *source, char *ch, char *list)
{
register aban *bans;
register aluser *luser;
register achannel *chan;
char channel[CHANNELNAME_LENGTH];
char buffer[512];
char one[200];
register int found;
register int i, exact;
if (*list == '#')
{
GetWord(0, list, channel);
list = ToWord(1, list);
}
else
{
strcpy(channel, ch);
GuessChannel(source, channel);
}
chan = ToChannel(channel);
if (chan == NULL || !chan->on)
{
notice(source, "I am NOT on that channel!");
return;
}
if (!chan->AmChanOp)
{
notice(source, "I am not channel operator!");
return;
}
if (*source && Access(channel, source) < BAN_LEVEL)
{
notice(source, "You're Access on this channel is too low");
return;
}
if (!*list)
{
notice(source, "SYNTAX: unban [#channel] <nick1|addr1> [<nick2|addr2>] [...]");
return;
}
i = 0;
GetWord(0, list, one);
while (*one)
{
found = 0;
luser = ToLuser(one);
if (luser != NULL)
{
sprintf(one, "%s!%s@%s", luser->nick, luser->username,
luser->site);
exact = 0;
}
else
{
exact = 1;
}
bans = chan->bans;
while (bans != NULL)
{
if ((!exact && match(one, bans->pattern)) ||
(exact && !strcasecmp(one, bans->pattern)))
{
sprintf(buffer, "I UNBAN %s ON %s",
bans->pattern, chan->name);
log(buffer);
changemode(channel, "-b", bans->pattern, 0);
RemBan(channel, bans->pattern);
bans = chan->bans;
found = 1;
if (exact)
break;
}
else
bans = bans->next;
}
if (*source && !found)
{
sprintf(buffer, "%s is not in %s's banlist!",
one, channel);
notice(source, buffer);
}
GetWord(++i, list, one);
}
flushmode(channel);
}
void showbanlist(char *source, char *ch, char *args)
{
char buffer[200];
char channel[80];
register achannel *chan;
register aban *curr;
if (*args == '#')
{
GetWord(0, args, channel);
}
else
{
strcpy(channel, ch);
GuessChannel(source, channel);
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: banlist <channel>");
return;
}
/* user must be on a channel to see the ban list
*/
if (ToUser(channel, source) == NULL)
{
sprintf(buffer, "%s: You are not on that channel", channel);
notice(source, buffer);
return;
}
chan = ToChannel(channel);
curr = chan->bans;
if (curr == NULL)
{
sprintf(buffer, "%s: ban list is empty.", channel);
notice(source, buffer);
return;
}
while (curr != NULL)
{
notice(source, curr->pattern);
curr = curr->next;
}
sprintf(buffer, "%s: End of ban list", channel);
notice(source, buffer);
}
void MakeBanMask(aluser * luser, char *output)
{
register int isip = 1;
register int i, j;
int a1, a2, a3, a4;
char hostmask[200];
register char *ptr;
if (luser == NULL)
{
/* Don't do anything */
return;
}
/* check if hostname is a numeric IP address
*/
for (i = 0; luser->site[i] != '\0' && isip; i++)
{
if (!isdigit(luser->site[i]) && luser->site[i] != '.')
isip = 0;
}
if (isip)
{
sscanf(luser->site, "%d.%d.%d.%d", &a1, &a2, &a3, &a4);
if (a1 <= 127)
{ /* class A */
/*sprintf(hostmask,"%d.*",a1); *shrugs* */
sprintf(hostmask, "%d.%d.*", a1, a2);
}
else if (a1 <= 191)
{ /* class B */
sprintf(hostmask, "%d.%d.*", a1, a2);
}
else
{ /* class C */
sprintf(hostmask, "%d.%d.%d.*", a1, a2, a3);
}
}
else
{ /* not numeric address */
ptr = luser->site + strlen(luser->site);
i = 0;
if (!strcasecmp(luser->site + strlen(luser->site) - 3, ".AU") ||
!strncasecmp(luser->site + strlen(luser->site) - 7, ".NET.", 4) ||
!strncasecmp(luser->site + strlen(luser->site) - 7, ".COM.", 4) ||
!strncasecmp(luser->site + strlen(luser->site) - 7, ".EDU.", 4) ||
!strncasecmp(luser->site + strlen(luser->site) - 6, ".AC.", 3))
j = 3;
else
j = 2;
while (i != j && ptr != luser->site)
{
if (*ptr == '.')
i++;
ptr--;
}
if (i == j)
ptr += 2;
if (ptr == luser->site)
strcpy(hostmask, ptr);
else
sprintf(hostmask, "*.%s", ptr);
}
if (!strncasecmp(luser->username, "^wld", 4))
{
/* special case for telnet users */
sprintf(output, "*!^wld*@%s", hostmask);
}
else
{
ptr = luser->username;
while (strlen(ptr) == 10 || *ptr == '~')
ptr++;
sprintf(output, "*!*%s@%s", ptr, hostmask);
}
}

288
Sources/buffer.c Normal file
View File

@@ -0,0 +1,288 @@
/* @(#)$Id: buffer.c,v 1.3 1996/11/13 00:40:34 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
/* These routines were first developed for the telnet3d project.
* Special thanks to Danny Mitchell (wildthang@irc) for his help
*/
#include "h.h"
static struct buffer_block *avail=NULL;
/*static unsigned long MEM_buffers=0;*/
static unsigned long NB_avail_buffer_blocks=0;
static unsigned long NB_alloc_buffer_blocks=0;
/* get_buffer_block() by SeKs <intru@step.polymtl.ca>
* returns a ptr to an empty buffer_block or NULL if malloc()
* returns an error.
*/
struct buffer_block *get_buffer_block(void)
{
register struct buffer_block *block;
/* I would like to move this to the GetMemory
** and linklist functions as soon as we get them
** finished. Mainly for use in keeping track
** of overall memory usage, and such.
** just a reminder. --DVM
*/
if(avail==NULL){
block=(struct buffer_block *)malloc(sizeof(struct buffer_block));
block->next=NULL;
}else{
block=avail;
avail=avail->next;
NB_avail_buffer_blocks--;
}
block->offset_read=0;
block->offset_write=0;
block->next=NULL;
NB_alloc_buffer_blocks++;
return block;
}
/* return_buffer_block() by SeKs <intru@step.polymtl.ca>
* returns the given "block" to the "system". Blocks are not
* free()'d. They are kept in order to be re-allocated by
* get_buffer_block().
*/
void return_buffer_block(struct buffer_block *block)
{
block->next=avail;
avail=block;
NB_avail_buffer_blocks++;
NB_alloc_buffer_blocks--;
}
/* copy_from_buffer() by SeKs <intru@step.polymtl.ca>
* copies characters from the buffer starting at the buffer_block
* '*block' into 'string' until a char in 'stop' is encountered or
* 'max' bytes are read.
* Blocks that are completely copied are returned to the system with
* return_buffer_block().
* Returns the number of characters that were copied.
*/
int
copy_from_buffer(struct buffer_block **block,char *string,char stop,int max)
{
register struct buffer_block *tmp;
register int count=0;
if(block==NULL || *block==NULL || string==NULL)
return -1;
while(count<max && *block!=NULL){
if((*block)->offset_read == (*block)->offset_write){
tmp=*block;
*block=(*block)->next;
return_buffer_block(tmp);
break;
}
count++;
*string=(*block)->buf[(*block)->offset_read++];
if((*block)->offset_read == BUFFER_BLOCK_SIZE){
tmp=*block;
*block=(*block)->next;
return_buffer_block(tmp);
}
string++;
if(stop!='\0' && stop==*(string-1))
break;
}
*string='\0';
return count;
}
/* look_in_buffer() by SeKs <intru@step.polymtl.ca>
* Same as copy_from_buffer() except that the buffer remains unchanged
* when the function returns.
* ** Added offset counter otherwise offset_read IS changed when returned -DVM
*/
int
look_in_buffer(struct buffer_block **block,char *string,char stop,int max)
{
register int count=0;
register int offset=0; /* added DVM */
if(block==NULL || *block==NULL || string==NULL)
return -1;
if((*block)->offset_read == (*block)->offset_write){
return_buffer_block(*block);
*block=NULL;
}
while(count<max && *block!=NULL){
if((*block)->offset_read+offset == (*block)->offset_write)
break;
count++;
*string=(*block)->buf[(*block)->offset_read+offset];
offset++;
if((*block)->offset_read+offset == BUFFER_BLOCK_SIZE){
block=&(*block)->next;
offset=0;
}
string++;
if(stop!='\0' && stop==*(string-1))
break;
}
*string='\0';
return count;
}
/* copy_to_buffer() by SeKs <intru@step.polymtl.ca>
* adds a string to the specified buffer.
* New buffer_blocks are requested when necessary.
* Returns the number of characters in the buffer after the
* new string is added.
* arguments are:
* ( struct buffer_block **block, char *format, args... )
*/
long copy_to_buffer(struct buffer_block **block, char *string,int length)
{
register long count=0;
if(block==NULL || length<=0)
return -1;
if(*block==NULL)
*block=get_buffer_block();
while((*block)->next!=NULL){
count+=(BUFFER_BLOCK_SIZE)-(*block)->offset_read;
block=&(*block)->next;
}
count+=(*block)->offset_write-(*block)->offset_read;
while(length--){
count++;
(*block)->buf[(*block)->offset_write++]=*(string++);
if((*block)->offset_write == BUFFER_BLOCK_SIZE){
(*block)->offset_write=-1;
(*block)->next=get_buffer_block();
block=&(*block)->next;
if(*block==NULL){
break;
}
}
}
return count;
}
/* zap_buffer() by SeKs <intru@step.polymtl.ca>
* clears the buffer starting at the buffer_block '*block'
* return -1 if block is NULL
* 0 otherwise
*/
int zap_buffer(struct buffer_block **block)
{
struct buffer_block *tmp;
if(block==NULL)
return -1;
while((tmp=*block)!=NULL){
*block=(*block)->next;
return_buffer_block(tmp);
}
return 0;
}
/* find_char_in_buffer() by SeKs <intru@step.polymtl.ca>
* returns 1 if any character of string 'findit' is present within the first
* 'max' characters of the buffer.
* returns 0 otherwise.
*/
int find_char_in_buffer(struct buffer_block **block, char findit,int max)
{
register int offset;
register int count=0;
if( (block == NULL) || (*block == NULL))
return 0; /* DVM */
offset=(*block)->offset_read;
loop:
if(offset == (*block)->offset_write)
return 0;
if(findit == (*block)->buf[offset])
return 1;
if(++count > max)
return 0;
if(++offset == BUFFER_BLOCK_SIZE){
block=&(*block)->next;
if(*block == NULL)
return 0;
offset=0;
}
goto loop;
}
/* skip_char_in_buffer() by SeKs <intru@step.polymtl.ca>
* flushes the first 'n' characters in buffer starting at
* buffer_block '*block'
*/
int skip_char_in_buffer(struct buffer_block **block, int n)
{
register struct buffer_block *tmp;
register int count=0;
while(count<n){
if((*block)->offset_read == (*block)->offset_write){
tmp=*block;
*block=(*block)->next;
return_buffer_block(tmp);
break;
}
count++;
(*block)->offset_read++;
if((*block)->offset_read == BUFFER_BLOCK_SIZE){
tmp=*block;
*block=(*block)->next;
return_buffer_block(tmp);
if(*block==NULL)
break;
}
}
return count;
}

185
Sources/change_byte_order.c Normal file
View File

@@ -0,0 +1,185 @@
/* @(#)$Id: change_byte_order.c,v 1.3 1996/11/13 00:40:34 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <netinet/in.h>
#include "defines.h"
#include "struct.h"
#include "version.h"
#include "../config.h"
typedef struct DiskUser {
char realname[80];
char match[80];
int Access;
char passwd[20];
char channel[80];
unsigned long flags;
char reserved[20];
time_t suspend;
time_t lastseen;
} DiskUser;
typedef struct ShitDisk {
time_t time;
time_t expiration;
char match[80];
char from[80];
char reason[200];
char channel[50];
int level;
} ShitDisk;
void main(void)
{
FILE *in;
FILE *out;
DiskUser olduser;
DiskUser user;
adefchan oldchan;
adefchan chan;
ShitDisk oldshit,shit;
time_t now;
char swap, *ptr;
if(chdir(HOMEDIR)<0){
perror(HOMEDIR);
exit(1);
}
now=time(NULL);
out=fopen("userlist.dat.new","w");
if(out==NULL){
perror("userlist.dat.new");
exit(1);
}
in=fopen(USERFILE,"r");
if(in==NULL){
perror(USERFILE);
return;
}
while(fread(&user,sizeof(DiskUser),1,in)>0){
ptr=(char *)&user.Access;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&user.flags;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&user.suspend;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&user.lastseen;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
fwrite(&user,sizeof(DiskUser),1,out);
}
fclose(in);
fclose(out);
out=fopen("channellist.dat.new","w");
if(out==NULL){
perror("channellist.dat.new");
exit(1);
}
in=fopen(DEFAULT_CHANNELS_FILE,"r");
if(in==NULL){
perror(DEFAULT_CHANNELS_FILE);
exit(1);
}
while(fread(&chan,sizeof(adefchan),1,in)>0){
ptr=(char *)&chan.MassDeopPro;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&chan.NickFloodPro;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&chan.MsgFloodPro;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&chan.TS;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&chan.flags;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&chan.uflags;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
fwrite(&chan,sizeof(adefchan),1,out);
}
fclose(in);
fclose(out);
out=fopen("shitlist.dat.new","w");
if(out==NULL){
perror("shitlist.dat.new");
exit(1);
}
in=fopen(SHITLIST_FILE,"r");
if(in==NULL){
perror(SHITLIST_FILE);
exit(1);
}
while(fread(&shit,sizeof(ShitDisk),1,in)>0){
ptr=(char *)&shit.time;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&shit.expiration;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
ptr=(char *)&shit.level;
swap=ptr[0]; ptr[0]=ptr[3]; ptr[3]=swap;
swap=ptr[1]; ptr[1]=ptr[2]; ptr[2]=swap;
fwrite(&shit,sizeof(ShitDisk),1,out);
}
fclose(in);
fclose(out);
}

1833
Sources/channels.c Normal file

File diff suppressed because it is too large Load Diff

266
Sources/chat.c Normal file
View File

@@ -0,0 +1,266 @@
/* @(#)$Id: chat.c,v 1.10 2000/09/09 15:38:13 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#ifdef DOHTTP
struct chat_user
{
char user[10];
char host[80];
aluser *luser;
};
void chat_sendtoall(char *from, char *msg)
{
register http_socket *scan = HttpList;
while (scan != NULL)
{
if (scan->status == HTTP_CHAT && ((struct chat_user *)scan->hook)->luser)
{
if (from)
sendto_http(scan, "<%s> %s\n", from, msg);
else
sendto_http(scan, "%s\n", msg);
}
scan = scan->next;
}
}
static void login_ok(struct http_socket *hsock, RegUser * reg)
{
char buffer[512], nick[15];
struct chat_user *cu = (struct chat_user *)hsock->hook;
register http_socket *scan;
int count = 0;
sprintf(buffer, "1 %ld %s %s %s", now, cu->user + 1, cu->host, VirtualServer.name);
strcpy(nick, cu->user);
while (ToLuser(nick) != NULL)
sprintf(nick, "+%d%s", ++count, cu->user + 1);
nick[9] = '\0';
onnick(VirtualServer.name, nick, buffer);
cu->luser = ToLuser(nick);
cu->luser->valchan = (avalchan *) MALLOC(sizeof(avalchan));
cu->luser->valchan->name = (char *)MALLOC(strlen(reg->channel) + 1);
strcpy(cu->luser->valchan->name, reg->channel);
cu->luser->valchan->reg = reg;
reg->inuse++;
reg->lastseen = now;
reg->modified = 1;
cu->luser->valchan->next = NULL;
sendto_http(hsock, "Welcome to %s's chat line\n", mynick);
count = 0;
sprintf(buffer, "*** Currently on: ");
for (scan = HttpList; scan != NULL; scan = scan->next)
{
if (scan->status != HTTP_CHAT || ((struct chat_user *)scan->hook)->luser == NULL)
continue;
if (strlen(buffer) > 70)
{
sendto_http(hsock, "%s\n", buffer);
sprintf(buffer, "*** ");
}
strcat(buffer, ((struct chat_user *)scan->hook)->luser->nick + 1);
strcat(buffer, " ");
}
sendto_http(hsock, "%s\n", buffer);
sprintf(buffer, "*** JOIN: %s@%s", cu->luser->nick + 1, cu->host);
chat_sendtoall(NULL, buffer);
}
static void
chat_login_callback(int *fd, off_t off, int action, void *hook1, void *hook2,
dbuser * dbu, int count)
{
extern RegUser *load_dbuser(off_t, dbuser *);
register RegUser *reg;
struct http_socket *hsock = (struct http_socket *)hook1;
struct chat_user *cu;
char userhost[200];
if (dbu != NULL)
{
cu = (struct chat_user *)hsock->hook;
reg = load_dbuser(off, dbu);
sprintf(userhost, "%s!%s@%s", cu->user, cu->user + 1, cu->host);
if (reg != NULL && *reg->match == '+' && match(userhost, reg->match))
{
#ifdef DEBUG
printf("login_ok: %s %s\n", userhost, reg->match);
#endif
login_ok(hsock, reg);
}
else
{
sendto_http(hsock, "Authentication failed!\n");
hsock->status = HTTP_ENDING;
}
}
else
{
if (count == 0)
{
sendto_http(hsock, "Authentication failed!\n");
hsock->status = HTTP_ENDING;
hsock->dbio = 0;
}
}
}
void chat_login(struct http_socket *hsock, char *user, char *password)
{
char userhost[200], channel[] = "*", buffer[200];
struct chat_user *cu;
register RegUser *ruser;
cu = (struct chat_user *)malloc(sizeof(struct chat_user));
sprintf(buffer, "+%s", user);
strncpy(cu->user, buffer, 9);
cu->user[9] = '\0';
strcpy(cu->host, inet_ntoa(hsock->peer.sin_addr));
cu->luser = NULL;
hsock->hook = (void *)cu;
sprintf(userhost, "%s!%s@%s", cu->user, cu->user + 1, cu->host);
ruser = UserList[ul_hash(channel)];
while (ruser != NULL)
{
if (!strcasecmp(ruser->channel, channel) &&
*ruser->match == '+' && match(userhost, ruser->match) &&
!strcmp(ruser->passwd, password))
break;
ruser = ruser->next;
}
if (ruser == NULL)
{ /* ok.. not in memory.. send db query */
db_fetch(channel, DBGETUHPASS, userhost, password, 0,
hsock, NULL, chat_login_callback);
hsock->dbio = 1;
}
else
{
#ifdef DEBUG
printf("login_ok: %s %s\n", userhost, ruser->match);
#endif
login_ok(hsock, ruser);
}
}
void chat_notice(char *user, char *msg)
{
register http_socket *scan = HttpList;
register struct chat_user *cu;
#ifdef DEBUG
printf("chat: ->%s %s\n", user, msg);
#endif
while (scan != NULL)
{
cu = (struct chat_user *)scan->hook;
if (scan->status == HTTP_CHAT && cu->luser &&
!strcasecmp(cu->luser->nick, user))
{
sendto_http(scan, "-%s- %s\n", mynick, msg);
break;
}
scan = scan->next;
}
}
void parse_chat(struct http_socket *hsock, char *line)
{
char buffer[200], global[] = "*", *ptr;
if (hsock == NULL || hsock->hook == NULL ||
((struct chat_user *)hsock->hook)->luser == NULL)
return;
if ((ptr = strpbrk(line, "\r\n")) != NULL)
*ptr = '\0';
#ifdef DEBUG
printf("chat: <%s> %s\n", ((struct chat_user *)hsock->hook)->luser->nick + 1, line);
#endif
if ((*line == '/') || (*line == '.'))
{
sprintf(buffer, "%s@%s", mynick, SERVERNAME);
parse_command(((struct chat_user *)hsock->hook)->luser->nick,
buffer, global, line + 1);
}
else
chat_sendtoall(((struct chat_user *)hsock->hook)->luser->nick + 1, line);
}
void chat_close(http_socket * hsock, char *comment)
{
char buffer[512];
struct chat_user *cu = (struct chat_user *)hsock->hook;
if (cu->luser)
{
sprintf(buffer, "*** LEAVE: %s@%s", cu->luser->nick + 1, cu->host);
chat_sendtoall(NULL, buffer);
onquit(cu->luser->nick);
}
}
void DccMe(char *source, char *arg)
{
char global[] = "*", buffer[512];
if(Access(global, source) >= 600)
{
unsigned long addr = inet_addr(BINDADDR);
addr = ntohl(addr);
sprintf(buffer, ":%s PRIVMSG %s :\001DCC CHAT chat %u %u\001\n",
mynick, source, addr, HTTP_PORT);
sendtoserv(buffer);
}
}
#endif

100
Sources/cksum.c Normal file
View File

@@ -0,0 +1,100 @@
/* $Id: cksum.c,v 1.1 1997/06/30 03:48:05 cvs Exp $
*/
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void cksum(char *file, unsigned int *sum1, unsigned int *sum2)
{
int fd=-1, size;
unsigned char buffer[1024];
if(strchr(file,'/') != NULL)
{
fd = open(file,O_RDONLY);
}
else /* check path */
{
char *tok,*path = getenv("PATH");
if(path == NULL)
return;
for(tok=strtok(path,":"); tok!=NULL; tok=strtok(NULL,":"))/* mangles PATH*/
{
strncpy(buffer,tok,1023);
strncat(buffer,"/",1023);
strncat(buffer,file,1023);
buffer[1023] = '\0';
fd = open(buffer,O_RDONLY);
if(fd >= 0)
break;
}
}
if(fd<0)
{
return;
}
*sum1 = *sum2 = 0;
while((size=read(fd,buffer,1023))>0)
{
while(size--)
{
*sum1 += buffer[size];
*sum2 += (size&1)?-buffer[size]:buffer[size];
}
}
close(fd);
}
#ifdef MAIN
int main(int argc, char **argv)
{
unsigned int sum,pro;
if(argc != 2)
{
fprintf(stderr,"usage: %s file\n",argv[0]);
exit(1);
}
cksum(argv[1],&sum,&pro);
printf("-DBINCKSUM1=0x%x -DBINCKSUM2=0x%x\n",sum,pro);
exit(0);
}
#endif

241
Sources/conf.c Normal file
View File

@@ -0,0 +1,241 @@
/* @(#)$Id: conf.c,v 1.5 1998/01/22 09:36:11 chaos Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
void read_conf(char *conf)
{
FILE *fp;
char buffer[1024], *ptr;
fp = fopen(conf, "r");
if (fp == NULL)
{
perror(conf);
exit(1);
}
while (fgets(buffer, 1024, fp) != NULL)
{
if (*buffer == '#' || *buffer == '\0')
continue;
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
if (!strncasecmp(buffer, "NICKNAME ", 9))
{
strncpy(mynick, buffer + 9, NICK_LENGTH);
mynick[NICK_LENGTH - 1] = '\0';
}
else if (!strncasecmp(buffer, "USERNAME ", 9))
{
strncpy(myuser, buffer + 9, USERNAME_LENGTH);
myuser[USERNAME_LENGTH - 1] = '\0';
}
else if (!strncasecmp(buffer, "HOSTNAME ", 9))
{
strncpy(mysite, buffer + 9, SITE_LENGTH);
mysite[SITE_LENGTH - 1] = '\0';
}
else if (!strncasecmp(buffer, "REALNAME ", 9))
{
strncpy(myrealname, buffer + 9, REALNAME_LENGTH);
myrealname[REALNAME_LENGTH - 1] = '\0';
}
else if (!strncasecmp(buffer, "UPLINK ", 7))
{
strncpy(server, buffer + 7, SERVER_NAME_LENGTH);
server[SERVER_NAME_LENGTH - 1] = '\0';
}
else if (!strncasecmp(buffer, "PORT ", 5))
{
DEFAULT_PORTNUM = atoi(buffer + 5);
}
else if (!strncasecmp(buffer, "UMODE ", 6))
{
strncpy(UMODE, buffer + 6, 10);
UMODE[9] = '\0';
}
else if (!strncasecmp(buffer, "SERVERNAME ", 11))
{
strncpy(SERVERNAME, buffer + 11, 80);
SERVERNAME[79] = '\0';
}
else if (!strncasecmp(buffer, "SERVERINFO ", 11))
{
strncpy(SERVERINFO, buffer + 11, 80);
SERVERINFO[79] = '\0';
}
else if (!strncasecmp(buffer, "PASSWORD ", 9))
{
strncpy(PASSWORD, buffer + 9, 80);
PASSWORD[79] = '\0';
}
else if (!strncasecmp(buffer, "HOMEDIR ", 8))
{
strncpy(HOMEDIR, buffer + 8, 256);
HOMEDIR[255] = '\0';
}
else if (!strncasecmp(buffer, "UMASK ", 6))
{
sscanf(buffer + 6, "%d", &UMASK);
}
else if (!strncasecmp(buffer, "EXEC ", 5))
{
strncpy(EXEC_FILE, buffer + 5, 256);
EXEC_FILE[255] = '\0';
}
else if (!strncasecmp(buffer, "MOTD ", 5))
{
strncpy(MOTD_FILE, buffer + 5, 256);
MOTD_FILE[255] = '\0';
}
else if (!strncasecmp(buffer, "LOG ", 4))
{
strncpy(LOGFILE, buffer + 4, 256);
LOGFILE[255] = '\0';
}
else if (!strncasecmp(buffer, "LOGBAK ", 7))
{
strncpy(LOGFILEBAK, buffer + 7, 256);
LOGFILEBAK[255] = '\0';
}
else if (!strncasecmp(buffer, "PID ", 4))
{
strncpy(PIDFILE, buffer + 4, 256);
PIDFILE[255] = '\0';
}
else if (!strncasecmp(buffer, "HELPDIR ", 8))
{
strncpy(HELP_DIR, buffer + 8, 256);
HELP_DIR[255] = '\0';
}
else if (!strncasecmp(buffer, "MASTER_NICK ", 12))
{
strncpy(MASTER_REALNAME, buffer + 12, 80);
MASTER_REALNAME[79] = '\0';
}
else if (!strncasecmp(buffer, "MASTER_MASK ", 12))
{
strncpy(MASTER_MATCH, buffer + 12, 80);
MASTER_MATCH[79] = '\0';
}
else if (!strncasecmp(buffer, "MASTER_PASSWD ", 14))
{
strncpy(MASTER_PASSWD, buffer + 14, 20);
MASTER_PASSWD[19] = '\0';
}
else if (!strncasecmp(buffer, "BROADCAST ", 10))
{
strncpy(BROADCAST_CHANNEL, buffer + 10, 80);
BROADCAST_CHANNEL[79] = '\0';
}
else if (!strncasecmp(buffer, "VERIFYID ", 9))
{
strncpy(VERIFY_ID, buffer + 9, 256);
VERIFY_ID[255] = '\0';
}
else if (!strncasecmp(buffer, "UWORLD_NICK ", 12))
{
strncpy(UWORLD, buffer + 12, 10);
UWORLD[9] = '\0';
}
else if (!strncasecmp(buffer, "UWORLD_HOST ", 12))
{
strncpy(UWORLD_HOST, buffer + 12, 80);
UWORLD_HOST[79] = '\0';
}
else if (!strncasecmp(buffer, "UWORLD_SERVER ", 14))
{
strncpy(UWORLD_SERVER, buffer + 14, 80);
UWORLD_SERVER[79] = '\0';
}
else if (!strncasecmp(buffer, "UWORLD2_NICK ", 13))
{
strncpy(UWORLD2_NICK, buffer + 13, 10);
UWORLD2_NICK[9] = '\0';
}
else if (!strncasecmp(buffer, "UWORLD2_HOST ", 13))
{
strncpy(UWORLD2_HOST, buffer + 13, 80);
UWORLD2_HOST[79] = '\0';
}
else if (!strncasecmp(buffer, "UWORLD2_SERVER ", 15))
{
strncpy(UWORLD2_SERVER, buffer + 15, 80);
UWORLD2_SERVER[79] = '\0';
}
else if (!strncasecmp(buffer, "CALMDOWNTOPIC ", 14))
{
strncpy(CALMDOWNTOPIC, buffer + 14, 512);
CALMDOWNTOPIC[511] = '\0';
}
else if (!strncasecmp(buffer, "NSERV_NICK ", 11))
{
#ifdef NICKSERV
strncpy(NSERV_NICK, buffer + 11, 10);
NSERV_NICK[9] = '\0';
#endif
}
else if (!strncasecmp(buffer, "NSERV_USER ", 11))
{
#ifdef NICKSERV
strncpy(NSERV_USER, buffer + 11, 10);
NSERV_USER[9] = '\0';
#endif
}
else if (!strncasecmp(buffer, "NSERV_HOST ", 11))
{
#ifdef NICKSERV
strncpy(NSERV_HOST, buffer + 11, 80);
NSERV_HOST[79] = '\0';
#endif
}
else if (!strncasecmp(buffer, "NSERV_INFO ", 11))
{
#ifdef NICKSERV
strncpy(NSERV_INFO, buffer + 11, 200);
NSERV_INFO[199] = '\0';
#endif
}
else if (!strncasecmp(buffer, "NSERV_STAT ", 11))
{
#ifdef NICKSERV
if (!strncmp(buffer + 11, "on", 2))
NServ_status = 1;
else if (!strncmp(buffer + 11, "off", 3))
NServ_status = 0;
else
fprintf(stderr, "NSERV_STAT: Unknown value. Must be ON or OFF\n");
#endif
}
else
{
fprintf(stderr, "%s: Unknown keyword \"%s\"\n", conf, buffer);
}
}
fclose(fp);
}

696
Sources/connect.c Normal file
View File

@@ -0,0 +1,696 @@
/* @(#)$Id: connect.c,v 1.12 1998/01/25 18:35:42 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#ifndef FD_ZERO
#define FD_ZERO(set) (((set)->fds_bits[0]) = 0)
#define FD_SET(s1, set) (((set)->fds_bits[0]) |= 1 << (s1))
#define FD_ISSET(s1, set) (((set)->fds_bits[0]) & (1 << (s1)))
#define FD_SETSIZE 30
#endif
int read_from_server(int);
int write_to_server(irc_socket *);
int connection(char *serv)
{
char buffer[200];
int portnum;
char *ptr;
struct sockaddr_in socketname;
#ifdef BINDADDR
struct sockaddr_in myname;
#endif
struct hostent *remote_host;
if ((ptr = strchr(serv, ':')) != NULL)
{
*(ptr++) = 0;
sscanf(ptr, "%d", &portnum);
#ifdef DEBUG
printf("Server: %s\nPort: %d\n", serv, portnum);
#endif
}
else
{
portnum = DEFAULT_PORTNUM;
}
sprintf(buffer, "CONNECTING TO %s ON PORT %d", serv, portnum);
log(buffer);
if (Irc.outbuf)
zap_buffer(&Irc.outbuf);
if (Irc.inbuf)
zap_buffer(&Irc.inbuf);
read_from_server(1); /* reset input buffer */
now = time(NULL);
/* open an inet socket */
if ((Irc.fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
#ifdef DEBUG
fprintf(stderr, "ERROR: Can't assign fd for socket, darn!\n");
#endif
log("ERROR ASSIGNING FD FOR SOCKET");
exit(1);
}
#ifdef BINDADDR
memset(&myname, 0, sizeof(myname));
myname.sin_family = AF_INET;
myname.sin_port = 0;
myname.sin_addr.s_addr = inet_addr(BINDADDR);
if (bind(Irc.fd, (struct sockaddr *)&myname, sizeof(myname)) < 0)
{
#ifdef DEBUG
fprintf(stderr, "ERROR: Can't bind local address %s\n", BINDADDR);
#endif
log("Can't bind local address");
log(BINDADDR);
exit(1);
}
#endif
/* make it non-blocking */
fcntl(Irc.fd, F_SETFL, O_NONBLOCK);
/* lookup host */
socketname.sin_family = AF_INET;
if ((remote_host = gethostbyname(serv)) == NULL)
{
#ifdef DEBUG
fprintf(stderr, "ERROR: Host %s is unknown, wtf?\n", serv);
#endif
log("ERROR: BULLSHIT HOST!");
exit(1);
}
memcpy((void *)&socketname.sin_addr, (void *)remote_host->h_addr, remote_host->h_length);
socketname.sin_port = htons(portnum);
/* connect socket */
if (connect(Irc.fd, (struct sockaddr *)&socketname, sizeof(socketname)) < 0
&& errno != EINPROGRESS)
{
close(Irc.fd);
Irc.fd = -1;
#ifdef DEBUG
printf("ERROR: connect() %d: %s\n", errno, strerror(errno));
#endif
log("ERROR: COULDN'T CONNECT");
return (1);
}
TSconnect = Irc.TS = now = time(NULL);
errno = 0;
return 0;
}
int wait_msg(void)
{
fd_set readfds, writefds;
struct timeval timeout;
static int pingflag = 0;
int maxfd = -1;
int to;
#ifdef DOHTTP
void http_log(char *fmt,...);
register http_socket *hsock, *hsocktmp;
register http_file_pipe *fpipe, *fpipetmp;
#endif
#ifdef UPGRADE
register misc_socket *msock, *msocktmp;
#endif
register dbquery **dq, *dqtmp;
register dbsync **ds, *dstmp;
/* initialize the fd_sets
*/
FD_ZERO(&readfds);
FD_ZERO(&writefds);
/* set timeout
*/
if (EventList != NULL)
{
to = EventList->time - now;
if (to < PING_FREQ)
timeout.tv_sec = (to > 0) ? to : 0;
else
timeout.tv_sec = PING_FREQ;
}
else
{
timeout.tv_sec = PING_FREQ;
}
timeout.tv_usec = 0;
/* Check the DBQuery list before the server fd because
* end_db_read() might writing something in the server's
* buffer.
*/
dq = &DBQuery;
while (*dq)
{
if ((*dq)->fd < 0)
{
dqtmp = *dq;
*dq = (*dq)->next;
end_db_read(dqtmp);
free(dqtmp);
}
else
{
if ((*dq)->fd > maxfd)
maxfd = (*dq)->fd;
FD_SET((*dq)->fd, &readfds);
dq = &(*dq)->next;
}
}
ds = &DBSync;
while (*ds)
{
if ((*ds)->fd < 0)
{
dstmp = *ds;
*ds = (*ds)->next;
end_db_sync(dstmp);
free(dstmp);
}
else
{
if ((*ds)->fd > maxfd)
maxfd = (*ds)->fd;
if ((*ds)->status == SYNC_PENDWRITE)
FD_SET((*ds)->fd, &writefds);
else
FD_SET((*ds)->fd, &readfds);
ds = &(*ds)->next;
}
}
/* check if the uplink's socket is ready for reading..
*/
FD_SET(Irc.fd, &readfds);
/* check if the uplink's socket is ready for writing only if
* we have something to write
*/
if (Irc.outbuf != NULL)
FD_SET(Irc.fd, &writefds);
if (Irc.fd > maxfd)
maxfd = Irc.fd;
#ifdef DOHTTP
fpipe = FilePipes;
while (fpipe != NULL)
{
if (fpipe->fd > maxfd)
maxfd = fpipe->fd;
FD_SET(fpipe->fd, &readfds);
fpipe = fpipe->next;
}
hsock = HttpList;
while (hsock != NULL)
{
if (hsock->fd < 0 || hsock->status == HTTP_ERROR)
{
hsock = hsock->next; /* am I an idiot or what? -Kev */
continue; /* you should see the logs from below! -Kev */
}
if (hsock->fd > maxfd)
maxfd = hsock->fd;
if (hsock->status != HTTP_LISTEN &&
hsock->status != HTTP_CHAT &&
hsock->since + 2 * HTTP_TIMEOUT < now)
{
http_log("ERROR: absolute timeout for fd %d (%d)",
hsock->fd, hsock->status);
close(hsock->fd);
hsock->fd = -1;
hsock->status = HTTP_ERROR;
}
if (hsock->status != HTTP_LISTEN &&
hsock->status != HTTP_CHAT &&
hsock->TS + HTTP_TIMEOUT < now)
{
close(hsock->fd);
hsock->fd = -1;
hsock->status = HTTP_ERROR;
}
if (hsock->status == HTTP_ENDING &&
hsock->outbuf == NULL)
{
close(hsock->fd);
hsock->fd = -1;
hsock->status = HTTP_ERROR;
}
if (hsock->status != HTTP_ERROR)
{
if (hsock->status != HTTP_ENDING &&
hsock->status != HTTP_PIPE)
FD_SET(hsock->fd, &readfds);
if (hsock->outbuf != NULL)
FD_SET(hsock->fd, &writefds);
}
hsock = hsock->next;
}
#endif
#ifdef UPGRADE
msock = MiscList;
while (msock != NULL)
{
if (msock->fd > maxfd)
maxfd = msock->fd;
if (msock->TS + MISC_TIMEOUT < now)
{
close(msock->fd);
msock->fd = -1;
msock->status = MISC_ERROR;
notice(msock->link, "connection timeout!");
}
if (msock->status != MISC_ERROR)
{
FD_SET(msock->fd, &readfds);
if (msock->outbuf != NULL)
FD_SET(msock->fd, &writefds);
}
msock = msock->next;
}
#endif
/* Wait till the socket is ready for reading
* and/or writing and/or a timeout
*/
if (select(maxfd + 1, &readfds, &writefds, NULL, &timeout) < 0)
{
log("ERROR: select()");
log((char *)sys_errlist[errno]);
return (-1);
}
now = time(NULL);
/* The uplink's socket is ready for reading... */
if (FD_ISSET(Irc.fd, &readfds))
{
if (read_from_server(0) < 0)
{
log("ERROR: in read_from_server()");
return (-1);
}
pingflag = 0;
Irc.TS = now;
}
/* The uplink's socket is ready for writing... */
if (FD_ISSET(Irc.fd, &writefds))
{
if (write_to_server(&Irc) < 0)
{
log("ERROR: in write_to_server()");
return (-1);
}
}
#ifdef DOHTTP
fpipe = FilePipes;
while (fpipe != NULL)
{
fpipetmp = fpipe;
fpipe = fpipe->next;
if (FD_ISSET(fpipetmp->fd, &readfds))
{
readfrom_file(fpipetmp);
}
}
hsock = HttpList;
while (hsock != NULL)
{
while (hsock != NULL && hsock->status == HTTP_ERROR)
{
hsocktmp = hsock;
hsock = hsock->next;
remove_httpsock(hsocktmp);
}
if (hsock == NULL)
break;
if (hsock->fd >= 0 && FD_ISSET(hsock->fd, &readfds))
{
if (hsock->status == HTTP_LISTEN)
{
http_accept(hsock->fd);
}
else
{
readfrom_http(hsock);
hsock->TS = now;
}
}
if (hsock->fd >= 0 && FD_ISSET(hsock->fd, &writefds))
{
if (flush_http_buffer(hsock) != -1)
hsock->TS = now;
if (hsock->status == HTTP_ENDING && hsock->outbuf == NULL)
{
close(hsock->fd);
hsock->fd = -1;
hsock->status = HTTP_ERROR;
}
}
hsock = hsock->next;
}
#endif
#ifdef UPGRADE
msocktmp = NULL;
msock = MiscList;
while (msock != NULL)
{
while (msock != NULL && msock->status == MISC_ERROR)
{
if (msocktmp == NULL)
{
MiscList = msock->next;
free(msock);
msock = MiscList;
}
else
{
msocktmp->next = msock->next;
free(msock);
msock = msocktmp->next;
}
}
if (msock == NULL)
break;
if (msock->fd >= 0 && FD_ISSET(msock->fd, &readfds))
{
readfrom_misc(msock);
msock->TS = now;
}
if (msock->fd >= 0 && FD_ISSET(msock->fd, &writefds))
{
if (flush_misc_buffer(msock) != -1)
msock->TS = now;
}
msocktmp = msock;
msock = msock->next;
}
#endif
dqtmp = DBQuery;
while (dqtmp)
{
if (FD_ISSET(dqtmp->fd, &readfds))
read_db(dqtmp);
dqtmp = dqtmp->next;
}
dstmp = DBSync;
while (dstmp)
{
if (FD_ISSET(dstmp->fd, &readfds) || FD_ISSET(dstmp->fd, &writefds))
db_sync_ready(dstmp);
dstmp = dstmp->next;
}
if (EventList != NULL && now >= EventList->time)
CheckEvent();
/* send a PING to the server if nothing is received within
* PING_FREQ seconds... if yet nothing arrives within 3 * PING_FREQ
* seconds it's a ping timeout and the connection should be closed
*/
if ((now - Irc.TS) >= (3 * PING_FREQ + 1))
{
log("Errr PING TIMEOUT");
#ifdef DEBUG
printf("Ping timeout..\n");
#endif
sendtoserv("ERROR :Connection timeout\n");
return (-1);
}
else if (pingflag == 0 && (now - Irc.TS) >= (PING_FREQ - 1))
{
sendtoserv("PING :");
sendtoserv(SERVERNAME);
sendtoserv("\n");
pingflag = 1;
}
if (DB_Save_Status != -1)
do_cold_sync_slice();
return 0;
}
void sendtoserv(char *msg)
{
#ifdef DEBUG
printf("#OUT#%s", msg);
#endif
CurrentSendQ = copy_to_buffer(&Irc.outbuf, msg, strlen(msg));
if (CurrentSendQ > MAX_SENDQ)
{
log("ERROR: Reached MAX_SENDQ!!!");
zap_buffer(&Irc.outbuf);
close(Irc.fd);
exit(-1);
}
}
void dumpbuff(void)
{
if (Irc.fd < 0)
return;
/* remove the O_NONBLOCK flag */
fcntl(Irc.fd, F_SETFL, 0);
write_to_server(&Irc);
if (Irc.fd >= 0)
/* reset the O_NONBLOCK flag */
fcntl(Irc.fd, F_SETFL, O_NONBLOCK);
}
int read_from_server(int reset)
{
static char inbuff[1025] = "";
static char source[SERVER_NAME_LENGTH] = "";
static char function[10] = "";
static char target[513] = "";
static char body[513] = "";
static int in_pos = 0;
static int in_offset = 0;
static int length = 0;
char *inchar;
int end;
#ifdef HISTORY
char buffer[600];
#endif
if (reset)
{
*inbuff = *source = *function = *target = *body = '\0';
in_pos = in_offset = length = 0;
return 0;
}
#ifdef DEBUG
printf("#IN#");
#endif
end = 1;
while (end > 0)
{
errno = 0;
if ((length = read(Irc.fd, inbuff, 1024)) <= 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN || length == 0)
{
end = 0;
}
else
{
end = -1;
in_pos = in_offset = 0;
*source = *function = *target = *body = '\0';
#ifdef DEBUG
printf("Read error.. not EWOULDBLOCK!\n");
#endif
}
return (end);
}
TTLREADBYTES += length;
inchar = inbuff;
while (length--)
{
#ifdef DEBUG
putchar(*inchar);
#endif
if (*inchar != '\n' && *inchar != '\r')
{
if (*inchar == ' ' && in_pos < 3)
{
switch (in_pos)
{
case 0:
source[in_offset] = '\0';
break;
case 1:
function[in_offset] = '\0';
break;
case 2:
target[in_offset] = '\0';
break;
default:
exit(1);
}
in_pos++;
in_offset = 0;
}
else
{
switch (in_pos)
{
case 0:
if (in_offset == 0 && *inchar != ':')
{
source[0] = '\0';
in_pos++;
function[in_offset++] = *inchar;
}
else
source[in_offset++] = *inchar;
break;
case 1:
function[in_offset++] = *inchar;
break;
case 2:
target[in_offset++] = *inchar;
break;
case 3:
body[in_offset++] = *inchar;
break;
default: /*shouldn't happen */
exit(1);
}
}
}
if (*inchar == '\n')
{
if (in_pos >= 3)
body[in_offset] = '\0';
else
{
body[0] = '\0';
switch (in_pos)
{
case 2:
target[in_offset] = '\0';
break;
case 1:
function[in_offset] = '\0';
break;
case 0:
source[in_offset] = '\0';
default:
break;
}
}
/* parse the received line */
#ifdef HISTORY
sprintf(buffer, "%s %s %s %s", source, function, target, body);
History(buffer);
#endif
proc(source, function, target, body);
in_pos = in_offset = end = 0;
*source = *function = *target = *body = '\0';
}
inchar++;
} /* while */
} /*while */
return 1;
}
int write_to_server(irc_socket * isock)
{
char buf[1024];
int length;
int count;
if (isock == NULL || isock->outbuf == NULL)
return -1;
while ((count = look_in_buffer(&isock->outbuf, buf, '\0', 1023)) > 0)
{
if ((length = write(isock->fd, buf, count)) <= 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN)
{
return 0;
}
else
{
close(isock->fd);
isock->fd = -1;
return -1;
}
}
else
{
TTLSENTBYTES += length;
CurrentSendQ -= length;
skip_char_in_buffer(&isock->outbuf, length);
}
}
return 0;
}

755
Sources/dbio.c Normal file
View File

@@ -0,0 +1,755 @@
/* @(#)$Id: dbio.c,v 1.12 1998/01/02 18:30:08 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
char *make_dbfname(char *channel)
{
static char fname[600];
char tmp[600];
register char *ptr;
strcpy(tmp, channel);
for (ptr = tmp; *ptr; ptr++)
{
if (*ptr == '/')
*ptr = ' ';
else
*ptr = tolower(*ptr);
}
sprintf(fname, "db/channels/%04X/%s", ul_hash(channel), tmp);
return fname;
}
/* db_query()
* This is used to *retreive* information from the database.
* The arguments are:
* channel := channel name (null terminated string)
* type := query type, either of:
* DBGETNICK (Get entry by nick)
* DBGET1STUH (Get first matching userhost)
* DBGETALLUH (Get all matching userhosts)
* DBCOUNTUH (Count the number of matching userhosts)
* ...
* info := Either a nick or a userhost depending on type
* action := value passed to the callback function
* hook1 := pointer passed to the callback function
* hook2 := pointer passed to the callback function
* callback := callback function
*
* Since the database is accessed asychronously, 'hook' should not point to
* a structure that can be free()'d by a function other than callback,
* e.g. a pointer to a luser structure.
*/
int db_fetch(char *channel, unsigned int type, char *info, char *passwd,
int action, void *hook1, void *hook2, DBCALLBACK(callback))
{
dbquery *new;
int fd;
if ((fd = open(make_dbfname(channel), O_RDONLY | O_NONBLOCK)) < 0)
{
callback(&fd, (off_t) 0, action, hook1, hook2, NULL, 0);
return -1; /* caller can check errno to see want happened */
}
new = (dbquery *) malloc(sizeof(dbquery));
new->fd = fd;
new->offset = (off_t) 0;
new->time = now;
new->type = type;
new->action = action;
new->count = 0;
new->callback = callback;
new->buf = NULL;
new->hook1 = hook1;
new->hook2 = hook2;
strcpy(new->info, info);
strncpy(new->channel, channel, 79);
new->channel[79] = '\0';
if (passwd)
strcpy(new->passwd, passwd);
else
new->passwd[0] = '\0';
new->next = DBQuery;
DBQuery = new;
return 0;
}
/* fix_db()
* Remove db entries that are not in the right file.
*/
static void fix_db(char *channel, off_t offset)
{
register RegUser *reg;
register int idx;
idx = ul_hash(channel);
/* check if already taken care of */
reg = UserList[idx];
while (reg != NULL && (reg->offset != offset || strcasecmp(reg->channel, channel)))
reg = reg->next;
if (reg) /* already there.. disregard */
return;
reg = (RegUser *) MALLOC(sizeof(RegUser));
memset(reg, 0, sizeof(RegUser));
reg->realname = (char *)MALLOC(6);
strcpy(reg->realname, "!DEL!");
reg->passwd = (char *)MALLOC(1);
*reg->passwd = '\0';
reg->match = (char *)MALLOC(6);
strcpy(reg->match, "!DEL!");
reg->channel = (char *)MALLOC(strlen(channel) + 1);
strcpy(reg->channel, channel);
reg->modif = (char *)MALLOC(1);
*reg->modif = '\0';
reg->modified = 1;
reg->offset = offset;
reg->next = UserList[idx];
UserList[idx] = reg;
}
/* read_db()
* This should be called from the select() loop. Data is read sequentially
* and the query is processed according to 'type'.
*/
void read_db(dbquery * query)
{
struct dbuser buffer[11];
int size, status, end = 0;
size = read(query->fd, buffer, 10 * sizeof(dbuser));
if (size <= 0)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
{
close(query->fd);
query->fd = -1;
}
return;
}
copy_to_buffer(&query->buf, (char *)buffer, size);
while (!end && look_in_buffer(&query->buf, (char *)buffer, '\0', sizeof(dbuser))
== sizeof(dbuser))
{
if (buffer[0].header[0] == 0xFF && buffer[0].header[1] == 0xFF &&
buffer[0].footer[0] == 0xFF && buffer[0].footer[1] == 0xFF)
{
status = 1; /* block is used */
}
else if (buffer[0].header[0] == 0x00 && buffer[0].header[1] == 0x00 &&
buffer[0].footer[0] == 0x00 && buffer[0].footer[1] == 0x00)
{
status = 0; /* block is free */
}
else
{
status = -1; /* block has been written to while reading it */
}
if (status == 1 && strcasecmp(query->channel, buffer[0].channel))
{
fix_db(query->channel, query->offset);
skip_char_in_buffer(&query->buf, sizeof(dbuser));
query->offset += sizeof(dbuser);
continue;
}
#ifdef DEBUG
printf("hdr: %X%X nick: %s match: %s passwd: %s channel: %s "
"modif: %s access: %d flags: %ld susp: %ld last: %ld ftr: %X%X"
"sta: %d\n",
buffer[0].header[0], buffer[0].header[1], buffer[0].nick, buffer[0].match, buffer[0].passwd,
buffer[0].channel, buffer[0].modif, buffer[0].access, buffer[0].flags, buffer[0].suspend,
buffer[0].lastseen, buffer[0].footer[0], buffer[0].footer[1], status);
#endif
switch (query->type)
{
case DBGETNICK:
if (status == 1 && !strcasecmp(buffer[0].nick, query->info))
{
close(query->fd);
query->fd = -1;
query->count++;
query->callback(&query->fd, query->offset, query->action, query->hook1,
query->hook2, buffer, query->count);
end = 1;
}
break;
case DBGET1STUH:
if (status == 1 && match(query->info, buffer[0].match))
{
close(query->fd);
query->fd = -1;
query->count++;
query->callback(&query->fd, query->offset, query->action, query->hook1,
query->hook2, buffer, query->count);
end = 1;
}
break;
case DBGETALLUH:
if (status == 1 && match(query->info, buffer[0].match))
{
query->count++;
query->callback(&query->fd, query->offset, query->action, query->hook1,
query->hook2, buffer, query->count);
}
break;
case DBGETUHPASS:
if (status == 1 && match(query->info, buffer[0].match) &&
!strcmp(query->passwd, buffer[0].passwd))
{
close(query->fd);
query->fd = -1;
query->count++;
query->callback(&query->fd, query->offset, query->action, query->hook1,
query->hook2, buffer, query->count);
end = 1;
}
break;
case DBCOUNTUH:
if (status == 1 && match(query->info, buffer[0].match))
{
query->count++;
}
break;
case DBGET1STCMP:
if (status == 1 && (!*query->info || compare(query->info, buffer[0].match)))
{
close(query->fd);
query->fd = -1;
query->count++;
query->callback(&query->fd, query->offset, query->action, query->hook1,
query->hook2, buffer, query->count);
end = 1;
}
break;
case DBGETALLCMP:
if (status == 1 && (!*query->info || compare(query->info, buffer[0].match)))
{
query->count++;
query->callback(&query->fd, query->offset, query->action, query->hook1,
query->hook2, buffer, query->count);
}
break;
case DBCNTCMP:
if (status == 1 && (!*query->info || compare(query->info, buffer[0].match)))
{
query->count++;
}
break;
case DBGET1STFREE:
if (status == 0)
{
close(query->fd);
query->fd = -1;
query->count++;
query->callback(&query->fd, query->offset, query->action, query->hook1,
query->hook2, buffer, query->count);
end = 1;
}
break;
}
skip_char_in_buffer(&query->buf, sizeof(dbuser));
query->offset += sizeof(dbuser);
if (query->fd < 0)
end = 1;
}
}
void end_db_read(dbquery * query)
{
zap_buffer(&query->buf);
query->callback(&query->fd, query->offset, query->action, query->hook1,
query->hook2, NULL, query->count);
}
void make_dbuser(RegUser * reg, dbuser * dbu)
{
memset(dbu, 0, sizeof(dbuser));
if (reg->access != 0)
{
strncpy(dbu->nick, reg->realname, 79);
dbu->nick[79] = '\0';;
strncpy(dbu->match, reg->match, 79);
dbu->match[79] = '\0';
strncpy(dbu->channel, reg->channel, 49);
dbu->channel[49] = '\0';
strncpy(dbu->passwd, reg->passwd, 19);
dbu->passwd[19] = '\0';
strncpy(dbu->modif, reg->modif, 79);
dbu->modif[79] = '\0';
dbu->access = reg->access;
dbu->flags = reg->flags;
dbu->suspend = reg->suspend;
dbu->lastseen = reg->lastseen;
dbu->header[0] = 0xFF;
dbu->header[1] = 0xFF;
dbu->footer[0] = 0xFF;
dbu->footer[1] = 0xFF;
}
}
void sync_next_channel(void)
{
register syncchan *tmp;
if ((tmp = SyncChan) != NULL)
{
SyncChan = SyncChan->next;
db_sync(tmp->name);
free(tmp);
}
}
static void set_sync(dbsync * sync)
{
struct dbuser dbu;
if (*sync->reg == NULL)
{
close(sync->fd);
sync->fd = -1;
return;
}
if ((*sync->reg)->access == 0) /* delete */
{
make_dbuser(*sync->reg, &dbu);
zap_buffer(&sync->buf);
copy_to_buffer(&sync->buf, (char *)&dbu, sizeof(dbuser));
sync->type = SYNC_DELETE;
sync->status = SYNC_PENDWRITE;
sync->offset = (*sync->reg)->offset;
lseek(sync->fd, (*sync->reg)->offset, SEEK_SET);
}
else if ((*sync->reg)->offset != (off_t) - 1) /* update */
{
make_dbuser(*sync->reg, &dbu);
zap_buffer(&sync->buf);
copy_to_buffer(&sync->buf, (char *)&dbu, sizeof(dbuser));
sync->type = SYNC_UPDATE;
sync->status = SYNC_PENDWRITE;
sync->offset = (*sync->reg)->offset;
lseek(sync->fd, (*sync->reg)->offset, SEEK_SET);
}
else
/* add */
{
sync->type = SYNC_ADD;
sync->status = SYNC_SEEKFREE;
sync->offset = (off_t) 0;
lseek(sync->fd, 0L, SEEK_SET);
}
}
static void sync_next(dbsync * sync, char *channel)
{
register RegUser **reg = sync->reg;
if (*reg == NULL)
{
close(sync->fd);
sync->fd = -1;
return;
}
while (*reg != NULL && ((*reg)->modified == 0 || (*reg)->access == 1000 ||
strcasecmp((*reg)->channel, channel)))
{
if ((*reg)->inuse == 0 && (*reg)->lastused + CACHE_TIMEOUT < now)
free_user(reg);
else
reg = &(*reg)->next;
}
sync->time = now;
sync->reg = reg;
set_sync(sync);
}
void db_sync(char *channel)
{
register RegUser **reg, *tmp;
register char *ch;
register dbsync *sync;
struct stat st;
int fd;
#ifdef DEBUG
printf("SYNC: %s\n", channel);
#endif
if (DBSync != NULL && (DBSync->fd != -1 || DBSync->next != NULL))
{
log("ERROR: simultaneous syncs??");
return;
}
ch = make_dbfname(channel);
/* IF file does not exist.. remove all deletes and mark
* all other entries as new.
*/
if (stat(ch, &st) < 0)
{
/* remove all deletes */
reg = &UserList[ul_hash(channel)];
while (*reg)
{
(*reg)->offset = (off_t) - 1;
if ((*reg)->access == 0 && (*reg)->inuse == 0 &&
!strcasecmp((*reg)->channel, channel))
{
tmp = *reg;
*reg = (*reg)->next;
free_user(reg);
}
else
reg = &(*reg)->next;
}
fd = open(ch, O_RDWR | O_CREAT | O_EXCL | O_NONBLOCK, 0600);
}
else
{
fd = open(ch, O_RDWR | O_NONBLOCK);
}
/* create new sync struct
*/
sync = (dbsync *) malloc(sizeof(dbsync));
sync->fd = fd;
sync->reg = &UserList[ul_hash(channel)];
sync->buf = NULL;
sync->next = DBSync;
DBSync = sync;
sync_next(sync, channel);
}
void db_sync_ready(dbsync * sync)
{
struct dbuser buffer[10];
register RegUser **reg = sync->reg;
int size;
#ifdef DEBUG
printf("SYNC_READY: status= %d\n", sync->status);
#endif
if (sync->status == SYNC_PENDWRITE)
{
size = look_in_buffer(&sync->buf, (char *)buffer, '\0', sizeof(dbuser));
if (size == 0)
zap_buffer(&sync->buf);
if (sync->buf == NULL)
{
if ((*reg)->access == 0 && (*reg)->inuse == 0)
free_user(reg);
else
(*reg)->modified = 0;
sync_next(sync, (*reg)->channel);
return;
}
#ifdef DEBUG
printf("PENDWRITE: %d bytes to write...", size);
#endif
size = write(sync->fd, buffer, size);
#ifdef DEBUG
printf("%d written\n", size);
#endif
if (size <= 0)
{
if (errno != EWOULDBLOCK && errno != EAGAIN)
{
close(sync->fd);
sync->fd = -1;
}
return;
}
skip_char_in_buffer(&sync->buf, size);
}
else if (sync->status == SYNC_SEEKFREE)
{
size = read(sync->fd, buffer, 10 * sizeof(dbuser));
if (size <= 0)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
{
make_dbuser(*sync->reg, buffer);
zap_buffer(&sync->buf);
copy_to_buffer(&sync->buf, (char *)buffer, sizeof(dbuser));
sync->status = SYNC_PENDWRITE;
lseek(sync->fd, 0L, SEEK_END);
}
return;
}
copy_to_buffer(&sync->buf, (char *)buffer, size);
while (look_in_buffer(&sync->buf, (char *)buffer, '\0', sizeof(dbuser))
== sizeof(dbuser))
{
if (buffer[0].header[0] == 0x00 && buffer[0].header[1] == 0x00 &&
buffer[0].footer[0] == 0x00 && buffer[0].footer[1] == 0x00)
{
make_dbuser(*sync->reg, buffer);
zap_buffer(&sync->buf);
copy_to_buffer(&sync->buf, (char *)buffer, sizeof(dbuser));
sync->status = SYNC_PENDWRITE;
(*sync->reg)->offset = sync->offset;
lseek(sync->fd, sync->offset, SEEK_SET);
return;
}
skip_char_in_buffer(&sync->buf, sizeof(dbuser));
sync->offset += sizeof(dbuser);
}
}
}
void end_db_sync(dbsync * sync)
{
#ifdef DEBUG
printf("SYNC_END\n");
#endif
sync_next_channel();
return;
}
void cold_save_one(RegUser * reg)
{
struct stat st;
dbuser dbu;
char *fname;
register int fd;
off_t off;
fname = make_dbfname(reg->channel);
if (stat(fname, &st) < 0) /* file doesn't exist -- don't save delete */
{
if (reg->access == 0)
return;
fd = open(fname, O_RDWR | O_CREAT, 0600);
}
else
fd = open(fname, O_RDWR | O_EXCL);
if (fd < 0) /* hmmm? */
return;
if (reg->offset == (off_t) - 1) /* new ==> seek for empty slot */
{
lseek(fd, 0L, SEEK_SET);
off = (off_t) 0;
while (read(fd, &dbu, sizeof(dbuser)) == sizeof(dbuser))
{
if (dbu.header[0] == 0x00 && dbu.header[1] == 0x00 &&
dbu.footer[0] == 0x00 && dbu.footer[1] == 0x00)
break; /* found empty slot */
off += sizeof(dbuser);
}
}
else
off = reg->offset;
lseek(fd, off, SEEK_SET); /* go to write position */
if (reg->access != 0)
make_dbuser(reg, &dbu);
else
memset(&dbu, 0, sizeof(dbuser));
write(fd, &dbu, sizeof(dbuser));
if (reg->access != 0)
reg->offset = off;
else
reg->offset = (off_t) - 1;
reg->modified = 0;
close(fd);
}
void do_cold_sync_slice(void)
{
register RegUser **reg;
if (DB_Save_Status < 0)
return;
reg = &UserList[DB_Save_Status];
while (*reg != NULL)
{
if ((*reg)->modified && (*reg)->access < 1000)
cold_save_one(*reg);
if ((*reg)->inuse == 0 && (*reg)->access < 1000 &&
((*reg)->access == 0 || (*reg)->lastused + CACHE_TIMEOUT < now))
free_user(reg);
else
reg = &(*reg)->next;
}
if (++DB_Save_Status == 1000)
{
DB_Save_Status = -1;
if (*DB_Save_Nick)
notice(DB_Save_Nick, "Userlist sync complete!");
}
}
void do_cold_sync(void)
{
register dbsync *sync;
register syncchan *schan;
register RegUser **reg;
register int i;
char buffer[200];
/* SET AWAY MESSAGE */
sprintf(buffer, ":%s AWAY :Busy saving precious user list\n", mynick);
sendtoserv(buffer);
dumpbuff();
/* First, cancel *all* sync requests */
while ((sync = DBSync) != NULL)
{
DBSync = DBSync->next;
if (sync->fd >= 0)
close(sync->fd);
zap_buffer(&sync->buf);
free(sync);
}
/* Also, clear *all* pending syncs */
while ((schan = SyncChan) != NULL)
{
SyncChan = SyncChan->next;
free(schan);
}
/* Now, go thru *all* the user entries in memory and save them
* to their respective files.
*/
for (i = 0; i < 1000; i++)
{
reg = &UserList[i];
while (*reg != NULL)
{
if ((*reg)->modified && (*reg)->access < 1000)
cold_save_one(*reg);
if ((*reg)->inuse == 0 && (*reg)->access < 1000 &&
((*reg)->access == 0 || (*reg)->lastused + CACHE_TIMEOUT < now))
free_user(reg);
else
reg = &(*reg)->next;
}
}
sprintf(buffer, ":%s AWAY\n", mynick);
sendtoserv(buffer);
}
#ifdef DEBUG
void db_test_callback(int *fd, off_t off, int action, void *hook1, void *hook2,
dbuser * dbu, int count)
{
char buffer[512];
sprintf(buffer, "off: %ld act: %d hook=%p cnt: %d", off, action, hook1, count);
notice((char *)hook1, buffer);
if (dbu)
{
sprintf(buffer, "hdr: %X%X nick: %s match: %s passwd: %s channel: %s "
"modif: %s access: %d flags: %ld susp: %ld last: %ld ftr: %X%X",
dbu->header[0], dbu->header[1], dbu->nick, dbu->match, dbu->passwd,
dbu->channel, dbu->modif, dbu->access, dbu->flags, dbu->suspend,
dbu->lastseen, dbu->footer[0], dbu->footer[1]);
notice((char *)hook1, buffer);
}
else
{
notice((char *)hook1, "End.");
free(hook1);
}
}
void db_test(char *source, char *chan, char *args)
{
char channel[80], type[80], info[80], *hook;
GetWord(0, args, channel);
GetWord(1, args, type);
GetWord(2, args, info);
hook = (char *)malloc(strlen(source) + 1);
strcpy(hook, source);
if (!strcmp(type, "nick"))
db_fetch(channel, DBGETNICK, info, NULL, 0, hook, NULL, db_test_callback);
else if (!strcmp(type, "alluh"))
db_fetch(channel, DBGETALLUH, info, NULL, 0, hook, NULL, db_test_callback);
else if (!strcmp(type, "1stuh"))
db_fetch(channel, DBGET1STUH, info, NULL, 0, hook, NULL, db_test_callback);
else if (!strcmp(type, "count"))
db_fetch(channel, DBCOUNTUH, info, NULL, 0, hook, NULL, db_test_callback);
else if (!strcmp(type, "1stcmp"))
db_fetch(channel, DBGET1STCMP, info, NULL, 0, hook, NULL, db_test_callback);
else if (!strcmp(type, "allcmp"))
db_fetch(channel, DBGETALLCMP, info, NULL, 0, hook, NULL, db_test_callback);
else if (!strcmp(type, "cntcmp"))
db_fetch(channel, DBCNTCMP, info, NULL, 0, hook, NULL, db_test_callback);
else if (!strcmp(type, "sync"))
db_sync(channel);
}
#endif

43
Sources/dbio.h Normal file
View File

@@ -0,0 +1,43 @@
/* @(#)$Id: dbio.h,v 1.3 1996/11/13 00:40:36 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#define DBGETNICK 0x00000001
#define DBGET1STUH 0x00000002
#define DBGETALLUH 0x00000004
#define DBCOUNTUH 0x00000008
#define DBGET1STCMP 0x00000010
#define DBGETALLCMP 0x00000020
#define DBCNTCMP 0x00000040
#define DBGETUHPASS 0x00000080
#define DBGET1STFREE 0x00000100
#define SYNC_UPDATE 0x00000001
#define SYNC_DELETE 0x00000002
#define SYNC_ADD 0x00000004
#define SYNC_PENDWRITE 0x00000001
#define SYNC_SEEKFREE 0x00000002

70
Sources/debug.c Normal file
View File

@@ -0,0 +1,70 @@
/* @(#)$Id: debug.c,v 1.3 1996/11/13 00:40:36 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#ifdef DEBUG_MALLOC
#include <stdarg.h>
#undef malloc
#undef free
static FILE *debug_malloc_file;
void open_debug_malloc(void)
{
debug_malloc_file=fopen("malloc.log","w");
}
void close_debug_malloc(void)
{
fclose(debug_malloc_file);
}
void log_malloc(char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
vfprintf(debug_malloc_file,fmt,ap);
va_end(ap);
}
void *debug_malloc(char *file, int line, size_t size)
{
register void *ptr;
ptr=malloc(size);
log_malloc("%s(%d):malloc(%ld)= %p\n",file,line,(long)size,ptr);
return ptr;
}
void debug_free(char *file, int line, void *ptr)
{
log_malloc("%s(%d):free(%p)\n",file,line,ptr);
free(ptr);
}
#endif

37
Sources/debug.h Normal file
View File

@@ -0,0 +1,37 @@
/* @(#)$Id: debug.h,v 1.3 1996/11/13 00:40:37 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#ifdef DEBUG_MALLOC
void open_debug_malloc(void);
void close_debug_malloc(void);
void *debug_malloc(char *,int,size_t);
void debug_free(char *,int,void *);
#define malloc(X) debug_malloc(__FILE__,__LINE__,X)
#define free(X) debug_free(__FILE__,__LINE__,X)
#endif

493
Sources/defchan.c Normal file
View File

@@ -0,0 +1,493 @@
/* @(#)$Id: defchan.c,v 1.7 1999/12/19 16:33:13 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#define FORMATNO 0x02
typedef struct adefchan0 {
char name[50];
char mode[80];
char reserved[20];
int MassDeopPro;
int NickFloodPro;
int MsgFloodPro;
time_t TS;
unsigned long flags;
unsigned long uflags;
struct adefchan *next;
} adefchan0;
typedef struct adefchan1 {
char name[50];
char mode[80];
int MassDeopPro;
int NickFloodPro;
int MsgFloodPro;
int lang;
time_t TS;
unsigned long flags;
unsigned long uflags;
struct adefchan *next;
} adefchan1;
static int active=0;
void SearchChan(char *source,char *ch,char *args)
{
char buffer[200],keylist[512];
char *tok[16];
adefchan *list[11];
register adefchan *curr;
register int found=0,i=0;
if(!*args){
notice(source,"SYNTAX: search <keywords>");
return;
}
strcpy(keylist,args);
tok[0]=strtok(keylist," ");
while(i<16 && (tok[++i]=strtok(NULL," "))!=NULL);
tok[i]=NULL;
for(curr=DefChanList; curr; curr=curr->next){
if((key_match(curr->name,tok)||key_match(curr->topic,tok)) &&
!IsSet(curr->name,'s',"") && !IsSet(curr->name,'p',"")){
list[found]=curr;
found++;
if(found>10){
sprintf(buffer,"There are more than 10 entries matching [%s]",args);
notice(source,buffer);
sprintf(buffer,"Please restrict your search mask");
notice(source,buffer);
return;
}
}
}
if(!found){
sprintf(buffer,"No matching entries for [%s]",args);
notice(source,buffer);
return;
}
for(i=0; i<found; i++){
sprintf(buffer,"%-15s - %s",list[i]->name,list[i]->topic);
notice(source,buffer);
}
}
void AddChan(char *source,char *ch,char *args)
{
char buffer[200];
char channel[80];
register adefchan *curr,**scan;
register achannel *chan;
register int found=0;
if(*args=='#'){
GetWord(0,args,channel);
}else{
strcpy(channel,ch);
GuessChannel(source,channel);
}
if(!strcmp(channel,"*")){
notice(source,"SYNTAX: addchan <channel>");
return;
}
chan=ToChannel(channel);
if(chan==NULL || !chan->on){
notice(source,replies[RPL_NOTONCHANNEL][L_DEFAULT]);
return;
}
if(Access(channel,source)<SET_DEFAULT_LEVEL){
ReplyNotAccess(source,channel);
return;
}
chan=ChannelList[cl_hash(channel)];
while(chan && !found){
if(!strcasecmp(chan->name,channel)){
/* look if the channel is already in the
* default channels list
*/
curr=DefChanList;
while(curr&&strcasecmp(curr->name,channel))
curr=curr->next;
/* The channel *IS NOT* in the list */
if(curr==NULL){
curr=(adefchan *)MALLOC(sizeof(adefchan));
scan=&DefChanList;
while(*scan && strcasecmp((*scan)->name,chan->name)<0)
scan=&(*scan)->next;
curr->next=*scan;
*scan=curr;
curr->url[0]='\0';
curr->topic[0]='\0';
}
strcpy(curr->name,chan->name);
strcpy(curr->mode,chan->mode);
curr->MassDeopPro=chan->MassDeopPro;
curr->NickFloodPro=chan->NickFloodPro;
curr->MsgFloodPro=chan->MsgFloodPro;
curr->lang=chan->lang;
curr->flags=chan->flags;
curr->uflags=chan->uflags;
curr->TS=chan->TS;
found=1;
}else
chan=chan->next;
}
sprintf(buffer,"I ADD DEFAULT CHANNEL %s",channel);
log(buffer);
if(found){
notice(source,replies[RPL_SETCHANDEFS][chan->lang]);
#ifdef BACKUP
notice(source,"This modification will not be permanent");
#endif
}else{
notice(source,replies[RPL_NOTONCHANNEL][L_DEFAULT]);
}
}
void RemChan(char *source, char *ch, char *arg)
{
char buffer[200];
char channel[80];
register adefchan *chan,*prev;
if(*arg=='#'){
GetWord(0,arg,channel);
}else{
strcpy(channel,ch);
GuessChannel(source,channel);
}
if(!strcmp(channel,"*")){
notice(source,"SYNTAX: remchan <channel>");
return;
}
if(*source && Access(channel,source)<SET_DEFAULT_LEVEL){
ReplyNotAccess(source,channel);
return;
}
prev=NULL;
for(chan=DefChanList;chan&&strcasecmp(channel,chan->name);chan=chan->next)
prev=chan;
if(!chan){
notice(source,replies[RPL_NOTDEF][L_DEFAULT]);
return;
}
if(prev)
prev->next=chan->next;
else
DefChanList=chan->next;
TTLALLOCMEM-=sizeof(adefchan);
free(chan);
sprintf(buffer,"I REMOVE DEFAULT CHANNEL %s",channel);
log(buffer);
if(*source){
notice(source,replies[RPL_REMDEF][L_DEFAULT]);
#ifdef BACKUP
notice(source,"This modification will not be permanent");
#endif
}
}
void SaveDefs(char *source)
{
register int file;
register adefchan *curr;
adefchan buff;
filehdr hdr;
char global[]="*";
char buffer[200];
if(*source&&Access(global,source)<SAVE_DEFAULTS_LEVEL){
notice(source,"Your admin Access is too low!");
return;
}
if(*source)
notice(source,"Saving defaults file...");
if(active)
return;
active=1;
sprintf(buffer,":%s AWAY :Busy saving precious channel list\n",mynick);
sendtoserv(buffer);
dumpbuff();
alarm(5); /* avoid NFS hangs */
file=open(DEFAULT_CHANNELS_FILE".new",O_WRONLY|O_CREAT|O_TRUNC,0600);
alarm(0);
if(file<0){
if(*source)
notice(source,"Error while opening file. Aborted!");
log("ERROR Saving defaults channels");
}else{
hdr.magic=0xff;
hdr.no=FORMATNO;
alarm(2);
if(write(file,&hdr,sizeof(hdr))<=0){
alarm(0);
close(file);
log("ERROR: Can't save channel list");
log((char *)sys_errlist[errno]);
alarm(2);
remove(DEFAULT_CHANNELS_FILE".new");
alarm(0);
active=0;
sprintf(buffer,":%s AWAY\n",mynick);
sendtoserv(buffer);
return;
}
alarm(0);
curr=DefChanList;
while(curr){
achannel *chan = ToChannel(curr->name);
buff = *curr;
if(chan)
buff.TS = chan->TS;
else
buff.TS = curr->TS;
buff.flags = curr->flags;
alarm(2);
if(write(file,&buff,sizeof(adefchan))<=0){
alarm(0);
close(file);
log("ERROR: Can't save channel list");
log((char *)sys_errlist[errno]);
alarm(2);
remove(DEFAULT_CHANNELS_FILE".new");
alarm(0);
active=0;
sprintf(buffer,":%s AWAY\n",mynick);
sendtoserv(buffer);
return;
}
alarm(0);
curr=curr->next;
}
close(file);
alarm(20);
rename(DEFAULT_CHANNELS_FILE".new",DEFAULT_CHANNELS_FILE);
alarm(0);
if(*source)
notice(source,"Done.");
}
active=0;
sprintf(buffer,":%s AWAY\n",mynick);
sendtoserv(buffer);
}
void LoadDefs(char *source)
{
register adefchan *curr,**scan;
adefchan buffer;
adefchan0 bufold0;
adefchan1 bufold1;
filehdr hdr;
register int file;
char global[]="*";
if(*source&&Access(global,source)<LOAD_DEFAULT_LEVEL){
notice(source,"Your admin Access is too low!");
return;
}
if(active)
return;
active=1;
file=open(DEFAULT_CHANNELS_FILE,O_RDONLY);
if(file<0){
if(*source) notice(source,"Error opening file! Aborted.");
log("ERROR Loading the default channels");
active=0;
return;
}
/* empty existing defaults */
while((curr=DefChanList)!=NULL){
DefChanList=DefChanList->next;
TTLALLOCMEM-=sizeof(adefchan);
free(curr);
}
/* find file format */
read(file,&hdr,sizeof(hdr));
if(hdr.magic!=0xff){
lseek(file,0L,SEEK_SET);
hdr.no=0x00;
}
if(hdr.no == FORMATNO){
scan=&DefChanList;
while(read(file,&buffer,sizeof(adefchan))>0){
#ifdef DEBUG
printf("DEFCHAN: %s %d %d %d %ld\n",buffer.name,
buffer.MassDeopPro,buffer.NickFloodPro,
buffer.MsgFloodPro,buffer.flags);
printf("TS: %lu\n",buffer.TS);
#endif
if(logTS==0||buffer.TS<logTS){
#ifdef DEBUG
printf("TS is older than %lu\n",logTS);
#endif
logTS=buffer.TS;
}
if(buffer.TS<0){
/* if the TS of a channel is negative
* the file is prolly corrupted!
*/
log("Channel file is corrupted");
quit("LoadDefs(): corrupted file!", 1);
}
curr=(adefchan *)MALLOC(sizeof(adefchan));
*curr=buffer;
curr->next=*scan;
*scan=curr;
scan=&(*scan)->next;
}
}else if(hdr.no == 0x01){
while(read(file,&bufold1,sizeof(adefchan1))>0){
#ifdef DEBUG
printf("DEFCHAN: %s %d %d %d %ld\n",bufold1.name,
bufold1.MassDeopPro,bufold1.NickFloodPro,
bufold1.MsgFloodPro,bufold1.flags);
printf("TS: %lu\n",bufold1.TS);
#endif
if(logTS==0||bufold1.TS<logTS){
#ifdef DEBUG
printf("TS is older than %lu\n",logTS);
#endif
logTS=bufold1.TS;
}
if(bufold1.TS<0){
/* if the TS of a channel is negative
* the file is prolly corrupted!
*/
log("Channel file is corrupted");
quit("LoadDefs(): corrupted file!", 1);
}
curr=(adefchan *)MALLOC(sizeof(adefchan));
strcpy(curr->name,bufold1.name);
strcpy(curr->mode,bufold1.mode);
curr->url[0]='\0';
curr->topic[0]='\0';
curr->MassDeopPro=bufold1.MassDeopPro;
curr->NickFloodPro=bufold1.NickFloodPro;
curr->MsgFloodPro=bufold1.MsgFloodPro;
curr->lang=bufold1.lang;
curr->TS=bufold1.TS;
curr->flags=bufold1.flags;
curr->uflags=bufold1.uflags;
scan=&DefChanList;
while(*scan && strcasecmp((*scan)->name,curr->name)<0)
scan=&(*scan)->next;
curr->next=*scan;
*scan=curr;
}
}else{ /* old file format */
while(read(file,&bufold0,sizeof(adefchan0))>0){
#ifdef DEBUG
printf("DEFCHAN: %s %d %d %d %ld\n",bufold0.name,
bufold0.MassDeopPro,bufold0.NickFloodPro,
bufold0.MsgFloodPro,bufold0.flags);
printf("TS: %lu\n",bufold0.TS);
#endif
if(logTS==0||bufold0.TS<logTS){
#ifdef DEBUG
printf("TS is older than %lu\n",logTS);
#endif
logTS=bufold0.TS;
}
if(bufold0.TS<0){
/* if the TS of a channel is negative
* the file is prolly corrupted!
*/
log("Channel file is corrupted");
quit("LoadDefs(): corrupted file!", 1);
}
curr=(adefchan *)MALLOC(sizeof(adefchan));
strcpy(curr->name,bufold0.name);
strcpy(curr->mode,bufold0.mode);
curr->url[0]='\0';
curr->topic[0]='\0';
curr->MassDeopPro=bufold0.MassDeopPro;
curr->NickFloodPro=bufold0.NickFloodPro;
curr->MsgFloodPro=bufold0.MsgFloodPro;
curr->lang=L_DEFAULT;
curr->TS=bufold0.TS;
curr->flags=bufold0.flags;
curr->uflags=bufold0.uflags;
scan=&DefChanList;
while(*scan && strcasecmp((*scan)->name,curr->name)<0)
scan=&(*scan)->next;
curr->next=*scan;
*scan=curr;
}
}
close(file);
if(*source)
notice(source,"Defaults file loaded!");
active=0;
}

141
Sources/defines.h Normal file
View File

@@ -0,0 +1,141 @@
/* @(#)$Id: defines.h,v 1.11 2000/06/04 16:54:16 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#define NICK_LENGTH 20
#define USERNAME_LENGTH 20
#define SITE_LENGTH 80
#define REALNAME_LENGTH 80
#define CHANNELNAME_LENGTH 80
#define SERVER_NAME_LENGTH 80
#define PASSWD_LENGTH 20
#define COMMAND_PREFIX "X "
#define MAX_MODE_PER_LINE 6
#define MAX_DEOP_RATE 3 /* deops within 15 seconds */
#define MASSDEOP_SUSPEND_TIME 600 /* seconds */
#define MASSDEOP_SHITLIST_TIME 1 /* hours */
#define MASSDEOP_SHITLIST_LEVEL 20
#define MAX_NICKCHANGE_RATE 5 /* nick change within 15 seconds */
#define NICK_FLOOD_SUSPEND_TIME 600 /* seconds */
#define MAX_PUBLIC_MSG_RATE 7 /* within 15 seconds */
#define PUBLIC_FLOOD_SUSPEND_TIME 600 /* seconds */
#define PUBLIC_FLOOD_SHITLIST_TIME 24 /* hour */
#define PUBLIC_FLOOD_SHITLIST_LEVEL 75
#define PRIVATE_FLOOD_RATE 10 /* messages per 30 seconds */
#define PRIVATE_FLOOD_SIZE 800 /* bytes per 30 seconds */
#define FLOOD_FLOOD_RATE 10 /* messages per 30 seconds */
#define FLOOD_FLOOD_SIZE 60 /* lines per 30 seconds */
#define MAX_IGNORE_PER_SITE 3 /* ignores per site */
#define IGNORE_TIME 3600 /* in seconds */
#define FLOOD_FLOOD_IGNORE 300 /* in seconds */
#define LEVEL_DIE 900
#define LEVEL_CORE 900
#define RUSAGE_ACCESS 900
#define LEVEL_UPGRADE 900
#define LEVEL_JOIN 450
#define LEVEL_PART 450
#define INVITE_LEVEL 100
#define OP_LEVEL 100
#define TOPIC_LEVEL 50
#define KICK_LEVEL 50
#define MASS_KICK_LEVEL 200
#define BAN_LEVEL 75
#define MASS_BAN_LEVEL 200
#define ADD_USER_LEVEL 400
#define SHOW_ACCESS_LEVEL 0
#define REMOVE_USER_LEVEL 400
#define MOD_USERINFO_LEVEL 400
#define LEVEL_SUSPEND 100
#define ADD_TO_SHITLIST_LEVEL 75
#define CLEAN_SHITLIST_LEVEL 200
#define SET_DEFAULT_LEVEL 450
#define LOAD_DEFAULT_LEVEL 999
#define SAVE_DEFAULTS_LEVEL 600
#define SAVE_SHITLIST_LEVEL 600
#define LOAD_SHITLIST_LEVEL 999
#define SAVE_USERLIST_LEVEL 600
#define LOAD_USERLIST_LEVEL 999
#define STATUS_ACCESS 1
#define STATUS_ACCESS_MODE 200
#define CH_FLOOD_LIMIT_LEVEL 500
#define CH_NICK_FLOOD_LIMIT_LEVEL 450
#define CH_MASSDEOP_LIMIT_LEVEL 450
#define CH_NOOP_LEVEL 500
#define CH_OPONLY_LEVEL 500
#define CH_AUTOTOPIC_LEVEL 450
#define CH_ALWAYSOP_LEVEL 450
#define CH_STRICTOP_LEVEL 500
#define CH_USERFLAGS_LEVEL 450
#define CH_LANG_LEVEL 500
#define CH_TOPIC_LEVEL 450
#define CH_URL_LEVEL 450
#define ACCESS_BAN_PRIORITY 450
#define ALWAYSOP_OVERRIDE_LEVEL 450
#define PROTECT_OVERRIDE_LEVEL 450
#define MASSDEOP_IMMUNE_LEVEL 450
#define CLEARMODE_LEVEL 400
#define XADMIN_LEVEL 750
#define AUTO_KICK_SHIT_LEVEL 75
#define NO_OP_SHIT_LEVEL 20
#define SHITLIST_DEFAULT_TIME (24*3) /* hours */
#define SUSPEND_TIME_FOR_OPPING_A_SHITLISTED_USER 600 /* seconds */
#define SUSPEND_TIME_FOR_BANNING_A_PROTECTED_USER 600 /* seconds */
#define DEOPME_SUSPEND_TIME 3600 /* seconds */
#define DEOP_SHITLIST_TIME 1 /* hours */
#define DEOP_SHITLIST_LEVEL 20
#define MAX_BAN 50
#define MIN_LASTSEEN (3*24*3600) /* 3 days */
#define HTTP_LISTEN 1
#define HTTP_ACTIVE 2
#define HTTP_ENDING 3
#define HTTP_RECV_POST 4
#define HTTP_PIPE 5
#define HTTP_CSRAW 6
#define HTTP_CHAT 7
#define HTTP_ERROR 0
#define MISC_GETPATCH 1
#define MISC_PIPE_PATCH 2
#define MISC_PIPE_MAKE 3
#define MISC_ERROR -1
#define MISC_CONNECTING 1
#define MISC_HANDSHAKE 2
#define MISC_RECV 3
#define BUFFER_BLOCK_SIZE 512
#define CACHE_TIMEOUT 4800 /* 1.5 hours */
#define AUTOTOPIC_FREQ 1800 /* 30 minutes*/

189
Sources/events.c Normal file
View File

@@ -0,0 +1,189 @@
/* @(#)$Id: events.c,v 1.6 1998/01/02 18:30:09 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
void InitEvent(void)
{
AddEvent(EVENT_SAVESHITLIST, now + SHITLIST_SAVE_FREQ + 300, "");
AddEvent(EVENT_SAVEDEFCHANNELS, now + DEFS_SAVE_FREQ + 600, "");
AddEvent(EVENT_SYNC, now + SYNC_FREQ + 900, "");
AddEvent(EVENT_CHECK_IDLE, now + CHECK_IDLE_FREQ, "");
AddEvent(EVENT_RENAME_LOGFILE, now + RENAME_LOGFILE_FREQ, "");
AddEvent(EVENT_SYNCDB, now + CACHE_TIMEOUT, "");
#ifdef CHANNEL_LOG
AddEvent(EVENT_LOG_CHANNEL, now + CHANNEL_LOG_FREQ, "");
#endif
#ifdef NICKSERV
AddEvent(EVENT_SAVENICKSERV, now + NSERV_SAVE_FREQ, "");
#endif
}
void AddEvent(int event, time_t time, char *param)
{
register anevent **curr = &EventList;
register anevent *new;
#ifdef DEBUG
printf("AddEvent( %d, %ld, %s)\n", event, time, param);
#endif
/* the events are store in ascending time order, so the new
* event is inserted before the first event with a greater
* time
*/
while (*curr && (*curr)->time < time)
curr = &(*curr)->next;
/* create a new event structure
*/
new = (anevent *) MALLOC(sizeof(anevent));
new->time = time;
new->event = event;
strncpy(new->param, param, 79);
new->param[79] = '\0';
/* link the new structure to the list
*/
new->next = *curr;
*curr = new;
}
void CheckEvent(void)
{
register anevent *curr;
register achannel *chan;
while (EventList != NULL && EventList->time <= now)
{
/* remove the event from the list */
curr = EventList;
EventList = EventList->next;
#ifdef DEBUG
printf("Scheduled event %d\n", curr->event);
#endif
switch (curr->event)
{
case EVENT_SAVEUSERLIST:
/* replaced by SYNCDB */
break;
case EVENT_SAVESHITLIST:
SaveShitList("", "");
AddEvent(EVENT_SAVESHITLIST,
now + SHITLIST_SAVE_FREQ, "");
break;
case EVENT_SAVEDEFCHANNELS:
SaveDefs("");
AddEvent(EVENT_SAVEDEFCHANNELS,
now + DEFS_SAVE_FREQ, "");
break;
case EVENT_CLEANSHITLIST:
CleanShitList("", curr->param);
break;
case EVENT_FLUSHMODEBUFF:
flushmode(curr->param);
break;
case EVENT_GETOPS:
chan = ToChannel(curr->param);
if (chan != NULL && chan->on &&
(IsOpless(curr->param) ||
((chan->flags & CFL_ALWAYSOP) &&
!chan->AmChanOp)))
GetOps(curr->param);
break;
case EVENT_SYNC:
sync();
AddEvent(EVENT_SYNC,
now + SYNC_FREQ, "");
break;
case EVENT_CLEAN_IGNORES:
CleanIgnores();
break;
case EVENT_CHECK_IDLE:
CheckIdleChannels();
AddEvent(EVENT_CHECK_IDLE, now + CHECK_IDLE_FREQ, "");
break;
case EVENT_RENAME_LOGFILE:
log("Closing log file");
close(logfile);
rename(LOGFILE, LOGFILEBAK);
logfile = open(LOGFILE, O_WRONLY | O_CREAT | O_APPEND, 0600); /* "a" in case rename() fails */
log("Opening log file");
AddEvent(EVENT_RENAME_LOGFILE, now + RENAME_LOGFILE_FREQ, "");
break;
case EVENT_SYNCDB:
if (DB_Save_Status == -1)
{
DB_Save_Status = 0;
*DB_Save_Nick = '\0';
}
/*SaveUserList("",""); */
/*
gather_sync_channels();
if(DBSync==NULL)
sync_next_channel();
sync_next_channel();
*/
AddEvent(EVENT_SYNCDB, now + CACHE_TIMEOUT, "");
break;
#ifdef CHANNEL_LOG
case EVENT_LOG_CHANNEL:
LogChan();
AddEvent(EVENT_LOG_CHANNEL, now + CHANNEL_LOG_FREQ, "");
break;
#endif
#ifdef NICKSERV
case EVENT_CHECKREGNICK:
nserv_checkregnick(curr->param);
break;
case EVENT_SAVENICKSERV:
nserv_save();
break;
#endif
default:
#ifdef DEBUG
printf("Err.. unknown event %d\n", curr->event);
#endif
break;
}
TTLALLOCMEM -= sizeof(anevent);
free(curr);
}
}

40
Sources/events.h Normal file
View File

@@ -0,0 +1,40 @@
/* @(#)$Id: events.h,v 1.4 1997/07/01 21:51:08 cvs Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#define EVENT_SAVEUSERLIST 1
#define EVENT_SAVESHITLIST 2
#define EVENT_SAVEDEFCHANNELS 3
#define EVENT_SYNC 4
#define EVENT_CLEANSHITLIST 5
#define EVENT_FLUSHMODEBUFF 6
#define EVENT_GETOPS 7
#define EVENT_CLEAN_IGNORES 8
#define EVENT_CHECK_IDLE 9
#define EVENT_RENAME_LOGFILE 10
#define EVENT_LOG_CHANNEL 11
#define EVENT_SYNCDB 12
#define EVENT_CHECKREGNICK 13
#define EVENT_SAVENICKSERV 14

203
Sources/fixdb.c Normal file
View File

@@ -0,0 +1,203 @@
/* @(#)$Id: fixdb.c,v 1.5 1998/01/12 20:02:17 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#include "dirent.h"
#define SPECFILE "special.log"
struct node
{
dbuser dbu;
struct node *next;
};
unsigned long ttlread = 0L, ttlwrite = 0L;
time_t now;
void SpecLog(char *text)
{
int fd;
char date[80], buffer[1024];
strcpy(date, ctime(&now));
*strchr(date, '\n') = '\0';
if ((fd = open(SPECFILE, O_WRONLY | O_CREAT | O_APPEND, 0600)) >= 0)
{
sprintf(buffer, "%s: %s\n", date, text);
write(fd, buffer, strlen(buffer));
close(fd);
}
}
void fix_user_file(char *file, char *channel)
{
char tmpfile[256], buffer[200];
struct node *List = NULL, *tmp;
dbuser dbu;
int fd;
fd = open(file, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "Can't open %s [%s]\n", file, sys_errlist[errno]);
return;
}
while (read(fd, &dbu, sizeof(dbuser)) == sizeof(dbuser))
{
ttlread += sizeof(dbuser);
if (dbu.header[0] != 0xFF || dbu.header[1] != 0xFF ||
dbu.footer[0] != 0xFF || dbu.footer[1] != 0xFF)
{
continue;
}
if (strcasecmp(channel, dbu.channel))
continue;
if (!strcmp(dbu.match, "!DEL!"))
continue;
if (dbu.lastseen + USERLIST_EXP_TIME <= now)
{
sprintf(buffer, "Exp: %s [%s] (%d) on %s",
dbu.nick, dbu.match, dbu.access, dbu.channel);
SpecLog(buffer);
continue;
}
tmp = (struct node *)malloc(sizeof(struct node));
memcpy(&tmp->dbu, &dbu, sizeof(dbuser));
tmp->next = List;
List = tmp;
}
close(fd);
sprintf(tmpfile, "%s.new", file);
fd = open(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0)
{
fprintf(stderr, "Can't open %s\n", tmpfile);
/* don't return.. need to free the list! */
}
while ((tmp = List) != NULL)
{
write(fd, &tmp->dbu, sizeof(dbuser));
ttlwrite += sizeof(dbuser);
List = List->next;
free(tmp);
}
close(fd);
if (fd >= 0)
rename(tmpfile, file);
}
void fix_user_db(void)
{
DIR *dp;
struct dirent *ent;
char dir[256], file[256], channel[80], *ptr;
int count;
for (count = 0; count < 1000; count++)
{
sprintf(dir, "db/channels/%04X", count);
dp = opendir(dir);
if (dp == NULL)
{
fprintf(stderr, "Can't read %s [%s]\n", dir, sys_errlist[errno]);
continue;
}
while ((ent = readdir(dp)) != NULL)
{
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
strcpy(channel, ent->d_name);
for (ptr = channel; *ptr; ptr++)
if (*ptr == ' ')
*ptr = '/';
sprintf(file, "db/channels/%04X/%s", count, ent->d_name);
/* If no comma in channel name, proceed with clean up */
if (strchr(channel, ',') == NULL)
fix_user_file(file, channel);
}
closedir(dp);
}
}
int main(void)
{
int pid = 0;
FILE *fp;
if (chdir(HOMEDIR) < 0)
{
perror(HOMEDIR);
exit(1);
}
if ((fp = fopen(PIDFILE, "r")) != NULL)
{
fscanf(fp, "%d", &pid);
fclose(fp);
if (!kill((pid_t) pid, 0))
{
fprintf(stderr, "Detected cs is running [pid %d]. Abort.\n", pid);
exit(1);
}
}
if (rename("cs", "cs.fixdb") < 0)
{
perror("rename");
exit(1);
}
if (symlink("/bin/true", "cs") < 0)
{
perror("symlink");
exit(1);
}
time(&now);
fix_user_db();
if (unlink("cs") < 0)
perror("unlink");
if (rename("cs.fixdb", "cs") < 0)
perror("rename");
printf("ttlread= %ld ttlwrite= %ld\n", ttlread, ttlwrite);
return 0;
}

36
Sources/flags.h Normal file
View File

@@ -0,0 +1,36 @@
/* @(#)$Id: flags.h,v 1.4 1996/11/13 00:40:39 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#define UFL_AUTOOP 1
/*#define UFL_PROTECT 2*/
#define CFL_NOOP 1
#define CFL_ALWAYSOP 2
#define CFL_OPONLY 4
#define CFL_STRICTOP 8
#define CFL_AUTOTOPIC 16
#define LFL_ISOPER 1

135
Sources/floodpro.c Normal file
View File

@@ -0,0 +1,135 @@
/* @(#)$Id: floodpro.c,v 1.4 1999/04/04 17:00:06 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
int CheckFlood(char *source, char *channel, int length)
{
char buffer[200];
register achannel *chan;
register auser *user;
register amsg *msg, *prev;
register int count = 0;
chan = ToChannel(channel);
user = ToUser(channel, source);
if (!chan || !chan->on || !user)
return 0;
/* BEGINNING OF FLOOD PROTECTION ROUTINE */
/* 1st clean msghist older than 15 seconds */
prev = NULL;
msg = user->msghist;
while (msg)
{
if (msg->time < (now - 15))
{
if (prev)
{
prev->next = msg->next;
TTLALLOCMEM -= sizeof(amsg);
free(msg);
msg = prev->next;
}
else
{
user->msghist = msg->next;
TTLALLOCMEM -= sizeof(amsg);
free(msg);
msg = user->msghist;
}
}
else
{
prev = msg;
msg = msg->next;
}
}
/* now add the current msg to the history */
msg = (amsg *) MALLOC(sizeof(amsg));
msg->time = now;
msg->length = length;
msg->next = user->msghist;
user->msghist = msg;
/* now count the number of entry in the history..
if it's greater than the max allowed... bite! */
count = 0;
for (msg = user->msghist; msg; msg = msg->next, count++);
if (chan->MsgFloodPro != 0 && count == chan->MsgFloodPro)
{
notice(source, "### FLOOD PROTECTION ACTIVATED ###");
sprintf(buffer, "%s!%s@%s %d", user->N->nick,
user->N->username, user->N->site, PUBLIC_FLOOD_SUSPEND_TIME);
suspend("", channel, buffer);
count = IsShit(channel, source, NULL, NULL);
#ifdef DEBUG
printf("Argh! %s has a shit level %d\n", source, count);
#endif
sprintf(buffer, "FLOODPRO ACTIVATED BY %s ON %s", source, channel);
log(buffer);
switch (count)
{
case 0:
case 1:
case 2:
case 3:
case 4:
log("First warning");
sprintf(buffer, "%s That was not very smart!", source);
break;
case 5:
case 6:
case 7:
case 8:
case 9:
log("Second warning");
sprintf(buffer, "%s You're pushing your luck too far!", source);
break;
default:
sprintf(buffer, "%s That was one time too many", source);
}
kick("", channel, buffer);
sprintf(buffer, "%s %d %d *** FLOOD ***",
user->N->nick,
PUBLIC_FLOOD_SHITLIST_TIME,
(count < 10) ? count + 5 :
PUBLIC_FLOOD_SHITLIST_LEVEL);
AddToShitList("", channel, buffer, 0);
return 1;
}
return 0;
}

105
Sources/globalvar.h Normal file
View File

@@ -0,0 +1,105 @@
/* @(#)$Id: globalvar.h,v 1.12 2000/10/24 15:15:53 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#if !defined(__FreeBSD__) && !defined(__linux__)
extern int errno;
extern char *sys_errlist[];
#endif
extern char mynick[NICK_LENGTH];
extern char myuser[USERNAME_LENGTH];
extern char mysite[SITE_LENGTH];
extern char myrealname[REALNAME_LENGTH];
extern char server[SERVER_NAME_LENGTH];
extern int logfile;
extern RegUser *UserList[1000];
extern ShitUser *ShitList[1000];
extern aluser *Lusers[1000];
extern achannel *ChannelList[1000];
extern adefchan *DefChanList;
extern anevent *EventList;
extern aserver *ServerList;
extern aserver VirtualServer;
extern dbquery *DBQuery;
extern dbsync *DBSync;
extern syncchan *SyncChan;
#ifdef DOHTTP
extern http_socket *HttpList;
extern http_file_pipe *FilePipes;
#endif
extern misc_socket *MiscList;
extern irc_socket Irc;
extern char *TmpPtr;
extern time_t now;
extern time_t logTS;
extern time_t TSoffset;
extern time_t TSonline;
extern time_t TSconnect;
extern unsigned long long TTLREADBYTES;
extern unsigned long long TTLSENTBYTES;
extern unsigned long TTLALLOCMEM;
extern unsigned long long HTTPTTLSENTBYTES;
extern alang Lang[NO_LANG];
extern char *replies[][NO_LANG];
#ifdef FAKE_UWORLD
extern int Uworld_status;
extern time_t UworldTS,UworldServTS;
#endif
#ifdef NICKSERV
extern int NServ_status;
#endif
extern unsigned long MEM_buffers;
extern unsigned long NB_avail_buffer_blocks;
extern unsigned long NB_alloc_buffer_blocks;
extern long CurrentSendQ;
extern int DB_Save_Status;
extern char DB_Save_Nick[NICK_LENGTH];
#define MALLOC(X) ((TmpPtr=(char *)malloc(X))? \
TmpPtr : (char *)quit("ERROR: malloc() failed", 1));\
TTLALLOCMEM+=X
#define close(X) if((X)>=0) close(X)
#define ABS(X) ((X>0)?(X):(-(X)))
/* I use '}' and ']' instead of 'z' and 'Z'
* in order to respect RFC-1459 (section 2.2)
*/
#undef toupper
#undef tolower
#if 0
#define toupper(X) ( ((X)>='a'&&(X)<='~') ? ((X)&223) : (X) )
#define tolower(X) ( ((X)>='A'&&(X)<='^') ? ((X)|32) : (X) )
#endif
#define toupper(X) ( ((X)>='a'&&(X)<='~') || ((unsigned char)(X)>=0xe0&&(unsigned char)(X)<=0xff&&(unsigned char)(X)!=0xf7)? ((X)&223) : (X) )
#define tolower(X) ( ((X)>='A'&&(X)<='^') || ((unsigned char)(X)>=0xc0&&(unsigned char)(X)<=0xdf&&(unsigned char)(X)!=0xd7)? ((X)|32) : (X) )
#define touppertmp(X) ( ((X)>='a'&&(X)<='~') || ((unsigned char)(X)>=0xe0&&(unsigned char)(X)<=0xff&&(unsigned char)(X)!=0xf7)? ((X)&223) : (X) )
#define tolowertmp(X) ( ((X)>='A'&&(X)<='^') || ((unsigned char)(X)>=0xc0&&(unsigned char)(X)<=0xdf&&(unsigned char)(X)!=0xd7)? ((X)|32) : (X) )
#define strcasecmp mycasecmp
#define strcmp mycasecmp

56
Sources/h.h Normal file
View File

@@ -0,0 +1,56 @@
/* @(#)$Id: h.h,v 1.3 1996/11/13 00:40:40 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/resource.h>
#include "../config.h"
#include "debug.h"
#include "defines.h"
#include "struct.h"
#include "lang.h"
#include "replies.h"
#include "prototypes.h"
#include "globalvar.h"
#include "events.h"
#include "flags.h"
#include "dbio.h"
#include "version.h"

761
Sources/help.c Normal file
View File

@@ -0,0 +1,761 @@
/* @(#)$Id: help.c,v 1.22 2000/10/02 00:55:13 lgm Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
static struct item
{
char *name;
int Access;
char *file;
}
commands[] =
{
{
"showcommands", 0, "SHOWCOMMANDS"
}
,
{
"status", STATUS_ACCESS, "STATUS"
}
,
{
"join", LEVEL_JOIN, "JOIN"
}
,
{
"invite", INVITE_LEVEL, "INVITE"
}
,
{
"part", LEVEL_PART, "JOIN"
}
,
{
"topic", TOPIC_LEVEL, "TOPIC"
}
,
{
"kick", KICK_LEVEL, "KICK"
}
,
{
"ban", BAN_LEVEL, "BAN"
}
,
{
"unban", BAN_LEVEL, "BAN"
}
,
{
"banlist", 0, "BAN"
}
,
{
"lbanlist", 0, "BAN"
}
,
{
"adduser", ADD_USER_LEVEL, "ADDUSER"
}
,
{
"access", SHOW_ACCESS_LEVEL, "ACCESS"
}
,
{
"verify", 0, "VERIFY"
}
,
{
"remuser", REMOVE_USER_LEVEL, "ADDUSER"
}
,
{
"modinfo", MOD_USERINFO_LEVEL, "ADDUSER"
}
,
{
"purge", XADMIN_LEVEL, "XADMIN"
}
,
{
"isreg", 0, "ISREG"
}
,
{
"set", CH_FLOOD_LIMIT_LEVEL, "SET"
}
,
{
"suspend", LEVEL_SUSPEND, "SUSPEND"
}
,
{
"unsuspend", LEVEL_SUSPEND, "SUSPEND"
}
,
{
"saveuserlist", SAVE_USERLIST_LEVEL, "SAVEUSERLIST"
}
,
{
"addchan", SET_DEFAULT_LEVEL, "DEFCHAN"
}
,
{
"remchan", SET_DEFAULT_LEVEL, "DEFCHAN"
}
,
{
"savedefs", SAVE_DEFAULTS_LEVEL, "DEFCHAN"
}
,
{
"loaddefs", LOAD_DEFAULT_LEVEL, "LOADDEFS"
}
,
{
"savebanlist", SAVE_SHITLIST_LEVEL, "SAVEBANLIST"
}
,
{
"loadbanlist", LOAD_SHITLIST_LEVEL, "LOADBANLIST"
}
,
{
"pass", 0, "PASSWORD"
}
,
{
"login", 0, "PASSWORD"
}
,
{
"newpass", 0, "PASSWORD"
}
,
{
"deauth", 0, "PASSWORD"
}
,
{
"die", LEVEL_DIE, "DIE"
}
,
{
"restart", LEVEL_DIE, "RESTART"
}
,
{
"core", LEVEL_CORE, "CORE"
}
,
{
"rusage", RUSAGE_ACCESS, "RUSAGE"
}
,
#ifdef UPGRADE
{
"upgrade", LEVEL_UPGRADE, "UPGRADE"
}
,
#endif
{
"op", OP_LEVEL, "OP"
}
,
{
"deop", OP_LEVEL, "OP"
}
,
{
"clearmode", CLEARMODE_LEVEL, "CLEARMODE"
}
,
{
"map", 0, "MAP"
}
,
{
"help", 0, "HELP"
}
,
{
"motd", 0, "MOTD"
}
,
{
"showignore", 0, "SHOWIGNORE"
}
,
{
"remignore", XADMIN_LEVEL, "REMIGNORE"
}
,
{
"chaninfo", 0, "CHANINFO"
}
,
{
NULL, -1, NULL
}
};
static int N = 0;
static void sort(void)
{
struct item tmp;
register int i, j, k;
/* sort the command list using a simple bubble sort algo.
* 1st sort the commands by decreasing access
*/
for (i = 0; i < N - 1; i++)
{
for (j = N - 1; j > i; j--)
{
if (commands[j - 1].Access < commands[j].Access)
{
tmp = commands[j - 1];
commands[j - 1] = commands[j];
commands[j] = tmp;
}
}
}
/* Then, sort the commands by alphabetical order
*/
i = k = 0;
while (k < N - 1)
{
while (commands[k].Access == commands[i].Access)
k++;
while (i < k - 1)
{
for (j = k - 1; j > i; j--)
{
if (strcmp(commands[j - 1].name, commands[j].name) > 0)
{
tmp = commands[j - 1];
commands[j - 1] = commands[j];
commands[j] = tmp;
}
}
i++;
}
i = k;
}
}
static void listinit(void)
{
static int sorted = 0;
/* count the number of commands
*/
if (N == 0)
{
for (N = 0; commands[N].name != NULL; N++);
N--;
}
/* sort the list if not already done
*/
if (!sorted)
{
sort();
sorted = 1;
}
}
void showcommands(char *source, char *chan, char *args)
{
char buffer[500];
char channel[80];
register aluser *luser;
register int useraccess;
register int i, j;
if (*args == '#' || *args == '*')
GetWord(0, args, channel);
else
{
strcpy(channel, chan);
GuessChannel(source, channel);
}
luser = ToLuser(source);
if (!luser)
return;
if (!strcmp(channel, "*") && !IsValid(luser, channel))
{
notice(source, "SYNTAX: showcommands <channel>");
return;
}
useraccess = LAccess(channel, luser);
listinit();
/* Now show the sorted command list to the user.
*/
i = useraccess;
sprintf(buffer, "Level%5d:", i);
for (j = 0; j < N + 1; j++)
{
if (commands[j].Access < i)
{
if (strlen(buffer) > 13)
notice(source, buffer);
i = commands[j].Access;
sprintf(buffer, "Level%5d:", i);
}
if (commands[j].Access <= useraccess)
{
strcat(buffer, " ");
strcat(buffer, commands[j].name);
}
}
notice(source, buffer);
}
void showhelp(char *source, char *chan, char *args)
{
struct buffer_block *dyn = NULL;
char buffer[512], word[80], *ptr;
int i, l, index = 0, found = 0, file, linecount = 0;
if (CurrentSendQ > HIGHSENDQTHRESHOLD)
{
notice(source, "Cannot process your request at this time. Try again later.");
return;
}
GetWord(0, args, word);
if (!*word)
strcpy(word, "help");
listinit();
/* find the command index */
for (i = 0; i <= N; i++)
{
if (!strcasecmp(word, commands[i].name))
{
found = 1;
index = i;
break;
}
else if (!strncasecmp(word, commands[i].name, strlen(word)))
{
found++;
index = i;
}
}
if (found > 1)
{
sprintf(buffer, "%s is ambiguous", word);
notice(source, buffer);
return;
}
else if (found == 0)
{
if (!strcasecmp(word, "INFO"))
{
sprintf(buffer, "%s/INFO", HELP_DIR);
}
else if (!strcasecmp(word, "FORM"))
{
sprintf(buffer, "%s/FORM", HELP_DIR);
}
else
{
sprintf(buffer, "No help on %s. Please use "
"showcommands to get a list of commands "
"available to you", word);
notice(source, buffer);
return;
}
}
else
{
sprintf(buffer, "%s/%s", HELP_DIR, commands[index].file);
}
alarm(2);
file = open(buffer, O_RDONLY);
alarm(0);
if (file < 0)
{
if (found)
sprintf(buffer, "The help file for command %s "
"is not available", commands[index].name);
else
sprintf(buffer, "This help file is not available");
notice(source, buffer);
return;
}
if (found)
{
sprintf(buffer,
" HELP on %-20s Minimum access: %4d ",
commands[index].name, commands[index].Access);
notice(source, buffer);
}
alarm(3);
while ((l = read(file, buffer, 511)) > 0)
{
copy_to_buffer(&dyn, buffer, l);
}
alarm(0);
close(file);
while (dyn != NULL)
{
copy_from_buffer(&dyn, buffer, '\n', 199);
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
else
continue;
if (*buffer == '\0')
strcpy(buffer, " ");
string_swap(buffer, 512, "$NICK", mynick);
string_swap(buffer, 512, "$SERVER", SERVERNAME);
notice(source, buffer);
linecount++;
}
if (linecount > 0)
CheckFloodFlood(source, linecount);
}
void showmotd(char *source)
{
struct buffer_block *dyn = NULL;
char buffer[512];
int fd, l;
alarm(3);
fd = open(MOTD_FILE, O_RDONLY);
if (fd < 0)
{
notice(source, "MOTD is empty");
return;
}
if (CurrentSendQ > HIGHSENDQTHRESHOLD)
{
notice(source, "Cannot process your request at this time. Try again later.");
return;
}
while ((l = read(fd, buffer, 511)) > 0)
{
copy_to_buffer(&dyn, buffer, l);
}
close(fd);
alarm(0);
while (dyn != NULL)
{
char *ptr;
copy_from_buffer(&dyn, buffer, '\n', 199);
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
else
continue;
if (*buffer == '\0')
strcpy(buffer, " ");
notice(source, buffer);
}
}
static void
chaninfo_callback(int *fd, off_t off, int action, void *hook1, void *hook2,
dbuser * dbu, int count)
{
char buffer[512];
register adefchan *def;
time_t t;
if (count == 1 && dbu != NULL)
{
sprintf(buffer, "%s is registered by:", (char *)hook2);
notice((char *)hook1, buffer);
}
if (dbu == NULL)
{
if (count == 0)
{
notice((char *)hook1, "That channel is not registered");
}
else
{
def = DefChanList;
while (def && strcasecmp(def->name, (char *)hook2))
def = def->next;
if (def)
{
if (*def->topic)
{
sprintf(buffer, "Desc: %s", def->topic);
notice((char *)hook1, buffer);
}
if (*def->url)
{
sprintf(buffer, "URL: %s", def->url);
notice((char *)hook1, buffer);
}
}
}
free(hook1);
free(hook2);
}
else if (dbu->access >= 500)
{
t = now - dbu->lastseen;
sprintf(buffer, "%s (%s) last seen: %s ago",
dbu->nick, dbu->match,
time_remaining(t));
notice((char *)hook1, buffer);
}
}
void ShowChanInfo(char *source, char *chan, char *args)
{
char channel[80], *hook1, *hook2;
if (*args == '#')
GetWord(0, args, channel);
else
{
strcpy(channel, chan);
GuessChannel(source, channel);
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: chaninfo <channel>");
return;
}
hook1 = (char *)malloc(strlen(source) + 1);
strcpy(hook1, source);
hook2 = (char *)malloc(strlen(channel) + 1);
strcpy(hook2, channel);
db_fetch(channel, DBGETALLCMP, "", NULL, 0, hook1, hook2, chaninfo_callback);
}
void isreg(char *source, char *chan, char *args)
{
char channel[80], buffer[512];
struct stat st;
if (*args == '#')
GetWord(0, args, channel);
else
{
strcpy(channel, chan);
GuessChannel(source, channel);
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: isreg <channel>");
return;
}
if (stat(make_dbfname(channel), &st) < 0)
sprintf(buffer, "%s is not registered.",channel);
else
sprintf(buffer, "%s is registered.",channel);
notice(source, buffer);
}
#ifdef DOHTTP
void http_show_help(http_socket * hsock, char *command)
{
char buffer[512], buffer2[200];
struct buffer_block *dyn = NULL;
register char *ptr, *ptr2;
register int i, index = 0, found = 0;
int file, l;
listinit();
/* find the command index */
for (i = 0; i <= N; i++)
{
if (!strcasecmp(command, commands[i].name))
{
found = 1;
index = i;
break;
}
else if (!strncasecmp(command, commands[i].name, strlen(command)))
{
found++;
index = i;
}
}
buffer[0] = '\0';
sendto_http(hsock, HTTP_HEADER, command);
sendto_http(hsock, HTTP_BODY);
sendto_http(hsock, "<H1>HELP ON %s</H1>\n", (*command) ? command : "COMMANDS");
sendto_http(hsock, "<PRE>\n");
if (found > 1)
{
if (*command)
sendto_http(hsock, "%s is ambiguous\n", command);
}
else if (found == 0)
{
if (!strcasecmp(command, "INFO"))
{
sprintf(buffer, "%s/INFO", HELP_DIR);
}
else if (!strcasecmp(command, "FORM"))
{
sprintf(buffer, "%s/FORM", HELP_DIR);
}
else
{
sendto_http(hsock, "No help on %s.\n", command);
}
}
else
{
sprintf(buffer, "%s/%s", HELP_DIR, commands[index].file);
}
if (buffer[0] != '\0')
{
alarm(2);
file = open(buffer, O_RDONLY);
if (file < 0)
{
alarm(0);
if (found)
sendto_http(hsock, "The help file for command %s "
"is not available\n", commands[index].name);
else
sendto_http(hsock, "This help file is not available\n");
}
else
{
alarm(2);
while ((l = read(file, buffer, 511)) > 0)
{
copy_to_buffer(&dyn, buffer, l);
}
alarm(0);
close(file);
while (dyn != NULL)
{
copy_from_buffer(&dyn, buffer, '\n', 199);
if ((ptr = strchr(buffer, '\n')) == NULL)
continue;
if ((ptr = strstr(buffer, "$NICK")) != NULL)
{
*ptr = '\0';
sprintf(buffer2, "%s%s%s", buffer, mynick, ptr + 5);
strcpy(buffer, buffer2);
}
/* Some nasty char quoting required.. */
ptr = buffer;
ptr2 = buffer2;
do
{
if (*ptr == '<')
{
ptr2[0] = '&';
ptr2[1] = 'l';
ptr2[2] = 't';
ptr2[3] = ';';
ptr2 += 4;
}
else if (*ptr == '>')
{
ptr2[0] = '&';
ptr2[1] = 'g';
ptr2[2] = 't';
ptr2[3] = ';';
ptr2 += 4;
}
else
{
ptr2[0] = ptr[0];
ptr2++;
}
}
while (*(ptr++) != '\0');
sendto_http(hsock, "%s", buffer2);
}
}
sendto_http(hsock, "</PRE>\n");
}
else
{ /* show list of commands */
sendto_http(hsock, "</PRE>\n<H2>List of commands:</H2>\n");
sendto_http(hsock, "<FONT SIZE=+1>\n");
for (i = 0; i < N + 1; i++)
{
if (commands[i].Access <= 500)
sendto_http(hsock, "<A HREF=\"/HELP/%s\">%s</A>\n",
commands[i].name, commands[i].name);
}
sendto_http(hsock, "</FONT><P>\n");
}
sendto_http(hsock, "<HR>%s\n", HTTP_FOOTER);
sendto_http(hsock, "</BODY></HTML>\n");
hsock->status = HTTP_ENDING;
}
#endif

1427
Sources/http.c Normal file

File diff suppressed because it is too large Load Diff

572
Sources/ignore.c Normal file
View File

@@ -0,0 +1,572 @@
/* @(#)$Id: ignore.c,v 1.19 2000/10/24 16:04:24 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
typedef struct aprivmsg
{
char user[200];
time_t time;
int length;
struct aprivmsg *next;
}
aprivmsg;
typedef struct aignore
{
char mask[200];
time_t time;
struct aignore *next;
}
aignore;
static aprivmsg *MessageList = NULL;
static aprivmsg *FloodList = NULL;
static aprivmsg *AddUserFloodList = NULL;
static aignore *IgnoreList = NULL;
void add_silence(char *, char *);
void rem_silence(char *);
int CheckPrivateFlood(char *source, int length, char *type)
{
char buffer[200];
char userhost[200];
char global[] = "*";
register aluser *user;
register aprivmsg *msg, *prev;
register int count, size;
if ((user = ToLuser(source)) == NULL)
{
sprintf(buffer, "ERROR! CheckPrivateFlood(): %s not found", source);
log(buffer);
return 1;
}
/* Don't check flood from admins */
if (IsValid(user, global) && Access(global, source) >= 1)
return 0;
if (!strcasecmp(user->username, DEFAULT_USERNAME) &&
!strcasecmp(user->site, DEFAULT_HOSTNAME))
{
return 0;
}
/* clean messages older than 30 seconds */
prev = NULL;
msg = MessageList;
while (msg != NULL)
{
if (msg->time < (now - 30))
{
if (prev)
{
prev->next = msg->next;
TTLALLOCMEM -= sizeof(aprivmsg);
free(msg);
msg = prev->next;
}
else
{
MessageList = msg->next;
TTLALLOCMEM -= sizeof(aprivmsg);
free(msg);
msg = MessageList;
}
}
else
{
prev = msg;
msg = msg->next;
}
}
/* now add the current message in the list */
sprintf(userhost, "%s@%s", user->username, user->site);
msg = (aprivmsg *) MALLOC(sizeof(aprivmsg));
strcpy(msg->user, userhost);
msg->time = now;
msg->length = length;
msg->next = MessageList;
MessageList = msg;
/* count how many messages were received from that user
* and also how many bytes
*/
count = size = 0;
for (msg = MessageList; msg != NULL; msg = msg->next)
{
if (compare(userhost, msg->user))
{
count++;
size += msg->length;
}
}
if (count >= PRIVATE_FLOOD_RATE || size >= PRIVATE_FLOOD_SIZE)
{
#ifdef DEBUG
printf("FLOODED by %s!%s\n", user->nick, userhost);
#endif
if (!IsIgnored(source))
{
sprintf(buffer, "%sFLOOD from %s!%s", type, user->nick, userhost);
log(buffer);
sprintf(buffer, "%sFLOOD from %s!%s (%s)", type,
user->nick, userhost, user->server->name);
broadcast(buffer, 1);
}
MakeBanMask(user, buffer);
AddIgnore(source, buffer, IGNORE_TIME);
return 1;
}
return 0;
}
void AddIgnore(char *source, char *mask, int t)
{
char buffer[200];
char *site;
aignore *curr;
int count;
if (IsIgnored(source))
return;
/* count number of ignores from the same site */
site = strchr(mask, '@') + 1;
count = 0;
curr = IgnoreList;
while (curr)
{
if (!mycasecmp(strchr(curr->mask, '@') + 1, site))
count++;
curr = curr->next;
}
/* add the entry in the list */
curr = (aignore *) MALLOC(sizeof(aignore));
curr->time = now + t;
curr->next = IgnoreList;
IgnoreList = curr;
strcpy(curr->mask, mask);
add_silence(source, curr->mask);
notice(source, "I don't like being flooded! "
"I will ignore you from now on.");
/* schedule ignore removal */
AddEvent(EVENT_CLEAN_IGNORES, curr->time, "");
/* If there are already too many ignores from this site
* ignore the whole site
*/
if (count >= (MAX_IGNORE_PER_SITE - 1))
{
curr = (aignore *) MALLOC(sizeof(aignore));
curr->time = now + 300;
curr->next = IgnoreList;
IgnoreList = curr;
#ifdef DEBUG
printf("TOO MANY IGNORES FROM THE SAME SITE\n");
#endif
log("Too many ignores.. ignoring the whole site");
sprintf(curr->mask, "*!*@%s", site);
sprintf(buffer, "Ignoring the whole site! (%s)", site);
broadcast(buffer, 1);
add_silence(source, curr->mask);
AddEvent(EVENT_CLEAN_IGNORES, curr->time, "");
}
}
void CleanIgnores(void)
{
char buffer[200];
aignore *curr, *prev;
prev = NULL;
curr = IgnoreList;
while (curr != NULL)
{
if (curr->time <= now)
{
sprintf(buffer, "Removing ignore for %s", curr->mask);
log(buffer);
rem_silence(curr->mask);
if (prev != NULL)
{
prev->next = curr->next;
TTLALLOCMEM -= sizeof(aignore);
free(curr);
curr = prev->next;
}
else
{
IgnoreList = curr->next;
TTLALLOCMEM -= sizeof(aignore);
free(curr);
curr = IgnoreList;
}
}
else
{
prev = curr;
curr = curr->next;
}
}
}
int IsIgnored(char *nick)
{
char userhost[200];
register aignore *curr;
register aluser *user;
register int found = 0;
if ((user = ToLuser(nick)) == NULL)
{
return 1;
}
sprintf(userhost, "%s!%s@%s", user->nick, user->username, user->site);
curr = IgnoreList;
while (curr != NULL && !found)
{
if (compare(userhost, curr->mask))
{
add_silence(nick, curr->mask);
found++;
}
curr = curr->next;
}
return (found);
}
void ShowIgnoreList(char *source, char *channel, char *args)
{
char buffer[200];
aignore *curr = IgnoreList;
time_t m;
if (curr == NULL)
{
notice(source, "Ignore list is empty");
}
else
{
notice(source, "Ignore list:");
while (curr != NULL)
{
m = (curr->time - now) / 60 + 1;
sprintf(buffer, "%s for %ld minute%s",
curr->mask, m, (m > 1) ? "s" : "");
notice(source, buffer);
curr = curr->next;
}
}
}
void add_silence(char *nick, char *mask)
{
char buffer[200];
sprintf(buffer, ":%s SILENCE %s :%s\n", mynick, nick, mask);
sendtoserv(buffer);
#ifdef FAKE_UWORLD
if (Uworld_status == 1)
{
sprintf(buffer, ":%s SILENCE %s :%s\n", UFAKE_NICK, nick, mask);
sendtoserv(buffer);
}
#endif
}
void rem_silence(char *mask)
{
char buffer[200];
sprintf(buffer, ":%s SILENCE * -%s\n", mynick, mask);
sendtoserv(buffer);
#ifdef FAKE_UWORLD
if (Uworld_status == 1)
{
sprintf(buffer, ":%s SILENCE * -%s\n", UFAKE_NICK, mask);
sendtoserv(buffer);
}
#endif
}
int CheckFloodFlood(char *source, int length)
{
char buffer[200];
char userhost[200];
char global[] = "*";
register aluser *user;
register aprivmsg *msg, *prev;
register int count, size;
if ((user = ToLuser(source)) == NULL)
{
sprintf(buffer, "ERROR! CheckFloodFlood(): %s not found", source);
log(buffer);
return 1;
}
/* Don't check flood from admins */
if (IsValid(user, global) && Access(global, source) >= 1)
return 0;
if (!strcasecmp(user->username, DEFAULT_USERNAME) &&
!strcasecmp(user->site, DEFAULT_HOSTNAME))
{
return 0;
}
/* clean messages older than 30 seconds */
prev = NULL;
msg = FloodList;
while (msg != NULL)
{
if (msg->time < (now - 30))
{
if (prev)
{
prev->next = msg->next;
TTLALLOCMEM -= sizeof(aprivmsg);
free(msg);
msg = prev->next;
}
else
{
FloodList = msg->next;
TTLALLOCMEM -= sizeof(aprivmsg);
free(msg);
msg = FloodList;
}
}
else
{
prev = msg;
msg = msg->next;
}
}
/* now add the current message in the list */
sprintf(userhost, "%s@%s", user->username, user->site);
msg = (aprivmsg *) MALLOC(sizeof(aprivmsg));
strcpy(msg->user, userhost);
msg->time = now;
msg->length = length;
msg->next = FloodList;
FloodList = msg;
/* count how many messages were received from that user
* and also how many bytes
*/
count = size = 0;
for (msg = FloodList; msg != NULL; msg = msg->next)
{
if (compare(userhost, msg->user))
{
count++;
size += msg->length;
}
}
if (count >= FLOOD_FLOOD_RATE || size >= FLOOD_FLOOD_SIZE)
{
if (!IsIgnored(source))
{
sprintf(buffer, "OUTPUT-FLOOD from %s!%s", user->nick, userhost);
log(buffer);
sprintf(buffer, "OUTPUT-FLOOD from %s!%s (%s)",
user->nick, userhost, user->server->name);
broadcast(buffer, 1);
}
MakeBanMask(user, buffer);
AddIgnore(source, buffer, FLOOD_FLOOD_IGNORE);
return 1;
}
return 0;
}
int CheckAdduserFlood(char *source, char *channel)
{
char buffer[200];
char userhost[200];
char global[] = "*";
register aluser *user;
register aprivmsg *msg, *prev;
register int count;
if ((user = ToLuser(source)) == NULL)
{
sprintf(buffer, "ERROR! CheckAdduserFlood(): %s not found", source);
log(buffer);
return 1;
}
/* Don't check flood from admins */
if (IsValid(user, global) && Access(global, source) >= 1)
return 0;
if (!strcasecmp(user->username, DEFAULT_USERNAME) &&
!strcasecmp(user->site, DEFAULT_HOSTNAME))
{
return 0;
}
/* clean messages older than 1 hour */
prev = NULL;
msg = AddUserFloodList;
while (msg != NULL)
{
if (msg->time < (now - 3600))
{
if (prev)
{
prev->next = msg->next;
TTLALLOCMEM -= sizeof(aprivmsg);
free(msg);
msg = prev->next;
}
else
{
AddUserFloodList = msg->next;
TTLALLOCMEM -= sizeof(aprivmsg);
free(msg);
msg = AddUserFloodList;
}
}
else
{
prev = msg;
msg = msg->next;
}
}
sprintf(userhost, "%s@%s", user->username, user->site);
/* now add the current message in the list */
msg = (aprivmsg *) MALLOC(sizeof(aprivmsg));
strcpy(msg->user, channel);
msg->time = now;
msg->length = 0;
msg->next = AddUserFloodList;
AddUserFloodList = msg;
/* count how many messages were received from that user
* and also how many bytes
*/
count = 0;
for (msg = AddUserFloodList; msg != NULL; msg = msg->next)
{
if (!strcmp(channel, msg->user))
{
count++;
}
}
if (count >= 20)
{
if (!IsIgnored(source))
{
sprintf(buffer, "ADDUSER-FLOOD from %s!%s [%s]", user->nick, userhost, channel);
log(buffer);
sprintf(buffer, "ADDUSER-FLOOD from %s!%s [%s] (%s)",
user->nick, userhost, channel, user->server->name);
broadcast(buffer, 1);
}
MakeBanMask(user, buffer);
AddIgnore(source, buffer, 120);
return 1;
}
return 0;
}
void AdminRemoveIgnore(char *source, char *ch, char *args)
{
char mask[200], global[] = "*";
char buffer[200];
aignore **curr, *tmp;
int change = 0;
if (Access(global, source) < XADMIN_LEVEL)
{
ReplyNotAccess(source, global);
return;
}
GetWord(0, args, mask);
if (!*mask)
{
notice(source, "SYNTAX: remignore <mask|all>");
return;
}
curr = &IgnoreList;
while (*curr != NULL)
{
if (!strcasecmp((*curr)->mask, mask) || !strcasecmp(mask, "all"))
{
change = 1;
sprintf(buffer, "removed %s", (*curr)->mask);
notice(source, buffer);
log(buffer);
rem_silence((*curr)->mask);
tmp = *curr;
*curr = tmp->next;
free(tmp);
TTLALLOCMEM -= sizeof(aignore);
}
else
{
curr = &(*curr)->next;
}
}
if (change)
{
sprintf(buffer, "%s removed ignore for [%s]", source, mask);
broadcast(buffer, 1);
}
}

148
Sources/kicks.c Normal file
View File

@@ -0,0 +1,148 @@
/* @(#)$Id: kicks.c,v 1.5 1997/07/18 07:55:04 cvs Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
void kick(char *source,char *chanarg,char *args)
{
char buffer[500];
char nick[80];
char channel[80];
char *comment;
int found=0;
achannel *chan;
auser *user;
if(*args=='#'){
GetWord(0,args,channel);
GetWord(1,args,nick);
comment=ToWord(2,args);
}else{
GetWord(0,args,nick);
comment=ToWord(1,args);
strcpy(channel,chanarg);
GuessChannel(source,channel);
}
if(strlen(comment)>200)
comment[200]='\0';
if(!strcmp(channel,"*") || !*nick){
notice(source,"SYNTAX: kick [#channel] <nick|pattern> [reason]");
return;
}
chan=ToChannel(channel);
if(!chan||!chan->on){
if(*source)
notice(source,replies[RPL_NOTONCHANNEL][L_DEFAULT]);
return;
}
if(*source && (chan->flags&CFL_OPONLY)){
notice(source,replies[RPL_OPONLY][chan->lang]);
return;
}
if(!chan->AmChanOp){
if(*source)
notice(source,replies[RPL_NOTCHANOP][chan->lang]);
return;
}
/* check whether there are wildcards or not.
* if there are wildcards, it's a masskick and nick is a match pattern
* otherwise, it's an ordinary kick and nick is the nick to kick
*/
if(!strpbrk(nick,"*?")){
#ifdef DEBUG
printf("KICK REQUEST (NO WILDCARDS)\nSOURCE %s\nCHANNEL %s\nTARGET %s\n",
source,channel,nick);
#endif
if(*source&&Access(channel,source)<KICK_LEVEL){
ReplyNotAccess(source,channel);
return;
}
user=ToUser(channel,nick);
if(!user) return;
if(*comment){
if(*source)
sprintf(buffer,":%s KICK %s %s :(%s) %s\n",
mynick,channel,nick,source,comment);
else
sprintf(buffer,":%s KICK %s %s :%s\n",
mynick,channel,nick,comment);
}else{
if(*source)
sprintf(buffer,":%s KICK %s %s :From %s\n",
mynick,channel,nick,source);
else
sprintf(buffer,":%s KICK %s %s :%s\n",
mynick,channel,nick,mynick);
}
sendtoserv(buffer);
sprintf(buffer,"I KICK %s OFF %s",nick,channel);
log(buffer);
}else{
#ifdef DEBUG
printf("KICK REQUEST (WITH WILDCARDS)\nSOURCE %s\nCHANNEL %s\nTARGET %s\n",
source,channel,nick);
#endif
if(*source&&Access(channel,source)<MASS_KICK_LEVEL){
ReplyNotAccess(source,channel);
return;
}
user=chan->users;
while(user){
sprintf(buffer,"%s!%s@%s",user->N->nick,user->N->username,user->N->site);
if(match(buffer,nick)&&(!*source||strcasecmp(user->N->nick,source))){
if(*comment){
if(*source)
sprintf(buffer,":%s KICK %s %s :(%s) %s\n",mynick,channel,user->N->nick,source,comment);
else
sprintf(buffer,":%s KICK %s %s :%s\n",mynick,channel,user->N->nick,comment);
}else{
if(*source)
sprintf(buffer,":%s KICK %s %s :From %s\n",
mynick,channel,user->N->nick,source);
else
sprintf(buffer,":%s KICK %s %s :%s\n",
mynick,channel,user->N->nick,mynick);
}
sendtoserv(buffer);
sprintf(buffer,"I KICK %s OFF %s",user->N->nick,channel);
log(buffer);
found=1;
}
user=user->next;
}
if(*source && !found)
notice(source,replies[RPL_NOMATCH][chan->lang]);
}
}

35
Sources/lang.h Normal file
View File

@@ -0,0 +1,35 @@
/* @(#)$Id: lang.h,v 1.5 1999/01/09 16:51:31 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#define NO_LANG 5
#define L_ENGLISH 0
#define L_DUTCH 1
#define L_FRENCH 2
#define L_SPANISH 3
#define L_GERMAN 4
#define L_DEFAULT L_ENGLISH

122
Sources/list.c Normal file
View File

@@ -0,0 +1,122 @@
/* @(#)$Id: list.c,v 1.3 1996/11/13 00:40:43 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <netinet/in.h>
#include "defines.h"
#include "struct.h"
#include "version.h"
#include "../config.h"
typedef struct DiskUser {
char realname[80];
char match[80];
int Access;
char passwd[20];
char channel[80];
unsigned long flags;
char reserved[20];
time_t suspend;
time_t lastseen;
} DiskUser;
void main(void)
{
FILE *in1,*in2;
FILE *out;
char *ptr;
adefchan channel;
DiskUser user;
time_t currtime;
if(chdir(HOMEDIR)<0){
perror(HOMEDIR);
exit(1);
}
out=fopen("Registered_Channels","w");
if(out==NULL){
fclose(in1);
perror("Registered_Channels");
exit(1);
}
currtime=time(NULL);
fprintf(out,
"%s\n"
"(c) 1995,1996 by Robin Thellend <intru@info.polymtl.ca>\n"
"\n"
"This is the list of currently registered channels on Undernet.\n"
"Note that secret and private channels are NOT showed here.\n"
"This file is updated every hour.\n"
"\n"
"Last update: %s"
"Montreal's local time is used.\n\n",
VERSION,ctime(&currtime));
in1=fopen(DEFAULT_CHANNELS_FILE,"r");
if(in1==NULL){
fprintf(out,"There are no registered channels\n");
return;
}
while(fread(&channel,sizeof(adefchan),1,in1)>0){
ptr=strchr(channel.mode,' ');
if(ptr!=NULL)
*ptr='\0';
/* don't show secret or private channel */
if(strpbrk(channel.mode,"sp"))
continue;
fprintf(out,"%s Created: %s",channel.name,ctime(&channel.TS));
in2=fopen(USERFILE,"r");
if(in2==NULL){
fprintf(out,"Can't open \"%s\"\n",USERFILE);
}else{
while(fread(&user,sizeof(DiskUser),1,in2)>0){
if(!strcasecmp(user.channel,channel.name)&&
user.Access>=SET_DEFAULT_LEVEL){
fprintf(out," %s %s Last seen: %s",
user.realname,user.match,
ctime(&user.lastseen));
}
}
fclose(in2);
}
fprintf(out,"\n");
}
fclose(in1);
fclose(out);
}

79
Sources/listall.c Normal file
View File

@@ -0,0 +1,79 @@
/* @(#)$Id: listall.c,v 1.3 1996/11/13 00:40:43 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <netinet/in.h>
#include "defines.h"
#include "struct.h"
#include "version.h"
#include "../config.h"
typedef struct DiskUser {
char realname[80];
char match[80];
char passwd[20];
char channel[80];
char modif[80];
int Access;
unsigned long flags;
time_t suspend;
time_t lastseen;
} DiskUser;
void main(void)
{
FILE *in1,*in2;
FILE *out;
char *ptr;
adefchan channel;
DiskUser user;
time_t currtime;
if(chdir(HOMEDIR)<0){
perror(HOMEDIR);
exit(1);
}
out=stdout;
currtime=time(NULL);
in2=fopen(USERFILE,"r");
while(fread(&user,sizeof(DiskUser),1,in2)>0){
for(ptr=user.channel;*ptr;ptr++)
*ptr=tolower(*ptr);
fprintf(out,"[%s] %s %s (%d) Last modif: %s, Last seen: %s",
user.channel,
user.realname,user.match,user.Access,
user.modif,ctime(&user.lastseen));
}
fclose(in2);
fclose(out);
}

1002
Sources/main.c Normal file

File diff suppressed because it is too large Load Diff

0
Sources/make.dep Normal file
View File

316
Sources/match.c Normal file
View File

@@ -0,0 +1,316 @@
/* @(#)$Id: match.c,v 1.10 1999/03/06 19:15:34 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#include <regex.h>
static int matchX(char *, char *);
int mycasecmp(char *s1, char *s2)
{
register unsigned char *c1 = (unsigned char *)s1, *c2 = (unsigned char *)s2;
register int d;
while (!(d = (toupper(*c1) - toupper(*c2))) && *c1)
{
c1++;
c2++;
}
return d;
}
char *strcasestr(register char *s1, char *s2)
{
register char *a, *b;
while (*s1)
{
a = s1;
b = s2;
while (*b && *a && toupper(*a) == toupper(*b))
{
a++;
b++;
}
if (!*b)
return s1;
s1++;
}
return NULL;
}
/* xmatch() returns 1 if both pat1 and pat2 can *possibly*
* match the same string. It returns 0 otherwise.
*/
int xmatch(char *pat1, char *pat2)
{
if (!strcmp(pat1, "*") || !strcmp(pat2, "*"))
return 1;
while (*pat1 && *pat2)
{
if (*pat1 == '*' && *pat2 == '*')
return (matchX(pat1 + 1, pat2 + 1) || matchX(pat2 + 1, pat1 + 1));
if (*pat1 == '*')
return matchX(pat1 + 1, pat2);
if (*pat2 == '*')
return matchX(pat2 + 1, pat1);
if (*pat1 == '?' || *pat2 == '?' || toupper(*pat1) == toupper(*pat2))
{
pat1++;
pat2++;
if ((!*pat1 && !strcmp(pat2, "*")) ||
(!*pat2 && !strcmp(pat1, "*")))
return 1;
}
else
return 0;
}
if (*pat1 || *pat2)
return 0;
return 1;
}
static int matchX(char *pat1, char *pat2)
{
do
{
if (xmatch(pat1, pat2))
return 1;
}
while (*pat2++);
return 0;
}
int match(register char *string, register char *mask)
{
char *stack[200][2] = {{NULL, NULL}};
register char type = 0;
register short quote, level = 0;
while (*string)
{
quote = 0;
switch (*mask)
{
case '*':
type = '*';
if (++level == 200)
return 0;
stack[level][0] = mask;
stack[level][1] = string;
while (*++mask == '*'); /* '*' eats any following '*' */
break;
case '\\':
quote++;
mask++;
/* no break! */
default:
if (toupper(*string) == toupper(*mask) || (*mask == '?' && !quote))
{
mask++;
}
else
{
while (stack[level][0] == NULL && --level > 0);
if (level <= 0)
return 0;
mask = stack[level][0];
string = stack[level][1];
level--;
}
string++;
}
}
while (*mask == '*') /* Skip everything that can */
mask++; /* match an empty string. */
return (*mask) ? 0 : 1;
}
/* compare() will return 1 if p1 and p2 can match the same
* nick!user@host. p1 and p2 are nick!user@host masks.
*/
int compare(char *p1, char *p2)
{
char tmp1[200], tmp2[200];
register char *s1 = tmp1, *s2 = tmp2;
register int ip1, ip2, in_uh = 0;
do
{
ip1 = ip2 = 1;
while (*p1 && *p1 != '!' && *p1 != '@')
{
if (ip1 && !isdigit(*p1) && *p1 != '.' && (*p1 != '*' || p1[1]) && (*p1 == '*' || s1 != tmp1))
ip1 = 0;
*(s1++) = *(p1++);
}
if (!in_uh && *p1 == '\0')
in_uh = 1;
while (*p2 && *p2 != '!' && *p2 != '@')
{
if (ip2 && !isdigit(*p2) && *p2 != '.' && (*p2 != '*' || p2[1]) && (*p2 == '*' || s2 != tmp2))
ip2 = 0;
*(s2++) = *(p2++);
}
*s2 = *s1 = '\0';
if (*p1 != *p2)
{
if (*p1 == '!')
{
s1 = tmp1;
if (*p1)
p1++;
while (*p1 && *p1 != '@')
{
if (ip1 && !isdigit(*p1) && *p1 != '.' && (*p1 != '*' || p1[1]) && (*p1 == '*' || s1 != tmp1))
ip1 = 0;
*(s1++) = *(p1++);
}
if (!in_uh && *p1 == '\0')
in_uh = 1;
}
else
{
s2 = tmp2;
if (*p2)
p2++;
while (*p2 && *p2 != '@')
{
if (ip2 && !isdigit(*p2) && *p2 != '.' && (*p2 != '*' || p2[1]) && (*p1 == '*' || s2 != tmp2))
ip2 = 0;
*(s2++) = *(p2++);
}
}
*s2 = *s1 = '\0';
}
if ((in_uh && ip1 != ip2) || !xmatch(tmp1, tmp2))
return 0;
if (*p1)
p1++;
if (*p2)
p2++;
s1 = tmp1;
s2 = tmp2;
}
while (*p1);
return 1;
}
int key_match(char *s, char *tok[])
{
register int k;
for (k = 0; tok[k] != NULL; k++)
{
if (!strcasestr(s, tok[k]))
return 0;
}
return 1;
}
void string_swap(char *buf, size_t size, char *orig, char *new)
{
char *ptr, *buf2;
buf2 = (char *)alloca(sizeof(char) * size);
while ((ptr = strstr((buf), orig)))
{
*ptr = '\0';
strncpy(buf2, buf, size - 1);
strncat(buf2, new, size - strlen(buf) - 1);
strncat(buf2, ptr + strlen(orig), size - strlen(buf) - strlen(new) - 1);
strcpy(buf, buf2);
}
}
/* regex_cmp() (stolen from RCSD)
* This function compares a regular expression (patern) with a string.
* Return value: 1 if there is a match
* 0 otherwise
*
* Note: if patern is NULL, the last patern that was passed to the
* function is used.
*/
#define HAVE_REGEXEC
int regex_cmp(char *patern, char *string)
{
#if defined(HAVE_REGEXEC)
static regex_t preg;
static int called_once = 0;
register int cmpv = 0, execv;
if (patern != NULL)
{
if (called_once)
regfree(&preg);
cmpv = regcomp(&preg, patern, REG_EXTENDED | REG_ICASE | REG_NOSUB);
}
called_once = 1;
if (cmpv == 0)
execv = regexec(&preg, string, 0, NULL, 0);
return cmpv ? 0 : execv ? 0 : 1;
#elif defined(HAVE_RE_EXEC)
register char *ptr;
ptr = re_comp(patern);
return ptr ? 0 : re_exec(string);
#else
#error neither re_exec() nor rexexec() :/
#endif
}
#ifdef MATCHALONE
void main(void)
{
char str1[80];
char str2[80];
puts("#1");
gets(str1);
puts("#2");
gets(str2);
printf("match: %d\n", match(str1, str2));
}
#endif

970
Sources/modes.c Normal file
View File

@@ -0,0 +1,970 @@
/* @(#)$Id: modes.c,v 1.10 1999/04/04 17:00:11 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
static void AddFlag(char *, char, char *);
static void RemFlag(char *, char);
void setchanmode(char *line)
{
register char *mode;
register achannel *chan;
if ((mode = strchr(line, ' ')) != NULL)
*(mode++) = 0;
chan = ToChannel(line);
if (!chan)
return;
strcpy(chan->mode, mode + 1); /* why +1 ???? coz I don't want the + */
}
void AddFlag(char *string, char flag, char *arg)
{
char newmode[15];
char newarg[200];
if (strchr(string, flag))
RemFlag(string, flag);
GetWord(0, string, newmode);
*(newmode + strlen(newmode) + 1) = 0;
*(newmode + strlen(newmode)) = flag;
strcpy(newarg, ToWord(1, string));
if (arg)
{
strcat(newarg, arg);
strcat(newarg, " ");
}
sprintf(string, "%s %s", newmode, newarg);
}
void RemFlag(char *string, char flag)
{
char newmode[15];
char newarg[200];
register char *ptr;
register char *curr = newmode;
register int count = 0;
GetWord(0, string, newmode);
strcpy(newarg, ToWord(1, string));
while (*curr)
{
ptr = strchr("lk", *curr);
if (*curr == flag)
{
strcpy(curr, curr + 1);
if (ptr)
strcpy(ToWord(count, newarg), ToWord(count + 1, newarg));
}
else
{
if (ptr)
count++;
curr++;
}
}
sprintf(string, "%s %s", newmode, newarg);
}
int IsSet(char *channel, char flag, char *param)
{
register achannel *chan;
register char *setmode;
char setflags[20];
char setparam[80];
register int out;
register int i, j;
chan = ToChannel(channel);
if (chan == NULL)
return 0;
setmode = chan->mode;
GetWord(0, setmode, setflags);
j = 0;
for (i = 0; setflags[i] != '\0' && setflags[i] != flag; i++)
{
if (setflags[i] == 'l' || setflags[i] == 'k')
j++;
}
if (setflags[i] != '\0')
{
if (flag == 'l' || flag == 'k')
{
GetWord(j + 1, setmode, setparam);
if (!strcmp(setparam, param))
out = 1;
else
out = 0;
}
else
{
out = 1;
}
}
else
{
out = 0;
}
#ifdef DEBUG
printf("IsSet(): +%c %s on %s (%d)\n", flag, param, channel, out);
#endif
return (out);
}
void bounce(char *channel, char *change, time_t TS)
{
char buffer[200];
char arg[200];
register char sign = '+';
register auser *user;
register achannel *chan;
register int pos = 1;
register int i;
chan = ToChannel(channel);
for (i = 0; change[i] != '\0' && change[i] != ' '; i++)
{
if (change[i] == '+')
sign = '+';
else if (change[i] == '-')
sign = '-';
else if (change[i] == 'o')
{
GetWord(pos++, change, arg);
user = ToUser(channel, arg);
if (user == NULL)
continue;
if (sign == '+')
{
if (!user->chanop)
{
changemode(channel, "-o", arg, 1);
user->chanop = 0;
}
}
else
{
if (user->chanop)
{
/*
changemode(channel,"+o",arg,1);
user->chanop=1;
*/
/* don't bounce -o */
user->chanop = 0;
}
}
}
else if (change[i] == 'v')
{
GetWord(pos++, change, arg);
if (sign == '+')
changemode(channel, "-v", arg, 1);
else
changemode(channel, "+v", arg, 1);
}
else if (change[i] == 'k')
{
GetWord(pos++, change, arg);
if (sign == '+')
{
if (!IsSet(channel, 'k', arg))
changemode(channel, "-k", arg, 1);
}
else
{
if (IsSet(channel, 'k', arg))
changemode(channel, "+k", arg, 1);
}
}
else if (change[i] == 'l')
{
pos++;
if (sign == '+' && !IsSet(channel, 'l', arg))
changemode(channel, "-l", "", 1);
}
else if ((IsSet(channel, change[i], "") && sign == '-') ||
(!IsSet(channel, change[i], "") && sign == '+'))
{
sprintf(buffer, "%c%c",
(sign == '+') ? '-' : '+',
change[i]);
changemode(channel, buffer, "", 1);
}
}
AddEvent(EVENT_FLUSHMODEBUFF, now + MODE_DELAY, channel);
}
void ModeChange(char *source, char *channel, char *change)
{
register char sign = '+';
char arg[200];
register char *ptr;
register achannel *chan;
register aluser *u;
register int count = 1;
int desync = 0;
#ifdef DEBUG
printf("ModeChange(%s, %s, %s)\n", source, channel, change);
#endif
chan = ToChannel(channel);
/* if chan == NULL at this point.. we're dealing with a
* user mode change
*/
if (chan != NULL)
chan->lastact = now;
u = ToLuser(source);
if (chan == NULL && u == NULL)
{
return; /* probably a lost MODE */
}
if (u == NULL)
{
/* This is a mode change from a server.. if it is not
* a +b, then the last argument is a TS
*/
for (ptr = change; *ptr != 'b' && *ptr != ' '; ptr++);
if (*ptr != 'b' && strcasecmp(UWORLD_SERVER, source)
#ifdef UWORLD2
&& strcasecmp(UWORLD2_SERVER, source)
#endif
#ifdef FAKE_UWORLD
&& strcasecmp(UFAKE_SERVER, source)
#endif
)
{
ptr = change + strlen(change);
while (*ptr != ' ')
ptr--;
*(ptr++) = '\0';
if (atol(ptr) > chan->TS && atol(ptr) != 0 && chan->on)
{
log(source);
log(channel);
log(change);
log(ptr);
bounce(channel, change, chan->TS);
return;
}
if (atol(ptr) != 0)
chan->TS = atol(ptr);
}
}
while (*change && *change != ' ')
{
if (*change == '+')
{
sign = '+';
}
else if (*change == '-')
{
sign = '-';
}
else
{
if (sign == '+')
{
if (chan != NULL)
{
ptr = strchr("blkov", *change);
if (ptr)
{
GetWord(count, change, arg);
if (strchr("lk", *change) && *arg)
AddFlag(chan->mode, *change, arg);
count++;
}
else
{
if (strchr("imntps", *change))
AddFlag(chan->mode, *change, NULL);
}
}
else
{
/* user mode change (+) */
if (*change == 'o')
{
u->mode |= LFL_ISOPER;
#ifdef DEBUG
printf("%s is now IRCOP\n", source);
#endif
}
}
}
else
{
if (chan != NULL)
{
ptr = strchr("bkov", *change);
if (strchr("ilkmntps", *change))
RemFlag(chan->mode, *change);
if (ptr)
{
GetWord(count, change, arg);
count++;
}
}
else
{
/* user mode change (-) */
if (*change == 'o')
{
u->mode &= ~LFL_ISOPER;
#ifdef DEBUG
printf("%s is no longer IRCOP\n", source);
#endif
}
}
}
/** other tests should go here **/
if (chan != NULL)
{
if (*change == 'o')
{
if (sign == '+')
onop(source, channel, arg);
else
ondeop(source, channel, arg, &desync);
}
else if (*change == 'b')
{
if (sign == '+')
onban(source, channel, arg);
else
onunban(source, channel, arg);
}
else if (*change == 'l')
{
if (sign == '+' && atoi(arg) < 2)
{
if (chan->on && chan->AmChanOp)
{
changemode(channel, "-l", "", 0);
RemFlag(chan->mode, *change);
}
}
}
}
}
change++;
if (*change == ' ')
{
change = ToWord(count, change);
count = 1;
}
}
if (chan != NULL)
{
if (desync)
{
part("", channel, "");
join("", channel, "");
}
CheckFlood(source, channel, 80);
flushmode(channel);
}
}
void onop(char *source, char *channel, char *target)
{
register auser *user;
register aluser *luser;
register achannel *chan;
char buffer[200];
chan = ToChannel(channel);
luser = ToLuser(source);
user = ToUser(channel, target);
if (!strcasecmp(mynick, target))
{
if (!chan)
{
log("ERROR: onop() channel not found!");
return;
}
chan->AmChanOp = 1;
}
else
{
#ifdef DEBUG
printf("OP for %s on %s\n", target, channel);
#endif
if (!user)
{
sprintf(buffer, "ERROR: onop() user not found (%s)",
target);
log(buffer);
return;
}
user->chanop = 1;
sprintf(buffer, "%s!%s@%s", user->N->nick, user->N->username, user->N->site);
if (luser && chan->on && (chan->flags & CFL_NOOP))
{
sprintf(buffer, "NoOp MODE! deopping %s and %s",
target, source);
log(buffer);
notice(target, replies[RPL_NOOP][chan->lang]);
notice(source, replies[RPL_NOOP][chan->lang]);
changemode(channel, "-o", target, 0);
changemode(channel, "-o", source, 0);
user->chanop = 0;
user = ToUser(channel, source);
if (user != NULL)
{
user->chanop = 0;
}
}
else if (luser && chan->on && (chan->flags & CFL_STRICTOP) &&
Access(channel, target) < OP_LEVEL)
{
sprintf(buffer, "StrictOp MODE! deopping %s and %s",
target, source);
log(buffer);
notice(target, "Only authenticated users may be op in StrictOp mode");
notice(source, "Only authenticated users may be op in StrictOp mode");
changemode(channel, "-o", target, 0);
user->chanop = 0;
if (Access(channel, source) < OP_LEVEL)
{
changemode(channel, "-o", source, 0);
user = ToUser(channel, source);
if (user != NULL)
{
user->chanop = 0;
}
}
}
else if (luser && chan->on && IsShit(channel, buffer, NULL, NULL) >= NO_OP_SHIT_LEVEL)
{
if (Access(channel, source) < ACCESS_BAN_PRIORITY)
{
sprintf(buffer, "%s is shitlisted (NO-OP LEVEL)!"
"Deopping %s and %s", target, target, source);
log(buffer);
notice(target, replies[RPL_CANTBEOP][chan->lang]);
notice(source, replies[RPL_CANTBEOPPED][chan->lang]);
changemode(channel, "-o", target, 0);
changemode(channel, "-o", source, 0);
user->chanop = 0;
user = ToUser(channel, source);
if (user != NULL)
user->chanop = 0;
sprintf(buffer, "%s %d", source, SUSPEND_TIME_FOR_OPPING_A_SHITLISTED_USER);
suspend("", channel, buffer);
}
else
{
unban(source, channel, target);
}
}
}
/** further tests should be put here **/
#ifdef NICKSERV
nserv_onop(channel, user);
#endif
}
void ondeop(char *source, char *channel, char *target, int *desync)
{
char buffer[200];
register auser *user1, *user2;
register achannel *chan;
register adeop *curr, *prec;
register int i;
chan = ToChannel(channel);
if (!chan)
{
log("ERROR: ondeop() channel not found!");
return;
}
user1 = ToUser(channel, source);
user2 = ToUser(channel, target);
if (chan->on && user1 == NULL)
{ /* desync! */
if (user2 != NULL)
{
user2->chanop = 0;
}
sprintf(buffer, "DESYNC detected! (%s deopped %s on %s)",
source, target, channel);
log(buffer);
/* part("",channel,"");
join("",channel,""); now doing this in ChangeMode */
*desync = 1;
return;
}
if (!strcasecmp(mynick, target))
{
if ((chan->flags & CFL_ALWAYSOP) &&
Access(channel, source) >= ALWAYSOP_OVERRIDE_LEVEL)
{
chan->flags &= ~CFL_ALWAYSOP;
sprintf(buffer, "AlwaysOp is turned off on %s (deopped by %s!%s@%s)",
channel, user1->N->nick, user1->N->username, user1->N->site);
log(buffer);
notice(source, replies[RPL_ALWAYSOPWASACTIVE][chan->lang]);
}
if (chan->flags & CFL_ALWAYSOP)
{
if (user1 != NULL)
{
sprintf(buffer, "DEOPPED by %s!%s@%s (%d) while AlwaysOp active on %s",
user1->N->nick, user1->N->username, user1->N->site,
Access(channel, source), channel);
log(buffer);
broadcast(buffer, 0);
i = IsShit(channel, source, NULL, NULL);
notice(source, replies[RPL_ALWAYSOP][chan->lang]);
switch (i)
{
case 0:
case 1:
case 2:
case 3:
case 4:
log("First warning");
notice(source, replies[RPL_DEOPPED1ST][chan->lang]);
changemode(channel, "-o", source, 0);
flushmode(channel);
user1->chanop = 0;
break;
case 5:
case 6:
case 7:
case 8:
case 9:
log("Second warning");
notice(source, replies[RPL_DEOPPED2ND][chan->lang]);
kick("", channel, source);
break;
default:
notice(source, "I warned you!");
changemode(channel, "-o", source, 0);
flushmode(channel);
user1->chanop = 0;
sprintf(buffer, "%s!%s@%s %d",
user1->N->nick, user1->N->username,
user1->N->site,
DEOPME_SUSPEND_TIME);
suspend("", channel, buffer);
sprintf(buffer, "Suspended %s!%s@%s on %s for repeatedly deopping me",
user1->N->nick, user1->N->username, user1->N->site, channel);
SpecLog(buffer);
broadcast(buffer, 0);
}
sprintf(buffer, "%s %d %d *** DEOP WHILE ALWAYSOP ACTIVE ***",
source, DEOP_SHITLIST_TIME,
(i < 10) ? i + 5 :
DEOP_SHITLIST_LEVEL);
AddToShitList("", channel, buffer, 0);
chan->AmChanOp = 0; /* to remove if I reop myself */
GetOps(channel);
}
}
else
{
chan->AmChanOp = 0;
if (IsOpless(channel))
onopless(channel);
}
}
/* massdeop protection does NOT apply to the bot itself!
if(!strcasecmp(source,mynick)) return; obsolete */
/* No protection against server deop :/
Hey! I'm not gonna /squit it just for doing a deop!! ;) */
if (!user1)
return;
if (user2)
user2->chanop = 0;
chan = ToChannel(channel);
if (!chan)
{
log("ERROR: ondeop() channel not found!");
return;
}
/* If not on channel.. do NOT check for massdeop
*/
if (!chan->on)
return;
curr = user1->deophist;
prec = NULL;
/* ok.. let's free the *old* deops from history */
while (curr)
{
if (curr->time < (now - 15) || !strcasecmp(curr->nick, target))
{
if (prec)
{
prec->next = curr->next;
TTLALLOCMEM -= sizeof(adeop);
free(curr);
curr = prec->next;
}
else
{
user1->deophist = curr->next;
TTLALLOCMEM -= sizeof(adeop);
free(curr);
curr = user1->deophist;
}
}
else
{
prec = curr;
curr = curr->next;
}
}
/* now store the deop in the user's deop history */
curr = (adeop *) MALLOC(sizeof(adeop));
strcpy(curr->nick, target);
curr->time = now;
curr->next = user1->deophist;
user1->deophist = curr;
/* now we count the number of deop in the user's history
if it's equal to the max number of deops per 15 seconds
interval.. activate the massdeop protection */
for (curr = user1->deophist, i = 0; curr; curr = curr->next, i++);
if (i == chan->MassDeopPro && chan->MassDeopPro != 0 && chan->on)
{
sprintf(buffer, "MASSDEOP from %s on %s", source, channel);
log(buffer);
notice(source, "### MASSDEOP PROTECTION ACTIVATED ###");
if (Access(channel, source) >= MASSDEOP_IMMUNE_LEVEL)
{
notice(source, "You are lucky your access is so high :P");
}
else
{
sprintf(buffer, "%s %d", source, MASSDEOP_SUSPEND_TIME);
suspend("", channel, buffer);
sprintf(buffer, "%s %d %d *** MASSDEOP ***", source,
MASSDEOP_SHITLIST_TIME,
MASSDEOP_SHITLIST_LEVEL);
AddToShitList("", channel, buffer, 0);
sprintf(buffer, "%s ### MASSDEOP PROTECTION ###", source);
kick("", channel, buffer);
}
}
}
void onban(char *nick, char *channel, char *pattern)
{
#ifdef DEBUG
printf("Wah! BAN FROM: %s\nON CHANNEL %s\nTARGET: %s\n",
nick, channel, pattern);
#endif
AddBan(channel, pattern);
}
void onunban(char *source, char *channel, char *pattern)
{
/*register achannel *chan; */
RemBan(channel, pattern);
/* mode -b no longer removes the ban from X's banlist
** it has to be removed with the 'unban' command.
chan=ToChannel(channel);
if(chan!=NULL && chan->on)
RemShitList(source,channel,pattern,1);
* */
}
void AddBan(char *channel, char *pattern)
{
register achannel *chan;
register aban *theban;
char buffer[200];
chan = ToChannel(channel);
if (chan == NULL)
{
sprintf(buffer, "ERROR: AddBan(): can't find %s", channel);
log(buffer);
return;
}
/* check if ban isn't already there */
for (theban = chan->bans; theban != NULL; theban = theban->next)
{
if (!strncasecmp(theban->pattern, pattern, 79))
{
return;
}
}
theban = (aban *) MALLOC(sizeof(aban));
strncpy(theban->pattern, pattern, 79);
theban->pattern[79] = '\0';
theban->next = chan->bans;
chan->bans = theban;
}
void RemBan(char *channel, char *pattern)
{
register achannel *chan;
register aban **b, *theban = NULL;
chan = ToChannel(channel);
b = &chan->bans;
while (*b != NULL)
{
if (!strncasecmp((*b)->pattern, pattern, 79))
{
theban = *b;
*b = theban->next;
TTLALLOCMEM -= sizeof(aban);
free(theban);
}
else
{
b = &(*b)->next;
}
}
#ifdef DEBUG
if (theban == NULL)
{
printf("WARNING: RemBan(): pattern NOT found!!\n");
}
#endif
}
void changemode(char *channel, char *flag, char *arg, int AsServer)
{
register achannel *chan;
register modequeue *mode, *curr;
#ifdef DEBUG
printf("Queueing mode change for channel %s %s %s %d\n", channel, flag, arg, AsServer);
#endif
chan = ToChannel(channel);
if (!AsServer && (!chan || !chan->on))
return; /* not on the channel.. ignore */
/* first, cancel previous contradicting mode changes..
ex.. mode #test +o-o+o-o+o .. the bot won't do that.. */
mode = chan->modebuff;
while (mode)
{
if (!strcmp(arg, mode->arg) && flag[1] == mode->flag[1] &&
((flag[0] == '+' && mode->flag[0] == '-') ||
(flag[0] == '-' && mode->flag[0] == '+')))
{
if (mode->prev)
mode->prev->next = mode->next;
else
chan->modebuff = mode->next;
if (mode->next)
mode->next->prev = mode->prev;
curr = mode;
TTLALLOCMEM -= sizeof(modequeue);
free(curr);
}
else if (!strcmp(arg, mode->arg) && flag[1] == mode->flag[1] &&
flag[0] == mode->flag[0])
return;
mode = mode->next;
}
curr = (modequeue *) MALLOC(sizeof(modequeue));
strcpy(curr->arg, arg);
strcpy(curr->flag, flag);
curr->AsServer = AsServer;
curr->next = NULL;
for (mode = chan->modebuff; mode && mode->next; mode = mode->next);
if (mode)
{
curr->prev = mode;
mode->next = curr;
}
else
{
chan->modebuff = curr;
curr->prev = NULL;
}
}
void flushmode(char *channel)
{
char buffer[500];
register achannel *chan;
register modequeue *mode, *tmp;
char flags[20] = "";
char args[500] = "";
register char lastsign;
register int AsServer;
register int count = 0;
#ifdef DEBUG
printf("Flushing mode change buffer.. for channel %s\n", channel);
#endif
/* gotta pass thru the list twice:
* the first time, check for Server mode changes
* the second time, check for user mode changes
*/
chan = ToChannel(channel);
if (chan == NULL)
return;
#ifdef FAKE_UWORLD
#define ASSERVERMAX 2
#else
#define ASSERVERMAX 1
#endif
for (AsServer = ASSERVERMAX; AsServer >= 0; AsServer--)
{
#undef ASSERVERMAX
lastsign = '\0';
mode = chan->modebuff;
while (mode != NULL)
{
if (!strcmp(mode->flag, "-b"))
{
RemBan(channel, mode->arg);
}
else if (!strcmp(mode->flag, "+b"))
{
AddBan(channel, mode->arg);
}
if (AsServer == mode->AsServer)
{
if (mode->arg[0] != '\0')
{
count++;
strcat(args, " ");
strcat(args, mode->arg);
}
if (lastsign != mode->flag[0])
{
strcat(flags, mode->flag);
lastsign = mode->flag[0];
}
else
{
strcat(flags, mode->flag + 1);
}
if (mode->prev)
mode->prev->next = mode->next;
else
chan->modebuff = mode->next;
if (mode->next)
mode->next->prev = mode->prev;
tmp = mode;
mode = mode->next;
TTLALLOCMEM -= sizeof(modequeue);
free(tmp);
}
else
{
mode = mode->next;
}
if (count == MAX_MODE_PER_LINE || !mode)
{
if (AsServer == 0 && chan->AmChanOp && *flags != '\0')
{
sprintf(buffer, ":%s MODE %s %s%s\n",
mynick, channel, flags, args);
sendtoserv(buffer);
}
else if (AsServer == 1 && *flags != '\0')
{
sprintf(buffer, ":%s MODE %s %s%s %ld\n",
SERVERNAME, channel,
flags, args, chan->TS);
sendtoserv(buffer);
}
#ifdef FAKE_UWORLD
else if (AsServer == 2 && Uworld_status == 1 && *flags != '\0')
{
sprintf(buffer, ":%s MODE %s %s%s\n",
UFAKE_SERVER, channel,
flags, args);
sendtoserv(buffer);
}
#endif
count = *args = *flags = 0;
lastsign = '+';
}
}
}
}

81
Sources/nick.c Normal file
View File

@@ -0,0 +1,81 @@
/* @(#)$Id: nick.c,v 1.3 1996/11/13 00:40:44 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
void NickInUse(void)
{
char buffer[200];
sprintf(buffer,":%s SQUIT %s 0 :Unexpected nick collision\n",
SERVERNAME,SERVERNAME);
sendtoserv(buffer);
dumpbuff();
close(Irc.fd);
Irc.fd=-1;
QuitAll();
if(reconnect(server)){
try_later(server);
}
#if 0
char *ptr;
achannel *chan;
int index=0;
do{
if(!strcmp(mynick,DEFAULT_NICKNAME)){
strcat(mynick,"1");
}else{
ptr = (mynick+strlen(mynick)-1);
(*ptr)++;
if(*ptr>'z') *ptr='0';
}
}while(ToLuser(mynick)!=NULL);
sprintf(buffer,
"ERROR: ARGH! Nick already in use! Changing to %s",mynick);
log(buffer);
for(index=0;index<1000;index++){
chan=ChannelList[index];
while(chan!=NULL){
chan->on=chan->AmChanOp=0;
chan=chan->next;
}
}
/*logTS=time(NULL);*/
signon();
joindefault();
#endif
}
void ChNick(char *newnick)
{
char buffer[80];
sprintf(buffer,":%s NICK %s :%ld\n",mynick,newnick,now);
sendtoserv(buffer);
strcpy(mynick,newnick);
}

763
Sources/opcom.c Normal file
View File

@@ -0,0 +1,763 @@
/* @(#)$Id: opcom.c,v 1.19 2000/10/24 16:07:33 lgm Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
void CalmDown(char *source, char *chan, char *args)
{
register aluser *user;
register achannel *ch;
char buffer[200], channel[80], global[] = "*";
if ((user = ToLuser(source)) == NULL)
{
log("ERROR: CalmDown() can't locate user!");
return;
}
if (*args == '#')
{
GetWord(0, args, channel);
args = ToWord(1, args);
}
else
{
strcpy(channel, chan);
GuessChannel(source, channel);
}
if (!(user->mode & LFL_ISOPER) && Access(global, source) < XADMIN_LEVEL)
{
notice(source, "This command is reserved for IRC Operators");
return;
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: calmdown [channel]");
return;
}
ch = ToChannel(channel);
if (ch == NULL || !ch->on)
{
notice(source, replies[RPL_NOTONCHANNEL][L_DEFAULT]);
return;
}
sprintf(buffer, ":%s WALLOPS :%s!%s@%s is asking me to calm down on %s\n",
SERVERNAME, user->nick, user->username, user->site, ch->name);
sendtoserv(buffer);
sprintf(buffer, "%s!%s@%s is asking me to calm down on %s\n",
user->nick, user->username, user->site, ch->name);
broadcast(buffer, 0);
sprintf(buffer, "CALMDOWN requested by %s!%s@%s on %s",
user->nick, user->username, user->site, ch->name);
SpecLog(buffer);
/*
part("",channel,"");
RemChan("",channel,"");
*/
ch->flags |= CFL_NOOP;
massdeop(channel);
#ifdef CALMDOWNTOPIC
topic("", channel, CALMDOWNTOPIC);
#endif
}
void OperJoin(char *source, char *chan, char *args)
{
register aluser *user;
register achannel *ch;
char buffer[200], channel[80];
if ((user = ToLuser(source)) == NULL)
{
log("ERROR: OperJoin() can't locate user!");
return;
}
if (*args == '#')
{
GetWord(0, args, channel);
args = ToWord(1, args);
}
else
{
strcpy(channel, chan);
GuessChannel(source, channel);
}
if (!(user->mode & LFL_ISOPER))
{
notice(source, "This command is reserved for IRC Operators");
return;
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: operjoin <channel>");
return;
}
if (!IsReg(channel))
{
notice(source, "That channel is not registered");
return;
}
ch = ToChannel(channel);
if (ch != NULL && ch->on)
{
notice(source, "I am already on that channel");
return;
}
sprintf(buffer, ":%s WALLOPS :%s!%s@%s is asking me to join channel %s\n",
SERVERNAME, user->nick, user->username, user->site, channel);
sendtoserv(buffer);
sprintf(buffer, "%s!%s@%s is asking me join channel %s\n",
user->nick, user->username, user->site, channel);
broadcast(buffer, 0);
sprintf(buffer, "OPERJOIN requested by %s!%s@%s on %s",
user->nick, user->username, user->site, channel);
SpecLog(buffer);
join("", channel, "");
}
void OperPart(char *source, char *chan, char *args)
{
register aluser *user;
register achannel *ch;
char buffer[200], channel[80];
if ((user = ToLuser(source)) == NULL)
{
log("ERROR: OperPart() can't locate user!");
return;
}
if (*args == '#')
{
GetWord(0, args, channel);
args = ToWord(1, args);
}
else
{
strcpy(channel, chan);
GuessChannel(source, channel);
}
if (!(user->mode & LFL_ISOPER))
{
notice(source, "This command is reserved for IRC Operators");
return;
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: operpart [channel]");
return;
}
ch = ToChannel(channel);
if (ch == NULL || !ch->on)
{
notice(source, "I am not on that channel");
return;
}
sprintf(buffer, ":%s WALLOPS :%s!%s@%s is asking me to leave channel %s\n",
SERVERNAME, user->nick, user->username, user->site, channel);
sendtoserv(buffer);
sprintf(buffer, "%s!%s@%s is asking me to leave channel %s\n",
user->nick, user->username, user->site, channel);
broadcast(buffer, 0);
sprintf(buffer, "OPERPART requested by %s!%s@%s on %s",
user->nick, user->username, user->site, channel);
SpecLog(buffer);
part("", channel, "");
}
void ClearMode(char *source, char *chan, char *args)
{
register aluser *user;
register achannel *ch;
register char *curr;
register int i;
char buffer[200], channel[80], arg[80];
if ((user = ToLuser(source)) == NULL)
{
log("ERROR: ClearMode() can't locate user!");
return;
}
if (*args == '#')
{
GetWord(0, args, channel);
args = ToWord(1, args);
}
else
{
strcpy(channel, chan);
GuessChannel(source, channel);
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: clearmode [channel]");
return;
}
if (Access(channel, source) < CLEARMODE_LEVEL)
{
if (user->mode & LFL_ISOPER)
{
sprintf(buffer, ":%s WALLOPS :%s is using clearmode on %s\n",
SERVERNAME, source, channel);
sendtoserv(buffer);
}
else
{
ReplyNotAccess(source, channel);
return;
}
}
if ((ch = ToChannel(channel)) == NULL)
{
notice(source, "No such channel!");
return;
}
if (!ch->on || !ch->AmChanOp)
{
notice(source, replies[RPL_NOTCHANOP][ch->lang]);
return;
}
sprintf(buffer, "CLEARMODE on %s requested by %s!%s@%s",
channel, user->nick, user->username, user->site);
log(buffer);
curr = ch->mode;
i = 1;
while (*curr && *curr != ' ')
{
if (strchr("kl", *curr))
{
GetWord(i++, ch->mode, arg);
if (*curr == 'k')
{
changemode(channel, "-k", arg, 0);
}
else
{
changemode(channel, "-l", "", 0);
}
}
else
{
sprintf(buffer, "-%c", *curr);
changemode(channel, buffer, "", 0);
}
curr++;
}
ch->mode[0] = '\0';
flushmode(channel);
}
void verify(char *source, char *arg)
{
aluser *luser;
char buffer[200], nick[80], global[] = "*", *oper;
int acc;
GetWord(0, arg, nick);
if (!*nick)
{
notice(source, "SYNTAX: verify <nick>");
return;
}
luser = ToLuser(nick);
if (luser == NULL)
{
sprintf(buffer, "No such nick: %s", nick);
notice(source, buffer);
return;
}
if (luser->mode & LFL_ISOPER)
{
oper = " and an IRC operator";
}
else
{
oper = "";
}
acc = Access(global, nick);
if (acc == 1000)
{
sprintf(buffer, "%s!%s@%s is my daddy%s",
luser->nick, luser->username, luser->site, oper);
}
else if (acc > 900)
{
sprintf(buffer, "%s!%s@%s is an Official %s coder%s",
luser->nick, luser->username, luser->site, VERIFY_ID, oper);
}
else if (acc == 900)
{
sprintf(buffer, "%s!%s@%s is my grandma%s",
luser->nick, luser->username, luser->site, oper);
}
else if (acc == 800)
{
sprintf(buffer, "%s!%s@%s is a Co-ordinator of %s%s",
luser->nick, luser->username, luser->site, VERIFY_ID, oper);
}
else if (acc > 500)
{
sprintf(buffer, "%s!%s@%s is an Official %s admin%s",
luser->nick, luser->username, luser->site, VERIFY_ID, oper);
}
else if (acc > 0)
{
sprintf(buffer, "%s!%s@%s is an Official %s helper%s",
luser->nick, luser->username, luser->site, VERIFY_ID, oper);
}
else if (acc < 0)
{
sprintf(buffer, "%s!%s@%s is a well-known TROUBLEMAKER%s",
luser->nick, luser->username, luser->site, oper);
}
else if (luser->mode & LFL_ISOPER)
{
sprintf(buffer, "%s!%s@%s is an IRC operator",
luser->nick, luser->username, luser->site);
}
else
{
sprintf(buffer, "%s!%s@%s is NOT an authenticated %s representative",
luser->nick, luser->username, luser->site, VERIFY_ID);
}
notice(source, buffer);
}
#ifdef FAKE_UWORLD
void Uworld_switch(char *source, char *ch, char *args)
{
char buffer[200];
aluser *user, *user2;
user = ToLuser(source);
if (!user || !(user->mode & LFL_ISOPER))
{
notice(source, "This command is reserved to IRC Operators");
return;
}
if (!strcasecmp(args, "ON"))
{
if (Uworld_status == 1)
{
sprintf(buffer, "%s is already active", UFAKE_NICK);
notice(source, buffer);
}
else
{
if ((user2 = ToLuser(UFAKE_NICK)) != NULL &&
!strcmp(user2->site, DEFAULT_HOSTNAME))
{
sprintf(buffer, "%s already present!", UFAKE_NICK);
notice(source, buffer);
return;
}
if (user2 != NULL)
{
onquit(UFAKE_NICK);
}
if (FindServer(&ServerList, UFAKE_SERVER) != NULL)
{
sprintf(buffer, "%s already present!", UFAKE_SERVER);
notice(source, buffer);
return;
}
sprintf(buffer, ":%s WALLOPS :%s activated %s\n",
SERVERNAME, source, UFAKE_NICK);
sendtoserv(buffer);
Uworld_status = 1;
IntroduceUworld();
sprintf(buffer, "%s activated by %s!%s@%s",
UFAKE_NICK, user->nick, user->username, user->site);
log(buffer);
}
}
else if (!strcasecmp(args, "OFF"))
{
if (Uworld_status == 0)
{
sprintf(buffer, "%s is not active", UFAKE_NICK);
notice(source, buffer);
}
else
{
sprintf(buffer, ":%s WALLOPS :%s deactivated %s\n",
SERVERNAME, source, UFAKE_NICK);
sendtoserv(buffer);
Uworld_status = 0;
sprintf(buffer, "Deactivated by %s!%s@%s",
user->nick, user->username, user->site);
KillUworld(buffer);
sprintf(buffer, "%s deactivated by %s!%s@%s",
UFAKE_NICK, user->nick, user->username, user->site);
log(buffer);
}
}
else
{
notice(source, "SYNTAX: uworld [ON|OFF]");
}
}
void parse_uworld_command(char *source, char *args)
{
char command[80];
GetWord(0, args, command);
args = ToWord(1, args);
if (!strcasecmp(command, "OPCOM"))
Uworld_opcom(source, args);
else if (!strcasecmp(command, "CLEARCHAN"))
ClearChan(source, args);
else if (!strcasecmp(command, "REOP"))
Uworld_reop(source, args);
}
void Uworld_opcom(char *source, char *args)
{
char buffer[512];
char command[80];
char channel[80];
aluser *user;
user = ToLuser(source);
if (!user || !(user->mode & LFL_ISOPER))
{
notice(source, "This command is reserved to IRC Operators");
return;
}
sprintf(buffer, "%s!%s@%s", user->nick, user->username, user->site);
if (IsOperSuspended(buffer))
{
notice(source, "Sorry, Your Uworld access is suspended");
return;
}
GetWord(0, args, command);
GetWord(1, args, channel);
args = ToWord(2, args);
if (!strcasecmp(command, "MODE"))
{
if (*channel != '#')
{
sprintf(buffer, ":%s NOTICE %s :bad channel name\n",
UFAKE_NICK, source);
sendtoserv(buffer);
return;
}
sprintf(buffer, ":%s WALLOPS :%s is using %s to: MODE %s %s\n",
UFAKE_SERVER, source, UFAKE_NICK, channel, args);
sendtoserv(buffer);
sprintf(buffer, ":%s MODE %s %s\n", UFAKE_SERVER, channel, args);
sendtoserv(buffer);
sprintf(buffer, "OPCOM MODE %s %s (%s!%s@%s)",
channel, args, user->nick, user->username, user->site);
log(buffer);
ModeChange(UFAKE_SERVER, channel, args);
}
else
{
sprintf(buffer, ":%s NOTICE %s :(yet) unsupported command (%s)\n",
UFAKE_NICK, source, command);
sendtoserv(buffer);
}
}
void ClearChan(char *source, char *args)
{
register aluser *user;
register auser *chanuser;
register achannel *ch;
register char *curr;
register aban *oneban;
register int i;
char buffer[200], channel[80], arg[80];
if ((user = ToLuser(source)) == NULL)
{
log("ERROR: ClearMode() can't locate user!");
return;
}
GetWord(0, args, channel);
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: clearmode [channel]");
return;
}
if (!user->mode & LFL_ISOPER)
{
sprintf(buffer, ":%s NOTICE %s :This command is reserved to IRC Operators\n",
UFAKE_NICK, source);
sendtoserv(buffer);
return;
}
sprintf(buffer, "%s!%s@%s", user->nick, user->username, user->site);
if (IsOperSuspended(buffer))
{
notice(source, "Sorry, Your Uworld access is suspended");
return;
}
if ((ch = ToChannel(channel)) == NULL)
{
sprintf(buffer, ":%s NOTICE %s :That channel does not exist\n",
UFAKE_NICK, source);
sendtoserv(buffer);
return;
}
sprintf(buffer, ":%s WALLOPS :%s is using %s to: CLEARCHAN %s\n",
UFAKE_SERVER, source, UFAKE_NICK, channel);
sendtoserv(buffer);
sprintf(buffer, "CLEARCHAN on %s requested by %s!%s@%s",
channel, user->nick, user->username, user->site);
log(buffer);
chanuser = ch->users;
while (chanuser != NULL)
{
if (chanuser->chanop)
{
changemode(channel, "-o", chanuser->N->nick, 2);
chanuser->chanop = 0;
}
chanuser = chanuser->next;
}
curr = ch->mode;
i = 1;
while (*curr && *curr != ' ')
{
if (strchr("kl", *curr))
{
GetWord(i++, ch->mode, arg);
if (*curr == 'k')
{
changemode(channel, "-k", arg, 2);
}
else
{
changemode(channel, "-l", "", 2);
}
}
else
{
sprintf(buffer, "-%c", *curr);
changemode(channel, buffer, "", 2);
}
curr++;
}
ch->mode[0] = '\0';
for (oneban = ch->bans; oneban != NULL; oneban = oneban->next)
{
changemode(channel, "-b", oneban->pattern, 2);
}
flushmode(channel);
}
void Uworld_reop(char *source, char *channel)
{
register aluser *user;
char buffer[200];
user = ToLuser(source);
if (user != NULL && !strcasecmp(user->username, DEFAULT_USERNAME) &&
!strcasecmp(user->site, DEFAULT_HOSTNAME))
{
sprintf(buffer, "%s called for REOP on %s", source, channel);
log(buffer);
changemode(channel, "+o", source, 2);
flushmode(channel);
}
}
void OperSuspend(char *source, char *args)
{
FILE *in, *out;
char Mask[200], strtimeout[80], global[] = "*", buffer[120], tmp[80],
*mask = Mask, *ptr;
time_t timeout;
int add = 1, count = 0;
if (Access(global, source) < 900)
{
notice(source, "You don't have access to that command");
return;
}
GetWord(0, args, mask);
GetWord(1, args, strtimeout);
if (!*mask)
{
notice(source, "SYNTAX: opersuspend [+/-]<mask> [timeout]");
return;
}
if (*mask == '+')
{
add = 1;
mask++;
}
else if (*mask == '-')
{
add = 0;
mask++;
}
if (add)
{
out = fopen("opersuspend.dat", "a");
if (!out)
{
notice(source, "Can't open file opersuspend.dat :(");
return;
}
timeout = atol(strtimeout);
if (timeout <= 0)
timeout = 1999999999;
else
timeout += now;
fprintf(out, "%s %ld\n", mask, timeout);
fclose(out);
notice(source, "1 entry added");
}
else
{
in = fopen("opersuspend.dat", "r");
if (!in)
{
notice(source, "Can't open file opersuspend.dat :(");
return;
}
out = fopen("opersuspend.dat.new", "w");
if (!in)
{
notice(source, "Can't open file opersuspend.dat.new :(");
return;
}
while (fgets(buffer, 120, in) != NULL)
{
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
GetWord(0, buffer, tmp);
if (strcasecmp(tmp, mask) && atol(ToWord(1, buffer)) > now)
fprintf(out, "%s\n", buffer);
else
count++;
}
fclose(in);
fclose(out);
rename("opersuspend.dat.new", "opersuspend.dat");
sprintf(buffer, "Removed %d entry(ies)", count);
notice(source, buffer);
}
}
int IsOperSuspended(char *userhost)
{
FILE *fp;
char buffer[120], mask[200], *ptr;
if ((fp = fopen("opersuspend.dat", "r")) == NULL)
return 0;
while (fgets(buffer, 120, fp) != NULL)
{
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
GetWord(0, buffer, mask);
if (atol(ToWord(1, buffer)) > now && match(userhost, mask))
{
fclose(fp);
return 1;
}
}
fclose(fp);
return 0;
}
#endif

266
Sources/ops.c Normal file
View File

@@ -0,0 +1,266 @@
/* @(#)$Id: ops.c,v 1.6 1999/04/04 17:00:13 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
void op(char *source, char *chan, char *nicklist)
{
char channel[80];
char nick[80];
char buffer[200];
register auser *user;
register achannel *ch;
register int i;
/* if the 1st arg is a channel name.. use it instead of 'chan' */
if (*nicklist == '#')
{
GetWord(0, nicklist, channel);
nicklist = ToWord(1, nicklist);
}
else
{
strncpy(channel, chan, 79);
channel[79] = '\0';
GuessChannel(source, channel);
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: op <channel> <nick1> [nick2] [nick3] [...]");
return;
}
/* Bad channel.. geez what am I supposed to do with it?? */
if ((ch = ToChannel(channel)) == NULL || !ch->on)
{
notice(source, replies[RPL_NOTONCHANNEL][L_DEFAULT]);
return;
}
if (!ch->AmChanOp)
{
notice(source, replies[RPL_NOTCHANOP][ch->lang]);
return;
}
if (*source && (ch->flags & CFL_OPONLY) &&
*nicklist && strcasecmp(nicklist, source))
{
notice(source, replies[RPL_OPSELFONLY][ch->lang]);
return;
}
if (*source && (ch->flags & CFL_NOOP))
{
notice(source, replies[RPL_NOOP][ch->lang]);
return;
}
#ifdef DEBUG
printf("OP requested....\nCHANNEL: %s\nNICKS: %s\n", channel, nicklist);
#endif
if (*source && Access(channel, source) < OP_LEVEL)
{
ReplyNotAccess(source, channel);
return;
}
if (!*nicklist)
{
strcpy(nick, source);
}
else
{
GetWord(0, nicklist, nick);
}
i = 0;
while (*nick)
{
user = ToUser(channel, nick);
#ifdef DEBUG
if (user)
{
printf("USER FOUND!\n");
printf("nick: %s\n", user->N->nick);
printf("Chanop: %s\n", (user->chanop) ? "YES" : "NO");
}
else
{
printf("USER %s NOT FOUND ON CHANNEL %s\n", nick, channel);
}
#endif
/* the user might be shitlisted.. */
if (user)
{
sprintf(buffer, "%s!%s@%s", user->N->nick, user->N->username, user->N->site);
if (ch->flags & CFL_STRICTOP && Access(channel, user->N->nick) < OP_LEVEL)
{
if (*source)
{
notice(source, "StrictOp is active and user is not authenticated");
}
}
else if (IsShit(channel, buffer, NULL, NULL) < NO_OP_SHIT_LEVEL)
{
if (user && !user->chanop)
{
user->chanop = 1;
changemode(channel, "+o", nick, 0);
if (*source && strcasecmp(source, nick))
{
sprintf(buffer, replies[RPL_YOUREOPPEDBY][ch->lang], source);
notice(nick, buffer);
}
}
}
else
{
sprintf(buffer, "%s: %s", nick, replies[RPL_CANTBEOPPED][ch->lang]);
notice(source, buffer);
}
}
else
{
sprintf(buffer, replies[RPL_USERNOTONCHANNEL][ch->lang], nick, channel);
notice(source, buffer);
}
GetWord(++i, nicklist, nick);
}
AddEvent(EVENT_FLUSHMODEBUFF, now + MODE_DELAY, channel);
}
void deop(char *source, char *ch, char *nicklist)
{
char channel[CHANNELNAME_LENGTH];
char nick[80];
char buffer[200];
register auser *user;
register achannel *chan;
register int i;
/* if the 1st arg is a channel name.. use it instead of 'channel' */
if (*nicklist == '#')
{
GetWord(0, nicklist, channel);
nicklist = ToWord(1, nicklist);
}
else
{
strncpy(channel, ch, CHANNELNAME_LENGTH);
GuessChannel(source, channel);
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: deop <channel> <nick1> [nick2] [nick3] [...]");
return;
}
#ifdef DEBUG
printf("DEOP requested....\nCHANNEL: %s\nNICKS: %s\n", channel, nicklist);
#endif
if ((chan = ToChannel(channel)) == NULL || !chan->on)
{
notice(source, replies[RPL_NOTONCHANNEL][L_DEFAULT]);
return;
}
if (*source && (chan->flags & CFL_OPONLY))
{
notice(source, replies[RPL_OPONLY][chan->lang]);
return;
}
if (!chan->AmChanOp)
{
notice(source, replies[RPL_NOTCHANOP][chan->lang]);
return;
}
if (*source && Access(channel, source) < OP_LEVEL)
{
ReplyNotAccess(source, channel);
return;
}
if (!*nicklist)
{
notice(source, "SYNTAX: deop [channel] <nick1> [nick2] [nick3] [...]");
return;
}
i = 0;
GetWord(i, nicklist, nick);
while (*nick)
{
user = ToUser(channel, nick);
if (user)
{
sprintf(buffer, "%s!%s@%s",
user->N->nick, user->N->username, user->N->site);
if (user && user->chanop)
{
user->chanop = 0;
changemode(channel, "-o", nick, 0);
if (*source && strcasecmp(source, nick))
{
sprintf(buffer, replies[RPL_YOUREDEOPPEDBY][chan->lang], source);
notice(nick, buffer);
}
}
}
GetWord(++i, nicklist, nick);
}
AddEvent(EVENT_FLUSHMODEBUFF, now + MODE_DELAY, channel);
}
void massdeop(char *channel)
{
achannel *chan;
auser *user;
chan = ToChannel(channel);
if (chan == NULL || !chan->on || !chan->AmChanOp)
return;
user = chan->users;
while (user != NULL)
{
if (user->chanop)
{
changemode(channel, "-o", user->N->nick, 0);
user->chanop = 0;
}
user = user->next;
}
flushmode(channel);
}

351
Sources/patch.c Normal file
View File

@@ -0,0 +1,351 @@
/* @(#)$Id: patch.c,v 1.3 1996/11/13 00:40:46 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#include <stdarg.h>
#ifdef UPGRADE
static void misc_closed_conn(misc_socket *);
void upgrade(char *source, char *args)
{
char global[]="*";
if(Access(global,source)<LEVEL_UPGRADE){
notice(source,"This command is not for you");
return;
}
open_patch_socket(source);
}
void open_patch_socket(char *source)
{
misc_socket *msock;
struct sockaddr_in socketname;
struct hostent *remote_host;
char pserver[80]=PATCH_SERVER, buffer[200], *ptr;
int port;
if((ptr=strchr(pserver,':'))==NULL){
notice(source,"PATCH_SERVER needs to be \"server:port\"!");
return;
}
*(ptr++)='\0';
sscanf(ptr,"%d",&port);
#ifdef DEBUG
printf("Connecting to patch server %s on port %d\n",pserver,port);
#endif
sprintf(buffer,"Connecting to patch server %s on port %d",pserver,port);
log(buffer);
notice(source,"Attempting to contact patch server...");
msock=(misc_socket *)MALLOC(sizeof(misc_socket));
msock->type=MISC_GETPATCH;
msock->status=MISC_CONNECTING;
msock->TS=now;
strcpy(msock->link,source);
msock->inbuf=NULL;
msock->outbuf=NULL;
if((msock->fd=socket(AF_INET,SOCK_STREAM,0))<0){
free(msock);
sprintf(buffer,"Can't assigned fd for socket: %s",sys_errlist[errno]);
notice(source,buffer);
return;
}
fcntl(msock->fd,F_SETFL,O_NONBLOCK);
socketname.sin_family=AF_INET;
if((remote_host=gethostbyname(pserver))==NULL){
sprintf(buffer,"gethostbyname() failed for %s: %s",pserver,sys_errlist[errno]);
notice(source,buffer);
close(msock->fd);
free(msock);
return;
}
memcpy((void *)&socketname.sin_addr,(void *)remote_host->h_addr,remote_host->h_length);
socketname.sin_port = htons(port);
if(connect(msock->fd,(struct sockaddr *)&socketname,sizeof(socketname))<0
&& errno != EINPROGRESS){
close(msock->fd);
sprintf(buffer,"Can't connect() to %s: %s",pserver,sys_errlist[errno]);
notice(source,buffer);
free(msock);
return;
}
msock->next=MiscList;
MiscList=msock;
send_misc_handshake(msock);
}
int readfrom_misc(misc_socket *msock)
{
void parse_misc(misc_socket *,char *);
char buf[1024];
int length;
if((length=read(msock->fd,buf,1023))<=0){
if(errno==EWOULDBLOCK || errno==EAGAIN){
return 0;
}else{
misc_closed_conn(msock);
close(msock->fd);
msock->fd=-1;
msock->status=MISC_ERROR;
return -1;
}
}
buf[length]='\0';
copy_to_buffer(&msock->inbuf,buf,length);
if(find_char_in_buffer(&msock->inbuf,'\n',1023)){
while(find_char_in_buffer(&msock->inbuf,'\n',1023)){
copy_from_buffer(&msock->inbuf,buf,'\n',1023);
parse_misc(msock,buf);
}
}
return 1;
}
int flush_misc_buffer(misc_socket *msock)
{
char buf[1024];
int length;
int count;
if(msock->status==MISC_CONNECTING){
msock->status=MISC_HANDSHAKE;
notice(msock->link,"Connected.");
}
if(msock==NULL || msock->outbuf==NULL)
return -1;
while((count = look_in_buffer(&msock->outbuf,buf,'\0',1023))>0){
if((length=write(msock->fd,buf,count))<=0){
if((errno==EWOULDBLOCK || errno==EAGAIN) && length!=0){
return 0;
}else{
misc_closed_conn(msock);
close(msock->fd);
msock->fd=-1;
msock->status=MISC_ERROR;
return -1;
}
}else{
skip_char_in_buffer(&msock->outbuf,length);
}
}
return 0;
}
long sendto_misc(misc_socket *msock, char *format, ...)
{
va_list args;
char string[1024];
va_start(args,format);
vsprintf(string,format,args);
#ifdef DEBUG
vprintf(format,args);
#endif
va_end(args);
return copy_to_buffer(&msock->outbuf,string,strlen(string));
}
void send_misc_handshake(misc_socket *msock)
{
struct stat stlast;
char tag[80], buffer[200];
FILE *fp;
if(msock->type==MISC_GETPATCH){
if(stat("lastupgrade",&stlast)<0){
sprintf(buffer,"lastupgrade: %s",
sys_errlist[errno]);
notice(msock->link,buffer);
close(msock->fd);
msock->status=MISC_ERROR;
}
fp=fopen("lastupgrade","r");
if(fp==NULL){
close(msock->fd);
msock->fd=-1;
msock->status=MISC_ERROR;
sprintf(buffer,"lastupgrade: %s",sys_errlist[errno]);
notice(msock->link,buffer);
return;
}
fgets(tag,80,fp);
fclose(fp);
sendto_misc(msock,"%s\n%s\n",GETPATCHPASS,tag);
}
}
static void misc_closed_conn(misc_socket *msock)
{
int pipefd[2],i;
char *ptr;
if(msock->type==MISC_GETPATCH){
if(msock->status==MISC_CONNECTING)
notice(msock->link,"Connection refused.");
else if(msock->status==MISC_HANDSHAKE)
notice(msock->link,"Handshake failed.");
else
notice(msock->link,"Connection closed.");
}else if(msock->type==MISC_PIPE_PATCH){
notice(msock->link,"patch process exited.");
pipe(pipefd);
switch(fork()){
case 0:
dup2(pipefd[1],1);
dup2(pipefd[1],2);
close(0);
for(i=3;i<MAX_CONNECTIONS;i++) close(i);
execl(MAKE,MAKE,(char *)0);
exit(-1);
case -1:
notice(msock->link,"fork() failed!");
/* socket already closed.. */
break;
default:
notice(msock->link,"Spawning make..");
close(pipefd[1]);
ptr=msock->link;
msock=(misc_socket *)MALLOC(sizeof(misc_socket));
msock->fd=pipefd[0];
msock->type=MISC_PIPE_MAKE;
msock->status=MISC_RECV;
msock->TS=now;
strcpy(msock->link,ptr);
msock->inbuf=NULL;
msock->outbuf=NULL;
msock->next=MiscList;
MiscList=msock;
break;
}
}else if(msock->type==MISC_PIPE_MAKE){
notice(msock->link,"make process exited.");
}else{
notice(msock->link,"Connection closed.");
}
}
void parse_misc(misc_socket *msock, char *line)
{
FILE *fp;
int fdpipe[2],i;
char *ptr;
if(msock->status==MISC_CONNECTING){
msock->status=MISC_HANDSHAKE;
notice(msock->link,"Connected!");
}
while((ptr=strpbrk(line,"\r\n"))!=NULL)
*ptr='\0';
if(!*line)
return;
if(msock->type==MISC_GETPATCH){
if(msock->status==MISC_HANDSHAKE){
if(strcmp(RECPATCHPASS,line)){
close(msock->fd);
msock->fd=-1;
msock->status=MISC_ERROR;
notice(msock->link,"Bad password!");
return;
}
msock->status=MISC_RECV;
}else if(msock->status==MISC_RECV){
fp=fopen("lastupgrade","w");
if(fp!=NULL){
fprintf(fp,"%s\n",line);
fclose(fp);
}
/* spawn patch */
pipe(fdpipe);
switch(fork()){
case 0:
fcntl(msock->fd,F_SETFL,0);
dup2(msock->fd,0);
dup2(fdpipe[1],1);
dup2(fdpipe[1],2);
for(i=3;i<MAX_CONNECTIONS;i++) close(i);
putenv("IFS="); /* I'm paranoid */
execl("/bin/sh","[patch script]","-c",
"tee upgrade.patch | "PATCH" -p1",
(char *)0);
exit(-1);
case -1:
notice(msock->link,"fork() failed");
close(msock->fd);
msock->fd=-1;
msock->status=MISC_ERROR;
break;
default:
notice(msock->link,"Spawning patch script..");
close(msock->fd);
while(msock->inbuf!=NULL){
char buf[512];
int l;
l=copy_from_buffer(&msock->inbuf,buf,'\0',511);
write(fdpipe[1],buf,l);
}
close(fdpipe[1]);
msock->fd=fdpipe[0];
msock->type=MISC_PIPE_PATCH;
zap_buffer(&msock->outbuf);
break;
}
}
}else if(msock->type==MISC_PIPE_PATCH || msock->type==MISC_PIPE_MAKE){
notice(msock->link,line);
}
}
#endif /* UPGRADE */

405
Sources/privmsg.c Normal file
View File

@@ -0,0 +1,405 @@
/* @(#)$Id: privmsg.c,v 1.22 2000/10/24 16:04:24 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
void privmsg(char *source, char *target, char *body)
{
register auser *user;
register achannel *chan;
register char *ptr;
char global[] = "*";
#ifdef DEBUG
printf("PRIVMSG from %s to %s\n", source, target);
#endif
if ((*target == '#' || *target == '$') && strchr(target, '*'))
{
#ifdef DEBUG
printf("Received WALL... ignoring.. \n");
#endif
return;
}
/* CTCP */
if (body[1] == '\001' && (ptr = strchr(body + 2, '\001')) != NULL)
{
if (*target == '#' || *target == '&')
{
if (CheckFlood(source, target, strlen(ToWord(1, body + 1))))
return;
}
*ptr = '\0';
if (!IsIgnored(source) &&
!CheckPrivateFlood(source, strlen(body), "CTCP-"))
parse_ctcp(source, target, body + 2);
}
/* PRIVMSG TO A CHANNEL */
else if (*target == '#' || *target == '&')
{
/* PRIVMSG #blah@channels.undernet.org ?? */
if (!(chan = ToChannel(target)))
return;
chan->lastact = now;
user = ToUser(target, source);
if (!user)
return; /* not on channel.. happens if not +n */
user->lastact = now;
if (CheckFlood(source, target, strlen(ToWord(1, body + 1))))
return;
if (!strncmp(body + 1, COMMAND_PREFIX, strlen(COMMAND_PREFIX)))
parse_command(source, target, target, body + strlen(COMMAND_PREFIX) + 1);
/* PRIVATE PRIVMSG */
}
else
{
if (!IsIgnored(source) && !CheckPrivateFlood(source, strlen(body), "MSG-"))
{
#ifdef FAKE_UWORLD
if (!strcasecmp(target, UFAKE_NICK))
{
parse_uworld_command(source, body + 1);
}
else
#endif
parse_command(source, target, global, body + 1);
}
}
}
void parse_command(char *source, char *target, char *channel, char *commandline)
{
char buffer[1024];
char command[80];
char global[] = "*";
register aluser *user;
GetWord(0, commandline, command);
#ifdef DEBUG
printf("PARSING COMMAND: %s\nCOMMAND: %s\nARGS: %s\nSOURCE: %s\n",
commandline, command, ToWord(1, commandline), source);
#endif
user = ToLuser(source);
/* all commands must come from a user */
if (user == NULL)
return;
if (strcasecmp(command, "pass") && strcasecmp(command, "login") &&
strcasecmp(command, "newpass"))
{
sprintf(buffer, "COMMAND FROM %s!%s@%s on %s: %s",
user->nick, user->username, user->site,
channel, commandline);
log(buffer);
}
else
{
sprintf(buffer, "COMMAND FROM %s!%s@%s on %s: %s XXXXXXX",
user->nick, user->username, user->site,
channel, command);
log(buffer);
}
if (!strcmp(command, "showcommands"))
showcommands(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "pass") || !strcmp(command, "login"))
validate(source, target, ToWord(1, commandline));
else if (!strcmp(command, "deauth"))
DeAuth(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "die") && Access(global, source) >= LEVEL_DIE)
quit(ToWord(1, commandline), 0);
else if (!strcmp(command, "restart") && Access(global, source) >= LEVEL_DIE)
restart(ToWord(1, commandline)); /* added by Kev; restarts */
else if (!strcmp(command, "search"))
SearchChan(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "join"))
join(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "part"))
part(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "op"))
op(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "deop"))
deop(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "banlist"))
showbanlist(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "kick"))
kick(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "invite"))
invite(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "topic"))
topic(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "adduser"))
AddUser(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "remuser"))
RemoveUser(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "modinfo"))
ModUserInfo(source, target, channel, ToWord(1, commandline));
else if (!strcmp(command, "newpass"))
ChPass(source, target, ToWord(1, commandline));
else if (!strcmp(command, "set"))
SetChanFlag(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "access"))
showaccess(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "suspend"))
suspend(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "unsuspend"))
unsuspend(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "saveuserlist"))
SaveUserList(source, channel);
else if (!strcmp(command, "lbanlist"))
ShowShitList(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "ban"))
AddToShitList(source, channel, ToWord(1, commandline), 0);
else if (!strcmp(command, "unban"))
RemShitList(source, channel, ToWord(1, commandline), 0);
else if (!strcmp(command, "cleanbanlist"))
CleanShitList(source, ToWord(1, commandline));
else if (!strcmp(command, "addchan"))
AddChan(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "remchan"))
RemChan(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "savedefs"))
SaveDefs(source);
else if (!strcmp(command, "loaddefs"))
LoadDefs(source);
else if (!strcmp(command, "saveshitlist"))
SaveShitList(source, channel);
else if (!strcmp(command, "loadshitlist"))
LoadShitList(source);
else if (!strcmp(command, "status"))
showstatus(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "map"))
showmap(source);
else if (!strcmp(command, "help"))
showhelp(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "chaninfo"))
ShowChanInfo(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "motd"))
showmotd(source);
else if (!strcmp(command, "isreg"))
isreg(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "core"))
dumpcore(source);
#ifdef RUSAGE_SELF
else if (!strcmp(command, "rusage"))
show_rusage(source);
#endif
else if (!strcmp(command, "showignore"))
ShowIgnoreList(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "remignore"))
AdminRemoveIgnore(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "calmdown"))
CalmDown(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "operjoin"))
OperJoin(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "operpart"))
OperPart(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "clearmode"))
ClearMode(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "purge"))
purge(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "verify"))
verify(source, ToWord(1, commandline));
#ifdef UPGRADE
else if (!strcmp(command, "upgrade"))
upgrade(source, ToWord(1, commandline));
#endif
else if (!strcmp(command, "random"))
RandomChannel(source);
else if (!strcmp(command, "say"))
Say(source, ToWord(1, commandline));
else if (!strcmp(command, "servnotice"))
ServNotice(source, ToWord(1, commandline));
else if (!strcmp(command, "fuck"))
notice(source, "This command is obsolete");
#ifdef DEBUG
else if (!strcmp(command, "db"))
db_test(source, channel, ToWord(1, commandline));
#endif
#ifdef DOHTTP
else if (!strcmp(command, "rehash"))
read_http_conf(source);
#endif
#ifdef FAKE_UWORLD
else if (!strcmp(command, "uworld"))
Uworld_switch(source, channel, ToWord(1, commandline));
else if (!strcmp(command, "opersuspend"))
OperSuspend(source, ToWord(1, commandline));
#endif
#ifdef DEBUG
else if (!strcmp(command, "showusers"))
showusers(ToWord(1, commandline));
else if (!strcmp(command, "showchannels"))
showchannels();
#endif
#ifdef NICKSERV
else if (!strcmp(command, "nickserv"))
nserv_nickserv(source, ToWord(1, commandline));
else if (!strcmp(command, "addnick"))
nserv_addnick(source, ToWord(1, commandline));
else if (!strcmp(command, "remnick"))
nserv_remnick(source, ToWord(1, commandline));
else if (!strcmp(command, "addmask"))
nserv_addmask(source, ToWord(1, commandline));
else if (!strcmp(command, "remmask"))
nserv_remmask(source, ToWord(1, commandline));
else if (!strcmp(command, "nickinfo"))
nserv_nickinfo(source, ToWord(1, commandline));
else if (!strcmp(command, "identify"))
nserv_identify(source, ToWord(1, commandline));
else if (!strcmp(command, "ghost"))
nserv_ghost(source, ToWord(1, commandline));
else if (!strcmp(command, "nicknewpass"))
nserv_nicknewpass(source, ToWord(1, commandline));
else if (!strcmp(command, "nicknewemail"))
nserv_nicknewemail(source, ToWord(1, commandline));
#endif
#ifdef DOHTTP
else if (!strcmp(command, "dccme"))
DccMe(source, ToWord(1, commandline));
#endif
}
void parse_ctcp(char *source, char *target, char *body)
{
char func[80];
char buffer[1024];
char tmp[80];
GetWord(0, body, func);
body = ToWord(1, body);
if (strcmp(func, "ACTION"))
{
sprintf(buffer, "CTCP %s from %s [%s]", func, source, body);
log(buffer);
}
if (match(func, "PING"))
{
sprintf(buffer, "\001PING %s\001", body);
notice(source, buffer);
}
else if (match(func, "TIME"))
{
strcpy(tmp, ctime(&now));
*strchr(tmp, '\n') = '\0';
sprintf(buffer, "\001TIME %s\001", tmp);
notice(source, buffer);
}
else if (match(func, "ITIME"))
{
sprintf(buffer, "\001ITIME @%03ld\001",
1000 * ((now + 3600) % 86400) / 86400);
notice(source, buffer);
}
else if (match(func, "VERSION"))
{
sprintf(buffer, "\001VERSION %s\001", VERSION);
notice(source, buffer);
}
else if (match(func, "GENDER"))
{
notice(source, "\001GENDER I'm a male bot! Are you a pretty young bottesse?\001");
}
}

271
Sources/prototypes.h Normal file
View File

@@ -0,0 +1,271 @@
/* @(#)$Id: prototypes.h,v 1.20 2000/10/24 15:15:53 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
void log(char *);
void SpecLog(char *);
void LogChan(void);
int connection(char *);
void try_later(char *);
void sendtoserv(char *);
int wait_msg(void);
void dumpbuff(void);
void rec_sigsegv(int);
void rec_sigbus(int);
void rec_sigterm(int);
void rec_sigint(int);
void dumpcore(char *);
void show_rusage(char *);
void regist(void);
void signon(void);
void onserver(char *,char *,char *);
void onsettime(char *,char *);
void onsquit(char *,char *,char *);
aserver *ToServer(char *);
aserver **FindServer(aserver **, char *);
char *ToWord(int,char *);
void GetWord(int,char *,char *);
char *time_remaining(time_t);
void proc(char *,char *, char *, char *);
void pong(char *);
void showversion(char *);
int reconnect(char *server);
int xmatch(char *, char *);
int compare(char *, char *);
int match(char *, char *);
int regex_cmp(char *patern, char *string);
int mycasecmp(char *,char *);
int key_match(char *,char *[]);
void string_swap(char *, size_t, char *, char *);
int quit(char *, int);
int restart(char *); /* added for restart function -Kev */
void showcommands(char *,char *,char *);
void showhelp(char *,char *,char *);
void showmotd(char *);
void ShowChanInfo(char *,char *,char *);
void isreg(char *,char *,char *);
void LoadUserList(char *);
void SaveUserList(char *,char *);
void DelChannel(char *);
void FreeUser(auser *);
void NewChannel(char *,time_t,int);
void QuitAll(void);
void privmsg(char *,char *,char *);
void parse_command(char *,char *,char *,char *);
int GuessChannel(char *, char *);
void try_find(char *,aluser *);
int LAccess(char *,aluser *);
int Access(char *,char *);
void verify(char *, char *);
RegUser *IsValid(aluser *,char *);
int IsShit(char *,char *,char *, char *);
void AddUser(char *,char *,char *);
void showaccess(char *,char *,char *);
void RemoveUser(char *,char *,char *);
void ModUserInfo(char *,char *,char *,char *);
void purge(char *,char *,char *);
void ChPass(char *,char *,char *);
void SetChanFlag(char *,char *,char *);
void free_user(RegUser **);
void validate(char *,char *,char *);
void DeAuth(char *, char *, char *);
void join(char *,char *,char *);
void joindefault(void);
void SendBurst(void);
void invite(char *,char *,char *);
void part(char *,char *,char *);
void oninvite(char *,char *);
void onjoin(char *,char *);
void onpart(char *,char *);
void onkick(char *,char *,char *);
void onop(char *,char *,char *);
void ondeop(char *,char *,char *,int *);
void GetOps(char *);
int IsOpless(char *);
void onopless(char *);
void onnick(char *,char *,char *);
void onban(char *,char *,char *);
void onunban(char *,char *,char *);
void showbanlist(char *,char *,char *);
void AddBan(char *,char *);
void RemBan(char *,char *);
void onwhois(char *,char *);
void UserQuit(char *);
achannel *ToChannel(char *);
auser *ToUser(char *,char *);
aluser *ToLuser(char *);
void onquit(char *);
void onkill(char *,char *,char *);
void onwho(char *);
void showusers(char *);
void showchannels(void);
void setchanmode(char *);
void ModeChange(char *,char *,char *);
void changemode(char *,char *,char *,int);
void flushmode(char *);
void bounce(char *,char *,time_t);
int IsSet(char *,char,char *);
void op(char *,char *,char *);
void deop(char *,char *,char *);
void massdeop(char *);
void MakeBanMask(aluser *, char *);
void ban(char *,char *,char *);
void mban(char *,char *,char *);
void unban(char *,char *,char *);
void kick(char *,char *,char *);
void topic(char *,char *,char *);
void notice(char *,char *);
void servnotice(char *,char *);
void broadcast(char *,int);
void NickInUse(void);
void ChNick(char *);
void AddToShitList(char *, char *, char *,int);
void RemShitList(char *,char *,char *,int);
void CleanShitList(char *,char *);
void suspend(char *, char *, char *);
void unsuspend(char *, char *, char *);
void ShowShitList(char *,char *,char *);
void LoadDefs(char *);
void SearchChan(char *,char *,char *);
void AddChan(char *,char *,char *);
void SaveDefs(char *);
void RemChan(char *, char *, char *);
int CheckFlood(char *,char *,int);
int CheckAdduserFlood(char *, char *);
void ontopic(char *,char *,char *);
void onnotice(char *,char *,char *);
void LoadShitList(char *);
void SaveShitList(char *,char *);
void parse_ctcp(char *,char *,char *);
void showstatus(char *,char *,char *);
void showmap(char *);
void showserv(char *,aserver *, int *);
void InitEvent(void);
void AddEvent(int, time_t, char *);
void CheckEvent(void);
void CleanIgnores(void);
void AddIgnore(char *,char *,int);
int CheckPrivateFlood(char *,int,char *);
int CheckFloodFlood(char *,int);
int IsIgnored(char *);
void ShowIgnoreList(char *,char *,char *);
void AdminRemoveIgnore(char *, char *, char *);
void CalmDown(char *,char *,char *);
void OperJoin(char *,char *,char *);
void OperPart(char *,char *,char *);
void ClearMode(char *, char *, char *);
void ReplyNotAccess(char *,char *);
void CheckIdleChannels(void);
void RandomChannel(char *);
void Say(char *,char *);
void RobinSay(char *,char *);
void ServNotice(char *,char *);
int IsReg(char *);
#ifdef FAKE_UWORLD
void IntroduceUworld(void);
void KillUworld(char *);
void Uworld_switch(char *,char *,char *);
void parse_uworld_command(char *,char *);
void Uworld_opcom(char *,char *);
void ClearChan(char *, char *);
void Uworld_reop(char *, char *);
void OperSuspend(char *, char *);
int IsOperSuspended(char *);
#endif
#ifdef NICKSERV
void IntroduceNickserv(void);
#endif
#ifdef DOHTTP
void open_http(void);
void remove_httpsock(http_socket *old);
void http_accept(int sock);
void parse_http(http_socket *hsock, char *buf);
void readfrom_file(http_file_pipe *fpipe);
void destroy_file_pipe(http_file_pipe *old);
void read_http_conf(char *);
long sendto_http(http_socket *sck, char *format, ...);
int readfrom_http(http_socket *);
int flush_http_buffer(http_socket *);
#endif
void upgrade(char *,char *);
void open_patch_socket(char *);
int readfrom_misc(misc_socket *);
int flush_misc_buffer(misc_socket *);
long sendto_misc(misc_socket *, char *, ...);
void send_misc_handshake(misc_socket *);
struct buffer_block *get_buffer_block(void);
void return_buffer_block(struct buffer_block *);
int copy_from_buffer(struct buffer_block **, char *, char, int);
int look_in_buffer(struct buffer_block **, char *, char, int);
long copy_to_buffer(struct buffer_block **, char *,int);
int zap_buffer(struct buffer_block **);
int find_char_in_buffer(struct buffer_block **, char,int);
int skip_char_in_buffer(struct buffer_block **, int);
char *make_dbfname(char *);
int db_fetch(char *,unsigned int,char *,char *,int,void *,void *,DBCALLBACK(x));
void read_db(dbquery *);
void end_db_read(dbquery *);
void db_sync(char *);
void db_sync_ready(dbsync *);
void end_db_sync(dbsync *);
void db_test(char *, char *,char *);
void gather_sync_channels(void);
void sync_next_channel(void);
void do_cold_sync(void);
void do_cold_sync_slice(void);
#ifdef HISTORY
void History(char *);
#endif
int ul_hash(char *);
int sl_hash(char *);
int lu_hash(char *);
int cl_hash(char *);
int su_hash(char *);
#ifdef NICKSERV
void IntroduceNickserv(void);
void KillNickserv(char *msg);
void nserv_nickserv(char *source, char *args);
void nserv_addnick(char *source, char *args);
void nserv_addmask(char *source, char *args);
void nserv_remnick(char *source, char *args);
void nserv_remmask(char *source, char *args);
void nserv_nickinfo(char *source, char *args);
void nserv_identify(char *source, char *args);
void nserv_ghost(char *source, char *args);
void nserv_nicknewpass(char *source, char *args);
void nserv_nicknewemail(char *source, char *args);
void nserv_save(void);
void nserv_load(void);
void nserv_checkregnick(char *nick);
void nserv_quit(aluser *user);
void nserv_nick(char *newnick, aluser *user);
void nserv_onop(char *channel, auser *user);
#endif
void DccMe(char *, char *);

614
Sources/replies.c Normal file
View File

@@ -0,0 +1,614 @@
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
/* Very appreciated contribution from: (just add your name here)
Stephan Mantler aka Step <smantler@atpibm6000.tuwien.ac.at>
Carlo Kid aka Run <carlo@tnrunaway.tn.tudelft.nl>
nirvana <nirvana@nil.fut.es>
*/
#include "h.h"
alang Lang[NO_LANG] =
{
{L_ENGLISH, "en", "english"},
{L_DUTCH, "nl", "dutch"},
{L_FRENCH, "fr", "fran<EFBFBD>ais"},
{L_SPANISH, "es", "espa<EFBFBD>ol"},
{L_GERMAN, "de", "deutsch"}
};
/* the %s will be expanded to the channel name
notaccessreply is only english for now */
char *notaccessreply[] =
{
"%s: Nice try. But I'm not a fool!",
"%s: Cheating is very bad you know!",
"%s: Do I know you?",
"You should come on %s more often",
"Ha! Ha! I don't think people on %s would like that!",
"%s: Pfft! Nice try!",
"%s: No, I don't think so.. you're not my type :P",
"go read the %s manual.. then I might consider it",
"I would.. but.. one teensy problem. You're not in %s's database",
"Oh.. are you trying to communicate with me?",
"You see, %s is some kinda private thing...",
NULL
};
void ReplyNotAccess(char *nick, char *channel)
{
static int index = 0;
register int i;
char buffer[200];
for (i = rand() % 5 + 1; i > 0; i--)
if (notaccessreply[++index] == NULL)
index = 0;
sprintf(buffer, notaccessreply[index], channel);
notice(nick, buffer);
}
void RandomChannel(char *source)
{
register int hash, offset;
register achannel *chan;
char buffer[200];
hash = rand() % 1000;
offset = rand() % 100;
chan = ChannelList[hash];
while (chan == NULL)
{
chan = ChannelList[(++hash) % 1000];
if (hash > 2000)
return;
}
while (offset > 0 && !chan->on)
{
chan = chan->next;
if (chan == NULL)
{
while (chan == NULL)
{
chan = ChannelList[(++hash) % 1000];
if (hash > 2000)
return;
}
}
offset--;
}
sprintf(buffer, "%s is cool!", chan->name);
notice(source, buffer);
}
void Say(char *source, char *args)
{
char buffer[1024], target[80], global[] = "*";
if (Access(global, source) < 900)
{
return; /*silently */
}
GetWord(0, args, target);
args = ToWord(1, args);
if (!*target || !*args)
{
notice(source, "Syntax: say [#channel] [whatever]");
return;
}
sprintf(buffer, ":%s PRIVMSG %s :%s\n", mynick, target, args);
sendtoserv(buffer);
}
void ServNotice(char *source, char *args)
{
char buffer[1024], target[80], global[] = "*";
if (Access(global, source) < 600)
{
return; /*silently */
}
GetWord(0, args, target);
args = ToWord(1, args);
if (!*target || !*args)
{
notice(source, "SYNTAX: servnotice [#channel] [whatever]");
return;
}
sprintf(buffer, "[Channel Service: %s] %s", source, args);
servnotice(target, buffer);
}
char *replies[][NO_LANG] =
{
/* RPL_NOTONCHANNEL */
{"I am not on that channel!", /* english */
"Ik zit niet op dat kanaal!", /* dutch */
"Je ne suis pas sur ce canal!", /* french */
"No estoy en ese canal!", /* spanish */
"Ich bin nicht auf diesem Kanal!" /* german */
},
/* RPL_NOTCHANOP */
{"I am not channel operator", /* english */
"Ik ben geen channel operator", /* dutch */
"Je ne suis pas op<6F>rateur de canal", /* french */
"No soy operador del canal", /* spanish */
"Ich bin kein Betreiber auf diesem Kanal" /* german */
},
/* RPL_OPONLY */
{"This channel is in OpOnly Mode", /* english */
"Dit kanaal is in OpOnly Mode", /* dutch */
"Ce canal est en mode OpOnly", /* french */
"Ese canal est<73> en modo OpOnly", /* spanish */
"Dieser Kanal is im OpOnly-Modus" /* german */
},
/* RPL_OPSELFONLY */
{"You can only op yourself in OpOnly mode", /* english */
"In OpOnly mode mag je alleen jezelf operator maken", /* dutch */
"Vous ne pouvez opper que vous-m<>me en mode OpOnly", /* french */
"Solo puedes ser operador en modo OpOnly", /* spanish */
"Sie koennen nur sich selbst zum Betreiber machen (Kanal im OpOnly-Modus)" /* german */
},
/* RPL_NOSUCHNICK */
{"No such nickname", /* english */
"Deze NICK is niet in gebruik", /* dutch */
"Ce nick n'existe pas", /* french */
"Ese nick no existe", /* spanish */
"Diesen Nickname gibt es nicht" /* german */
},
/* RPL_ALREADYONCHANNEL */
{"This user is already on channel", /* english */
"Deze persoon is al op dat kanaal", /* dutch */
"Cet usager est d<>j<EFBFBD> sur le canal", /* french */
"Ese usuario ya est<73> en el canal", /* spanish */
"Dieser Benutzer ist bereits auf dem Kanal" /* german */
},
/* RPL_IINVITED */
{"I invited %s to %s", /* english */
"%s is uitgenodigd naar %s te komen", /* dutch */
"J'ai invit<69> %s sur %s", /* french */
"Yo he invitado a %s en %s", /* spanish */
"Ich haben %s eingeladen, auf %s zu kommen" /* german */
},
/* RPL_YOUAREINVITED */
{"%s invites you to %s", /* english */
"%s vraagt of naar %s komt", /* dutch */
"%s vous invite sur %s", /* french */
"%s te invita en %s", /* spanish */
"%s laedt Sie ein, auf %s zu kommen" /* german */
},
/* RPL_ALWAYSOPWASACTIVE */
{"AlwaysOp was active! It's now deactivated", /* english */
"AlwaysOp was actief! Het is nu uitgeschakeld", /* dutch */
"AlwaysOp <20>tait actif! Il est maintenant d<>sactiv<69>", /* french */
"AlwaysOp estaba activado! Ahora ya esta desactivado", /* spanish */
"AlwaysOp war aktiv! Es wurde ausgeschalten" /* german */
},
/* RPL_ALWAYSOP */
{"This channel is in AlwaysOp mode!", /* english */
"Dit kanaal is in AlwaysOp mode!", /* dutch */
"Ce canal est en mode AlwaysOp!", /* french */
"Este canal est<73> en modo AlwaysOp!", /* spanish */
"Dieser Kanal is im AlwaysOp-Modus!" /* german */
},
/* RPL_KICK1ST */
{"You are not allowed to KICK me!", /* english */
"Het is niet toegestaan mij te KICKen!", /* dutch */
"Vous n'avez pas le droit de me kicker!", /* french */
"No estas autorizado para kickearme!", /* spanish */
"Sie duerfen mich nicht kicken!" /* german */
},
/* RPL_KICK2ND */
{"Please STOP kicking me!", /* english */
"STOP mij te KICKen!", /* dutch */
"Veuillez arr<72>ter de me kicker!", /* french */
"Por favor <20>para de kickearme!", /* spanish */
"Bitte hoeren Sie auf, mich zu kicken!" /* german */
},
/* RPL_CHANNOTEXIST */
{"That channel does not exist!", /* english */
"Dat kanaal bestaat niet!", /* dutch */
"Ce canal n'existe pas!", /* french */
"Ese canal no existe!", /* spanish */
"Diesen Kanal gibt es nicht!" /* german */
},
/* RPL_BADFLOODLIMIT */
{"value of FLOODPRO must be in the range [3-20] or 0 to turn it off",
"FLOODPRO moet een waarde hebben tussen 3 en 20 of 0 om het uit te schakelen",
"la valeur de FLOODPRO doit <20>tre entre 3 et 20 ou 0 pour le d<>sactiver",
"El valor de FLOODPRO tiene que estar entre 3 y 20 <20> 0 para desactivarlo",
"der Wert fon FLOODPRO muss im Bereich von 3 und 20 sein (oder 0 um es abzuschalten)"
},
/* RPL_SETFLOODLIMIT */
{"value of FLOODPRO is now %d", /* english */
"De waarde van FLOODPRO is nu %d", /* dutch */
"la valeur de FLOODPRO est maintenant %d", /* french */
"El valor de FLOOPRO est<73> ahora %d", /* spanish */
"FLOODPRO hat jetzt den Wert %d" /* german */
},
/* RPL_BADNICKFLOODLIMIT */
{"value of NICKFLOODPRO must be in the range [3-10] or 0 to turn it off",
"NICKFLOODPRO moet een waarde hebben tussen 3 en 10 of 0 om het uit te schakelen",
"la valeur de NICKFLOODPRO doit <20>tre entre 3 et 10 ou 0 pour le d<>sactiver",
"El valor de NICKFLOOPRO tiene que estar entre 3 y 10 <20> 0 para desactivarlo",
"Werte fuer NICKFLOODPRO muessen im Bereich von 3 bis 10 sein. Oder 0 um es abzuschalten"
},
/* RPL_SETNICKFLOODLIMIT */
{"value of NICKFLOODPRO is now %d", /* english */
"De waarde van NICKFLOODPRO is nu %d", /* dutch */
"la valeur de NICKFLOODPRO est maintenant %d", /* french */
"El valor de NICKFLOOPRO est<73> ahora en %d", /* spanish */
"der Wert fuer NICKFLOODPRO ist jetzt %d" /* german */
},
/* RPL_BADMASSDEOPLIMIT */
{"value of MASSDEOPPRO must be in the range [3-10] or 0 to turn it off",
"MASSDEOPPRO moet een waarde hebben tussen 3 en 10 of 0 om het uit te schakelen",
"la valeur de MASSDEOPPRO doit <20>tre entre 3 et 10 ou 0 pour le d<>sactiver",
"El valor de MASSDEOPPRO tiene que estar entre 3 y 10 <20> 0 para desactivarlo",
"der Wert von MASSDEOPPRO muss zwischen 3 und 10 liegen, oder 0 um es abzuschalten"
},
/* RPL_SETMASSDEOPLIMIT */
{"value of MASSDEOPPRO is now %d", /* english */
"De waarde van MASSDEOPPRO is nu %d", /* dutch */
"la valeur de MASSDEOPPRO est maintenant %d", /* french */
"El valor de MASSDEOPPRO est<73> ahora en %d", /* spanish */
"MASSDEOPPRO ist jetzt %d" /* german */
},
/* RPL_NOOPON */
{"value of NOOP is now ON", /* english */
"NOOP mode is nu ingeschakeld", /* dutch */
"la valeur de NOOP est maintenant ON", /* french */
"El valor de NOOP est<73> ahora en ON", /* spanish */
"NOOP hat jetzt den Wert EIN" /* german */
},
/* RPL_NOOPOFF */
{"value of NOOP is now OFF", /* english */
"NOOP mode is nu uit", /* dutch */
"la valeur de NOOP est maintenant OFF", /* french */
"El valor de NOOP est<73> ahora en OFF", /* spanish */
"NOOP hat jetzt den Wert AUS" /* german */
},
/* RPL_BADNOOP */
{"value of NOOP must be ON or OFF", /* english */
"Kies 'ON' of 'OFF' voor de waarde van NOOP", /* dutch */
"la valeur de NOOP doit <20>tre ON ou OFF", /* french */
"El valor de NOOP debe ser ON o OFF", /* spanish */
"NOOP kann nur EIN oder AUS sein" /* german */
},
/* RPL_ALWAYSOPON */
{"value of ALWAYSOP is now ON", /* english */
"ALWAYSOP mode is nu ingeschakeld", /* dutch */
"la valeur de ALWAYSOP est maintenant ON", /* french */
"El valor de ALWAYSOP es ahora ON", /* spanish */
"ALWAYSOP ist jetzt EIN" /* german */
},
/* RPL_ALWAYSOPOFF */
{"value of ALWAYSOP is now OFF", /* english */
"ALWAYSOP mode is nu uit", /* dutch */
"la valeur de ALWAYSOP est maintenant OFF", /* french */
"El valor de ALWAYSOP es ahora OFF", /* spanish */
"ALWAYSOP ist jetzt AUS" /* german */
},
/* RPL_BADALWAYSOP */
{"value of ALWAYSOP must be ON or OFF", /* english */
"Kies 'ON' of 'OFF' voor de waarde van ALWAYSOP", /* dutch */
"la valeur de ALWAYSOP doit <20>tre ON ou OFF", /* french */
"El valor de ALWAYSOP debe ser ON o OFF", /* spanish */
"Werte fuer ALWAYSOP sind EIN oder AUS" /* german */
},
/* RPL_OPONLYON */
{"value of OPONLY is now ON", /* english */
"OPONLY mode is nu ingeschakeld", /* dutch */
"la valeur de OPONLY est maintenant ON", /* french */
"El valor de OPONLY es ahora ON", /* spanish */
"der Wert fuer OPONLY ist jetzt EIN" /* german */
},
/* RPL_OPONLYOFF */
{"value of OPONLY is now OFF", /* english */
"OPONLY mode is nu uit", /* dutch */
"la valeur de OPONLY est maintenant OFF", /* french */
"El valor de OPONLY es ahora OFF", /* spanish */
"der Wert fuer OPONLY ist jetzt AUS" /* german */
},
/* RPL_BADOPONLY */
{"value of OPONLY must be ON or OFF", /* english */
"Kies 'ON' of 'OFF' voor de waarde van OPONLY", /* dutch */
"la valeur de OPONLY doit <20>tre ON ou OFF", /* french */
"El valor de OPONLY debe ser ON o OFF", /* spanish */
"Werte fuer OPONLY sind EIN oder AUS" /* german */
},
/* RPL_AUTOTOPICON */
{"value of AUTOTOPIC is now ON", /* english */
"AUTOTOPIC mode is nu ingeschakeld", /* dutch */
"la valeur de AUTOTOPIC est maintenant ON", /* french */
"El valor de AUTOTOPIC es ahora ON", /* spanish */
"der Wert fuer AUTOTOPIC ist jetzt EIN" /* german */
},
/* RPL_AUTOTOPICOFF */
{"value of AUTOTOPIC is now OFF", /* english */
"AUTOTOPIC mode is nu uit", /* dutch */
"la valeur de AUTOTOPIC est maintenant OFF", /* french */
"El valor de AUTOTOPIC es ahora OFF", /* spanish */
"der Wert fuer AUTOTOPIC ist jetzt AUS" /* german */
},
/* RPL_BADAUTOTOPIC */
{"value of AUTOTOPIC must be ON or OFF", /* english */
"Kies 'ON' of 'OFF' voor de waarde van AUTOTOPIC", /* dutch */
"la valeur de AUTOTOPIC doit <20>tre ON ou OFF", /* french */
"El valor de AUTOTOPIC debe ser ON o OFF", /* spanish */
"Werte fuer AUTOTOPIC sind EIN oder AUS" /* german */
},
/* RPL_STRICTOPON */
{"value of STRICTOP is now ON", /* english */
"value of STRICTOP is now ON", /* dutch */
"value of STRICTOP is now ON", /* french */
"El valor de STRICTOP es ahora ON", /* spanish */
"value of STRICTOP is now ON" /* german */
},
/* RPL_STRICTOPOFF */
{"value of STRICTOP is now OFF", /* english */
"value of STRICTOP is now OFF", /* dutch */
"value of STRICTOP is now OFF", /* french */
"El valor de STRICTOP es ahora OFF", /* spanish */
"value of STRICTOP is now OFF" /* german */
},
/* RPL_BADSTRICTOP */
{"value of STRICTOP must be ON or OFF", /* english */
"value of STRICTOP must be ON or OFF", /* dutch */
"value of STRICTOP must be ON or OFF", /* french */
"El valor de STRICTOP debe ser ON o OFF", /* spanish */
"value of STRICTOP must be ON or OFF" /* german */
},
/* RPL_BADUSERFLAGS */
{"New value can be 1-AUTOOP or 0-NO AUTOOP",
"De nieuwe waarde kan zijn 1-AUTOOP, 2-PROTECT ou 3-BOTH",
"La nouvelle valeur peut <20>tre 1-AUTOOP ou 0-PAS DE AUTOOP",
"El nuevo valor puede ser 1-AUTOOP o 0- NOAUTOOP", /* spanish */
"Der neue Wert kann 1-AUTOOP, 2-PROTECT oder 3-BEIDE sein."
},
/* RPL_SETUSERFLAGS */
{"value of USERFLAGS is now %d", /* english */
"de waarde van USERFLAGS is nu %d", /* dutch */
"la nouvelles valeur de USERFLAGS est %d", /* french */
"El nuevo valor de USERFLAGS es ahora %d", /* spanish */
"USERFLAGS ist jetzt %d" /* german */
},
/* RPL_KNOWNLANG */
{"Known languages are", /* english */
"De volgende talen zijn bekend", /* dutch */
"Je connais les langues", /* french */
"Yo hablo y escribo los siguientes idiomas", /* spanish */
"Folgende Sprachen sind bekannt" /* german */
},
/* RPL_SETLANG */
{"Default language is now %s (%s)", /* english */
"De default taal is nu %s (%s)", /* dutch */
"La langue par d<>faut est maintenant %s (%s)", /* french */
"El idioma configurado por defecto es ahora %s (%s)", /* spanish */
"Die neue Default-Sprache ist %s (%s)" /* german */
},
/* RPL_STATUS1 */
{"Channel %s has %d user%s (%d operator%s)", /* english */
"Kanaal %s heeft %d deelnemer%s (%d operator%s)", /* dutch */
"Canal %s a %d usager%s (%d op<6F>rateur%s)", /* french */
"El canal %s tiene %d usuarios%s (%d operadores%s)", /* spanish */
"Kanal %s hat %d Benutzer (%d Betreiber)" /* german */
/* ### NOTE the german version does not use plurals!
The code reflects this. */
},
/* RPL_STATUS2 */
{"Mode is +%s", /* english */
"Mode is +%s", /* dutch */
"Le mode est +%s", /* french */
"El modo es +%s", /* spanish */
"Der Modus ist +%s" /* german */
},
/* RPL_STATUS3 */
{"Default user flags%s", /* english */
"Default 'user flags'%s", /* dutch */
"Flags d'usager par d<>faut%s", /* french */
"Flags por defectos son %s", /* spanish */
"Default-Flags fuer Benutzer %s" /* german */
},
/* RPL_STATUS4 */
{"Default language is %s", /* english */
"Default taal is %s", /* dutch */
"Langue par d<>faut %s", /* french */
"Idioma por defecto %s", /* spanish */
"Default-Sprache ist %s" /* german */
},
/* RPL_STATUS5 */
{"Channel has been idle for %d second%s", /* english */
"Het kanaal is %d second%s idle", /* dutch */
"Le canal est inactif depuis %d seconde%s", /* french */
"El canal no est<73> activo desde hace %d segundos%s", /* spanish */
"Der Kanal ist seit %d Sekunden inaktiv." /* german */
},
/* RPL_SETCHANDEFS */
{"Channel defaults set.", /* english */
"Kanaal defaults geregistreerd.", /* dutch */
"L'<27>tat du canal est enregistr<74>", /* french */
"Los nuevos cambios han sido registrados", /* spanish */
"Default-Werte fuer den Kanal wurden gesetzt" /* german */
},
/* RPL_NOTDEF */
{"That channel is not in my default channel list", /* english */
"Dat kanaal staat niet in mijn default kanaal lijst", /* dutch */
"Ce canal n'est pas sur ma liste", /* french */
"Ese canal no est<73> en mi lista por defecto", /* spanish */
"Dieser Kanal ist nicht auf meiner Liste" /* german */
},
/* RPL_REMDEF */
{"Channel removed from default channel list", /* english */
"Het kanaal is van de default kanaal lijst verwijderd", /* dutch */
"Ce canal n'est plus sur ma liste", /* french */
"Canal eliminado de la lista por defecto", /* spanish */
"Der Kanal wurde aus meiner Liste entfernt" /* german */
},
/* RPL_NOMATCH */
{"No match.", /* english */
"Niet gevonden.", /* dutch */
"Introuvable", /* french */
"No se encuentra", /* spanish */
"Nicht gefunden." /* german */
},
/* RPL_NOOP */
{"Sorry. This channel is in NoOp mode!", /* english */
"Sorry. Dit kanaal is in NoOp mode!", /* dutch */
"D<EFBFBD>sol<EFBFBD>. Ce canal est en mode NoOp!", /* french */
"Lo siento, <20>Ese canal est<73> en modo NoOp!", /* spanish */
"Tut mir leid, aber dieser Kanal ist im NoOp-Modus!" /* german */
},
/* RPL_CANTBEOP */
{"Sorry. You are not allowed to be chanop", /* english */
"Sorry. Het is niet toegestaan dat u kanaal operator bent", /* dutch */
"D<EFBFBD>sol<EFBFBD>. Il ne vous est pas permis d'<27>tre op<6F>rateur", /* french */
"Lo siento. No estas autorizado para ser operador en el canal", /* spanish */
"Tut mir leid, aber Sie duerfen nicht Betreiber werden." /*german */
},
/* RPL_CANTBEOPPED */
{"This user is not allowed to be chanop", /* english */
"Deze gebruiker is het niet toegestaan kanaal operator te zijn", /* dutch */
"Cet usager n'a pas le droit d'<27>tre op<6F>rateur", /* french */
"Ese usuario no est<73> autorizado para ser operador en el canal", /* spanish */
"Dieser Benutzer darf nicht Betreiber werden." /* german */
},
/* RPL_DEOPPED1ST */
{"You are not allowed to DEOP me!", /* english */
"Je mag me niet deoppen!", /* dutch */
"Vous ne pouvez pas me deopper!", /* french */
"<EFBFBD>No me puedes quitar el op!", /* spanish */
"Sie duerfen mich nicht deoppen!" /* german */
},
/* RPL_DEOPPED2ND */
{"Please STOP deopping me!", /* english */
"STOP met me te de-oppen!", /* dutch */
"Veuillez arr<72>ter de me deopper!", /* french */
"Por favor, <20>para de quitarme el op!", /* spanish */
"Bitte hoeren Sie auf, mich zu deoppen!" /* german */
},
/* RPL_DEOPPED3RD */
{"I warned you!", /* english */
"Je was gewaarschuwd!", /* dutch */
"Je vous aurai pr<70>venu!", /* french */
"<EFBFBD>Te he hecho una advertencia!", /* spanish */
"Sie wurden gewarnt!" /* german */
},
/* RPL_USERISPROTECTED */
{"This user is protected", /* english */
"Deze gebruiker is beschermd", /* dutch */
"Cet usager est prot<6F>g<EFBFBD>", /* french */
"Este usuario est<73> protegido", /* spanish */
"Dieser Benutzer ist geschuetzt" /* german */
},
/* RPL_YOUREOPPEDBY */
{"You're opped by %s", /* english */
"U bent kanaal operator gemaakt door %s", /* dutch */
"Vous <20>tes opp<70> par %s", /* french */
"El %s te ha puesto de operador en el canal", /*spanish */
"Sie wurden von %s zum Betreiber gemacht." /* german */
},
/* RPL_USERNOTONCHANNEL */
{"User %s is not on channel %s!", /* english */
"%s bevindt zich niet op kanaal %s!", /* dutch */
"%s n'est pas sur %s!", /* french */
"El usuario %s no est<73> presente en el canal %s!", /* spanish */
"%s ist nicht auf dem Kanal %s!" /* german */
},
/* RPL_YOUREDEOPPEDBY */
{"You're deopped by %s", /* english */
"Het kanaal operatorschap is u ontnomen door %s", /* dutch */
"Vous <20>tes d<>opp<70> par %s", /* french */
"El %s te quit<69> el status de op%s", /* spanish */
"%s hat ihnen den Betreiberstatus entzogen" /* german */
}
};

83
Sources/replies.h Normal file
View File

@@ -0,0 +1,83 @@
/* @(#)$Id: replies.h,v 1.4 1996/11/13 00:40:47 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#define RPL_NOTONCHANNEL 0
#define RPL_NOTCHANOP 1
#define RPL_OPONLY 2
#define RPL_OPSELFONLY 3
#define RPL_NOSUCHNICK 4
#define RPL_ALREADYONCHANNEL 5
#define RPL_IINVITED 6
#define RPL_YOUAREINVITED 7
#define RPL_ALWAYSOPWASACTIVE 8
#define RPL_ALWAYSOP 9
#define RPL_KICK1ST 10
#define RPL_KICK2ND 11
#define RPL_CHANNOTEXIST 12
#define RPL_BADFLOODLIMIT 13
#define RPL_SETFLOODLIMIT 14
#define RPL_BADNICKFLOODLIMIT 15
#define RPL_SETNICKFLOODLIMIT 16
#define RPL_BADMASSDEOPLIMIT 17
#define RPL_SETMASSDEOPLIMIT 18
#define RPL_NOOPON 19
#define RPL_NOOPOFF 20
#define RPL_BADNOOP 21
#define RPL_ALWAYSOPON 22
#define RPL_ALWAYSOPOFF 23
#define RPL_BADALWAYSOP 24
#define RPL_OPONLYON 25
#define RPL_OPONLYOFF 26
#define RPL_BADOPONLY 27
#define RPL_AUTOTOPICON 28
#define RPL_AUTOTOPICOFF 29
#define RPL_BADAUTOTOPIC 30
#define RPL_STRICTOPON 31
#define RPL_STRICTOPOFF 32
#define RPL_BADSTRICTOP 33
#define RPL_BADUSERFLAGS 34
#define RPL_SETUSERFLAGS 35
#define RPL_KNOWNLANG 36
#define RPL_SETLANG 37
#define RPL_STATUS1 38
#define RPL_STATUS2 39
#define RPL_STATUS3 40
#define RPL_STATUS4 41
#define RPL_STATUS5 42
#define RPL_SETCHANDEFS 43
#define RPL_NOTDEF 44
#define RPL_REMDEF 45
#define RPL_NOMATCH 46
#define RPL_NOOP 47
#define RPL_CANTBEOP 48
#define RPL_CANTBEOPPED 49
#define RPL_DEOPPED1ST 50
#define RPL_DEOPPED2ND 51
#define RPL_DEOPPED3RD 52
#define RPL_USERISPROTECTED 53
#define RPL_YOUREOPPEDBY 54
#define RPL_USERNOTONCHANNEL 55
#define RPL_YOUREDEOPPEDBY 56

265
Sources/servers.c Normal file
View File

@@ -0,0 +1,265 @@
/* @(#)$Id: servers.c,v 1.9 1998/01/25 18:35:47 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
aserver **FindServer(aserver ** head, char *name)
{
register aserver **tmp;
if (head == NULL || *head == NULL)
return NULL;
while (*head != NULL)
{
if (!strcasecmp((*head)->name, name))
{
return head;
}
if ((tmp = FindServer(&(*head)->down, name)) != NULL)
{
return tmp;
}
else
{
head = &(*head)->next;
}
}
return NULL;
}
aserver *ToServer(char *name)
{
return (*FindServer(&ServerList, name));
}
void onserver(char *source, char *newserver, char *args)
{
register aserver *head;
register aserver *tmp;
register int i;
char TS[80];
if (source[0] != '\0')
{
head = ToServer(source);
}
else
{
head = NULL;
}
#ifdef BACKUP
if (!strcasecmp(newserver, MAIN_SERVERNAME))
{
quit(MAIN_NICK " is back", 0);
}
#endif
tmp = (aserver *) MALLOC(sizeof(aserver));
tmp->name = (char *)MALLOC(strlen(newserver) + 1);
strcpy(tmp->name, newserver);
GetWord(2, args, TS);
tmp->TS = atol(TS);
if (head == NULL)
{
tmp->next = ServerList;
ServerList = tmp;
TSoffset = tmp->TS - now;
#ifdef DEBUG
printf("New connection: my time: %ld others' time %ld (%ld)\n",
now, tmp->TS, TSoffset);
#endif
}
else
{
tmp->next = head->down;
head->down = tmp;
}
tmp->up = head;
tmp->down = NULL;
for (i = 0; i < 100; i++)
tmp->users[i] = NULL;
}
void onsquit(char *source, char *theserver, char *args)
{
register aserver *serv, **s;
register int i;
char TS[80];
#ifdef FAKE_UWORLD
if (!strcasecmp(theserver, UFAKE_SERVER) && Uworld_status == 1)
{
GetWord(0, args, TS);
if (atol(TS) == UworldServTS)
{
char buffer[200];
sprintf(buffer, "%s squitted", UFAKE_NICK);
log(buffer);
Uworld_status = 0;
}
return;
}
#endif
s = FindServer(&ServerList, theserver);
if (s == NULL)
{
char buffer[200];
sprintf(buffer, "ERROR: SQUIT unknown server %s (from %s)",
theserver, source);
log(buffer);
return;
}
serv = *s;
#ifdef DEBUG
printf("SQUIT: %s %s\n", source, theserver);
#endif
if (args != NULL)
{
GetWord(0, args, TS);
#ifdef DEBUG
if (s != NULL)
printf("ConnectTS: %ld SquitTS: %ld\n", serv->TS, atol(TS));
#endif
}
if (serv != ServerList && args != NULL && serv->TS != atol(TS))
{
#ifdef DEBUG
printf("TS's are different.. ignoring squit!\n");
#endif
return;
}
while (serv->down != NULL)
{
onsquit(NULL, serv->down->name, NULL);
}
for (i = 0; i < 100; i++)
{
while (serv->users[i] != NULL)
{
onquit(serv->users[i]->N->nick);
}
}
TTLALLOCMEM -= strlen(serv->name) + 1;
free(serv->name);
*s = serv->next;
TTLALLOCMEM -= sizeof(aserver);
free(serv);
}
void showmap(char *source)
{
int count = 0;
if (CurrentSendQ > HIGHSENDQTHRESHOLD)
{
notice(source, "Cannot process your request at this time. Try again later.");
return;
}
notice(source, SERVERNAME);
showserv(source, ServerList, &count);
CheckFloodFlood(source, count);
}
void showserv(char *source, aserver * server, int *count)
{
static char prefix[80] = "";
static int offset = 0;
char buffer[200];
register asuser *suser;
register int nbusers = 0, i;
if (server == NULL)
{
return;
}
(*count)++; /* number of servers */
/* count number of users */
for (i = 0; i < 100; i++)
{
suser = server->users[i];
while (suser != NULL)
{
nbusers++;
suser = suser->next;
}
}
if (server->next == NULL)
{
sprintf(buffer, "%s`-%s (%d client%s)", prefix, server->name, nbusers, (nbusers != 1) ? "s" : "");
}
else
{
sprintf(buffer, "%s|-%s (%d client%s)", prefix, server->name, nbusers, (nbusers != 1) ? "s" : "");
}
notice(source, buffer);
if (server->next != NULL)
strcpy(prefix + offset, "| ");
else
strcpy(prefix + offset, " ");
offset += 2;
showserv(source, server->down, count);
offset -= 2;
prefix[offset] = '\0';
showserv(source, server->next, count);
}
void onsettime(char *source, char *value)
{
char buffer[200];
TSoffset = atol(value) - now;
sprintf(buffer, "SETTIME from %s (%s) (%ld)", source, value, TSoffset);
log(buffer);
#ifdef DEBUG
puts(buffer);
#endif
}
void showversion(char *source)
{
char buffer[200];
sprintf(buffer, ":%s 351 %s . %s :%s\n", SERVERNAME, source, SERVERNAME, VERSION);
sendtoserv(buffer);
}

791
Sources/shitlist.c Normal file
View File

@@ -0,0 +1,791 @@
/* @(#)$Id: shitlist.c,v 1.12 2000/01/28 01:29:14 lgm Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
typedef struct ShitDisk
{
time_t time;
time_t expiration;
char match[80];
char from[80];
char reason[200];
char channel[50];
int level;
}
ShitDisk;
static int active = 0;
int sl_hash(char *channel)
{
register int i, j = 0;
for (i = 1; i < strlen(channel); i++)
j += (unsigned char)toupper(channel[i]);
return (j % 1000);
}
void AddToShitList(char *source, char *ch, char *args, int force)
{
char buffer[1024];
char srcuh[200];
char channel[80];
char pattern[200];
char strtime[80];
char strlevel[80];
char *reason;
time_t exp;
int shitlevel;
int srcAccess;
int exact;
register char *ptr1, *ptr2;
register aluser *luser;
register ShitUser *curr;
register achannel *chan;
if (*args == '#')
{
GetWord(0, args, channel);
args = ToWord(1, args);
}
else
{
strcpy(channel, ch);
GuessChannel(source, channel);
}
if (*source && force == 0)
{
chan = ToChannel(channel);
if (chan != NULL && (chan->flags & CFL_OPONLY))
{
notice(source, replies[RPL_OPONLY][chan->lang]);
return;
}
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: ban <#channel> <nick|address> "
"<duration in hours> <level> <reason>");
return;
}
if (!*source || force > 0)
srcAccess = (MASTER_ACCESS + 1);
else
srcAccess = Access(channel, source);
if (srcAccess < ADD_TO_SHITLIST_LEVEL)
{
ReplyNotAccess(source, channel);
return;
}
GetWord(0, args, pattern);
GetWord(1, args, strtime);
GetWord(2, args, strlevel);
reason = ToWord(3, args);
if (strlen(reason) > 200)
reason[199] = '\0';
if (!*pattern || (*strtime != '\0' && !isdigit(*strtime)))
{
notice(source, "SYNTAX: ban [#channel] <nick|address> "
"[duration in hours] [level] [reason]");
return;
}
if (!*strtime)
{
exp = SHITLIST_DEFAULT_TIME;
}
else
{
exp = atoi(strtime);
}
if (!*strlevel)
{
shitlevel = AUTO_KICK_SHIT_LEVEL;
}
else
{
shitlevel = atoi(strlevel);
}
exp *= 3600;
if (exp < 0 || exp > (MAX_BAN_DURATION * 24 * 3600))
{
sprintf(buffer, "Invalid duration (Max %d days)", MAX_BAN_DURATION);
notice(source, buffer);
return;
}
if (shitlevel < 1 || shitlevel > 1000)
{
notice(source, "Ban level must be in the range 1-1000");
return;
}
if (srcAccess < shitlevel)
{
notice(source, "Can't ban to a higher level than your access level.");
return;
}
exp += now;
if ((luser = ToLuser(source)) != NULL)
{
sprintf(srcuh, "%s!%s@%s", luser->nick, luser->username, luser->site);
}
else
{
strcpy(srcuh, source);
}
/* look if the user is on the channel, if so, take his address */
luser = ToLuser(pattern);
if (luser != NULL)
{
MakeBanMask(luser, pattern);
exact = 0;
}
else
{
if ((ptr2 = strchr(pattern, '@')) == NULL)
{
strcat(pattern, "@*");
ptr2 = strchr(pattern, '@');
}
if ((ptr1 = strchr(pattern, '!')) == NULL)
{
char tmp[200];
sprintf(tmp, "*!%s", pattern);
strncpy(pattern, tmp, 200);
pattern[199] = '\0';
ptr1 = pattern + 1;
}
if (ptr1 > ptr2)
{
notice(source, "Illegal ban mask");
return;
}
exact = 1;
}
/* count number of bans.. if it's > MAX_BAN.. refuse to add */
if (!force && *source && shitlevel > 0)
{
register int count = 0;
curr = ShitList[sl_hash(channel)];
while (curr)
{
if (!strcasecmp(curr->channel, channel))
count++;
curr = curr->next;
}
if (count > MAX_BAN)
{
notice(source, "Sorry, there are too many bans on"
" your channel. You'll have to remove some first.");
return;
}
}
/* Now, seek thru the ShitList if the pattern is already there.
if it is, only change the information already present */
curr = ShitList[sl_hash(channel)];
if (exact)
{
while (curr && (strcasecmp(curr->match, pattern) || strcasecmp(curr->channel, channel)))
{
curr = curr->next;
}
}
else
{
while (curr && (!match(pattern, curr->match) || strcasecmp(curr->channel, channel)))
{
curr = curr->next;
}
}
if (curr)
{
/* if the user is already on the shitlist.. */
/* if this is the result of a flood protection.. we have to
make sure the user is not already shitlisted for a longer
time.. */
if (shitlevel == 0 || curr->expiration < exp)
curr->expiration = exp;
curr->time = now;
/* if this is the result of a flood protection.. we have to
make sure the user is not already shitlisted at a higher
level.. */
if (shitlevel == 0 || curr->level < shitlevel)
curr->level = shitlevel;
TTLALLOCMEM -= strlen(curr->from) + 1;
free(curr->from);
curr->from = (char *)MALLOC(strlen(srcuh) + 1);
strcpy(curr->from, srcuh);
TTLALLOCMEM -= strlen(curr->reason) + 1;
free(curr->reason);
curr->reason = (char *)MALLOC(strlen(reason) + 1);
strcpy(curr->reason, reason);
}
else
{
#ifdef DEBUG
printf("TIME: %ld EXP: %ld LEVEL %d\n", now, exp, shitlevel);
#endif
/* if the user is NOT already on the shitlist */
/* first, create a new structure */
curr = (ShitUser *) MALLOC(sizeof(ShitUser));
curr->time = now;
curr->expiration = exp;
curr->level = shitlevel;
curr->match = (char *)MALLOC(strlen(pattern) + 1);
strcpy(curr->match, pattern);
curr->from = (char *)MALLOC(strlen(srcuh) + 1);
strcpy(curr->from, srcuh);
curr->reason = (char *)MALLOC(strlen(reason) + 1);
strcpy(curr->reason, reason);
curr->channel = (char *)MALLOC(strlen(channel) + 1);
strcpy(curr->channel, channel);
/* Then, link it to the list.. */
curr->next = ShitList[sl_hash(channel)];
ShitList[sl_hash(channel)] = curr;
}
/* schedule the removal of the entry..
*/
AddEvent(EVENT_CLEANSHITLIST, exp, channel);
if (*source && !force)
notice(source, "Ban list updated");
if (shitlevel >= AUTO_KICK_SHIT_LEVEL && !force)
{
#ifdef DEBUG
printf("Calling mban(\"\",%s,%s)\n", channel, pattern);
#endif
mban("", channel, pattern);
sprintf(buffer, "%s (%s) %s", pattern, source, reason);
kick("", channel, buffer);
}
/* Now, clean the shitlist */
if (!force)
CleanShitList("", channel);
}
void RemShitList(char *source, char *ch, char *args, int force)
{
char channel[80];
char pattern[2][200];
register aluser *luser;
register ShitUser *curr;
register achannel *chan;
int srcaccess, exact;
if (*args == '#')
{
GetWord(0, args, channel);
args = ToWord(1, args);
}
else
{
strcpy(channel, ch);
GuessChannel(source, channel);
}
if (*source && force == 0)
{
chan = ToChannel(channel);
if (chan != NULL && (chan->flags & CFL_OPONLY))
{
notice(source, replies[RPL_OPONLY][chan->lang]);
return;
}
}
if (!strcmp(channel, "*"))
{
notice(source, "SYNTAX: unban <#channel> <nick|address>");
return;
}
if (!*source || force > 0)
srcaccess = (MASTER_ACCESS + 1);
else
srcaccess = Access(channel, source);
if (srcaccess < ADD_TO_SHITLIST_LEVEL)
{
ReplyNotAccess(source, channel);
return;
}
GetWord(0, args, pattern[0]);
if (!*pattern[0])
{
notice(source, "SYNTAX: unban [#channel] <nick|address>");
return;
}
/* look if the user is on the channel, if so, take his address */
luser = ToLuser(pattern[0]);
if (luser != NULL)
{
sprintf(pattern[1], "%s!%s@%s",
luser->nick, luser->username, luser->site);
exact = 0;
}
else
{
exact = 1;
}
/* Now, seek thru the ShitList if the pattern is already there. */
curr = ShitList[sl_hash(channel)];
if (exact)
{
while (curr && (strcasecmp(curr->match, pattern[0]) || strcasecmp(curr->channel, channel) || srcaccess < curr->level))
{
curr = curr->next;
}
}
else
{
while (curr && (!match(pattern[1], curr->match) || strcasecmp(curr->channel, channel) || srcaccess < curr->level))
{
curr = curr->next;
}
}
if (curr)
{
curr->expiration = now - 1;
if (*source && !force)
notice(source, "Ban list updated");
CleanShitList("", channel);
}
else
{
unban("", channel, pattern[0]);
}
}
void CleanShitList(char *source, char *channel)
{
char buffer[200];
register ShitUser *curr, *prev;
register achannel *chan;
int i;
if (*source && Access(channel, source) < CLEAN_SHITLIST_LEVEL)
{
notice(source, "Your admin Access is too low");
return;
}
i = sl_hash(channel);
curr = ShitList[i];
prev = NULL;
while (curr)
{
chan = ToChannel(curr->channel);
if (chan == NULL || (curr->expiration <= now && !strcasecmp(channel, chan->name))
|| curr->level == 0)
{
if (chan != NULL && chan->on && chan->AmChanOp)
{
unban("", curr->channel, curr->match);
}
if (prev)
{
prev->next = curr->next;
TTLALLOCMEM -= strlen(curr->match) + 1;
free(curr->match);
TTLALLOCMEM -= strlen(curr->from) + 1;
free(curr->from);
TTLALLOCMEM -= strlen(curr->reason) + 1;
free(curr->reason);
TTLALLOCMEM -= strlen(curr->channel) + 1;
free(curr->channel);
TTLALLOCMEM -= sizeof(ShitUser);
free(curr);
curr = prev->next;
}
else
{
ShitList[i] = curr->next;
TTLALLOCMEM -= strlen(curr->match) + 1;
free(curr->match);
TTLALLOCMEM -= strlen(curr->from) + 1;
free(curr->from);
TTLALLOCMEM -= strlen(curr->reason) + 1;
free(curr->reason);
TTLALLOCMEM -= strlen(curr->channel) + 1;
free(curr->channel);
TTLALLOCMEM -= sizeof(ShitUser);
free(curr);
curr = ShitList[i];
}
}
else
{
prev = curr;
curr = curr->next;
}
}
if (*source)
notice(source, "Ban list is now up-to-date");
sprintf(buffer, "Cleaned banlist on %s", channel);
log(buffer);
}
int IsShit(char *channel, char *user, char *out, char *reason)
{
register ShitUser *curr;
register aluser *luser;
char uh[200];
if (strchr(user, '!') != NULL)
{
strcpy(uh, user);
}
else
{
luser = ToLuser(user);
sprintf(uh, "%s!%s@%s", luser->nick, luser->username, luser->site);
}
curr = ShitList[sl_hash(channel)];
#ifdef DEBUG
printf("IsShit(%s,%s,%s)\n", channel, user, out);
#endif
while (curr && (!match(channel, curr->channel) || !match(uh, curr->match)))
curr = curr->next;
#ifdef DEBUG
if (curr)
printf("Banlevel: %d\n", curr->level);
#endif
if (curr)
{
if (out != NULL)
strcpy(out, curr->match);
if (reason != NULL)
strcpy(reason, curr->reason);
return (curr->level);
}
else
{
return 0;
}
}
void ShowShitList(char *source, char *ch, char *args)
{
register ShitUser *curr;
struct tm *tp;
char buffer[1024], global[] = "*";
char channel[80];
int found = 0;
if (*args == '#')
{
GetWord(0, args, channel);
args = ToWord(1, args);
}
else
{
strcpy(channel, ch);
GuessChannel(source, channel);
}
if (!strcmp(channel, "*") || !*args)
{
notice(source, "SYNTAX: lbanlist [#channel] <search pattern>");
return;
}
if (!ToUser(channel, source) &&
Access(channel, source) < 500 && Access(global, source) < 500)
{
notice(source, "You are not on that channel");
return;
}
curr = ShitList[sl_hash(channel)];
while (curr)
{
if (!strcasecmp(channel, curr->channel) && match(curr->match, args))
{
found++;
}
curr = curr->next;
}
if ((found > 15) && (source[0] != '+'))
{
sprintf(buffer, "There are %d matching entries. Please use a userhost mask to narrow down the list.", found);
notice(source, buffer);
return;
}
if (found == 0)
{
sprintf(buffer, "*** No entry matching with %s ***", args);
notice(source, buffer);
return;
}
sprintf(buffer, "*** Ban List for channel %s ***", channel);
notice(source, buffer);
curr = ShitList[sl_hash(channel)];
while (curr)
{
if (!strcasecmp(channel, curr->channel) && match(curr->match, args))
{
sprintf(buffer, "%s %s Level: %d", curr->channel,
curr->match, curr->level);
notice(source, buffer);
sprintf(buffer, "ADDED BY: %s (%s)", curr->from,
(*curr->reason) ? curr->reason : "No reason given");
notice(source, buffer);
tp = gmtime(&curr->time);
sprintf(buffer, "SINCE: %sUCT", asctime(tp));
*strchr(buffer, '\n') = ' ';
notice(source, buffer);
sprintf(buffer, "EXP: %s", time_remaining(curr->expiration - now));
notice(source, buffer);
}
curr = curr->next;
}
notice(source, "*** END ***");
}
void SaveShitList(char *source, char *channel)
{
ShitDisk tmp;
register ShitUser *user;
register int file;
char buffer[200];
int i;
if (*source && Access(channel, source) < SAVE_SHITLIST_LEVEL)
{
notice(source, "Your admin Access is too low!");
return;
}
if (active)
return;
active = 1;
alarm(5); /* avoid NFS hangs */
file = open(SHITLIST_FILE ".new", O_WRONLY | O_CREAT | O_TRUNC, 0600);
alarm(0);
if (file < 0)
{
if (*source)
notice(source, "Error opening BanList file! Aborted.");
log("Error saving shitlist");
active = 0;
return;
}
sprintf(buffer, ":%s AWAY :Busy saving precious ban list\n", mynick);
sendtoserv(buffer);
dumpbuff();
for (i = 0; i < 1000; i++)
{
user = ShitList[i];
while (user)
{
tmp.time = user->time;
tmp.expiration = user->expiration;
strncpy(tmp.match, user->match, 79);
tmp.match[79] = '\0';
strncpy(tmp.from, user->from, 79);
tmp.from[79] = '\0';
strncpy(tmp.reason, user->reason, 199);
tmp.reason[199] = '\0';
strncpy(tmp.channel, user->channel, 49);
tmp.channel[49] = '\0';
tmp.level = user->level;
alarm(2);
if (write(file, &tmp, sizeof(ShitDisk)) <= 0)
{
alarm(0);
close(file);
log("ERROR: Can't save banlist");
log((char *)sys_errlist[errno]);
alarm(2);
remove(SHITLIST_FILE ".new");
alarm(0);
active = 0;
sprintf(buffer, ":%s AWAY\n", mynick);
sendtoserv(buffer);
return;
}
alarm(0);
user = user->next;
}
}
close(file);
alarm(20);
rename(SHITLIST_FILE ".new", SHITLIST_FILE);
alarm(0);
if (*source)
notice(source, "banlist saved.");
active = 0;
sprintf(buffer, ":%s AWAY\n", mynick);
sendtoserv(buffer);
}
void LoadShitList(char *source)
{
ShitDisk tmp;
ShitUser *user;
int file;
int i;
if (*source && Access("*", source) < LOAD_SHITLIST_LEVEL)
{
notice(source, "Your admin access is too low!");
return;
}
if (active)
return;
active = 1;
file = open(SHITLIST_FILE, O_RDONLY);
if (file < 0)
{
if (*source)
notice(source, "Error opening BanList file! Aborted.");
log("ERROR loading banlist");
active = 0;
return;
}
/* empty existing shitlist */
for (i = 0; i < 1000; i++)
{
while ((user = ShitList[i]) != NULL)
{
ShitList[i] = ShitList[i]->next;
TTLALLOCMEM -= strlen(user->match) + 1;
free(user->match);
TTLALLOCMEM -= strlen(user->from) + 1;
free(user->from);
TTLALLOCMEM -= strlen(user->reason) + 1;
free(user->reason);
TTLALLOCMEM -= strlen(user->channel) + 1;
free(user->channel);
TTLALLOCMEM -= sizeof(ShitUser);
free(user);
}
}
while (read(file, &tmp, sizeof(ShitDisk)) > 0)
{
if (tmp.expiration < now)
continue;
user = (ShitUser *) MALLOC(sizeof(ShitUser));
user->time = tmp.time;
user->expiration = tmp.expiration;
if (tmp.level > 500)
tmp.level = 500;
user->level = tmp.level;
user->match = (char *)MALLOC(strlen(tmp.match) + 1);
strcpy(user->match, tmp.match);
user->from = (char *)MALLOC(strlen(tmp.from) + 1);
strcpy(user->from, tmp.from);
user->reason = (char *)MALLOC(strlen(tmp.reason) + 1);
strcpy(user->reason, tmp.reason);
user->channel = (char *)MALLOC(strlen(tmp.channel) + 1);
strcpy(user->channel, tmp.channel);
user->next = ShitList[sl_hash(tmp.channel)];
ShitList[sl_hash(tmp.channel)] = user;
}
close(file);
if (*source)
notice(source, "BanList loaded!");
active = 0;
}

133
Sources/show_old_managers.c Normal file
View File

@@ -0,0 +1,133 @@
/* @(#)$Id: show_old_managers.c,v 1.2 1998/01/08 17:02:18 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#include "dirent.h"
time_t now;
#define HOWLONG (30*24*60*60) /* 30 days */
void fix_user_file(char *file, char *channel)
{
dbuser dbu;
int fd;
fd = open(file, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "Can't open %s [%s]\n", file, sys_errlist[errno]);
return;
}
/* Find at least one 500 seen within the last 30 days */
while (read(fd, &dbu, sizeof(dbuser)) == sizeof(dbuser))
{
if (dbu.header[0] != 0xFF || dbu.header[1] != 0xFF ||
dbu.footer[0] != 0xFF || dbu.footer[1] != 0xFF)
{
continue;
}
if (!strcmp(dbu.match, "!DEL!"))
continue;
if (dbu.access == 500 && (now - dbu.lastseen) < HOWLONG)
{
close(fd);
return;
}
}
/* Ok.. at this point, there is no channel manager that was seen
* within 30 days. Show all of them.
*/
lseek(fd, 0L, SEEK_SET);
while (read(fd, &dbu, sizeof(dbuser)) == sizeof(dbuser))
{
if (dbu.header[0] != 0xFF || dbu.header[1] != 0xFF ||
dbu.footer[0] != 0xFF || dbu.footer[1] != 0xFF)
{
continue;
}
if (!strcmp(dbu.match, "!DEL!"))
continue;
if (dbu.access != 500)
continue;
printf("%-14s %-9s %03d %-26s %.24s\n",
dbu.channel, dbu.nick, dbu.access, dbu.match, ctime(&dbu.lastseen));
}
close(fd);
}
void fix_user_db(void)
{
DIR *dp;
struct dirent *ent;
char dir[256], file[256], channel[80], *ptr;
int count;
for (count = 0; count < 1000; count++)
{
sprintf(dir, "db/channels/%04X", count);
dp = opendir(dir);
if (dp == NULL)
{
fprintf(stderr, "Can't read %s [%s]\n", dir, sys_errlist[errno]);
continue;
}
while ((ent = readdir(dp)) != NULL)
{
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
strcpy(channel, ent->d_name);
for (ptr = channel; *ptr; ptr++)
if (*ptr == ' ')
*ptr = '/';
sprintf(file, "db/channels/%04X/%s", count, ent->d_name);
fix_user_file(file, channel);
}
closedir(dp);
}
}
int main(void)
{
if (chdir(HOMEDIR) < 0)
{
perror(HOMEDIR);
exit(1);
}
time(&now);
fix_user_db();
return 0;
}

110
Sources/showdb.c Normal file
View File

@@ -0,0 +1,110 @@
/* @(#)$Id: showdb.c,v 1.6 1999/01/18 04:17:40 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#include "dirent.h"
time_t now;
void fix_user_file(char *file, char *channel)
{
dbuser dbu;
int fd;
fd = open(file, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "Can't open %s [%s]\n", file, sys_errlist[errno]);
return;
}
while (read(fd, &dbu, sizeof(dbuser)) == sizeof(dbuser))
{
if (dbu.header[0] != 0xFF || dbu.header[1] != 0xFF ||
dbu.footer[0] != 0xFF || dbu.footer[1] != 0xFF)
{
continue;
}
if (!strcmp(dbu.match, "!DEL!"))
continue;
printf("%-14s %-9s %03d %-26s %.24s\n",
dbu.channel, dbu.nick, dbu.access, dbu.match, ctime(&dbu.lastseen));
}
close(fd);
}
void fix_user_db(void)
{
DIR *dp;
struct dirent *ent;
char dir[256], file[256], channel[80], *ptr;
int count;
for (count = 0; count < 1000; count++)
{
sprintf(dir, "db/channels/%04X", count);
dp = opendir(dir);
if (dp == NULL)
{
fprintf(stderr, "Can't read %s [%s]\n", dir, sys_errlist[errno]);
continue;
}
while ((ent = readdir(dp)) != NULL)
{
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
strcpy(channel, ent->d_name);
for (ptr = channel; *ptr; ptr++)
if (*ptr == ' ')
*ptr = '/';
sprintf(file, "db/channels/%04X/%s", count, ent->d_name);
fix_user_file(file, channel);
}
closedir(dp);
}
}
int main(int argc, char **argv)
{
if (chdir(HOMEDIR) < 0)
{
perror(HOMEDIR);
exit(1);
}
time(&now);
if (argc == 3)
{
fix_user_file(argv[1], argv[2]);
}
else
fix_user_db();
return 0;
}

183
Sources/socketio.c Normal file
View File

@@ -0,0 +1,183 @@
/* @(#)$Id: socketio.c,v 1.7 1998/06/23 23:35:08 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
/* These routines were first developed for the telnet3d project.
* Special thanks to Danny Mitchell (wildthang@irc) for his help.
*/
#include "h.h"
#ifdef DOHTTP
#include <stdarg.h>
extern void chat_close(http_socket *, char *);
int readfrom_http(http_socket * client)
{
void http_log(char *fmt,...);
char buf[1024];
int length;
if ((length = read(client->fd, buf, 1023)) <= 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN)
{
return 0;
}
else
{
if (client->status == HTTP_CHAT)
chat_close(client, "read error");
close(client->fd);
client->fd = -1;
client->status = HTTP_ERROR;
return -1;
}
}
buf[length] = '\0';
#ifdef DEBUG
printf("AA: |%s|\n", buf);
#endif
if (copy_to_buffer(&client->inbuf, buf, length) >= 4096)
{
http_log("ERROR: Recv'd more than 4K from client! (flood?)");
if (client->status == HTTP_CHAT)
chat_close(client, "Input packet too big");
client->status = HTTP_ERROR;
close(client->fd);
client->fd = -1;
return -1;
}
if (find_char_in_buffer(&client->inbuf, '\n', 1023))
{
while (find_char_in_buffer(&client->inbuf, '\n', 1023) &&
client->status != HTTP_PIPE &&
client->status != HTTP_ENDING &&
client->status != HTTP_ERROR)
{
copy_from_buffer(&client->inbuf, buf, '\n', 1023);
parse_http(client, buf);
}
/* Check for STUPID MSIE! who doesn't send a \n after post data
** so check for a = in the first 10 chars, assume *ugh* it's post data
*/
if (find_char_in_buffer(&client->inbuf, '=', 10))
{
if (client->status != HTTP_PIPE &&
client->status != HTTP_ENDING &&
client->status != HTTP_ERROR)
{
#ifdef DEBUG
printf("SEND\n");
#endif
copy_from_buffer(&client->inbuf, buf, '\0', 1023);
parse_http(client, buf);
}
}
}
else if (length > 200)
{
if (client->status == HTTP_CHAT)
chat_close(client, "line too long");
client->status = HTTP_ERROR;
close(client->fd);
client->fd = -1;
return -1;
}
return 1;
}
int flush_http_buffer(http_socket * client)
{
http_file_pipe *fpipe;
char buf[1024];
int length;
int count;
if (client == NULL || client->outbuf == NULL)
return -1;
while ((count = look_in_buffer(&client->outbuf, buf, '\0', 1023)) > 0)
{
if ((length = write(client->fd, buf, count)) <= 0)
{
if ((errno == EWOULDBLOCK || errno == EAGAIN) && length != 0)
{
return 0;
}
else
{
if (client->status == HTTP_PIPE)
{
for (fpipe = FilePipes; fpipe != NULL; fpipe = fpipe->next)
{
if (fpipe->hsock == client)
{
close(fpipe->fd);
destroy_file_pipe(fpipe);
break;
}
}
}
if (client->status == HTTP_CHAT)
chat_close(client, "write error");
close(client->fd);
client->fd = -1;
client->status = HTTP_ERROR;
return -1;
}
}
else
{
skip_char_in_buffer(&client->outbuf, length);
HTTPTTLSENTBYTES += length;
}
}
return 0;
}
/* sendto_client() by SeKs <intru@step.polymtl.ca>
* args (struct buffer_block **block, char *format, args...)
* adds 'args' according to 'format' to the client's output
* buffer.
*/
long sendto_http(http_socket * sck, char *format,...)
{
va_list args;
char string[1024];
va_start(args, format);
vsprintf(string, format, args);
va_end(args);
return copy_to_buffer(&sck->outbuf, string, strlen(string));
}
#endif /* DOHTTP */

198
Sources/special.c Normal file
View File

@@ -0,0 +1,198 @@
/* @(#)$Id: special.c,v 1.3 1996/11/13 00:40:49 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
#define SPECFILE "special.log"
void SpecLog(char *text)
{
int fd;
char date[80],buffer[1024];
strcpy(date,ctime(&now));
*strchr(date,'\n')='\0';
alarm(2);
if((fd=open(SPECFILE,O_WRONLY|O_CREAT|O_APPEND,0600))>=0){
alarm(0);
sprintf(buffer,"%s: %s\n",date,text);
alarm(2);
write(fd,buffer,strlen(buffer));
alarm(0);
close(fd);
}
alarm(0);
}
void logmap(aserver *server,FILE *fp)
{
static char prefix[80]="";
static int offset=0;
asuser *suser;
int nbusers=0,i;
if(server==NULL){
return;
}
/* count number of users */
for(i=0;i<100;i++){
suser=server->users[i];
while(suser!=NULL){
nbusers++;
suser=suser->next;
}
}
if(server->next==NULL){
fprintf(fp,"%s`-%s (%d user%s)\n",prefix,server->name,nbusers,(nbusers>1)?"s":"");
}else{
fprintf(fp,"%s|-%s (%d user%s)\n",prefix,server->name,nbusers,(nbusers>1)?"s":"");
}
if(server->next!=NULL)
strcpy(prefix+offset,"| ");
else
strcpy(prefix+offset," ");
offset+=2;
logmap(server->down,fp);
offset-=2;
prefix[offset]='\0';
logmap(server->next,fp);
}
void SpecMap(void)
{
FILE *fp;
if((fp=fopen(SPECFILE,"a"))!=NULL){
logmap(ServerList,fp);
fclose(fp);
}
}
#ifdef CHANNEL_LOG
void LogChan(void)
{
register achannel *chan;
register auser *user;
register aluser *luser;
register int i,isreg,count;
register FILE *fp;
char mode[80];
char flag;
if((fp=fopen(CHANNEL_LOG,"a"))==NULL)
return;
fprintf(fp,"%ld %s",now,ctime(&now));
for(i=0;i<1000;i++){
for(chan=ChannelList[i];chan!=NULL;chan=chan->next){
count=isreg=(chan->on)?1:0;
for(user=chan->users;user;user=user->next){
count++;
if(!isreg &&
!strcasecmp(user->N->username,DEFAULT_USERNAME)&&
!strcasecmp(user->N->site,DEFAULT_HOSTNAME)){
isreg=1;
}
}
GetWord(0,chan->mode,mode);
if(strchr(mode,'s'))
flag='S';
else if(strchr(mode,'p'))
flag='P';
else
flag='+';
fprintf(fp,"%s %c %d %s\n",
chan->name,flag,count,isreg?"REG'D":"");
}
}
count=0;
for(i=0;i<1000;i++){
luser=Lusers[i];
while(luser!=NULL){
count++;
luser=luser->next;
}
}
fprintf(fp,"* %d \n",count);
fclose(fp);
}
#endif
#ifdef HISTORY
void HistLog(char *text)
{
int fd;
char date[80],buffer[1024];
strcpy(date,ctime(&now));
*strchr(date,'\n')='\0';
alarm(2);
if((fd=open("hist.log",O_WRONLY|O_CREAT|O_APPEND,0600))>=0){
alarm(0);
sprintf(buffer,"%s: %s\n",date,text);
alarm(2);
write(fd,buffer,strlen(buffer));
alarm(0);
close(fd);
}
alarm(0);
}
void History(char *line)
{
static char Log[25][512];
static int offset=0;
if(line==NULL){
int i=offset,top=offset-1;
if(top==-1)
top=25;
while(i!=top){
if(i==25)
i=0;
HistLog(Log[i]);
i++;
}
}
else
{
strncpy(Log[offset],line,511);
Log[offset][511]='\0';
if(++offset==25)
offset=0;
}
}
#endif

303
Sources/struct.h Normal file
View File

@@ -0,0 +1,303 @@
/* @(#)$Id: struct.h,v 1.6 1997/07/01 21:51:09 cvs Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#ifdef NICKSERV
#include "nickserv.h"
#endif
typedef struct filehdr {
unsigned char magic;
unsigned int no;
} filehdr;
typedef struct RegUser {
char *realname;
char *match;
char *channel;
char *passwd;
char *modif;
int access;
unsigned long flags;
time_t suspend;
time_t lastseen;
off_t offset;
int modified;
int inuse;
time_t lastused;
struct RegUser *next;
} RegUser;
typedef struct dbuser {
unsigned char header[2];
char nick[80];
char match[80];
char passwd[20];
char channel[50];
char modif[80];
int access;
unsigned long flags;
time_t suspend;
time_t lastseen;
unsigned char footer[2];
} dbuser;
typedef struct achannel {
char *name;
int AmChanOp;
int on;
int MassDeopPro;
int NickFloodPro;
int MsgFloodPro;
int lang;
time_t TS;
time_t lastact;
time_t lasttopic;
unsigned long flags;
unsigned long uflags;
char mode[80];
char lastjoin[20];
struct modequeue *modebuff;
struct aban *bans;
struct auser *users;
struct achannel *next;
} achannel;
typedef struct adefchan {
char name[50];
char mode[80];
char url[80];
char topic[80];
int MassDeopPro;
int NickFloodPro;
int MsgFloodPro;
int lang;
time_t TS;
unsigned long flags;
unsigned long uflags;
struct adefchan *next;
} adefchan;
typedef struct achannelnode {
struct achannel *N;
struct anickchange *nickhist;
struct achannelnode *next;
} achannelnode;
typedef struct aserver {
char *name;
time_t TS;
struct asuser *users[100];
struct aserver *up;
struct aserver *down;
struct aserver *next;
} aserver;
typedef struct asuser {
struct aluser *N;
struct asuser *next;
} asuser;
typedef struct aluser {
char *nick;
char *username;
char *site;
time_t time;
char mode;
struct aserver *server;
struct achannelnode *channel;
struct avalchan *valchan;
struct aluser *next;
#ifdef NICKSERV
struct aregnick *regnick;
time_t reglimit;
#endif
} aluser;
typedef struct avalchan {
char *name;
RegUser *reg;
struct avalchan *next;
} avalchan;
typedef struct auser {
struct aluser *N;
char chanop;
time_t lastact;
struct amsg *msghist;
struct adeop *deophist;
struct auser *next;
} auser;
typedef struct aban {
char pattern[80];
struct aban *next;
} aban;
typedef struct adeop {
time_t time;
char nick[NICK_LENGTH];
struct adeop *next;
} adeop;
typedef struct anickchange {
time_t time;
char nick[NICK_LENGTH];
struct anickchange *next;
} anickchange;
typedef struct modequeue {
int AsServer;
char flag[3];
char arg[80];
struct modequeue *prev;
struct modequeue *next;
} modequeue;
typedef struct amsg {
time_t time;
int length;
struct amsg *next;
} amsg;
typedef struct ShitUser {
time_t time;
time_t expiration;
char *match;
char *from;
char *reason;
char *channel;
int level;
struct ShitUser *next;
} ShitUser;
typedef struct anevent {
time_t time;
int event;
char param[80];
struct anevent *next;
} anevent;
typedef struct alang {
int no;
char *abbr;
char *name;
} alang;
struct buffer_block {
char buf[BUFFER_BLOCK_SIZE];
short offset_read;
short offset_write;
struct buffer_block *next;
};
typedef struct irc_socket {
int fd;
time_t TS;
struct buffer_block *inbuf;
struct buffer_block *outbuf;
struct irc_socket *next;
} irc_socket;
typedef struct http_raw {
unsigned long key;
} http_raw;
typedef struct http_post {
char path[80];
char protocol[80];
int count;
int ready;
} http_post;
typedef struct http_socket {
int fd;
int status;
int dbio;
time_t TS;
time_t since;
void *hook;
struct buffer_block *inbuf;
struct buffer_block *outbuf;
struct sockaddr_in peer;
struct http_socket *next;
} http_socket;
typedef struct http_file_pipe {
int fd;
http_socket *hsock;
struct http_file_pipe *next;
} http_file_pipe;
typedef struct misc_socket {
int fd;
int type;
int status;
time_t TS;
char link[80];
struct buffer_block *inbuf;
struct buffer_block *outbuf;
struct misc_socket *next;
} misc_socket;
#define DBCALLBACK(X) void (*X)(int *,off_t,int,void *,void *,dbuser*,int)
typedef struct dbquery {
int fd;
off_t offset;
time_t time;
unsigned int type;
int action;
int count;
DBCALLBACK(callback);
struct buffer_block *buf;
void *hook1;
void *hook2;
struct dbquery *next;
char channel[80];
char info[80];
char passwd[80];
} dbquery;
typedef struct dbsync {
int fd;
off_t offset;
time_t time;
int type; /* update, delete, add */
int status; /* pending_write, seeking_empty_slot */
RegUser **reg;
struct buffer_block *buf;
struct dbsync *next;
} dbsync;
typedef struct syncchan {
char name[50];
struct syncchan *next;
} syncchan;

2139
Sources/userlist.c Normal file

File diff suppressed because it is too large Load Diff

521
Sources/users.c Normal file
View File

@@ -0,0 +1,521 @@
/* @(#)$Id: users.c,v 1.7 1998/11/21 14:58:43 seks Exp $ */
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
#include "h.h"
int lu_hash(char *nick)
{
register int i, j;
for (i = 0, j = 0; i < strlen(nick); i++)
j += toupper((unsigned char)nick[i]);
return (j % 1000);
}
int su_hash(char *nick)
{
register int i, j;
for (i = 0, j = 0; i < strlen(nick); i++)
j += toupper((unsigned char)nick[i]);
return (j % 100);
}
aluser *ToLuser(char *nick)
{
register aluser *curr;
curr = Lusers[lu_hash(nick)];
while (curr && strcasecmp(nick, curr->nick))
curr = curr->next;
return (curr);
}
void onnick(char *source, char *newnick, char *body)
{
register aluser *user, **u;
register asuser *suser, **s;
register aserver *serv;
char username[80];
char hostname[80];
char TS[80];
char server[80];
register achannelnode *chan;
register anickchange *curr, *prec;
char buffer[512];
int i = 0;
#ifdef DEBUG
printf("NICK: %s --> %s ...\n", source, newnick);
#endif
/* a new user */
if (!ToLuser(source))
{ /* Not a user, so a server or nothing */
if (strchr(source, '.') == NULL)
{
/* Source is not a user and not a server either */
return;
}
if (!strcasecmp(newnick, mynick))
{
log("ERROR: I'm nick collided");
#ifdef DEBUG
printf("ARGH!!! I'M NICK COLLIDED!\n");
#endif
GetWord(1, body, TS);
GetWord(2, body, username);
GetWord(3, body, hostname);
if (atol(TS) <= logTS &&
strcasecmp(username, myuser) &&
strcasecmp(hostname, mysite))
{
NickInUse();
log(source);
log(newnick);
log(body);
}
else
{
onquit(source);
return; /*ignore */
}
#ifdef BACKUP
}
else if (!strcasecmp(newnick, MAIN_NICK))
{
return; /* ignore */
#endif
}
else if (ToLuser(newnick))
{
#ifdef DEBUG
printf("ARGH!!! NICK COLLISION\n");
#endif
onquit(newnick);
}
GetWord(1, body, TS);
GetWord(2, body, username);
GetWord(3, body, hostname);
GetWord(4, body, server);
#ifdef FAKE_UWORLD
if (Uworld_status == 1 && !strcasecmp(newnick, UFAKE_NICK))
{
if (atol(TS) <= UworldTS && atol(TS) != 0 &&
strcasecmp(username, UFAKE_NICK) &&
strcasecmp(hostname, UFAKE_HOST))
{
sprintf(buffer, "%s nick collided", UFAKE_NICK);
log(buffer);
Uworld_status = 0;
KillUworld("nick collision");
return; /* ignore if younger */
}
}
#endif
user = (aluser *) MALLOC(sizeof(aluser));
user->nick = (char *)MALLOC(strlen(newnick) + 1);
strcpy(user->nick, newnick);
user->username = (char *)MALLOC(strlen(username) + 1);
strcpy(user->username, username);
user->site = (char *)MALLOC(strlen(hostname) + 1);
strcpy(user->site, hostname);
if (*newnick == '+')
serv = &VirtualServer;
else
serv = ToServer(server);
user->server = serv;
user->time = atol(TS);
user->mode = 0;
user->channel = NULL;
user->valchan = NULL;
user->next = Lusers[lu_hash(newnick)];
Lusers[lu_hash(newnick)] = user;
/* add user in server's userlist
*/
suser = (asuser *) MALLOC(sizeof(asuser));
suser->N = user;
suser->next = serv->users[su_hash(newnick)];
serv->users[su_hash(newnick)] = suser;
#ifdef NICKSERV
nserv_nick(newnick, user);
#endif
}
else
{ /* nick change */
#if 0
if (!strcasecmp(source, DEFAULT_NICKNAME) &&
strcasecmp(newnick, DEFAULT_NICKNAME))
{
ChNick(DEFAULT_NICKNAME);
}
#endif
if (!strcasecmp(newnick, mynick))
{
#ifdef DEBUG
printf("ARGH!!! I'M NICK COLLIDED!\n");
#endif
GetWord(0, body, TS);
if (atol(TS + 1) <= logTS)
{
NickInUse();
log(source);
log(newnick);
log(body);
}
else
{
onquit(source);
return; /*ignore */
}
}
u = &Lusers[lu_hash(source)];
while (*u && strcasecmp(source, (*u)->nick))
u = &(*u)->next;
user = *u;
#ifdef NICKSERV
nserv_nick(newnick, user);
#endif
if (user == NULL)
quit("ERROR! onnick() can't find user", 1);
s = &user->server->users[su_hash(source)];
while (*s && strcasecmp((*s)->N->nick, user->nick))
s = &(*s)->next;
suser = *s;
/* change the nick in memory */
TTLALLOCMEM -= strlen(user->nick) + 1;
free(user->nick);
user->nick = (char *)MALLOC(strlen(newnick) + 1);
strcpy(user->nick, newnick);
/* now relocate the structure */
*u = user->next;
user->next = Lusers[lu_hash(newnick)];
Lusers[lu_hash(newnick)] = user;
*s = suser->next;
suser->next = user->server->users[su_hash(newnick)];
user->server->users[su_hash(newnick)] = suser;
/* NICK FLOOD PROTECTION */
/* 1st wipe old nick changes off */
chan = user->channel;
while (chan)
{
curr = chan->nickhist;
prec = NULL;
/* if not on channel.. ignore nick flood pro */
if (!chan->N->on)
{
chan = chan->next;
continue; /* yurk.. as bad as a goto ;) */
}
while (curr)
{
if (curr->time < (now - 15))
{
if (prec)
{
prec->next = curr->next;
TTLALLOCMEM -= sizeof(anickchange);
free(curr);
curr = prec->next;
}
else
{
chan->nickhist = curr->next;
TTLALLOCMEM -= sizeof(anickchange);
free(curr);
curr = chan->nickhist;
}
}
else
{
prec = curr;
curr = curr->next;
}
}
/* now add the new nick change to the history */
curr = (anickchange *) MALLOC(sizeof(anickchange));
strcpy(curr->nick, source);
curr->time = now; /* a lil confusing :( */
curr->next = chan->nickhist;
chan->nickhist = curr;
/* now count the nick changes in history
if there are more than allowed.. grrrr */
for (i = 0, curr = chan->nickhist; curr;
curr = curr->next, i++);
if (i == chan->N->NickFloodPro && chan->N->NickFloodPro != 0
&& chan->N->on)
{
sprintf(buffer, "%s!%s@%s", user->nick, user->username, user->site);
notice(newnick,
"### NICK FLOOD PROTECTION ACTIVATED ###");
sprintf(buffer, "%s %d", newnick,
NICK_FLOOD_SUSPEND_TIME);
suspend("", chan->N->name, buffer);
ban("", chan->N->name, newnick);
}
chan = chan->next;
}
}
}
void onquit(char *nick)
{
register aluser *user, **u;
register asuser *suser, **s;
register avalchan *valchan;
#ifdef DEBUG
printf("Detected user quit..\n");
#endif
u = &Lusers[lu_hash(nick)];
while (*u && strcasecmp(nick, (*u)->nick))
u = &(*u)->next;
user = *u;
if (user == NULL)
{
log("ERROR: onquit() can't find user!");
#ifdef HISTORY
History(NULL);
#endif
return;
}
/* remove from memory */
while ((valchan = user->valchan) != NULL)
{
#ifdef DEBUG
printf("\twas validated on %s\n", valchan->name);
#endif
valchan->reg->inuse--;
user->valchan = valchan->next;
TTLALLOCMEM -= strlen(valchan->name) + 1;
free(valchan->name);
TTLALLOCMEM -= sizeof(avalchan);
free(valchan);
}
while (user->channel != NULL)
{
#ifdef DEBUG
printf("\twas on %s\n", user->channel->N->name);
#endif
/* onpart() free's the chan structure
* we can't do chan=chan->next after the
* onpart() call. We must start from the
* beginning of the list every time
*/
onpart(nick, user->channel->N->name);
}
/* remove user from server's userlist
*/
s = &user->server->users[su_hash(user->nick)];
while (*s != NULL && strcasecmp((*s)->N->nick, user->nick))
{
s = &(*s)->next;
}
if (*s != NULL)
{
suser = *s;
*s = (*s)->next;
TTLALLOCMEM -= sizeof(asuser);
free(suser);
}
else
{
log("ERROR: onquit() user not found in server's userlist!");
}
*u = user->next;
#if 0
if (!strcasecmp(user->nick, DEFAULT_NICKNAME))
{
ChNick(DEFAULT_NICKNAME);
}
#endif
#ifdef NICKSERV
nserv_quit(user);
#endif
TTLALLOCMEM -= strlen(user->nick) + 1;
free(user->nick);
TTLALLOCMEM -= strlen(user->username) + 1;
free(user->username);
TTLALLOCMEM -= strlen(user->site) + 1;
free(user->site);
TTLALLOCMEM -= sizeof(aluser);
free(user);
}
void onkill(char *source, char *target, char *comment)
{
char buffer[200];
if (!strcasecmp(target, mynick))
{
#if 0
/* ignore kill for nick collisions because we
* already check in onnick() if we're collided.
* This kill is prolly a lost kill resulting of
* another nick collision..
*/
if (strstr(comment, "older nick overruled") ||
strstr(comment, "collided yourself"))
{
log("ERROR: Nick collision on me?");
return;
}
#endif
sprintf(buffer, ":%s SQUIT %s 0 :killed by %s\n",
SERVERNAME, SERVERNAME, source);
sendtoserv(buffer);
dumpbuff();
close(Irc.fd);
Irc.fd = -1;
if (reconnect(server))
{
try_later(server);
}
#ifdef BACKUP
}
else if (!strcasecmp(target, MAIN_NICK))
{
quit(MAIN_NICK " is back", 0);
#endif
#ifdef FAKE_UWORLD
}
else if (!strcasecmp(target, UFAKE_NICK))
{
char buffer[200];
sprintf(buffer, "%s is KILLED by %s", UFAKE_NICK, source);
log(buffer);
Uworld_status = 0;
KillUworld("Killed");
#endif
}
else
onquit(target);
}
void onwhois(char *source, char *nick)
{
register aluser *user;
register auser *usr;
register achannelnode *chan;
char buffer[512];
user = ToLuser(nick);
if (user == NULL)
{
sprintf(buffer, ":%s 401 %s %s :No such nick\n", SERVERNAME, source, nick);
sendtoserv(buffer);
}
else
{
sprintf(buffer, ":%s 311 %s %s %s %s * :\n", SERVERNAME, source, user->nick,
user->username, user->site);
sendtoserv(buffer);
chan = user->channel;
if (chan != NULL && strcmp(user->nick, "X") && strcmp(user->nick, "W"))
{
sprintf(buffer, ":%s 319 %s %s :", SERVERNAME, source, nick);
while (chan != NULL)
{
/* show a channel only if it is
* not +s or +p
*/
if (!IsSet(chan->N->name, 's', "") &&
!IsSet(chan->N->name, 'p', ""))
{
usr = ToUser(chan->N->name, nick);
if (usr->chanop)
strcat(buffer, "@");
strcat(buffer, chan->N->name);
strcat(buffer, " ");
}
chan = chan->next;
if (strlen(buffer) > 300)
{
strcat(buffer, "\n");
sendtoserv(buffer);
sprintf(buffer, ":%s 319 %s %s :",
SERVERNAME, source, nick);
}
}
strcat(buffer, "\n");
sendtoserv(buffer);
}
sprintf(buffer, ":%s 312 %s %s %s :\n", SERVERNAME, source, source, user->server->name);
sendtoserv(buffer);
if (user->mode & LFL_ISOPER)
{
sprintf(buffer, ":%s 313 %s %s :is an IRC Operator\n",
SERVERNAME, source, user->nick);
sendtoserv(buffer);
}
}
sprintf(buffer, ":%s 318 %s :End of /WHOIS list.\n", SERVERNAME, source);
sendtoserv(buffer);
}

38
Sources/version.SH Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/sh
TAG="v20020715 build-`date -u '+%Y%m%d%H%M%S'`"
echo Updating version... $TAG
cat << NUFF > version.c
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
/* This file is generated by version.SH and any change will be
* overwritten when you recompile.
*/
char VERSION[]="Undernet Channel Service $TAG ";
NUFF

30
Sources/version.c Normal file
View File

@@ -0,0 +1,30 @@
/* Undernet Channel Service (X)
* Copyright (C) 1995-2002 Robin Thellend
*
* This program 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 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contact by email at <csfeedback@robin.pfft.net>
*
* Please note that this software is unsupported and mostly
* obsolete. It was replaced by GNUworld/CMaster. See
* http://gnuworld.sourceforge.net/ for more information.
*/
/* This file is generated by version.SH and any change will be
* overwritten when you recompile.
*/
char VERSION[]="Undernet Channel Service v20020715151606 ";

4
Sources/version.h Normal file
View File

@@ -0,0 +1,4 @@
/* @(#)$Id: version.h,v 1.3 1996/11/13 00:40:51 seks Exp $ */
extern char VERSION[];