From 4005d211b7dbfa996eb046a6109d41d19bfd66f2 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 1 Apr 2008 19:35:46 -0500 Subject: [PATCH] libratbox is the new libcharybdis... thanks to androsyn and jilles on making something sane where previous attempts failed. ;) --- libcharybdis/Makefile.in | 87 ---- libcharybdis/balloc.c | 652 ------------------------ libcharybdis/balloc.h | 112 ---- libcharybdis/commio.c | 911 --------------------------------- libcharybdis/commio.h | 208 -------- libcharybdis/epoll.c | 263 ---------- libcharybdis/event.c | 352 ------------- libcharybdis/event.h | 64 --- libcharybdis/kqueue.c | 287 ----------- libcharybdis/libcharybdis.c | 91 ---- libcharybdis/libcharybdis.h | 48 -- libcharybdis/linebuf.c | 686 ------------------------- libcharybdis/linebuf.h | 87 ---- libcharybdis/memory.c | 75 --- libcharybdis/memory.h | 79 --- libcharybdis/poll.c | 305 ----------- libcharybdis/ports.c | 180 ------- libcharybdis/select.c | 202 -------- libcharybdis/snprintf.c | 981 ------------------------------------ libcharybdis/tools.c | 99 ---- libcharybdis/tools.h | 378 -------------- 21 files changed, 6147 deletions(-) delete mode 100644 libcharybdis/Makefile.in delete mode 100644 libcharybdis/balloc.c delete mode 100644 libcharybdis/balloc.h delete mode 100644 libcharybdis/commio.c delete mode 100644 libcharybdis/commio.h delete mode 100644 libcharybdis/epoll.c delete mode 100644 libcharybdis/event.c delete mode 100644 libcharybdis/event.h delete mode 100644 libcharybdis/kqueue.c delete mode 100644 libcharybdis/libcharybdis.c delete mode 100644 libcharybdis/libcharybdis.h delete mode 100644 libcharybdis/linebuf.c delete mode 100644 libcharybdis/linebuf.h delete mode 100644 libcharybdis/memory.c delete mode 100644 libcharybdis/memory.h delete mode 100644 libcharybdis/poll.c delete mode 100644 libcharybdis/ports.c delete mode 100644 libcharybdis/select.c delete mode 100644 libcharybdis/snprintf.c delete mode 100644 libcharybdis/tools.c delete mode 100644 libcharybdis/tools.h diff --git a/libcharybdis/Makefile.in b/libcharybdis/Makefile.in deleted file mode 100644 index e5023a9..0000000 --- a/libcharybdis/Makefile.in +++ /dev/null @@ -1,87 +0,0 @@ -# -# Makefile.in for ircd/src/io -# -# $Id: Makefile.in 1269 2006-04-30 16:51:11Z nenolod $ -# -CC = @CC@ -INSTALL = @INSTALL@ -INSTALL_BIN = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_SUID = @INSTALL_PROGRAM@ -o root -m 4755 -RM = @RM@ -LEX = @LEX@ -LEXLIB = @LEXLIB@ -CFLAGS = @IRC_CFLAGS@ -DIRCD_PREFIX=\"@prefix@\" -LDFLAGS = @LDFLAGS@ -MKDEP = @MKDEP@ -DIRCD_PREFIX=\"@prefix@\" -MV = @MV@ -RM = @RM@ -YACC = @YACC@ -AR = @AR@ -RANLIB = @RANLIB@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -libexecdir = @libexecdir@ -sysconfdir = @sysconfdir@ -localstatedir = @localstatedir@ -# Change this later! -- adrian -moduledir = @prefix@/modules -automoduledir = @prefix@/modules/autoload - -INCLUDES = -I../include -I../adns -I. -CPPFLAGS = ${INCLUDES} @CPPFLAGS@ - -default: all - -BASE_SRCS = \ - balloc.c \ - commio.c \ - event.c \ - libcharybdis.c \ - linebuf.c \ - memory.c \ - snprintf.c \ - tools.c - -SRCS = ${BASE_SRCS} @SELECT_TYPE@.c - -OBJS = ${SRCS:.c=.o} - -all: libcharybdis.a - -build: all - -libcharybdis.a: ${OBJS} - rm -f $@ - ${AR} cqv $@ ${OBJS} - ${RANLIB} $@ - -# this is really the default rule for c files -.c.o: - ${CC} ${CPPFLAGS} ${CFLAGS} -c $< - -.PHONY: depend clean distclean - -install: - -depend: - @${MKDEP} ${CPPFLAGS} ${BASE_SRCS} ${EXTRA_SRCS} > .depend.tmp - @sed -e '/^# DO NOT DELETE THIS LINE/,$$d' Makefile.depend - @echo '# DO NOT DELETE THIS LINE!!!' >>Makefile.depend - @echo '# make depend needs it.' >>Makefile.depend - @cat .depend.tmp >>Makefile.depend - @mv Makefile.depend Makefile - @rm -f .depend.tmp - -clean: - ${RM} -f *.o *.exe *~ libcharybdis.a - -lint: - -distclean: clean - ${RM} -f Makefile version.c.last - -# DO NOT DELETE THIS LINE!!! -# make depend needs it. diff --git a/libcharybdis/balloc.c b/libcharybdis/balloc.c deleted file mode 100644 index c3f0bbe..0000000 --- a/libcharybdis/balloc.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * balloc.c: A block allocator. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * File: blalloc.c - * Owner: Wohali (Joan Touzet) - * - * Modified 2001/11/29 for mmap() support by Aaron Sethman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: balloc.c 388 2005-12-07 16:34:40Z nenolod $ - */ - -/* - * About the block allocator - * - * Basically we have three ways of getting memory off of the operating - * system. Below are this list of methods and the order of preference. - * - * 1. mmap() anonymous pages with the MMAP_ANON flag. - * 2. mmap() via the /dev/zero trick. - * 3. malloc() - * - * The advantages of 1 and 2 are this. We can munmap() the pages which will - * return the pages back to the operating system, thus reducing the size - * of the process as the memory is unused. malloc() on many systems just keeps - * a heap of memory to itself, which never gets given back to the OS, except on - * exit. This of course is bad, if say we have an event that causes us to allocate - * say, 200MB of memory, while our normal memory consumption would be 15MB. In the - * malloc() case, the amount of memory allocated to our process never goes down, as - * malloc() has it locked up in its heap. With the mmap() method, we can munmap() - * the block and return it back to the OS, thus causing our memory consumption to go - * down after we no longer need it. - * - * Of course it is up to the caller to make sure BlockHeapGarbageCollect() gets - * called periodically to do this cleanup, otherwise you'll keep the memory in the - * process. - * - * - */ - -#include "stdinc.h" -#include "libcharybdis.h" - -#define WE_ARE_MEMORY_C -#include "setup.h" -#include "balloc.h" -#ifndef NOBALLOC - -#include "ircd_defs.h" /* DEBUG_BLOCK_ALLOCATOR */ -#include "ircd.h" -#include "memory.h" -#include "irc_string.h" -#include "tools.h" -#include "s_log.h" -#include "client.h" -#include "event.h" - -#ifdef HAVE_MMAP /* We've got mmap() that is good */ -#include -/* HP-UX sucks */ -#ifdef MAP_ANONYMOUS -#ifndef MAP_ANON -#define MAP_ANON MAP_ANONYMOUS -#endif -#endif -#endif - -static int newblock(BlockHeap * bh); -static int BlockHeapGarbageCollect(BlockHeap *); -static void block_heap_gc(void *unused); -static dlink_list heap_lists; - -#if defined(HAVE_MMAP) && !defined(MAP_ANON) -static int zero_fd = -1; -#endif - -#define blockheap_fail(x) _blockheap_fail(x, __FILE__, __LINE__) - -static void -_blockheap_fail(const char *reason, const char *file, int line) -{ - libcharybdis_log("Blockheap failure: %s (%s:%d)", reason, file, line); - abort(); -} - - -/* - * static inline void free_block(void *ptr, size_t size) - * - * Inputs: The block and its size - * Output: None - * Side Effects: Returns memory for the block back to the OS - */ -static inline void -free_block(void *ptr, size_t size) -{ -#ifdef HAVE_MMAP - munmap(ptr, size); -#else - free(ptr); -#endif -} - -#ifdef DEBUG_BALLOC -/* Check the list length the very slow way */ -static unsigned long -slow_list_length(dlink_list *list) -{ - dlink_node *ptr; - unsigned long count = 0; - - for (ptr = list->head; ptr; ptr = ptr->next) - { - count++; - if(count > list->length * 2) - { - blockheap_fail("count > list->length * 2 - I give up"); - } - } - return count; -} - -static void -bh_sanity_check_block(BlockHeap *bh, Block *block) -{ - unsigned long s_used, s_free; - s_used = slow_list_length(&block->used_list); - s_free = slow_list_length(&block->free_list); - if(s_used != dlink_list_length(&block->used_list)) - blockheap_fail("used link count doesn't match head count"); - if(s_free != dlink_list_length(&block->free_list)) - blockheap_fail("free link count doesn't match head count"); - - if(dlink_list_length(&block->used_list) + dlink_list_length(&block->free_list) != bh->elemsPerBlock) - blockheap_fail("used_list + free_list != elemsPerBlock"); -} - -#if 0 -/* See how confused we are */ -static void -bh_sanity_check(BlockHeap *bh) -{ - Block *walker; - unsigned long real_alloc = 0; - unsigned long s_used, s_free; - unsigned long blockcount = 0; - unsigned long allocated; - if(bh == NULL) - blockheap_fail("Trying to sanity check a NULL block"); - - allocated = bh->blocksAllocated * bh->elemsPerBlock; - - for(walker = bh->base; walker != NULL; walker = walker->next) - { - blockcount++; - s_used = slow_list_length(&walker->used_list); - s_free = slow_list_length(&walker->free_list); - - if(s_used != dlink_list_length(&walker->used_list)) - blockheap_fail("used link count doesn't match head count"); - if(s_free != dlink_list_length(&walker->free_list)) - blockheap_fail("free link count doesn't match head count"); - - if(dlink_list_length(&walker->used_list) + dlink_list_length(&walker->free_list) != bh->elemsPerBlock) - blockheap_fail("used_list + free_list != elemsPerBlock"); - - real_alloc += dlink_list_length(&walker->used_list); - real_alloc += dlink_list_length(&walker->free_list); - } - - if(allocated != real_alloc) - blockheap_fail("block allocations don't match heap"); - - if(bh->blocksAllocated != blockcount) - blockheap_fail("blocksAllocated don't match blockcount"); - - -} - -static void -bh_sanity_check_all(void *unused) -{ - dlink_node *ptr; - DLINK_FOREACH(ptr, heap_lists.head) - { - bh_sanity_check(ptr->data); - } -} -#endif - -#endif - - - -/* - * void initBlockHeap(void) - * - * Inputs: None - * Outputs: None - * Side Effects: Initializes the block heap - */ - -void -initBlockHeap(void) -{ -#if defined(HAVE_MMAP) && !defined(MAP_ANON) - zero_fd = open("/dev/zero", O_RDWR); - - if(zero_fd < 0) - blockheap_fail("Failed opening /dev/zero"); - comm_socket(zero_fd, FD_FILE, "Anonymous mmap()"); -#endif - eventAddIsh("block_heap_gc", block_heap_gc, NULL, 30); -} - -/* - * static inline void *get_block(size_t size) - * - * Input: Size of block to allocate - * Output: Pointer to new block - * Side Effects: None - */ -static inline void * -get_block(size_t size) -{ - void *ptr; -#ifdef HAVE_MMAP -#ifdef MAP_ANON - ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); -#else - ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0); -#endif - if(ptr == MAP_FAILED) - { - ptr = NULL; - } -#else - ptr = malloc(size); -#endif - return (ptr); -} - - -static void -block_heap_gc(void *unused) -{ - dlink_node *ptr; - DLINK_FOREACH(ptr, heap_lists.head) - { - BlockHeapGarbageCollect(ptr->data); - } -} - -/* ************************************************************************ */ -/* FUNCTION DOCUMENTATION: */ -/* newblock */ -/* Description: */ -/* Allocates a new block for addition to a blockheap */ -/* Parameters: */ -/* bh (IN): Pointer to parent blockheap. */ -/* Returns: */ -/* 0 if successful, 1 if not */ -/* ************************************************************************ */ - -static int -newblock(BlockHeap * bh) -{ - MemBlock *newblk; - Block *b; - unsigned long i; - void *offset; - - /* Setup the initial data structure. */ - b = (Block *) calloc(1, sizeof(Block)); - if(b == NULL) - { - return (1); - } - b->free_list.head = b->free_list.tail = NULL; - b->used_list.head = b->used_list.tail = NULL; - b->next = bh->base; - - b->alloc_size = (bh->elemsPerBlock + 1) * (bh->elemSize + sizeof(MemBlock)); - - b->elems = get_block(b->alloc_size); - if(b->elems == NULL) - { - return (1); - } - offset = b->elems; - /* Setup our blocks now */ - for (i = 0; i < bh->elemsPerBlock; i++) - { - void *data; - newblk = (void *) offset; - newblk->block = b; -#ifdef DEBUG_BALLOC - newblk->magic = BALLOC_MAGIC; -#endif - data = (void *) ((size_t) offset + sizeof(MemBlock)); - newblk->block = b; - dlinkAdd(data, &newblk->self, &b->free_list); - offset = (unsigned char *) ((unsigned char *) offset + - bh->elemSize + sizeof(MemBlock)); - } - - ++bh->blocksAllocated; - bh->freeElems += bh->elemsPerBlock; - bh->base = b; - - return (0); -} - - -/* ************************************************************************ */ -/* FUNCTION DOCUMENTATION: */ -/* BlockHeapCreate */ -/* Description: */ -/* Creates a new blockheap from which smaller blocks can be allocated. */ -/* Intended to be used instead of multiple calls to malloc() when */ -/* performance is an issue. */ -/* Parameters: */ -/* elemsize (IN): Size of the basic element to be stored */ -/* elemsperblock (IN): Number of elements to be stored in a single block */ -/* of memory. When the blockheap runs out of free memory, it will */ -/* allocate elemsize * elemsperblock more. */ -/* Returns: */ -/* Pointer to new BlockHeap, or NULL if unsuccessful */ -/* ************************************************************************ */ -BlockHeap * -BlockHeapCreate(size_t elemsize, int elemsperblock) -{ - BlockHeap *bh; - s_assert(elemsize > 0 && elemsperblock > 0); - - /* Catch idiotic requests up front */ - if((elemsize <= 0) || (elemsperblock <= 0)) - { - blockheap_fail("Attempting to BlockHeapCreate idiotic sizes"); - } - - /* Allocate our new BlockHeap */ - bh = (BlockHeap *) calloc(1, sizeof(BlockHeap)); - if(bh == NULL) - { - blockheap_fail("Attempt to calloc() failed"); - outofmemory(); /* die.. out of memory */ - } - - if((elemsize % sizeof(void *)) != 0) - { - /* Pad to even pointer boundary */ - elemsize += sizeof(void *); - elemsize &= ~(sizeof(void *) - 1); - } - - bh->elemSize = elemsize; - bh->elemsPerBlock = elemsperblock; - bh->blocksAllocated = 0; - bh->freeElems = 0; - bh->base = NULL; - - /* Be sure our malloc was successful */ - if(newblock(bh)) - { - if(bh != NULL) - free(bh); - libcharybdis_restart("Aiee! -- newblock() failed!!!"); - } - - if(bh == NULL) - { - blockheap_fail("bh == NULL when it shouldn't be"); - } - dlinkAdd(bh, &bh->hlist, &heap_lists); - return (bh); -} - -/* ************************************************************************ */ -/* FUNCTION DOCUMENTATION: */ -/* BlockHeapAlloc */ -/* Description: */ -/* Returns a pointer to a struct within our BlockHeap that's free for */ -/* the taking. */ -/* Parameters: */ -/* bh (IN): Pointer to the Blockheap. */ -/* Returns: */ -/* Pointer to a structure (void *), or NULL if unsuccessful. */ -/* ************************************************************************ */ - -void * -BlockHeapAlloc(BlockHeap * bh) -{ - Block *walker; - dlink_node *new_node; - - s_assert(bh != NULL); - if(bh == NULL) - { - blockheap_fail("Cannot allocate if bh == NULL"); - } - - if(bh->freeElems == 0) - { - /* Allocate new block and assign */ - /* newblock returns 1 if unsuccessful, 0 if not */ - - if(newblock(bh)) - { - /* That didn't work..try to garbage collect */ - BlockHeapGarbageCollect(bh); - if(bh->freeElems == 0) - { - libcharybdis_restart("newblock() failed and garbage collection didn't help"); - } - } - } - - for (walker = bh->base; walker != NULL; walker = walker->next) - { - if(dlink_list_length(&walker->free_list) > 0) - { -#ifdef DEBUG_BALLOC - bh_sanity_check_block(bh, walker); -#endif - bh->freeElems--; - new_node = walker->free_list.head; - dlinkMoveNode(new_node, &walker->free_list, &walker->used_list); - s_assert(new_node->data != NULL); - if(new_node->data == NULL) - blockheap_fail("new_node->data is NULL and that shouldn't happen!!!"); - memset(new_node->data, 0, bh->elemSize); -#ifdef DEBUG_BALLOC - do - { - struct MemBlock *memblock = (void *) ((size_t) new_node->data - sizeof(MemBlock)); - if(memblock->magic == BALLOC_FREE_MAGIC) - memblock->magic = BALLOC_MAGIC; - - } while(0); - bh_sanity_check_block(bh, walker); -#endif - return (new_node->data); - } - } - blockheap_fail("BlockHeapAlloc failed, giving up"); - return NULL; -} - - -/* ************************************************************************ */ -/* FUNCTION DOCUMENTATION: */ -/* BlockHeapFree */ -/* Description: */ -/* Returns an element to the free pool, does not free() */ -/* Parameters: */ -/* bh (IN): Pointer to BlockHeap containing element */ -/* ptr (in): Pointer to element to be "freed" */ -/* Returns: */ -/* 0 if successful, 1 if element not contained within BlockHeap. */ -/* ************************************************************************ */ -int -BlockHeapFree(BlockHeap * bh, void *ptr) -{ - Block *block; - struct MemBlock *memblock; - - s_assert(bh != NULL); - s_assert(ptr != NULL); - - if(bh == NULL) - { - libcharybdis_restart("balloc.c:BlockHeapFree() bh == NULL"); - return (1); - } - - if(ptr == NULL) - { - libcharybdis_restart("balloc.BlockHeapFree() ptr == NULL"); - return (1); - } - - memblock = (void *) ((size_t) ptr - sizeof(MemBlock)); -#ifdef DEBUG_BALLOC - if(memblock->magic == BALLOC_FREE_MAGIC) - { - blockheap_fail("double free of a block"); - outofmemory(); - } else - if(memblock->magic != BALLOC_MAGIC) - { - blockheap_fail("memblock->magic != BALLOC_MAGIC"); - outofmemory(); - } -#endif - s_assert(memblock->block != NULL); - if(memblock->block == NULL) - { - blockheap_fail("memblock->block == NULL, not a valid block?"); - outofmemory(); - } - - block = memblock->block; -#ifdef DEBUG_BALLOC - bh_sanity_check_block(bh, block); -#endif - bh->freeElems++; - mem_frob(ptr, bh->elemSize); - dlinkMoveNode(&memblock->self, &block->used_list, &block->free_list); -#ifdef DEBUG_BALLOC - bh_sanity_check_block(bh, block); -#endif - return (0); -} - -/* ************************************************************************ */ -/* FUNCTION DOCUMENTATION: */ -/* BlockHeapGarbageCollect */ -/* Description: */ -/* Performs garbage collection on the block heap. Any blocks that are */ -/* completely unallocated are removed from the heap. Garbage collection */ -/* will never remove the root node of the heap. */ -/* Parameters: */ -/* bh (IN): Pointer to the BlockHeap to be cleaned up */ -/* Returns: */ -/* 0 if successful, 1 if bh == NULL */ -/* ************************************************************************ */ -static int -BlockHeapGarbageCollect(BlockHeap * bh) -{ - Block *walker, *last; - if(bh == NULL) - { - return (1); - } - - if(bh->freeElems < bh->elemsPerBlock || bh->blocksAllocated == 1) - { - /* There couldn't possibly be an entire free block. Return. */ - return (0); - } - - last = NULL; - walker = bh->base; - - while (walker != NULL) - { - if((dlink_list_length(&walker->free_list) == bh->elemsPerBlock) != 0) - { - free_block(walker->elems, walker->alloc_size); - if(last != NULL) - { - last->next = walker->next; - if(walker != NULL) - free(walker); - walker = last->next; - } - else - { - bh->base = walker->next; - if(walker != NULL) - free(walker); - walker = bh->base; - } - bh->blocksAllocated--; - bh->freeElems -= bh->elemsPerBlock; - } - else - { - last = walker; - walker = walker->next; - } - } - return (0); -} - -/* ************************************************************************ */ -/* FUNCTION DOCUMENTATION: */ -/* BlockHeapDestroy */ -/* Description: */ -/* Completely free()s a BlockHeap. Use for cleanup. */ -/* Parameters: */ -/* bh (IN): Pointer to the BlockHeap to be destroyed. */ -/* Returns: */ -/* 0 if successful, 1 if bh == NULL */ -/* ************************************************************************ */ -int -BlockHeapDestroy(BlockHeap * bh) -{ - Block *walker, *next; - - if(bh == NULL) - { - return (1); - } - - for (walker = bh->base; walker != NULL; walker = next) - { - next = walker->next; - free_block(walker->elems, walker->alloc_size); - if(walker != NULL) - free(walker); - } - dlinkDelete(&bh->hlist, &heap_lists); - free(bh); - return (0); -} - -void -BlockHeapUsage(BlockHeap * bh, size_t * bused, size_t * bfree, size_t * bmemusage) -{ - size_t used; - size_t freem; - size_t memusage; - if(bh == NULL) - { - return; - } - - freem = bh->freeElems; - used = (bh->blocksAllocated * bh->elemsPerBlock) - bh->freeElems; - memusage = used * (bh->elemSize + sizeof(MemBlock)); - - if(bused != NULL) - *bused = used; - if(bfree != NULL) - *bfree = freem; - if(bmemusage != NULL) - *bmemusage = memusage; -} - -#endif /* NOBALLOC */ - diff --git a/libcharybdis/balloc.h b/libcharybdis/balloc.h deleted file mode 100644 index 32fb066..0000000 --- a/libcharybdis/balloc.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * balloc.h: The ircd block allocator header. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2004 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: balloc.h 1781 2006-07-30 18:07:38Z jilles $ - */ - -#ifndef INCLUDED_blalloc_h -#define INCLUDED_blalloc_h - -#include "setup.h" -#include "tools.h" -#include "memory.h" -#include "ircd_defs.h" - -#define CACHEFILE_HEAP_SIZE 32 -#define CACHELINE_HEAP_SIZE 64 - - -#ifdef NOBALLOC - -typedef struct BlockHeap BlockHeap; -#define initBlockHeap() -#define BlockHeapGarbageCollect(x) -#define BlockHeapCreate(es, epb) ((BlockHeap*)(es)) -#define BlockHeapDestroy(x) -#define BlockHeapAlloc(x) MyMalloc((int)x) -#define BlockHeapFree(x,y) MyFree(y) -#define BlockHeapUsage(bh, bused, bfree, bmemusage) do { if (bused) (*(size_t *)bused) = 0; if (bfree) *((size_t *)bfree) = 0; if (bmemusage) *((size_t *)bmemusage) = 0; } while(0) -typedef struct MemBlock -{ - void *dummy; -} MemBlock; - -#else - -#undef DEBUG_BALLOC - -#ifdef DEBUG_BALLOC -#define BALLOC_MAGIC 0x3d3a3c3d -#define BALLOC_FREE_MAGIC 0xafafafaf -#endif - -/* status information for an allocated block in heap */ -struct Block -{ - size_t alloc_size; - struct Block *next; /* Next in our chain of blocks */ - void *elems; /* Points to allocated memory */ - dlink_list free_list; - dlink_list used_list; -}; -typedef struct Block Block; - -struct MemBlock -{ -#ifdef DEBUG_BALLOC - unsigned long magic; -#endif - dlink_node self; - Block *block; /* Which block we belong to */ -}; - -typedef struct MemBlock MemBlock; - -/* information for the root node of the heap */ -struct BlockHeap -{ - dlink_node hlist; - size_t elemSize; /* Size of each element to be stored */ - unsigned long elemsPerBlock; /* Number of elements per block */ - unsigned long blocksAllocated; /* Number of blocks allocated */ - unsigned long freeElems; /* Number of free elements */ - Block *base; /* Pointer to first block */ -}; -typedef struct BlockHeap BlockHeap; - -extern int BlockHeapFree(BlockHeap * bh, void *ptr); -extern void *BlockHeapAlloc(BlockHeap * bh); - -extern BlockHeap *BlockHeapCreate(size_t elemsize, int elemsperblock); -extern int BlockHeapDestroy(BlockHeap * bh); - -extern void initBlockHeap(void); -extern void BlockHeapUsage(BlockHeap * bh, size_t * bused, size_t * bfree, size_t * bmemusage); - - - -#endif /* NOBALLOC */ - - - -#endif /* INCLUDED_blalloc_h */ diff --git a/libcharybdis/commio.c b/libcharybdis/commio.c deleted file mode 100644 index c7dfe1a..0000000 --- a/libcharybdis/commio.c +++ /dev/null @@ -1,911 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * commio.c: Network/file related functions - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: commio.c 3354 2007-04-03 09:21:31Z nenolod $ - */ - -#include "libcharybdis.h" - -#ifndef IN_LOOPBACKNET -#define IN_LOOPBACKNET 0x7f -#endif - -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned int) 0xffffffff) -#endif - -const char *const NONB_ERROR_MSG = "set_non_blocking failed for %s:%s"; -const char *const SETBUF_ERROR_MSG = "set_sock_buffers failed for server %s:%s"; - -static const char *comm_err_str[] = { "Comm OK", "Error during bind()", - "Error during DNS lookup", "connect timeout", - "Error during connect()", - "Comm Error" -}; - -#define FD_HASH_SIZE 128 -static dlink_list fd_table[FD_HASH_SIZE]; - -static void fdlist_update_biggest(int fd, int opening); - -/* Highest FD and number of open FDs .. */ -int highest_fd = -1; /* Its -1 because we haven't started yet -- adrian */ -int number_fd = 0; - -static void comm_connect_callback(int fd, int status); -static PF comm_connect_timeout; -static void comm_connect_dns_callback(void *vptr, struct DNSReply *reply); -static PF comm_connect_tryconnect; -static int comm_max_connections = 0; - -static int -comm_read_raw(fde_t *F, void *buf, size_t count) -{ - s_assert(F != NULL); - s_assert(buf != NULL); - s_assert(count > 0); - - return read(F->fd, buf, count); -} - -static int -comm_write_raw(fde_t *F, const void *buf, size_t count) -{ - s_assert(F != NULL); - s_assert(buf != NULL); - s_assert(count > 0); - - return write(F->fd, buf, count); -} - -inline fde_t * -comm_locate_fd(int fd) -{ - int bucket = fd % FD_HASH_SIZE; - dlink_list *list = &fd_table[bucket]; - dlink_node *n; - - DLINK_FOREACH(n, list->head) - { - fde_t *F = (fde_t *) n->data; - - if (F->fd == fd) - return F; - } - - return NULL; -} - -inline fde_t * -comm_add_fd(int fd) -{ - fde_t *F = comm_locate_fd(fd); - dlink_list *list; - - if (F != NULL) - return F; - - F = MyMalloc(sizeof(fde_t)); - F->fd = fd; - - F->read_impl = comm_read_raw; - F->write_impl = comm_write_raw; - - list = &fd_table[fd % FD_HASH_SIZE]; - dlinkAdd(F, &F->node, list); - - return F; -} - -inline void -comm_remove_fd(int fd) -{ - int bucket = fd % FD_HASH_SIZE; - fde_t *F; - dlink_list *list = &fd_table[bucket]; - - F = comm_locate_fd(fd); - if (F == NULL) - return; - - dlinkDelete(&F->node, list); - MyFree(F); -} - -/* 32bit solaris is kinda slow and stdio only supports fds < 256 - * so we got to do this crap below. - * (BTW Fuck you Sun, I hate your guts and I hope you go bankrupt soon) - * XXX: this is no longer needed in Solaris 10. --nenolod - */ -#if defined (__SVR4) && defined (__sun) -static void comm_fd_hack(int *fd) -{ - int newfd; - if(*fd > 256 || *fd < 0) - return; - if((newfd = fcntl(*fd, F_DUPFD, 256)) != -1) - { - close(*fd); - *fd = newfd; - } - return; -} -#else -#define comm_fd_hack(fd) -#endif - - -/* close_all_connections() can be used *before* the system come up! */ - -void -comm_close_all(void) -{ - int i; -#ifndef NDEBUG - int fd; -#endif - - /* - * we start at 4 to avoid giving fds where malloc messages - * could be written --nenolod - */ - for (i = 4; i < comm_max_connections; ++i) - { - fde_t *F = comm_locate_fd(i); - - if(F != NULL && F->flags.open) - comm_close(i); - else - close(i); - } - - /* XXX should his hack be done in all cases? */ -#ifndef NDEBUG - /* fugly hack to reserve fd == 2 */ - (void) close(2); - fd = open("stderr.log", O_WRONLY | O_CREAT | O_APPEND, 0644); - if(fd >= 0) - { - dup2(fd, 2); - close(fd); - } -#endif -} - -/* - * get_sockerr - get the error value from the socket or the current errno - * - * Get the *real* error from the socket (well try to anyway..). - * This may only work when SO_DEBUG is enabled but its worth the - * gamble anyway. - */ -int -comm_get_sockerr(int fd) -{ - int errtmp = errno; -#ifdef SO_ERROR - int err = 0; - socklen_t len = sizeof(err); - - if(-1 < fd && !getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *) &err, (socklen_t *) & len)) - { - if(err) - errtmp = err; - } - errno = errtmp; -#endif - return errtmp; -} - -/* - * set_sock_buffers - set send and receive buffers for socket - * - * inputs - fd file descriptor - * - size to set - * output - returns true (1) if successful, false (0) otherwise - * side effects - - */ -int -comm_set_buffers(int fd, int size) -{ - if(setsockopt - (fd, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof(size)) - || setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &size, sizeof(size))) - return 0; - return 1; -} - -/* - * set_non_blocking - Set the client connection into non-blocking mode. - * - * inputs - fd to set into non blocking mode - * output - 1 if successful 0 if not - * side effects - use POSIX compliant non blocking and - * be done with it. - */ -int -comm_set_nb(int fd) -{ - int nonb = 0; - int res; - fde_t *F = comm_locate_fd(fd); - - nonb |= O_NONBLOCK; - res = fcntl(fd, F_GETFL, 0); - if(-1 == res || fcntl(fd, F_SETFL, res | nonb) == -1) - return 0; - - if (F != NULL) - F->flags.nonblocking = 1; - - return 1; -} - - -/* - * stolen from squid - its a neat (but overused! :) routine which we - * can use to see whether we can ignore this errno or not. It is - * generally useful for non-blocking network IO related errnos. - * -- adrian - */ -int -ignoreErrno(int ierrno) -{ - switch (ierrno) - { - case EINPROGRESS: - case EWOULDBLOCK: -#if EAGAIN != EWOULDBLOCK - case EAGAIN: -#endif - case EALREADY: - case EINTR: -#ifdef ERESTART - case ERESTART: -#endif - return 1; - default: - return 0; - } -} - - -/* - * comm_settimeout() - set the socket timeout - * - * Set the timeout for the fd - */ -void -comm_settimeout(int fd, time_t timeout, PF * callback, void *cbdata) -{ - fde_t *F; - s_assert(fd >= 0); - F = comm_locate_fd(fd); - s_assert(F->flags.open); - - F->timeout = CurrentTime + (timeout / 1000); - F->timeout_handler = callback; - F->timeout_data = cbdata; -} - - -/* - * comm_setflush() - set a flush function - * - * A flush function is simply a function called if found during - * comm_timeouts(). Its basically a second timeout, except in this case - * I'm too lazy to implement multiple timeout functions! :-) - * its kinda nice to have it seperate, since this is designed for - * flush functions, and when comm_close() is implemented correctly - * with close functions, we _actually_ don't call comm_close() here .. - */ -void -comm_setflush(int fd, time_t timeout, PF * callback, void *cbdata) -{ - fde_t *F; - s_assert(fd >= 0); - F = comm_locate_fd(fd); - s_assert(F->flags.open); - - F->flush_timeout = CurrentTime + (timeout / 1000); - F->flush_handler = callback; - F->flush_data = cbdata; -} - - -/* - * comm_checktimeouts() - check the socket timeouts - * - * All this routine does is call the given callback/cbdata, without closing - * down the file descriptor. When close handlers have been implemented, - * this will happen. - */ -void -comm_checktimeouts(void *notused) -{ - PF *hdl; - void *data; - fde_t *F; - dlink_list *bucket; - int i; - dlink_node *n, *n2; - - for (i = 0; i <= FD_HASH_SIZE; i++) - { - bucket = &fd_table[i]; - - if (dlink_list_length(bucket) <= 0) - continue; - - DLINK_FOREACH_SAFE(n, n2, bucket->head) - { - F = (fde_t *) n->data; - - if(F == NULL) - continue; - if(!F->flags.open) - continue; - if(F->flags.closing) - continue; - - /* check flush functions */ - if(F->flush_handler && - F->flush_timeout > 0 && F->flush_timeout < CurrentTime) - { - hdl = F->flush_handler; - data = F->flush_data; - comm_setflush(F->fd, 0, NULL, NULL); - hdl(F->fd, data); - } - - /* check timeouts */ - if(F->timeout_handler && - F->timeout > 0 && F->timeout < CurrentTime) - { - /* Call timeout handler */ - hdl = F->timeout_handler; - data = F->timeout_data; - comm_settimeout(F->fd, 0, NULL, NULL); - hdl(F->fd, data); - } - } - } -} - -/* - * void comm_connect_tcp(int fd, const char *host, u_short port, - * struct sockaddr *clocal, int socklen, - * CNCB *callback, void *data, int aftype, int timeout) - * Input: An fd to connect with, a host and port to connect to, - * a local sockaddr to connect from + length(or NULL to use the - * default), a callback, the data to pass into the callback, the - * address family. - * Output: None. - * Side-effects: A non-blocking connection to the host is started, and - * if necessary, set up for selection. The callback given - * may be called now, or it may be called later. - */ -void -comm_connect_tcp(int fd, const char *host, u_short port, - struct sockaddr *clocal, int socklen, CNCB * callback, - void *data, int aftype, int timeout) -{ - void *ipptr = NULL; - fde_t *F; - s_assert(fd >= 0); - F = comm_locate_fd(fd); - F->flags.called_connect = 1; - s_assert(callback); - F->connect.callback = callback; - F->connect.data = data; - - memset(&F->connect.hostaddr, 0, sizeof(F->connect.hostaddr)); -#ifdef IPV6 - if(aftype == AF_INET6) - { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&F->connect.hostaddr; - SET_SS_LEN(F->connect.hostaddr, sizeof(struct sockaddr_in6)); - in6->sin6_port = htons(port); - in6->sin6_family = AF_INET6; - ipptr = &in6->sin6_addr; - } else -#endif - { - struct sockaddr_in *in = (struct sockaddr_in *)&F->connect.hostaddr; - SET_SS_LEN(F->connect.hostaddr, sizeof(struct sockaddr_in)); - in->sin_port = htons(port); - in->sin_family = AF_INET; - ipptr = &in->sin_addr; - } - - /* Note that we're using a passed sockaddr here. This is because - * generally you'll be bind()ing to a sockaddr grabbed from - * getsockname(), so this makes things easier. - * XXX If NULL is passed as local, we should later on bind() to the - * virtual host IP, for completeness. - * -- adrian - */ - if((clocal != NULL) && (bind(F->fd, clocal, socklen) < 0)) - { - /* Failure, call the callback with COMM_ERR_BIND */ - comm_connect_callback(F->fd, COMM_ERR_BIND); - /* ... and quit */ - return; - } - - /* Next, if we have been given an IP, get the addr and skip the - * DNS check (and head direct to comm_connect_tryconnect(). - */ - if(inetpton(aftype, host, ipptr) <= 0) - { - /* Send the DNS request, for the next level */ - F->dns_query = MyMalloc(sizeof(struct DNSQuery)); - F->dns_query->ptr = F; - F->dns_query->callback = comm_connect_dns_callback; -#ifdef IPV6 - if (aftype == AF_INET6) - gethost_byname_type(host, F->dns_query, T_AAAA); - else -#endif - gethost_byname_type(host, F->dns_query, T_A); - } - else - { - /* We have a valid IP, so we just call tryconnect */ - /* Make sure we actually set the timeout here .. */ - comm_settimeout(F->fd, timeout * 1000, comm_connect_timeout, NULL); - comm_connect_tryconnect(F->fd, NULL); - } -} - -/* - * comm_connect_callback() - call the callback, and continue with life - */ -static void -comm_connect_callback(int fd, int status) -{ - CNCB *hdl; - fde_t *F = comm_locate_fd(fd); - - /* This check is gross..but probably necessary */ - if(F == NULL || F->connect.callback == NULL) - return; - - /* Clear the connect flag + handler */ - hdl = F->connect.callback; - F->connect.callback = NULL; - F->flags.called_connect = 0; - - /* Clear the timeout handler */ - comm_settimeout(F->fd, 0, NULL, NULL); - - /* Call the handler */ - hdl(F->fd, status, F->connect.data); -} - - -/* - * comm_connect_timeout() - this gets called when the socket connection - * times out. This *only* can be called once connect() is initially - * called .. - */ -static void -comm_connect_timeout(int fd, void *notused) -{ - /* error! */ - comm_connect_callback(fd, COMM_ERR_TIMEOUT); -} - - -/* - * comm_connect_dns_callback() - called at the completion of the DNS request - * - * The DNS request has completed, so if we've got an error, return it, - * otherwise we initiate the connect() - */ -static void -comm_connect_dns_callback(void *vptr, struct DNSReply *reply) -{ - fde_t *F = vptr; - - /* Free dns_query now to avoid double reslist free -- jilles */ - MyFree(F->dns_query); - F->dns_query = NULL; - - if(!reply) - { - comm_connect_callback(F->fd, COMM_ERR_DNS); - return; - } - - /* No error, set a 10 second timeout */ - comm_settimeout(F->fd, 30 * 1000, comm_connect_timeout, NULL); - - /* Copy over the DNS reply info so we can use it in the connect() */ -#ifdef IPV6 - if(reply->addr.ss_family == AF_INET6) - { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&F->connect.hostaddr; - memcpy(&in6->sin6_addr, &((struct sockaddr_in6 *)&reply->addr)->sin6_addr, sizeof(struct in6_addr)); - } - else -#endif - { - struct sockaddr_in *in = (struct sockaddr_in *)&F->connect.hostaddr; - in->sin_addr.s_addr = ((struct sockaddr_in *)&reply->addr)->sin_addr.s_addr; - } - - /* Now, call the tryconnect() routine to try a connect() */ - comm_connect_tryconnect(F->fd, NULL); -} - - -/* static void comm_connect_tryconnect(int fd, void *notused) - * Input: The fd, the handler data(unused). - * Output: None. - * Side-effects: Try and connect with pending connect data for the FD. If - * we succeed or get a fatal error, call the callback. - * Otherwise, it is still blocking or something, so register - * to select for a write event on this FD. - */ -static void -comm_connect_tryconnect(int fd, void *notused) -{ - int retval; - fde_t *F = comm_locate_fd(fd); - - if(F->connect.callback == NULL) - return; - /* Try the connect() */ - retval = connect(fd, (struct sockaddr *) &F->connect.hostaddr, - GET_SS_LEN(F->connect.hostaddr)); - /* Error? */ - if(retval < 0) - { - /* - * If we get EISCONN, then we've already connect()ed the socket, - * which is a good thing. - * -- adrian - */ - if(errno == EISCONN) - comm_connect_callback(F->fd, COMM_OK); - else if(ignoreErrno(errno)) - /* Ignore error? Reschedule */ - comm_setselect(F->fd, FDLIST_SERVER, COMM_SELECT_WRITE|COMM_SELECT_RETRY, - comm_connect_tryconnect, NULL, 0); - else - /* Error? Fail with COMM_ERR_CONNECT */ - comm_connect_callback(F->fd, COMM_ERR_CONNECT); - return; - } - /* If we get here, we've suceeded, so call with COMM_OK */ - comm_connect_callback(F->fd, COMM_OK); -} - -/* - * comm_error_str() - return an error string for the given error condition - */ -const char * -comm_errstr(int error) -{ - if(error < 0 || error >= COMM_ERR_MAX) - return "Invalid error number!"; - return comm_err_str[error]; -} - - -/* - * comm_socket() - open a socket - * - * This is a highly highly cut down version of squid's comm_open() which - * for the most part emulates socket(), *EXCEPT* it fails if we're about - * to run out of file descriptors. - */ -int -comm_socket(int family, int sock_type, int proto, const char *note) -{ - int fd; - /* First, make sure we aren't going to run out of file descriptors */ - if(number_fd >= comm_max_connections) - { - errno = ENFILE; - return -1; - } - - /* - * Next, we try to open the socket. We *should* drop the reserved FD - * limit if/when we get an error, but we can deal with that later. - * XXX !!! -- adrian - */ - fd = socket(family, sock_type, proto); - comm_fd_hack(&fd); - if(fd < 0) - return -1; /* errno will be passed through, yay.. */ - -#if defined(IPV6) && defined(IPV6_V6ONLY) - /* - * Make sure we can take both IPv4 and IPv6 connections - * on an AF_INET6 socket - */ - if(family == AF_INET6) - { - int off = 1; - if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) == -1) - { - libcharybdis_log("comm_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s", - fd, strerror(errno)); - close(fd); - return -1; - } - } -#endif - - /* Set the socket non-blocking, and other wonderful bits */ - if(!comm_set_nb(fd)) - { - libcharybdis_log("comm_open: Couldn't set FD %d non blocking: %s", fd, strerror(errno)); - close(fd); - return -1; - } - - /* Next, update things in our fd tracking */ - comm_open(fd, FD_SOCKET, note); - return fd; -} - - -/* - * comm_accept() - accept an incoming connection - * - * This is a simple wrapper for accept() which enforces FD limits like - * comm_open() does. - */ -int -comm_accept(int fd, struct sockaddr *pn, socklen_t *addrlen) -{ - int newfd; - if(number_fd >= comm_max_connections) - { - errno = ENFILE; - return -1; - } - - /* - * Next, do the accept(). if we get an error, we should drop the - * reserved fd limit, but we can deal with that when comm_open() - * also does it. XXX -- adrian - */ - newfd = accept(fd, (struct sockaddr *) pn, addrlen); - comm_fd_hack(&newfd); - - if(newfd < 0) - return -1; - - /* Set the socket non-blocking, and other wonderful bits */ - if(!comm_set_nb(newfd)) - { - libcharybdis_log("comm_accept: Couldn't set FD %d non blocking!", newfd); - close(newfd); - return -1; - } - - /* Next, tag the FD as an incoming connection */ - comm_open(newfd, FD_SOCKET, "Incoming connection"); - - /* .. and return */ - return newfd; -} - -/* - * If a sockaddr_storage is AF_INET6 but is a mapped IPv4 - * socket manged the sockaddr. - */ -#ifndef mangle_mapped_sockaddr -void -mangle_mapped_sockaddr(struct sockaddr *in) -{ - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in; - - if(in->sa_family == AF_INET) - return; - - if(in->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr)) - { - struct sockaddr_in in4; - memset(&in4, 0, sizeof(struct sockaddr_in)); - in4.sin_family = AF_INET; - in4.sin_port = in6->sin6_port; - in4.sin_addr.s_addr = ((uint32_t *)&in6->sin6_addr)[3]; - memcpy(in, &in4, sizeof(struct sockaddr_in)); - } - return; -} -#endif - - -static void -fdlist_update_biggest(int fd, int opening) -{ - if(fd < highest_fd) - return; - s_assert(fd < comm_max_connections); - - if(fd > highest_fd) - { - /* - * s_assert that we are not closing a FD bigger than - * our known biggest FD - */ - s_assert(opening); - highest_fd = fd; - return; - } - /* if we are here, then fd == Biggest_FD */ - /* - * s_assert that we are closing the biggest FD; we can't be - * re-opening it - */ - s_assert(!opening); - while (highest_fd >= 0 && comm_locate_fd(fd) != NULL) - highest_fd--; -} - - -void -fdlist_init(void) -{ - static int initialized = 0; - struct rlimit limit; - - if(!initialized) - { - memset(&fd_table, '\0', sizeof(dlink_list) * FD_HASH_SIZE); - - /* set up comm_max_connections. */ - if(!getrlimit(RLIMIT_NOFILE, &limit)) - comm_max_connections = limit.rlim_cur; - - initialized = 1; - } -} - -/* Called to open a given filedescriptor */ -void -comm_open(int fd, unsigned int type, const char *desc) -{ - fde_t *F = comm_add_fd(fd); - s_assert(fd >= 0); - - if(F->flags.open) - { - comm_close(fd); - } - s_assert(!F->flags.open); - F->fd = fd; - F->type = type; - F->flags.open = 1; -#ifdef NOTYET - F->defer.until = 0; - F->defer.n = 0; - F->defer.handler = NULL; -#endif - fdlist_update_biggest(fd, 1); - F->comm_index = -1; - F->list = FDLIST_NONE; - if(desc) - strlcpy(F->desc, desc, sizeof(F->desc)); - number_fd++; -} - - -/* Called to close a given filedescriptor */ -void -comm_close(int fd) -{ - fde_t *F = comm_locate_fd(fd); - s_assert(F->flags.open); - /* All disk fd's MUST go through file_close() ! */ - s_assert(F->type != FD_FILE); - if(F->type == FD_FILE) - { - s_assert(F->read_handler == NULL); - s_assert(F->write_handler == NULL); - } - comm_setselect(F->fd, FDLIST_NONE, COMM_SELECT_WRITE | COMM_SELECT_READ, NULL, NULL, 0); - comm_setflush(F->fd, 0, NULL, NULL); - F->timeout = 0; - - if (F->dns_query != NULL) - { - delete_resolver_queries(F->dns_query); - MyFree(F->dns_query); - F->dns_query = NULL; - } - - F->flags.open = 0; - fdlist_update_biggest(fd, 0); - number_fd--; - comm_remove_fd(fd); - - /* Unlike squid, we're actually closing the FD here! -- adrian */ - close(fd); -} - -/* - * comm_dump() - dump the list of active filedescriptors - */ -void -comm_dump(struct Client *source_p) -{ - int i; - - for (i = 0; i <= FD_HASH_SIZE; i++) - { - dlink_node *n; - - if (dlink_list_length(&fd_table[i]) <= 0) - continue; - - DLINK_FOREACH(n, fd_table[i].head) - { - fde_t *F = (fde_t *) n->data; - - if(F == NULL || !F->flags.open) - continue; - - sendto_one_numeric(source_p, RPL_STATSDEBUG, - "F :fd %-3d bucket %-3d desc '%s'", - F->fd, i, F->desc); - } - } -} - -/* - * comm_note() - set the fd note - * - * Note: must be careful not to overflow fd_table[fd].desc when - * calling. - */ -void -comm_note(int fd, const char *format, ...) -{ - va_list args; - fde_t *F = comm_add_fd(fd); /* XXX: epoll, kqueue. */ - - if(format) - { - va_start(args, format); - ircvsnprintf(F->desc, FD_DESC_SZ, format, args); - va_end(args); - } - else - F->desc[0] = '\0'; -} - -extern int -comm_get_maxconnections(void) -{ - fdlist_init(); - - return comm_max_connections; -} diff --git a/libcharybdis/commio.h b/libcharybdis/commio.h deleted file mode 100644 index db65ca0..0000000 --- a/libcharybdis/commio.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * commio.h: A header for the network subsystem. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2004 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: commio.h 3354 2007-04-03 09:21:31Z nenolod $ - */ - -#ifndef INCLUDED_commio_h -#define INCLUDED_commio_h - -#include "setup.h" -#include "config.h" -#include "ircd_defs.h" -#include "tools.h" - -typedef struct _fde fde_t; - -/* Callback for completed IO events */ -typedef void PF(int fd, void *); - -/* virtual function types for I/O --nenolod */ -typedef int IOFuncRead(fde_t *, void *buf, size_t count); -typedef int IOFuncWrite(fde_t *, const void *buf, size_t count); - -/* Callback for completed connections */ -/* int fd, int status, void * */ -typedef void CNCB(int fd, int, void *); - -#define FD_DESC_SZ 128 /* hostlen + comment */ - - -/* FD type values */ -enum -{ - FD_NONE, - FD_LOG, - FD_FILE, - FD_FILECLOSE, - FD_SOCKET, - FD_PIPE, - FD_UNKNOWN -}; - -enum -{ - COMM_OK, - COMM_ERR_BIND, - COMM_ERR_DNS, - COMM_ERR_TIMEOUT, - COMM_ERR_CONNECT, - COMM_ERROR, - COMM_ERR_MAX -}; - -typedef enum fdlist_t -{ - FDLIST_NONE, - FDLIST_SERVICE, - FDLIST_SERVER, - FDLIST_IDLECLIENT, - FDLIST_BUSYCLIENT, - FDLIST_MAX -} -fdlist_t; - - -extern int highest_fd; -extern int number_fd; - -struct Client; - -struct _fde -{ - /* New-school stuff, again pretty much ripped from squid */ - /* - * Yes, this gives us only one pending read and one pending write per - * filedescriptor. Think though: when do you think we'll need more? - */ - int fd; /* So we can use the fde_t as a callback ptr */ - int type; - fdlist_t list; /* Which list this FD should sit on */ - int comm_index; /* where in the poll list we live */ - char desc[FD_DESC_SZ]; - - PF *read_handler; - void *read_data; - - PF *write_handler; - void *write_data; - - PF *timeout_handler; - void *timeout_data; - time_t timeout; - - PF *flush_handler; - void *flush_data; - time_t flush_timeout; - - IOFuncRead *read_impl; - IOFuncWrite *write_impl; - - struct DNSQuery *dns_query; - struct - { - unsigned int open:1; - unsigned int close_request:1; - unsigned int write_daemon:1; - unsigned int closing:1; - unsigned int socket_eof:1; - unsigned int nolinger:1; - unsigned int nonblocking:1; - unsigned int ipc:1; - unsigned int called_connect:1; - } - flags; - struct - { - struct irc_sockaddr_storage hostaddr; - CNCB *callback; - void *data; - /* We'd also add the retry count here when we get to that -- adrian */ - } - connect; - int pflags; - dlink_node node; -}; - - -void fdlist_init(void); - -extern void comm_open(int, unsigned int, const char *); -extern void comm_close(int); -extern void comm_dump(struct Client *source_p); -#ifndef __GNUC__ -extern void comm_note(int fd, const char *format, ...); -#else -extern void comm_note(int fd, const char *format, ...) __attribute__ ((format(printf, 2, 3))); -#endif - -#define FB_EOF 0x01 -#define FB_FAIL 0x02 - - -/* Size of a read buffer */ -#define READBUF_SIZE 16384 /* used by src/packet.c and src/s_serv.c */ - -/* Type of IO */ -#define COMM_SELECT_READ 0x1 -#define COMM_SELECT_WRITE 0x2 -#define COMM_SELECT_RETRY 0x4 -extern int readcalls; -extern const char *const NONB_ERROR_MSG; -extern const char *const SETBUF_ERROR_MSG; - -extern void comm_close_all(void); -extern int comm_set_nb(int); -extern int comm_set_buffers(int, int); - -extern int comm_get_sockerr(int); -extern int ignoreErrno(int ierrno); - -extern void comm_settimeout(int fd, time_t, PF *, void *); -extern void comm_setflush(int fd, time_t, PF *, void *); -extern void comm_checktimeouts(void *); -extern void comm_connect_tcp(int fd, const char *, u_short, - struct sockaddr *, int, CNCB *, void *, int, int); -extern const char *comm_errstr(int status); -extern int comm_socket(int family, int sock_type, int proto, const char *note); -extern int comm_accept(int fd, struct sockaddr *pn, socklen_t *addrlen); - -/* These must be defined in the network IO loop code of your choice */ -extern void comm_setselect(int fd, fdlist_t list, unsigned int type, - PF * handler, void *client_data, time_t timeout); -extern void init_netio(void); -extern int read_message(time_t, unsigned char); -extern int comm_select(unsigned long); -extern int disable_sock_options(int); -#ifdef IPV6 -extern void mangle_mapped_sockaddr(struct sockaddr *in); -#else -#define mangle_mapped_sockaddr(x) -#endif - -extern int comm_get_maxconnections(void); - -extern fde_t *comm_locate_fd(int fd); -extern fde_t *comm_add_fd(int fd); - -#endif /* INCLUDED_commio_h */ diff --git a/libcharybdis/epoll.c b/libcharybdis/epoll.c deleted file mode 100644 index f06ced3..0000000 --- a/libcharybdis/epoll.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * charybdis: A slightly useful ircd. - * epoll.c: Linux epoll compatible network routines. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2001 Adrian Chadd - * Copyright (C) 2002-2005 ircd-ratbox development team - * Copyright (C) 2002 Aaron Sethman - * Copyright (C) 2008 William Pitcock - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: epoll.c 3444 2007-05-09 00:32:08Z nenolod $ - */ - -#include "config.h" -#include "stdinc.h" -#include - -#include "libcharybdis.h" - -static int ep; /* epoll file descriptor */ -static struct epoll_event *pfd; -static int pfd_size; - - -#ifndef HAVE_EPOLL_CTL /* bah..glibc doesn't support epoll yet.. */ -#include -#include - -_syscall1(int, epoll_create, int, maxfds); -_syscall4(int, epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, events); -_syscall4(int, epoll_wait, int, epfd, struct epoll_event *, pevents, - int, maxevents, int, timeout); - -#endif /* HAVE_EPOLL_CTL */ - - -/* - * init_netio - * - * This is a needed exported function which will be called to initialise - * the network loop code. - */ -void -init_netio(void) -{ - pfd_size = getdtablesize(); - ep = epoll_create(pfd_size); - pfd = MyMalloc(sizeof(struct epoll_event) * pfd_size); - if(ep < 0) - { - fprintf(stderr, "init_netio: Couldn't open epoll fd!\n"); - exit(115); /* Whee! */ - } - comm_note(ep, "epoll file descriptor"); -} - -/* - * comm_setselect - * - * This is a needed exported function which will be called to register - * and deregister interest in a pending IO state for a given FD. - */ -void -comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler, - void *client_data, time_t timeout) -{ - struct epoll_event ep_event; - fde_t *F = comm_locate_fd(fd); - int old_flags = F->pflags; - int op = -1; - - s_assert(fd >= 0); - s_assert(F->flags.open); - - /* Update the list, even though we're not using it .. */ - F->list = list; - if(type & COMM_SELECT_READ) - { - if(handler != NULL) - F->pflags |= EPOLLIN; - else - F->pflags &= ~EPOLLIN; - F->read_handler = handler; - F->read_data = client_data; - } - - if(type & COMM_SELECT_WRITE) - { - if(handler != NULL) - F->pflags |= EPOLLOUT; - else - F->pflags &= ~EPOLLOUT; - F->write_handler = handler; - F->write_data = client_data; - } - - if(timeout) - F->timeout = CurrentTime + (timeout / 1000); - - if(old_flags == 0 && F->pflags == 0) - return; - else if(F->pflags <= 0) - op = EPOLL_CTL_DEL; - else if(old_flags == 0 && F->pflags > 0) - op = EPOLL_CTL_ADD; - else if(F->pflags != old_flags) - op = EPOLL_CTL_MOD; - - if(op == -1) - return; - - - ep_event.events = F->pflags; - ep_event.data.ptr = F; - - if(epoll_ctl(ep, op, fd, &ep_event) != 0) - { - libcharybdis_log("comm_setselect(): epoll_ctl failed: %s", strerror(errno)); - abort(); - } -} - -/* - * comm_select - * - * Called to do the new-style IO, courtesy of squid (like most of this - * new IO code). This routine handles the stuff we've hidden in - * comm_setselect and fd_table[] and calls callbacks for IO ready - * events. - */ - -int -comm_select(unsigned long delay) -{ - int num, i, flags, old_flags, op; - struct epoll_event ep_event; - void *data; - - num = epoll_wait(ep, pfd, pfd_size, delay); - set_time(); - if(num < 0 && !ignoreErrno(errno)) - { - return COMM_ERROR; - } - - if(num == 0) - return COMM_OK; - for (i = 0; i < num; i++) - { - PF *hdl; - fde_t *F = pfd[i].data.ptr; - old_flags = F->pflags; - if(pfd[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)) - { - hdl = F->read_handler; - data = F->read_data; - F->read_handler = NULL; - F->read_data = NULL; - if(hdl) { - hdl(F->fd, data); - } - else - libcharybdis_log("epoll.c: NULL read handler called"); - } - - - if(F->flags.open == 0 && F->pflags == 0) - continue; - else if (F->flags.open == 0) - { - F->pflags = ep_event.events = flags; - ep_event.data.ptr = F; - - if(epoll_ctl(ep, EPOLL_CTL_DEL, F->fd, &ep_event) != 0) { - /* XXX: we assume this is because close(2) has been called here. */ - if (errno == EBADF) - continue; - - libcharybdis_log("comm_select(): epoll_ctl failed while trying to delete an FD marked as closed: %s", strerror(errno)); - abort(); - } - - continue; - } - - if(pfd[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR)) - { - hdl = F->write_handler; - data = F->write_data; - F->write_handler = NULL; - F->write_data = NULL; - - if(hdl) { - hdl(F->fd, data); - } - else - libcharybdis_log("epoll.c: NULL write handler called"); - } - - if(F->flags.open == 0 && F->pflags == 0) - continue; - else if (F->flags.open == 0) - { - F->pflags = ep_event.events = flags; - ep_event.data.ptr = F; - - if(epoll_ctl(ep, EPOLL_CTL_DEL, F->fd, &ep_event) != 0) { - /* XXX: we assume this is because close(2) has been called here. */ - if (errno == EBADF) - continue; - - libcharybdis_log("comm_select(): epoll_ctl failed while trying to delete an FD marked as closed: %s", strerror(errno)); - abort(); - } - - continue; - } - - flags = 0; - - if(F->read_handler != NULL) - flags |= EPOLLIN; - else - flags &= ~EPOLLIN; - - if(F->write_handler != NULL) - flags |= EPOLLOUT; - else - flags &= ~EPOLLOUT; - - if(old_flags != flags) - { - if(flags == 0) - op = EPOLL_CTL_DEL; - else - op = EPOLL_CTL_MOD; - - F->pflags = ep_event.events = flags; - ep_event.data.ptr = F; - - if(epoll_ctl(ep, op, F->fd, &ep_event) != 0) - libcharybdis_log("comm_select(): epoll_ctl failed: %s", strerror(errno)); - } - - } - return COMM_OK; -} diff --git a/libcharybdis/event.c b/libcharybdis/event.c deleted file mode 100644 index 8568d70..0000000 --- a/libcharybdis/event.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * event.c: Event functions. - * - * Copyright (C) 1998-2000 Regents of the University of California - * Copyright (C) 2001-2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * Code borrowed from the squid web cache by Adrian Chadd. - * Original header: - * - * DEBUG: section 41 Event Processing - * AUTHOR: Henrik Nordstrom - * - * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from the - * Internet community. Development is led by Duane Wessels of the - * National Laboratory for Applied Network Research and funded by the - * National Science Foundation. Squid is Copyrighted (C) 1998 by - * the Regents of the University of California. Please see the - * COPYRIGHT file for full details. Squid incorporates software - * developed and/or copyrighted by other sources. Please see the - * CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: event.c 498 2006-01-15 16:40:33Z jilles $ - */ - -/* - * How its used: - * - * Should be pretty self-explanatory. Events are added to the static - * array event_table with a frequency time telling eventRun how often - * to execute it. - */ - -#include "stdinc.h" -#include "config.h" - -#include "ircd.h" -#include "event.h" -#include "client.h" -#include "send.h" -#include "memory.h" -#include "s_log.h" -#include "numeric.h" - -static const char *last_event_ran = NULL; -struct ev_entry event_table[MAX_EVENTS]; -static time_t event_time_min = -1; - -/* - * void eventAdd(const char *name, EVH *func, void *arg, time_t when) - * - * Input: Name of event, function to call, arguments to pass, and frequency - * of the event. - * Output: None - * Side Effects: Adds the event to the event list. - */ -void -eventAdd(const char *name, EVH * func, void *arg, time_t when) -{ - int i; - - /* find first inactive index */ - for (i = 0; i < MAX_EVENTS; i++) - { - if(event_table[i].active == 0) - { - event_table[i].func = func; - event_table[i].name = name; - event_table[i].arg = arg; - event_table[i].when = CurrentTime + when; - event_table[i].frequency = when; - event_table[i].active = 1; - - if((event_table[i].when < event_time_min) || (event_time_min == -1)) - event_time_min = event_table[i].when; - - return; - } - } - - /* erk! couldnt add to event table */ - sendto_realops_snomask(SNO_DEBUG, L_ALL, "Unable to add event [%s] to event table", name); - -} - -void -eventAddOnce(const char *name, EVH *func, void *arg, time_t when) -{ - int i; - - /* find first inactive index */ - for (i = 0; i < MAX_EVENTS; i++) - { - if(event_table[i].active == 0) - { - event_table[i].func = func; - event_table[i].name = name; - event_table[i].arg = arg; - event_table[i].when = CurrentTime + when; - event_table[i].frequency = 0; - event_table[i].active = 1; - - if ((event_table[i].when < event_time_min) || (event_time_min == -1)) - event_time_min = event_table[i].when; - - return; - } - } - - /* erk! couldnt add to event table */ - sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Unable to add event [%s] to event table", name); -} - -/* - * void eventDelete(EVH *func, void *arg) - * - * Input: Function handler, argument that was passed. - * Output: None - * Side Effects: Removes the event from the event list - */ -void -eventDelete(EVH * func, void *arg) -{ - int i; - - i = eventFind(func, arg); - - if(i == -1) - return; - - event_table[i].name = NULL; - event_table[i].func = NULL; - event_table[i].arg = NULL; - event_table[i].active = 0; -} - -/* - * void eventAddIsh(const char *name, EVH *func, void *arg, time_t delta_isa) - * - * Input: Name of event, function to call, arguments to pass, and frequency - * of the event. - * Output: None - * Side Effects: Adds the event to the event list within +- 1/3 of the - * specified frequency. - */ -void -eventAddIsh(const char *name, EVH * func, void *arg, time_t delta_ish) -{ - if(delta_ish >= 3.0) - { - const time_t two_third = (2 * delta_ish) / 3; - delta_ish = two_third + ((rand() % 1000) * two_third) / 1000; - /* - * XXX I hate the above magic, I don't even know if its right. - * Grr. -- adrian - */ - } - eventAdd(name, func, arg, delta_ish); -} - -/* - * void eventRun(void) - * - * Input: None - * Output: None - * Side Effects: Runs pending events in the event list - */ -void -eventRun(void) -{ - int i; - - for (i = 0; i < MAX_EVENTS; i++) - { - if(event_table[i].active && (event_table[i].when <= CurrentTime)) - { - last_event_ran = event_table[i].name; - event_table[i].func(event_table[i].arg); - event_time_min = -1; - - /* event is scheduled more than once */ - if(event_table[i].frequency) - event_table[i].when = CurrentTime + event_table[i].frequency; - else - { - event_table[i].name = NULL; - event_table[i].func = NULL; - event_table[i].arg = NULL; - event_table[i].active = 0; - } - } - } -} - - -/* - * time_t eventNextTime(void) - * - * Input: None - * Output: Specifies the next time eventRun() should be run - * Side Effects: None - */ -time_t -eventNextTime(void) -{ - int i; - - if(event_time_min == -1) - { - for (i = 0; i < MAX_EVENTS; i++) - { - if(event_table[i].active && - ((event_table[i].when < event_time_min) || (event_time_min == -1))) - event_time_min = event_table[i].when; - } - } - - return event_time_min; -} - -/* - * void eventInit(void) - * - * Input: None - * Output: None - * Side Effects: Initializes the event system. - */ -void -eventInit(void) -{ - last_event_ran = NULL; - memset((void *) event_table, 0, sizeof(event_table)); -} - -/* - * int eventFind(EVH *func, void *arg) - * - * Input: Event function and the argument passed to it - * Output: Index to the slow in the event_table - * Side Effects: None - */ -int -eventFind(EVH * func, void *arg) -{ - int i; - - for (i = 0; i < MAX_EVENTS; i++) - { - if((event_table[i].func == func) && - (event_table[i].arg == arg) && event_table[i].active) - return i; - } - - return -1; -} - -/* - * void show_events(struct Client *source_p) - * - * Input: Client requesting the event - * Output: List of events - * Side Effects: None - */ -void -show_events(struct Client *source_p) -{ - int i; - - if(last_event_ran) - sendto_one_numeric(source_p, RPL_STATSDEBUG, - "E :Last event to run: %s", - last_event_ran); - - sendto_one_numeric(source_p, RPL_STATSDEBUG, - "E :Operation Next Execution"); - - for (i = 0; i < MAX_EVENTS; i++) - { - if(event_table[i].active) - { - sendto_one_numeric(source_p, RPL_STATSDEBUG, - "E :%-28s %-4d seconds", - event_table[i].name, - (int)(event_table[i].when - CurrentTime)); - } - } -} - -/* - * void set_back_events(time_t by) - * Input: Time to set back events by. - * Output: None. - * Side-effects: Sets back all events by "by" seconds. - */ -void -set_back_events(time_t by) -{ - int i; - - for (i = 0; i < MAX_EVENTS; i++) - { - if(event_table[i].when > by) - event_table[i].when -= by; - else - event_table[i].when = 0; - } -} - -void -eventUpdate(const char *name, time_t freq) -{ - int i; - - for(i = 0; i < MAX_EVENTS; i++) - { - if(event_table[i].active && - !irccmp(event_table[i].name, name)) - { - event_table[i].frequency = freq; - - /* update when its scheduled to run if its higher - * than the new frequency - */ - if((CurrentTime + freq) < event_table[i].when) - event_table[i].when = CurrentTime + freq; - - return; - } - } -} - - diff --git a/libcharybdis/event.h b/libcharybdis/event.h deleted file mode 100644 index 7e70cac..0000000 --- a/libcharybdis/event.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * event.h: The ircd event header. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2004 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: event.h 380 2005-12-07 15:08:37Z nenolod $ - */ - -#ifndef INCLUDED_event_h -#define INCLUDED_event_h - -/* - * How many event entries we need to allocate at a time in the block - * allocator. 16 should be plenty at a time. - */ -#define MAX_EVENTS 50 - - -typedef void EVH(void *); - -/* The list of event processes */ -struct ev_entry -{ - EVH *func; - void *arg; - const char *name; - time_t frequency; - time_t when; - int active; -}; - -extern void eventAdd(const char *name, EVH * func, void *arg, time_t when); -extern void eventAddOnce(const char *name, EVH * func, void *arg, time_t when); -extern void eventAddIsh(const char *name, EVH * func, void *arg, time_t delta_ish); -extern void eventRun(void); -extern time_t eventNextTime(void); -extern void eventInit(void); -extern void eventDelete(EVH * func, void *); -extern int eventFind(EVH * func, void *); -extern void set_back_events(time_t); - -void eventUpdate(const char *name, time_t freq); - -extern void show_events(struct Client *source_p); - -#endif /* INCLUDED_event_h */ diff --git a/libcharybdis/kqueue.c b/libcharybdis/kqueue.c deleted file mode 100644 index 6b82554..0000000 --- a/libcharybdis/kqueue.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * kqueue.c: FreeBSD kqueue compatible network routines. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2001 Adrian Chadd - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: kqueue.c 3358 2007-04-03 09:34:38Z nenolod $ - */ - -#include "stdinc.h" -#include - -#include "libcharybdis.h" - -#define KE_LENGTH 128 - -/* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */ - -#ifndef EV_SET -#define EV_SET(kevp, a, b, c, d, e, f) do { \ - (kevp)->ident = (a); \ - (kevp)->filter = (b); \ - (kevp)->flags = (c); \ - (kevp)->fflags = (d); \ - (kevp)->data = (e); \ - (kevp)->udata = (f); \ -} while(0) -#endif - -static void kq_update_events(fde_t *, short, PF *); -static int kq; -static struct timespec zero_timespec; - -static struct kevent *kqlst; /* kevent buffer */ -static int kqmax; /* max structs to buffer */ -static int kqoff; /* offset into the buffer */ - - -/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* Private functions */ - -void -kq_update_events(fde_t * F, short filter, PF * handler) -{ - PF *cur_handler; - int kep_flags; - - switch (filter) - { - case EVFILT_READ: - cur_handler = F->read_handler; - break; - case EVFILT_WRITE: - cur_handler = F->write_handler; - break; - default: - /* XXX bad! -- adrian */ - return; - break; - } - - if((cur_handler == NULL && handler != NULL) || (cur_handler != NULL && handler == NULL)) - { - struct kevent *kep; - - kep = kqlst + kqoff; - - if(handler != NULL) - { - if(filter == EVFILT_WRITE) - kep_flags = (EV_ADD | EV_ENABLE | EV_ONESHOT); - else - kep_flags = (EV_ADD | EV_ENABLE); - } - else - { - /* lets definately not poll stuff that isn't real -- - * some kqueue implementations hate doing this... and - * it's intended to delete AND disable at the same time. - * - * don't believe me? read kevent(4). --nenolod - */ - kep_flags = (EV_DELETE | EV_DISABLE); - } - - EV_SET(kep, (uintptr_t) F->fd, filter, kep_flags, 0, 0, (void *) F); - - if(++kqoff == kqmax) - { - int ret; - - ret = kevent(kq, kqlst, kqoff, NULL, 0, &zero_timespec); - /* jdc -- someone needs to do error checking... */ - if(ret == -1) - { - libcharybdis_log("kq_update_events(): kevent(): %s", strerror(errno)); - return; - } - kqoff = 0; - } - } -} - - - -/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* Public functions */ - - -/* - * init_netio - * - * This is a needed exported function which will be called to initialise - * the network loop code. - */ -void -init_netio(void) -{ - kq = kqueue(); - if(kq < 0) - { - libcharybdis_log("init_netio: Couldn't open kqueue fd!\n"); - exit(115); /* Whee! */ - } - kqmax = getdtablesize(); - kqlst = MyMalloc(sizeof(struct kevent) * kqmax); - zero_timespec.tv_sec = 0; - zero_timespec.tv_nsec = 0; -} - -/* - * comm_setselect - * - * This is a needed exported function which will be called to register - * and deregister interest in a pending IO state for a given FD. - */ -void -comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler, - void *client_data, time_t timeout) -{ - fde_t *F = comm_locate_fd(fd); - s_assert(fd >= 0); - s_assert(F->flags.open); - - /* Update the list, even though we're not using it .. */ - F->list = list; - - if(type & COMM_SELECT_READ) - { - kq_update_events(F, EVFILT_READ, handler); - F->read_handler = handler; - F->read_data = client_data; - } - if(type & COMM_SELECT_WRITE) - { - kq_update_events(F, EVFILT_WRITE, handler); - F->write_handler = handler; - F->write_data = client_data; - } - if(timeout) - F->timeout = CurrentTime + (timeout / 1000); - -} - -/* - * Check all connections for new connections and input data that is to be - * processed. Also check for connections with data queued and whether we can - * write it out. - */ - -/* - * comm_select - * - * Called to do the new-style IO, courtesy of squid (like most of this - * new IO code). This routine handles the stuff we've hidden in - * comm_setselect and fd_table[] and calls callbacks for IO ready - * events. - */ - -int -comm_select(unsigned long delay) -{ - int num, i; - static struct kevent ke[KE_LENGTH]; - struct timespec poll_time; - - /* - * remember we are doing NANOseconds here, not micro/milli. God knows - * why jlemon used a timespec, but hey, he wrote the interface, not I - * -- Adrian - */ - - poll_time.tv_sec = delay / 1000; - - poll_time.tv_nsec = (delay % 1000) * 1000000; - - for (;;) - { - num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, &poll_time); - kqoff = 0; - - if(num >= 0) - break; - - if(ignoreErrno(errno)) - break; - - set_time(); - - return COMM_ERROR; - - /* NOTREACHED */ - } - - set_time(); - - if(num == 0) - return COMM_OK; /* No error.. */ - - for (i = 0; i < num; i++) - { - int fd = (int) ke[i].ident; - PF *hdl = NULL; - fde_t *F = comm_locate_fd(fd); - - if(ke[i].flags & EV_ERROR) - { - errno = (int) ke[i].data; - /* XXX error == bad! -- adrian */ - continue; /* XXX! */ - } - if (F == NULL) - { - /* XXX this is because of our "queueing" of - * kqueue changes so we may get ones for fds - * we have already closed? -- jilles */ - continue; - } - - switch (ke[i].filter) - { - - case EVFILT_READ: - - if((hdl = F->read_handler) != NULL) - { - F->read_handler = NULL; - hdl(fd, F->read_data); - } - - break; - - case EVFILT_WRITE: - - if((hdl = F->write_handler) != NULL) - { - F->write_handler = NULL; - hdl(fd, F->write_data); - } - break; - - default: - /* Bad! -- adrian */ - break; - } - } - return COMM_OK; -} - diff --git a/libcharybdis/libcharybdis.c b/libcharybdis/libcharybdis.c deleted file mode 100644 index 2cef3a9..0000000 --- a/libcharybdis/libcharybdis.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * charybdis: A slightly useful ircd. - * libcharybdis.c: library entrypoint - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * Copyright (C) 2005 William Pitcock and Jilles Tjoelker - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: libcharybdis.c 386 2005-12-07 16:21:24Z nenolod $ - */ - -#include "stdinc.h" -#include "libcharybdis.h" - -static void (*log_callback)(const char *str) = NULL; -static void (*restart_callback)(const char *str) = NULL; -static void (*die_callback)(const char *str) = NULL; -static char errbuf[BUFSIZE * 2]; - -void libcharybdis_log(const char *str, ...) -{ - va_list args; - - if (log_callback == NULL) - return; - - va_start(args, str); - ircvsnprintf(errbuf, BUFSIZE * 2, str, args); - va_end(args); - - log_callback(errbuf); -} - -void libcharybdis_restart(const char *str, ...) -{ - va_list args; - - if (restart_callback == NULL) - return; - - va_start(args, str); - ircvsnprintf(errbuf, BUFSIZE * 2, str, args); - va_end(args); - - restart_callback(errbuf); -} - -void libcharybdis_die(const char *str, ...) -{ - va_list args; - - if (die_callback == NULL) - return; - - va_start(args, str); - ircvsnprintf(errbuf, BUFSIZE * 2, str, args); - va_end(args); - - die_callback(errbuf); -} - -void libcharybdis_init(void (*log_cb)(const char *str), - void (*restart_cb)(const char *str), void (*die_cb)(const char *str)) -{ - log_callback = log_cb; - restart_callback = restart_cb; - die_callback = die_cb; - - fdlist_init(); - init_netio(); - eventInit(); - initBlockHeap(); - init_dlink_nodes(); - linebuf_init(); -} diff --git a/libcharybdis/libcharybdis.h b/libcharybdis/libcharybdis.h deleted file mode 100644 index 1ac9bd5..0000000 --- a/libcharybdis/libcharybdis.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * charybdis: A slightly useful ircd. - * libcharybdis.h: library entrypoint - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * Copyright (C) 2005 William Pitcock and Jilles Tjoelker - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: libcharybdis.h 388 2005-12-07 16:34:40Z nenolod $ - */ - -#ifndef _LIBCHARYBDIS_H -#define _LIBCHARYBDIS_H - -#include "stdinc.h" -#include "res.h" -#include "numeric.h" -#include "tools.h" -#include "memory.h" -#include "balloc.h" -#include "linebuf.h" -#include "sprintf_irc.h" -#include "commio.h" -#include "event.h" - -extern void libcharybdis_log(const char *str, ...); -extern void libcharybdis_restart(const char *str, ...); -extern void libcharybdis_die(const char *str, ...); -extern void libcharybdis_init(void (*)(const char *), - void (*)(const char *), void (*)(const char *)); - -#endif diff --git a/libcharybdis/linebuf.c b/libcharybdis/linebuf.c deleted file mode 100644 index a532395..0000000 --- a/libcharybdis/linebuf.c +++ /dev/null @@ -1,686 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * linebuf.c: Maintains linebuffers. - * - * Copyright (C) 2001-2002 Adrian Chadd - * Copyright (C) 2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: linebuf.c 1110 2006-03-29 22:55:25Z nenolod $ - */ - -#include "stdinc.h" -#include "tools.h" -#include "client.h" -#include "linebuf.h" -#include "memory.h" -#include "event.h" -#include "balloc.h" -#include "hook.h" -#include "commio.h" -#include "sprintf_irc.h" - -#ifdef STRING_WITH_STRINGS -# include -# include -#else -# ifdef HAVE_STRING_H -# include -# else -# ifdef HAVE_STRINGS_H -# include -# endif -# endif -#endif - -extern BlockHeap *linebuf_heap; - -static int bufline_count = 0; - - -/* - * linebuf_init - * - * Initialise the linebuf mechanism - */ - - -void -linebuf_init(void) -{ - linebuf_heap = BlockHeapCreate(sizeof(buf_line_t), LINEBUF_HEAP_SIZE); -} - -static buf_line_t * -linebuf_allocate(void) -{ - buf_line_t *t; - t = BlockHeapAlloc(linebuf_heap); - t->refcount = 0; - return (t); - -} - -static void -linebuf_free(buf_line_t * p) -{ - BlockHeapFree(linebuf_heap, p); -} - -/* - * linebuf_new_line - * - * Create a new line, and link it to the given linebuf. - * It will be initially empty. - */ -static buf_line_t * -linebuf_new_line(buf_head_t * bufhead) -{ - buf_line_t *bufline; - dlink_node *node; - - bufline = linebuf_allocate(); - if(bufline == NULL) - return NULL; - ++bufline_count; - - - node = make_dlink_node(); - - bufline->len = 0; - bufline->terminated = 0; - bufline->flushing = 0; - bufline->raw = 0; - - /* Stick it at the end of the buf list */ - dlinkAddTail(bufline, node, &bufhead->list); - bufline->refcount++; - - /* And finally, update the allocated size */ - bufhead->alloclen++; - bufhead->numlines++; - - return bufline; -} - - -/* - * linebuf_done_line - * - * We've finished with the given line, so deallocate it - */ -static void -linebuf_done_line(buf_head_t * bufhead, buf_line_t * bufline, dlink_node * node) -{ - /* Remove it from the linked list */ - dlinkDestroy(node, &bufhead->list); - - /* Update the allocated size */ - bufhead->alloclen--; - bufhead->len -= bufline->len; - s_assert(bufhead->len >= 0); - bufhead->numlines--; - - bufline->refcount--; - s_assert(bufline->refcount >= 0); - - if(bufline->refcount == 0) - { - /* and finally, deallocate the buf */ - --bufline_count; - s_assert(bufline_count >= 0); - linebuf_free(bufline); - } -} - - -/* - * skip to end of line or the crlfs, return the number of bytes .. - */ -static inline int -linebuf_skip_crlf(char *ch, int len) -{ - int orig_len = len; - - /* First, skip until the first non-CRLF */ - for (; len; len--, ch++) - { - if(*ch == '\r') - break; - else if(*ch == '\n') - break; - } - - /* Then, skip until the last CRLF */ - for (; len; len--, ch++) - { - if((*ch != '\r') && (*ch != '\n')) - break; - } - s_assert(orig_len > len); - return (orig_len - len); -} - - - -/* - * linebuf_newbuf - * - * Initialise the new buffer - */ -void -linebuf_newbuf(buf_head_t * bufhead) -{ - /* not much to do right now :) */ - memset(bufhead, 0, sizeof(buf_head_t)); -} - -/* - * client_flush_input - * - * inputs - pointer to client - * output - none - * side effects - all input line bufs are flushed - */ -void -client_flush_input(struct Client *client_p) -{ - /* This way, it can be called for remote client as well */ - - if(client_p->localClient == NULL) - return; - - linebuf_donebuf(&client_p->localClient->buf_recvq); -} - - -/* - * linebuf_donebuf - * - * Flush all the lines associated with this buffer - */ -void -linebuf_donebuf(buf_head_t * bufhead) -{ - while (bufhead->list.head != NULL) - { - linebuf_done_line(bufhead, - (buf_line_t *) bufhead->list.head->data, bufhead->list.head); - } -} - -/* - * linebuf_copy_line - * - * Okay..this functions comments made absolutely no sense. - * - * Basically what we do is this. Find the first chunk of text - * and then scan for a CRLF. If we didn't find it, but we didn't - * overflow our buffer..we wait for some more data. - * If we found a CRLF, we replace them with a \0 character. - * If we overflowed, we copy the most our buffer can handle, terminate - * it with a \0 and return. - * - * The return value is the amount of data we consumed. This could - * be different than the size of the linebuffer, as when we discard - * the overflow, we don't want to process it again. - * - * This still sucks in my opinion, but it seems to work. - * - * -Aaron - */ -static int -linebuf_copy_line(buf_head_t * bufhead, buf_line_t * bufline, char *data, int len) -{ - int cpylen = 0; /* how many bytes we've copied */ - char *ch = data; /* Pointer to where we are in the read data */ - char *bufch = bufline->buf + bufline->len; - int clen = 0; /* how many bytes we've processed, - and don't ever want to see again.. */ - - /* If its full or terminated, ignore it */ - - bufline->raw = 0; - s_assert(bufline->len < BUF_DATA_SIZE); - if(bufline->terminated == 1) - return 0; - - clen = cpylen = linebuf_skip_crlf(ch, len); - if(clen == -1) - return -1; - - /* This is the ~overflow case..This doesn't happen often.. */ - if(cpylen > (BUF_DATA_SIZE - bufline->len - 1)) - { - memcpy(bufch, ch, (BUF_DATA_SIZE - bufline->len - 1)); - bufline->buf[BUF_DATA_SIZE - 1] = '\0'; - bufch = bufline->buf + BUF_DATA_SIZE - 2; - while (cpylen && (*bufch == '\r' || *bufch == '\n')) - { - *bufch = '\0'; - cpylen--; - bufch--; - } - bufline->terminated = 1; - bufline->len = BUF_DATA_SIZE - 1; - bufhead->len += BUF_DATA_SIZE - 1; - return clen; - } - - memcpy(bufch, ch, cpylen); - bufch += cpylen; - *bufch = '\0'; - bufch--; - - if(*bufch != '\r' && *bufch != '\n') - { - /* No linefeed, bail for the next time */ - bufhead->len += cpylen; - bufline->len += cpylen; - bufline->terminated = 0; - return clen; - } - - /* Yank the CRLF off this, replace with a \0 */ - while (cpylen && (*bufch == '\r' || *bufch == '\n')) - { - *bufch = '\0'; - cpylen--; - bufch--; - } - - bufline->terminated = 1; - bufhead->len += cpylen; - bufline->len += cpylen; - return clen; -} - -/* - * linebuf_copy_raw - * - * Copy as much data as possible directly into a linebuf, - * splitting at \r\n, but without altering any data. - * - */ -static int -linebuf_copy_raw(buf_head_t * bufhead, buf_line_t * bufline, char *data, int len) -{ - int cpylen = 0; /* how many bytes we've copied */ - char *ch = data; /* Pointer to where we are in the read data */ - char *bufch = bufline->buf + bufline->len; - int clen = 0; /* how many bytes we've processed, - and don't ever want to see again.. */ - - /* If its full or terminated, ignore it */ - - bufline->raw = 1; - s_assert(bufline->len < BUF_DATA_SIZE); - if(bufline->terminated == 1) - return 0; - - clen = cpylen = linebuf_skip_crlf(ch, len); - if(clen == -1) - return -1; - - /* This is the overflow case..This doesn't happen often.. */ - if(cpylen > (BUF_DATA_SIZE - bufline->len - 1)) - { - clen = BUF_DATA_SIZE - bufline->len - 1; - memcpy(bufch, ch, clen); - bufline->buf[BUF_DATA_SIZE - 1] = '\0'; - bufch = bufline->buf + BUF_DATA_SIZE - 2; - bufline->terminated = 1; - bufline->len = BUF_DATA_SIZE - 1; - bufhead->len += BUF_DATA_SIZE - 1; - return clen; - } - - memcpy(bufch, ch, cpylen); - bufch += cpylen; - *bufch = '\0'; - bufch--; - - if(*bufch != '\r' && *bufch != '\n') - { - /* No linefeed, bail for the next time */ - bufhead->len += cpylen; - bufline->len += cpylen; - bufline->terminated = 0; - return clen; - } - - bufline->terminated = 1; - bufhead->len += cpylen; - bufline->len += cpylen; - return clen; -} - - -/* - * linebuf_parse - * - * Take a given buffer and break out as many buffers as we can. - * If we find a CRLF, we terminate that buffer and create a new one. - * If we don't find a CRLF whilst parsing a buffer, we don't mark it - * 'finished', so the next loop through we can continue appending .. - * - * A few notes here, which you'll need to understand before continuing. - * - * - right now I'm only dealing with single sized buffers. Later on, - * I might consider chaining buffers together to get longer "lines" - * but seriously, I don't see the advantage right now. - * - * - This *is* designed to turn into a reference-counter-protected setup - * to dodge copious copies. - */ -int -linebuf_parse(buf_head_t * bufhead, char *data, int len, int raw) -{ - buf_line_t *bufline; - int cpylen; - int linecnt = 0; - - /* First, if we have a partial buffer, try to squeze data into it */ - if(bufhead->list.tail != NULL) - { - /* Check we're doing the partial buffer thing */ - bufline = bufhead->list.tail->data; - s_assert(!bufline->flushing); - /* just try, the worst it could do is *reject* us .. */ - if(!raw) - cpylen = linebuf_copy_line(bufhead, bufline, data, len); - else - cpylen = linebuf_copy_raw(bufhead, bufline, data, len); - - if(cpylen == -1) - return -1; - - linecnt++; - /* If we've copied the same as what we've got, quit now */ - if(cpylen == len) - return linecnt; /* all the data done so soon? */ - - /* Skip the data and update len .. */ - len -= cpylen; - s_assert(len >= 0); - data += cpylen; - } - - /* Next, the loop */ - while (len > 0) - { - /* We obviously need a new buffer, so .. */ - bufline = linebuf_new_line(bufhead); - - /* And parse */ - if(!raw) - cpylen = linebuf_copy_line(bufhead, bufline, data, len); - else - cpylen = linebuf_copy_raw(bufhead, bufline, data, len); - - if(cpylen == -1) - return -1; - - len -= cpylen; - s_assert(len >= 0); - data += cpylen; - linecnt++; - } - return linecnt; -} - - -/* - * linebuf_get - * - * get the next buffer from our line. For the time being it will copy - * data into the given buffer and free the underlying linebuf. - */ -int -linebuf_get(buf_head_t * bufhead, char *buf, int buflen, int partial, int raw) -{ - buf_line_t *bufline; - int cpylen; - char *start, *ch; - - /* make sure we have a line */ - if(bufhead->list.head == NULL) - return 0; /* Obviously not.. hrm. */ - - bufline = bufhead->list.head->data; - - /* make sure that the buffer was actually *terminated */ - if(!(partial || bufline->terminated)) - return 0; /* Wait for more data! */ - - /* make sure we've got the space, including the NULL */ - cpylen = bufline->len; - s_assert(cpylen + 1 <= buflen); - - /* Copy it */ - start = bufline->buf; - - /* if we left extraneous '\r\n' characters in the string, - * and we don't want to read the raw data, clean up the string. - */ - if(bufline->raw && !raw) - { - /* skip leading EOL characters */ - while (cpylen && (*start == '\r' || *start == '\n')) - { - start++; - cpylen--; - } - /* skip trailing EOL characters */ - ch = &start[cpylen - 1]; - while (cpylen && (*ch == '\r' || *ch == '\n')) - { - ch--; - cpylen--; - } - } - memcpy(buf, start, cpylen + 1); - - /* convert CR/LF to NULL */ - if(bufline->raw && !raw) - buf[cpylen] = '\0'; - - s_assert(cpylen >= 0); - - /* Deallocate the line */ - linebuf_done_line(bufhead, bufline, bufhead->list.head); - - /* return how much we copied */ - return cpylen; -} - -/* - * linebuf_attach - * - * attach the lines in a buf_head_t to another buf_head_t - * without copying the data (using refcounts). - */ -void -linebuf_attach(buf_head_t * bufhead, buf_head_t * new) -{ - dlink_node *ptr; - buf_line_t *line; - - DLINK_FOREACH(ptr, new->list.head) - { - line = ptr->data; - dlinkAddTailAlloc(line, &bufhead->list); - - /* Update the allocated size */ - bufhead->alloclen++; - bufhead->len += line->len; - bufhead->numlines++; - - line->refcount++; - } -} - -/* - * linebuf_putmsg - * - * Similar to linebuf_put, but designed for use by send.c. - * - * prefixfmt is used as a format for the varargs, and is inserted first. - * Then format/va_args is appended to the buffer. - */ -void -linebuf_putmsg(buf_head_t * bufhead, const char *format, va_list * va_args, - const char *prefixfmt, ...) -{ - buf_line_t *bufline; - int len = 0; - va_list prefix_args; - - /* make sure the previous line is terminated */ -#ifndef NDEBUG - if(bufhead->list.tail) - { - bufline = bufhead->list.tail->data; - s_assert(bufline->terminated); - } -#endif - /* Create a new line */ - bufline = linebuf_new_line(bufhead); - - if(prefixfmt != NULL) - { - va_start(prefix_args, prefixfmt); - len = ircvsnprintf(bufline->buf, BUF_DATA_SIZE, prefixfmt, prefix_args); - va_end(prefix_args); - } - - if(va_args != NULL) - { - len += ircvsnprintf((bufline->buf + len), (BUF_DATA_SIZE - len), format, *va_args); - } - - bufline->terminated = 1; - - /* Truncate the data if required */ - if(len > 510) - { - len = 510; - bufline->buf[len++] = '\r'; - bufline->buf[len++] = '\n'; - } - else if(len == 0) - { - bufline->buf[len++] = '\r'; - bufline->buf[len++] = '\n'; - bufline->buf[len] = '\0'; - } - else - { - /* Chop trailing CRLF's .. */ - while ((bufline->buf[len] == '\r') - || (bufline->buf[len] == '\n') || (bufline->buf[len] == '\0')) - { - len--; - } - - bufline->buf[++len] = '\r'; - bufline->buf[++len] = '\n'; - bufline->buf[++len] = '\0'; - } - - bufline->len = len; - bufhead->len += len; -} - - - -/* - * linebuf_flush - * - * Flush data to the buffer. It tries to write as much data as possible - * to the given socket. Any return values are passed straight through. - * If there is no data in the socket, EWOULDBLOCK is set as an errno - * rather than returning 0 (which would map to an EOF..) - * - * Notes: XXX We *should* have a clue here when a non-full buffer is arrived. - * and tag it so that we don't re-schedule another write until - * we have a CRLF. - */ - -int -linebuf_flush(fde_t *fd, buf_head_t * bufhead) -{ - buf_line_t *bufline; - int retval; - /* Check we actually have a first buffer */ - if(bufhead->list.head == NULL) - { - /* nope, so we return none .. */ - errno = EWOULDBLOCK; - return -1; - } - - bufline = bufhead->list.head->data; - - /* And that its actually full .. */ - if(!bufline->terminated) - { - errno = EWOULDBLOCK; - return -1; - } - - /* Check we're flushing the first buffer */ - if(!bufline->flushing) - { - bufline->flushing = 1; - bufhead->writeofs = 0; - } - - /* Now, try writing data */ - retval = fd->write_impl(fd, bufline->buf + bufhead->writeofs, bufline->len - bufhead->writeofs); - - if(retval <= 0) - return retval; - - /* we've got data, so update the write offset */ - bufhead->writeofs += retval; - - /* if we've written everything *and* the CRLF, deallocate and update - bufhead */ - if(bufhead->writeofs == bufline->len) - { - bufhead->writeofs = 0; - s_assert(bufhead->len >= 0); - linebuf_done_line(bufhead, bufline, bufhead->list.head); - } - - /* Return line length */ - return retval; -} - - - -/* - * count linebufs for stats z - */ - -void -count_linebuf_memory(size_t * count, size_t * linebuf_memory_used) -{ - BlockHeapUsage(linebuf_heap, count, NULL, linebuf_memory_used); -} diff --git a/libcharybdis/linebuf.h b/libcharybdis/linebuf.h deleted file mode 100644 index df84dbc..0000000 --- a/libcharybdis/linebuf.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * linebuf.h: A header for the linebuf code. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2004 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: linebuf.h 376 2005-12-07 15:00:41Z nenolod $ - */ - -#ifndef __LINEBUF_H__ -#define __LINEBUF_H__ - -#include "tools.h" -#include "commio.h" - -/* How big we want a buffer - 510 data bytes, plus space for a '\0' */ -#define BUF_DATA_SIZE 511 - -#define LINEBUF_COMPLETE 0 -#define LINEBUF_PARTIAL 1 -#define LINEBUF_PARSED 0 -#define LINEBUF_RAW 1 - -struct _buf_line; -struct _buf_head; - -typedef struct _buf_line buf_line_t; -typedef struct _buf_head buf_head_t; - -struct _buf_line -{ - char buf[BUF_DATA_SIZE + 2]; - unsigned int terminated; /* Whether we've terminated the buffer */ - unsigned int flushing; /* Whether we're flushing .. */ - unsigned int raw; /* Whether this linebuf may hold 8-bit data */ - int len; /* How much data we've got */ - int refcount; /* how many linked lists are we in? */ - struct _buf_line *next; /* next in free list */ -}; - -struct _buf_head -{ - dlink_list list; /* the actual dlink list */ - int len; /* length of all the data */ - int alloclen; /* Actual allocated data length */ - int writeofs; /* offset in the first line for the write */ - int numlines; /* number of lines */ -}; - -/* they should be functions, but .. */ -#define linebuf_len(x) ((x)->len) -#define linebuf_alloclen(x) ((x)->alloclen) -#define linebuf_numlines(x) ((x)->numlines) - -extern void linebuf_init(void); -/* declared as static */ -/* extern buf_line_t *linebuf_new_line(buf_head_t *); */ -/* extern void linebuf_done_line(buf_head_t *, buf_line_t *, dlink_node *); */ -/* extern int linebuf_skip_crlf(char *, int); */ -/* extern void linebuf_terminate_crlf(buf_head_t *, buf_line_t *); */ -extern void linebuf_newbuf(buf_head_t *); -extern void client_flush_input(struct Client *); -extern void linebuf_donebuf(buf_head_t *); -extern int linebuf_parse(buf_head_t *, char *, int, int); -extern int linebuf_get(buf_head_t *, char *, int, int, int); -extern void linebuf_putmsg(buf_head_t *, const char *, va_list *, const char *, ...); -extern int linebuf_flush(fde_t *, buf_head_t *); -extern void linebuf_attach(buf_head_t *, buf_head_t *); -extern void count_linebuf_memory(size_t *, size_t *); -#endif diff --git a/libcharybdis/memory.c b/libcharybdis/memory.c deleted file mode 100644 index c2c5c11..0000000 --- a/libcharybdis/memory.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * memory.c: Memory utilities. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: memory.c 388 2005-12-07 16:34:40Z nenolod $ - */ - - -#define WE_ARE_MEMORY_C - -#include "libcharybdis.h" - -/* - * MyMalloc - allocate memory, call outofmemory on failure - */ -void * -MyMalloc(size_t size) -{ - void *ret = calloc(1, size); - if(ret == NULL) - outofmemory(); - return ret; -} - -/* - * MyRealloc - reallocate memory, call outofmemory on failure - */ -void * -MyRealloc(void *x, size_t y) -{ - void *ret = realloc(x, y); - - if(ret == NULL) - outofmemory(); - return ret; -} - -/* - * outofmemory() - * - * input - NONE - * output - NONE - * side effects - simply try to report there is a problem. Abort if it was called more than once - */ -void -outofmemory() -{ - static int was_here = 0; - - if(was_here) - libcharybdis_die("Out of Memory!"); - - was_here = 1; - - libcharybdis_restart("Aiee! Out of memory... >_ -#else /* No inttypes.h */ -#ifndef HAVE_UINTPTR_T -typedef unsigned long uintptr_t; -#endif -#endif - -extern void outofmemory(void); - -extern void *MyMalloc(size_t size); -extern void *MyRealloc(void *x, size_t y); - -/* forte (and maybe others) dont like double declarations, - * so we dont declare the inlines unless GNUC - */ -/* darwin doesnt like these.. */ -#ifndef __APPLE__ - -#ifdef __GNUC__ -extern inline void * -MyMalloc(size_t size) -{ - void *ret = calloc(1, size); - if(ret == NULL) - outofmemory(); - return (ret); -} - -extern inline void * -MyRealloc(void *x, size_t y) -{ - void *ret = realloc(x, y); - - if(ret == NULL) - outofmemory(); - return (ret); -} - -#endif /* __GNUC__ */ -#endif /* __APPLE__ */ - -#define MyFree(x) do { if(x) free(x); } while (0) - -#endif /* _I_MEMORY_H */ diff --git a/libcharybdis/poll.c b/libcharybdis/poll.c deleted file mode 100644 index 407fb61..0000000 --- a/libcharybdis/poll.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * s_bsd_poll.c: POSIX poll() compatible network routines. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2001 Adrian Chadd - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: poll.c 3528 2007-07-07 08:08:23Z nenolod $ - */ - -#include "config.h" -#include "stdinc.h" -#include - -#include "libcharybdis.h" - -/* I hate linux -- adrian */ -#ifndef POLLRDNORM -#define POLLRDNORM POLLIN -#endif -#ifndef POLLWRNORM -#define POLLWRNORM POLLOUT -#endif - -struct _pollfd_list -{ - struct pollfd *pollfds; - int maxindex; /* highest FD number */ - int allocated; -}; - -typedef struct _pollfd_list pollfd_list_t; - -pollfd_list_t pollfd_list; -static void poll_update_pollfds(int, short, PF *); -static unsigned long last_count = 0; -static unsigned long empty_count = 0; - -/* - * init_netio - * - * This is a needed exported function which will be called to initialise - * the network loop code. - */ -void -init_netio(void) -{ - int fd; - int maxconn = comm_get_maxconnections(); - - pollfd_list.pollfds = calloc(sizeof(struct pollfd), maxconn); - - for (fd = 0; fd < maxconn; fd++) - pollfd_list.pollfds[fd].fd = -1; - - pollfd_list.maxindex = 0; - pollfd_list.allocated = maxconn; -} - -static inline void -resize_poll_array(int fd) -{ - int i, old_value = pollfd_list.allocated; - - if (fd < pollfd_list.allocated) - return; - - pollfd_list.allocated += 1024; - pollfd_list.pollfds = MyRealloc(pollfd_list.pollfds, pollfd_list.allocated * sizeof(struct pollfd)); - - /* because realloced memory can contain junk, we have to zero it out. */ - memset(&pollfd_list.pollfds[old_value+1], 0, sizeof(struct pollfd) * 1024); - - for (i = old_value + 1; i <= pollfd_list.allocated; i++) - pollfd_list.pollfds[i].fd = -1; -} - -/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* Private functions */ - -/* - * find a spare slot in the fd list. We can optimise this out later! - * -- adrian - */ -static inline int -poll_findslot(void) -{ - int i; - for (i = 0; i < pollfd_list.allocated; i++) - { - if(pollfd_list.pollfds[i].fd == -1) - { - /* MATCH!!#$*&$ */ - return i; - } - } - - s_assert(1 == 0); - /* NOTREACHED */ - return -1; -} - -/* - * set and clear entries in the pollfds[] array. - */ -static void -poll_update_pollfds(int fd, short event, PF * handler) -{ - fde_t *F = comm_locate_fd(fd); - int comm_index; - - resize_poll_array(fd); - - if (F == NULL) - F = comm_add_fd(fd); - - if(F->comm_index < 0) - F->comm_index = poll_findslot(); - - comm_index = F->comm_index; - - /* Update the events */ - if(handler) - { - F->list = FDLIST_IDLECLIENT; - pollfd_list.pollfds[comm_index].events |= event; - pollfd_list.pollfds[comm_index].fd = fd; - /* update maxindex here */ - if(comm_index > pollfd_list.maxindex) - pollfd_list.maxindex = comm_index; - } - else - { - if(comm_index >= 0) - { - pollfd_list.pollfds[comm_index].events &= ~event; - if(pollfd_list.pollfds[comm_index].events == 0) - { - pollfd_list.pollfds[comm_index].fd = -1; - pollfd_list.pollfds[comm_index].revents = 0; - F->comm_index = -1; - F->list = FDLIST_NONE; - - /* update pollfd_list.maxindex here */ - if(comm_index == pollfd_list.maxindex) - while (pollfd_list.maxindex >= 0 && - pollfd_list.pollfds[pollfd_list.maxindex].fd == -1) - pollfd_list.maxindex--; - } - } - } -} - - -/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* Public functions */ - -/* - * comm_setselect - * - * This is a needed exported function which will be called to register - * and deregister interest in a pending IO state for a given FD. - */ -void -comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler, - void *client_data, time_t timeout) -{ - fde_t *F = comm_locate_fd(fd); - s_assert(fd >= 0); - s_assert(F->flags.open); - - if(type & COMM_SELECT_READ) - { - F->read_handler = handler; - F->read_data = client_data; - poll_update_pollfds(fd, POLLRDNORM, handler); - } - if(type & COMM_SELECT_WRITE) - { - F->write_handler = handler; - F->write_data = client_data; - poll_update_pollfds(fd, POLLWRNORM, handler); - } - if(timeout) - F->timeout = CurrentTime + (timeout / 1000); -} - -static void -irc_sleep(unsigned long useconds) -{ -#ifdef HAVE_NANOSLEEP - struct timespec t; - t.tv_sec = useconds / (unsigned long) 1000000; - t.tv_nsec = (useconds % (unsigned long) 1000000) * 1000; - nanosleep(&t, (struct timespec *) NULL); -#else - struct timeval t; - t.tv_sec = 0; - t.tv_usec = useconds; - select(0, NULL, NULL, NULL, &t); -#endif - return; -} - -/* int comm_select_fdlist(unsigned long delay) - * Input: The maximum time to delay. - * Output: Returns -1 on error, 0 on success. - * Side-effects: Deregisters future interest in IO and calls the handlers - * if an event occurs for an FD. - * Comments: Check all connections for new connections and input data - * that is to be processed. Also check for connections with data queued - * and whether we can write it out. - * Called to do the new-style IO, courtesy of squid (like most of this - * new IO code). This routine handles the stuff we've hidden in - * comm_setselect and fd_table[] and calls callbacks for IO ready - * events. - */ -int -comm_select(unsigned long delay) -{ - int num; - int fd; - int ci; - unsigned long ndelay; - PF *hdl; - - if(last_count > 0) - { - empty_count = 0; - ndelay = 0; - } - else { - ndelay = ++empty_count * 15000 ; - if(ndelay > delay * 1000) - ndelay = delay * 1000; - } - - for (;;) - { - /* XXX kill that +1 later ! -- adrian */ - if(ndelay > 0) - irc_sleep(ndelay); - last_count = num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, 0); - if(num >= 0) - break; - if(ignoreErrno(errno)) - continue; - /* error! */ - set_time(); - return -1; - /* NOTREACHED */ - } - - /* update current time again, eww.. */ - set_time(); - - if(num == 0) - return 0; - /* XXX we *could* optimise by falling out after doing num fds ... */ - for (ci = 0; ci < pollfd_list.maxindex + 1; ci++) - { - fde_t *F; - int revents; - if(((revents = pollfd_list.pollfds[ci].revents) == 0) || - (pollfd_list.pollfds[ci].fd) == -1) - continue; - fd = pollfd_list.pollfds[ci].fd; - F = comm_locate_fd(fd); - if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) - { - hdl = F->read_handler; - F->read_handler = NULL; - poll_update_pollfds(fd, POLLRDNORM, NULL); - if(hdl) - hdl(fd, F->read_data); - } - if(revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) - { - hdl = F->write_handler; - F->write_handler = NULL; - poll_update_pollfds(fd, POLLWRNORM, NULL); - if(hdl) - hdl(fd, F->write_data); - } - } - return 0; -} - diff --git a/libcharybdis/ports.c b/libcharybdis/ports.c deleted file mode 100644 index a0fdead..0000000 --- a/libcharybdis/ports.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * charybdis: A slightly useful ircd. - * ports.c: Solaris ports compatible network routines. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2001 Adrian Chadd - * Copyright (C) 2002-2004 ircd-ratbox development team - * Copyright (C) 2005 Edward Brocklesby. - * Copyright (C) 2005 William Pitcock and Jilles Tjoelker - * Copyright (C) 2007 River Tarnell - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: ports.c 3366 2007-04-03 09:57:53Z nenolod $ - */ - -#include "stdinc.h" -#include -#include - -#include "stdinc.h" -#include "res.h" -#include "numeric.h" -#include "tools.h" -#include "memory.h" -#include "balloc.h" -#include "linebuf.h" -#include "sprintf_irc.h" -#include "commio.h" -#include "ircevent.h" -#include "modules.h" - -static int comm_init(void); -static void comm_deinit(void); - -static int comm_select_impl(unsigned long delay); -static void comm_setselect_impl(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout); - -static void pe_update_events(fde_t *, short, PF *); -static int pe; -static struct timespec zero_timespec; - -static port_event_t *pelst; /* port buffer */ -static int pemax; /* max structs to buffer */ - -static void -pe_update_events(fde_t * F, short filter, PF * handler) -{ - PF *cur_handler = NULL; - - if (filter == POLLRDNORM) - cur_handler = F->read_handler; - else if (filter == POLLWRNORM) - cur_handler = F->write_handler; - - if (!cur_handler && handler) - port_associate(pe, PORT_SOURCE_FD, F->fd, filter, F); - else if (cur_handler && !handler) - port_dissociate(pe, PORT_SOURCE_FD, F->fd); -} - -/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* Public functions */ - - -/* - * init_netio - * - * This is a needed exported function which will be called to initialise - * the network loop code. - */ -static int -init_netio(void) -{ - if((pe = port_create()) < 0) { - ilog(L_MAIN, "init_netio: Couldn't open port fd!\n"); - exit(115); /* Whee! */ - } - pemax = getdtablesize(); - pelst = MyMalloc(sizeof(port_event_t) * pemax); - zero_timespec.tv_sec = 0; - zero_timespec.tv_nsec = 0; - - return 0; -} - -/* - * ircd_setselect - * - * This is a needed exported function which will be called to register - * and deregister interest in a pending IO state for a given FD. - */ -void -comm_setselect(int fd, unsigned int type, PF * handler, - void *client_data, time_t timeout) -{ - fde_t *F = &fd_table[fd]; - s_assert(fd >= 0); - s_assert(F->flags.open); - - if (type & COMM_SELECT_READ) { - pe_update_events(F, POLLRDNORM, handler); - F->read_handler = handler; - F->read_data = client_data; - } - if (type & COMM_SELECT_WRITE) { - pe_update_events(F, POLLWRNORM, handler); - F->write_handler = handler; - F->write_data = client_data; - } -} - -/* - * ircd_select - * - * Called to do the new-style IO, courtesy of squid (like most of this - * new IO code). This routine handles the stuff we've hidden in - * ircd_setselect and fd_table[] and calls callbacks for IO ready - * events. - */ - -int -comm_select(unsigned long delay) -{ - int i, fd; - unsigned int nget = 1; - struct timespec poll_time; - - poll_time.tv_sec = delay / 1000; - poll_time.tv_nsec = (delay % 1000) * 1000000; - - i = port_getn(pe, pelst, pemax, &nget, &poll_time); - set_time(); - - if (i == -1) - return COMM_ERROR; - - for (i = 0; i < nget; i++) - { - PF *hdl = NULL; - fde_t *F; - - switch(pelst[i].portev_source) - { - case PORT_SOURCE_FD: - fd = pelst[i].portev_object; - F = &fd_table[fd]; - - if ((pelst[i].portev_events & POLLRDNORM) && (hdl = F->read_handler)) { - F->read_handler = NULL; - hdl(fd, F->read_data); - } - if (F->flags.open == 0) - continue; - - if ((pelst[i].portev_events & POLLWRNORM) && (hdl = F->write_handler)) { - F->write_handler = NULL; - hdl(fd, F->write_data); - } - break; - default: - break; - } - } - return COMM_OK; -} diff --git a/libcharybdis/select.c b/libcharybdis/select.c deleted file mode 100644 index d019203..0000000 --- a/libcharybdis/select.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * select.c: select() compatible network routines. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2001 Adrian Chadd - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: select.c 3528 2007-07-07 08:08:23Z nenolod $ - */ - -#include "config.h" - -#include "libcharybdis.h" - -/* - * Note that this is only a single list - multiple lists is kinda pointless - * under select because the list size is a function of the highest FD :-) - * -- adrian - */ - -fd_set select_readfds; -fd_set select_writefds; - -/* - * You know, I'd rather have these local to comm_select but for some - * reason my gcc decides that I can't modify them at all.. - * -- adrian - */ -fd_set tmpreadfds; -fd_set tmpwritefds; - -static void select_update_selectfds(int fd, short event, PF * handler); - -/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* Private functions */ - -/* - * set and clear entries in the select array .. - */ -static void -select_update_selectfds(int fd, short event, PF * handler) -{ - /* Update the read / write set */ - if(event & COMM_SELECT_READ) - { - if(handler) - FD_SET(fd, &select_readfds); - else - FD_CLR(fd, &select_readfds); - } - if(event & COMM_SELECT_WRITE) - { - if(handler) - FD_SET(fd, &select_writefds); - else - FD_CLR(fd, &select_writefds); - } -} - - -/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* Public functions */ - - -/* - * init_netio - * - * This is a needed exported function which will be called to initialise - * the network loop code. - */ -void -init_netio(void) -{ - FD_ZERO(&select_readfds); - FD_ZERO(&select_writefds); -} - -/* - * comm_setselect - * - * This is a needed exported function which will be called to register - * and deregister interest in a pending IO state for a given FD. - */ -void -comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler, - void *client_data, time_t timeout) -{ - fde_t *F = comm_locate_fd(fd); - s_assert(fd >= 0); - - if (!F) - F = comm_add_fd(fd); - - if(type & COMM_SELECT_READ) - { - F->read_handler = handler; - F->read_data = client_data; - select_update_selectfds(fd, COMM_SELECT_READ, handler); - } - if(type & COMM_SELECT_WRITE) - { - F->write_handler = handler; - F->write_data = client_data; - select_update_selectfds(fd, COMM_SELECT_WRITE, handler); - } - if(timeout) - F->timeout = CurrentTime + (timeout / 1000); -} - -/* - * Check all connections for new connections and input data that is to be - * processed. Also check for connections with data queued and whether we can - * write it out. - */ - -/* - * comm_select - * - * Do IO events - */ - -int -comm_select(unsigned long delay) -{ - int num; - int fd; - PF *hdl; - fde_t *F; - struct timeval to; - - /* Copy over the read/write sets so we don't have to rebuild em */ - memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set)); - memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set)); - - for (;;) - { - to.tv_sec = 0; - to.tv_usec = delay * 1000; - num = select(highest_fd + 1, &tmpreadfds, &tmpwritefds, NULL, &to); - if(num >= 0) - break; - if(ignoreErrno(errno)) - continue; - set_time(); - /* error! */ - return -1; - /* NOTREACHED */ - } - set_time(); - - if(num == 0) - return 0; - - /* XXX we *could* optimise by falling out after doing num fds ... */ - for (fd = 0; fd < highest_fd + 1; fd++) - { - F = comm_locate_fd(fd); - - if(FD_ISSET(fd, &tmpreadfds)) - { - hdl = F->read_handler; - F->read_handler = NULL; - if(hdl) - hdl(fd, F->read_data); - } - - if(F->flags.open == 0) - continue; /* Read handler closed us..go on */ - - if(FD_ISSET(fd, &tmpwritefds)) - { - hdl = F->write_handler; - F->write_handler = NULL; - if(hdl) - hdl(fd, F->write_data); - } - - if(F->read_handler == NULL) - select_update_selectfds(fd, COMM_SELECT_READ, NULL); - if(F->write_handler == NULL) - select_update_selectfds(fd, COMM_SELECT_WRITE, NULL); - } - return 0; -} - diff --git a/libcharybdis/snprintf.c b/libcharybdis/snprintf.c deleted file mode 100644 index f71d5a6..0000000 --- a/libcharybdis/snprintf.c +++ /dev/null @@ -1,981 +0,0 @@ -/* - * libString, Copyright (C) 1999 Patrick Alken - * This library comes with absolutely NO WARRANTY - * - * Should you choose to use and/or modify this source code, please - * do so under the terms of the GNU General Public License under which - * this library is distributed. - * - * $Id: snprintf.c 382 2005-12-07 15:15:59Z nenolod $ - */ - -#include -#include -#include -#include -#include -#include "setup.h" -#include "sprintf_irc.h" - -/* - * This table is arranged in chronological order from 0-999, - * however the numbers are written backwards, so the number 100 - * is expressed in this table as "001". - * It's purpose is to ensure fast conversions from integers to - * ASCII strings. When an integer variable is encountered, a - * simple hash algorithm is used to determine where to look - * in this array for the corresponding string. - * This outperforms continually dividing by 10 and using the - * digit obtained as a character, because we can now divide by - * 1000 and use the remainder directly, thus cutting down on - * the number of costly divisions needed. For an integer's worst - * case, 2 divisions are needed because it can only go up to - * 32767, so after 2 divisions by 1000, and some algebra, we will - * be left with 327 which we can get from this table. This is much - * better than the 5 divisions by 10 that we would need if we did - * it the conventional way. Of course, if we made this table go - * from 0-9999, only 1 division would be needed. - * Longs and unsigned ints of course, are another matter :-). - * - * Patrick Alken - */ - -/* - * Set this to the number of indices (numbers) in our table - */ -#define TABLE_MAX 1000 - -static const char *IntTable[] = { - "000", "100", "200", "300", "400", - "500", "600", "700", "800", "900", - "010", "110", "210", "310", "410", - "510", "610", "710", "810", "910", - "020", "120", "220", "320", "420", - "520", "620", "720", "820", "920", - "030", "130", "230", "330", "430", - "530", "630", "730", "830", "930", - "040", "140", "240", "340", "440", - "540", "640", "740", "840", "940", - "050", "150", "250", "350", "450", - "550", "650", "750", "850", "950", - "060", "160", "260", "360", "460", - "560", "660", "760", "860", "960", - "070", "170", "270", "370", "470", - "570", "670", "770", "870", "970", - "080", "180", "280", "380", "480", - "580", "680", "780", "880", "980", - "090", "190", "290", "390", "490", - "590", "690", "790", "890", "990", - "001", "101", "201", "301", "401", - "501", "601", "701", "801", "901", - "011", "111", "211", "311", "411", - "511", "611", "711", "811", "911", - "021", "121", "221", "321", "421", - "521", "621", "721", "821", "921", - "031", "131", "231", "331", "431", - "531", "631", "731", "831", "931", - "041", "141", "241", "341", "441", - "541", "641", "741", "841", "941", - "051", "151", "251", "351", "451", - "551", "651", "751", "851", "951", - "061", "161", "261", "361", "461", - "561", "661", "761", "861", "961", - "071", "171", "271", "371", "471", - "571", "671", "771", "871", "971", - "081", "181", "281", "381", "481", - "581", "681", "781", "881", "981", - "091", "191", "291", "391", "491", - "591", "691", "791", "891", "991", - "002", "102", "202", "302", "402", - "502", "602", "702", "802", "902", - "012", "112", "212", "312", "412", - "512", "612", "712", "812", "912", - "022", "122", "222", "322", "422", - "522", "622", "722", "822", "922", - "032", "132", "232", "332", "432", - "532", "632", "732", "832", "932", - "042", "142", "242", "342", "442", - "542", "642", "742", "842", "942", - "052", "152", "252", "352", "452", - "552", "652", "752", "852", "952", - "062", "162", "262", "362", "462", - "562", "662", "762", "862", "962", - "072", "172", "272", "372", "472", - "572", "672", "772", "872", "972", - "082", "182", "282", "382", "482", - "582", "682", "782", "882", "982", - "092", "192", "292", "392", "492", - "592", "692", "792", "892", "992", - "003", "103", "203", "303", "403", - "503", "603", "703", "803", "903", - "013", "113", "213", "313", "413", - "513", "613", "713", "813", "913", - "023", "123", "223", "323", "423", - "523", "623", "723", "823", "923", - "033", "133", "233", "333", "433", - "533", "633", "733", "833", "933", - "043", "143", "243", "343", "443", - "543", "643", "743", "843", "943", - "053", "153", "253", "353", "453", - "553", "653", "753", "853", "953", - "063", "163", "263", "363", "463", - "563", "663", "763", "863", "963", - "073", "173", "273", "373", "473", - "573", "673", "773", "873", "973", - "083", "183", "283", "383", "483", - "583", "683", "783", "883", "983", - "093", "193", "293", "393", "493", - "593", "693", "793", "893", "993", - "004", "104", "204", "304", "404", - "504", "604", "704", "804", "904", - "014", "114", "214", "314", "414", - "514", "614", "714", "814", "914", - "024", "124", "224", "324", "424", - "524", "624", "724", "824", "924", - "034", "134", "234", "334", "434", - "534", "634", "734", "834", "934", - "044", "144", "244", "344", "444", - "544", "644", "744", "844", "944", - "054", "154", "254", "354", "454", - "554", "654", "754", "854", "954", - "064", "164", "264", "364", "464", - "564", "664", "764", "864", "964", - "074", "174", "274", "374", "474", - "574", "674", "774", "874", "974", - "084", "184", "284", "384", "484", - "584", "684", "784", "884", "984", - "094", "194", "294", "394", "494", - "594", "694", "794", "894", "994", - "005", "105", "205", "305", "405", - "505", "605", "705", "805", "905", - "015", "115", "215", "315", "415", - "515", "615", "715", "815", "915", - "025", "125", "225", "325", "425", - "525", "625", "725", "825", "925", - "035", "135", "235", "335", "435", - "535", "635", "735", "835", "935", - "045", "145", "245", "345", "445", - "545", "645", "745", "845", "945", - "055", "155", "255", "355", "455", - "555", "655", "755", "855", "955", - "065", "165", "265", "365", "465", - "565", "665", "765", "865", "965", - "075", "175", "275", "375", "475", - "575", "675", "775", "875", "975", - "085", "185", "285", "385", "485", - "585", "685", "785", "885", "985", - "095", "195", "295", "395", "495", - "595", "695", "795", "895", "995", - "006", "106", "206", "306", "406", - "506", "606", "706", "806", "906", - "016", "116", "216", "316", "416", - "516", "616", "716", "816", "916", - "026", "126", "226", "326", "426", - "526", "626", "726", "826", "926", - "036", "136", "236", "336", "436", - "536", "636", "736", "836", "936", - "046", "146", "246", "346", "446", - "546", "646", "746", "846", "946", - "056", "156", "256", "356", "456", - "556", "656", "756", "856", "956", - "066", "166", "266", "366", "466", - "566", "666", "766", "866", "966", - "076", "176", "276", "376", "476", - "576", "676", "776", "876", "976", - "086", "186", "286", "386", "486", - "586", "686", "786", "886", "986", - "096", "196", "296", "396", "496", - "596", "696", "796", "896", "996", - "007", "107", "207", "307", "407", - "507", "607", "707", "807", "907", - "017", "117", "217", "317", "417", - "517", "617", "717", "817", "917", - "027", "127", "227", "327", "427", - "527", "627", "727", "827", "927", - "037", "137", "237", "337", "437", - "537", "637", "737", "837", "937", - "047", "147", "247", "347", "447", - "547", "647", "747", "847", "947", - "057", "157", "257", "357", "457", - "557", "657", "757", "857", "957", - "067", "167", "267", "367", "467", - "567", "667", "767", "867", "967", - "077", "177", "277", "377", "477", - "577", "677", "777", "877", "977", - "087", "187", "287", "387", "487", - "587", "687", "787", "887", "987", - "097", "197", "297", "397", "497", - "597", "697", "797", "897", "997", - "008", "108", "208", "308", "408", - "508", "608", "708", "808", "908", - "018", "118", "218", "318", "418", - "518", "618", "718", "818", "918", - "028", "128", "228", "328", "428", - "528", "628", "728", "828", "928", - "038", "138", "238", "338", "438", - "538", "638", "738", "838", "938", - "048", "148", "248", "348", "448", - "548", "648", "748", "848", "948", - "058", "158", "258", "358", "458", - "558", "658", "758", "858", "958", - "068", "168", "268", "368", "468", - "568", "668", "768", "868", "968", - "078", "178", "278", "378", "478", - "578", "678", "778", "878", "978", - "088", "188", "288", "388", "488", - "588", "688", "788", "888", "988", - "098", "198", "298", "398", "498", - "598", "698", "798", "898", "998", - "009", "109", "209", "309", "409", - "509", "609", "709", "809", "909", - "019", "119", "219", "319", "419", - "519", "619", "719", "819", "919", - "029", "129", "229", "329", "429", - "529", "629", "729", "829", "929", - "039", "139", "239", "339", "439", - "539", "639", "739", "839", "939", - "049", "149", "249", "349", "449", - "549", "649", "749", "849", "949", - "059", "159", "259", "359", "459", - "559", "659", "759", "859", "959", - "069", "169", "269", "369", "469", - "569", "669", "769", "869", "969", - "079", "179", "279", "379", "479", - "579", "679", "779", "879", "979", - "089", "189", "289", "389", "489", - "589", "689", "789", "889", "989", - "099", "199", "299", "399", "499", - "599", "699", "799", "899", "999" -}; - -/* - * Since we calculate the right-most digits for %d %u etc first, - * we need a temporary buffer to store them in until we get - * to the left-most digits - */ - -#define TEMPBUF_MAX 20 - -static char TempBuffer[TEMPBUF_MAX]; - -/* -vSnprintf() - Backend to Snprintf() - performs the construction of 'dest' -using the string 'format' and the given arguments. Also makes sure -not more than 'bytes' characters are copied to 'dest' - - We always allow room for a terminating \0 character, so at most, -bytes - 1 characters will be written to dest. - -Return: Number of characters written, NOT including the terminating - \0 character which is *always* placed at the end of the string - -NOTE: This function handles the following flags only: - %s %d %c %u %ld %lu - In addition, this function performs *NO* precision, padding, - or width formatting. If it receives an unknown % character, - it will call vsprintf() to complete the remainder of the - string. -*/ - -int -ircvsnprintf(char *dest, const size_t bytes, const char *format, va_list args) -{ - char ch; - int written = 0; /* bytes written so far */ - int maxbytes = bytes - 1; - - while ((ch = *format++) && (written < maxbytes)) - { - if(ch == '%') - { - /* - * Advance past the % - */ - ch = *format++; - - /* - * Put the most common cases first - %s %d etc - */ - - if(ch == 's') - { - const char *str = va_arg(args, const char *); - - while ((*dest = *str)) - { - ++dest; - ++str; - - if(++written >= maxbytes) - break; - } - - continue; - } - - if(ch == 'd') - { - int num = va_arg(args, int); - int quotient; - const char *str; - char *digitptr = TempBuffer; - - /* - * We have to special-case "0" unfortunately - */ - if(num == 0) - { - *dest++ = '0'; - ++written; - continue; - } - - if(num < 0) - { - *dest++ = '-'; - if(++written >= maxbytes) - continue; - - num = -num; - } - - do - { - quotient = num / TABLE_MAX; - - /* - * We'll start with the right-most digits of 'num'. - * Dividing by TABLE_MAX cuts off all but the X - * right-most digits, where X is such that: - * - * 10^X = TABLE_MAX - * - * For example, if num = 1200, and TABLE_MAX = 1000, - * quotient will be 1. Multiplying this by 1000 and - * subtracting from 1200 gives: 1200 - (1 * 1000) = 200. - * We then go right to slot 200 in our array and behold! - * The string "002" (200 backwards) is conveniently - * waiting for us. Then repeat the process with the - * digits left. - * - * The reason we need to have the integers written - * backwards, is because we don't know how many digits - * there are. If we want to express the number 12130 - * for example, our first pass would leave us with 130, - * whose slot in the array yields "031", which we - * plug into our TempBuffer[]. The next pass gives us - * 12, whose slot yields "21" which we append to - * TempBuffer[], leaving us with "03121". This is the - * exact number we want, only backwards, so it is - * a simple matter to reverse the string. If we used - * straightfoward numbers, we would have a TempBuffer - * looking like this: "13012" which would be a nightmare - * to deal with. - */ - - str = IntTable[num - (quotient * TABLE_MAX)]; - - while ((*digitptr = *str)) - { - ++digitptr; - ++str; - } - } - while ((num = quotient) != 0); - - /* - * If the last quotient was a 1 or 2 digit number, there - * will be one or more leading zeroes in TempBuffer[] - - * get rid of them. - */ - while (*(digitptr - 1) == '0') - --digitptr; - - while (digitptr != TempBuffer) - { - *dest++ = *--digitptr; - if(++written >= maxbytes) - break; - } - - continue; - } /* if (ch == 'd') */ - - if(ch == 'c') - { - *dest++ = va_arg(args, int); - - ++written; - - continue; - } /* if (ch == 'c') */ - - if(ch == 'u') - { - unsigned int num = va_arg(args, unsigned int); - unsigned int quotient; - const char *str; - char *digitptr = TempBuffer; - - if(num == 0) - { - *dest++ = '0'; - ++written; - continue; - } - - do - { - quotient = num / TABLE_MAX; - - /* - * Very similar to case 'd' - */ - - str = IntTable[num - (quotient * TABLE_MAX)]; - - while ((*digitptr = *str)) - { - ++digitptr; - ++str; - } - } - while ((num = quotient) != 0); - - while (*(digitptr - 1) == '0') - --digitptr; - - while (digitptr != TempBuffer) - { - *dest++ = *--digitptr; - if(++written >= maxbytes) - break; - } - - continue; - } /* if (ch == 'u') */ - - if(ch == 'l') - { - if(*format == 'u') - { - unsigned long num = va_arg(args, unsigned long); - unsigned long quotient; - const char *str; - char *digitptr = TempBuffer; - - ++format; - - if(num == 0) - { - *dest++ = '0'; - ++written; - continue; - } - - do - { - quotient = num / TABLE_MAX; - - /* - * Very similar to case 'u' - */ - - str = IntTable[num - (quotient * TABLE_MAX)]; - - while ((*digitptr = *str)) - { - ++digitptr; - ++str; - } - } - while ((num = quotient) != 0); - - while (*(digitptr - 1) == '0') - --digitptr; - - while (digitptr != TempBuffer) - { - *dest++ = *--digitptr; - if(++written >= maxbytes) - break; - } - - continue; - } else /* if (*format == 'u') */ - - if(*format == 'd') - { - long num = va_arg(args, long); - long quotient; - const char *str; - char *digitptr = TempBuffer; - - ++format; - - if(num == 0) - { - *dest++ = '0'; - ++written; - continue; - } - - if(num < 0) - { - *dest++ = '-'; - if(++written >= maxbytes) - continue; - - num = -num; - } - - do - { - quotient = num / TABLE_MAX; - - str = IntTable[num - (quotient * TABLE_MAX)]; - - while ((*digitptr = *str)) - { - ++digitptr; - ++str; - } - } - while ((num = quotient) != 0); - - while (*(digitptr - 1) == '0') - --digitptr; - - while (digitptr != TempBuffer) - { - *dest++ = *--digitptr; - if(++written >= maxbytes) - break; - } - - continue; - } else /* if (*format == 'd') */ - { - int ret; - format -= 2; - #ifdef HAVE_VSNPRINTF - ret = vsnprintf(dest, maxbytes - written, format, args); - #else - ret = vsprintf(dest, format, args); - #endif - dest += ret; - written += ret; - break; - } - - - } /* if (ch == 'l') */ - - if(ch != '%') - { - int ret; - - /* - * The character might be invalid, or be a precision, - * padding, or width specification - call vsprintf() - * to finish off the string - */ - - format -= 2; - #ifdef HAVE_VSNPRINTF - ret = vsnprintf(dest, maxbytes - written, format, args); - #else - ret = vsprintf(dest, format, args); - #endif - dest += ret; - written += ret; - - break; - } /* if (ch != '%') */ - } /* if (ch == '%') */ - - *dest++ = ch; - ++written; - } /* while ((ch = *format++) && (written < maxbytes)) */ - - /* - * Terminate the destination buffer with a \0 - */ - *dest = '\0'; - - return (written); -} /* vSnprintf() */ - -/* -ircvsprintf() - Backend to Sprintf() - performs the construction of 'dest' -using the string 'format' and the given arguments. - - We always place a \0 character onto the end of 'dest'. - -Return: Number of characters written, NOT including the terminating - \0 character which is *always* placed at the end of the string - -NOTE: This function handles the following flags only: - %s %d %c %u %ld %lu - In addition, this function performs *NO* precision, padding, - or width formatting. If it receives an unknown % character, - it will call vsprintf() to complete the remainder of the - string. -*/ - -int -ircvsprintf(char *dest, const char *format, va_list args) -{ - char ch; - int written = 0; /* bytes written so far */ - - while ((ch = *format++)) - { - if(ch == '%') - { - /* - * Advance past the % - */ - ch = *format++; - - /* - * Put the most common cases first - %s %d etc - */ - - if(ch == 's') - { - const char *str = va_arg(args, const char *); - - while ((*dest = *str)) - { - ++dest; - ++str; - - ++written; - } - - continue; - } /* if (ch == 's') */ - - - if(ch == 'd') - { - int num = va_arg(args, int); - int quotient; - const char *str; - char *digitptr = TempBuffer; - - /* - * We have to special-case "0" unfortunately - */ - if(num == 0) - { - *dest++ = '0'; - ++written; - continue; - } - - if(num < 0) - { - *dest++ = '-'; - ++written; - - num = -num; - } - - do - { - quotient = num / TABLE_MAX; - - /* - * We'll start with the right-most digits of 'num'. - * Dividing by TABLE_MAX cuts off all but the X - * right-most digits, where X is such that: - * - * 10^X = TABLE_MAX - * - * For example, if num = 1200, and TABLE_MAX = 1000, - * quotient will be 1. Multiplying this by 1000 and - * subtracting from 1200 gives: 1200 - (1 * 1000) = 200. - * We then go right to slot 200 in our array and behold! - * The string "002" (200 backwards) is conveniently - * waiting for us. Then repeat the process with the - * digits left. - * - * The reason we need to have the integers written - * backwards, is because we don't know how many digits - * there are. If we want to express the number 12130 - * for example, our first pass would leave us with 130, - * whose slot in the array yields "031", which we - * plug into our TempBuffer[]. The next pass gives us - * 12, whose slot yields "21" which we append to - * TempBuffer[], leaving us with "03121". This is the - * exact number we want, only backwards, so it is - * a simple matter to reverse the string. If we used - * straightfoward numbers, we would have a TempBuffer - * looking like this: "13012" which would be a nightmare - * to deal with. - */ - - str = IntTable[num - (quotient * TABLE_MAX)]; - - while ((*digitptr = *str)) - { - ++digitptr; - ++str; - } - } - while ((num = quotient) != 0); - - /* - * If the last quotient was a 1 or 2 digit number, there - * will be one or more leading zeroes in TempBuffer[] - - * get rid of them. - */ - while (*(digitptr - 1) == '0') - --digitptr; - - while (digitptr != TempBuffer) - { - *dest++ = *--digitptr; - ++written; - } - - continue; - } /* if (ch == 'd') */ - - if(ch == 'c') - { - *dest++ = va_arg(args, int); - - ++written; - - continue; - } /* if (ch == 'c') */ - - if(ch == 'u') - { - unsigned int num = va_arg(args, unsigned int); - unsigned int quotient; - const char *str; - char *digitptr = TempBuffer; - - if(num == 0) - { - *dest++ = '0'; - ++written; - continue; - } - - do - { - quotient = num / TABLE_MAX; - - /* - * Very similar to case 'd' - */ - - str = IntTable[num - (quotient * TABLE_MAX)]; - - while ((*digitptr = *str)) - { - ++digitptr; - ++str; - } - } - while ((num = quotient) != 0); - - while (*(digitptr - 1) == '0') - --digitptr; - - while (digitptr != TempBuffer) - { - *dest++ = *--digitptr; - ++written; - } - - continue; - } /* if (ch == 'u') */ - - if(ch == 'l') - { - if(*format == 'u') - { - unsigned long num = va_arg(args, unsigned long); - unsigned long quotient; - const char *str; - char *digitptr = TempBuffer; - - ++format; - - if(num == 0) - { - *dest++ = '0'; - ++written; - continue; - } - - do - { - quotient = num / TABLE_MAX; - - /* - * Very similar to case 'u' - */ - - str = IntTable[num - (quotient * TABLE_MAX)]; - - while ((*digitptr = *str)) - { - ++digitptr; - ++str; - } - } - while ((num = quotient) != 0); - - while (*(digitptr - 1) == '0') - --digitptr; - - while (digitptr != TempBuffer) - { - *dest++ = *--digitptr; - ++written; - } - - continue; - } /* if (*format == 'u') */ - - if(*format == 'd') - { - long num = va_arg(args, long); - long quotient; - const char *str; - char *digitptr = TempBuffer; - - ++format; - - if(num == 0) - { - *dest++ = '0'; - ++written; - continue; - } - - if(num < 0) - { - *dest++ = '-'; - ++written; - - num = -num; - } - - do - { - quotient = num / TABLE_MAX; - - str = IntTable[num - (quotient * TABLE_MAX)]; - - while ((*digitptr = *str)) - { - ++digitptr; - ++str; - } - } - while ((num = quotient) != 0); - - while (*(digitptr - 1) == '0') - --digitptr; - - while (digitptr != TempBuffer) - { - *dest++ = *--digitptr; - ++written; - } - - continue; - } /* if (*format == 'd') */ - - continue; - } /* if (ch == 'l') */ - - if(ch != '%') - { - int ret; - - format -= 2; - ret = vsprintf(dest, format, args); - dest += ret; - written += ret; - - break; - } /* if (ch != '%') */ - } /* if (ch == '%') */ - - *dest++ = ch; - ++written; - } /* while ((ch = *format++)) */ - - /* - * Terminate the destination buffer with a \0 - */ - *dest = '\0'; - - return (written); -} /* vSprintf() */ - -/* -ircsnprintf() - Optimized version of snprintf(). - -Inputs: dest - destination string - bytes - number of bytes to copy - format - formatted string - args - args to 'format' - -Return: number of characters copied, NOT including the terminating - NULL which is always placed at the end of the string -*/ - -int -ircsnprintf(char *dest, const size_t bytes, const char *format, ...) -{ - va_list args; - int count; - - va_start(args, format); - - count = ircvsnprintf(dest, bytes, format, args); - - va_end(args); - - return (count); -} /* Snprintf() */ - -/* -ircsprintf() - Optimized version of sprintf() - -Inputs: dest - destination string - format - formatted string - args - arguments to 'format' - -Return: number of characters copied, NOT including the terminating - NULL which is always placed at the end of the string -*/ - -int -ircsprintf(char *dest, const char *format, ...) -{ - va_list args; - int count; - - va_start(args, format); - - count = ircvsprintf(dest, format, args); - - va_end(args); - - return (count); -} /* Sprintf() */ diff --git a/libcharybdis/tools.c b/libcharybdis/tools.c deleted file mode 100644 index 298bfaa..0000000 --- a/libcharybdis/tools.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * tools.c: Various functions needed here and there. - * - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: tools.c 3201 2007-02-04 01:59:38Z jilles $ - * - * Here is the original header: - * - * Useful stuff, ripped from places .. - * adrian chadd - * - * When you update these functions make sure you update the ones in tools.h - * as well!!! - */ - -#include "stdinc.h" -#define TOOLS_C -#include "tools.h" -#include "balloc.h" -#include "s_user.h" - -#ifndef NDEBUG -/* - * frob some memory. debugging time. - * -- adrian - */ -void -mem_frob(void *data, int len) -{ - unsigned long x = 0xdeadbeef; - unsigned char *b = (unsigned char *)&x; - int i; - char *cdata = data; - for (i = 0; i < len; i++) - { - *cdata = b[i % 4]; - cdata++; - } -} -#endif - -/* - * init_dlink_nodes - * - */ -extern BlockHeap *dnode_heap; -void -init_dlink_nodes(void) -{ - dnode_heap = BlockHeapCreate(sizeof(dlink_node), DNODE_HEAP_SIZE); - if(dnode_heap == NULL) - outofmemory(); -} - -/* - * make_dlink_node - * - * inputs - NONE - * output - pointer to new dlink_node - * side effects - NONE - */ -dlink_node * -make_dlink_node(void) -{ - return(BlockHeapAlloc(dnode_heap)); -} - -/* - * free_dlink_node - * - * inputs - pointer to dlink_node - * output - NONE - * side effects - free given dlink_node - */ -void -free_dlink_node(dlink_node * ptr) -{ - assert(ptr != NULL); - - BlockHeapFree(dnode_heap, ptr); -} diff --git a/libcharybdis/tools.h b/libcharybdis/tools.h deleted file mode 100644 index ede6c45..0000000 --- a/libcharybdis/tools.h +++ /dev/null @@ -1,378 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * tools.h: Header for the various tool functions. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2004 ircd-ratbox development team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * $Id: tools.h 3201 2007-02-04 01:59:38Z jilles $ - */ - -#ifndef __LIBCHARYBDIS_TOOLS_H__ -#define __LIBCHARYBDIS_TOOLS_H__ - - -/* - * double-linked-list stuff - */ -typedef struct _dlink_node dlink_node; -typedef struct _dlink_list dlink_list; - -struct _dlink_node -{ - void *data; - dlink_node *prev; - dlink_node *next; - -}; - -struct _dlink_list -{ - dlink_node *head; - dlink_node *tail; - unsigned long length; -}; - -dlink_node *make_dlink_node(void); -void free_dlink_node(dlink_node * lp); -void init_dlink_nodes(void); - -#ifndef NDEBUG -void mem_frob(void *data, int len); -#else -#define mem_frob(x, y) -#endif - -/* This macros are basically swiped from the linux kernel - * they are simple yet effective - */ - -/* - * Walks forward of a list. - * pos is your node - * head is your list head - */ -#define DLINK_FOREACH(pos, head) for (pos = (head); pos != NULL; pos = pos->next) - -/* - * Walks forward of a list safely while removing nodes - * pos is your node - * n is another list head for temporary storage - * head is your list head - */ -#define DLINK_FOREACH_SAFE(pos, n, head) for (pos = (head), n = pos ? pos->next : NULL; pos != NULL; pos = n, n = pos ? pos->next : NULL) - -#define DLINK_FOREACH_PREV(pos, head) for (pos = (head); pos != NULL; pos = pos->prev) - - -/* Returns the list length */ -#define dlink_list_length(list) (list)->length -#define dlink_move_list(oldlist, newlist, node) - -#define dlinkAddAlloc(data, list) dlinkAdd(data, make_dlink_node(), list) -#define dlinkAddTailAlloc(data, list) dlinkAddTail(data, make_dlink_node(), list) -#define dlinkDestroy(node, list) do { dlinkDelete(node, list); free_dlink_node(node); } while(0) - - -/* - * The functions below are included for the sake of inlining - * hopefully this will speed up things just a bit - * - */ - -/* - * dlink_ routines are stolen from squid, except for dlinkAddBefore, - * which is mine. - * -- adrian - */ - -/* I hate C sometimes */ -#if defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__ && !defined __NO_INLINE__ -#define INLINE_FUNC extern inline -#define NEED_INLINES -#else -#undef INLINE_FUNC -#define INLINE_FUNC -#endif - -#ifdef TOOLS_C -#undef INLINE_FUNC -#define INLINE_FUNC -#endif - -void dlinkMoveNode(dlink_node * m, dlink_list * oldlist, dlink_list * newlist); -void dlinkAdd(void *data, dlink_node * m, dlink_list * list); -void dlinkAddBefore(dlink_node * b, void *data, dlink_node * m, dlink_list * list); -void dlinkMoveTail(dlink_node *m, dlink_list *list); -void dlinkAddTail(void *data, dlink_node * m, dlink_list * list); -void dlinkDelete(dlink_node * m, dlink_list * list); -dlink_node *dlinkFindDelete(void *data, dlink_list *list); -int dlinkFindDestroy(void *data, dlink_list *list); -dlink_node *dlinkFind(void *data, dlink_list *list); -void dlinkMoveList(dlink_list * from, dlink_list * to); - -#if defined(NEED_INLINES) || defined(TOOLS_C) -INLINE_FUNC void -dlinkMoveNode(dlink_node * m, dlink_list * oldlist, dlink_list * newlist) -{ - /* Assumption: If m->next == NULL, then list->tail == m - * and: If m->prev == NULL, then list->head == m - */ - assert(m != NULL); - assert(oldlist != NULL); - assert(newlist != NULL); - - if(m->next) - m->next->prev = m->prev; - else - oldlist->tail = m->prev; - - if(m->prev) - m->prev->next = m->next; - else - oldlist->head = m->next; - - m->prev = NULL; - m->next = newlist->head; - if(newlist->head != NULL) - newlist->head->prev = m; - else if(newlist->tail == NULL) - newlist->tail = m; - newlist->head = m; - - oldlist->length--; - newlist->length++; -} - -INLINE_FUNC void -dlinkAdd(void *data, dlink_node * m, dlink_list * list) -{ - assert(data != NULL); - assert(m != NULL); - assert(list != NULL); - m->data = data; - m->prev = NULL; - m->next = list->head; - - /* Assumption: If list->tail != NULL, list->head != NULL */ - if(list->head != NULL) - list->head->prev = m; - else if(list->tail == NULL) - list->tail = m; - - list->head = m; - list->length++; -} - -INLINE_FUNC void -dlinkAddBefore(dlink_node * b, void *data, dlink_node * m, dlink_list * list) -{ - assert(b != NULL); - assert(data != NULL); - assert(m != NULL); - assert(list != NULL); - - /* Shortcut - if its the first one, call dlinkAdd only */ - if(b == list->head) - { - dlinkAdd(data, m, list); - } - else - { - m->data = data; - b->prev->next = m; - m->prev = b->prev; - b->prev = m; - m->next = b; - list->length++; - } -} - -INLINE_FUNC void -dlinkMoveTail(dlink_node *m, dlink_list *list) -{ - if(list->tail == m) - return; - - /* From here assume that m->next != NULL as that can only - * be at the tail and assume that the node is on the list - */ - - m->next->prev = m->prev; - - if(m->prev != NULL) - m->prev->next = m->next; - else - list->head = m->next; - - list->tail->next = m; - m->prev = list->tail; - m->next = NULL; - list->tail = m; -} - -INLINE_FUNC void -dlinkAddTail(void *data, dlink_node * m, dlink_list * list) -{ - assert(m != NULL); - assert(list != NULL); - assert(data != NULL); - m->data = data; - m->next = NULL; - m->prev = list->tail; - - /* Assumption: If list->tail != NULL, list->head != NULL */ - if(list->tail != NULL) - list->tail->next = m; - else if(list->head == NULL) - list->head = m; - - list->tail = m; - list->length++; -} - -/* Execution profiles show that this function is called the most - * often of all non-spontaneous functions. So it had better be - * efficient. */ -INLINE_FUNC void -dlinkDelete(dlink_node * m, dlink_list * list) -{ - assert(m != NULL); - assert(list != NULL); - - /* Assumption: If m->next == NULL, then list->tail == m - * and: If m->prev == NULL, then list->head == m - */ - if(m->next) - m->next->prev = m->prev; - else - list->tail = m->prev; - - if(m->prev) - m->prev->next = m->next; - else - list->head = m->next; - - m->next = m->prev = NULL; - list->length--; -} - -INLINE_FUNC dlink_node * -dlinkFindDelete(void *data, dlink_list *list) -{ - dlink_node *m; - assert(list != NULL); - assert(data != NULL); - - DLINK_FOREACH(m, list->head) - { - if(m->data != data) - continue; - - if(m->next) - m->next->prev = m->prev; - else - list->tail = m->prev; - - if(m->prev) - m->prev->next = m->next; - else - list->head = m->next; - - m->next = m->prev = NULL; - list->length--; - return m; - } - - return NULL; -} - -INLINE_FUNC int -dlinkFindDestroy(void *data, dlink_list *list) -{ - void *ptr; - - assert(list != NULL); - assert(data != NULL); - - ptr = dlinkFindDelete(data, list); - - if(ptr != NULL) - { - free_dlink_node(ptr); - return 1; - } - return 0; -} - -/* - * dlinkFind - * inputs - list to search - * - data - * output - pointer to link or NULL if not found - * side effects - Look for ptr in the linked listed pointed to by link. - */ -INLINE_FUNC dlink_node * -dlinkFind(void *data, dlink_list *list) -{ - dlink_node *ptr; - assert(list != NULL); - assert(data != NULL); - - DLINK_FOREACH(ptr, list->head) - { - if(ptr->data == data) - return (ptr); - } - return (NULL); -} - -INLINE_FUNC void -dlinkMoveList(dlink_list * from, dlink_list * to) -{ - assert(from != NULL); - assert(to != NULL); - - /* There are three cases */ - /* case one, nothing in from list */ - if(from->head == NULL) - return; - - /* case two, nothing in to list */ - if(to->head == NULL) - { - to->head = from->head; - to->tail = from->tail; - from->head = from->tail = NULL; - to->length = from->length; - from->length = 0; - return; - } - - /* third case play with the links */ - from->tail->next = to->head; - to->head->prev = from->tail; - to->head = from->head; - from->head = from->tail = NULL; - to->length += from->length; - from->length = 0; -} -#endif - -#endif /* __TOOLS_H__ */