init
This commit is contained in:
63
common/Makefile
Normal file
63
common/Makefile
Normal file
@@ -0,0 +1,63 @@
|
||||
#************************************************************************
|
||||
#* IRC - Internet Relay Chat, common/Makefile
|
||||
#* Copyright (C) 1990 Jarkko Oikarinen
|
||||
#*
|
||||
#* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#*/
|
||||
|
||||
CC=cc
|
||||
RM=/bin/rm
|
||||
INCLUDE=../include
|
||||
|
||||
# For MIPS, use:
|
||||
# CFLAGS=-O -systype bsd43 -I${INCLUDE}
|
||||
# and otherwise:
|
||||
CFLAGS=-O -I${INCLUDE}
|
||||
|
||||
|
||||
OBJS=bsd.o dbuf.o packet.o send.o match.o parse.o support.o
|
||||
|
||||
SRC=bsd.c dbuf.c packet.c parse.c send.c match.c support.c
|
||||
|
||||
tm: tm.o match.o tab.o
|
||||
$(CC) -g tab.o tm.o match.o -o tm
|
||||
|
||||
all: build
|
||||
|
||||
build: $(OBJS)
|
||||
|
||||
install:
|
||||
|
||||
clean:
|
||||
$(RM) -f *.o *~ core \#* *.bak *.orig
|
||||
|
||||
depend:
|
||||
makedepend -I${INCLUDE} ${SRC}
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
bsd.o: bsd.c ../include/common.h ../include/sys.h ../include/config.h
|
||||
dbuf.o: ../include/config.h ../include/common.h ../include/dbuf.h
|
||||
dbuf.o: ../include/sys.h dbuf.c
|
||||
packet.o: ../include/struct.h ../include/config.h ../include/class.h
|
||||
packet.o: ../include/dbuf.h ../include/common.h ../include/msg.h packet.c
|
||||
parse.o: ../include/struct.h ../include/config.h
|
||||
parse.o: ../include/class.h ../include/dbuf.h ../include/common.h
|
||||
parse.o: ../include/msg.h ../include/sys.h
|
||||
parse.o: ../include/numeric.h parse.c
|
||||
send.o: ../include/struct.h ../include/config.h ../include/class.h
|
||||
send.o: ../include/dbuf.h ../include/common.h send.c
|
||||
match.o: ../include/config.h ../include/common.h ../include/sys.h match.c
|
||||
support.o: ../include/config.h ../include/common.h ../include/sys.h support.c
|
||||
186
common/bsd.c
Normal file
186
common/bsd.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, common/bsd.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Computing Center
|
||||
*
|
||||
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)bsd.c 2.14 1/30/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "h.h"
|
||||
#include <signal.h>
|
||||
|
||||
extern int errno; /* ...seems that errno.h doesn't define this everywhere */
|
||||
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__bsdi__)
|
||||
extern char *sys_errlist[];
|
||||
#endif
|
||||
|
||||
extern char *last_dead_comment;
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
int writecalls = 0, writeb[10] = {0,0,0,0,0,0,0,0,0,0};
|
||||
#endif
|
||||
VOIDSIG dummy()
|
||||
{
|
||||
#ifndef HAVE_RELIABLE_SIGNALS
|
||||
(void)signal(SIGALRM, dummy);
|
||||
(void)signal(SIGPIPE, dummy);
|
||||
#ifndef HPUX /* Only 9k/800 series require this, but don't know how to.. */
|
||||
# ifdef SIGWINCH
|
||||
(void)signal(SIGWINCH, dummy);
|
||||
# endif
|
||||
#endif
|
||||
#else
|
||||
# ifdef POSIX_SIGNALS
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = dummy;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGALRM);
|
||||
(void)sigaddset(&act.sa_mask, SIGPIPE);
|
||||
# ifdef SIGWINCH
|
||||
(void)sigaddset(&act.sa_mask, SIGWINCH);
|
||||
# endif
|
||||
(void)sigaction(SIGALRM, &act, (struct sigaction *)NULL);
|
||||
(void)sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
|
||||
# ifdef SIGWINCH
|
||||
(void)sigaction(SIGWINCH, &act, (struct sigaction *)NULL);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** deliver_it
|
||||
** Attempt to send a sequence of bytes to the connection.
|
||||
** Returns
|
||||
**
|
||||
** < 0 Some fatal error occurred, (but not EWOULDBLOCK).
|
||||
** This return is a request to close the socket and
|
||||
** clean up the link.
|
||||
**
|
||||
** >= 0 No real error occurred, returns the number of
|
||||
** bytes actually transferred. EWOULDBLOCK and other
|
||||
** possibly similar conditions should be mapped to
|
||||
** zero return. Upper level routine will have to
|
||||
** decide what to do with those unwritten bytes...
|
||||
**
|
||||
** *NOTE* alarm calls have been preserved, so this should
|
||||
** work equally well whether blocking or non-blocking
|
||||
** mode is used...
|
||||
**
|
||||
** We don't use blocking anymore, that is impossible with the
|
||||
** net.loads today anyway. Commented out the alarms to save cpu.
|
||||
** --Run
|
||||
*/
|
||||
int deliver_it(cptr, str, len)
|
||||
aClient *cptr;
|
||||
int len;
|
||||
char *str;
|
||||
{
|
||||
int retval;
|
||||
aClient *acpt = cptr->acpt;
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
writecalls++;
|
||||
#endif
|
||||
/* (void)alarm(WRITEWAITDELAY); Bullshit */
|
||||
#ifdef VMS
|
||||
retval = netwrite(cptr->fd, str, len);
|
||||
#else
|
||||
retval = send(cptr->fd, str, len, 0);
|
||||
/*
|
||||
** Convert WOULDBLOCK to a return of "0 bytes moved". This
|
||||
** should occur only if socket was non-blocking. Note, that
|
||||
** all is Ok, if the 'write' just returns '0' instead of an
|
||||
** error and errno=EWOULDBLOCK.
|
||||
**
|
||||
** ...now, would this work on VMS too? --msa
|
||||
*/
|
||||
if (retval < 0 && (errno == EWOULDBLOCK || errno == EAGAIN ||
|
||||
errno == ENOBUFS))
|
||||
{
|
||||
retval = 0;
|
||||
cptr->flags |= FLAGS_BLOCKED;
|
||||
}
|
||||
else if (retval > 0)
|
||||
{
|
||||
#ifdef pyr
|
||||
(void)gettimeofday(&cptr->lw, NULL);
|
||||
#endif
|
||||
cptr->flags &= ~FLAGS_BLOCKED;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* (void )alarm(0); */
|
||||
#ifdef DEBUGMODE
|
||||
if (retval < 0) {
|
||||
writeb[0]++;
|
||||
Debug((DEBUG_ERROR,"write error (%s) to %s",
|
||||
sys_errlist[errno], cptr->name));
|
||||
} else if (retval == 0)
|
||||
writeb[1]++;
|
||||
else if (retval < 16)
|
||||
writeb[2]++;
|
||||
else if (retval < 32)
|
||||
writeb[3]++;
|
||||
else if (retval < 64)
|
||||
writeb[4]++;
|
||||
else if (retval < 128)
|
||||
writeb[5]++;
|
||||
else if (retval < 256)
|
||||
writeb[6]++;
|
||||
else if (retval < 512)
|
||||
writeb[7]++;
|
||||
else if (retval < 1024)
|
||||
writeb[8]++;
|
||||
else
|
||||
writeb[9]++;
|
||||
#endif
|
||||
if (retval > 0)
|
||||
{
|
||||
cptr->sendB += retval;
|
||||
me.sendB += retval;
|
||||
if (cptr->sendB > 1023)
|
||||
{
|
||||
cptr->sendK += (cptr->sendB >> 10);
|
||||
cptr->sendB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */
|
||||
}
|
||||
if (acpt != &me)
|
||||
{
|
||||
acpt->sendB += retval;
|
||||
if (acpt->sendB > 1023)
|
||||
{
|
||||
acpt->sendK += (acpt->sendB >> 10);
|
||||
acpt->sendB &= 0x03ff;
|
||||
}
|
||||
}
|
||||
else if (me.sendB > 1023)
|
||||
{
|
||||
me.sendK += (me.sendB >> 10);
|
||||
me.sendB &= 0x03ff;
|
||||
}
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
345
common/dbuf.c
Normal file
345
common/dbuf.c
Normal file
@@ -0,0 +1,345 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, common/dbuf.c
|
||||
* Copyright (C) 1990 Markku Savela
|
||||
*
|
||||
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* -- Jto -- 20 Jun 1990
|
||||
* extern void free() fixed as suggested by
|
||||
* gruner@informatik.tu-muenchen.de
|
||||
*/
|
||||
|
||||
/* -- Jto -- 10 May 1990
|
||||
* Changed memcpy into bcopy and removed the declaration of memset
|
||||
* because it was unnecessary.
|
||||
* Added the #includes for "struct.h" and "sys.h" to get bcopy/memcpy
|
||||
* work
|
||||
*/
|
||||
|
||||
/*
|
||||
** For documentation of the *global* functions implemented here,
|
||||
** see the header file (dbuf.h).
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)dbuf.c 2.17 1/30/94 (C) 1990 Markku Savela";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
|
||||
#if !defined(VALLOC) && !defined(valloc)
|
||||
#define valloc malloc
|
||||
#endif
|
||||
|
||||
int dbufalloc = 0, dbufblocks = 0;
|
||||
static dbufbuf *freelist = NULL;
|
||||
|
||||
/* This is a dangerous define because a broken compiler will set DBUFSIZ
|
||||
** to 4, which will work but will be very inefficient. However, there
|
||||
** are other places where the code breaks badly if this is screwed
|
||||
** up, so... -- Wumpus
|
||||
*/
|
||||
|
||||
#define DBUFSIZ sizeof(((dbufbuf *)0)->data)
|
||||
|
||||
/*
|
||||
** dbuf_alloc - allocates a dbufbuf structure either from freelist or
|
||||
** creates a new one.
|
||||
*/
|
||||
static dbufbuf *dbuf_alloc()
|
||||
{
|
||||
#if defined(VALLOC) && !defined(DEBUGMODE)
|
||||
Reg1 dbufbuf *dbptr, *db2ptr;
|
||||
Reg2 int num;
|
||||
#else
|
||||
Reg1 dbufbuf *dbptr;
|
||||
#endif
|
||||
|
||||
dbufalloc++;
|
||||
if ((dbptr = freelist))
|
||||
{
|
||||
freelist = freelist->next;
|
||||
return dbptr;
|
||||
}
|
||||
if (dbufalloc * DBUFSIZ > BUFFERPOOL)
|
||||
{
|
||||
dbufalloc--;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(VALLOC) && !defined(DEBUGMODE)
|
||||
# if defined(SOL20) || defined(_SC_PAGESIZE)
|
||||
num = sysconf(_SC_PAGESIZE)/sizeof(dbufbuf);
|
||||
# else
|
||||
num = getpagesize()/sizeof(dbufbuf);
|
||||
# endif
|
||||
if (num < 0)
|
||||
num = 1;
|
||||
|
||||
dbufblocks += num;
|
||||
|
||||
dbptr = (dbufbuf *)valloc(num*sizeof(dbufbuf));
|
||||
if (!dbptr)
|
||||
return (dbufbuf *)NULL;
|
||||
|
||||
num--;
|
||||
for (db2ptr = dbptr; num; num--)
|
||||
{
|
||||
db2ptr = (dbufbuf *)((char *)db2ptr + sizeof(dbufbuf));
|
||||
db2ptr->next = freelist;
|
||||
freelist = db2ptr;
|
||||
}
|
||||
return dbptr;
|
||||
#else
|
||||
dbufblocks++;
|
||||
return (dbufbuf *)MyMalloc(sizeof(dbufbuf));
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
** dbuf_free - return a dbufbuf structure to the freelist
|
||||
*/
|
||||
static void dbuf_free(ptr)
|
||||
Reg1 dbufbuf *ptr;
|
||||
{
|
||||
dbufalloc--;
|
||||
ptr->next = freelist;
|
||||
freelist = ptr;
|
||||
}
|
||||
/*
|
||||
** This is called when malloc fails. Scrap the whole content
|
||||
** of dynamic buffer and return -1. (malloc errors are FATAL,
|
||||
** there is no reason to continue this buffer...). After this
|
||||
** the "dbuf" has consistent EMPTY status... ;)
|
||||
*/
|
||||
static int dbuf_malloc_error(dyn)
|
||||
dbuf *dyn;
|
||||
{
|
||||
dbufbuf *p;
|
||||
|
||||
dyn->length = 0;
|
||||
dyn->offset = 0;
|
||||
while ((p = dyn->head) != NULL)
|
||||
{
|
||||
dyn->head = p->next;
|
||||
dbuf_free(p);
|
||||
}
|
||||
dyn->tail = dyn->head;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int dbuf_put(dyn, buf, length)
|
||||
dbuf *dyn;
|
||||
char *buf;
|
||||
int length;
|
||||
{
|
||||
Reg1 dbufbuf **h, *d;
|
||||
Reg2 int off;
|
||||
Reg3 int chunk;
|
||||
|
||||
off = (dyn->offset + dyn->length) % DBUFSIZ;
|
||||
/*
|
||||
** Locate the last non-empty buffer. If the last buffer is
|
||||
** full, the loop will terminate with 'd==NULL'. This loop
|
||||
** assumes that the 'dyn->length' field is correctly
|
||||
** maintained, as it should--no other check really needed.
|
||||
*/
|
||||
if (!dyn->length) h = &(dyn->head);
|
||||
else {
|
||||
if (off) h = &(dyn->tail);
|
||||
else h = &(dyn->tail->next);
|
||||
}
|
||||
/*
|
||||
** Append users data to buffer, allocating buffers as needed
|
||||
*/
|
||||
chunk = DBUFSIZ - off;
|
||||
dyn->length += length;
|
||||
for ( ;length > 0; h = &(d->next))
|
||||
{
|
||||
if ((d = *h) == NULL)
|
||||
{
|
||||
if ((d = (dbufbuf *)dbuf_alloc()) == NULL)
|
||||
return dbuf_malloc_error(dyn);
|
||||
dyn->tail = d;
|
||||
*h = d;
|
||||
d->next = NULL;
|
||||
}
|
||||
if (chunk > length)
|
||||
chunk = length;
|
||||
bcopy(buf, d->data + off, chunk);
|
||||
length -= chunk;
|
||||
buf += chunk;
|
||||
off = 0;
|
||||
chunk = DBUFSIZ;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char *dbuf_map(dyn,length)
|
||||
dbuf *dyn;
|
||||
int *length;
|
||||
{
|
||||
if (dyn->head == NULL)
|
||||
{
|
||||
dyn->tail = NULL;
|
||||
*length = 0;
|
||||
return NULL;
|
||||
}
|
||||
*length = DBUFSIZ - dyn->offset;
|
||||
if (*length > dyn->length)
|
||||
*length = dyn->length;
|
||||
return (dyn->head->data + dyn->offset);
|
||||
}
|
||||
|
||||
int dbuf_delete(dyn,length)
|
||||
dbuf *dyn;
|
||||
int length;
|
||||
{
|
||||
dbufbuf *d;
|
||||
int chunk;
|
||||
|
||||
if (length > dyn->length)
|
||||
length = dyn->length;
|
||||
chunk = DBUFSIZ - dyn->offset;
|
||||
while (length > 0)
|
||||
{
|
||||
if (chunk > length)
|
||||
chunk = length;
|
||||
length -= chunk;
|
||||
dyn->offset += chunk;
|
||||
dyn->length -= chunk;
|
||||
if (dyn->offset == DBUFSIZ || dyn->length == 0)
|
||||
{
|
||||
d = dyn->head;
|
||||
dyn->head = d->next;
|
||||
dyn->offset = 0;
|
||||
dbuf_free(d);
|
||||
}
|
||||
chunk = DBUFSIZ;
|
||||
}
|
||||
if (dyn->head == (dbufbuf *)NULL) {
|
||||
dyn->length = 0;
|
||||
dyn->tail = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dbuf_get(dyn, buf, length)
|
||||
dbuf *dyn;
|
||||
char *buf;
|
||||
int length;
|
||||
{
|
||||
int moved = 0;
|
||||
int chunk;
|
||||
char *b;
|
||||
|
||||
while (length > 0 && (b = dbuf_map(dyn, &chunk)) != NULL)
|
||||
{
|
||||
if (chunk > length)
|
||||
chunk = length;
|
||||
bcopy(b, buf, (int)chunk);
|
||||
(void)dbuf_delete(dyn, chunk);
|
||||
buf += chunk;
|
||||
length -= chunk;
|
||||
moved += chunk;
|
||||
}
|
||||
return moved;
|
||||
}
|
||||
|
||||
/*
|
||||
** dbuf_getmsg
|
||||
**
|
||||
** Check the buffers to see if there is a string which is terminted with
|
||||
** either a \r or \n prsent. If so, copy as much as possible (determined by
|
||||
** length) into buf and return the amount copied - else return 0.
|
||||
*/
|
||||
int dbuf_getmsg(dyn, buf, length)
|
||||
dbuf *dyn;
|
||||
char *buf;
|
||||
register int length;
|
||||
{
|
||||
dbufbuf *d;
|
||||
register char *s;
|
||||
register int dlen;
|
||||
register int i;
|
||||
int copy;
|
||||
|
||||
getmsg_init:
|
||||
d = dyn->head;
|
||||
dlen = dyn->length;
|
||||
i = DBUFSIZ - dyn->offset;
|
||||
if (i <= 0)
|
||||
return -1;
|
||||
copy = 0;
|
||||
if (d && dlen)
|
||||
s = dyn->offset + d->data;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (i > dlen)
|
||||
i = dlen;
|
||||
while (length > 0 && dlen > 0)
|
||||
{
|
||||
dlen--;
|
||||
if (*s == '\n' || *s == '\r')
|
||||
{
|
||||
copy = dyn->length - dlen;
|
||||
/*
|
||||
** Shortcut this case here to save time elsewhere.
|
||||
** -avalon
|
||||
*/
|
||||
if (copy == 1)
|
||||
{
|
||||
(void)dbuf_delete(dyn, 1);
|
||||
goto getmsg_init;
|
||||
}
|
||||
break;
|
||||
}
|
||||
length--;
|
||||
if (!--i)
|
||||
{
|
||||
if ((d = d->next))
|
||||
{
|
||||
s = d->data;
|
||||
i = MIN(DBUFSIZ, dlen);
|
||||
}
|
||||
}
|
||||
else
|
||||
s++;
|
||||
}
|
||||
|
||||
if (copy <= 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
** copy as much of the message as wanted into parse buffer
|
||||
*/
|
||||
i = dbuf_get(dyn, buf, MIN(copy, length));
|
||||
/*
|
||||
** and delete the rest of it!
|
||||
*/
|
||||
if (copy - i > 0)
|
||||
(void)dbuf_delete(dyn, copy - i);
|
||||
if (i >= 0)
|
||||
*(buf+i) = '\0'; /* mark end of messsage */
|
||||
|
||||
return i;
|
||||
}
|
||||
327
common/match.c
Normal file
327
common/match.c
Normal file
@@ -0,0 +1,327 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, common/match.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen
|
||||
*
|
||||
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "%W% %G% (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
static int calls = 0;
|
||||
#define MAX_CALLS 200
|
||||
/*
|
||||
** Compare if a given string (name) matches the given
|
||||
** mask (which can contain wild cards: '*' - match any
|
||||
** number of chars, '?' - match any single character.
|
||||
**
|
||||
** return 0, if match
|
||||
** 1, if no match
|
||||
*/
|
||||
|
||||
/*
|
||||
** _match()
|
||||
** Iterative matching function, rather than recursive.
|
||||
** Written by Douglas A Lewis (dalewis@acsu.buffalo.edu)
|
||||
*/
|
||||
|
||||
static int _match(mask, name)
|
||||
char *mask, *name;
|
||||
{
|
||||
Reg1 u_char *m = (u_char *)mask, *n = (u_char *)name;
|
||||
char *ma = mask, *na = name;
|
||||
int wild = 0, q = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (calls++ > MAX_CALLS)
|
||||
return 1;
|
||||
if (*m == '*')
|
||||
{
|
||||
while (*m == '*')
|
||||
m++;
|
||||
wild = 1;
|
||||
ma = (char *)m;
|
||||
na = (char *)n;
|
||||
}
|
||||
|
||||
if (!*m)
|
||||
{
|
||||
if (!*n)
|
||||
return 0;
|
||||
for (m--; (m > (u_char *)mask) && (*m == '?'); m--)
|
||||
;
|
||||
if ((*m == '*') && (m > (u_char *)mask) &&
|
||||
(m[-1] != '\\'))
|
||||
return 0;
|
||||
if (!wild)
|
||||
return 1;
|
||||
m = (u_char *)ma;
|
||||
n = (u_char *)++na;
|
||||
}
|
||||
else if (!*n)
|
||||
{
|
||||
while(*m == '*')
|
||||
m++;
|
||||
return (*m != 0);
|
||||
}
|
||||
if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
|
||||
{
|
||||
m++;
|
||||
q = 1;
|
||||
}
|
||||
else
|
||||
q = 0;
|
||||
|
||||
if ((tolower(*m) != tolower(*n)) && ((*m != '?') || q))
|
||||
{
|
||||
if (!wild)
|
||||
return 1;
|
||||
m = (u_char *)ma;
|
||||
n = (u_char *)++na;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*m)
|
||||
m++;
|
||||
if (*n)
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* External interfaces to the above matching routine.
|
||||
*/
|
||||
int match(ma, na)
|
||||
char *ma, *na;
|
||||
{
|
||||
calls = 0;
|
||||
return _match(ma, na);
|
||||
}
|
||||
|
||||
int matches(ma, na)
|
||||
char *ma,*na;
|
||||
{
|
||||
int r;
|
||||
|
||||
calls = 0;
|
||||
return _match(ma, na);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** collapse a pattern string into minimal components.
|
||||
** This particular version is "in place", so that it changes the pattern
|
||||
** which is to be reduced to a "minimal" size.
|
||||
*/
|
||||
char *collapse(pattern)
|
||||
char *pattern;
|
||||
{
|
||||
Reg1 char *s = pattern, *s1, *t;
|
||||
|
||||
if (BadPtr(pattern))
|
||||
return pattern;
|
||||
/*
|
||||
* Collapse all \** into \*, \*[?]+\** into \*[?]+
|
||||
*/
|
||||
for (; *s; s++)
|
||||
if (*s == '\\')
|
||||
if (!*(s + 1))
|
||||
break;
|
||||
else
|
||||
s++;
|
||||
else if (*s == '*')
|
||||
{
|
||||
if (*(t = s1 = s + 1) == '*')
|
||||
while (*t == '*')
|
||||
t++;
|
||||
else if (*t == '?')
|
||||
for (t++, s1++; *t == '*' || *t == '?'; t++)
|
||||
if (*t == '?')
|
||||
*s1++ = *t;
|
||||
while ((*s1++ = *t++))
|
||||
;
|
||||
}
|
||||
return pattern;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Case insensitive comparison of two NULL terminated strings.
|
||||
**
|
||||
** returns 0, if s1 equal to s2
|
||||
** <0, if s1 lexicographically less than s2
|
||||
** >0, if s1 lexicographically greater than s2
|
||||
*/
|
||||
int mycmp(s1, s2)
|
||||
const char *s1;
|
||||
const char *s2;
|
||||
{
|
||||
Reg1 const unsigned char *str1 = (const unsigned char *)s1;
|
||||
Reg2 const unsigned char *str2 = (const unsigned char *)s2;
|
||||
Reg3 int res;
|
||||
|
||||
while ((res = toupper(*str1) - toupper(*str2)) == 0)
|
||||
{
|
||||
if (*str1 == '\0')
|
||||
return 0;
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
||||
int myncmp(str1, str2, n)
|
||||
const char *str1;
|
||||
const char *str2;
|
||||
int n;
|
||||
{
|
||||
Reg1 const unsigned char *s1 = (const unsigned char *)str1;
|
||||
Reg2 const unsigned char *s2 = (const unsigned char *)str2;
|
||||
Reg3 int res;
|
||||
|
||||
while ((res = toupper(*s1) - toupper(*s2)) == 0)
|
||||
{
|
||||
s1++; s2++; n--;
|
||||
if (n == 0 || (*s1 == '\0' && *s2 == '\0'))
|
||||
return 0;
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
||||
unsigned char tolowertab[] =
|
||||
{ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
|
||||
0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
|
||||
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
|
||||
0x1e, 0x1f,
|
||||
' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
|
||||
'*', '+', ',', '-', '.', '/',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
':', ';', '<', '=', '>', '?',
|
||||
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
||||
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
|
||||
't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
|
||||
'_',
|
||||
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
||||
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
|
||||
't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
|
||||
0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
|
||||
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
|
||||
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
|
||||
0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
|
||||
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
|
||||
0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
|
||||
0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
|
||||
0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
|
||||
0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
|
||||
|
||||
unsigned char touppertab[] =
|
||||
{ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
|
||||
0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
|
||||
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
|
||||
0x1e, 0x1f,
|
||||
' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
|
||||
'*', '+', ',', '-', '.', '/',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
':', ';', '<', '=', '>', '?',
|
||||
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
|
||||
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
|
||||
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
|
||||
0x5f,
|
||||
'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
|
||||
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
|
||||
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
|
||||
0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
|
||||
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
|
||||
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
|
||||
0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
|
||||
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
|
||||
0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
|
||||
0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
|
||||
0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
|
||||
0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
|
||||
|
||||
unsigned char char_atribs[] = {
|
||||
/* 0-7 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
|
||||
/* 8-12 */ CNTRL, CNTRL|SPACE, CNTRL|SPACE, CNTRL|SPACE, CNTRL|SPACE,
|
||||
/* 13-15 */ CNTRL|SPACE, CNTRL, CNTRL,
|
||||
/* 16-23 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
|
||||
/* 24-31 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
|
||||
/* space */ PRINT|SPACE,
|
||||
/* !"#$%&'( */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT,
|
||||
/* )*+,-./ */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT,
|
||||
/* 0123 */ PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT,
|
||||
/* 4567 */ PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT,
|
||||
/* 89:; */ PRINT|DIGIT, PRINT|DIGIT, PRINT, PRINT,
|
||||
/* <=>? */ PRINT, PRINT, PRINT, PRINT,
|
||||
/* @ */ PRINT,
|
||||
/* ABC */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* DEF */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* GHI */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* JKL */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* MNO */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* PQR */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* STU */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* VWX */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* YZ[ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* \]^ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* _` */ PRINT,PRINT,
|
||||
/* abc */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* def */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* ghi */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* jkl */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* mno */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* pqr */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* stu */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* vwx */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* yz{ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* |}~ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA,
|
||||
/* del */ 0,
|
||||
/* 80-8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 90-9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* a0-af */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* b0-bf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* c0-cf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* d0-df */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* e0-ef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* f0-ff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
115
common/packet.c
Normal file
115
common/packet.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, common/packet.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Computing Center
|
||||
*
|
||||
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)packet.c 2.12 1/30/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "msg.h"
|
||||
#include "h.h"
|
||||
|
||||
extern char *last_dead_comment;
|
||||
|
||||
/*
|
||||
** dopacket
|
||||
** cptr - pointer to client structure for which the buffer data
|
||||
** applies.
|
||||
** buffer - pointr to the buffer containing the newly read data
|
||||
** length - number of valid bytes of data in the buffer
|
||||
**
|
||||
** Note:
|
||||
** It is implicitly assumed that dopacket is called only
|
||||
** with cptr of "local" variation, which contains all the
|
||||
** necessary fields (buffer etc..)
|
||||
*/
|
||||
int dopacket(cptr, buffer, length)
|
||||
Reg3 aClient *cptr;
|
||||
char *buffer;
|
||||
Reg4 int length;
|
||||
{
|
||||
Reg1 char *ch1;
|
||||
Reg2 char *ch2;
|
||||
register char *cptrbuf;
|
||||
aClient *acpt = cptr->acpt;
|
||||
|
||||
cptrbuf = cptr->buffer;
|
||||
me.receiveB += length; /* Update bytes received */
|
||||
cptr->receiveB += length;
|
||||
if (cptr->receiveB > 1023)
|
||||
{
|
||||
cptr->receiveK += (cptr->receiveB >> 10);
|
||||
cptr->receiveB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */
|
||||
}
|
||||
if (acpt != &me)
|
||||
{
|
||||
acpt->receiveB += length;
|
||||
if (acpt->receiveB > 1023)
|
||||
{
|
||||
acpt->receiveK += (acpt->receiveB >> 10);
|
||||
acpt->receiveB &= 0x03ff;
|
||||
}
|
||||
}
|
||||
else if (me.receiveB > 1023)
|
||||
{
|
||||
me.receiveK += (me.receiveB >> 10);
|
||||
me.receiveB &= 0x03ff;
|
||||
}
|
||||
ch1 = cptrbuf + cptr->count;
|
||||
ch2 = buffer;
|
||||
while (--length >= 0)
|
||||
{
|
||||
register char g;
|
||||
g = (*ch1 = *ch2++);
|
||||
/*
|
||||
* Yuck. Stuck. To make sure we stay backward compatible,
|
||||
* we must assume that either CR or LF terminates the message
|
||||
* and not CR-LF. By allowing CR or LF (alone) into the body
|
||||
* of messages, backward compatibility is lost and major
|
||||
* problems will arise. - Avalon
|
||||
*/
|
||||
if ( g < '\16' && (g== '\n' || g == '\r'))
|
||||
{
|
||||
if (ch1 == cptrbuf)
|
||||
continue; /* Skip extra LF/CR's */
|
||||
*ch1 = '\0';
|
||||
me.receiveM += 1; /* Update messages received */
|
||||
cptr->receiveM += 1;
|
||||
if (cptr->acpt != &me)
|
||||
cptr->acpt->receiveM += 1;
|
||||
if (parse(cptr, cptr->buffer, ch1, msgtab) ==
|
||||
CPTR_KILLED)
|
||||
return CPTR_KILLED;
|
||||
/*
|
||||
** Socket is dead so exit
|
||||
*/
|
||||
if (IsDead(cptr))
|
||||
return exit_client(cptr, cptr, &me, last_dead_comment);
|
||||
ch1 = cptrbuf;
|
||||
}
|
||||
else if (ch1 < cptrbuf + (sizeof(cptr->buffer)-1))
|
||||
ch1++; /* There is always room for the null */
|
||||
}
|
||||
cptr->count = ch1 - cptr->buffer;
|
||||
return 0;
|
||||
}
|
||||
464
common/parse.c
Normal file
464
common/parse.c
Normal file
@@ -0,0 +1,464 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, common/parse.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Computing Center
|
||||
*
|
||||
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* -- Jto -- 03 Jun 1990
|
||||
* Changed the order of defines...
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)parse.c 2.33 1/30/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#define MSGTAB
|
||||
#include "msg.h"
|
||||
#undef MSGTAB
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "h.h"
|
||||
|
||||
/*
|
||||
* NOTE: parse() should not be called recursively by other functions!
|
||||
*/
|
||||
static char *para[MAXPARA+1];
|
||||
static char sender[HOSTLEN+1];
|
||||
|
||||
/*
|
||||
** Find a client (server or user) by name.
|
||||
**
|
||||
** *Note*
|
||||
** Semantics of this function has been changed from
|
||||
** the old. 'name' is now assumed to be a null terminated
|
||||
** string and the search is the for server and user.
|
||||
*/
|
||||
aClient *find_client(name, cptr)
|
||||
char *name;
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
if (name)
|
||||
cptr = hash_find_client(name, cptr);
|
||||
|
||||
return cptr;
|
||||
}
|
||||
|
||||
aClient *find_nickserv(name, cptr)
|
||||
char *name;
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
if (name)
|
||||
cptr = hash_find_nickserver(name, cptr);
|
||||
|
||||
return cptr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Find a user@host (server or user).
|
||||
**
|
||||
** *Note*
|
||||
** Semantics of this function has been changed from
|
||||
** the old. 'name' is now assumed to be a null terminated
|
||||
** string and the search is the for server and user.
|
||||
*/
|
||||
aClient *find_userhost(user, host, cptr, count)
|
||||
char *user, *host;
|
||||
aClient *cptr;
|
||||
int *count;
|
||||
{
|
||||
Reg1 aClient *c2ptr;
|
||||
Reg2 aClient *res = cptr;
|
||||
|
||||
*count = 0;
|
||||
if (collapse(user))
|
||||
for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
|
||||
{
|
||||
if (!MyClient(c2ptr)) /* implies mine and a user */
|
||||
continue;
|
||||
if ((!host || !match(host, c2ptr->user->host)) &&
|
||||
mycmp(user, c2ptr->user->username) == 0)
|
||||
{
|
||||
(*count)++;
|
||||
res = c2ptr;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** Find server by name.
|
||||
**
|
||||
** This implementation assumes that server and user names
|
||||
** are unique, no user can have a server name and vice versa.
|
||||
** One should maintain separate lists for users and servers,
|
||||
** if this restriction is removed.
|
||||
**
|
||||
** *Note*
|
||||
** Semantics of this function has been changed from
|
||||
** the old. 'name' is now assumed to be a null terminated
|
||||
** string.
|
||||
*/
|
||||
aClient *find_server(name, cptr)
|
||||
char *name;
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
if (name)
|
||||
cptr = hash_find_server(name, cptr);
|
||||
return cptr;
|
||||
}
|
||||
|
||||
aClient *find_match_server(mask)
|
||||
char *mask;
|
||||
{
|
||||
aClient *acptr;
|
||||
|
||||
if (BadPtr(mask))
|
||||
return NULL;
|
||||
for (acptr = client, (void)collapse(mask); acptr; acptr = acptr->next)
|
||||
{
|
||||
if (!IsServer(acptr) && !IsMe(acptr))
|
||||
continue;
|
||||
if (!match(mask, acptr->name))
|
||||
break; continue;
|
||||
}
|
||||
return acptr;
|
||||
}
|
||||
|
||||
aClient *find_name(name, cptr)
|
||||
char *name;
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 aClient *c2ptr = cptr;
|
||||
|
||||
if (!collapse(name))
|
||||
return c2ptr;
|
||||
|
||||
if ((c2ptr = hash_find_server(name, cptr)))
|
||||
return (c2ptr);
|
||||
if (!index(name, '*'))
|
||||
return c2ptr;
|
||||
for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
|
||||
{
|
||||
if (!IsServer(c2ptr) && !IsMe(c2ptr))
|
||||
continue;
|
||||
if (match(name, c2ptr->name) == 0)
|
||||
break;
|
||||
if (index(c2ptr->name, '*'))
|
||||
if (match(c2ptr->name, name) == 0)
|
||||
break;
|
||||
}
|
||||
return (c2ptr ? c2ptr : cptr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Find person by (nick)name.
|
||||
*/
|
||||
aClient *find_person(name, cptr)
|
||||
char *name;
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 aClient *c2ptr = cptr;
|
||||
|
||||
c2ptr = find_client(name, c2ptr);
|
||||
|
||||
if (c2ptr && IsClient(c2ptr) && c2ptr->user)
|
||||
return c2ptr;
|
||||
else
|
||||
return cptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse a buffer.
|
||||
*
|
||||
* NOTE: parse() should not be called recusively by any other fucntions!
|
||||
*/
|
||||
int parse(cptr, buffer, bufend, mptr)
|
||||
aClient *cptr;
|
||||
char *buffer, *bufend;
|
||||
struct Message *mptr;
|
||||
{
|
||||
Reg1 aClient *from = cptr;
|
||||
Reg2 char *ch, *s;
|
||||
Reg3 int len, i, numeric, paramcount, noprefix = 0;
|
||||
|
||||
Debug((DEBUG_DEBUG,"Parsing: %s", buffer));
|
||||
if (IsDead(cptr))
|
||||
return 0;
|
||||
|
||||
s = sender;
|
||||
*s = '\0';
|
||||
for (ch = buffer; *ch == ' '; ch++)
|
||||
;
|
||||
para[0] = from->name;
|
||||
if (*ch == ':')
|
||||
{
|
||||
/*
|
||||
** Copy the prefix to 'sender' assuming it terminates
|
||||
** with SPACE (or NULL, which is an error, though).
|
||||
*/
|
||||
for (++ch, i = 0; *ch && *ch != ' '; ++ch )
|
||||
if (s < (sender + sizeof(sender)-1))
|
||||
*s++ = *ch; /* leave room for NULL */
|
||||
*s = '\0';
|
||||
|
||||
/*
|
||||
** Actually, only messages coming from servers can have
|
||||
** the prefix--prefix silently ignored, if coming from
|
||||
** a user client...
|
||||
**
|
||||
** ...sigh, the current release "v2.2PL1" generates also
|
||||
** null prefixes, at least to NOTIFY messages (e.g. it
|
||||
** puts "sptr->nickname" as prefix from server structures
|
||||
** where it's null--the following will handle this case
|
||||
** as "no prefix" at all --msa (": NOTICE nick ...")
|
||||
*/
|
||||
if (*sender && IsServer(cptr))
|
||||
{
|
||||
from = find_client(sender, (aClient *) NULL);
|
||||
if (!from || matches(from->name, sender))
|
||||
from = find_server(sender, (aClient *)NULL);
|
||||
else if (!from && index(sender, '@'))
|
||||
from = find_nickserv(sender, (aClient *)NULL);
|
||||
|
||||
para[0] = sender;
|
||||
|
||||
/* If the client corresponding to the
|
||||
* prefix is not found. We must ignore it,
|
||||
* it is simply a lagged message travelling
|
||||
* upstream a SQUIT that removed the client
|
||||
* --Run
|
||||
*/
|
||||
if (!from)
|
||||
{
|
||||
Debug((DEBUG_NOTICE,
|
||||
"Unknown prefix (%s)(%s) from (%s)",
|
||||
sender, buffer, cptr->name));
|
||||
ircstp->is_unpf++;
|
||||
while (*ch == ' ')
|
||||
ch++;
|
||||
/*
|
||||
** However, the only thing that MUST be
|
||||
** allowed to travel upstream against an
|
||||
** squit, is an SQUIT itself (the timestamp
|
||||
** protects us from being used wrong)
|
||||
*/
|
||||
if (strncmp(ch, "SQUIT ", 6)==0)
|
||||
{
|
||||
strcpy(sender, cptr->name);
|
||||
from = cptr;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else if (from->from != cptr)
|
||||
{
|
||||
ircstp->is_wrdi++;
|
||||
Debug((DEBUG_NOTICE,
|
||||
"Fake direction: Message (%s) coming from (%s)",
|
||||
buffer, cptr->name));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (*ch == ' ')
|
||||
ch++;
|
||||
}
|
||||
else
|
||||
noprefix = 1;
|
||||
if (*ch == '\0')
|
||||
{
|
||||
ircstp->is_empt++;
|
||||
Debug((DEBUG_NOTICE, "Empty message from host %s:%s",
|
||||
cptr->name, from->name));
|
||||
return(-1);
|
||||
}
|
||||
/*
|
||||
** Extract the command code from the packet. Point s to the end
|
||||
** of the command code and calculate the length using pointer
|
||||
** arithmetic. Note: only need length for numerics and *all*
|
||||
** numerics must have paramters and thus a space after the command
|
||||
** code. -avalon
|
||||
*/
|
||||
s = (char *)index(ch, ' '); /* s -> End of the command code */
|
||||
len = (s) ? (s - ch) : 0;
|
||||
if (len == 3 &&
|
||||
isdigit(*ch) && isdigit(*(ch + 1)) && isdigit(*(ch + 2)))
|
||||
{
|
||||
mptr = NULL;
|
||||
numeric = (*ch - '0') * 100 + (*(ch + 1) - '0') * 10
|
||||
+ (*(ch + 2) - '0');
|
||||
paramcount = MAXPARA;
|
||||
ircstp->is_num++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s)
|
||||
*s++ = '\0';
|
||||
for (; mptr->cmd; mptr++)
|
||||
if (mycmp(mptr->cmd, ch) == 0)
|
||||
break;
|
||||
|
||||
if (!mptr->cmd)
|
||||
{
|
||||
/*
|
||||
** Note: Give error message *only* to recognized
|
||||
** persons. It's a nightmare situation to have
|
||||
** two programs sending "Unknown command"'s or
|
||||
** equivalent to each other at full blast....
|
||||
** If it has got to person state, it at least
|
||||
** seems to be well behaving. Perhaps this message
|
||||
** should never be generated, though... --msa
|
||||
** Hm, when is the buffer empty -- if a command
|
||||
** code has been found ?? -Armin
|
||||
*/
|
||||
if (buffer[0] != '\0')
|
||||
{
|
||||
if (IsPerson(from))
|
||||
sendto_one(from,
|
||||
":%s %d %s %s :Unknown command",
|
||||
me.name, ERR_UNKNOWNCOMMAND,
|
||||
from->name, ch);
|
||||
Debug((DEBUG_ERROR,"Unknown (%s) from %s",
|
||||
ch, get_client_name(cptr, TRUE)));
|
||||
}
|
||||
ircstp->is_unco++;
|
||||
return(-1);
|
||||
}
|
||||
paramcount = mptr->parameters;
|
||||
i = bufend - ((s) ? s : ch);
|
||||
mptr->bytes += i;
|
||||
if ((mptr->flags & 1) && !(IsServer(cptr) || IsService(cptr)))
|
||||
cptr->since += (2 + i / 120);
|
||||
/* Allow only 1 msg per 2 seconds
|
||||
* (on average) to prevent dumping.
|
||||
* to keep the response rate up,
|
||||
* bursts of up to 5 msgs are allowed
|
||||
* -SRB
|
||||
*/
|
||||
}
|
||||
/*
|
||||
** Must the following loop really be so devious? On
|
||||
** surface it splits the message to parameters from
|
||||
** blank spaces. But, if paramcount has been reached,
|
||||
** the rest of the message goes into this last parameter
|
||||
** (about same effect as ":" has...) --msa
|
||||
*/
|
||||
|
||||
/* Note initially true: s==NULL || *(s-1) == '\0' !! */
|
||||
|
||||
i = 0;
|
||||
if (s)
|
||||
{
|
||||
if (paramcount > MAXPARA)
|
||||
paramcount = MAXPARA;
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
** Never "FRANCE " again!! ;-) Clean
|
||||
** out *all* blanks.. --msa
|
||||
*/
|
||||
while (*s == ' ')
|
||||
*s++ = '\0';
|
||||
|
||||
if (*s == '\0')
|
||||
break;
|
||||
if (*s == ':')
|
||||
{
|
||||
/*
|
||||
** The rest is single parameter--can
|
||||
** include blanks also.
|
||||
*/
|
||||
para[++i] = s + 1;
|
||||
break;
|
||||
}
|
||||
para[++i] = s;
|
||||
if (i >= paramcount)
|
||||
break;
|
||||
for (; *s != ' ' && *s; s++)
|
||||
;
|
||||
}
|
||||
}
|
||||
para[++i] = NULL;
|
||||
if (mptr == NULL)
|
||||
return (do_numeric(numeric, cptr, from, i, para));
|
||||
mptr->count++;
|
||||
if (!IsRegistered(cptr) && (
|
||||
/* patch to avoid server flooding from unregistered connects : --dl */
|
||||
(mptr->func!=m_user)
|
||||
&& (mptr->func!=m_quit)
|
||||
&& (mptr->func!=m_admin)
|
||||
&& (mptr->func!=m_version)
|
||||
&& (mptr->func!=m_server)
|
||||
&& (mptr->func!=m_pass)
|
||||
&& (mptr->func!=m_nick)
|
||||
&& (mptr->func!=m_pong)
|
||||
&& (mptr->func!=m_error) ) )
|
||||
{
|
||||
sendto_one(from,
|
||||
":%s %d %s %s :Register first.",
|
||||
me.name, ERR_NOTREGISTERED,
|
||||
from->name, ch);
|
||||
return -1;
|
||||
}
|
||||
if (IsRegisteredUser(cptr) &&
|
||||
#ifdef IDLE_FROM_MSG
|
||||
mptr->func == m_private)
|
||||
#else
|
||||
mptr->func != m_ping && mptr->func != m_pong)
|
||||
#endif
|
||||
from->user->last = now;
|
||||
|
||||
/* Lame protocol 4 stuff... this if can be removed when all are 2.9 */
|
||||
if (noprefix && IsServer(cptr) && i >= 2 && mptr->func == m_squit &&
|
||||
(!(from = find_server(para[1], (aClient *)NULL)) ||
|
||||
from->from != cptr))
|
||||
{
|
||||
Debug((DEBUG_DEBUG,"Ignoring protocol 4 \"%s %s %s ...\"",
|
||||
para[0], para[1], para[2]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (*mptr->func)(cptr, from, i, para);
|
||||
}
|
||||
|
||||
/*
|
||||
* field breakup for ircd.conf file.
|
||||
*/
|
||||
char *getfield(newline)
|
||||
char *newline;
|
||||
{
|
||||
static char *line = NULL;
|
||||
char *end, *field;
|
||||
|
||||
if (newline)
|
||||
line = newline;
|
||||
if (line == NULL)
|
||||
return(NULL);
|
||||
|
||||
field = line;
|
||||
if ((end = (char *)index(line,':')) == NULL)
|
||||
{
|
||||
line = NULL;
|
||||
if ((end = (char *)index(field,'\n')) == NULL)
|
||||
end = field + strlen(field);
|
||||
}
|
||||
else
|
||||
line = end + 1;
|
||||
*end = '\0';
|
||||
return(field);
|
||||
}
|
||||
955
common/send.c
Normal file
955
common/send.c
Normal file
@@ -0,0 +1,955 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, common/send.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Computing Center
|
||||
*
|
||||
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* -- Run -- 28 sept 1994
|
||||
* Corrected the wrong way varargs were treated...
|
||||
*/
|
||||
|
||||
/* -- Jto -- 16 Jun 1990
|
||||
* Added Armin's PRIVMSG patches...
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)send.c 2.32 2/28/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "h.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static char sendbuf[2048];
|
||||
static void sendbufto_one PROTO((aClient *));
|
||||
static int sentalong[MAXCONNECTIONS];
|
||||
|
||||
/*
|
||||
** dead_link
|
||||
** An error has been detected. The link *must* be closed,
|
||||
** but *cannot* call ExitClient (m_bye) from here.
|
||||
** Instead, mark it with FLAGS_DEADSOCKET. This should
|
||||
** generate ExitClient from the main loop.
|
||||
**
|
||||
** If 'notice' is not NULL, it is assumed to be a format
|
||||
** for a message to local opers. I can contain only one
|
||||
** '%s', which will be replaced by the sockhost field of
|
||||
** the failing link.
|
||||
**
|
||||
** Also, the notice is skipped for "uninteresting" cases,
|
||||
** like Persons and yet unknown connections...
|
||||
*/
|
||||
char *last_dead_comment = NULL;
|
||||
|
||||
static void dead_link(to, notice)
|
||||
aClient *to;
|
||||
char *notice;
|
||||
{
|
||||
char dead_comment_buf[256]; /* SHOULD be big enough */
|
||||
|
||||
to->flags |= FLAGS_DEADSOCKET;
|
||||
/*
|
||||
* If because of BUFFERPOOL problem then clean dbuf's now so that
|
||||
* notices don't hurt operators below.
|
||||
*/
|
||||
DBufClear(&to->recvQ);
|
||||
DBufClear(&to->sendQ);
|
||||
|
||||
/* Keep a copy of the last comment, for later use... */
|
||||
sprintf(dead_comment_buf, notice, get_client_name(to, FALSE));
|
||||
if (last_dead_comment)
|
||||
MyFree(last_dead_comment);
|
||||
last_dead_comment = (char *)MyMalloc(strlen(dead_comment_buf) + 1);
|
||||
strcpy(last_dead_comment, dead_comment_buf);
|
||||
|
||||
if (!IsPerson(to) && !IsUnknown(to) && !(to->flags & FLAGS_CLOSING))
|
||||
sendto_ops(last_dead_comment);
|
||||
Debug((DEBUG_ERROR, last_dead_comment));
|
||||
}
|
||||
|
||||
/*
|
||||
** flush_connections
|
||||
** Used to empty all output buffers for all connections. Should only
|
||||
** be called once per scan of connections. There should be a select in
|
||||
** here perhaps but that means either forcing a timeout or doing a poll.
|
||||
** When flushing, all we do is empty the obuffer array for each local
|
||||
** client and try to send it. if we cant send it, it goes into the sendQ
|
||||
** -avalon
|
||||
*/
|
||||
void flush_connections(fd)
|
||||
int fd;
|
||||
{
|
||||
Reg1 int i;
|
||||
Reg2 aClient *cptr;
|
||||
|
||||
if (fd == me.fd)
|
||||
{
|
||||
for (i = highest_fd; i >= 0; i--)
|
||||
if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0)
|
||||
send_queued(cptr);
|
||||
}
|
||||
else if (fd >= 0 && (cptr = local[fd]) && DBufLength(&cptr->sendQ) > 0)
|
||||
send_queued(cptr);
|
||||
}
|
||||
|
||||
/*
|
||||
** send_queued
|
||||
** This function is called from the main select-loop (or whatever)
|
||||
** when there is a chance that some output would be possible. This
|
||||
** attempts to empty the send queue as far as possible...
|
||||
*/
|
||||
void send_queued(to)
|
||||
aClient *to;
|
||||
{
|
||||
#ifndef pyr
|
||||
if (to->flags & FLAGS_BLOCKED)
|
||||
return; /* Don't bother */
|
||||
#endif
|
||||
/*
|
||||
** Once socket is marked dead, we cannot start writing to it,
|
||||
** even if the error is removed...
|
||||
*/
|
||||
if (IsDead(to))
|
||||
{
|
||||
/*
|
||||
** Actually, we should *NEVER* get here--something is
|
||||
** not working correct if send_queued is called for a
|
||||
** dead socket... --msa
|
||||
*/
|
||||
return;
|
||||
}
|
||||
while (DBufLength(&to->sendQ) > 0)
|
||||
{
|
||||
char *msg;
|
||||
int len, rlen;
|
||||
|
||||
msg = dbuf_map(&to->sendQ, &len);
|
||||
/* Returns always len > 0 */
|
||||
if ((rlen = deliver_it(to, msg, len)) < 0)
|
||||
{
|
||||
dead_link(to,"Write error to %s, closing link");
|
||||
return;
|
||||
}
|
||||
(void)dbuf_delete(&to->sendQ, rlen);
|
||||
to->lastsq = DBufLength(&to->sendQ)/1024;
|
||||
if (rlen < len)
|
||||
{
|
||||
to->flags |= FLAGS_BLOCKED; /* Wait till select() says we can write again */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** send message to single client
|
||||
*/
|
||||
#ifdef USE_VARARGS
|
||||
void sendto_one(to, pattern, va_alist)
|
||||
aClient *to;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl);
|
||||
vsendto_one(to, pattern, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void vsendto_one(to, pattern, vl)
|
||||
aClient *to;
|
||||
char *pattern;
|
||||
va_list vl;
|
||||
{
|
||||
#else
|
||||
void sendto_one(to, pattern, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
|
||||
aClient *to;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11;
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
(void)vsprintf(sendbuf, pattern, vl);
|
||||
#else
|
||||
(void)sprintf(sendbuf, pattern, p1, p2, p3, p4, p5, p6,
|
||||
p7, p8, p9, p10, p11);
|
||||
#endif
|
||||
sendbufto_one(to);
|
||||
}
|
||||
|
||||
static void sendbufto_one(to)
|
||||
aClient *to;
|
||||
{
|
||||
int len;
|
||||
|
||||
Debug((DEBUG_SEND,"Sending [%s] to %s", sendbuf,to->name));
|
||||
|
||||
if (to->from)
|
||||
to = to->from;
|
||||
if (IsDead(to))
|
||||
return; /* This socket has already been marked as dead */
|
||||
if (to->fd < 0)
|
||||
{
|
||||
/* This is normal when 'to' was being closed (via exit_client
|
||||
** and close_connection) --Run
|
||||
** Print the debug message anyway...
|
||||
*/
|
||||
Debug((DEBUG_ERROR,
|
||||
"Local socket %s with negative fd %d... AARGH!",
|
||||
to->name, to->fd));
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(sendbuf);
|
||||
if (sendbuf[len-1] != '\n')
|
||||
{
|
||||
#ifndef IRCII_KLUDGE
|
||||
if (len > 510)
|
||||
len = 510;
|
||||
sendbuf[len++] = '\r';
|
||||
#else
|
||||
if (len > 511)
|
||||
len = 511;
|
||||
#endif
|
||||
sendbuf[len++] = '\n';
|
||||
sendbuf[len] = '\0';
|
||||
}
|
||||
|
||||
if (IsMe(to))
|
||||
{
|
||||
char tmp_sendbuf[sizeof(sendbuf)];
|
||||
|
||||
strcpy(tmp_sendbuf, sendbuf);
|
||||
sendto_ops("Trying to send [%s] to myself!", tmp_sendbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DBufLength(&to->sendQ) > get_sendq(to))
|
||||
{
|
||||
if (IsServer(to))
|
||||
sendto_ops("Max SendQ limit exceeded for %s: %d > %d",
|
||||
get_client_name(to, FALSE),
|
||||
DBufLength(&to->sendQ), get_sendq(to));
|
||||
dead_link(to, "Max Sendq exceeded");
|
||||
return;
|
||||
}
|
||||
|
||||
else if (dbuf_put(&to->sendQ, sendbuf, len) < 0)
|
||||
{
|
||||
dead_link(to, "Buffer allocation error for %s");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
** Update statistics. The following is slightly incorrect
|
||||
** because it counts messages even if queued, but bytes
|
||||
** only really sent. Queued bytes get updated in SendQueued.
|
||||
*/
|
||||
to->sendM += 1;
|
||||
me.sendM += 1;
|
||||
if (to->acpt != &me)
|
||||
to->acpt->sendM += 1;
|
||||
/*
|
||||
** This little bit is to stop the sendQ from growing too large when
|
||||
** there is no need for it to. Thus we call send_queued() every time
|
||||
** 2k has been added to the queue since the last non-fatal write.
|
||||
** Also stops us from deliberately building a large sendQ and then
|
||||
** trying to flood that link with data (possible during the net
|
||||
** relinking done by servers with a large load).
|
||||
*/
|
||||
if (DBufLength(&to->sendQ)/1024 > to->lastsq)
|
||||
send_queued(to);
|
||||
}
|
||||
|
||||
# ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_channel_butone(one, from, chptr, pattern,
|
||||
p1, p2, p3, p4, p5, p6, p7, p8)
|
||||
aClient *one, *from;
|
||||
aChannel *chptr;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
|
||||
{
|
||||
# else
|
||||
void sendto_channel_butone(one, from, chptr, pattern, va_alist)
|
||||
aClient *one, *from;
|
||||
aChannel *chptr;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
# endif
|
||||
Reg1 Link *lp;
|
||||
Reg2 aClient *acptr;
|
||||
Reg3 int i;
|
||||
|
||||
# ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
# endif
|
||||
for (i = 0; i < MAXCONNECTIONS; i++)
|
||||
sentalong[i] = 0;
|
||||
for (lp = chptr->members; lp; lp = lp->next)
|
||||
{
|
||||
acptr = lp->value.cptr;
|
||||
if (acptr->from == one || /* ...was the one I should skip */
|
||||
(lp->flags & CHFL_ZOMBIE) || IsDeaf(acptr))
|
||||
continue;
|
||||
i = acptr->from->fd;
|
||||
if (MyConnect(acptr) && IsRegisteredUser(acptr))
|
||||
{
|
||||
# ifdef USE_VARARGS
|
||||
vsendto_prefix_one(acptr, from, pattern, vl);
|
||||
# else
|
||||
sendto_prefix_one(acptr, from, pattern, p1, p2,
|
||||
p3, p4, p5, p6, p7, p8);
|
||||
# endif
|
||||
sentalong[i] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now check whether a message has been sent to this
|
||||
* remote link already */
|
||||
if (sentalong[i] == 0)
|
||||
{
|
||||
# ifdef USE_VARARGS
|
||||
vsendto_prefix_one(acptr, from, pattern, vl);
|
||||
# else
|
||||
sendto_prefix_one(acptr, from, pattern,
|
||||
p1, p2, p3, p4,
|
||||
p5, p6, p7, p8);
|
||||
# endif
|
||||
sentalong[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
# ifdef USE_VARARGS
|
||||
va_end(vl);
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_server_butone
|
||||
*
|
||||
* Send a message to all connected servers except the client 'one'.
|
||||
*/
|
||||
# ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_serv_butone(one, pattern, p1, p2, p3, p4, p5, p6, p7, p8)
|
||||
aClient *one;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
|
||||
{
|
||||
# else
|
||||
void sendto_serv_butone(one, pattern, va_alist)
|
||||
aClient *one;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
# endif
|
||||
Reg1 Dlink *lp;
|
||||
|
||||
# ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
(void)vsprintf(sendbuf, pattern, vl);
|
||||
va_end(vl);
|
||||
# else
|
||||
(void)sprintf(sendbuf, pattern, p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
# endif
|
||||
|
||||
for (lp = me.serv->down; lp; lp=lp->next)
|
||||
{
|
||||
if (one && lp->value.cptr == one->from)
|
||||
continue;
|
||||
sendbufto_one(lp->value.cptr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_common_channels()
|
||||
*
|
||||
* Sends a message to all people (inclusing user) on local server who are
|
||||
* in same channel with user.
|
||||
*/
|
||||
# ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_common_channels(user, pattern, p1, p2, p3, p4,
|
||||
p5, p6, p7, p8)
|
||||
aClient *user;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
|
||||
{
|
||||
# else
|
||||
void sendto_common_channels(user, pattern, va_alist)
|
||||
aClient *user;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
# endif
|
||||
Reg1 int i;
|
||||
Reg2 aClient *cptr;
|
||||
Reg3 Link *lp;
|
||||
|
||||
# ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
# endif
|
||||
|
||||
for (i = 0; i <= highest_fd; i++)
|
||||
{
|
||||
if (!(cptr = local[i]) || IsServer(cptr) ||
|
||||
user == cptr || !user->user)
|
||||
continue;
|
||||
for (lp = user->user->channel; lp; lp = lp->next)
|
||||
if (IsMember(user, lp->value.chptr) &&
|
||||
IsMember(cptr, lp->value.chptr))
|
||||
{
|
||||
# ifdef USE_VARARGS
|
||||
vsendto_prefix_one(cptr, user, pattern, vl);
|
||||
# else
|
||||
sendto_prefix_one(cptr, user, pattern,
|
||||
p1, p2, p3, p4,
|
||||
p5, p6, p7, p8);
|
||||
# endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (MyConnect(user))
|
||||
# ifdef USE_VARARGS
|
||||
vsendto_prefix_one(user, user, pattern, vl);
|
||||
va_end(vl);
|
||||
# else
|
||||
sendto_prefix_one(user, user, pattern, p1, p2, p3, p4,
|
||||
p5, p6, p7, p8);
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_channel_butserv
|
||||
*
|
||||
* Send a message to all members of a channel that are connected to this
|
||||
* server.
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_channel_butserv(chptr, from, pattern, p1, p2, p3,
|
||||
p4, p5, p6, p7, p8)
|
||||
aChannel *chptr;
|
||||
aClient *from;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
|
||||
{
|
||||
#else
|
||||
void sendto_channel_butserv(chptr, from, pattern, va_alist)
|
||||
aChannel *chptr;
|
||||
aClient *from;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
Reg1 Link *lp;
|
||||
Reg2 aClient *acptr;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
for (va_start(vl), lp = chptr->members; lp; lp = lp->next)
|
||||
if (MyConnect(acptr = lp->value.cptr) &&
|
||||
!(lp->flags & CHFL_ZOMBIE))
|
||||
vsendto_prefix_one(acptr, from, pattern, vl);
|
||||
va_end(vl);
|
||||
#else
|
||||
for (lp = chptr->members; lp; lp = lp->next)
|
||||
if (MyConnect(acptr = lp->value.cptr) &&
|
||||
!(lp->flags & CHFL_ZOMBIE))
|
||||
sendto_prefix_one(acptr, from, pattern,
|
||||
p1, p2, p3, p4,
|
||||
p5, p6, p7, p8);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** send a msg to all ppl on servers/hosts that match a specified mask
|
||||
** (used for enhanced PRIVMSGs)
|
||||
**
|
||||
** addition -- Armin, 8jun90 (gruner@informatik.tu-muenchen.de)
|
||||
*/
|
||||
|
||||
static int match_it(one, mask, what)
|
||||
aClient *one;
|
||||
char *mask;
|
||||
int what;
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case MATCH_HOST:
|
||||
return (matches(mask, one->user->host)==0);
|
||||
case MATCH_SERVER:
|
||||
default:
|
||||
return (matches(mask, one->user->server->name)==0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_match_servs
|
||||
*
|
||||
* send to all servers which match the mask at the end of a channel name
|
||||
* (if there is a mask present) or to all if no mask.
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_match_servs(chptr, from, format, p1,p2,p3,p4,p5,p6,p7,p8,p9)
|
||||
aChannel *chptr;
|
||||
aClient *from;
|
||||
char *format, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
|
||||
{
|
||||
#else
|
||||
void sendto_match_servs(chptr, from, format, va_alist)
|
||||
aChannel *chptr;
|
||||
aClient *from;
|
||||
char *format;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
Reg1 Dlink *lp;
|
||||
Reg2 aClient *cptr;
|
||||
char *mask;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
#endif
|
||||
if (chptr)
|
||||
{
|
||||
if (*chptr->chname == '&')
|
||||
return;
|
||||
if (mask = (char *)rindex(chptr->chname, ':'))
|
||||
mask++;
|
||||
}
|
||||
else
|
||||
mask = NULL;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
vsprintf(sendbuf, format, vl);
|
||||
va_end(vl);
|
||||
#else
|
||||
sprintf(sendbuf, format, p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||
#endif
|
||||
for (lp = me.serv->down; lp; lp = lp->next)
|
||||
{
|
||||
if ((cptr=lp->value.cptr) == from)
|
||||
continue;
|
||||
if (!BadPtr(mask) && matches(mask, cptr->name))
|
||||
continue;
|
||||
sendbufto_one(cptr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_match_butone
|
||||
*
|
||||
* Send to all clients which match the mask in a way defined on 'what';
|
||||
* either by user hostname or user servername.
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_match_butone(one, from, mask, what, pattern,
|
||||
p1, p2, p3, p4, p5, p6, p7, p8)
|
||||
aClient *one, *from;
|
||||
int what;
|
||||
char *mask, *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
|
||||
{
|
||||
#else
|
||||
void sendto_match_butone(one, from, mask, what, pattern, va_alist)
|
||||
aClient *one, *from;
|
||||
int what;
|
||||
char *mask, *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
Reg1 int i;
|
||||
Reg2 aClient *cptr, *acptr;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
#endif
|
||||
for (i = 0; i <= highest_fd; i++)
|
||||
{
|
||||
if (!(cptr = local[i]))
|
||||
continue; /* that clients are not mine */
|
||||
if (cptr == one) /* must skip the origin !! */
|
||||
continue;
|
||||
if (IsServer(cptr))
|
||||
{
|
||||
for (acptr = client; acptr; acptr = acptr->next)
|
||||
if (IsRegisteredUser(acptr)
|
||||
&& match_it(acptr, mask, what)
|
||||
&& acptr->from == cptr)
|
||||
break;
|
||||
/* a person on that server matches the mask, so we
|
||||
** send *one* msg to that server ...
|
||||
*/
|
||||
if (acptr == NULL)
|
||||
continue;
|
||||
/* ... but only if there *IS* a matching person */
|
||||
}
|
||||
/* my client, does he match ? */
|
||||
else if (!(IsRegisteredUser(cptr) &&
|
||||
match_it(cptr, mask, what)))
|
||||
continue;
|
||||
#ifdef USE_VARARGS
|
||||
vsendto_prefix_one(cptr, from, pattern, vl);
|
||||
}
|
||||
va_end(vl);
|
||||
#else
|
||||
sendto_prefix_one(cptr, from, pattern,
|
||||
p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_all_butone.
|
||||
*
|
||||
* Send a message to all connections except 'one'. The basic wall type
|
||||
* message generator.
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_all_butone(one, from, pattern, p1, p2, p3, p4, p5, p6, p7, p8)
|
||||
aClient *one, *from;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
|
||||
{
|
||||
#else
|
||||
void sendto_all_butone(one, from, pattern, va_alist)
|
||||
aClient *one, *from;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
Reg1 int i;
|
||||
Reg2 aClient *cptr;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
for (va_start(vl), i = 0; i <= highest_fd; i++)
|
||||
if ((cptr = local[i]) && !IsMe(cptr) && one != cptr)
|
||||
vsendto_prefix_one(cptr, from, pattern, vl);
|
||||
va_end(vl);
|
||||
#else
|
||||
for (i = 0; i <= highest_fd; i++)
|
||||
if ((cptr = local[i]) && !IsMe(cptr) && one != cptr)
|
||||
sendto_prefix_one(cptr, from, pattern,
|
||||
p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_lops_butone
|
||||
*
|
||||
* Send to *local* ops but one.
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_lops_butone(one, pattern, p1, p2, p3, p4, p5, p6, p7)
|
||||
aClient *one;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7;
|
||||
{
|
||||
#else
|
||||
void sendto_lops_butone(one, pattern, va_alist)
|
||||
aClient *one;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
Reg1 aClient *cptr;
|
||||
Reg2 Dlink *lp;
|
||||
char nbuf[1024];
|
||||
|
||||
(void)sprintf(nbuf, ":%s NOTICE %%s :*** Notice -- ", me.name);
|
||||
#ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
(void)vsprintf(nbuf + strlen(nbuf), pattern, vl);
|
||||
va_end(vl);
|
||||
#else
|
||||
(void)strncat(nbuf, pattern, sizeof(nbuf) - strlen(nbuf));
|
||||
#endif
|
||||
for (lp = me.serv->client; lp; lp=lp->next)
|
||||
if ((cptr=lp->value.cptr)!=one && SendServNotice(cptr))
|
||||
#ifdef USE_VARARGS
|
||||
{
|
||||
(void)sprintf(sendbuf, nbuf, cptr->name);
|
||||
sendbufto_one(cptr);
|
||||
}
|
||||
#else
|
||||
sendto_one(cptr, nbuf, cptr->name, p1, p2, p3, p4, p5, p6, p7);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_ops
|
||||
*
|
||||
* Send to *local* ops only.
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_ops(pattern, p1, p2, p3, p4, p5, p6, p7)
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7;
|
||||
{
|
||||
#else
|
||||
void sendto_ops(pattern, va_alist)
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
Reg1 aClient *cptr;
|
||||
Reg2 int i;
|
||||
char fmt[1024];
|
||||
char *fmt_target;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
#endif
|
||||
|
||||
(void)sprintf(fmt, ":%s NOTICE ", me.name);
|
||||
fmt_target = &fmt[strlen(fmt)];
|
||||
|
||||
for (i = 0; i <= highest_fd; i++)
|
||||
if ((cptr = local[i]) && !IsServer(cptr) && !IsMe(cptr) &&
|
||||
SendServNotice(cptr))
|
||||
{
|
||||
strcpy(fmt_target, cptr->name);
|
||||
strcat(fmt_target, " :*** Notice -- ");
|
||||
strcat(fmt_target, pattern);
|
||||
#ifdef USE_VARARGS
|
||||
vsendto_one(cptr, fmt, vl);
|
||||
#else
|
||||
sendto_one(cptr, fmt, p1, p2, p3, p4, p5, p6, p7);
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_SERVICES
|
||||
else if (cptr && IsService(cptr) &&
|
||||
(cptr->service->wanted & SERVICE_WANT_SERVNOTE))
|
||||
{
|
||||
strcpy(fmt_target, cptr->name);
|
||||
strcat(fmt, " :*** Notice -- ");
|
||||
strcat(fmt, pattern);
|
||||
# ifdef USE_VARARGS
|
||||
vsendto_one(cptr, fmt, vl);
|
||||
# else
|
||||
sendto_one(cptr, fmt, cptr->name, p1, p2, p3, p4, p5, p6, p7);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
va_end(vl);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** sendto_ops_butone
|
||||
** Send message to all operators.
|
||||
** one - client not to send message to
|
||||
** from- client which message is from *NEVER* NULL!!
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_ops_butone(one, from, pattern, p1, p2, p3, p4, p5, p6, p7, p8)
|
||||
aClient *one, *from;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
|
||||
{
|
||||
#else
|
||||
void sendto_ops_butone(one, from, pattern, va_alist)
|
||||
aClient *one, *from;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
Reg1 int i;
|
||||
Reg2 aClient *cptr;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
#endif
|
||||
for (i=0; i <= highest_fd; i++)
|
||||
sentalong[i] = 0;
|
||||
for (cptr = client; cptr; cptr = cptr->next)
|
||||
{
|
||||
if (!SendWallops(cptr))
|
||||
continue;
|
||||
i = cptr->from->fd; /* find connection oper is on */
|
||||
if (sentalong[i]) /* sent message along it already ? */
|
||||
continue;
|
||||
if (cptr->from == one)
|
||||
continue; /* ...was the one I should skip */
|
||||
sentalong[i] = 1;
|
||||
# ifdef USE_VARARGS
|
||||
vsendto_prefix_one(cptr->from, from, pattern, vl);
|
||||
}
|
||||
va_end(vl);
|
||||
# else
|
||||
sendto_prefix_one(cptr->from, from, pattern,
|
||||
p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
}
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* to - destination client
|
||||
* from - client which message is from
|
||||
*
|
||||
* NOTE: NEITHER OF THESE SHOULD *EVER* BE NULL!!
|
||||
* -avalon
|
||||
*/
|
||||
#ifdef USE_VARARGS
|
||||
void sendto_prefix_one(to, from, pattern, va_alist)
|
||||
Reg1 aClient *to;
|
||||
Reg2 aClient *from;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl);
|
||||
vsendto_prefix_one(to, from, pattern, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void vsendto_prefix_one(to, from, pattern, vl)
|
||||
Reg1 aClient *to;
|
||||
Reg2 aClient *from;
|
||||
char *pattern;
|
||||
va_list vl;
|
||||
{
|
||||
#else
|
||||
void sendto_prefix_one(to, from, pattern, p1, p2, p3, p4, p5, p6, p7, p8)
|
||||
Reg1 aClient *to;
|
||||
Reg2 aClient *from;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
|
||||
{
|
||||
#endif
|
||||
static char sender[HOSTLEN+NICKLEN+USERLEN+5];
|
||||
Reg3 anUser *user;
|
||||
char *par;
|
||||
int flag = 0;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
par = va_arg(vl, char *);
|
||||
#else
|
||||
par = p1;
|
||||
#endif
|
||||
if (to && from && MyClient(to) && IsPerson(from) &&
|
||||
!mycmp(par, from->name))
|
||||
{
|
||||
user = from->user;
|
||||
(void)strcpy(sender, from->name);
|
||||
if (user)
|
||||
{
|
||||
if (*user->username)
|
||||
{
|
||||
(void)strcat(sender, "!");
|
||||
(void)strcat(sender, user->username);
|
||||
}
|
||||
if (*user->host && !MyConnect(from))
|
||||
{
|
||||
(void)strcat(sender, "@");
|
||||
(void)strcat(sender, user->host);
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
** flag is used instead of index(sender, '@') for speed and
|
||||
** also since username/nick may have had a '@' in them. -avalon
|
||||
*/
|
||||
if (!flag && MyConnect(from) && *user->host)
|
||||
{
|
||||
(void)strcat(sender, "@");
|
||||
if (IsUnixSocket(from))
|
||||
(void)strcat(sender, user->host);
|
||||
else
|
||||
(void)strcat(sender, from->sockhost);
|
||||
}
|
||||
par = sender;
|
||||
}
|
||||
#ifdef USE_VARARGS
|
||||
/* Assuming 'pattern' always starts with ":%s ..." */
|
||||
sprintf(sendbuf, ":%s", par);
|
||||
vsprintf(sendbuf + strlen(sendbuf), &pattern[3], vl);
|
||||
sendbufto_one(to);
|
||||
#else
|
||||
sendto_one(to, pattern, par, p2, p3, p4, p5, p6, p7, p8);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* sendto_realops
|
||||
*
|
||||
* Send to *local* ops only but NOT +s nonopers.
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
void sendto_realops(pattern, p1, p2, p3, p4, p5, p6, p7)
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7;
|
||||
{
|
||||
#else
|
||||
void sendto_realops(pattern, va_alist)
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
Reg1 aClient *cptr;
|
||||
Reg2 int i;
|
||||
char fmt[1024];
|
||||
Reg3 char *fmt_target;
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
#endif
|
||||
|
||||
(void)sprintf(fmt, ":%s NOTICE ", me.name);
|
||||
fmt_target = &fmt[strlen(fmt)];
|
||||
|
||||
for (i = 0; i <= highest_fd; i++)
|
||||
if ((cptr = local[i]) && IsOper(cptr))
|
||||
{
|
||||
strcpy(fmt_target, cptr->name);
|
||||
strcat(fmt_target, " :*** Notice -- ");
|
||||
strcat(fmt_target, pattern);
|
||||
#ifdef USE_VARARGS
|
||||
vsendto_one(cptr, fmt, vl);
|
||||
#else
|
||||
sendto_one(cptr, fmt, p1, p2, p3, p4, p5, p6, p7);
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_VARARGS
|
||||
va_end(vl);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
472
common/support.c
Normal file
472
common/support.c
Normal file
@@ -0,0 +1,472 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, common/support.c
|
||||
* Copyright (C) 1990, 1991 Armin Gruner
|
||||
*
|
||||
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)support.c 2.21 4/13/94 1990, 1991 Armin Gruner;\
|
||||
1992, 1993 Darren Reed";
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#ifdef DYNIXPTX
|
||||
#include <sys/timers.h>
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
|
||||
extern int errno; /* ...seems that errno.h doesn't define this everywhere */
|
||||
extern void outofmemory();
|
||||
|
||||
#ifdef NEED_STRTOKEN
|
||||
/*
|
||||
** strtoken.c -- walk through a string of tokens, using a set
|
||||
** of separators
|
||||
** argv 9/90
|
||||
**
|
||||
** $Id: support.c,v 1.1.1.1 1996/05/05 22:25:22 klmitch Exp $
|
||||
*/
|
||||
|
||||
char *strtoken(save, str, fs)
|
||||
char **save;
|
||||
char *str, *fs;
|
||||
{
|
||||
char *pos = *save; /* keep last position across calls */
|
||||
Reg1 char *tmp;
|
||||
|
||||
if (str)
|
||||
pos = str; /* new string scan */
|
||||
|
||||
while (pos && *pos && index(fs, *pos) != NULL)
|
||||
pos++; /* skip leading separators */
|
||||
|
||||
if (!pos || !*pos)
|
||||
return (pos = *save = NULL); /* string contains only sep's */
|
||||
|
||||
tmp = pos; /* now, keep position of the token */
|
||||
|
||||
while (*pos && index(fs, *pos) == NULL)
|
||||
pos++; /* skip content of the token */
|
||||
|
||||
if (*pos)
|
||||
*pos++ = '\0'; /* remove first sep after the token */
|
||||
else
|
||||
pos = NULL; /* end of string */
|
||||
|
||||
*save = pos;
|
||||
return(tmp);
|
||||
}
|
||||
#endif /* NEED_STRTOKEN */
|
||||
|
||||
#ifdef NEED_STRTOK
|
||||
/*
|
||||
** NOT encouraged to use!
|
||||
*/
|
||||
|
||||
char *strtok(str, fs)
|
||||
char *str, *fs;
|
||||
{
|
||||
static char *pos;
|
||||
|
||||
return strtoken(&pos, str, fs);
|
||||
}
|
||||
|
||||
#endif /* NEED_STRTOK */
|
||||
|
||||
#ifdef NEED_STRERROR
|
||||
/*
|
||||
** strerror - return an appropriate system error string to a given errno
|
||||
**
|
||||
** argv 11/90
|
||||
** $Id: support.c,v 1.1.1.1 1996/05/05 22:25:22 klmitch Exp $
|
||||
*/
|
||||
|
||||
char *strerror(err_no)
|
||||
int err_no;
|
||||
{
|
||||
extern char *sys_errlist[]; /* Sigh... hopefully on all systems */
|
||||
extern int sys_nerr;
|
||||
|
||||
static char buff[40];
|
||||
char *errp;
|
||||
|
||||
errp = (err_no > sys_nerr ? (char *)NULL : sys_errlist[err_no]);
|
||||
|
||||
if (errp == (char *)NULL)
|
||||
{
|
||||
errp = buff;
|
||||
(void) sprintf(errp, "Unknown Error %d", err_no);
|
||||
}
|
||||
return errp;
|
||||
}
|
||||
|
||||
#endif /* NEED_STRERROR */
|
||||
|
||||
/*
|
||||
** inetntoa -- changed name to remove collision possibility and
|
||||
** so behaviour is gaurunteed to take a pointer arg.
|
||||
** -avalon 23/11/92
|
||||
** inet_ntoa -- returned the dotted notation of a given
|
||||
** internet number (some ULTRIX don't have this)
|
||||
** argv 11/90).
|
||||
** inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
|
||||
** $Id: support.c,v 1.1.1.1 1996/05/05 22:25:22 klmitch Exp $
|
||||
*/
|
||||
|
||||
char *inetntoa(in)
|
||||
char *in;
|
||||
{
|
||||
static char buf[16];
|
||||
Reg1 u_char *s = (u_char *)in;
|
||||
Reg2 int a,b,c,d;
|
||||
|
||||
a = (int)*s++;
|
||||
b = (int)*s++;
|
||||
c = (int)*s++;
|
||||
d = (int)*s++;
|
||||
(void) sprintf(buf, "%d.%d.%d.%d", a,b,c,d );
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef NEED_INET_NETOF
|
||||
/*
|
||||
** inet_netof -- return the net portion of an internet number
|
||||
** argv 11/90
|
||||
** $Id: support.c,v 1.1.1.1 1996/05/05 22:25:22 klmitch Exp $
|
||||
**
|
||||
*/
|
||||
|
||||
int inet_netof(in)
|
||||
struct in_addr in;
|
||||
{
|
||||
int addr = in.s_net;
|
||||
|
||||
if (addr & 0x80 == 0)
|
||||
return ((int) in.s_net);
|
||||
|
||||
if (addr & 0x40 == 0)
|
||||
return ((int) in.s_net * 256 + in.s_host);
|
||||
|
||||
return ((int) in.s_net * 256 + in.s_host * 256 + in.s_lh);
|
||||
}
|
||||
#endif /* NEED_INET_NETOF */
|
||||
|
||||
#ifdef DYNIXPTX
|
||||
/* This is copied from ircu3.0.0 (with permission), not vica versa. */
|
||||
int gettimeofday(tv, tz)
|
||||
struct timeval *tv;
|
||||
void *tz; /* Unused */
|
||||
{
|
||||
register int ret;
|
||||
static struct timespec tp;
|
||||
|
||||
if ((ret=getclock(TIMEOFDAY, &tp)))
|
||||
return ret;
|
||||
tv->tv_sec=(long)tp.tv_sec;
|
||||
tv->tv_usec=(tp.tv_nsec + 500) / 1000;
|
||||
return 0;
|
||||
}
|
||||
#endif /* DYNIXPTX */
|
||||
|
||||
#if defined(DEBUGMODE)
|
||||
void dumpcore(msg, p1, p2, p3, p4, p5, p6, p7, p8, p9)
|
||||
char *msg, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
|
||||
{
|
||||
static time_t lastd = 0;
|
||||
static int dumps = 0;
|
||||
char corename[12];
|
||||
time_t now;
|
||||
int p;
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
if (!lastd)
|
||||
lastd = now;
|
||||
else if (now - lastd < 60 && dumps > 2)
|
||||
(void)s_die();
|
||||
if (now - lastd > 60)
|
||||
{
|
||||
lastd = now;
|
||||
dumps = 1;
|
||||
}
|
||||
else
|
||||
dumps++;
|
||||
p = getpid();
|
||||
if (fork()>0) {
|
||||
kill(p, 3);
|
||||
kill(p, 9);
|
||||
}
|
||||
write_pidfile();
|
||||
(void)sprintf(corename, "core.%d", p);
|
||||
(void)rename("core", corename);
|
||||
Debug((DEBUG_FATAL, "Dumped core : core.%d", p));
|
||||
sendto_ops("Dumped core : core.%d", p);
|
||||
Debug((DEBUG_FATAL, msg, p1, p2, p3, p4, p5, p6, p7, p8, p9));
|
||||
sendto_ops(msg, p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||
(void)s_die();
|
||||
}
|
||||
|
||||
static char *marray[20000];
|
||||
static int mindex = 0;
|
||||
|
||||
#define SZ_EX (sizeof(char *) + sizeof(size_t) + 4)
|
||||
#define SZ_CHST (sizeof(char *) + sizeof(size_t))
|
||||
#define SZ_CH (sizeof(char *))
|
||||
#define SZ_ST (sizeof(size_t))
|
||||
|
||||
char *MyMalloc(x)
|
||||
size_t x;
|
||||
{
|
||||
register int i;
|
||||
register char **s;
|
||||
char *ret;
|
||||
|
||||
ret = (char *)malloc(x + (size_t)SZ_EX);
|
||||
|
||||
if (!ret)
|
||||
outofmemory();
|
||||
|
||||
bzero(ret, (int)x + SZ_EX);
|
||||
bcopy((char *)&ret, ret, SZ_CH);
|
||||
bcopy((char *)&x, ret + SZ_CH, SZ_ST);
|
||||
bcopy("VAVA", ret + SZ_CHST + (int)x, 4);
|
||||
Debug((DEBUG_MALLOC, "MyMalloc(%ld) = %#x", x, ret+8));
|
||||
for(i = 0, s = marray; *s && i < mindex; i++, s++)
|
||||
;
|
||||
if (i < 20000)
|
||||
{
|
||||
*s = ret;
|
||||
if (i == mindex)
|
||||
mindex++;
|
||||
}
|
||||
return ret + SZ_CHST;
|
||||
}
|
||||
|
||||
char *MyRealloc(x, y)
|
||||
char *x;
|
||||
size_t y;
|
||||
{
|
||||
register int l;
|
||||
register char **s;
|
||||
char *ret, *cp;
|
||||
size_t i;
|
||||
int k;
|
||||
|
||||
x -= SZ_CHST;
|
||||
bcopy(x, (char *)&cp, SZ_CH);
|
||||
bcopy(x + SZ_CH, (char *)&i, SZ_ST);
|
||||
bcopy(x + (int)i + SZ_CHST, (char *)&k, 4);
|
||||
if (bcmp((char *)&k, "VAVA", 4) || (x != cp))
|
||||
dumpcore("MyRealloc %#x %d %d %#x %#x", x, y, i, cp, k);
|
||||
ret = (char *)realloc(x, y + (size_t)SZ_EX);
|
||||
|
||||
if (!ret)
|
||||
outofmemory();
|
||||
|
||||
bcopy((char *)&ret, ret, SZ_CH);
|
||||
bcopy((char *)&y, ret + SZ_CH, SZ_ST);
|
||||
bcopy("VAVA", ret + SZ_CHST + (int)y, 4);
|
||||
Debug((DEBUG_NOTICE, "MyRealloc(%#x,%ld) = %#x", x, y, ret + SZ_CHST));
|
||||
for(l = 0, s = marray; *s != x && l < mindex; l++, s++)
|
||||
;
|
||||
if (l < mindex)
|
||||
*s = NULL;
|
||||
else if (l == mindex)
|
||||
Debug((DEBUG_MALLOC, "%#x !found", x));
|
||||
for(l = 0, s = marray; *s && l < mindex; l++,s++)
|
||||
;
|
||||
if (l < 20000)
|
||||
{
|
||||
*s = ret;
|
||||
if (l == mindex)
|
||||
mindex++;
|
||||
}
|
||||
return ret + SZ_CHST;
|
||||
}
|
||||
|
||||
void MyFree(x)
|
||||
char *x;
|
||||
{
|
||||
size_t i;
|
||||
char *j;
|
||||
u_char k[4];
|
||||
register int l;
|
||||
register char **s;
|
||||
|
||||
if (!x)
|
||||
return;
|
||||
x -= SZ_CHST;
|
||||
|
||||
bcopy(x, (char *)&j, SZ_CH);
|
||||
bcopy(x + SZ_CH, (char *)&i, SZ_ST);
|
||||
bcopy(x + SZ_CHST + (int)i, (char *)k, 4);
|
||||
|
||||
if (bcmp((char *)k, "VAVA", 4) || (j != x))
|
||||
dumpcore("MyFree %#x %ld %#x %#x", x, i, j,
|
||||
(k[3]<<24) | (k[2]<<16) | (k[1]<<8) | k[0]);
|
||||
|
||||
#undef free
|
||||
(void)free(x);
|
||||
#define free(x) MyFree(x)
|
||||
Debug((DEBUG_MALLOC, "MyFree(%#x)",x + SZ_CHST));
|
||||
|
||||
for (l = 0, s = marray; *s != x && l < mindex; l++, s++)
|
||||
;
|
||||
if (l < mindex)
|
||||
*s = NULL;
|
||||
else if (l == mindex)
|
||||
Debug((DEBUG_MALLOC, "%#x !found", x));
|
||||
}
|
||||
|
||||
#else
|
||||
char *MyMalloc(x)
|
||||
size_t x;
|
||||
{
|
||||
char *ret = (char *)malloc(x);
|
||||
|
||||
if (!ret)
|
||||
outofmemory();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *MyRealloc(x, y)
|
||||
char *x;
|
||||
size_t y;
|
||||
{
|
||||
char *ret = (char *)realloc(x, y);
|
||||
|
||||
if (!ret)
|
||||
outofmemory();
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** read a string terminated by \r or \n in from a fd
|
||||
**
|
||||
** Created: Sat Dec 12 06:29:58 EST 1992 by avalon
|
||||
** Returns:
|
||||
** 0 - EOF
|
||||
** -1 - error on read
|
||||
** >0 - number of bytes returned (<=num)
|
||||
** After opening a fd, it is necessary to init dgets() by calling it as
|
||||
** dgets(x,y,0);
|
||||
** to mark the buffer as being empty.
|
||||
*/
|
||||
int dgets(fd, buf, num)
|
||||
int fd, num;
|
||||
char *buf;
|
||||
{
|
||||
static char dgbuf[8192];
|
||||
static char *head = dgbuf, *tail = dgbuf;
|
||||
register char *s, *t;
|
||||
register int n, nr;
|
||||
|
||||
/*
|
||||
** Sanity checks.
|
||||
*/
|
||||
if (head == tail)
|
||||
*head = '\0';
|
||||
if (!num)
|
||||
{
|
||||
head = tail = dgbuf;
|
||||
*head = '\0';
|
||||
return 0;
|
||||
}
|
||||
if (num > sizeof(dgbuf) - 1)
|
||||
num = sizeof(dgbuf) - 1;
|
||||
dgetsagain:
|
||||
if (head > dgbuf)
|
||||
{
|
||||
for (nr = tail - head, s = head, t = dgbuf; nr > 0; nr--)
|
||||
*t++ = *s++;
|
||||
tail = t;
|
||||
head = dgbuf;
|
||||
}
|
||||
/*
|
||||
** check input buffer for EOL and if present return string.
|
||||
*/
|
||||
if (head < tail &&
|
||||
((s = index(head, '\n')) || (s = index(head, '\r'))) && s < tail)
|
||||
{
|
||||
n = MIN(s - head + 1, num); /* at least 1 byte */
|
||||
dgetsreturnbuf:
|
||||
bcopy(head, buf, n);
|
||||
head += n;
|
||||
if (head == tail)
|
||||
head = tail = dgbuf;
|
||||
return n;
|
||||
}
|
||||
|
||||
if (tail - head >= num) /* dgets buf is big enough */
|
||||
{
|
||||
n = num;
|
||||
goto dgetsreturnbuf;
|
||||
}
|
||||
|
||||
n = sizeof(dgbuf) - (tail - dgbuf) - 1;
|
||||
nr = read(fd, tail, n);
|
||||
if (nr == -1)
|
||||
{
|
||||
head = tail = dgbuf;
|
||||
return -1;
|
||||
}
|
||||
if (!nr)
|
||||
{
|
||||
if (head < tail)
|
||||
{
|
||||
n = MIN(tail - head, num);
|
||||
goto dgetsreturnbuf;
|
||||
}
|
||||
head = tail = dgbuf;
|
||||
return 0;
|
||||
}
|
||||
tail += nr;
|
||||
*tail = '\0';
|
||||
for (t = head; (s = index(t, '\n')); )
|
||||
{
|
||||
if ((s > head) && (s > dgbuf))
|
||||
{
|
||||
t = s-1;
|
||||
for (nr = 0; *t == '\\'; nr++)
|
||||
t--;
|
||||
if (nr & 1)
|
||||
{
|
||||
t = s+1;
|
||||
s--;
|
||||
nr = tail - t;
|
||||
while (nr--)
|
||||
*s++ = *t++;
|
||||
tail -= 2;
|
||||
*tail = '\0';
|
||||
}
|
||||
else
|
||||
s++;
|
||||
}
|
||||
else
|
||||
s++;
|
||||
t = s;
|
||||
}
|
||||
*tail = '\0';
|
||||
goto dgetsagain;
|
||||
}
|
||||
Reference in New Issue
Block a user