This commit is contained in:
2023-12-26 16:40:53 -05:00
commit ab64084f63
93 changed files with 40857 additions and 0 deletions

63
common/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}