Initial import of the ircii-pana-1.1-final source tree.
git-svn-id: svn://svn.code.sf.net/p/bitchx/code/tags/ircii-pana-1.1-final@1 13b04d17-f746-0410-82c6-800466cd88b0
This commit is contained in:
1025
source/Makefile.in
Normal file
1025
source/Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
37
source/X.c
Normal file
37
source/X.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <zvt/zvtterm.h>
|
||||
|
||||
void size_allocate (GtkWidget *widget, GtkWindow *window)
|
||||
{
|
||||
ZvtTerm *term;
|
||||
XSizeHints sizehints;
|
||||
|
||||
g_assert (widget != NULL);
|
||||
term = ZVT_TERM (widget);
|
||||
|
||||
/* Not sure why it is x3 and x2.... klass shows as 2x2 and the variation is 6x4 */
|
||||
sizehints.base_width =
|
||||
(GTK_WIDGET (window)->allocation.width) +
|
||||
(GTK_WIDGET (term)->style->klass->xthickness * 3) -
|
||||
(GTK_WIDGET (term)->allocation.width);
|
||||
|
||||
sizehints.base_height =
|
||||
(GTK_WIDGET (window)->allocation.height) +
|
||||
(GTK_WIDGET (term)->style->klass->ythickness * 2) -
|
||||
(GTK_WIDGET (term)->allocation.height);
|
||||
|
||||
sizehints.width_inc = term->charwidth;
|
||||
sizehints.height_inc = term->charheight;
|
||||
sizehints.min_width = sizehints.base_width + (sizehints.width_inc * 20);
|
||||
sizehints.min_height = sizehints.base_height + (sizehints.height_inc * 5);
|
||||
|
||||
sizehints.flags = (PBaseSize|PMinSize|PResizeInc);
|
||||
|
||||
XSetWMNormalHints (GDK_DISPLAY(),
|
||||
GDK_WINDOW_XWINDOW (GTK_WIDGET (window)->window),
|
||||
&sizehints);
|
||||
gdk_flush ();
|
||||
}
|
||||
2490
source/alias.c
Normal file
2490
source/alias.c
Normal file
File diff suppressed because it is too large
Load Diff
431
source/alist.c
Normal file
431
source/alist.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* alist.c -- resizeable arrays.
|
||||
* Written by Jeremy Nelson
|
||||
* Copyright 1997 EPIC Software Labs
|
||||
*
|
||||
* This file presumes a good deal of chicanery. Specifically, it assumes
|
||||
* that your compiler will allocate disparate structures congruently as
|
||||
* long as the members match as to their type and location. This is
|
||||
* critically important for how this code works, and all hell will break
|
||||
* loose if your compiler doesnt do this. Every compiler i know of does
|
||||
* it, which is why im assuming it, even though im not allowed to assume it.
|
||||
*
|
||||
* This file is hideous. Ill kill each and every one of you who made
|
||||
* me do this. ;-)
|
||||
*/
|
||||
|
||||
#define _cs_alist_hash_
|
||||
#define _ci_alist_hash_
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: alist.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(alist_c)
|
||||
#include "alist.h"
|
||||
#include "ircaux.h"
|
||||
#include "output.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
u_32int_t bin_ints = 0;
|
||||
u_32int_t lin_ints = 0;
|
||||
u_32int_t bin_chars = 0;
|
||||
u_32int_t lin_chars = 0;
|
||||
u_32int_t alist_searches = 0;
|
||||
u_32int_t char_searches = 0;
|
||||
|
||||
|
||||
#define ARRAY_ITEM(array, loc) ((Array_item *) ((array) -> list [ (loc) ]))
|
||||
#define LARRAY_ITEM(array, loc) (((array) -> list [ (loc) ]))
|
||||
|
||||
/* Function decls */
|
||||
static void check_array_size (Array *list);
|
||||
void move_array_items (Array *list, int start, int end, int dir);
|
||||
|
||||
/*
|
||||
* Returns an entry that has been displaced, if any.
|
||||
*/
|
||||
Array_item *BX_add_to_array (Array *array, Array_item *item)
|
||||
{
|
||||
int count;
|
||||
int location = 0;
|
||||
Array_item *ret = NULL;
|
||||
u_32int_t mask; /* Dummy var */
|
||||
|
||||
if (array->hash == HASH_INSENSITIVE)
|
||||
item->hash = ci_alist_hash(item->name, &mask);
|
||||
else
|
||||
item->hash = cs_alist_hash(item->name, &mask);
|
||||
|
||||
check_array_size(array);
|
||||
if (array->max)
|
||||
{
|
||||
find_array_item(array, item->name, &count, &location);
|
||||
if (count < 0)
|
||||
{
|
||||
ret = ARRAY_ITEM(array, location);
|
||||
array->max--;
|
||||
}
|
||||
else
|
||||
move_array_items(array, location, array->max, 1);
|
||||
}
|
||||
|
||||
array->list[location] = item;
|
||||
array->max++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the entry that has been removed, if any.
|
||||
*/
|
||||
Array_item *BX_remove_from_array (Array *array, char *name)
|
||||
{
|
||||
int count, location = 0;
|
||||
|
||||
if (array->max)
|
||||
{
|
||||
find_array_item(array, name, &count, &location);
|
||||
if (count >= 0)
|
||||
return NULL;
|
||||
|
||||
return array_pop(array, location);
|
||||
}
|
||||
return NULL; /* Cant delete whats not there */
|
||||
}
|
||||
|
||||
/* Remove the 'which'th item from the given array */
|
||||
Array_item *BX_array_pop (Array *array, int which)
|
||||
{
|
||||
Array_item *ret = NULL;
|
||||
|
||||
if (which < 0 || which >= array->max)
|
||||
return NULL;
|
||||
|
||||
ret = ARRAY_ITEM(array, which);
|
||||
move_array_items(array, which + 1, array->max, -1);
|
||||
array->max--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the entry that has been removed, if any.
|
||||
*/
|
||||
Array_item *BX_remove_all_from_array (Array *array, char *name)
|
||||
{
|
||||
int count, location = 0;
|
||||
Array_item *ret = NULL;
|
||||
|
||||
if (array->max)
|
||||
{
|
||||
find_array_item(array, name, &count, &location);
|
||||
if (count == 0)
|
||||
return NULL;
|
||||
ret = ARRAY_ITEM(array, location);
|
||||
move_array_items(array, location + 1, array->max, -1);
|
||||
array->max--;
|
||||
return ret;
|
||||
}
|
||||
return NULL; /* Cant delete whats not there */
|
||||
}
|
||||
|
||||
Array_item *BX_array_lookup (Array *array, char *name, int wild, int delete)
|
||||
{
|
||||
int count, location;
|
||||
|
||||
if (delete)
|
||||
return remove_from_array(array, name);
|
||||
else
|
||||
return find_array_item(array, name, &count, &location);
|
||||
}
|
||||
|
||||
static void check_array_size (Array *array)
|
||||
{
|
||||
if (array->total_max == 0)
|
||||
array->total_max = 6; /* Good size to start with */
|
||||
else if (array->max == array->total_max-1)
|
||||
array->total_max *= 2;
|
||||
else if (array->max * 3 < array->total_max)
|
||||
array->total_max /= 2;
|
||||
else
|
||||
return;
|
||||
|
||||
/*yell("Resizing...");*/
|
||||
RESIZE(array->list, Array_item *, array->total_max);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move ``start'' through ``end'' array elements ``dir'' places up
|
||||
* in the array. If ``dir'' is negative, move them down in the array.
|
||||
* Fill in the vacated spots with NULLs.
|
||||
*/
|
||||
void move_array_items (Array *array, int start, int end, int dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dir > 0)
|
||||
{
|
||||
for (i = end; i >= start; i--)
|
||||
LARRAY_ITEM(array, i + dir) = ARRAY_ITEM(array, i);
|
||||
for (i = dir; i > 0; i--)
|
||||
LARRAY_ITEM(array, start + i - 1) = NULL;
|
||||
}
|
||||
else if (dir < 0)
|
||||
{
|
||||
for (i = start; i <= end; i++)
|
||||
LARRAY_ITEM(array, i + dir) = ARRAY_ITEM(array, i);
|
||||
for (i = end - dir + 1; i <= end; i++)
|
||||
LARRAY_ITEM(array, i) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is just a generalization of the old function ``find_command''
|
||||
*
|
||||
* You give it an alist_item and a name, and it gives you the number of
|
||||
* items that are completed by that name, and where you could find/put that
|
||||
* item in the list. It returns the alist_item most appropriate.
|
||||
*
|
||||
* If ``cnt'' is less than -1, then there was one exact match and one or
|
||||
* more ambiguous matches in addition. The exact match's location
|
||||
* is put into ``loc'' and its entry is returned. The ambigous matches
|
||||
* are (of course) immediately subsequent to it.
|
||||
*
|
||||
* If ``cnt'' is -1, then there was one exact match. Its location is
|
||||
* put into ``loc'' and its entry is returned.
|
||||
*
|
||||
* If ``cnt'' is zero, then there were no matches for ``name'', but ``loc''
|
||||
* is set to the location in the array in which you could place the
|
||||
* specified name in the sorted list.
|
||||
*
|
||||
* If ``cnt'' is one, then there was one command that non-ambiguously
|
||||
* completes ``name''
|
||||
*
|
||||
* If ``cnt'' is greater than one, then there was exactly ``cnt'' number
|
||||
* of entries that completed ``name'', but they are all ambiguous.
|
||||
* The entry that is lowest alphabetically is returned, and its
|
||||
* location is put into ``loc''.
|
||||
*/
|
||||
Array_item *BX_find_array_item (Array *set, char *name, int *cnt, int *loc)
|
||||
{
|
||||
size_t len = strlen(name);
|
||||
int c = 0,
|
||||
pos = 0,
|
||||
min,
|
||||
max;
|
||||
u_32int_t mask, hash;
|
||||
|
||||
if (set->hash == HASH_INSENSITIVE)
|
||||
hash = ci_alist_hash(name, &mask);
|
||||
else
|
||||
hash = cs_alist_hash(name, &mask);
|
||||
|
||||
*cnt = 0;
|
||||
if (!set->list || !set->max)
|
||||
{
|
||||
*loc = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
alist_searches++;
|
||||
max = set->max - 1;
|
||||
min = 0;
|
||||
|
||||
while (max >= min)
|
||||
{
|
||||
bin_ints++;
|
||||
pos = (max - min) / 2 + min;
|
||||
c = (hash & mask) - (ARRAY_ITEM(set, pos)->hash & mask);
|
||||
if (c == 0)
|
||||
break;
|
||||
else if (c < 0)
|
||||
max = pos - 1;
|
||||
else
|
||||
min = pos + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we can't find a symbol that qualifies, then we can just drop
|
||||
* out here. This is good because a "pass" (lookup for a symbol that
|
||||
* does not exist) requires only cheap integer comparisons.
|
||||
*/
|
||||
if (c != 0)
|
||||
{
|
||||
if (c > 0)
|
||||
*loc = pos + 1;
|
||||
else
|
||||
*loc = pos;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we've found some symbol that has the same first four letters.
|
||||
* Expand the min/max range to include all of the symbols that have
|
||||
* the same first four letters...
|
||||
*/
|
||||
min = max = pos;
|
||||
while ((min > 0) && (hash & mask) == (ARRAY_ITEM(set, min)->hash & mask))
|
||||
min--, lin_ints++;
|
||||
while ((max < set->max - 1) && (hash &mask) == (ARRAY_ITEM(set, max)->hash & mask))
|
||||
max++, lin_ints++;
|
||||
|
||||
char_searches++;
|
||||
|
||||
/*
|
||||
* Then do a full blown binary search on the smaller range
|
||||
*/
|
||||
while (max >= min)
|
||||
{
|
||||
bin_chars++;
|
||||
pos = (max - min) / 2 + min;
|
||||
c = set->func(name, ARRAY_ITEM(set, pos)->name, len);
|
||||
if (c == 0)
|
||||
break;
|
||||
else if (c < 0)
|
||||
max = pos - 1;
|
||||
else
|
||||
min = pos + 1;
|
||||
}
|
||||
|
||||
|
||||
if (c != 0)
|
||||
{
|
||||
if (c > 0)
|
||||
*loc = pos + 1;
|
||||
else
|
||||
*loc = pos;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've gotten this far, then we've found at least
|
||||
* one appropriate entry. So we set *cnt to one
|
||||
*/
|
||||
*cnt = 1;
|
||||
|
||||
/*
|
||||
* So we know that 'pos' is a match. So we start 'min'
|
||||
* at one less than 'pos' and walk downard until we find
|
||||
* an entry that is NOT matched.
|
||||
*/
|
||||
min = pos - 1;
|
||||
while (min >= 0 && !set->func(name, ARRAY_ITEM(set, min)->name, len))
|
||||
(*cnt)++, min--, lin_chars++;
|
||||
min++;
|
||||
|
||||
/*
|
||||
* Repeat the same ordeal, except this time we walk upwards
|
||||
* from 'pos' until we dont find a match.
|
||||
*/
|
||||
max = pos + 1;
|
||||
while (max < set->max && !set->func(name, ARRAY_ITEM(set, max)->name, len))
|
||||
(*cnt)++, max++, lin_chars++;
|
||||
|
||||
/*
|
||||
* Alphabetically, the string that would be identical to
|
||||
* 'name' would be the first item in a string of items that
|
||||
* all began with 'name'. That is to say, if there is an
|
||||
* exact match, its sitting under item 'min'. So we check
|
||||
* for that and whack the count appropriately.
|
||||
*/
|
||||
if (strlen(ARRAY_ITEM(set, min)->name) == len)
|
||||
*cnt *= -1;
|
||||
|
||||
/*
|
||||
* Then we tell the caller where the lowest match is,
|
||||
* in case they want to insert here.
|
||||
*/
|
||||
if (loc)
|
||||
*loc = min;
|
||||
|
||||
/*
|
||||
* Then we return the first item that matches.
|
||||
*/
|
||||
return ARRAY_ITEM(set, min);
|
||||
}
|
||||
|
||||
#define FIXED_ITEM(list, pos, size) (*(Array_item *) (list + ( pos * size )))
|
||||
|
||||
/*
|
||||
* This is useful for finding items in a fixed array (eg, those lists that
|
||||
* are a simple fixed length arrays of 1st level structs.)
|
||||
*
|
||||
* This code is identical to find_array_item except ``list'' is a 1st
|
||||
* level array instead of a 2nd level array.
|
||||
*/
|
||||
void * BX_find_fixed_array_item (void *list, size_t size, int howmany, char *name, int *cnt, int *loc)
|
||||
{
|
||||
int len = strlen(name),
|
||||
min = 0,
|
||||
max = howmany,
|
||||
old_pos = -1,
|
||||
pos,
|
||||
c;
|
||||
|
||||
*cnt = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
pos = (max + min) / 2;
|
||||
if (pos == old_pos)
|
||||
{
|
||||
*loc = pos;
|
||||
return NULL;
|
||||
}
|
||||
old_pos = pos;
|
||||
|
||||
c = strncmp(name, FIXED_ITEM(list, pos, size).name, len);
|
||||
if (c == 0)
|
||||
break;
|
||||
else if (c > 0)
|
||||
min = pos;
|
||||
else
|
||||
max = pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've gotten this far, then we've found at least
|
||||
* one appropriate entry. So we set *cnt to one
|
||||
*/
|
||||
*cnt = 1;
|
||||
|
||||
/*
|
||||
* So we know that 'pos' is a match. So we start 'min'
|
||||
* at one less than 'pos' and walk downard until we find
|
||||
* an entry that is NOT matched.
|
||||
*/
|
||||
min = pos - 1;
|
||||
while (min >= 0 && !strncmp(name, FIXED_ITEM(list, min, size).name, len))
|
||||
(*cnt)++, min--;
|
||||
min++;
|
||||
|
||||
/*
|
||||
* Repeat the same ordeal, except this time we walk upwards
|
||||
* from 'pos' until we dont find a match.
|
||||
*/
|
||||
max = pos + 1;
|
||||
while ((max < howmany) && !strncmp(name, FIXED_ITEM(list, max, size).name, len))
|
||||
(*cnt)++, max++;
|
||||
|
||||
/*
|
||||
* Alphabetically, the string that would be identical to
|
||||
* 'name' would be the first item in a string of items that
|
||||
* all began with 'name'. That is to say, if there is an
|
||||
* exact match, its sitting under item 'min'. So we check
|
||||
* for that and whack the count appropriately.
|
||||
*/
|
||||
if (strlen(FIXED_ITEM(list, min, size).name) == len)
|
||||
*cnt *= -1;
|
||||
|
||||
/*
|
||||
* Then we tell the caller where the lowest match is,
|
||||
* in case they want to insert here.
|
||||
*/
|
||||
if (loc)
|
||||
*loc = min;
|
||||
|
||||
/*
|
||||
* Then we return the first item that matches.
|
||||
*/
|
||||
return (void *)&FIXED_ITEM(list, min, size);
|
||||
}
|
||||
|
||||
|
||||
456
source/alloca.c
Normal file
456
source/alloca.c
Normal file
@@ -0,0 +1,456 @@
|
||||
/* alloca.c -- allocate automatically reclaimed memory
|
||||
(Mostly) portable public-domain implementation -- D A Gwyn
|
||||
|
||||
This implementation of the PWB library alloca function,
|
||||
which is used to allocate space off the run-time stack so
|
||||
that it is automatically reclaimed upon procedure exit,
|
||||
was inspired by discussions with J. Q. Johnson of Cornell.
|
||||
J.Otto Tennant <jot@cray.com> contributed the Cray support.
|
||||
|
||||
There are some preprocessor constants that can
|
||||
be defined when compiling for your specific system, for
|
||||
improved efficiency; however, the defaults should be okay.
|
||||
|
||||
The general concept of this implementation is to keep
|
||||
track of all alloca-allocated blocks, and reclaim any
|
||||
that are found to be deeper in the stack than the current
|
||||
invocation. This heuristic does not reclaim storage as
|
||||
soon as it becomes invalid, but it will do so eventually.
|
||||
|
||||
As a special case, alloca(0) reclaims storage without
|
||||
allocating any. It is a good idea to use alloca(0) in
|
||||
your main control loop, etc. to force garbage collection. */
|
||||
|
||||
/* If compiling with GCC 2, this file's not needed. */
|
||||
#if !defined (__GNUC__) || __GNUC__ < 2
|
||||
|
||||
/* If someone has defined alloca as a macro,
|
||||
there must be some other way alloca is supposed to work. */
|
||||
#ifndef alloca
|
||||
|
||||
/* If your stack is a linked list of frames, you have to
|
||||
provide an "address metric" ADDRESS_FUNCTION macro. */
|
||||
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
long i00afunc ();
|
||||
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
|
||||
#else
|
||||
#define ADDRESS_FUNCTION(arg) &(arg)
|
||||
#endif
|
||||
|
||||
typedef void *pointer;
|
||||
|
||||
#define NULL 0
|
||||
|
||||
/* Different portions of Emacs need to call different versions of
|
||||
malloc. The Emacs executable needs alloca to call xmalloc, because
|
||||
ordinary malloc isn't protected from input signals. On the other
|
||||
hand, the utilities in lib-src need alloca to call malloc; some of
|
||||
them are very simple, and don't have an xmalloc routine.
|
||||
|
||||
Non-Emacs programs expect this to call use xmalloc.
|
||||
|
||||
Callers below should use malloc. */
|
||||
|
||||
#define malloc xmalloc
|
||||
extern pointer malloc ();
|
||||
|
||||
/* Define STACK_DIRECTION if you know the direction of stack
|
||||
growth for your system; otherwise it will be automatically
|
||||
deduced at run-time.
|
||||
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
|
||||
#ifndef STACK_DIRECTION
|
||||
#define STACK_DIRECTION 0 /* Direction unknown. */
|
||||
#endif
|
||||
|
||||
#if STACK_DIRECTION != 0
|
||||
|
||||
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
|
||||
|
||||
#else /* STACK_DIRECTION == 0; need run-time code. */
|
||||
|
||||
static int stack_dir; /* 1 or -1 once known. */
|
||||
#define STACK_DIR stack_dir
|
||||
|
||||
static void
|
||||
find_stack_direction ()
|
||||
{
|
||||
static char *addr = NULL; /* Address of first `dummy', once known. */
|
||||
auto char dummy; /* To get stack address. */
|
||||
|
||||
if (addr == NULL)
|
||||
{ /* Initial entry. */
|
||||
addr = ADDRESS_FUNCTION (dummy);
|
||||
|
||||
find_stack_direction (); /* Recurse once. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Second entry. */
|
||||
if (ADDRESS_FUNCTION (dummy) > addr)
|
||||
stack_dir = 1; /* Stack grew upward. */
|
||||
else
|
||||
stack_dir = -1; /* Stack grew downward. */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* STACK_DIRECTION == 0 */
|
||||
|
||||
/* An "alloca header" is used to:
|
||||
(a) chain together all alloca'ed blocks;
|
||||
(b) keep track of stack depth.
|
||||
|
||||
It is very important that sizeof(header) agree with malloc
|
||||
alignment chunk size. The following default should work okay. */
|
||||
|
||||
#ifndef ALIGN_SIZE
|
||||
#define ALIGN_SIZE sizeof(double)
|
||||
#endif
|
||||
|
||||
typedef union hdr
|
||||
{
|
||||
char align[ALIGN_SIZE]; /* To force sizeof(header). */
|
||||
struct
|
||||
{
|
||||
union hdr *next; /* For chaining headers. */
|
||||
char *deep; /* For stack depth measure. */
|
||||
} h;
|
||||
} header;
|
||||
|
||||
static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||
|
||||
/* Return a pointer to at least SIZE bytes of storage,
|
||||
which will be automatically reclaimed upon exit from
|
||||
the procedure that called alloca. Originally, this space
|
||||
was supposed to be taken from the current stack frame of the
|
||||
caller, but that method cannot be made to work for some
|
||||
implementations of C, for example under Gould's UTX/32. */
|
||||
|
||||
pointer
|
||||
alloca (size)
|
||||
unsigned size;
|
||||
{
|
||||
auto char probe; /* Probes stack depth: */
|
||||
register char *depth = ADDRESS_FUNCTION (probe);
|
||||
|
||||
#if STACK_DIRECTION == 0
|
||||
if (STACK_DIR == 0) /* Unknown growth direction. */
|
||||
find_stack_direction ();
|
||||
#endif
|
||||
|
||||
/* Reclaim garbage, defined as all alloca'd storage that
|
||||
was allocated from deeper in the stack than currently. */
|
||||
|
||||
{
|
||||
register header *hp; /* Traverses linked list. */
|
||||
|
||||
for (hp = last_alloca_header; hp != NULL;)
|
||||
if ((STACK_DIR > 0 && hp->h.deep > depth)
|
||||
|| (STACK_DIR < 0 && hp->h.deep < depth))
|
||||
{
|
||||
register header *np = hp->h.next;
|
||||
|
||||
free ((pointer) hp); /* Collect garbage. */
|
||||
|
||||
hp = np; /* -> next header. */
|
||||
}
|
||||
else
|
||||
break; /* Rest are not deeper. */
|
||||
|
||||
last_alloca_header = hp; /* -> last valid storage. */
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
return NULL; /* No allocation required. */
|
||||
|
||||
/* Allocate combined header + user data storage. */
|
||||
|
||||
{
|
||||
register pointer new = malloc (sizeof (header) + size);
|
||||
/* Address of header. */
|
||||
|
||||
((header *) new)->h.next = last_alloca_header;
|
||||
((header *) new)->h.deep = depth;
|
||||
|
||||
last_alloca_header = (header *) new;
|
||||
|
||||
/* User storage begins just after header. */
|
||||
|
||||
return (pointer) ((char *) new + sizeof (header));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifndef CRAY_STACK
|
||||
#define CRAY_STACK
|
||||
#ifndef CRAY2
|
||||
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
|
||||
struct stack_control_header
|
||||
{
|
||||
long shgrow:32; /* Number of times stack has grown. */
|
||||
long shaseg:32; /* Size of increments to stack. */
|
||||
long shhwm:32; /* High water mark of stack. */
|
||||
long shsize:32; /* Current size of stack (all segments). */
|
||||
};
|
||||
|
||||
/* The stack segment linkage control information occurs at
|
||||
the high-address end of a stack segment. (The stack
|
||||
grows from low addresses to high addresses.) The initial
|
||||
part of the stack segment linkage control information is
|
||||
0200 (octal) words. This provides for register storage
|
||||
for the routine which overflows the stack. */
|
||||
|
||||
struct stack_segment_linkage
|
||||
{
|
||||
long ss[0200]; /* 0200 overflow words. */
|
||||
long sssize:32; /* Number of words in this segment. */
|
||||
long ssbase:32; /* Offset to stack base. */
|
||||
long:32;
|
||||
long sspseg:32; /* Offset to linkage control of previous
|
||||
segment of stack. */
|
||||
long:32;
|
||||
long sstcpt:32; /* Pointer to task common address block. */
|
||||
long sscsnm; /* Private control structure number for
|
||||
microtasking. */
|
||||
long ssusr1; /* Reserved for user. */
|
||||
long ssusr2; /* Reserved for user. */
|
||||
long sstpid; /* Process ID for pid based multi-tasking. */
|
||||
long ssgvup; /* Pointer to multitasking thread giveup. */
|
||||
long sscray[7]; /* Reserved for Cray Research. */
|
||||
long ssa0;
|
||||
long ssa1;
|
||||
long ssa2;
|
||||
long ssa3;
|
||||
long ssa4;
|
||||
long ssa5;
|
||||
long ssa6;
|
||||
long ssa7;
|
||||
long sss0;
|
||||
long sss1;
|
||||
long sss2;
|
||||
long sss3;
|
||||
long sss4;
|
||||
long sss5;
|
||||
long sss6;
|
||||
long sss7;
|
||||
};
|
||||
|
||||
#else /* CRAY2 */
|
||||
/* The following structure defines the vector of words
|
||||
returned by the STKSTAT library routine. */
|
||||
struct stk_stat
|
||||
{
|
||||
long now; /* Current total stack size. */
|
||||
long maxc; /* Amount of contiguous space which would
|
||||
be required to satisfy the maximum
|
||||
stack demand to date. */
|
||||
long high_water; /* Stack high-water mark. */
|
||||
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
|
||||
long hits; /* Number of internal buffer hits. */
|
||||
long extends; /* Number of block extensions. */
|
||||
long stko_mallocs; /* Block allocations by $STKOFEN. */
|
||||
long underflows; /* Number of stack underflow calls ($STKRETN). */
|
||||
long stko_free; /* Number of deallocations by $STKRETN. */
|
||||
long stkm_free; /* Number of deallocations by $STKMRET. */
|
||||
long segments; /* Current number of stack segments. */
|
||||
long maxs; /* Maximum number of stack segments so far. */
|
||||
long pad_size; /* Stack pad size. */
|
||||
long current_address; /* Current stack segment address. */
|
||||
long current_size; /* Current stack segment size. This
|
||||
number is actually corrupted by STKSTAT to
|
||||
include the fifteen word trailer area. */
|
||||
long initial_address; /* Address of initial segment. */
|
||||
long initial_size; /* Size of initial segment. */
|
||||
};
|
||||
|
||||
/* The following structure describes the data structure which trails
|
||||
any stack segment. I think that the description in 'asdef' is
|
||||
out of date. I only describe the parts that I am sure about. */
|
||||
|
||||
struct stk_trailer
|
||||
{
|
||||
long this_address; /* Address of this block. */
|
||||
long this_size; /* Size of this block (does not include
|
||||
this trailer). */
|
||||
long unknown2;
|
||||
long unknown3;
|
||||
long link; /* Address of trailer block of previous
|
||||
segment. */
|
||||
long unknown5;
|
||||
long unknown6;
|
||||
long unknown7;
|
||||
long unknown8;
|
||||
long unknown9;
|
||||
long unknown10;
|
||||
long unknown11;
|
||||
long unknown12;
|
||||
long unknown13;
|
||||
long unknown14;
|
||||
};
|
||||
|
||||
#endif /* CRAY2 */
|
||||
#endif /* not CRAY_STACK */
|
||||
|
||||
#ifdef CRAY2
|
||||
/* Determine a "stack measure" for an arbitrary ADDRESS.
|
||||
I doubt that "lint" will like this much. */
|
||||
|
||||
static long
|
||||
i00afunc (long *address)
|
||||
{
|
||||
struct stk_stat status;
|
||||
struct stk_trailer *trailer;
|
||||
long *block, size;
|
||||
long result = 0;
|
||||
|
||||
/* We want to iterate through all of the segments. The first
|
||||
step is to get the stack status structure. We could do this
|
||||
more quickly and more directly, perhaps, by referencing the
|
||||
$LM00 common block, but I know that this works. */
|
||||
|
||||
STKSTAT (&status);
|
||||
|
||||
/* Set up the iteration. */
|
||||
|
||||
trailer = (struct stk_trailer *) (status.current_address
|
||||
+ status.current_size
|
||||
- 15);
|
||||
|
||||
/* There must be at least one stack segment. Therefore it is
|
||||
a fatal error if "trailer" is null. */
|
||||
|
||||
if (trailer == 0)
|
||||
abort ();
|
||||
|
||||
/* Discard segments that do not contain our argument address. */
|
||||
|
||||
while (trailer != 0)
|
||||
{
|
||||
block = (long *) trailer->this_address;
|
||||
size = trailer->this_size;
|
||||
if (block == 0 || size == 0)
|
||||
abort ();
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
if ((block <= address) && (address < (block + size)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the result to the offset in this segment and add the sizes
|
||||
of all predecessor segments. */
|
||||
|
||||
result = address - block;
|
||||
|
||||
if (trailer == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (trailer->this_size <= 0)
|
||||
abort ();
|
||||
result += trailer->this_size;
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
}
|
||||
while (trailer != 0);
|
||||
|
||||
/* We are done. Note that if you present a bogus address (one
|
||||
not in any segment), you will get a different number back, formed
|
||||
from subtracting the address of the first block. This is probably
|
||||
not what you want. */
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
#else /* not CRAY2 */
|
||||
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
|
||||
Determine the number of the cell within the stack,
|
||||
given the address of the cell. The purpose of this
|
||||
routine is to linearize, in some sense, stack addresses
|
||||
for alloca. */
|
||||
|
||||
static long
|
||||
i00afunc (long address)
|
||||
{
|
||||
long stkl = 0;
|
||||
|
||||
long size, pseg, this_segment, stack;
|
||||
long result = 0;
|
||||
|
||||
struct stack_segment_linkage *ssptr;
|
||||
|
||||
/* Register B67 contains the address of the end of the
|
||||
current stack segment. If you (as a subprogram) store
|
||||
your registers on the stack and find that you are past
|
||||
the contents of B67, you have overflowed the segment.
|
||||
|
||||
B67 also points to the stack segment linkage control
|
||||
area, which is what we are really interested in. */
|
||||
|
||||
stkl = CRAY_STACKSEG_END ();
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
|
||||
/* If one subtracts 'size' from the end of the segment,
|
||||
one has the address of the first word of the segment.
|
||||
|
||||
If this is not the first segment, 'pseg' will be
|
||||
nonzero. */
|
||||
|
||||
pseg = ssptr->sspseg;
|
||||
size = ssptr->sssize;
|
||||
|
||||
this_segment = stkl - size;
|
||||
|
||||
/* It is possible that calling this routine itself caused
|
||||
a stack overflow. Discard stack segments which do not
|
||||
contain the target address. */
|
||||
|
||||
while (!(this_segment <= address && address <= stkl))
|
||||
{
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
|
||||
#endif
|
||||
if (pseg == 0)
|
||||
break;
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
this_segment = stkl - size;
|
||||
}
|
||||
|
||||
result = address - this_segment;
|
||||
|
||||
/* If you subtract pseg from the current end of the stack,
|
||||
you get the address of the previous stack segment's end.
|
||||
This seems a little convoluted to me, but I'll bet you save
|
||||
a cycle somewhere. */
|
||||
|
||||
while (pseg != 0)
|
||||
{
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
fprintf (stderr, "%011o %011o\n", pseg, size);
|
||||
#endif
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
result += size;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
#endif /* not CRAY2 */
|
||||
#endif /* CRAY */
|
||||
|
||||
#endif /* no alloca */
|
||||
#endif /* not GCC version 2 */
|
||||
1012
source/array.c
Normal file
1012
source/array.c
Normal file
File diff suppressed because it is too large
Load Diff
441
source/art.c
Normal file
441
source/art.c
Normal file
@@ -0,0 +1,441 @@
|
||||
|
||||
#include "irc.h"
|
||||
#include "output.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
void do_ansi_logo(int i)
|
||||
{
|
||||
put_it("[40m");
|
||||
|
||||
#ifdef ASCII_LOGO
|
||||
#ifndef BITCHX_LITE
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
put_it("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::");
|
||||
put_it(":::[1;31m:.[0m.[1;31m.[14C[0m.[1;35m.:[0m:::::::::::::::::[1;31m:.[0m.[14C[1;35m.[0m.[1;35m.:[0m:::::::::::::::::");
|
||||
put_it(":::::::[1;31m:.[11C[35m:[0m:::::::::::::::::::::::[1;31m:[11C[35m.:[0m:::::::::::::::::::::");
|
||||
put_it(":::::::::[1;31m:.[10C[35m`:[0m:::::::::::::::::::[1;31m:'[10C[35m.:[0m:::[1;31m:\"[0m`````````````````\"");
|
||||
put_it(":::::::::::[1;31m:.[10C[35m`:[0m:::::::::::::::[1;31m:'[10C[35m.:[0m::::[1;31m: [35mB[0;35mitch[1mX [0mby [1;32mp[0;32manasync[36m!");
|
||||
put_it("[37m:::::::::::::[1;31m:.[10C[35m`:[0m:::::::::::[1;31m:'[10C[35m.:[0m:::::::[1;31m:.[0m..................");
|
||||
put_it(":::::::::::::::[1;31m:.[10C[35m`:[0m:::::::[1;31m:'[10C[35m.:[0m:::::::::::::::::::::::::::::");
|
||||
put_it("::[1;31m:\"[0m\"````\"[1;35m\":[0m::[1;31m:'[36m.g$[0;36m$S[32m$'[6C[1;35m`:[0m:::[1;31m:'[11C[35m\":[0m::[1;31m:\"[0m\"```[1;35m\":[0m::::::::::::::::::::");
|
||||
put_it("[1;31m'[36ms#S[0;36m$$$\"[1m$$[0;36mS#[32mn.[1;31m` [36m$$[0;36m$$[32mS\". [1;36ms#S[0;36m$$[32m$ [1;35m`[31m:' [36m.g#[0;36mS$$[1m\"$[0;36m$S#[32mn. [1;36ms#S[0;36m$$[32m$ [1;35m`[0m\"[1;35m\":[0m::::::::::::::::");
|
||||
put_it(" [1;36m$$[0;36m$$$[32m$[1;36m_,$[0;36m$[32m$S'[1;30mrE[36m.g#[0;36mS$$[32m$ [1;36m$$[0;36m$$$$ss[32mn [1;36m$$[0;36m$$$[32m$ [1;36m$[0;36m$$[32m$$$ [1;36m$$[0;36m$$$$[1m\"$[0;36m$S#[32mn.[1;35m`:[0m::::::::::::");
|
||||
put_it(" [1;36m$[0;36m$$$$[32m$[1;36m`\"$[0;36m$SSn[32m. [1;36m$$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36mgg#[0;36mS[32m$ [1;36m$[0;36m$$$$[32m$ [1;36mggg[0;36mgg[32mn [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;35m:[0m:[1;31m::\"[0m````````");
|
||||
put_it(" [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$$[0;36m$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$$[0;36m$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;35m:[0m:[1;31m: [37mG[0mreets [1mT[0mo[1;30m");
|
||||
put_it(" [36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;35m:[0m:[1;31m: [36mT[0;36mrench[1;30m,");
|
||||
put_it(" [36m$[0;36m$$$$[32m$ [1;36m,$[0;36m$$$[32m$$ [1;36m$[0;36m$$$$[32m$$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$[32m$$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$[32m$$ [1;36m$[0;36m$$$[32m$$ [1;36m$[0;36m$$$[32m$$ [1;35m:[0m:[1;31m: [36mL[0;36mifendel[1;30m,");
|
||||
put_it(" [36m$[0;36m$$$$$ss$$$[32m$S' [1;36m$[0;36m$$$[32m$$$ [1;36m`S[0;36m$$$$s$$[32m$S' [1;36m`S[0;36m$$$$s$$$[32m$S' [1;36m$[0;36m$$[32m$$$ [1;36m$[0;36m$$[32m$$$ [1;35m:[0m:[1;31m: [36mJ[0;36mondala[1mR[30m,");
|
||||
put_it("[31m.[0m............[1;35m.:[31m:[11C[35m.[0m......[1;35m.:[31m:.[11C[35m:[31m:.[0m.....[1;31m:[0m.......[1;35m:[0m:[1;31m: [36mZ[0;36mircon[1;30m,");
|
||||
put_it("[0m:::::::::::::[1;31m:'[10C[35m.:[0m:::::::::::[1;31m:.[10C[35m`:[0m::::::[1;31m:\"[0m``````[1;31m`' [36mO[0;36mtiluke[1;30m,");
|
||||
put_it("[0m:::::::::::[1;31m:'[10C[35m.:[0m:::::::::::::::[1;31m:.[10C[35m`:[0m:::[1;31m: [36mH[0;36mappy[1mC[0;36mrappy[1;30m, [36mY[0;36mak[1;30m,");
|
||||
put_it("[0m:::::::::[1;31m:'[10C[35m.:[0m:::::::::::::::::::[1;31m:.[10C[35m`:[0m:[1;31m: [36mM[0;36masonry[1;30m, [36mB[0;36muddha[1mX[30m..");
|
||||
put_it("[0m:::::::[1;31m:'[11C[35m:[0m:::::::::::::::::::::::[1;31m:[11C[35m`:[31m:.[0m...................");
|
||||
put_it(":::[1;31m:\"[0m\"[1;31m'[14C[0m`[1;35m\":[0m:::::::::::::::::[1;31m:\"[0m'[14C[1;35m`[0m\"[1;35m\":[0m:::::::::::::::::");
|
||||
put_it("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::[0m");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
put_it(" [1;35ml$[0;35m$[31mS'[1;30m.:[0m::[1m:... [35m`[0;35m\"~^\"[31m' [1;35m`\"[0;35ml[31m' [1;30m..:[0m:::::::::::.[1;35m`[0;35m\"[31m\"[37m.:[1m:..[5C[35m\"[0;35m|[7C[1;30m.[0m.[1;30m.:[0m:[1m:.[35m`S$$[0;35m$[31ml");
|
||||
put_it(" [1;35m$[0;35m$[31m$ [1;30m:[0m::::::::[1m:.[9C[0;31m| [1;30m:[0m:::::::::::::::::::::::[1m:[5C[0;31m:[5C[1;30m.:[0m:::::::[1m:.[35m`$[0;35m$[31m$");
|
||||
put_it(" [1;35m$[0;35m$[31m$ [1;30m:[0m::::::::::[1m:.[7C[0;35m. [1;30m`:[0m:::::::::::::::::::[1m:'[6C[0;31m. [1;30m.:[0m::::::::::[1m: [35m$[0;35m$[31m$");
|
||||
put_it(" [1;35m$[0;35m$[31ml [1;30m:[0m::::::::::::[1m:.[10C[30m`:[0m:::::::::::::::[1m:'[10C[30m.:[0m::::::::::::[1m: [35ml[0;35m$[31m$");
|
||||
put_it(" [1;35m$[0;35m$[31m| [1;30m:[0m::::::::::::::[1m:.[10C[30m`:[0m:::::::::::[1m:'[10C[30m.:[0m::::::::::::::[1m: [35ml[0;35m$[31m'");
|
||||
put_it(" [1;35m$[0;35m$[31m'[1;30m.:[0m::::::::::::::::[1m:.[10C[30m`:[0m:::::::[1m:'[10C[30m.:[0m::::::::::::::::[1m: [0;35ml[31m'[35m_");
|
||||
put_it(" [1m$[0;35mg [1;30m:[0m::::[1m:\"[0m\"````\"[1;30m\":[0m::[1m:'[36m.g$[0;36m$S[32m$'[6C[1;30m`:[0m:::[1m:'[11C[30m\":[0m::[1m:\"[0m\"```[1;30m\":[0m:::::::[1m: [0;31m| [35mL");
|
||||
put_it(" [1ml[0;31m\"[1;30m.:[0m:[1m:'[36ms#S[0;36m$$$\"[1m$$[0;36mS#[32mn.[1;37m` [36m$$[0;36m$$[32mS\". [1;36ms#S[0;36m$$[32m$ [1;30m`[37m:' [36m.g#[0;36mS$$[1m\"$[0;36m$S#[32mn. [1;36ms#S[0;36m$$[32m$ [1;30m`[0m\"[1;30m\":[0m::::[1m: [0;31m:[1;35m,[0;31m$");
|
||||
put_it(" [35m| [1;30m:[0m::[1m: [36m$$[0;36m$$$[32m$[1;36m_,$[0;36m$[32m$S'[1;30mrE[36m.g#[0;36mS$$[32m$ [1;36m$$[0;36m$$$$ss[32mn [1;36m$$[0;36m$$$[32m$ [1;36m$[0;36m$$[32m$$$ [1;36m$$[0;36m$$$$[1m\"$[0;36m$S#[32mn.[1;30m`:[37m:'[35m,$[0;31m$");
|
||||
put_it("[1;35m_[0;35m,L[1;30m`:[0m:[1m: [36m$[0;36m$$$$[32m$[1;36m`\"$[0;36m$SSn[32m. [1;36m$$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36mgg#[0;36mS[32m$ [1;36m$[0;36m$$$$[32m$ [1;36mggg[0;36mgg[32mn [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;30m:[37m: [35m$[0;35m$[31m$");
|
||||
put_it("[1;35m`\"$[0;31mn[1;30m\":[37m: [36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$$[32m$ [1;30m:[37m: [35m$[0;35m$[31m$");
|
||||
put_it(" [1;35m$$[0;35m'[31mL[1;30m:[37m: [36m$[0;36m$$$$[32m$ [1;36m,$[0;36m$$$[32m$$ [1;36m$[0;36m$$$$[32m$$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$[32m$$ [1;36m$[0;36m$$$$[32m$ [1;36m$[0;36m$$$[32m$$ [1;36m$[0;36m$$$[32m$$ [1;36m$[0;36m$$$[32m$$ [1;30m:[37m: [35m$[0;35m$[31m$");
|
||||
put_it(" [1;35m$[0;31m$[35m.[31m\"[1;30m:[37m: [36m$[0;36m$$$$$ss$$$[32m$S' [1;36m$[0;36m$$$[32m$$$ [1;36m`S[0;36m$$$$s$$[32m$S' [1;36m`S[0;36m$$$$s$$$[32m$S' [1;36m$[0;36m$$[32m$$$ [1;36m$[0;36m$$[32m$$$ [1;30m:[37m: [35m$[0;35m$[31m$");
|
||||
put_it(" [1;35m$[0;35m$[31m. [1;30m:[37m:.[0m............[1;30m.:[37m:[11C[30m.[0m....[1m. [32mB[0;32mitch[1mX [37mb[0my [1;36mP[0;36manasync[1;34m! [30m.[0m..[1m:[0m.......[1;30m:[37m: [35m$[0;35m$[31m$");
|
||||
put_it(" [1;35m$[0;35m$[31m| [1;30m:[0m::::::::::::::[1m:'[10C[30m.:[0m:::::::::::[1m:.[11C[30m:[0m:::::::::::::[1m:'[35m.[0;35m$$[31m$");
|
||||
put_it(" [1;35m$[0;35m$[31ml.[1;30m`:[0m:::::::::::[1m:'[10C[30m.:[0m:[1m:'[30m\":[0m::::::::::[1m:.[10C[30m`:[0m:::::::::::[1m: [35ml[0;35m$$[31m$");
|
||||
put_it(" [1;35m$[0;35m$$[31ml [1;30m`:[0m::::::::[1m:'[10C[30m.:[0m:::[1m: [0;31m|[1;30m`:[0m:::::::::::[1m:.[10C[30m`:[0m::::::::[1m:'[35m,$[0;35m$[31m$$");
|
||||
put_it(" [1;35m$[0;35m$S[31m$s,._[1;30m`\"\":[0m:[1m:'[11C[30m:[0m:::[1m:'[35m_a[0;35ml[31m-[1;30m`:[0m::::::::::::[1m:[11C[30m`:[0m::[1m:\"\"'[35m,S$[0;35m$[31m$$$");
|
||||
put_it(" [1;35m$[0;35m$$S$$$[31m$$SS#ss,.__[9C[1;30m`\":[0m:[1m:[35m`$[0;35m$[31ms.[35m_[31m_[1;30m`\":[0m:::::[1m:\"[0m' [1;35m__[0;35m_.[1m,[0;35m,,[1mss[0;35ms##SSSS$$$$[31m$S\"`");
|
||||
put_it(" [1;35m`\"[0;35mS$$$$$$$$$$$$$$$$$$$$$$$$$SSSSSS[31m$'[35m~\"\"\"\"\"\"\"\"\"~~~~~~~~\"\"\"\"\"\"\"\"\"\"\"\"```[31m```'[0m");
|
||||
break;
|
||||
case 2:
|
||||
#endif
|
||||
put_it(" ,");
|
||||
put_it(" . ,$");
|
||||
put_it(" . ,$'");
|
||||
put_it(" . . ,$'");
|
||||
put_it(" : ,g$p, . $, ,$'");
|
||||
put_it(" y&$ `\"` .,. $&y `$, ,$'");
|
||||
put_it(" $$$ o oooy$$$yoo o $$$ `$, ,$' -acidjazz");
|
||||
put_it(" . $$$%%yyyp, gyp`$$$'gyyyyyyp, $$$yyyyp, `$, ,$' .");
|
||||
put_it(" . yxxxx $$$\"`\"$$$ $$$ $$$ $y$\"`\"$$$ $$$\"`\"$$$ xxx`$,$'xxxxxxy .");
|
||||
put_it(" $ $$7 l$$ $$$ $$$ $$7 \"\"\" $$7 ly$ .$' $");
|
||||
put_it(" $ $$b dy$ $$$ $y$ $$b $$$ $$b d$$ ,$`$, $");
|
||||
put_it(" . $xxxx $$$uuu$$$ $$$ $$$ $$$uuu$$$ $$$ $$$ x ,$'x`$, xxxx$ .");
|
||||
put_it(" . \"\"\" \"\"\" \"\"\" \"\"\" \"\"\" ,$' `$, .");
|
||||
put_it(" b i t c h - x ,$' `$,");
|
||||
put_it(" $' `$,");
|
||||
put_it(" ' `$,");
|
||||
put_it(" `$,");
|
||||
put_it(" `$");
|
||||
put_it(" `");
|
||||
|
||||
|
||||
#ifndef BITCHX_LITE
|
||||
break;
|
||||
case 3:
|
||||
put_it(" : :");
|
||||
put_it(" :::::::::: ::::::::::");
|
||||
put_it(" : : _:______ ______:_ : :");
|
||||
put_it(" :::: _\\ \\ / / ::::");
|
||||
put_it(" _ ___ _ \\/_ /__ _______");
|
||||
put_it(" ::::::::: _________/\\___/\\__ /__ _____/\\__ / ::::::::::");
|
||||
put_it(" : \\_____ ___ __ _________ __ /_ :");
|
||||
put_it(" : ::: . / /____/ / /___/ /___/ ___ \\ . ::: :");
|
||||
put_it(" : : : : _/ /_ \\ / // / / / / : : : :");
|
||||
put_it(" ::::: | \\_____ /___/\\___ /\\____ /___/ / | :::::");
|
||||
put_it(" : +------- \\/ ------- \\/ ---- \\/ - /___// ----+ :");
|
||||
put_it(" : ::::: //_______/ \\_______\\_ ::::: :");
|
||||
put_it(" : : : : : :");
|
||||
put_it(" [ b i t c h X i r c c l i e n t ]");
|
||||
put_it(" : : by panasync : :");
|
||||
put_it(" :::::::::: ::::::::::");
|
||||
put_it(" : :[blaze] : :");
|
||||
put_it(" ::::: :::::");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
put_it("[8C[1;35m________[0m[9C[1;30m [35m________ [0m[8C[1;35m________[30m [0m [1;30m [0m[4C[1;35m________");
|
||||
put_it("[0m[8C[1;35m\\[0m[6C[1;35m//___________\\[0m[6C[1;35m/________\\\\[0m[6C[1;35m/_________\\_[0m[5C[1;35m//");
|
||||
put_it("[0m[6C[1;35m___[0;35m\\[37m [1;30m [0m [1;30m [0;35m___[37m [35m_________[1;30m [0m[4C[35m__[37m[5C[35m_______[37m[8C[1;30m [0;35m\\[37m[5C[35m/[37m[4C[35m/");
|
||||
put_it("[37m[8C[35m<<_____[1;30m [0m[4C[35m\\[1;30m [0m[4C[1;30m [0;35m/[37m[6C[35m> [37m[4C[35m\\[37m [1;30m [0m [35m/____\\[1;30m [0m [35m>>[37m[8C[35m\\[1;35m ___");
|
||||
put_it("[0m[6C[1;30m____[0m[4C[1;30m/______\\_____<<_____//___________>> /_______\\[0m [1;30m/_____>>sm");
|
||||
put_it("[0m[8C[1;30m<<___________[0m[7C[1;30m [0m bitchx by panasync[7C[1;30m /______\\\\[0m [1;30m____");
|
||||
put_it("[0m[20C[1;30m/------------------------------------------------\\\\");
|
||||
put_it("");
|
||||
put_it("");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef BITCHX_LITE
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
put_it("[0m[12C[35m [37m");
|
||||
put_it("[4C[35m ÜÜÜ[37m[33C[35m [37m[28C[34m [37m");
|
||||
put_it("[35m ÜÛ[1mß[0;35mßÜÜÜÜÜ[37m[10C[35m°[30;45m²[37;40m[5C[36m [37m[4C[35m [37m [1;35;45mÞ[40mÜ[0m[3C[35mÜ[1mÜ[0;35m [37m");
|
||||
put_it("[4C[35m Ü[1mÜ[45mÛ[40mßß[0;35mß ÜÜÜ[1mÜÜ[0;35mÛßßß [37m [35m [37m[4C[36m [37m[7C[35mß[37m[6C[35m ß[1mßß[45mßÛÜ[40mÜÜ[0;35mÜ[37m [35mÜ[1;45mÜ[0;35mÜ[37m");
|
||||
put_it("[6C[35m ßß Ü[1mÜÜ[45mÜ[47mßß²[45mÛß[31m [0;35mß[37m[7C[35m [37m[4C[35m [37m[5C[35m [37m[21C[35mß[1;45mß[47m²²[45mÜÛÛß[0;35mß[37m");
|
||||
put_it(" [34mÛ[1;44m°°[0;34mÛÛ[37m [35mÜ[1;45mÜÛ[47mÛ²Ýß Þ[45mÛÝ[31m [0;35mÝ[34m [37m[5C[34mÜ[1mÜÜ[0;34mÜ[37m [35m [37m [34mÞ[1;44m [0;34mÛÛ[37m [35m [37m[12C[34mÞÛÛÛÛ[1;44m [0;34m [35mÞ[1mÜÜ[0;35mÜÞ[1;45mÞÛÛß[0;35mß [37m");
|
||||
put_it(" [34mÛ[1;44m²²[40mÜÜÜÜÜÜÜÜÜÜ[0;34mÜ[37m [1;35mßß[0;35mßÛÜ[37m [34m [37m [34mÜ[1;44mÜÛÛ[47m²ß[44mÛÛÜ[0;34mÜ[37m [35m [37m [34mÛ[1;44m°°°[0;34mÛ[37m [35m [37m[3C[34mÜÜÜ[37m[5C[34mÛÛ[1;44m°°° [0;34m [35mÞ[1;45mÞ[47mß[45mÛ[47mÛÛÛ[45mÜ[40mÜ[0;35mÜ[37m");
|
||||
put_it(" [34mÛ[1;44mÛÛ[47mß[44mÝ[0;34mÝ[37m[5C[34mß[1mß[44mßÛÛÜ[40mÜÜ[0;34mÜ[37m [35mß[37m [34mÞ[1;44mÞÛ²Û[47mÛÜÜÞ[44mÛÝ[0;34mÝ[37m [34mÞ[1;44mÞ²²Ý[0;34mÝ[1mÜÜÜ[44mÜÛ[46m²[44mÛ²°[0m[5C[1;34m [0;34mÞ[1;44m°²²[40m²[44mÝ[0;34mÝ[37m [35mÛ[1;47mÝß²²[40mÛÛÛ[45mß[40mß[0;35mß[37m");
|
||||
put_it(" [34mÞ[1;44mÞ[47mßÞ[44mÝ[0;34mÝ[35mßÝ[37m[7C[34mß[1;44mßÛÛÛÛÜ[0;34mÜ ß[1;44mßßßÞÛ[47mÛÛ[44mß[0;34mß Û[1;44mÛÛÛÝ [40mß[0;34m [37m [34mÛ[1;44mÛÛÝ[0;34mÝ[37m [34mÜ[1mÜÜÜ[0;30;44mÛÛ[1;34m [40mÛ[44mÛ²Ý[0;34mÝ [35mÛ[1;47mÝ Ü[45mß[40mß[0;35mß[34m ÜÜÛ[37m");
|
||||
put_it("[35mÜ[34mÞ[1;44mÞ[47mܰ[40mÛ[0;34mÛ[35m [1mÝ[0;35mܰ[30;45m²[37;40m[5C[34mÞ[1;44mÞ[47m²²[44mÛ²°[0;34mÝ ßßßß ÜÜ Þ[1;44mÞÛ[47mÛ[40mÛ[44m [0;34mÝ Þ[1;44mÞÛÛÜ[47m²²[44mÛß[40mßß[0m [34mÞ[1;44mÞÛÛÛ[0;34mÛ[37m [35mÞ[1mß[0;35mß[37m [34mÜ[1mÜ[44mÜÛÛÜ[40mÜ[0;34mÜ[37m");
|
||||
put_it("[35mÝ[34mÞ[1;44mÞ[47mÛ²Û[44m [0m [1;35mß[0;35mß[37m[3C[34m ÜÛ[1;44mß[40mß[0;34mßß [37m [34mÜ[1mÜÜÜ[44mÜÛÛÛÝ[0;34mÝ[37m [1;34;44m ÛÛÛÛ[0;34mÛ[37m [34m Ü[1;44mÜÛ[47mÛÜ[44mÛß[0;34mß [37m [35m [34m Û[1;44mÛÛÛ°[0m [34mÜÜ[1;44mÞß[40mßß[44mßÛÛÛ²°[0m");
|
||||
put_it("[35mÝ [34mÛ[1;47mÛÛ[44mÛ[0;34mÛ[37m[6C[34mßß[37m[10C[34mß[1mß[0;34mÞ[1;44mÞ[47mÝ ÜÛ[0;34mÛ[37m [34mÞ[1;44mÞÛ[47m²Û[44mÝ[0;34mÝ[37m [34m Þ[1;44mÞ[47mÛÝß[44mÛÝ[0;34mÝ[37m [35m [1;30m Pe^[0;35m [34mÞ[1;44mÞ[47m²²[44mÛÛß[0;34mß [37m [34m Û[1;44mÛ[47m²[44mÛÝ[0;34mÝ[37m");
|
||||
put_it("[30;45m°[37;40m [34mÛ[1;44mÛÛßß[40mßßß[44mßÛÛÜ[40mÜÜÜÜ[0;34mÜ[37m[8C[34mÞ[1;44mÞ[47mݰ[44mÛÝ[0;34mÝ[37m [34mÛ[1;44mÛ[47mݰÛ[44mÝ[0;34mÝ[37m [35m [34m ß[1;44mßÛ[47mÜÜÛ[44mÜ[0;34mÜ[37m [35m [37m [34mÛ[1;44mÛÛÛ [0m [34m [37m [34mÞ[1;44mÞ[47mß°[44mÛ [0m[35mÜ[37m");
|
||||
put_it("[35m°[37m [34mÛ[1;44mÛÛÛÝ[0;34mÝ[37m [35mÜÜÜ[37m [34mß[1mßß[44mßÛ[47mÛßÛ[44mÜ[40mÜÜ[0m [34mÛ[1;44mÛ[47mܲ[44mÛÝ[0;34mÝÞ[1;44mÞÛ[47m Þ[44mÛ[0;34mÛ[37m [35mÜÞ [37m [34m ß[1mß[44mßÛ[40mÛÛ[44mÜ[40mÜ[0;34mÜ[37m [35m [37m [34mÞ[1;44mÞÛÛÝ[0;34mÝ[37m [35m°[30;45m²[37;40m [34mÞ[1;44mÞ[47m Þ[44mÝ[0;34mÝ[35mÝ[37m");
|
||||
put_it(" [34mÞ[1;44mÞ[46mß²[44mÝ[0;34mÝ[37m[4C[35mß[1;45m°ÜÜ[0;35mÜÜ[37m [34mß[1;44mßÛ[47mÜ ßßÛ[44mÛÛÛÛÛÛÜÜ[47m²ß[44mÛÛÛ[0;34mÛ [35mÛÜ[37m[3C[34mÞ[1;44mÞÛÛÛÛßßÛÛÛÜ[40mÜ[0;34mÜ [1;44m ÛÛÝ[0;34mÝ[37m[4C[34mÛ[1;44mÛÛÛ[0;34mÛ[35mÜÝ[37m");
|
||||
put_it(" [34mÞ[1;44mÞ²ÛÛÜ[0;34mÜ [37m [35m Þ[1;45mÞ[47m²[45mßÝ[0;35mÝ[37m [34mÞ[1;44mÞ[47mÛÝ °²²[44mÛÛ[40mÛÛÛ[44mÛÛÛÛÛ[0;34mßßß Ü[1;44mÜÛÛÛß[0;34mß[37m [35mÜ[37m [34mß[1mß[44mßÛÛÛÜÞÛÛ[0;34mÛ[37m [34m [37m [34mÛßß[1;44m [0;34mÝ[35m°[30;45m²[37;40m");
|
||||
put_it(" [30;44m°[34;40m²[1;44m°[0;34mÝß[1mß[0;34mß [37m [35m [37m [35mß[1mßß[0m[3C[34mÜ[1;44mÜÛßÛ[47m²²[44mÛß[40mßß[0;34mß [37m [34mßß[1mß[44mßÛÜ[40mÜÜÜ[44mÜÛß[40mßß[0;34mß [35mÜ[1mÜ[45mÜ[47mß[45mÛÜ[0;35mÜ[37m [34mß[1;44mßÛÛ[46mß[44mÛ[0;34mÛ [37m [34m ÛÜ [37m");
|
||||
put_it(" [34m°[30;44m²[34;40m [37m [34m [37m [34mÜ[1mÜÜÜ[44mÜ[40mÛÛÛ[44mÝ[0;34mÝ[1;44mÞß[0;34mß[37m [34m [37m[5C[34mß[1;44mßÛÛÜ[0;34mÜ [35mßÛ[1;45mß[47mÛÜ °²[45m²°[0;35mÝ [37m [34mÞ[1;44mÞ[46m²²[44m²°[0;34mÝ[37m [34m [37m");
|
||||
put_it(" [34m [37m[14C[35m [37m [1;34;44mÞ[0;34mÝ[37m[4C[1;30mP[41mh[40monyEye[0;34m [37m [34mÞ[1;44mÞÛ²°[0;34mÝ [35mÞ[1;45m ÞßÛ[47m²[45mÛß[0;35mß[34m [35m [34m [37m");
|
||||
put_it("[4C[34m[[37m%15s[34m][35m [37m [1;34mÞ[0;34mß[37m[4C[1;30m^[0m[10C[34mÜ[1;44mÜÛß[40mß[0;34mß[37m [35mÜÛ[1;45m ß[0;35mÝßß°[30;45m²[37;40m[8C[1;30mAwe/Cia[0m", irc_version);
|
||||
put_it("[10C[35m [34m [1mß[0;34m [37m[9C[34mÛÛ ß[37m[5C[35m [34m [35mÝ[37m[7C[0m");
|
||||
put_it("[1;30m [0;35m [37m[32C[35mß[37m[14C[35m [37m");
|
||||
put_it("[10C[35m [37m");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
#endif
|
||||
|
||||
|
||||
put_it("[0;1;44m [0;34mÛÛÛßÛÛÛÛÛÛÛÛÛß[35mÜ[1;45m±²[40mÜ[0;34mßÛÛ");
|
||||
put_it("[44m [1;46m±[5C[44m [46m±[5C[0;34mÛÛÛÛÛ[44m [40mÛÛÛÛÛÛÛÛÛÛÛÛ[1;46m°[5C[44m [0;34mÛßß[35mÜ[1mÝ[0;34mÞÛÛÛÛÛÛß[35mÜ[1;45m°±²Û[40mß[0;34mÜÛÛ");
|
||||
put_it("[44m [1;46m²[5C[40mÜ [0;34mß[1;46m±[5C²[5C[0;34mÜÜÜÛÛÛ[1;44mÜ[40mß Ü [0;34mß[1;46m±[5C[40mÜ [0;35mÜÜÜÜ[1;45m°±²[40mÝ[0;34mÞÛÛÛÛß[35mÜ[1;45m°±[0;35mßß[1mß[0;34mÜÛÛÛÛ");
|
||||
put_it("[44m [1mÛ[5CÛ[5CÜ[0;34mßßßßß[1;44mÛ[5CÛ[5CÛ[5C²[5C[46m²[5C[44mÛ[5C[0;35mßßßß[1;45m±²[40mÜ[0;34mßÛß[35mÜßß[34mÜÜÛÛÛÛÛÛÛÛ");
|
||||
put_it("[44m [1m²[5C²[5CÛ[5C²[5C²[5C²[5CÜ[0;34mßßßßß[1;44mÛ[5C²[5C[0;34mÛÛÛÛÜÜÜ[35mß[1mþ[0;34mÜþÛÛÛÛÛÛÛÛÛÛÛÛ");
|
||||
put_it("[44m [1m±[5C±[5C²[5C±[5C±[5C±[5C±[5C²[5C±[5C [0;34mÛÛÛÛß[35mÜ [34mÛÜ[1;35mßÜÜ[0;34mßßßÛÛÛÛÛÛÛ");
|
||||
put_it("[44m [1m°[5C°[5C±[5C°[5C°[5C°[5C°[5C±[5C°[5C [0;34mÛÛß[35mÜ[1;45m°[0;35mÝ[34mÞÛÛÝ[1;35mÞ[45mÛ²±°[0;35mÜÜÜ[34mßÛÛÛ");
|
||||
put_it("[44m [5C[30mÜ[5C[1;34m°[5C [0;34mÜ ß Ü[44m [40mÜ ß Ü[1;44m°[5C[0;34mÛ[5CÛß[1;35mÜ[45m±° [1C[0;34mÛÛÛÛ [1;35;45m²±± ° [0;35mÛÛÜÜÜ");
|
||||
put_it("[44m [34;40mÛÛß[1;35mÜ[45m²±° [0;35mÝ[34mÞÛÛÛÛÛ [1;35;45m±°°[0;35mÛÛÛßß[34mÜÜ");
|
||||
put_it("[44mÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÝ[1;35mÞ[45m²±° [1C[0;34mÛÛÛÛÛÛÛ [1;35;45m°[0;35mßß[34mÜÜÛÛÛÛ");
|
||||
put_it("[44mÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÜ[1;35mß[0;35mßßß[34mÜÛÛÛÛÛÛÛÛÛÜÛÛÛÛÛÛÛÛ");
|
||||
put_it("[0m");
|
||||
|
||||
|
||||
#ifndef BITCHX_LITE
|
||||
break;
|
||||
case 2:
|
||||
put_it("[24C[1;30mÜß[0m [1;30mß[0m");
|
||||
put_it("[23C[1;30mÛÜþÜß[0m [1;30mß[0m [1;30mÜ[0m[24C[1;31m [0m");
|
||||
put_it("[23C[1;30mß[0m [1;30mþ[37m [30mÜ[0m [1;30mÜÛß[0m[21C[1;31mÜÜ[41m°±²²[40mÜ [0m");
|
||||
put_it("[23C[1;30mßÜÛÜ[0m [1;30mÜ[0m[22C[1;31mÜÛ[41m°°±±²²±°[40m [0m");
|
||||
put_it("[20C[1;30m [0m [1;30mßÜ[33m [0;31mÜ[1;37m [0m[19C[1;31mÜÛ[41m°°±±²²²±[40mß[0m");
|
||||
put_it("[11C[1;33m [30m [33m [30;41m°±[33;43m°[30;41mÛ[37;40m [0m[16C[34mÜÛ[1;31;44mß[40mÛ[41m°°±±²²[40mß[0m");
|
||||
put_it("[13C[1;33m [0m [1;30m [0;31mÜ[1;30;41m°²[33;43m±°[37;40mÛÛÜ[0m[14C[34mÜÛ[1;44mÛ²±°[31mßß[40mÛßß[0m");
|
||||
put_it("[22C[32m [1;30m [0;31mß[1;30;41m±[37;40mÛ[42mÛÛÛÛÛ[40mÜÜ [0;32m [37m[7C[34mÜÛ[1;44mÜÛ²±°[0;34mß [37m");
|
||||
put_it("[7C[32mÜÜÜÜÜÜÜÜ [1;37m [0m [32mÜÜÜÜ[37m[4C[32mÜÜ[1;37;42mßßßßßß[40mÛ[0;32mÜÜÜÜ[37m [34mÜÛ[1;44mÜÛ²±°[0;34mß[37m");
|
||||
put_it("[32m [37m[6C[32m° Û[1;42m [0;32m ÛÛ ßÛÛ °[37m [32mÛÛÜÜ ° ÛÛ[1;37mÛÛ[0;32mÛÛ[1;37mÛÛÛ[0;32mÛÛ[34mÜÛ[1;44mÜÛÛ²±[0;34mß[37m");
|
||||
put_it("[9C[32mÛ[1;42m [0;32m ÜÛß[37m [32m ÛÛ[37m[3C[32mÛÛ [37m [32mÛÛ[37m [1mßÛÛÛÛÛ[0;32mÛÛ[1;34;42mÜÜ[0;32mÛÛ[34mÛß[37m");
|
||||
put_it(" [32m [37m[7C[32mÛ[1;42m [0m [32mßÛÜ[37m [32m ÛÛ[37m[3C[32mÛÛ[37m [32m [37m [32mÛÛ[37m [1m [0;32mÛÛ[1;37mÛ[44mß[34m [0;32mÛÛ[1;34;44mÛß[0;32mÛÛ[1;30m [0m [1;30mby panasync[0m");
|
||||
put_it("[8C [32mÛ[1;42m [37;40m [0;32m ÛÛ[37m [32m ÛÛ [37m [32mÛÛ[1;37m [0;32mÛÛ[37m [32mÛÛ[1;37m [0;32mÛÛ[1;34;44m°±²[0;32mÛÛ[34mÛß[32mÛÛ[1;37mÛ [0m");
|
||||
put_it("[7C[32mÜÜ[1;42m [0;32mÜÜÛÛ[1;37m [0;32mÜÛÛ ÜÜ[1;42m [0;32mÛÜÜÛÛ[37m [32mÜ[1;42m [0;32mÛÜÜÛÛ[1;34;44mÛ[42mßß[0;32mÛÛ[1;37mÜÛ[0;32mÛÛ[1;37mÛÛÜ[0m");
|
||||
put_it(" [32m [37m[28C[34mÜ[1;44m°±²Ûß[0;34mÛß[1;37m ßÛÛÛÛÛÛÛÛ [0m");
|
||||
put_it("[8C[1m*[30mSpark it Up[37m*[0m[8C[34mÜ[1;44m°±²Ûß[0;34mÛß[37m[5C[1mßßÛÛÛÛÛÛÜ[0m [1m [0m");
|
||||
put_it("[27C[34mÜ[1;44m°±²Ûß[0;34mÛß[37m[10C[1mßÛÛÛÛÛÛ [0m");
|
||||
put_it("[26C[34mß[1;44m°±²Û[0;34mÛß[37m [1;30m[Joker][0m[5C[1mßßÛÛÛÛÜ[0m");
|
||||
put_it("[27C[1;34m [0;34mß[1;44m°[0;34mß[37m[18C[1m ßÛÛÜ[0m");
|
||||
put_it("[15C[1m [0m[11C[1;34m [0m[24C[1mßß[0m");
|
||||
put_it(space);
|
||||
break;
|
||||
case 3:
|
||||
put_it(space);
|
||||
put_it(space);
|
||||
put_it("[5C[1;36m [0;36;40mÜ[0m[8C[1;36mÜÜÜÜ[0m[10C[36mÜ[0m[21CÜ[1;47m°Ü[40mÜÜ[0m [36mÜ[0m");
|
||||
put_it("[6C[36mÞ[1;46m°Ü[40mÛÜÜÛßß[46m±²[40mÛÛ[47m²[40mÜ[0m[5C[36mß[1;46m°[0;36;40mÜ[1;46m±Ü²[40mÛÛÜÜÜÜ[47m²[40mÜ[0m ßÜÜ [1mÜÜ[0mß[1;47m°±²[40mÛÛÝ[0m [36mÞ[1;46m°±[40mÜÜÜÛß[0m");
|
||||
put_it("[7C[36mÛ[1mÛÛ[47m²[40mÛÝ[0m [36mÞ[1;46m°[40mÛÛÛÛß[0m ÜÜ[1mÜÜ[0;36;40mß[1;46m°[40mÛÛ[47m²[40mÛ[0m [1;36m²[0m[5C[1;47m [40mÛ[47mÜÛ[40mÛÝ[0m Þ[1;47mÞßß±²[40mß[0m [1;36;46m±²[40mÛ[47m²²[40mÛ[0m");
|
||||
put_it(" Ûßßß [36mÛ[1;46m°ß±²[40mÝ[0;36;40mÜÜ[1;46m°±ß²[40mÛß[0m Ü[1;47m°Ü²ÛÛ[40mÛ[0m [1;36;46m°ßß±²[40mÝ[0m[8Cß[1;47m°ßß±²[0m ßß[6C[36mß[1;46m°ßß±²[40mÜ[0m [1;36mÜÜÜ[0m ßßßßß[1;47m°[0m");
|
||||
put_it(" Û [1;47m±²[0m ÜÜÜÜ[1mÜÜ[0m [36mß[0mÜÜÜ[1mÜÜ[0m [36mÜÜÜ[1mÜÜÜÜ[0m ÜÜÜÜ[1mÜÜ[0m ßÜÜÜÜ[1;47mÜ[40mÛß[0;36;40mÜÜÜ[1mÜÜ[0m [36mß[1;46m°[40mÜÜ[46m²[40mÛÛß[0mÜÜÜ[1mÜÜÜ[36mßßß[0mÜÜ[1;47mܱ[40mÜßÛÛ[0m [1;47m°[0m");
|
||||
put_it(" Û Ü[1;47mÜ[40mÝ[0mÞ[1;47m±²[40mÛÛÛÝ[0m Þ[1;47mÞÛ[33mÛ[37;40mÛÛÜ[0m [1;36;46m°[40mÛÛ[47m²[40mÛ[0m Þ[1;47m°±²[40mÛÛÝ[0m Þ[1;47m°±Û[40mÛÛÝ[0;36;40mÞ[1;46m°±[40mÛÛÝ[0m [36mÞ[1;46mÞ[40mÛÛ[47m²²[40mÝ[0mÞ[1;47m°Þ[33mÛ[37mÛ[40mÛÝ[30m°±[0mÞ[1;47mÞÛ[40mÛÛÝÞÛ[0m Û");
|
||||
put_it(" [1;47m°[0m [1mÛÛ[0m [1;47m°±[40mÛÛ[47m²²[40mÛ[0m [1;47m°±[40mÛ[47m²²[40mÛÝ[0;36;40mÞ[1;46m°ß±²[40mÛÝ[0mÜßß[1mß[47m±²ßß[40mÜÜ[47mܲ²[40mÛß[0m [1;36;46m°±ß[40mÛ[46m²[40mÛ[0m [1;36;46m°²Û[40mÛß[0m Û[1;47m°ßß±²Û[30;40m [0mÛßß[1mß[47m°ß[40mÜß[0m Û");
|
||||
put_it(" [1;47m°[0m [1mÛÜ[0mßßß[1mßÜÜßßß[0mÜ[1;47m°ß[40mßßÜ[0;36;40mßß[1;37mÜÜÜ[36mßßß[0m [1;30m²±[0m[6Cßß[1mß[0m [36mßßß[0m [1;36;46m²[40mÜ[46m±[0;36;40mÜ[1;46m±[0;36;40mßß[1mß[37mÜÜ[0mßßß[1mÜÜÜÜßß[0m [1mÜÛÛÛÜÜÜß[0m Û");
|
||||
put_it(" Û [1mÛÛÛ[0mß[1;47m°±[40mÛÜ[0mßßß[1mÜÜ[30m [0mß[1;47mß±²[40mÛß[0mÜÜßß[34mÜÜ[1mÜÜ[44mÜÜÛÛ[40mÛ[44m²²[40mÛÛÛÛ[44m²[40mÜÜÜ[0m Ü [1mÛÛÛ[47m²²[40mÛÛÛÛÛß[30m [0mß[1;47m°±[40mÛÛ[47mß±[40mÛÛÜ[30m [0m [1;47m±[0m");
|
||||
put_it(" Û [1mÛÛÜ[30m [0mß[1;47mß[40mÛ[47mÛ²±²[40mÛÛ[0mÜ[1;47mÜÛ[40mÛß[0mÜß [34mÜ[1;44mܱ[40mÛÛßßßß[0m [34mÜ[1;44m±[40mßßß[30m [0m [34mÜ[1;44m±²[40mÛÛÛÜ[0mßßÜ[1mßÛ[47mß²[40mÛ[32;47mÛÛ[37;40mÛÛÛ[0mÜ[1;47mܲ[40mÛß[30m [0mÜ[1;47m²²[40mÛÛÛ[0m [1;47m±[0m");
|
||||
put_it(" [1;47m±[0m [1mÛÛÛÛÜ[47m±²[40mÛÛß[30m [0mß[1;47m°ßß²[40mÛÝ[0mÞÝp[34mÞ[1;44mÞ²[47m²[44m²[40mÛ[47mÛ[40mÝ[0m [1;30m°[0m [34mÞ[1;44mÞ[40mÛÝ[30m [0m [34mÞ[1;44mÞ[40mÛÛÛÛ[47m²²[40mÝ[0mXÞÝ[1mß[30m [0mß[1;47m°ß[40mÛ[47m²²[40mÛÛÛÛÛÛ[0mÜ[1;47m°±[40mÛÛÛÛ[0m [1;47m°[0m");
|
||||
put_it(" [1;47m°[0mÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛÜ [34mß[1;44mß±[40mÛÛÛ[47m²²[40mÜ[0m [34mß[1;44m°[40mß[0m [34mÜÜÜ[1;44m°[40mÛÛÛÛ[47m²²[40mß[0m ÜÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ[1;47m°[0m");
|
||||
put_it("[29C[34mßß[1mß[0m [34mÜÜ[1;44mÜ[0;34;40mß[0m [34mß[1;44m°[0;34;40mÜÜßßß[1mßß[0;34;40m [0m");
|
||||
put_it("%17s irc client [34mÞ[1;44m°[40mÛ[47m²²[40mÜÜ[0m [34mÞ[1;44m±²[40mÝ[0m", irc_version);
|
||||
put_it("[13C-by Panasync[8C[34mß[1;44m°ß[40mßß[0m [34mÜ[1;44m°[40mÛ[47m²²[0m");
|
||||
put_it("[36C[34mÜÜ[1;44m°Ü[40mÛ[47m²²[40mÝ[0m");
|
||||
put_it("[37C[34mßß[1mß[44mß±[40mß[0m");
|
||||
put_it(space);
|
||||
break;
|
||||
case 4:
|
||||
put_it("[0;1;31;41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²Û²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²Û²[40mÛ[41m²²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²Û²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ[41m²[40mÛ");
|
||||
put_it("[41m±²±²±²±²±²±²±²±²±²±²±²±²±±²±²±²±²±²±²±±²±²±²±²±²±²±²±²±²±²±²±²±²±²±²±²±²±²±²±²[40m");
|
||||
put_it("[41m°±°±°±°±°±°±°±°±°±°±°±°±°°±°±°±°±°±°±°°±°±°±°±°±°±°±°±°±°±°±°±°±°±°±°±°±°±°±°±[40m");
|
||||
put_it("[0;31mÛ[1;41m°[0;31mÛßßßßßßßÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mßßßßßÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mßßßßßßßÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛßßßßßßßÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[0;31mßßßßßßÛ[1;41m°[0;31mÛ[1;41m°[0;31mÛ[1;41m°[40m");
|
||||
put_it("[0;31mß[1;37mÜÜÜ[47m²[40mÛÛßß [0;31mÛÛÛÛÛÛÛ [34mÜÜÜÛÛ[1;44m°[0;34mÜÜÜ[31mÞ [1;37mÜÜÜ[47m²[40mÛÛßß [0;31mÛÛÛÛÛÛÛ [1;37mÜÜÜ[47m²[40mÛÛßßÛÜÜÜÜ [0;31mßß [1;37mÜÜÜ[47m²[40mÛÛßß [0;31mÛÛÛÛÛÛ");
|
||||
put_it("[1;37mÞ[47m²[40mÛ[47m²±²[40mÝ [0;31mßßßßßßßÛÛ [34mßß[1;44m°°[0;34mÛÛ[1;44m°[0;34mßß [1;37mÞ[47m²[40mÛ[47m²±²[40mÝ [0;31mßßßßßßßÛß[1;37mÞ[47m²[40mÛ[47m²±²[40mÝ[5C[47m²²[40mÛ[47m²[1C[40mÞ[47m²[40mÛ[47m²±²[40mÝ [0;31mßßßßßßßß");
|
||||
put_it("[37mÛ[1;47m±²±°±[0mßßßßÛÛ[1;47m±[0mÛÜ [31mÛ [1;37;47m°[0mÜÜÜ ÜÜÜ[1;47m°[1C[0mÛ[1;47m±²±°±[0mßßßßÛÛ[1;47m±[0mÛÜ Û[1;47m±²±°±[6C±±[40mßß [0mÛ[1;47m±²±°±[0mßßßßÛÛ[1;47m±[0mÛÜ");
|
||||
put_it("Û[1;47m°±°[0mÛ[1;47m°[5C[0mÞ[1;47m°±°[0mÝ Þ[1;47m±°±[0mÛ[1;47m±[0mÛ[1;47m°°[0mÝ Û[1;47m°±°[0mÛ[1;47m°[11C[0mÛ[1;47m°±°[0mÛ[1;47m°[7C[0mÜÜÜ Û[1;47m°±°[0mÛ[1;47m°[5C[0mÞ[1;47m°±°[0mÝ");
|
||||
put_it("ßßßßßß[6Cßßßß ßßßßßßßßß ßßßßßß[11Cßßßßßß[6Cßßßß ßßßßßß[6Cßßßß");
|
||||
put_it("[36mÛ[1;46m°°±°±[6C°°±²[1C[0;36mÛ[1;46m°°°±°±°±[2C[0;36mÛ[1;46m°°±°±[6C°°±²[1C[0;36mÛ[1;46m°°±°±[6C°°±²[1C[0;36mÛ[1;46m°°±°±[6C°°±²[40m");
|
||||
put_it("Þ[46m²±²±²[40mÝ Þ[46m±±²[40mÝ [0;36mÞ[1;46m±±±²±²±²[40mÝ Þ[46m²±²±²[40mÝ Þ[46m±±²[40mÝ Þ[46m²±²±²[40mÝ Þ[46m±±²[40mÝ Þ[46m²±²±²[40mÝ Þ[46m±±²[40mÝ");
|
||||
put_it(" ß[46m²Û²Û²[40mÜÜÜÛÛ[46m²[40mßß [46m²[40mÛ[46m²[40mÛ[46m²[40mÛ[46m²[40mÛÛ ß[46m²Û²Û²[40mÜÜÜÛÛ[46m²[40mßß [37mnd[36mß[46m²Û²Û²[40mÜÜÜÛÛ[46m²[40mßß ß[46m²Û²Û²[2C[40mÜÛÛ[46m²[40mßß");
|
||||
put_it(space);
|
||||
put_it("[32C[31mßÛ[41m²[40mÜ [0;31mÜ[1;41m°°[0;31mß");
|
||||
put_it("[34C[1;41m±²[40mÛ [0;31mÜ[1;41m±[0;31mÛß");
|
||||
put_it("[32C[1mÜÜ[0;31mÞ[1;41m±²[40mÝ[0;31mßß");
|
||||
put_it("[30C[1mÜ[41m²±[40mß [41m°±±[40m");
|
||||
put_it("[28CÜÛ[41m²[40mß [0;31mß[1;41m°[0;31mÛÜÜ");
|
||||
put_it("[27C[1mßßß[9C[0;31mßßß");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
put_it("[37m ");
|
||||
put_it(space);
|
||||
put_it("[5CÜþ");
|
||||
put_it("[4CÞÝ[22C[34m°°");
|
||||
put_it("[5C[37mßÜ [34mßß[1;34;44m°[0;37m [1;37m°°[0;34mÞ[1;34;44mÞÛÛÛÛ²²°°[0;34mÛÛÛÛ²²°°[37m [34m°");
|
||||
put_it("[6CÜ[37mßÛ[1;37mÜÜ[0;37mÜ[1;37m°°[0;37m [34mß[1;34mß[44mßÛÛÛÛ²²°°[0;34mßßßß");
|
||||
put_it("[6C[1;34;44m°[0;34mÝ[37mÛ[1;37;47mÛÛÛ[40m²²Û[47mÜ[0;37mÜÜÜ [34mß[1;34mß[44mß[0;34mß[37m ÜÜßßßß");
|
||||
put_it("[6C[1;34;44m²[0;34mÝ[37mÛ[1;37;47mÛÛÛÛÛÛ[0;37mÛ Ý ßßÜ ÜßÝ[34mÜÜÛßß");
|
||||
put_it("[6C[1;34;44mÛ[0;34mÝ[37mÛ[1;37;47mÛÛÛÛÛÛ[0;37mÛ Ý[34mÞß[37m ÞÛÝ Ý[34mÞ[1;34;44m°[0;34mÝ[1;37m°°");
|
||||
put_it("[6C[0;37mÜÜÛ[1;37;47mÛÛÛÛÛÛ[0;37mÛÜÛÜßÞß ßÜÛ [34mßÝ[1;37m°°[23C[0;31mßÜ[18CÜ[1;31;41mÜÜ[0;31mÛ");
|
||||
put_it("[4C[37mÜß Û[1;37;47mßßݲ²ß[0;37mÛ Ý [34mÜþ[37m [34mß[37m ÜÜ[1;37;47mÜ[40mÛ[47mÜ[40m²²Ü[0;37mÜ[23C[31mßÜ[14CÜ[1;31;41mÜÛÛß[0;31mß");
|
||||
put_it("[3C[1;36mÞ[0;37mÝ °°[1;36;47m°[0;37m Þ[1;37;47m°°[0;37m Û Ý[34mÞÛ[37m [1;36m°[0;37mÜ[1;37;47mÜÛÛÛÛÛÛß[0;37mß[26C[31mßÜ[10CÜ[1;31;41m°²²ß[0;31mß");
|
||||
put_it("[4C[1;36mßÜ[0;37mÜ [1;36;47m²[3C[0;37m²² Þ Ý[34mÞ[1;34;44m°[0;37m [1;36m²[37;47mÞÛÛ²²ÛÛÝ[0;37mÝ[7C[1;37;47m° [0;37mÜÜ[4CÜÜÜÜÜ[3C[1;37;47m°[0;37mÛÜ[3C[31mßÜ[6CÜß°²[1;31;41m°[0;31mß");
|
||||
put_it("[6C[34mÜ[1;36mßß[0;37mßß °° Þ Ý[34mÞ[1;34;44m²[0;37m [1;36mÛ[0;37mß[1;37;47mßß°°ßß[0;37mÛ[5C[1;30;47m [37m°[0;37m [1;37;47m²Ý[3C° [0;37m [1;37;47m °[3C[0;37mÜÜ [1;37;47m²Ý[0;37m þÜ [31mßÜ[37m [31mÜß Üß");
|
||||
put_it("[6C[34mÞ[1;34;44m°°[0;34mÛÛÛÜÜ[1;36mß[0;37mß[1;36mÜ[0;37mÝ[1;34mß[44mÛ[0;34mÜ[1;36mÞ[47m°[0;37m ²² Ý[34mß[4C[1;37;47mÞ²[0;37m [1;37;47mÞÝ[3C²Ý[0;37m [1;37;47mÞ²[3CÞ²[0;37m [1;37;47mÞÝ[0;37m [1;37;47mÞ²[0;37m [31m °²Ü[37m [31mßܲ");
|
||||
put_it("[6C[34mÞ[1;34;44m²²°° [0;34mÛÛÝ[37m [1;36mÞ[47mÝ[0;37mÜÜ Üßþ °° Þ²°° ° [1;37;47mÞÝ[0;37m [1;37;47mÞÝ[0;34m°°[37mÞ[1;37;47mÛ[0;37mÝ [1;37;47mÞÝ[0;34m°[37m Þ[1;37;47mÛ[0;37mÝ [1;37;47mÞÝ[0;34m°[37m [1;37;47mÞÝ[0;34m°°[37m [31mÜß ßÜ[37m [31mßÜ[37m [34m°°[37m [34m°");
|
||||
put_it("[37m [1;34m°[0;37m [1;34m°°²²[44mÛÛ²²°°[0;34mß[37m [1;36mþß[0;34mÜ[1;36mÞ[0;37mÝ [34mÜÜ[37m [34mÜ[37mßßß[1;36;47m°[0;37mÜ[5Cßß ßþ ß[3Cßþ ß[7Cß [31mÜß Üß[4CßÜ");
|
||||
put_it("[6C[34mÞ[1;34m²²ßß[0;34mßß[37m [34mßßß[37m [1;36mßÜ[0;37mÜ [1;36mÜ[0;37mÜ[1;36mßß[0;37mß[31C[31mÜ[1;31;41m°[0;31m²°Üß[8CßÜ");
|
||||
put_it("[7C[1;34m°°[11C[36mÞ[0;37mÜß[34C[31mÜ[1;31;41mܲ²°[0;31mß[12CßÜ");
|
||||
put_it("[7C[1;34m°°[11C[36mÞÝ[33C[0;31mÜ[1;31;41mÜÛÛß[0;31mß[16CßÜ");
|
||||
put_it("[21C[1;36mß[0;37mþ[32C[1;31;41m ßß[0;31mß");
|
||||
put_it("[37mÿ");
|
||||
break;
|
||||
case 6:
|
||||
put_it("[63C[31mÜ[37m");
|
||||
put_it(" [30mbitchx! [37m[16C[30mÛ[37m [1mÜ[35mÜÜ[0;35m [37m[8C[31mßÜ[37m[13C[31mÜß[37m");
|
||||
put_it("[3C[1;30m [0;35m [1mÜÜÜÜÜÜÜ[0;35m [1;30m°°°°°°°°°°[0m[4C[1;35mÜÜÜ[37mÜÜ[35mÜÜÛÛ[45m²[40mÜÜ[0;35mÜÜ [1;30m°°°°[0;35m [31mßÜ[35m [1;30m°°[0;35m [1mÜÜÜÜÜÜ[0;35m [1;30m°°°°°°[0m [1;30m°°[0m[3C[1;30m°[0;35m [1;30m ");
|
||||
put_it("[6C[1;45m°Û[40mÛ[45m²[35;40mÛÛÜÜÜÜ[0m [35m [1;37mÜÜ[45m²[40mÜ[35mÜÜÜ[0;35m [1mßßßß[45m²°[0;35mßßßßß [30;45mÛ[35;40m [37m[6C[35m [1mÜ[0;35m [1mÛ[37;45m²²[40mÛ[35mÜÜÜÜ");
|
||||
put_it(" [31m [1m [0;31mÜÜ[35m [1;45mÛ²Û²²²°[0;35m [1mß[45m²²[40mÛÜÜ[0;35m [37m [1;45m°[35;40mÛÛ[45mÛÛ²²[0;35m [30;45m²[35;40mÛÛ[30;45m Û[35;40m [37m°[1;35mÜÜÜÜßßß[45m²ÛÛ[40mÜÜÜ[0;30;45mÛ[1;35m°²²[40mÛ[37;45m²[35m²[0;35m [1mß[45m²²[40mÛÜÜ[0;31m [37m");
|
||||
put_it(" [30;41mÛ[1;31;40m²[0;30;41m²Û²[35;40m [1;45m°°°°° [0;35m [30;45m²±±[1;35m°±ßß²[40mÜ[0;35m [1mß[45m²°°°[0;35mÛ ÛÛÛ [1mÜ[45m²²ßß[0;35mß[30;45mÛ[35;40m [30;45mÛ[35;40mÜ[1;45m°° ß[0;35m Û[1;45m°°°°°[0;35m [1;45m °ßß²[40mÜ[0;35m [37m");
|
||||
put_it("[7C[35mÛ[47mÛ[46mÛÛÛÛ[40mÜÜÜ ÛÛÛÛÛÛÛ[1;45m°[0;35m ßÛÛÛÛ [30;45m²±°°°[35;40m [1;45mÛ±°°°[0;35mÝ [30;45mÛÛÛ[35;40m [31mÜ[35m ß ÛÛÛÛÛß [30;45m²±°[35;40mÛÛÛÛÛ[1;45m ±[0;30;45m²²[35;40m [30;45m²[37;40m");
|
||||
put_it("[4C[35m [30;45m²[35;40mßßßßß[30;45mÛÛ[35;40m [30;45mÛ[35;40mÜÛ[46mÛÛ[40m²ßßßßß Û[46mÛ[40mÛÛ[30;45mÛ[35;40mßßßÛÛßßßÛÛÛÛÜ ßßß ÜÜÜ[30;45m²[35;40mßßßß [31mÜ[35m Ü[30;45m [35;40mÛÛ[30;45m°[35;40mßßßßß[30;45mÛÛ[35;40m [37m");
|
||||
put_it("[12C[30;41m²²[37;40m[9C[30;45m²°°[35;46mÛ[30;45m°[35;40mßßßßß[37m [1;32m [0;35m [30;45mÛ[35;40mßßßßßßÛ[30;45m °±[35;40mß [37m[6C[31mßÜ[35m [30;45mÛÛÛÛÛ[37;40m");
|
||||
put_it("[6C[30m [37m[13C[30;45m²Û[35;40m [30;45mÛ[1;40m sty[0;30m [1m(twilght°. [0;31mÜß[37m [1;30m [0m [30;45mÛ[37;40m [1;30m [0m [31mß[37m");
|
||||
put_it("[44C[31mß[37m [30m [37m");
|
||||
break;
|
||||
case 7:
|
||||
put_it("[51C[1;30m [0m");
|
||||
put_it(empty_string);
|
||||
put_it("[6C [1;30mÜ[37;47m²[40mÜ[0m[40C[1;30m [0m");
|
||||
put_it("[6C[1;30mÜ[37;47m°±±²²[40mÜ[0m [25C[1mÜ[0m[8C[1;36mÜ[46m±[30;40m ° [0m[14C[1;36;46m°[40mÜ[0m");
|
||||
put_it("[6C[1;30m°[47m±°[37m°±²[30;40m°[0m [1;30m [0m[21C[1;30mÜ[37;47m°±²[40mÜ[0m[4C[1;36mÜ[46m°±²[0m [1;30m [0m[4C[1;30m [0m[3C[1;36;46m±°°[40mÜ[0m");
|
||||
put_it("[6C[1;30m°[47m²±°[37m°±[0m[3C[1;30m [0m[3C[1mÜ[0m[7C[1;30mß[47m±°[37m°±²[30;40mß[0m [1;36mÜ[46m°°±²²[40mÜ[30m°° [0m[10C[1;36mÜ[46m²±°°±[40mÜ[0;36m [37m");
|
||||
put_it("[6C[1;30m°[47m²±°[0mÛ[1;47m°[30;40m°Ü[0m [1;30m [0m[5C[1;30mÜ[37;47m±²[40mÜ[0m[6C [1;30;47m±²±[37m°±[0m [1;30mßß[46m°[0;36mÛ[1;46m°±²²²[40mÜ[30m° [0m[3C[1;36m Ü[46m²±°[0;36mÛ[1;46m°±²[40mßß[0m");
|
||||
put_it("[5C[1;30m°±[47m±°[0mÛÛÛ[1;30m°[47mÛ²[40mÜ[0m [1;30m Ü[37mÜ[47m²[40mÜ[30m °[37;47m°±[30;40m±[0m [1;30mÜÜÜÜܰ[47m²[37m°[30;40m°Ü[0m [1;30mß[46m°°[36m°±²²²[40mÜ[30m° [36mÜ[46m²±°[0;36mÛ[1;46m°±²[40mß[30m°°[0m");
|
||||
put_it("[1;30m°° °°±²[47m°[0mÛÛÛ[1;30;47m°[40m Þ[47m±°ß[40mÜ[0m [1;30mß[47mÜ[37m±±²[30;40m±[36m [30m°[0mÛ[1;47m°[30;40m²ß[0m [1;30mÜ[47mß[0mÛÛ[1;30;47mÜ[40mß°Ü[47m±[37m°[30;40m°[47mÛ²[40mÜ[0m [1;30mß[46m°°[36m°°±²²[40mÜ[30m° [36mÜ[46m²±°[0;36mÛ[1;46m°±²[40mß[30m°±°°±±±[0m [1;30m°[0m");
|
||||
put_it("[5C[1;30m°±[0mÛÛÛÛ[1;30;47m°[0m ß[1;30;47m°°[0mÛ[1;30;47mß[40mÜ[0m [1;30;47mÝ[37m°±[40m [30m°[47m°[0mÛ[1;30;47m°[0m [1;30mÜ[47mß[0mÛÛ[1;30;47mÜ[40mß[0m [1;30mÜ[47m²±°°[40m [47m²±°ß[40mÜ[0m [1;30mß[46m°°[0;36mÛ[1;46m°±²²[40mÜ[46m²²±°[0;36mÛ[1;46m°±[40mß[30m°±±°[0m");
|
||||
put_it("[6C[1;30m°[47m°[0mÛÛ[1;30;47m°°[40m°[0m [1;30mÞ[47m°°[0mÛÛ[1;30mÝ[0mÞ[1;30;47m°[37m°[0m [1;30m°[0mÛÛ[1;30;47m°[40m°[0mÛÛÛ[1;30;47m°[40m°° [47m±±°±²[0m ß[1;30;47m°±²Û[40mÜ[0m [36m [1;30mß[46m°°[0;36mÛ[1;46m°±²±°°[0;36mÛ[1;46m°[40mß[30m°°°°°[0m");
|
||||
put_it("[6C[1;30m°[0mÛÛ[1;30;47m °±[40m°[0m[3C[1;30;47m±±°°[40mÝÞ[47m°±[0m [1;30m°[0mÛ[1;30;47m°±[40m°[47m°[0mÛ[1;30;47m°±[40m°[0m [1;30;47m°°±²Û[0m [1;30mÞ[47m²²[40mÛ²°[0m [1;30mÞ[46m°°[0;36mÛ[1;46m°°°[30m°°[0;36mÛ[1;30mݰ°±°°[0m");
|
||||
put_it("[3C[1;30m°°°°[47m°[0mÛ[1;30;47m°±²[40m°[0m [1;30m°Û[47m²±±[40mÝÞ[47m±²[0m [1;30m°[47m°±²[40m°[47m°±±²[40mÜ[0m [1;30;47m°±²Û[40m²[0m [1;30m±²Û²°°[0;36m [1;30mÜ[46m°°[0;36mÛÛ[1;30;46m°[0;36mÛ[1;30;46m°±±°ß[40mÜ[0;36m [1;30m°°°±±°[0m [1;30m°[0m");
|
||||
put_it("[6C[1;30m°[47m°°±²Û[0m [1;30m±±²²Ûß Û[47m²Û[0m [1;30m°[47m±²Û[40m±[0m [1;30mß[47m²Û[40m²²°[0m [1;30mßßß²[0m [1;30m±±²°°Ü[46m°°[0;36mÛÛ[1;30;46m°°Ü[40mß[46m²²±±°[0;36mÛ[1;30;46m°[40mÜ[0m [1;30m°°[0m");
|
||||
put_it("[6C[1;30m°[47m±²ÛÛ[40m²[0m [1;30m°°±±ß[0m [1;30mܱ²[47mÛ[40m²±Ü[0m [1;30;47mÛ[40m²²ß[0m [1;30mß²²±±±ß[0m [1;30m²[0m[3C[1;30m°°°Ü[46m±°°[0;36mÛ[1;30;46m°°Ü[40mß [0m [1;30m°ß[46mÛ²±°°°±[40mÜ[0m [1;30m°[0m");
|
||||
put_it("[6C [1;30;47m²Û[40m²²± °°[0m [4C[1;30m°°°[0m [1;30m ܲ°[0m[3C [1;30mß±°[0m [1;30m ±±[0m [1;30m °Ü[46mÛ²²±±°Ü[40m± [0m[3C[1;30m °ß[46m²°±±²²Û[40mÜ °[37me[0mn[36mx[1m![37m [0m");
|
||||
put_it("[6C [1;30mÛ²²±± °[0m[7C[1;30m°[0m [1;30m °[0m[3C [3C[1;30m°[0m [1;30m°°±[0m [1;30mÜܲ²[46mÛÛ²²±[40m°° [0m[7C[1;30m °±[46m±²²ÛÛ[40m²²ÜÜ[0m");
|
||||
put_it("[6C [1;30m°±±°[0m [1;30m [0m[26C[1;30m°°[0m [1;30m ±²±²²[46mÛ[40m±°[0m [1;30m [0m[9C[1;30m °°Û[46mÛ[40m²²±²±[0;36m [37m");
|
||||
put_it("[9C[1;30m°±°[0m .[1;30mt[0mhe [1;30mb[0mitch [1;30mo[0mf[1;30m I[0mrC. [1;30m°[0m[5C[1;30m°±±²°[0m[15C[1;30m°²±±° [0m");
|
||||
put_it("[10C[1;30m°[0m[37C[1;30m°±[0m[16C[1;30m°±° [0m");
|
||||
put_it("[49C[1;30m°[0m[17C[1;30m°[0m");
|
||||
break;
|
||||
case 8:
|
||||
put_it("[0;25;37;40m");
|
||||
put_it(empty_string);
|
||||
put_it("[63C[1;30m [0m");
|
||||
put_it("[20C[1;32mÝÜ[0m[38C[1;32mÜÝ[0m [1;30m [0m");
|
||||
put_it("[17C[1;32mÜÜ[42m²²²[40mÛ[0m[34C[32mÜ[1;42m°[40mß[42m±²²[40mÜÜ[0m [1;30m [0m");
|
||||
put_it("[14C[32mÜ[30;42m [1;32m°°°±±²²[40mÝ[0m[31C[1;30mÜÜÜÜÜ[0;30;42mÜ[1;32m°±²²Û[40mÜ[0m [1;30m [0m");
|
||||
put_it("[11C[1;30mÜÜ[0;32;40mßÛÛ[30;42m [1;32m° °°±[40mßÝ[0;32;40mÜ[0m[28C[1;30;47mÝ[37m°[30m ßß[40mÝ[0;30;42m [1;32m°±±²[40mÜ[0m [1;30m [0m");
|
||||
put_it("[7C[1;30mÜ[47mßßß °ßß[40mÜ[0;32;40mß[30;42m [1;32m°[0;30;42m ÜÜ[1;40mÜÜÜ[0m[5C[1;30mÜ[47mßßßß[40mÞ[0m[7C[1;30mÜÜÜÜÜ[0m [32mÜ[30;42m [1;40mÞ[37;47m° [30m °Þ[40mß[0;30;42mÝ[1;32m°°°±±[0;32;40mßß[0m [1;30m [0m");
|
||||
put_it("[9C[1;30mÛ[47m ÜÜ[40mÝ[0m [32mß[30;42m Þ[1;40mÜ[0m [1;30;47mßß °Ü[40mß[0m [32mß[0m [1;30mÞ[37;47m°[30m Þ[40mß[0m[5C[1;30mÜ[47mßß[37m°[30m °°ß[40mÝ[0;30;42m [0m [1;30;47mÝ[37m°[30m °Þ[0;30;42mÝ [1;32m°[30;40mfictionÞ[0m");
|
||||
put_it("[8C[1;30mÛ[37;47m° [30mÞ[0m [1;30mÜ[0m [1;30mÜÜÜ[0m [32mß[0m [1;30;47mÝ[37m°[30m [40mÝÜ[47mßßß[37m°[30m °Þ[40mÜ[47mßßßßßÜ[37m°[30m °Ü[40mþ[47mÜ[40mß[0;30;42mÝÞ[1;47mÝ[37m°[30m °±[40mÝ[0;32;40mß[1;30mÜÜ[47mßßßß[40mÜÜÝ[0m [1;30m [0m");
|
||||
put_it("[7C[1;30mÞ[37;47m° °[30m [40mÝÜ[47mß Ü ßß[40mÜÞ[37;47m°°[30m °Þ[0m [1;30mß[0m [1;30;47mÜ[37m°°[30m °°ÜÜ[40mßÜ[37;47m°[30m [37m°[30m °°[40mÝ[0;30;42m [32;40mÜ[30;42m [32;40mßß[1;30mÞ[37;47m°[30m °[40mÜ[47mß °°±Þ[0m [1;30m [0m");
|
||||
put_it("[7C[1;30mÞ[37;47m°° [30mÞÝß [40mß[0m [1;30mß[47mܰ°[40mÝß[37;47m°[30m °±[40mÛ[0m [1;30;47mÝ[37m° [30m °[40mÝß[0m [32mÜ[1;30mÞ[37;47m±°°[30m °Þ[0m [32mß[1;30mÜÜÜÜ[47mß[37m±°[30m °°±[40mÝ[0m [1;30m [0m");
|
||||
put_it("[7C[1;30mÛ[37;47m²±° [30m ß[40mÜ[47mß °Þ[0m [1;30mÞ[37;47m°[30m °Þ[40mÝ[47mÝ[37m° [30m °Þ[0m [32mÛþÝ[1;30mÜÞ[37;47m±°[30m °°[40mÝßÛ[47m °°Û[40mÝ[37;47m°°[30m °Þ[40mß[47mÜ[37m°[30m °Þ[0m [1;30m [0m");
|
||||
put_it(" [1;30mÜÛÜÞ[37;47m±°° [30m °°±[40mÝ[0m [1;47m°[30m °°[40mÛÞ[37;47m°°[30m °°[40mÛ[0m [1;30mÜ[47mß±[40mÛ[47mÝ[37m°°[30m °Þ[40mÜÞ[47m °±ÞÝ[37m°[30m °°[40mÝÞ[37;47m°[30m °°[40mÝ[0m [1;30m [0m");
|
||||
put_it(" [1;30;47mÝ[37m°[30mß[37m°°[30m [37m° [30m [37m [30m ° °°Ü[40mß[0m [1;30mÛ[37;47m±°[30m °Þ[0;32;40mÞ[1;30mÞ[37;47m²±°[30m °°°ÜÜ[40mßÞ[37;47m°[30m ° ß °°[40mÛ[0m [1;30mÜ[37;47m°°[30m °Ü[40mßÞ[47mÜ °Þ[0m [1;30m [0m");
|
||||
put_it(" [1;30mßßß[47mÜÜ[37m°[30m [37m°[30m ÜÜÜ[40mßß[0;30;42mß[0m [1;30mß[37;47m°°[30m °[40mß[0;32;40mÝ[1;30mßß[47mÜÜÜÜ[40mßßß[0m [1;30mß[47mÜÜ °°ÜÜÜ[40mßß[42m°[40mß[0m [1;30mÜßßß[0;32;40mÜ[0m [1;30mÜ[47mÝ °°°Ü[40mß[0m [1;30m [0m");
|
||||
put_it("[9C[1;30mßßßßß[0m [30;42mßß[1m°[0;30;42m Þ[1;40mÝßß[47mÜÜÜ[40mßßÝ[0;32;40mÛß[0m[7C[1;30m [0m [1;30mßßßß[0;30;42mßßß[1m°[0;30;42m [1m°°°[0;30;42mß[1m°°[0;30;42m [1m°[0;30;42m [0m [1;30mßßßß[0m [1;30m [0m");
|
||||
put_it("[14C[32mßß[1;30;42m°°°°[0;30;42mß[1m°°[0;30;42mßßß[1m°°[0;32;40mÛÝ[1;30m [0m [1;30m[7C[0m[6C[32mßß[30;42m [1m°[0;30;42m [1m°°±°°°[0;30;42m [1m°[0;30;42mÜ[0m [1;30m [0m [1;30m [0m");
|
||||
put_it("[18C[32mßß[1;30;42m±[0;30;42mÜ[1m±°°°[0;30;42m [32;40mß[0m[9C[1;30m[6C[0m[9C[32mßß[1;30;42m±²±°[0;32;40mßß[0m [1;30m[5C[0m");
|
||||
put_it("[24C[32mßÝ[0m[28C[32mÞ[0m [32mß[0m [1;30m[5C[0m");
|
||||
put_it("[57C[1;30m [0m");
|
||||
break;
|
||||
case 9:
|
||||
put_it("[0m [34mþ[30;46m²[36;40m°[37m [30;44m²[34;40m° ÜÜÜ [37m [34mÜÛÛ[1;44m Ü[0;34mÜ[37m[8C[34mÜÜÜÜÜ[1;44m [0;34mÛ[1;44m°[0;34mÛÛÛÛÛÛ[1;44m°°°[0;34mÜÜ[37m [1;36m°[46m°[40m²[46m²[40mÛ[46mÛÜ[0;36mÜ [37m");
|
||||
put_it(" [34mÜ[36;44m°°[34;40mܲ[30;44m°[34;40mÛÛ[1;44m°ß[0;34mÛÛÛßÛÛÛ[1;44m [0;34mßÞ ÜÜÛÛÛÛÛÛ[1;44m°°°°[0;34mÛÛÛÛ[1;44m°°°[40m²[44m²²²ÛÝ[0;34mÝ[1;36m±[0;34;46m°[1;36m °²[47mÛ[46mÛÛÝ[0m");
|
||||
put_it(" [34mßß[37m [34mßÝßÛÛÛßÛÛÛÛ[1;44m°°[0;34mÛÛÛÜ[1;44m°[0;34mÛ ßßÛ[1;44m°°[40m²[44m²² °°°²²²²ÛÛß[0;34mßÜ[46m²°°°[1;36m °²²[40m²[46mÛ[0;36mÝ[37m [1;30m[_v9(Vade79)ùFiRE][0m");
|
||||
put_it(" [1;30mß ßß [0;34mÝ[37m[4C[34mÜÛÛ[1;44m°°²²[0;34mÛÛÞ[1;44m° [0;34m [37m [34m° [1m [0;34mßßÞÛ[1;44m²²²ÛÛß[40mß[0;34mß[37m [1;34;44m°°[0;34;46mÛÛ²[36;44m°[34;46m±°°[1;36m°°[40m±[0;36mß[37m [1;30m ßßß ßßßßßßßßßßßß ß[0m");
|
||||
put_it(" Ü[1;47mÜ[40m²[30;47mß[0m± [34mÜÛ[1;44mÜ[0;34mÜ ÜÛ[1;44m²²[47mÛ[44mÛ[0;34mÛÝÞ[1;44m [0;34m [37m [34mÞ [1;30m°²[0m±[1;30;47mß²[0m° [34mÞß[1;44m°[0;34mß[1;44mÛ[40mÛÜÜ[0;34mÜ[37m [34mÞ[1;44mÛ²°°[0;34;46mÛ[36;44m°°[34;46m²²Ü[40mß[1;30m ßß ßßÛßÛ[47mÛßÛÛßÛßß[37m °²[40mÜ[0m");
|
||||
put_it(" [1;30;47mܰÜ[40mÝß[0m [34mß[1m±[0;34mÛß ßÜ[1;44m°Û[47mÜ[44mÜ[0;34mÜ ÞÝ Þ [37m [1;30m ßßßßß[0m [34mÞßÛß [1;47mÛ²Ü[44mÛ[0;34mÛ[37m [34mß[1;44mß²²°[0;34mßßß[37m[3C[1;30mßßßßßßßßßßßßßßßßßßß[47mÛÜ[37m°[40m²[0m");
|
||||
put_it(" [1;30;47mÛ²[40mÛ[0m [35m [1;30mÜ[0;35m [1;30mÜ[0;35mÜÜ [34mß[1mßß[0;34mß Þ [37m [1m [0m [1;30mÜÜÜ[0;35mÜÜÜÜ [37m [1;34m ßß[0;34mß [37m [34mÞß[37m [35m [1;30mÜÜ[0;35mÜ[1;30mÜ[0;35mÜÜÜÜÜÜÜÜÜÜÜÜÜÜ[1;30mÜ ÜÜÜ[0;35m [1;30m Û[47m°[37;40m°[0m");
|
||||
put_it(" [1;30mÛßÛ[0m [1;30m°Û[45m²[0;35mÛÛ[1;30;45m°[0;35mßßßÛÛÛ[1;30;45m°°[0;35mÜ [37m°[1;30;45m²[40mßßß[45m²²°[0;35mßßßßßßß[1;30mß[0;36m [35mß[1;30mß[0;35m [30;45m²[35;40m Ü[36m [1;30mß[0;35mßßßßßßßÛÛÛßßßÛ[1;30;45m°°[0;35mßßßÛÛÛ[1;30;45mß²[40m°[0m [1;30mÛ[47m²Û[0m");
|
||||
put_it(" [1;30mÛÜÛ[0m [1;30m°[45m²°[0;35mÛ[1;45m°[0;35mÛ[1;30m°[31;41mÜ[0;36m [35mÛÛ[1;45m°[0;35mÛÛ[1;45m°[0;35mÞÛ[1;30;45m°[0;35mÜÜÜ[1;30;45m°°[0;35mÛ [31m°[35m Û[1;45m [0;35mÛ [1;31m²[0;36m [35mÛÛÛ ²[30;45m°[35;40mÛ[1;30m°[31;41mÜ[0m [35mÛÛÛÜÜÜ[1;45m°[0;35mÛÛ[36m [1;31;41mÜ[0;36m [1;35;45m°[0;35mÛÛ[36m [1;31;41mÜ[0;35m ÛÛ[1;45m [30m °[40m°[0m [1;30mÛÛÛ[0m");
|
||||
put_it(" [1;30mÛ[0m°[1;30mÛ[0m [1;30m°[45m°[0;35mÛ[1m±[45m²°[30;40m°[31;47m²[0;36m [1;35;45m°°²°°²[0;35mÛ[1;45m °[0;35mßßßÛÛ[1;45m°[0;35mÜÜÜÛ[1;45m° [0;35m [1;31m±[0;36m [1;35;45m°°[0;35mÛÜÜÜ[1;45m°[0;35mÛÛ[1;30m°[31;41m²[0;36m [35mÛ[1;45m°°[0;35mßßß[1;45m²°°[0;36m [1;31;41m²[0;36m [1;35;45m²°°[30;40m°[31;41m²[0;35m ÛÛ[1;45m°°[0;35mÛ[37m [1;30mÛÜÛ[0m");
|
||||
put_it(" [1;30mÛ[0m°[1;30mÛ[0m [1;30m°[0;35mÛ[1;45m°[40m²[45mÛ²[0;31m [1;41m²[0;31m [1;35m²[45m²Û²²Û°°²[0;35m [1;31;41mÜ[0;35m [1;45m°°²°[0;35mÛ[1;45m°°²Ý[0;35m [31m²[36m [1;35;45m²²[40m±[45m°° ²°°[0;36m [1;31;41m°[0;36m [1;35;45m°²²[0;36m [1;31m²[0;36m [1;35;45mÛ²²[0;36m [1;31;41m°[0;36m [1;35;45mÛ²²[30;40m°[31;41m°[0;35m Û[1;45m°²²°[30;40m°[0m [1;30mÛßÛ[0m");
|
||||
put_it(" [1;30mÛÜÛ[0m [1;30m°[0;35mÛ[1;45m²ÛÛÛ[0;31m [1;41m°[0;31m [35mÜ[1mÜÜ[0;35m [31mÜ[35m [1m²[45m²Û[0;35m [1;31m²[0;35m [1;45m²²Û²[40m²[45m²²ÛÝ[0;35m [31m°[36m [1;35;47mÛ[45mÛ[40m²[45m²²[0;35mÞ[1;45mß²²[30;40m°[0;31m²[36m [1;35;45m²Û[40m²[0;36m [31m²[36m [1;35;47m²[45mÛß[0;36m [31m²[36m [35mÜ[1mÜÜ[30m°[0;31m²[35m [1;45mÞ²ÛÛ°[0m [1;30mÛßÛ[0m");
|
||||
put_it(" [1;30mÛ Û[0m [35mÛ[1;45mÛÛ[47m²²[0;31m Û [1;35;45m°Û[40mÜ[0;35m [31m²[36m [1;35;45m²Û[47m²[0;36m [1;31m°[0;36m [1;35;45mß[40mßßß ß[0;35mß[37m[4C[36m [1;35;47m²[45mß[40mßß[0;35mß[37m[3C[35mß[36m [31m°[36m [1;35;45mÛß[0;35mß[36m [1;35mß[0;35mß [36m [35mß[1;45mÛ[40m²[0;36m [31m°[36m [1;35;45mÞ[47mß²²[45m°[0m [1;30mÛÜÛ[0m");
|
||||
put_it(" [1;30mÛßÛ[0m [1;30m°[0;35mÛ[1;45mÛ[47mÛ°°[0;31m [30;41m°[31;40m [1;35;45m²Û[47m²[0;35m [31m°[36m [1;35;45mÛß[0;35mß[36m [37m [36mÜ[1mÜÜ[46mÜÜ[37;47mÜÜÛ[40mÛ[47mÛÛÝ[0m [34mÜÜÜÛÛÛßßß [37m [34mÜÜÜÜ[37;44m°[34;40mÛÛÜÜÛÛ[37;44m°[34;47m²[40mÝÜÜÜÜ[37m [35mß[1mßßß[45m [0m [1;30mÛ Û[0m");
|
||||
put_it(" [1;30mÛ[47mß[40mÛ[0m [1;30m°[45m°[35m²[47mÝÜÜ[0;31m ° [1;35mßßß[0;35m [32m [36m [35mÝ [36mÜ[1m²[46m²²Û[47m²²ÛÛ[40mß[46mÜ[0;36mß [37m [34mÜÜÜ[46mÜ[36;44m°[34;40mÜÜ[46mÛ[1;44m°°[0;34mÛÛÛÛßÛÛÛÛ[1;44m°°°°°°[0;34mÛÛÛÛÛÛßÛ[37;44m°[34;40m²[37m [30;45m°[37;40m [1;30m²[0m [1;30mÛ[0m");
|
||||
put_it(" [1;30;47mÛß[40mÛ[0m [1;30;45m²[35m°ßß[40mÛÜÜÜ[45mܲ° [30m²[40mÝ[0;36m ²[34;46m°[1;36m°°°[0;34;46mÜ[40mß [36mÜ[1;46mÛ²²[40m²[0;34;46mß[36;40mÜÜÜ[34mÜÜ[46mÛÛÛ[1;44m ²²°°[0;34mÛß[1;44m°°°°[40m²[44m²²²²²² °°[0;34mÛÛÛÛßß°[37m [35m°[37m [1;30m± Û[0m");
|
||||
put_it(" [1;30;47mÛ[37m°[30;40mÛ°[0m [35m [1;30mß[0;35mß[1mßßßßßß[0;35mßßß[1;30mß[0;35m [34mÞ[46m±[36;44m²²[34;46m°Þ[40m [46m°[1;36m°²²[0;36mßß[1;46m°±°[0;34;46m° ÜÜÛ[1;44mÜÞÛÛ²²[0;34mÝÞ[1;44m²²²²ÛÛÛÛ[0;34mÝßßÞ[1;44m²²[0;34mß[37m [34mÜܰ[37m [1;30m°[0m [1;30m° ²[0m");
|
||||
put_it(" [1;30;47mÛ[37m²[30mß[40m²ÜÜÜÜÜÜÜÜÜÜÜÜÜ [0;34m Û[46m²[36;44m°[34;46m²±[40mÝ Þ[36;44m°²[1;46m°°°[0;34;46m °°°²[40mÝß[1;44m°[40m²[44mÛ[47mܲ²[44mß[0;34mß[31m [34mÜ[1;44m°[0;34mßß[37m [1;34;44mÞ[40mÜ[47m²²[44mÜ[0;34mÜÞ[1;44mÛß[0;34m²°[37m [34mß[1;30m ÜÜ[0m[3C[1;30m °[0m");
|
||||
put_it(" ß[1;47mß°[30mÜÜÜÛÜÛ[40mÜ[47m²Û[40mÜÜÛÜÜÜ[0;34m ÞÛ[1;44m [0;34;46m²Û[40m [46mÛ²±[36;44m²[34;46m°°²[40mÜÜ[1;30m [0;31mþ [37m [1;34mßß[0;34mß[37m [36m [31mܰ [34mÜ[1;44m Ü[0;34mÜÝ[1mß[47mÜ[44mÛß[0;34mßÞ[1;30m ÜÜÜÜÛÜܲ° [0m");
|
||||
put_it(" [1;30mÜ ÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜ Ü [0;34mßÞÛ[1;44m°°[0;34mÛÜ Û[36;44m°[34;46m²²²[40mÛÛÛÛÜ [31mßßÛÜÜ[1;41m°[0;31mßÝ[37m [34mßÛÛÛßÝ[1;30m [0m [1;30mÜÜ[0m [34mÞ[37m[3C [34mÜÜ[37m");
|
||||
put_it("[21C[34m ÞßßÛÛÛÛÛÜ[1;44m°Ü[0;34mÛÞ[30;44m°[34;40m²²²Ý [37m [31m Ü[1;41mß[0;31mßÛ[47m²[40mÜ[37m[6C[34m°[37m [1;30m [0m [34mÞ[37m[3C[34mßÛ[1;44mß[0;34mß[37m [34mÛß[37m");
|
||||
put_it(" [1;30m..B[0m i [1mt[0m [1mc[0m h [1;30mX..[0m [34m°[37m[3C[34m [37m [34mßßßßßß [30;44m²²[34;40m°° [31m Ü [37m [31mßß Ü[37m[6C[30;41m²[31;40m°[37m [34m ß[37m[8C[34m°[37m");
|
||||
break;
|
||||
case 10:
|
||||
|
||||
put_it("[1;25;33;43m²±°[0;33;40mßß ß[0m[27C[36m Ü [0m[7C[36m ÜÜ ß [0m[7C[1;30m ß [0m");
|
||||
put_it("[1;33;43m±[0;33;40m ß[34m [0m [33m [0m[10C[34m Ü ß ß Ü[0m [36m Þ[1;46mÜ[0;36;40mÜ [0m[5C[36m ²Ü[1;46mÜÛ[0;36;40mÝ[6C[0m[7C[1;30m Û[8CÜ[0m");
|
||||
put_it("[33mÝ[5Cß[0m[10C[34m [1;44m°[0m[11C[1;34;44m± [0m [36mÞÝ[0m [36mÛ[1;46mÛÜÜ[0;36;40mÜÜÜÛ[1;46mÜÜÛÛ[0;36;40mÝ ÜÜ ßß[0m[8C[1;30m Þ[47m²[40mÜÜ Ü[0m²[1;30mÝ[0m");
|
||||
put_it("[15C[34m ÞÝ[0m[11C[34mÞÝ[0m [36mß Þ[1;46mÞÛ²ß[0;36;40mÛ[1;46mß[0;36;40m²[1;46mß²²ß[0;36;40mÜ[0m[15C[1;30m Û[47m ß²ßßÛ [40mÜ[0m");
|
||||
put_it(" [34mÞ[1;44mܱ[0;34;40mÝ [0m[8C[34m [1;44m°[0;34;40mÜÜ[0m[7C[34mÜÜÛ[0m[6C[36m [1;46m²Û[0;36;40mßß ßß [34mÜÜ[1;44m [0;34;40m²[1;44m°[0;34;40mÛÛÛÜÜ[0m [1;30m ²[47m²Ýß ° Þ²[40m²ß[0m");
|
||||
put_it("[34m [1;44mÞ²[0;34;40mÛßßß²ßßÛÛÜÜÜÜ ßßÛ²[1;44m [0;34;40mÜÛ[1;44m° [0;34;40mß[0m[5C[36m Ü[1;46mÛ²[0;36;40mÝ[0m [35mÜ[1;45mÜÜ[0;35;40mÜ[34m Ü[1;44m°°°[0;34;40mß[0m[5C[34mß[1;44mßÛÜ[0;34;40mÜ[0m [1;30m ßßß[47m² Ü ° Þ[0m");
|
||||
put_it("[34m [0m [34mÛ[1;44mÛÝ[0m[10C[34mß[1;44m Ü[0;34;40mÛÜ [1;44m°°±[0;34;40m Þ[1;44m°° [0;34;40m [36m ßßßß[0m [35mÞÛÛ[1;45mÞÛ[0;35;40mÝ[1;34;44m ²Ý[0m[9C[34mÞ[1;44mÛ²[0;34;40mÝ[1;44m ±°[0m [1;30m ßßß[47mÝ[0m²[1;30;47m [40mÝ[0m");
|
||||
put_it("[34m [0m [34mÞ[1;44mßß[0;34;40mÝ [32m [34m [0m [34m [0m [34mÞ[1;44mÞÛÜ[0;34;40mÝ [1;44mÞ²Ý[0;34;40m Þ[1;44m±°±[0;34;40mßß[1;44m°[0;34;40mßßßß²[35m Û[1;45m°[0;35;40mÛÛ[1;45m²Ý[0;35;40m [1;34;44mÞ[0;34;40mÝ [0m[8C[34m [1;44m°±°[0;34;40mÜÜÜÜÜ²Ü [1;30mßß[0m");
|
||||
put_it("[34m [32mÜÜÜÜ [34m [32m [0m [34m [0m [34mÛ[1;44mÛÛ[0;34;40mÛ Þ[1;44mÞÛ[0;34;40mÝ [1;44m²²Ý[0;34;40mÝ[0m[7C[35m ÞÛ[1;45m°ÞÛ[0;35;40mÝ[34mÞ[1;44mÛ[0m[14C[34mÞ[1;44m²Û[0;34;40mÝ ßßß[1;44m°±[0;34;40mÜ [0m");
|
||||
put_it("[34m [32mÜÛ[1;42m° ßßÛÜÜ[0;32;40mÜ [34m Þ[1;44mÞÛÝ[0;34;40mÝÞ[1;44mÛÝ[0;34;40mÝ [1;44m ÛÛ[0;34;40mÝ[0m[7C[35m ß[1;45mßß[0;35;40mß [1;34;44mÞÛ[0;34;40mÝ[0m[9C[34mÞ[1;44mܲ[0;34;40mÝÞ[1;44mÛÛ[0;34;40mÝ[0m[7C[34mÞ[1;44m²±[0;34;40mÝ [0m");
|
||||
put_it("[32mÞÛ[1;42m°[0;32;40mÛÛ[1;42m [0;32;40mÛ[1;42mÞ²ÛÝ[0;32;40mÝ [34m Û[1;44mÛ[47mÛ[44mÜ ÜÛ[0;34;40mÛ Þ[1;44mÞÛ [0m [34m Þ[1;44mÜܰ[0;34;40mÜÜÜÜÛ[1;44mÛ²Ý[0;34;40m [1;35m [0;35;40m [34m Þ[1;44mÛÛ[0;34;40mÝ [1;44mÞÛÝ[0m[7C[34mÞ[1;44mÛ²[0;34;40mÝ [0m");
|
||||
put_it("[34m [32mßÛÛ[1;42mÜ ÜÛßß[0;32;40mß [0m [34mÞ[1;44mÞ[47mÛ²ÛßÛÛ[0;34;40mÛ [1;35m [0;34;40mÞ[1;44mÞÛÝ[0;34;40mÝ [0m [34mÞ[1;44mÞ[47m²ß[44mÛ²ßßßßÛÛÜ[0;34;40mÜ [35m [0m [34m [0m [31m ÜÜÜÜÜÜÜÜÜ [0m [34m [1;44mÞÛÝ[0m");
|
||||
put_it("[34m [32m ßßßß [34m [0m [1;35m [0;34;40mÜ[1;44mÜÛ²[47mÛß°Þ[44mÝ[0;34;40mÝ[0m [34m [1;44m°ÛÝ[0;34;40mÝ Ü[1mÜ[44mÜÛ[47mÝÜ[44mÝ[0;34;40mÝ [1;35m [34;44m [0;34;40mßß[1;44mßßÛ[47m²°[0mÜ[31m ÜÛß Þ[1;41mß[0;31;40mÝ [1m [0;31;40m ß[1;41mÜ[0;31;40mÜ[0m [34m [1;44mÞÛÝ[0;34;40m [0m");
|
||||
put_it("[34m Û[1;44m²ß[0;34;40mÛÜܲÜÛÛßßß[1;44mßßÛ[47mÜ ²[44mÝ[0;34;40mÝ[0m [34mß[0m [1;34;44m ßß[0;34;40mÝßßßßß[1;44m ßßß[0;34;40mÛ [1;35m [0;34;40m [35m [34m ß[1;44mÞ[47m²[0;34;40mÝ[31mÞ[1;41m°[0;31;40mÛÛÜÜÜ ß ÜÜÜ[1;41m°²Û[0;31;40mÝ [0m [34mÞ[1;47m²Û[0;34;40mÝ[0m");
|
||||
put_it("[34m ßßß[0m[8C[1;35m [0;34;40m ßß[1;44mßÛ[0;34;40mÝ [0m[5C[34m [0m[17C[1;35m [0m [1;35m [0;34;40mÞ[1;44mÝ[0;34;40m [31mÛÛßß [1m [0;31;40m ÜÜÜ [1m [0;31;40m [1mßßÛ[41mÝ[0;31;40m [0m [34mÞ[1;44mß²[0;34;40mÝ [0m");
|
||||
put_it("[34m [0m[15C[35m [34m ÞÝ [1;30mdark horizon(dh!toolshed) [34;44mÝ[0;34;40m [31mÞÝ [1m [0;31;40mÞÛ[1;41m°[0;31;40mÛÝ[1m [0;31;40m [1mÞ[0;31;40mÝ [0m");
|
||||
put_it("[16C[35m [34m ß [0m[23C[1;35m [0;34;40mÞ[1;44m²[0;34;40mÝ[1;31m [0;31;40mßÜÜ[1m [0;31;40m [1;41m ÜÜ[0;31;40m [1m [0;31;40m ÜÜß [0m");
|
||||
put_it("[44m[[35;40m%s by panasync[37;44m][0m[23C[34m ß[1;35m [0;31;40m ßßßßßßßßß[1m [0;31;40m [0m", irc_version);
|
||||
break;
|
||||
case 11:
|
||||
put_it("[7C[0;1;31m°°° [37mÛ[33;41m²[37;40mÛ [33;41m²²[2C[37;40mÛ[33;41m²²²[37;40mÛ[33;41m²²[37;40mÛ[33;41m²²[37;40mÛ[33;41m²²²[37;40mÛ [31m°°° [37mÛÛÛ[11CÛÛÛÛÛ[5C[31mú");
|
||||
put_it("[7C° ° [1;33;41m²±²[1C²±±²[3C²±²±±²±±²±±±²[1C[31;40m° ° [37mÛÛÛÛÛ[7CÛÛÛÛÛÛÛ[5C[34mb");
|
||||
put_it("[7C[1;31m° ° [33;41m±±±[1C±±±±[1C[31;40m° [33;41m±±±±±±±±±±±±[1C[31;40m° ° [37mÛÛÛÛ[33;41m²²[5C[37;40mÛ[33;41m²²²[37;40mÛÛÛÛ[5C[34my");
|
||||
put_it("[7C[1;31m° ° [33;41m°±°[1C±°°±[1C[31;40m°° [33;41m°±±°±±°±±°°[1C[31;40m° ° [37mÛÛ[33;41m²²²²²[4C²²²²²[37;40mÛÛÛ[5C[31mú");
|
||||
put_it("[7C° ° [1;33;41m°°°[2C°°[2C[31;40m° ° [33;41m°°°°°°°°°°°[1C[31;40m° ° [37mÛ[33;41m²²±²²[3C²°²²²[37;40mÛÛ[6C[34mp");
|
||||
put_it("[7C[1;31m° °[10C° °[13C° °[5C[33;41m²²°°²[1C²°²°²²[37;40mÛ[7C[34ma");
|
||||
put_it("[7C[1;31m° °°°° °°°° ° °°°°° °°°° ° °°°° [33;41m²°°°°°²²²[9C[34;40mn");
|
||||
put_it("[6C[1;31m°ÛÛÛÛÛÛ° °ÛÛ° °Û°[6C°ÛÛÛÛ° °ÛÛÛÛÛ°[5C[33;41m²°°²[12C[34;40ma");
|
||||
put_it("[7C[1;31m°Û°°°ÛÛ° °Û° °ÛÛ°°°° °ÛÛ°°° °Û°°°ÛÛ° [37mÛ[33;41m°°°°[1C°°°[10C[34;40ms");
|
||||
put_it("[6C[1;31m°ÛÛÛÛÛÛÛ° °Û° °ÛÛÛÛ° °ÛÛÛÛÛ° °Û° °Û° [37mÛÛ[33;41m°°[1C°°[1C°°°[8C[34;40my");
|
||||
put_it("[7C[1;31m°°°°°°° °°°° °°°° °°°°° °°° °°° [37mÛÛÛÛ [33;41m°[4C°°°[5C[34;40mn");
|
||||
put_it("[51C[1;33;41m°°[6C°°°[2C[34;40mc");
|
||||
put_it("[6C[1;33;41mÛÛ[2CÛÛ[1CÛÛ[1CÛÛ²[1C²²[1C²²[1C±[1C²²[1C±[1C±±[1C±±[1C°[1C°°[1C°[1C°°°[1C°°°°°°°°°°°°°[1C[31;40mú");
|
||||
put_it("[7C[1;34mf e e l i n [31m' [34mf i n e [31mú [34ma s c i i [31mú [34mb y [31mú [34ms o r t o f [31mú [33;41m°[40m");
|
||||
put_it(empty_string);
|
||||
break;
|
||||
case 12:
|
||||
put_it("[55CÜÜÜ[1;47mÜÜÛÛÛÜ[0mÜÜ");
|
||||
put_it("[11CÜÜÜÜ[1;47mÜÛÛÛÛÛÛ[0mÜÜÜÜÜÜ[1mÜ[0mÜÜÜ[8CÜÜÜ[1;47mÜÛÛÛÛ[0mÜ[8Cß[1;47mßÛÛÛÛÜ[0mÜ");
|
||||
put_it("[5C[35m°[30;45m²[37;40m[6CÞÛ[1;47mÞÛÛÛÛÛÛ[0mÝ[5Cßß[1;47mßÛÛÛÜ[0mÜ[6CÞ[1;47mÞÛÛÛÛ[0mÝ[33m [37mÞ[1;47mÞÛÛÛÛÛ[0mÝ[5C[35m°[30;45m²[37;40m [33mzalt[37m");
|
||||
put_it("[35mÜÜ ÜÜÜ[1mÜÜÜ[0;35mÝ[37m[3CÛÛ[1;47mÛÛÛÛÛÛ[0mÝ [35mÜÜÜ[37m Þ[1;47mÞÛÛÛÛ[0mÝ [35mÜÜÜ [37m ß[1;47mßÛÛÛÜ[0mÜ[3C[35mÜ[37m[3CÜ[1;47mÜÛÛÛÛß[0mß[3C[35m ÜÜÜÜ[1mÜÜÜ[37mÜÜÜ[0m");
|
||||
put_it("[1;35;45m [0;35mÛÝÞ[1;45m °ÛÛ[37;40mÛÛ[0;35mÝ[37m[3CÛ[1;47m ÛÛÛÛÛÛÝ[0m ÜÜÜÜÜ[1;47mÜÛÛÛß[0mß[3C[35mßß[1;45mß[0;35mÝ[37m ßß[1;47mßÛÛܰ[0mÜÜÜ[1;47mÜÜÛß[0mßßß[3C[35m ÜÛÛ[1;45mß[0;35mÛ[1;45mÛÛÛ[37;40mÛÛÛ[0;35mÝ[37m");
|
||||
put_it("[35mÛÛÛÞÛÛ[1;45mßÛÛÛÝ[0m[3CÞ[1;47m°±²²²²²Ý[0m[4C [1;30mß[0mßß[1;30;47mÜ[37mßßÛÛÛÛÜ[0mÜÜ Ü[1;47mÜÜÜÛß[0mÛÛ[1;30;47mÜ[0mßßß[1;30;47mÜ[0mÛ[1;47mßÛÛÛÛÜ[40mÜÜ[0mÜ[3C[35m ßßÛ[1;45mßÛÛß[0;35mß [37m");
|
||||
put_it("[30;45m°[35;40m²² ÛÛÛ[1;45mÛÛÛÝ[0m[3CÞÛ[1;47m°±±±±±±[0mÝ [35mÜÜ[1mÜ[0;35m [37m[3C[1;30mß[0mß[1;47mßÛÛÛÛÛÜÜÛÛÛß[0mßß[1;30mß[0m [35m [37m [1;30mß[0mßß[1;47m ßÛÛÛÛÛÜ[0mÜ [35m Þ[30;45m°[35;40m²ß [1;37mÜ[0m");
|
||||
put_it("[35mÛÛÝ ÛÛ[1;45mÜÜ[0;35mÛÛÛÝ[37m[3CÛ[1;47m °°°°°°[0mÝ [35mÛ[1;45mÛÛ[37;40mÛ[35;45mÜ[0;35mÜ [37m ÞÛ[1;47mÞÛÛÛÛÛÛ²[0mÛÝ [35m ÜÜ[1;45mÜ[0;35mÝÛ[1;45mÜ[37;40mÛ[35mÜ[0;35m [37m ßÛ[1;47mßÛÛÛÛÛ[0mÝ [35m ß Û[1mÛ[0m");
|
||||
put_it("[35mÛÛ ÞÛ[1;45mßß[0;35mÛÛ[37m[4C[1;30mÜ[0mÛÛÛÛÛÛÛ[1;47m [0mÛ [35mÞÛ[1;45mßßß[0;35mÛÝ [37m Û[1;47m Û²²²²²°[0mÛ [35m Û[1;45mßÛÝ[0;35m ÛÛ[1;45mÛÝ[0;35mÝ [37m ÞÛ[1;47mÞÛÛÛÛÝ[0m [35m ÜÛÛÛ[37m");
|
||||
put_it("[35mÛÝ ÛÛÛ[1;45mß[0;35mÛ[37m[3CßßßßßÝ[30;47m°[37;40m²[30;47m°[37;40m²ßß [35mÛ[30;45m°[35;40m²ßß [37m ÞÛ[1;47m±±±±±°[0mÛÛ[1;30;47mÜ[0mÝ [35m Þ[30;45m°[35;40m²Ý ÞÛÛ[30;45m°[35;40m² [37m[3CÛÛ[1;47m²²²²²[0mÝ [35m ÞÛÛ[30;45m°[35;40m²[37m");
|
||||
put_it("[35mßÝ ßß[30;45m°[35;40m²ß °[30;45m²[37;40m °[30;47m²[37;40m°[30;47m²[37;40m [35m [37m[4C[1;30mÜ[0mÜ[1;30;47mß[0;46m²²[1;47m°°°[0mÛÛß[1;30mß[0m[4C[35m ßßß ßßß [37m ÜÜÛ[1;47m °°°°°[0mÝ[1;30mÜ[0m [35m ßßßß[37m");
|
||||
put_it("[8C[35m°[30;45m²[37;40m[5C[35m [37m[10C[1;30mÜ[36mÜÜ[30;46mß[33m [0;46m°±±²²[1;30;47mÜ[0mßß[1;30mßß[0m[21C[1;30mß[47mÜ[0mÛ[1;47m [0mÛÛ[4C[35m°[30;45m²[37;40m");
|
||||
put_it("[23C[1;30;46mÝ[0;36mÛ[1;32;46mÞ[33;40mÛ[37mÛÛ[33mÛ[32;46mÝ[0;36mßßßß[1;30mß[0m[10C[1;33mbITCHX[0m[14C[1;30mß[0;30;47m°[37;40m²[30;47m°[37;40m²[1;30mß[0m");
|
||||
put_it("[24C [1;30mß[0;36mß[1mß[30;46mÜ[32mß[33m [0;36mÛÜ[37m[16C[33mby panasync [37m[6C°[30;47m²[37;40m°[30;47m²[37;40m");
|
||||
put_it("[31C[36mßß[37m [36mÜÜ[37m[31C ");
|
||||
put_it("[34C[1;30mß[0;36mß[37m [1;30mÜ[0m");
|
||||
break;
|
||||
case 13:
|
||||
|
||||
put_it("[0m");
|
||||
put_it("[1m ÜÜÜÜÜ ÛÛ²² [0;34mÛÛ²²²[37m[4C[1;34mÛ²±[0;34m²[1m°±[0m");
|
||||
put_it("[1mÛÛ²²² Üß [0m [1m ßÛÛ²±° ÜÜÛßßÛ²Ü ÛÛ²± [0;34m²±²ÛÛ[37m[4C[1;34m²[0;34m±[1m±°[0m");
|
||||
put_it("[1m ÛÛ²²± Û[0m [1m [0m [1m²±[0m±[1m ÜÛ²[0m²[1m Þ²±° Û²±[0m±[1m [34m [0;34mÛÛ²²Ý[1;37m [34mÞ±[0;34m°[37m");
|
||||
put_it("[1m ²²±±[0m±[1m Û²±°[0mÜ[1m ÛÝ Þ±[0mÝ[1m Þ²°[0m²Ý[1m Þ²±° Û±°[0m²[1m [0;34m²±±²[1;37m [0;34m ÛÛ[37m");
|
||||
put_it("[1m ²±°[34m°[37m [0mÜ[1m²±[0m±°±[1m²² [34m±[0m²[1m [34m°[37m°[0m°²[1m ²±[0m²Ý[1m²°±[34m°[37m [0m°[34m²±²[1;37m [0;34m±±[37m°");
|
||||
put_it("[1m ±[0m±[1;30mÛÛÜÛß[37m [34m°[0m±²Ý[1mß²[0mÜ[1m [0mÜ[1;34m°[0m²Ý[1m [0mÞ[1;34m°[37m°[0m²Ý[1m ±°°[0m²[1m±[0m²±[1;34m±[37m [0mÜÛßßÛ±Ü[1m [0;34m²²±Ý[37m°[34m²[37m");
|
||||
put_it("[1m [0m±°[1;34m°°[37m [34m °[0m±°[1m ±°[0m°[1;34m°[0mÜÜÛ[1;34m±°[0m°[1m±±[0mßßß [1;34m²±°[0m°[1m °[0mÛÛ[1;34m°²[0mß[1m [34m°[0m²Û[1m [0m°±°[34m±Ý[37m");
|
||||
put_it("[1m [0m°[1;30mÛ[34m°[0mÝ[1m [34mÞ°[0m±[1;34m°[37m°[0m²±[1;34m°[37m [34m±²[0m±²ß[1m ÜÛ²±[0m°²[1;34m±°[37m °[0m±[1;34m±°[37m [34m°[0mÛ²Ý[1m [0;34m²[37m°[34m±[37m°");
|
||||
put_it("[1m [30mÛ[34m°²Ý [37m [34m±±±[0m±²[1;34m±°[37m [34m²²²±[0mÝ[1m Û²±[0m±²Û[1;34m²±[37m [0m²²±[1;34m°Û²±Ý[37m [34m±[0m±±[1m [0;34m²[37m°°±[34mÝ[37m");
|
||||
put_it("[1m [34m°±±[37m [34m±²±[0m°[1;34m²±°ÞÛ²Û²[37m [34m±²±±[0mÞÛ[1;34m±°Ý[37m [0m²°[1;34m°°Û²Û[37m [34m²±[0m²[1m [0m°°Ý°±");
|
||||
put_it("[1m [34m²±[0mÝ[1m [34mÞÛ²²²Û²±ÛÛÛÛ[37m [34mÛ²±²[37m [0m²[1;34m²²±[37m [0m±[1;34m±±[37m [34m±²Ý[37m [34mÞÛ²Ý[37m [0m±°±[1m [0m°°");
|
||||
put_it("[1m [34m²[0m°[1m [34mÜÛ²²[37m [34mÞ²²±Û²ÛÛ±ÜÜÜÛ²²ß[37m [34mÞÛ²²Ý[37m [34mÞ²±Ý ²±[37m [34m²±±[37m [0mÛ²±[1m [0m±[1m°[0m");
|
||||
put_it("[1m [34m°°±²ß[37m [34mÛ²Û[37m [34mßÛ²²[37m [34mÛÛ²[37m [34m²Ý[37m [34mÞÛ²Û[37m [0mÛ²²[1mÝ [0m±[1m±[0m");
|
||||
put_it("[1m [34m²±[37m [34mÛÛÛ[37m [30m..[0;35m.m[1mi[37md [34mßßÛÜÜÛÛß[37m [34mÛ[37m [34mÛÛÛ[37m [0mÛ±²[1m² [0mÞ[1m²Û[0m");
|
||||
put_it("[1m [34mÛ[37m [0mÛ²[1m±²[0m[7CÛ[1m±²Ý[0m");
|
||||
put_it("[1m [0mÜ[1m [0mÜÜÜÜÛ[1m°±²²ÛÛÛ[34m [0m ÜÜÛ²[1m²²ÛÛ[0m");
|
||||
|
||||
break;
|
||||
case 14:
|
||||
put_it("[8C[1;35m________[0m[9C[1;30m [35m________ [0m[8C[1;35m________[30m [0m [1;30m [0m[4C[1;35m________");
|
||||
put_it("[0m[8C[1;35m\\[0m[6C[1;35m//___________\\[0m[6C[1;35m/________\\\\[0m[6C[1;35m/_________\\_[0m[5C[1;35m//");
|
||||
put_it("[0m[6C[1;35m___[0;35m\\[37m [1;30m [0m [1;30m [0;35m___[37m [35m_________[1;30m [0m[4C[35m__[37m[5C[35m_______[37m[8C[1;30m [0;35m\\[37m[5C[35m/[37m[4C[35m/");
|
||||
put_it("[37m[8C[35m<<_____[1;30m [0m[4C[35m\\\\[1;30m [0m[4C[1;30m [0;35m/[37m[6C[35m> [37m[4C[35m\\[37m [1;30m [0m [35m/____\\[1;30m [0m [35m>>[37m[8C[35m\\[1;35m ___");
|
||||
put_it("[0m[6C[1;30m____[0m[4C[1;30m/______\\_____<<_____//___________>> /_______\\[0m [1;30m/_____>>sm");
|
||||
put_it("[0m[8C[1;30m<<___________[0m[7C[1;30m [0m bitchx by panasync[7C[1;30m /______\\\\[0m [1;30m____");
|
||||
put_it("[0m[20C[1;30m/------------------------------------------------\\\\");
|
||||
put_it("");
|
||||
put_it("");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
1540
source/banlist.c
Normal file
1540
source/banlist.c
Normal file
File diff suppressed because it is too large
Load Diff
1
source/bcompat.c
Symbolic link
1
source/bcompat.c
Symbolic link
@@ -0,0 +1 @@
|
||||
./compat.c
|
||||
1
source/bircsig.c
Symbolic link
1
source/bircsig.c
Symbolic link
@@ -0,0 +1 @@
|
||||
./ircsig.c
|
||||
1049
source/bot_link.c
Normal file
1049
source/bot_link.c
Normal file
File diff suppressed because it is too large
Load Diff
1955
source/cdcc.c
Normal file
1955
source/cdcc.c
Normal file
File diff suppressed because it is too large
Load Diff
493
source/cdns.c
Normal file
493
source/cdns.c
Normal file
@@ -0,0 +1,493 @@
|
||||
/************
|
||||
* cdns.c *
|
||||
************
|
||||
*
|
||||
* A threaded DNS lookup implementation.
|
||||
*
|
||||
* This was written exclusively to get around the fact that
|
||||
* gethostbyaddr()/gethostbyname() will BLOCK until the resolver either
|
||||
* gets an answer, or times out. So we create a thread, and allow
|
||||
* the calls to block as long as they want, as the main app's thread
|
||||
* will keep on chugging along regardless.
|
||||
*
|
||||
* BTW, even tho the file is .cc, it really is only C code, I just like
|
||||
* C++'s strict type checking.
|
||||
*
|
||||
* Written by Scott H Kilau
|
||||
*
|
||||
* Copyright(c) 1999
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
* $Id: cdns.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "cdns.h"
|
||||
#include "irc.h" /* To pick up our next #define checks */
|
||||
static char cvsrevision[] = "$Id: cdns.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(cdns_c)
|
||||
#include "commands.h"
|
||||
|
||||
#include "struct.h"
|
||||
#include "newio.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#if defined(THREAD) && defined(WANT_NSLOOKUP)
|
||||
|
||||
/* Our static functions */
|
||||
static void init_dns_mutexes(void);
|
||||
static void *start_dns_thread(void *);
|
||||
static void do_dns_lookup(DNS_QUEUE *);
|
||||
static void cleanup_dns(void);
|
||||
static void destroy_dns_queue(DNS_QUEUE **, DNS_QUEUE **);
|
||||
static void free_dns_entry(DNS_QUEUE *);
|
||||
static void kill_dns_thread(int);
|
||||
static DNS_QUEUE *build_dns_entry(char *, void (*)(DNS_QUEUE *), char *, void *);
|
||||
static DNS_QUEUE *dns_dequeue(DNS_QUEUE **, DNS_QUEUE **);
|
||||
static DNS_QUEUE *dns_enqueue(DNS_QUEUE **, DNS_QUEUE **, DNS_QUEUE *);
|
||||
static DNS_QUEUE *dns_enqueue_urgent(DNS_QUEUE **, DNS_QUEUE **, DNS_QUEUE *);
|
||||
|
||||
/* Our static globals */
|
||||
static pthread_t dns_thread = {0};
|
||||
static pthread_mutex_t pending_queue_mutex = {0};
|
||||
static pthread_mutex_t finished_queue_mutex = {0};
|
||||
static pthread_mutex_t quit_mutex = {0};
|
||||
static pthread_cond_t pending_queue_cond;
|
||||
static DNS_QUEUE *PendingQueueHead = NULL, *PendingQueueTail = NULL;
|
||||
static DNS_QUEUE *FinishedQueueHead = NULL, *FinishedQueueTail = NULL;
|
||||
static int cdns_write = -1;
|
||||
static int cdns_read = -1;
|
||||
|
||||
/*
|
||||
* start_dns : This should be called by the main app thread,
|
||||
* whenever it wants to start up the dns stuff
|
||||
*/
|
||||
void start_dns(void)
|
||||
{
|
||||
int fd_array[2];
|
||||
/* Init our queues. */
|
||||
Q_OPEN(&PendingQueueHead, &PendingQueueTail);
|
||||
Q_OPEN(&FinishedQueueHead, &FinishedQueueTail);
|
||||
/* Create our mutexes */
|
||||
init_dns_mutexes();
|
||||
/* init our pending queue condition, and set to default attributes (NULL) */
|
||||
pthread_cond_init(&pending_queue_cond, NULL);
|
||||
/* lock up the quit mutex */
|
||||
pthread_mutex_lock(&quit_mutex);
|
||||
/* create our pipe [0] = main to read from, [1] = cdns to write to */
|
||||
pipe(fd_array);
|
||||
cdns_read = fd_array[0];
|
||||
cdns_write = fd_array[1];
|
||||
new_open(cdns_read);
|
||||
new_open(cdns_write);
|
||||
/* create our dns thread */
|
||||
pthread_create(&dns_thread, NULL, start_dns_thread, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* stop_dns : This should be called by the main app thread,
|
||||
* whenever it wants to stop the dns stuff.
|
||||
*/
|
||||
void stop_dns(void)
|
||||
{
|
||||
void *ptr;
|
||||
if (!dns_thread)
|
||||
return;
|
||||
/* Unlock the quit mutex */
|
||||
pthread_mutex_unlock(&quit_mutex);
|
||||
/* lock up pending queue mutex */
|
||||
pthread_mutex_lock(&pending_queue_mutex);
|
||||
/* signal thread to wake up */
|
||||
pthread_cond_signal(&pending_queue_cond);
|
||||
/* Give lock back, so dns thread can react to signal */
|
||||
pthread_mutex_unlock(&pending_queue_mutex);
|
||||
/* Wait until the thread kills itself. */
|
||||
pthread_join(dns_thread, &ptr);
|
||||
cleanup_dns();
|
||||
}
|
||||
|
||||
/*
|
||||
* kill_dns : This should be called by the main app thread,
|
||||
* when it wants the dns thread to go away forever. This function
|
||||
* kills the thread uncleanly, and probably should only be used
|
||||
* when the main app is about to exit()
|
||||
*/
|
||||
void kill_dns(void)
|
||||
{
|
||||
sigset_t set, oldset;
|
||||
|
||||
/* Fill set with all known signals */
|
||||
sigfillset(&set);
|
||||
/* Remove the few signals that POSIX says we should */
|
||||
sigdelset(&set, SIGFPE);
|
||||
sigdelset(&set, SIGILL);
|
||||
sigdelset(&set, SIGSEGV);
|
||||
/* Tell our thread (main) to block against the above signals */
|
||||
sigprocmask(SIG_BLOCK, &set, &oldset);
|
||||
/* lock up pending queue mutex */
|
||||
pthread_mutex_lock(&pending_queue_mutex);
|
||||
/* signal thread to wake up */
|
||||
pthread_cond_signal(&pending_queue_cond);
|
||||
/* Kill the dns thread, using the SIGQUIT signal */
|
||||
pthread_kill(dns_thread, SIGQUIT);
|
||||
/* Put back the previous blocking signals */
|
||||
sigprocmask(SIG_BLOCK, &oldset, &set);
|
||||
/* cleanup anything dealing with the dns stuff */
|
||||
cleanup_dns();
|
||||
}
|
||||
|
||||
/*
|
||||
* add_to_dns_queue : This should be called by the main app thread,
|
||||
* whenever it wants us to resolve something... host <---> ip.
|
||||
*/
|
||||
void
|
||||
add_to_dns_queue(char *userhost, void (*callback)(DNS_QUEUE *), char *cmd, void *data, int urgency)
|
||||
{
|
||||
char *split = (char *) 0;
|
||||
DNS_QUEUE *tmp;
|
||||
|
||||
if (userhost && *userhost) {
|
||||
/* Look for user@host */
|
||||
split = index(userhost, '@');
|
||||
if (split)
|
||||
split++;
|
||||
else
|
||||
split = userhost;
|
||||
if (split && *split) {
|
||||
/* Build dns entry */
|
||||
tmp = build_dns_entry(split, callback, cmd, data);
|
||||
/* Wait until we can get mutex lock for queue */
|
||||
pthread_mutex_lock(&pending_queue_mutex);
|
||||
/* Enqueue the entry, checking urgency */
|
||||
if (urgency == DNS_URGENT)
|
||||
dns_enqueue_urgent(&PendingQueueHead,
|
||||
&PendingQueueTail, tmp);
|
||||
else
|
||||
dns_enqueue(&PendingQueueHead,
|
||||
&PendingQueueTail, tmp);
|
||||
/* signal dns thread, its got work to do */
|
||||
pthread_cond_signal(&pending_queue_cond);
|
||||
/* Give lock back, so dns thread can react to signal */
|
||||
pthread_mutex_unlock(&pending_queue_mutex);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s:%d error: No host!", __FILE__, __LINE__);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s:%d error: NULL!", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
/* set_dns_output_fd : This makes check_dns_queue much better.
|
||||
* This will add our piped fd into the main's select() loop, so
|
||||
* we will know right away when the output queue has data waiting.
|
||||
*/
|
||||
void set_dns_output_fd(fd_set *rd)
|
||||
{
|
||||
if (cdns_read >= 0)
|
||||
FD_SET(cdns_read, rd);
|
||||
}
|
||||
|
||||
/* dns_check : See above. */
|
||||
void dns_check(fd_set *rd)
|
||||
{
|
||||
char blah[2];
|
||||
if (cdns_read >= 0 && FD_ISSET(cdns_read, rd)) {
|
||||
read(cdns_read, &blah, 1);
|
||||
check_dns_queue();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check_dns_queue : This should be called by the main app thread, at
|
||||
* periodic intervals, ie, whenever its convenient.
|
||||
*/
|
||||
void check_dns_queue()
|
||||
{
|
||||
DNS_QUEUE *dns = (DNS_QUEUE *) 0;
|
||||
while (pthread_mutex_trylock(&finished_queue_mutex) == 0) {
|
||||
dns = dns_dequeue(&FinishedQueueHead, &FinishedQueueTail);
|
||||
pthread_mutex_unlock(&finished_queue_mutex);
|
||||
if (dns) {
|
||||
#ifdef MY_DEBUG
|
||||
fprintf(stderr, "DNS IN: %s: %s <-> %s",
|
||||
dns->in ? dns->in : "<NULL>",
|
||||
dns->in ? dns->in : "<NULL>",
|
||||
dns->out ? dns->out : "<NULL>");
|
||||
#endif
|
||||
if (dns->alias)
|
||||
{
|
||||
char buffer[BIG_BUFFER_SIZE+1];
|
||||
snprintf(buffer, BIG_BUFFER_SIZE, "%s %s ", dns->in ? dns->in : "<NULL>", dns->out ? dns->out : "<NULL>");
|
||||
parse_line("NSLOOKUP", dns->alias, buffer, 0, 0, 1);
|
||||
}
|
||||
else if (dns->callback)
|
||||
dns->callback(dns);
|
||||
else
|
||||
fprintf(stderr, "%s:%d error: No callback!",
|
||||
__FILE__, __LINE__);
|
||||
free_dns_entry(dns);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Give back memory that we allocated for this entry */
|
||||
static void free_dns_entry(DNS_QUEUE *tmp)
|
||||
{
|
||||
if (tmp->in)
|
||||
free(tmp->in);
|
||||
if (tmp->out)
|
||||
free(tmp->out);
|
||||
if (tmp->alias)
|
||||
free(tmp->alias);
|
||||
if (tmp->hostentr)
|
||||
freemyhostent(tmp->hostentr);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/* init our dns mutexes */
|
||||
static void init_dns_mutexes(void)
|
||||
{
|
||||
pthread_mutex_init(&pending_queue_mutex, NULL);
|
||||
pthread_mutex_init(&finished_queue_mutex, NULL);
|
||||
pthread_mutex_init(&quit_mutex, NULL);
|
||||
}
|
||||
|
||||
static void kill_dns_thread(int notused)
|
||||
{
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
static void kill_dns_thread2(int notused)
|
||||
{
|
||||
int ecode = 0;
|
||||
pthread_exit(&ecode);
|
||||
}
|
||||
|
||||
static void dns_thread_signal_setup(void)
|
||||
{
|
||||
sigset_t set;
|
||||
|
||||
/* Create SIGQUIT signal handler for this thread */
|
||||
#if 0
|
||||
signal(SIGQUIT, kill_dns_thread);
|
||||
#endif
|
||||
/* Use ircii's portable implementation of signal() instead */
|
||||
my_signal(SIGQUIT, (sigfunc *) kill_dns_thread, 0);
|
||||
/* Fill set with every signal */
|
||||
sigfillset(&set);
|
||||
/* Remove the SIGQUIT signal from the set */
|
||||
sigdelset(&set, SIGQUIT);
|
||||
/* Apply the mask on this thread */
|
||||
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
||||
}
|
||||
|
||||
/* Our main function of the dns thread */
|
||||
static void *start_dns_thread(void *args)
|
||||
{
|
||||
DNS_QUEUE *dns = NULL;
|
||||
/* Set up the thread's signal handlers and mask */
|
||||
dns_thread_signal_setup();
|
||||
/* loop */
|
||||
while(1) {
|
||||
/* Try the quit mutex, if we get it, that means
|
||||
* main() wants us to die.
|
||||
*/
|
||||
if (pthread_mutex_trylock(&quit_mutex) == 0) {
|
||||
kill_dns_thread2(0);
|
||||
}
|
||||
/* Lock the queue */
|
||||
pthread_mutex_lock(&pending_queue_mutex);
|
||||
dns = dns_dequeue(&PendingQueueHead, &PendingQueueTail);
|
||||
if (!dns) {
|
||||
/*
|
||||
* Give back the cpu, and go to sleep until cond gets signalled.
|
||||
* Note: the mutex MUST be locked, before going into the wait!
|
||||
*/
|
||||
pthread_cond_wait(&pending_queue_cond, &pending_queue_mutex);
|
||||
/* We have been woken up. Thus, 2 conditions are present.
|
||||
* 1) We have been signalled that data is waiting.
|
||||
* 2) The mutex is locked.
|
||||
*/
|
||||
pthread_mutex_unlock(&pending_queue_mutex);
|
||||
}
|
||||
else {
|
||||
char c = ' ';
|
||||
pthread_mutex_unlock(&pending_queue_mutex);
|
||||
do_dns_lookup(dns);
|
||||
/* block until we get the lock */
|
||||
pthread_mutex_lock(&finished_queue_mutex);
|
||||
dns_enqueue(&FinishedQueueHead, &FinishedQueueTail, dns);
|
||||
pthread_mutex_unlock(&finished_queue_mutex);
|
||||
/* Write to our pipe, this will wake up mains select loop */
|
||||
write(cdns_write, &c, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Makes a malloced duplicate of the hostent returned. */
|
||||
my_hostent *duphostent(struct hostent *orig)
|
||||
{
|
||||
my_hostent *tmp = new_malloc(sizeof(my_hostent));
|
||||
int z;
|
||||
|
||||
tmp->h_name = m_strdup(orig->h_name);
|
||||
tmp->h_length = orig->h_length;
|
||||
tmp->h_addrtype = orig->h_addrtype;
|
||||
|
||||
for(z=0;z<MAXALIASES && orig->h_aliases[z];z++)
|
||||
tmp->h_aliases[z] = m_strdup(orig->h_aliases[z]);
|
||||
|
||||
for(z=0;z<MAXADDRS && orig->h_addr_list[z];z++)
|
||||
memcpy(&tmp->h_addr_list[z], orig->h_addr_list[z], sizeof(*orig->h_addr_list));
|
||||
|
||||
return (my_hostent *)tmp;
|
||||
}
|
||||
|
||||
/* Free's the replica hostent. */
|
||||
void freemyhostent(my_hostent *freeme)
|
||||
{
|
||||
int z;
|
||||
|
||||
if(!freeme)
|
||||
return;
|
||||
|
||||
new_free(&freeme->h_name);
|
||||
|
||||
for(z=0;z<MAXALIASES;z++)
|
||||
if(freeme->h_aliases[z])
|
||||
new_free(&freeme->h_aliases[z]);
|
||||
|
||||
new_free(&freeme);
|
||||
}
|
||||
|
||||
/* Does the actual DNS lookup.... host <---> ip */
|
||||
static void do_dns_lookup(DNS_QUEUE *dns)
|
||||
{
|
||||
struct hostent *temp;
|
||||
struct in_addr temp1;
|
||||
int ip = 0;
|
||||
|
||||
/* If nothing, give back nothing */
|
||||
if (!dns->in)
|
||||
return;
|
||||
if (isdigit(*(dns->in + strlen(dns->in) - 1))) {
|
||||
ip = 1;
|
||||
temp1.s_addr = inet_addr(dns->in);
|
||||
temp = gethostbyaddr((char*) &temp1,
|
||||
sizeof (struct in_addr), AF_INET);
|
||||
}
|
||||
else {
|
||||
temp = gethostbyname(dns->in);
|
||||
if (temp)
|
||||
#if defined(_Windows)
|
||||
memcpy(&temp1, temp->h_addr, temp->h_length);
|
||||
#else
|
||||
memcpy((caddr_t)&temp1, temp->h_addr, temp->h_length);
|
||||
#endif
|
||||
else
|
||||
return;
|
||||
}
|
||||
if (!temp)
|
||||
return;
|
||||
if (ip) {
|
||||
dns->ip = 1;
|
||||
if (temp->h_name && *temp->h_name) {
|
||||
dns->out = (char *) malloc(strlen(temp->h_name) + 1);
|
||||
strcpy(dns->out, temp->h_name);
|
||||
dns->hostentr = duphostent(temp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dns->ip = 0;
|
||||
dns->out = (char *) malloc(strlen(inet_ntoa(temp1)) + 1);
|
||||
strcpy(dns->out, inet_ntoa(temp1));
|
||||
dns->hostentr = duphostent(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/* dequeue an entry from the passed in queue */
|
||||
DNS_QUEUE *
|
||||
dns_dequeue(DNS_QUEUE **headp, DNS_QUEUE **tailp)
|
||||
{
|
||||
DNS_QUEUE *tmp = NULL;
|
||||
|
||||
if (*headp == NULL)
|
||||
return NULL;
|
||||
tmp = *headp;
|
||||
*headp = Q_NEXT(tmp);
|
||||
if (*headp == NULL)
|
||||
*tailp = NULL;
|
||||
Q_NEXT(tmp) = NULL;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* enqueue a request onto the passed in queue */
|
||||
DNS_QUEUE *
|
||||
dns_enqueue(DNS_QUEUE **headp, DNS_QUEUE **tailp, DNS_QUEUE *tmp)
|
||||
{
|
||||
Q_NEXT(tmp) = NULL;
|
||||
if (*headp == NULL)
|
||||
*headp = *tailp = tmp;
|
||||
else {
|
||||
Q_NEXT(*tailp) = tmp;
|
||||
*tailp = tmp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* enqueue a request onto the passed in queue, putting it at the front
|
||||
* of the queue. This means it will be the next requested dequeue.
|
||||
*/
|
||||
DNS_QUEUE *
|
||||
dns_enqueue_urgent(DNS_QUEUE **headp, DNS_QUEUE **tailp, DNS_QUEUE *tmp)
|
||||
{
|
||||
Q_NEXT(tmp) = *headp;
|
||||
*headp = tmp;
|
||||
if (*tailp == NULL)
|
||||
*tailp = tmp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* build a dns entry struct */
|
||||
static DNS_QUEUE *
|
||||
build_dns_entry(char *text, void (*callback) (DNS_QUEUE *), char *cmd, void *data)
|
||||
{
|
||||
DNS_QUEUE *tmp = (DNS_QUEUE *) malloc(sizeof(DNS_QUEUE));
|
||||
bzero(tmp, sizeof(DNS_QUEUE));
|
||||
tmp->in = (char *) malloc(strlen(text) + 1);
|
||||
strcpy(tmp->in, text);
|
||||
tmp->callback = callback;
|
||||
tmp->callinfo = data;
|
||||
if (cmd)
|
||||
tmp->alias = strdup(cmd);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* cleanup_dns : cleanup anything regarding the dns thread */
|
||||
static void cleanup_dns(void)
|
||||
{
|
||||
pthread_mutex_destroy(&pending_queue_mutex);
|
||||
pthread_mutex_destroy(&finished_queue_mutex);
|
||||
pthread_mutex_destroy(&quit_mutex);
|
||||
pthread_cond_destroy(&pending_queue_cond);
|
||||
destroy_dns_queue(&PendingQueueHead, &PendingQueueTail);
|
||||
destroy_dns_queue(&FinishedQueueHead, &FinishedQueueTail);
|
||||
close(cdns_read);
|
||||
close(cdns_write);
|
||||
cdns_read = cdns_write = -1;
|
||||
}
|
||||
|
||||
/* destroy_dns_queue : Walks the queue, blowing away each node */
|
||||
static void destroy_dns_queue(DNS_QUEUE **QueueHead, DNS_QUEUE **QueueTail)
|
||||
{
|
||||
DNS_QUEUE *dns;
|
||||
|
||||
while((dns = dns_dequeue(QueueHead, QueueTail)) != NULL)
|
||||
free_dns_entry(dns);
|
||||
}
|
||||
#endif /* THREAD && NSLOOKUP */
|
||||
414
source/cdrom.c
Normal file
414
source/cdrom.c
Normal file
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* cdrom.c: This file handles all the CDROM routines, in BitchX
|
||||
*
|
||||
* Written by Tom Zickel
|
||||
* a.k.a. IceBreak on the irc
|
||||
*
|
||||
* Copyright(c) 1996
|
||||
* Modified Colten Edwards aka panasync.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Version 0.2 22/07/97 written by IceBreak (ice_break@hotmail.com) */
|
||||
/* 0.2: Finnally I rewrote the playing method inside the cdrom player to work
|
||||
* with msf instead of lba, and frames instead of tracks, this should fix
|
||||
* all the compability problems that the cdroms player had with some
|
||||
* cdroms. I also fixed some bugs and better problem messages.
|
||||
* FreeBSD support added by Eric A. Griff aka setjmp!eagriff@*.global2000.net
|
||||
*
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: cdrom.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(cdrom_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "ircaux.h"
|
||||
#include "cdrom.h"
|
||||
#include "output.h"
|
||||
#include "misc.h"
|
||||
#include "vars.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#define cparse(s) convert_output_format(s, NULL, NULL)
|
||||
|
||||
static int drive = 0;
|
||||
|
||||
static char cdrom_prompt[]="%gC%Gd%gROM%w";
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static struct cdrom_tochdr hdr;
|
||||
static struct cdrom_ti ti;
|
||||
#else
|
||||
static struct ioc_toc_header hdr;
|
||||
#endif
|
||||
|
||||
static struct cdrom_etocentry TocEntry[101];
|
||||
|
||||
int cd_init(char *);
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
void play_chunk(int start, int end)
|
||||
{
|
||||
struct cdrom_msf msf;
|
||||
|
||||
end--;
|
||||
if (start >= end)
|
||||
start = end-1;
|
||||
|
||||
msf.cdmsf_min0 = start / (60*75);
|
||||
msf.cdmsf_sec0 = (start % (60*75)) / 75;
|
||||
msf.cdmsf_frame0 = start % 75;
|
||||
msf.cdmsf_min1 = end / (60*75);
|
||||
msf.cdmsf_sec1 = (end % (60*75)) / 75;
|
||||
msf.cdmsf_frame1 = end % 75;
|
||||
|
||||
if (ioctl(drive, CDROMSTART))
|
||||
{
|
||||
put_it("%s: Could not start the cdrom",cparse(cdrom_prompt));
|
||||
return;
|
||||
}
|
||||
if (ioctl(drive, CDROMPLAYMSF, &msf))
|
||||
{
|
||||
put_it("%s: Could not play the track",cparse(cdrom_prompt));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int check_cdrom_str(void)
|
||||
{
|
||||
char *str;
|
||||
if ((str = get_string_var(CD_DEVICE_VAR)))
|
||||
{
|
||||
if (!drive)
|
||||
cd_init(str);
|
||||
return 1;
|
||||
}
|
||||
put_it("%s: /SET CD_DEVICE - The name of the CDROM device",cparse(cdrom_prompt));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd_init(char *dev)
|
||||
{
|
||||
#if 0
|
||||
unsigned char msf_ent[3];
|
||||
unsigned char msf1_ent[3];
|
||||
#endif
|
||||
int i, pos;
|
||||
|
||||
if (((drive = open(dev, 0)) < 0))
|
||||
{
|
||||
if (errno == EACCES)
|
||||
put_it("%s: you dont have access to the cdrom driver",cparse(cdrom_prompt));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (ioctl(drive, CDROMREADTOCHDR, &hdr))
|
||||
{
|
||||
put_it("%s: Can't get TocHeader",cparse(cdrom_prompt));
|
||||
return (-2);
|
||||
}
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
for (i=1;i<=hdr.cdth_trk1+1;i++)
|
||||
{
|
||||
if (i!=hdr.cdth_trk1+1)
|
||||
TocEntry[i].cdte_track = i;
|
||||
else
|
||||
TocEntry[i].cdte_track = CDROM_LEADOUT;
|
||||
TocEntry[i].cdte_format = CDROM_MSF;
|
||||
if (ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]))
|
||||
put_it("%s: Can't get TocEntry #%d",cparse(cdrom_prompt), i);
|
||||
else
|
||||
{
|
||||
TocEntry[i].avoid=TocEntry[i].cdte_ctrl & CDROM_DATA_TRACK ? 1 : 0;
|
||||
TocEntry[i].m_length = TocEntry[i].cdte_addr.msf.minute * 60 + TocEntry[i].cdte_addr.msf.second;
|
||||
TocEntry[i].m_start = TocEntry[i].m_length * 75 + TocEntry[i].cdte_addr.msf.frame;
|
||||
}
|
||||
}
|
||||
|
||||
pos = TocEntry[1].m_length;
|
||||
|
||||
for (i=1;i<=hdr.cdth_trk1+1;i++)
|
||||
{
|
||||
TocEntry[i].m_length = TocEntry[i+1].m_length - pos;
|
||||
pos = TocEntry[i+1].m_length;
|
||||
if (TocEntry[i].avoid)
|
||||
TocEntry[i].m_length = (TocEntry[i+1].m_start - TocEntry[i+1].m_start) *2;
|
||||
}
|
||||
return (hdr.cdth_trk1);
|
||||
#else
|
||||
for (i = hdr.starting_track; i <= hdr.ending_track; i++)
|
||||
{
|
||||
TocEntry[i].avoid=0;
|
||||
TocEntry[i].m_start=1;
|
||||
TocEntry[i].m_length=1;
|
||||
}
|
||||
return (hdr.ending_track);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int check_mount(char *device)
|
||||
{
|
||||
#ifndef __FreeBSD__
|
||||
FILE *fp;
|
||||
struct mntent *mnt;
|
||||
|
||||
if ((fp = setmntent(MOUNTED, "r")) == NULL)
|
||||
return 0;
|
||||
|
||||
while ((mnt = getmntent (fp)) != NULL)
|
||||
{
|
||||
if (!strcmp (mnt->mnt_type, "iso9660") && !strcmp (mnt->mnt_fsname, device))
|
||||
{
|
||||
endmntent(fp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
endmntent (fp);
|
||||
#else
|
||||
struct statfs *mntinfo;
|
||||
int i,count;
|
||||
|
||||
if(!(count=getmntinfo(&mntinfo,MNT_WAIT|MOUNT_CD9660)))
|
||||
return 0;
|
||||
|
||||
for(i=0; i<count; i++)
|
||||
if(strstr(mntinfo[i].f_mntfromname,device))
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void set_cd_device(Window *win, char *str, int blah)
|
||||
{
|
||||
if (drive)
|
||||
close(drive);
|
||||
if (!str || !check_mount(str))
|
||||
{
|
||||
put_it("%s: ERROR: CDROM is already mounted, please unmount, and try again",cparse(cdrom_prompt));
|
||||
set_string_var(CD_DEVICE_VAR,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cd_init(str) < 0)
|
||||
{
|
||||
put_it("%s: ERROR: Could not initalize the CDROM, check if a disk is inside",cparse(cdrom_prompt));
|
||||
set_string_var(CD_DEVICE_VAR,NULL);
|
||||
return;
|
||||
}
|
||||
put_it("%s: CDROM device is now set to - %s",cparse(cdrom_prompt),str);
|
||||
set_string_var(CD_DEVICE_VAR,str);
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(cd_stop)
|
||||
{
|
||||
if (!check_cdrom_str())
|
||||
return;
|
||||
|
||||
if (ioctl(drive,CDROMSTOP))
|
||||
put_it("%s: Couldnt stop the cdrom",cparse(cdrom_prompt));
|
||||
else
|
||||
put_it("%s: Stopped playing cdrom",cparse(cdrom_prompt));
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(cd_eject)
|
||||
{
|
||||
if (!check_cdrom_str())
|
||||
return;
|
||||
|
||||
if (!drive)
|
||||
return;
|
||||
if (ioctl(drive,CDROMEJECT))
|
||||
put_it("%s: Couldnt eject the cdrom tray",cparse(cdrom_prompt));
|
||||
else
|
||||
put_it("%s: Ejected cdrom tray",cparse(cdrom_prompt));
|
||||
close(drive);
|
||||
drive=0;
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(cd_play)
|
||||
{
|
||||
int tn;
|
||||
char *trackn;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
unsigned char first, last;
|
||||
struct cdrom_tochdr tocHdr;
|
||||
#else
|
||||
struct ioc_play_track cdrom_play_args;
|
||||
int result;
|
||||
#endif
|
||||
|
||||
if (!check_cdrom_str() || !drive)
|
||||
return;
|
||||
|
||||
if (args && *args)
|
||||
{
|
||||
trackn = next_arg(args, &args);
|
||||
tn = atoi(trackn);
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
if (ioctl(drive,CDROMREADTOCHDR,&tocHdr))
|
||||
{
|
||||
put_it("%s: Couldnt get cdrom heder",cparse(cdrom_prompt));
|
||||
return;
|
||||
}
|
||||
|
||||
first = tocHdr.cdth_trk0;
|
||||
last = tocHdr.cdth_trk1;
|
||||
ti.cdti_trk0=tn;
|
||||
|
||||
if (ti.cdti_trk0<first)
|
||||
ti.cdti_trk0=first;
|
||||
if (ti.cdti_trk0>last)
|
||||
ti.cdti_trk0=last;
|
||||
|
||||
ti.cdti_ind0=0;
|
||||
ti.cdti_trk1=last;
|
||||
ti.cdti_ind1=0;
|
||||
#else
|
||||
if (tn < hdr.starting_track)
|
||||
tn=hdr.starting_track;
|
||||
if (tn > hdr.ending_track)
|
||||
tn=hdr.ending_track;
|
||||
#endif
|
||||
|
||||
if (TocEntry[tn].avoid==0)
|
||||
{
|
||||
#ifndef __FreeBSD__
|
||||
play_chunk(TocEntry[tn].m_start,TocEntry[last+1].m_start - 1);
|
||||
#else
|
||||
cdrom_play_args.start_track=tn;
|
||||
cdrom_play_args.start_index=1;
|
||||
cdrom_play_args.end_track=hdr.ending_track;
|
||||
cdrom_play_args.end_index=1;
|
||||
(void)ioctl(drive,CDIOCPLAYTRACKS,&cdrom_play_args);
|
||||
#endif
|
||||
put_it("%s: Playing track number #%d",cparse(cdrom_prompt),tn);
|
||||
}
|
||||
else
|
||||
put_it("%s: Cannot play track #%d (Might be data track)",cparse(cdrom_prompt),tn);
|
||||
}
|
||||
else
|
||||
put_it("%s: Usage: /cdplay <track number>",cparse(cdrom_prompt));
|
||||
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(cd_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!check_cdrom_str())
|
||||
return;
|
||||
#ifndef __FreeBSD__
|
||||
for (i=1;i<=hdr.cdth_trk1;i++)
|
||||
#else
|
||||
for (i = hdr.starting_track; i < hdr.ending_track; i++)
|
||||
#endif
|
||||
{
|
||||
put_it("%s: Track #%02d: %02d:%02d:%02d %02d:%02d:%02d",
|
||||
cparse(cdrom_prompt),
|
||||
i,
|
||||
TocEntry[i].m_length / (60*75),
|
||||
(TocEntry[i].m_length % (60*75)) / 75,
|
||||
TocEntry[i].m_length % 75,
|
||||
TocEntry[i].m_start / (60*75),
|
||||
(TocEntry[i].m_start % (60*75)) /75,
|
||||
TocEntry[i].m_start % 75
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(cd_volume)
|
||||
{
|
||||
char *left, *right;
|
||||
#ifndef __FreeBSD__
|
||||
struct cdrom_volctrl volctrl;
|
||||
#else
|
||||
struct ioc_vol volctrl;
|
||||
#endif
|
||||
|
||||
if (!check_cdrom_str())
|
||||
return;
|
||||
|
||||
if (args && *args)
|
||||
{
|
||||
left=next_arg(args, &args);
|
||||
right=next_arg(args, &args);
|
||||
ioctl(drive, CDROMVOLREAD, &volctrl);
|
||||
if (left && *left)
|
||||
#ifndef __FreeBSD__
|
||||
volctrl.channel0 = atoi(left);
|
||||
#else
|
||||
volctrl.vol[0] = atoi(left);
|
||||
#endif
|
||||
if (right && *right)
|
||||
#ifndef __FreeBSD__
|
||||
volctrl.channel1 = atoi(right);
|
||||
#else
|
||||
volctrl.vol[1] = atoi(right);
|
||||
#endif
|
||||
if (ioctl(drive,CDROMVOLCTRL,&volctrl))
|
||||
put_it("%s: Couldnt set cdrom volume",cparse(cdrom_prompt));
|
||||
else
|
||||
put_it("%s: CDROM Volume is now <%d> <%d>",cparse(cdrom_prompt),
|
||||
#ifndef __FreeBSD__
|
||||
volctrl.channel0,volctrl.channel1);
|
||||
#else
|
||||
volctrl.vol[0],volctrl.vol[1]);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
put_it("%s: Usage: /cdvol <left> <right>",cparse(cdrom_prompt));
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(cd_pause)
|
||||
{
|
||||
static int cpause = 0;
|
||||
if (!check_cdrom_str())
|
||||
return;
|
||||
if (ioctl(drive, !cpause?CDROMPAUSE:CDROMRESUME))
|
||||
put_it("%s: Couldnt pause/resume your cdrom",cparse(cdrom_prompt));
|
||||
else
|
||||
put_it("%s: %s",cparse(cdrom_prompt),!cpause?"Your cdrom has been paused":"Your cdrom has been resumed");
|
||||
cpause ^= 1;
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(cd_help)
|
||||
{
|
||||
put_it("%s: CDPLAY - Play a CDROM Track Number",cparse(cdrom_prompt));
|
||||
put_it("%s: CDSTOP - Make the CDROM Stop playing",cparse(cdrom_prompt));
|
||||
put_it("%s: CDEJECT - Eject the CDROM Tray",cparse(cdrom_prompt));
|
||||
put_it("%s: CDVOL - Set's the CDROM Volume",cparse(cdrom_prompt));
|
||||
put_it("%s: CDLIST - List of CDROM tracks",cparse(cdrom_prompt));
|
||||
put_it("%s: CDPAUSE - Pause/resume the CDROM",cparse(cdrom_prompt));
|
||||
}
|
||||
|
||||
#if 0
|
||||
char *status_cdrom(window)
|
||||
Window *window;
|
||||
{
|
||||
static char text[BIG_BUFFER_SIZE];
|
||||
|
||||
if ((drive) && (get_string_var(CD_DEVICE_VAR)))
|
||||
{
|
||||
rc=ioctl(drive,CDROMSUBCHNL,&subchnl);
|
||||
strcpy(text,"[CD:");
|
||||
if (subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY)
|
||||
{
|
||||
strcat(text,"P");
|
||||
strcat(text,":");
|
||||
strcat(text,ltoa((long)subchnl.cdsc_trk));
|
||||
} else {
|
||||
strcat(text,"S");
|
||||
}
|
||||
strcat(text,"]");
|
||||
return(text);
|
||||
}
|
||||
else
|
||||
return (empty_string);
|
||||
}
|
||||
#endif
|
||||
230
source/chelp.c
Normal file
230
source/chelp.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright Colten Edwards (c) 1996
|
||||
* BitchX help file system.
|
||||
* When Chelp is called the help file is loaded from
|
||||
* BitchX.help and saved. This file is never loaded from disk after this.
|
||||
* Information from the help file is loaded into an array as 0-Topic.
|
||||
* $help() also calls the same routines except this information is loaded
|
||||
* differantly as 1-Topic. this allows us to distingush between them
|
||||
* internally.
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: chelp.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(chelp_c)
|
||||
#include "struct.h"
|
||||
#include "ircaux.h"
|
||||
#include "chelp.h"
|
||||
#include "output.h"
|
||||
#include "hook.h"
|
||||
#include "misc.h"
|
||||
#include "vars.h"
|
||||
#include "window.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#ifdef WANT_CHELP
|
||||
int read_file (FILE *help_file, int helpfunc);
|
||||
extern int in_cparse;
|
||||
int in_chelp = 0;
|
||||
|
||||
typedef struct _chelp_struct {
|
||||
char *title;
|
||||
char **contents;
|
||||
char *relates;
|
||||
} Chelp;
|
||||
|
||||
Chelp **help_index = NULL;
|
||||
Chelp **script_help = NULL;
|
||||
|
||||
char *get_help_topic(char *args, int helpfunc)
|
||||
{
|
||||
char *new_comm = NULL;
|
||||
int found = 0, i;
|
||||
char *others = NULL;
|
||||
|
||||
new_comm = LOCAL_COPY(args);
|
||||
|
||||
for (i = 0; helpfunc ? script_help[i] : help_index[i]; i++)
|
||||
{
|
||||
if (!my_strnicmp(helpfunc?script_help[i]->title:help_index[i]->title, new_comm, strlen(new_comm)))
|
||||
{
|
||||
int j;
|
||||
char *text = NULL;
|
||||
if (found++)
|
||||
{
|
||||
m_s3cat(&others, " , ", helpfunc?script_help[i]->title:help_index[i]->title);
|
||||
continue;
|
||||
}
|
||||
if (args && *args && do_hook(HELPTOPIC_LIST, "%s", args))
|
||||
put_it("%s",convert_output_format("$G \002$0\002: Help on Topic: \002$1\002", version, args));
|
||||
for (j = 0; ; j++)
|
||||
{
|
||||
if (helpfunc && (script_help[i] && script_help[i]->contents[j]))
|
||||
text = script_help[i]->contents[j];
|
||||
else if (!helpfunc && (help_index[i] && help_index[i]->contents[j]))
|
||||
text = help_index[i]->contents[j];
|
||||
else
|
||||
break;
|
||||
|
||||
if (text && do_hook(HELPSUBJECT_LIST, "%s %s", new_comm, text))
|
||||
{
|
||||
in_chelp++;
|
||||
put_it("%s", convert_output_format(text, NULL));
|
||||
in_chelp--;
|
||||
}
|
||||
}
|
||||
text = helpfunc ?script_help[i]->relates:help_index[i]->relates;
|
||||
if (text && do_hook(HELPTOPIC_LIST, "%s", text))
|
||||
put_it("%s", convert_output_format(text, NULL));
|
||||
}
|
||||
else if (found)
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
if (do_hook(HELPTOPIC_LIST, "%s", args))
|
||||
bitchsay("No help on %s", args);
|
||||
}
|
||||
|
||||
if (others && found)
|
||||
{
|
||||
if (do_hook(HELPTOPIC_LIST, "%d %s", found, others))
|
||||
put_it("Other %d subjects: %s", found - 1, others);
|
||||
}
|
||||
new_free(&others);
|
||||
if (helpfunc)
|
||||
return m_strdup(empty_string);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(chelp)
|
||||
{
|
||||
static int first_time = 1;
|
||||
reset_display_target();
|
||||
if (args && *args == '-' && !my_strnicmp(args, "-dump", 4))
|
||||
{
|
||||
int i, j;
|
||||
next_arg(args, &args);
|
||||
first_time = 1;
|
||||
if (help_index)
|
||||
{
|
||||
for (i = 0; help_index[i]; i++)
|
||||
{
|
||||
if (help_index[i]->contents)
|
||||
{
|
||||
for (j =0; help_index[i]->contents[j]; j++)
|
||||
new_free(&help_index[i]->contents[j]);
|
||||
}
|
||||
new_free(&help_index[i]->contents);
|
||||
new_free(&help_index[i]->title);
|
||||
new_free(&help_index[i]->relates);
|
||||
new_free(&help_index[i]);
|
||||
}
|
||||
new_free(&help_index);
|
||||
}
|
||||
}
|
||||
if (first_time)
|
||||
{
|
||||
char *help_dir = NULL;
|
||||
FILE *help_file;
|
||||
#ifdef PUBLIC_SYSTEM
|
||||
malloc_sprintf(&help_dir, "%s", DEFAULT_BITCHX_HELP_FILE);
|
||||
#else
|
||||
malloc_sprintf(&help_dir, "%s", get_string_var(BITCHX_HELP_VAR));
|
||||
#endif
|
||||
if (!(help_file = uzfopen(&help_dir, get_string_var(LOAD_PATH_VAR), 1)))
|
||||
{
|
||||
new_free(&help_dir);
|
||||
return;
|
||||
}
|
||||
new_free(&help_dir);
|
||||
first_time = 0;
|
||||
read_file(help_file, 0);
|
||||
fclose(help_file);
|
||||
}
|
||||
if (!args || !*args)
|
||||
{
|
||||
userage(command, helparg);
|
||||
return;
|
||||
}
|
||||
get_help_topic(args, 0);
|
||||
}
|
||||
|
||||
int read_file(FILE *help_file, int helpfunc)
|
||||
{
|
||||
char line[BIG_BUFFER_SIZE + 1];
|
||||
char *topic = NULL;
|
||||
char *subject = NULL;
|
||||
int item_number = 0;
|
||||
int topics = 0;
|
||||
fgets(line, sizeof(line)-1, help_file);
|
||||
if (line)
|
||||
line[strlen(line)-1] = '\0';
|
||||
while (!feof(help_file))
|
||||
{
|
||||
if (!line || !*line || *line == '#')
|
||||
{
|
||||
fgets(line, sizeof(line)-1, help_file);
|
||||
continue;
|
||||
}
|
||||
else if (*line && (*line != ' ')) /* we got a topic copy to topic */
|
||||
{
|
||||
topics++;
|
||||
item_number = 0;
|
||||
if (!my_strnicmp(line, "-RELATED", 7))
|
||||
{
|
||||
if (topic)
|
||||
{
|
||||
if (helpfunc)
|
||||
script_help[topics-1]->relates = m_strdup(line+8);
|
||||
else
|
||||
help_index[topics-1]->relates = m_strdup(line+8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_free(&topic); new_free(&subject);
|
||||
malloc_strcpy(&topic, line);
|
||||
if (helpfunc)
|
||||
{
|
||||
RESIZE(script_help, Chelp, topics+1);
|
||||
script_help[topics-1] = new_malloc(sizeof(Chelp));
|
||||
script_help[topics-1]->title = m_strdup(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
RESIZE(help_index, Chelp, topics+1);
|
||||
help_index[topics-1] = new_malloc(sizeof(Chelp));
|
||||
help_index[topics-1]->title = m_strdup(line);
|
||||
}
|
||||
}
|
||||
fgets(line, sizeof(line)-1, help_file);
|
||||
if (line)
|
||||
line[strlen(line)-1] = '\0';
|
||||
}
|
||||
else if (topic && *topic)
|
||||
{ /* we found the subject material */
|
||||
do {
|
||||
if (!line || (line && *line != ' '))
|
||||
break;
|
||||
if (helpfunc)
|
||||
{
|
||||
RESIZE(script_help[topics-1]->contents, char **, ++item_number);
|
||||
script_help[topics-1]->contents[item_number-1] = m_strdup(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
RESIZE(help_index[topics-1]->contents, char **, ++item_number);
|
||||
help_index[topics-1]->contents[item_number-1] = m_strdup(line);
|
||||
}
|
||||
fgets(line, sizeof(line)-1, help_file);
|
||||
if (line)
|
||||
line[strlen(line)-1] = '\0';
|
||||
} while (!feof(help_file));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
5547
source/commands.c
Normal file
5547
source/commands.c
Normal file
File diff suppressed because it is too large
Load Diff
2892
source/commands2.c
Normal file
2892
source/commands2.c
Normal file
File diff suppressed because it is too large
Load Diff
2403
source/compat.c
Normal file
2403
source/compat.c
Normal file
File diff suppressed because it is too large
Load Diff
1308
source/cset.c
Normal file
1308
source/cset.c
Normal file
File diff suppressed because it is too large
Load Diff
1666
source/ctcp.c
Normal file
1666
source/ctcp.c
Normal file
File diff suppressed because it is too large
Load Diff
4449
source/dcc.c
Normal file
4449
source/dcc.c
Normal file
File diff suppressed because it is too large
Load Diff
263
source/debug.c
Normal file
263
source/debug.c
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* debug.c -- controll the values of x_debug.
|
||||
*
|
||||
* Written by Jeremy Nelson
|
||||
* Copyright 1997 EPIC Software Labs
|
||||
* See the COPYRIGHT file for more information
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: debug.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(debug_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "ircaux.h"
|
||||
#include "output.h"
|
||||
#include "misc.h"
|
||||
#include "window.h"
|
||||
#include "hook.h"
|
||||
#include "lastlog.h"
|
||||
#include "cset.h"
|
||||
#include "screen.h"
|
||||
#include "input.h"
|
||||
#include "status.h"
|
||||
#include "vars.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
unsigned long x_debug = 0;
|
||||
unsigned long internal_debug = 0;
|
||||
unsigned long alias_debug = 0;
|
||||
unsigned int debug_count = 1;
|
||||
int in_debug_yell = 0;
|
||||
|
||||
struct debug_opts
|
||||
{
|
||||
char *command;
|
||||
int flag;
|
||||
};
|
||||
|
||||
static struct debug_opts opts[] =
|
||||
{
|
||||
{ "LOCAL_VARS", DEBUG_LOCAL_VARS },
|
||||
{ "CTCPS", DEBUG_CTCPS },
|
||||
{ "DCC_SEARCH", DEBUG_DCC_SEARCH },
|
||||
{ "OUTBOUND", DEBUG_OUTBOUND },
|
||||
{ "INBOUND", DEBUG_INBOUND },
|
||||
{ "DCC_XMIT", DEBUG_DCC_XMIT },
|
||||
{ "WAITS", DEBUG_WAITS },
|
||||
{ "MEMORY", DEBUG_MEMORY },
|
||||
{ "SERVER_CONNECT", DEBUG_SERVER_CONNECT },
|
||||
{ "CRASH", DEBUG_CRASH },
|
||||
{ "COLOR", DEBUG_COLOR },
|
||||
{ "NOTIFY", DEBUG_NOTIFY },
|
||||
{ "REGEX", DEBUG_REGEX },
|
||||
{ "REGEX_DEBUG", DEBUG_REGEX_DEBUG },
|
||||
{ "BROKEN_CLOCK", DEBUG_BROKEN_CLOCK },
|
||||
{ "UNKNOWN", DEBUG_UNKNOWN },
|
||||
{ "DEBUG", DEBUG_DEBUGGER },
|
||||
{ "NEW_MATH", DEBUG_NEW_MATH },
|
||||
{ "NEW_MATH_DEBUG", DEBUG_NEW_MATH_DEBUG },
|
||||
{ "AUTOKEY", DEBUG_AUTOKEY },
|
||||
{ "STRUCTURES", DEBUG_STRUCTURES },
|
||||
{ "ALL", DEBUG_ALL },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
|
||||
|
||||
BUILT_IN_COMMAND(xdebugcmd)
|
||||
{
|
||||
int cnt;
|
||||
int remove = 0;
|
||||
char *this_arg;
|
||||
|
||||
if (!args || !*args)
|
||||
{
|
||||
char buffer[540];
|
||||
char *q;
|
||||
int i = 0;
|
||||
|
||||
buffer[0] = 0;
|
||||
strmcat(buffer, "[-][+][option(s)] ", 511);
|
||||
q = &buffer[strlen(buffer)];
|
||||
for (i = 0; opts[i].command; i++)
|
||||
{
|
||||
if (q)
|
||||
strmcat(q, ", ", 511);
|
||||
strmcat(q, opts[i].command, 511);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (args && *args)
|
||||
{
|
||||
this_arg = upper(next_arg(args, &args));
|
||||
if (*this_arg == '-')
|
||||
remove = 1, this_arg++;
|
||||
else if (*this_arg == '+')
|
||||
this_arg++;
|
||||
|
||||
for (cnt = 0; opts[cnt].command; cnt++)
|
||||
{
|
||||
if (!strncmp(this_arg, opts[cnt].command, strlen(this_arg)))
|
||||
{
|
||||
if (remove)
|
||||
x_debug &= ~opts[cnt].flag;
|
||||
else
|
||||
x_debug |= opts[cnt].flag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!opts[cnt].command)
|
||||
say("Unrecognized XDEBUG option '%s'", this_arg);
|
||||
}
|
||||
}
|
||||
|
||||
void debugyell(const char *format, ...)
|
||||
{
|
||||
const char *save_from;
|
||||
unsigned long save_level;
|
||||
unsigned long old_alias_debug = alias_debug;
|
||||
alias_debug = 0;
|
||||
save_display_target(&save_from, &save_level);
|
||||
set_display_target(NULL, LOG_DEBUG);
|
||||
if (format)
|
||||
{
|
||||
char debugbuf[BIG_BUFFER_SIZE+1];
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
*debugbuf = 0;
|
||||
vsnprintf(debugbuf, BIG_BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
in_debug_yell = 1;
|
||||
if (*debugbuf && do_hook(DEBUG_LIST, "%s", debugbuf))
|
||||
put_echo(debugbuf);
|
||||
in_debug_yell = 0;
|
||||
}
|
||||
alias_debug = old_alias_debug;
|
||||
reset_display_target();
|
||||
restore_display_target(save_from, save_level);
|
||||
}
|
||||
|
||||
int parse_debug(char *value, int nvalue, char **rv)
|
||||
{
|
||||
char *str1, *str2;
|
||||
char *copy;
|
||||
char *nv = NULL;
|
||||
|
||||
if (rv)
|
||||
*rv = NULL;
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
copy = alloca(strlen(value) + 1);
|
||||
strcpy(copy, value);
|
||||
|
||||
while ((str1 = new_next_arg(copy, ©)))
|
||||
{
|
||||
while (*str1 && (str2 = next_in_comma_list(str1, &str1)))
|
||||
{
|
||||
if (!my_strnicmp(str2, "ALL", 3))
|
||||
nvalue = (0x7F - (DEBUG_TCL));
|
||||
else if (!my_strnicmp(str2, "-ALL", 4))
|
||||
nvalue = 0;
|
||||
else if (!my_strnicmp(str2, "COMMANDS", 4))
|
||||
nvalue |= DEBUG_COMMANDS;
|
||||
else if (!my_strnicmp(str2, "-COMMANDS", 4))
|
||||
nvalue &= ~(DEBUG_COMMANDS);
|
||||
else if (!my_strnicmp(str2, "EXPANSIONS", 4))
|
||||
nvalue |= DEBUG_EXPANSIONS;
|
||||
else if (!my_strnicmp(str2, "-EXPANSIONS", 4))
|
||||
nvalue &= ~(DEBUG_EXPANSIONS);
|
||||
else if (!my_strnicmp(str2, "TCL", 3))
|
||||
nvalue |= DEBUG_TCL;
|
||||
else if (!my_strnicmp(str2, "-TCL", 3))
|
||||
nvalue &= ~(DEBUG_TCL);
|
||||
else if (!my_strnicmp(str2, "ALIAS", 3))
|
||||
nvalue |= DEBUG_CMDALIAS;
|
||||
else if (!my_strnicmp(str2, "-ALIAS", 3))
|
||||
nvalue &= ~(DEBUG_CMDALIAS);
|
||||
else if (!my_strnicmp(str2, "HOOK", 3))
|
||||
nvalue |= DEBUG_HOOK;
|
||||
else if (!my_strnicmp(str2, "-HOOK", 3))
|
||||
nvalue &= ~(DEBUG_HOOK);
|
||||
else if (!my_strnicmp(str2, "VARIABLES", 3))
|
||||
nvalue |= DEBUG_VARIABLE;
|
||||
else if (!my_strnicmp(str2, "-VARIABLES", 3))
|
||||
nvalue &= ~(DEBUG_VARIABLE);
|
||||
else if (!my_strnicmp(str2, "FUNCTIONS", 3))
|
||||
nvalue |= DEBUG_FUNC;
|
||||
else if (!my_strnicmp(str2, "-FUNCTIONS", 3))
|
||||
nvalue &= ~(DEBUG_FUNC);
|
||||
else if (!my_strnicmp(str2, "STRUCTURES", 3))
|
||||
nvalue |= DEBUG_STRUCTURES;
|
||||
else if (!my_strnicmp(str2, "-STRUCTURES", 3))
|
||||
nvalue &= ~(DEBUG_STRUCTURES);
|
||||
}
|
||||
}
|
||||
if (rv)
|
||||
{
|
||||
if (nvalue & DEBUG_COMMANDS)
|
||||
m_s3cat(&nv, comma, "COMMANDS");
|
||||
if (nvalue & DEBUG_EXPANSIONS)
|
||||
m_s3cat(&nv, comma, "EXPANSIONS");
|
||||
if (nvalue & DEBUG_TCL)
|
||||
m_s3cat(&nv, comma, "TCL");
|
||||
if (nvalue & DEBUG_CMDALIAS)
|
||||
m_s3cat(&nv, comma, "ALIAS");
|
||||
if (nvalue & DEBUG_HOOK)
|
||||
m_s3cat(&nv, comma, "HOOK");
|
||||
if (nvalue & DEBUG_VARIABLE)
|
||||
m_s3cat(&nv, comma, "VARIABLES");
|
||||
if (nvalue & DEBUG_FUNC)
|
||||
m_s3cat(&nv, comma, "FUNCTIONS");
|
||||
if (nvalue & DEBUG_STRUCTURES)
|
||||
m_s3cat(&nv, comma, "STRUCTURES");
|
||||
*rv = nv;
|
||||
}
|
||||
return nvalue;
|
||||
}
|
||||
|
||||
void debug_window(Window *win, char *value, int unused)
|
||||
{
|
||||
Window *old_win = win;
|
||||
char *nv = NULL;
|
||||
|
||||
internal_debug = parse_debug(value, internal_debug, &nv);
|
||||
set_string_var(DEBUG_VAR, nv);
|
||||
|
||||
if (internal_debug)
|
||||
{
|
||||
Window *tmp = NULL;
|
||||
if (!get_window_by_name("debug") && (tmp = new_window(win->screen)))
|
||||
{
|
||||
malloc_strcpy(&tmp->name, "debug");
|
||||
tmp->double_status = 0;
|
||||
hide_window(tmp);
|
||||
tmp->window_level = LOG_DEBUG;
|
||||
tmp->absolute_size = 1;
|
||||
tmp->skip = 1;
|
||||
debugging_window = tmp;
|
||||
set_wset_string_var(tmp->wset, STATUS_FORMAT1_WSET, DEFAULT_FORMAT_DEBUG_FSET);
|
||||
build_status(tmp, NULL, 0);
|
||||
update_all_windows();
|
||||
set_input_prompt(win, get_string_var(INPUT_PROMPT_VAR), 0);
|
||||
cursor_to_input();
|
||||
set_screens_current_window(old_win->screen, old_win);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((old_win = get_window_by_name("debug")))
|
||||
{
|
||||
delete_window(old_win);
|
||||
debugging_window = NULL;
|
||||
update_all_windows();
|
||||
set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 0);
|
||||
cursor_to_input();
|
||||
}
|
||||
}
|
||||
new_free(&nv);
|
||||
}
|
||||
204
source/digraph.inc
Normal file
204
source/digraph.inc
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* diagraph.inc: included several times by translat.c
|
||||
*/
|
||||
|
||||
DiLo(' ') DiHi(0xa8) DiDi(0x22) /* Digital VT300 / VT400 */
|
||||
DiLo(' ') DiHi(0xb4) DiDi(0x27) /* Digital VT300 / VT400 */
|
||||
|
||||
/*
|
||||
* We don't really need to be *that* pedantic, so let's skip the useless
|
||||
* ones: /Tomten
|
||||
*/
|
||||
/* DiLo(' ') DiHi(' ') DiDi(0xa0) */ /* Digital VT300 / VT400 */
|
||||
/* DiLo(' ') DiHi('^') DiDi('^') */ /* Digital VT300 / VT400 */
|
||||
/* DiLo(' ') DiHi('`') DiDi('`') */ /* Digital VT300 / VT400 */
|
||||
/* DiLo(' ') DiHi('~') DiDi('~') */ /* Digital VT300 / VT400 */
|
||||
/* DiLo(' ') DiHi(0xa8) DiDi(0xa8) */ /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('!') DiHi('!') DiDi(0xa1) /* Digital VT300 / VT400 */
|
||||
DiLo('!') DiHi('P') DiDi(0xb6) /* Digital VT300 / VT400 */
|
||||
DiLo('!') DiHi('S') DiDi(0xa7) /* Digital VT300 / VT400 */
|
||||
DiLo('!') DiHi('^') DiDi(0xa6) /* Digital VT300 / VT400 */
|
||||
DiLo('!') DiHi('~') DiDi(0xa1)
|
||||
|
||||
DiLo(0x22) DiHi(0x22) DiDi(0xa8) /* Digital VT300 / VT400 */
|
||||
DiLo(0x22) DiHi('>') DiDi(0xab)
|
||||
DiLo(0x22) DiHi('<') DiDi(0xbb)
|
||||
DiLo(0x22) DiHi('A') DiDi(0xc4)
|
||||
DiLo(0x22) DiHi('E') DiDi(0xcb)
|
||||
DiLo(0x22) DiHi('I') DiDi(0xcf)
|
||||
DiLo(0x22) DiHi('O') DiDi(0xd6)
|
||||
DiLo(0x22) DiHi('U') DiDi(0xdc)
|
||||
DiLo(0x22) DiHi('a') DiDi(0xe4)
|
||||
DiLo(0x22) DiHi('e') DiDi(0xeb)
|
||||
DiLo(0x22) DiHi('i') DiDi(0xef)
|
||||
DiLo(0x22) DiHi('o') DiDi(0xf6)
|
||||
DiLo(0x22) DiHi('u') DiDi(0xfc)
|
||||
DiLo(0x22) DiHi('y') DiDi(0xff)
|
||||
|
||||
DiLo(0x27) DiHi(0x27) DiDi(0xb4) /* Digital VT300 / VT400 */
|
||||
DiLo(0x27) DiHi('A') DiDi(0xc1)
|
||||
DiLo(0x27) DiHi('E') DiDi(0xc9)
|
||||
DiLo(0x27) DiHi('I') DiDi(0xcd)
|
||||
DiLo(0x27) DiHi('O') DiDi(0xd3)
|
||||
DiLo(0x27) DiHi('U') DiDi(0xda)
|
||||
DiLo(0x27) DiHi('Y') DiDi(0xdd)
|
||||
DiLo(0x27) DiHi('a') DiDi(0xe1)
|
||||
DiLo(0x27) DiHi('e') DiDi(0xe9)
|
||||
DiLo(0x27) DiHi('i') DiDi(0xed)
|
||||
DiLo(0x27) DiHi('o') DiDi(0xf3)
|
||||
DiLo(0x27) DiHi('u') DiDi(0xfa)
|
||||
|
||||
DiLo('(') DiHi('(') DiDi('[') /* Digital VT300 / VT400 */
|
||||
DiLo('(') DiHi('-') DiDi('{') /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo(')') DiHi(')') DiDi(']') /* Digital VT300 / VT400 */
|
||||
DiLo(')') DiHi('-') DiDi('}') /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('*') DiHi('A') DiDi(0xc5) /* Digital VT300 / VT400 */
|
||||
DiLo('*') DiHi('a') DiDi(0xe5)
|
||||
|
||||
DiLo('+') DiHi('+') DiDi('#') /* Digital VT300 / VT400 */
|
||||
DiLo('+') DiHi('-') DiDi(0xb1) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo(',') DiHi(',') DiDi(0xb8) /* Digital VT300 / VT400 */
|
||||
DiLo(',') DiHi('-') DiDi(0xac) /* Digital VT300 / VT400 */
|
||||
DiLo(',') DiHi('C') DiDi(0xc7)
|
||||
DiLo(',') DiHi('c') DiDi(0xe7)
|
||||
|
||||
DiLo('-') DiHi('-') DiDi(0xad) /* Digital VT300 / VT400 */
|
||||
DiLo('-') DiHi(':') DiDi(0xf7) /* Digital VT300 / VT400 */
|
||||
DiLo('-') DiHi('D') DiDi(0xd0)
|
||||
DiLo('-') DiHi('L') DiDi(0xa3) /* Digital VT300 / VT400 */
|
||||
DiLo('-') DiHi('Y') DiDi(0xa5) /* Digital VT300 / VT400 */
|
||||
DiLo('-') DiHi('^') DiDi(0xaf) /* Digital VT300 / VT400 */
|
||||
DiLo('-') DiHi('a') DiDi(0xaa)
|
||||
DiLo('-') DiHi('d') DiDi(0xf0)
|
||||
DiLo('-') DiHi('o') DiDi(0xba)
|
||||
|
||||
DiLo('.') DiHi('^') DiDi(0xb7) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('/') DiHi('/') DiDi('\\') /* Digital VT300 / VT400 */
|
||||
DiLo('/') DiHi('<') DiDi('\\') /* Digital VT300 / VT400 */
|
||||
DiLo('/') DiHi('C') DiDi(0xa2) /* Digital VT300 / VT400 */
|
||||
DiLo('/') DiHi('O') DiDi(0xd8)
|
||||
DiLo('/') DiHi('U') DiDi(0xb5) /* Digital VT300 / VT400 */
|
||||
DiLo('/') DiHi('^') DiDi('|') /* Digital VT300 / VT400 */
|
||||
DiLo('/') DiHi('o') DiDi(0xf8)
|
||||
|
||||
DiLo('0') DiHi('C') DiDi(0xa9) /* Digital VT300 / VT400 */
|
||||
DiLo('0') DiHi('S') DiDi(0xa7) /* Digital VT300 / VT400 */
|
||||
DiLo('0') DiHi('X') DiDi(0xa4) /* Digital VT300 / VT400 */
|
||||
DiLo('0') DiHi('^') DiDi(0xb0) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('1') DiHi('^') DiDi(0xb9) /* Digital VT300 / VT400 */
|
||||
DiLo('1') DiHi('2') DiDi(0xbd) /* Digital VT300 / VT400 */
|
||||
DiLo('1') DiHi('4') DiDi(0xbc) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('2') DiHi('^') DiDi(0xb2) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('3') DiHi('4') DiDi(0xbe) /* Digital VT300 / VT400 */
|
||||
DiLo('3') DiHi('^') DiDi(0xb3) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('<') DiHi('<') DiDi(0xab) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('=') DiHi('L') DiDi(0xa3) /* Digital VT300 / VT400 */
|
||||
DiLo('=') DiHi('Y') DiDi(0xa5) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('>') DiHi('>') DiDi(0xbb) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('?') DiHi('?') DiDi(0xbf) /* Digital VT300 / VT400 */
|
||||
DiLo('?') DiHi('~') DiDi(0xbf)
|
||||
|
||||
DiLo('@') DiHi('A') DiDi(0xc5)
|
||||
DiLo('@') DiHi('a') DiDi(0xe5)
|
||||
|
||||
DiLo('A') DiHi('A') DiDi('@') /* Digital VT300 / VT400 */
|
||||
DiLo('A') DiHi('E') DiDi(0xc6)
|
||||
DiLo('A') DiHi('^') DiDi(0xc2)
|
||||
DiLo('A') DiHi('_') DiDi(0xaa) /* Digital VT300 / VT400 */
|
||||
DiLo('A') DiHi('`') DiDi(0xc0)
|
||||
DiLo('A') DiHi('~') DiDi(0xc3)
|
||||
DiLo('A') DiHi(0xa8) DiDi(0xc4) /* Digital VT300 / VT400 */
|
||||
DiLo('A') DiHi(0xb0) DiDi(0xc5) /* Digital VT300 / VT400 */
|
||||
DiLo('A') DiHi(0xb4) DiDi(0xc1) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('C') DiHi('O') DiDi(0xa9) /* Digital VT300 / VT400 */
|
||||
DiLo('C') DiHi('|') DiDi(0xa2) /* Digital VT300 / VT400 */
|
||||
DiLo('C') DiHi(0xb8) DiDi(0xc7) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('E') DiHi('^') DiDi(0xca)
|
||||
DiLo('E') DiHi('`') DiDi(0xc8)
|
||||
DiLo('E') DiHi(0xa8) DiDi(0xcb) /* Digital VT300 / VT400 */
|
||||
DiLo('E') DiHi(0xb4) DiDi(0xc9) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('H') DiHi('T') DiDi(0xde) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('I') DiHi('^') DiDi(0xce)
|
||||
DiLo('I') DiHi('`') DiDi(0xcc)
|
||||
DiLo('I') DiHi(0xa8) DiDi(0xcf) /* Digital VT300 / VT400 */
|
||||
DiLo('I') DiHi(0xb4) DiDi(0xcd) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('N') DiHi('~') DiDi(0xd1)
|
||||
|
||||
DiLo('O') DiHi('R') DiDi(0xae) /* Digital VT300 / VT400 */
|
||||
DiLo('O') DiHi('S') DiDi(0xa7) /* Digital VT300 / VT400 */
|
||||
DiLo('O') DiHi('X') DiDi(0xa4) /* Digital VT300 / VT400 */
|
||||
DiLo('O') DiHi('^') DiDi(0xd4)
|
||||
DiLo('O') DiHi('_') DiDi(0xba) /* Digital VT300 / VT400 */
|
||||
DiLo('O') DiHi('`') DiDi(0xd2)
|
||||
DiLo('O') DiHi('~') DiDi(0xd5)
|
||||
DiLo('O') DiHi(0xa8) DiDi(0xd6) /* Digital VT300 / VT400 */
|
||||
DiLo('O') DiHi(0xb4) DiDi(0xd3) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('U') DiHi('^') DiDi(0xdb)
|
||||
DiLo('U') DiHi('`') DiDi(0xd9)
|
||||
DiLo('U') DiHi(0xa8) DiDi(0xdc) /* Digital VT300 / VT400 */
|
||||
DiLo('U') DiHi(0xb4) DiDi(0xda) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('Y') DiHi(0xb4) DiDi(0xdd) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('^') DiHi('a') DiDi(0xe2)
|
||||
DiLo('^') DiHi('e') DiDi(0xea)
|
||||
DiLo('^') DiHi('i') DiDi(0xee)
|
||||
DiLo('^') DiHi('o') DiDi(0xf4)
|
||||
DiLo('^') DiHi('u') DiDi(0xfb)
|
||||
|
||||
DiLo('`') DiHi('a') DiDi(0xe0)
|
||||
DiLo('`') DiHi('e') DiDi(0xe8)
|
||||
DiLo('`') DiHi('i') DiDi(0xec)
|
||||
DiLo('`') DiHi('o') DiDi(0xf2)
|
||||
DiLo('`') DiHi('u') DiDi(0xf9)
|
||||
|
||||
DiLo('a') DiHi('e') DiDi(0xe6)
|
||||
DiLo('a') DiHi('~') DiDi(0xe3)
|
||||
DiLo('a') DiHi(0xa8) DiDi(0xe4) /* Digital VT300 / VT400 */
|
||||
DiLo('a') DiHi(0xb0) DiDi(0xe5) /* Digital VT300 / VT400 */
|
||||
DiLo('a') DiHi(0xb4) DiDi(0xe1) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('c') DiHi(0xb8) DiDi(0xe7) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('e') DiHi(0xa8) DiDi(0xeb) /* Digital VT300 / VT400 */
|
||||
DiLo('e') DiHi(0xb4) DiDi(0xe9) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('h') DiHi('t') DiDi(0xfe) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('i') DiHi(0xa8) DiDi(0xef) /* Digital VT300 / VT400 */
|
||||
DiLo('i') DiHi(0xb4) DiDi(0xed) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('n') DiHi('~') DiDi(0xf1)
|
||||
|
||||
DiLo('o') DiHi('~') DiDi(0xf5)
|
||||
DiLo('o') DiHi(0xa8) DiDi(0xf6) /* Digital VT300 / VT400 */
|
||||
DiLo('o') DiHi(0xb4) DiDi(0xf3) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('s') DiHi('s') DiDi(0xdf) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('u') DiHi(0xa8) DiDi(0xfc) /* Digital VT300 / VT400 */
|
||||
DiLo('u') DiHi(0xb4) DiDi(0xfa) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('x') DiHi('x') DiDi(0xd7) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('y') DiHi(0xa8) DiDi(0xff) /* Digital VT300 / VT400 */
|
||||
|
||||
DiLo('|') DiHi('|') DiDi(0xa6) /* Digital VT300 / VT400 */
|
||||
260
source/encrypt.c
Normal file
260
source/encrypt.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* crypt.c: handles some encryption of messages stuff.
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
*
|
||||
* Copyright(c) 1990
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: encrypt.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(encrypt_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "encrypt.h"
|
||||
#include "vars.h"
|
||||
#include "ircaux.h"
|
||||
#include "list.h"
|
||||
#include "ctcp.h"
|
||||
#include "output.h"
|
||||
#include "newio.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
static void add_to_crypt (char *, char *);
|
||||
static int remove_crypt (char *);
|
||||
static char *do_crypt (char *, char *, int);
|
||||
|
||||
#define CRYPT_BUFFER_SIZE (IRCD_BUFFER_SIZE - 50) /* Make this less than
|
||||
* the trasmittable
|
||||
* buffer */
|
||||
/*
|
||||
* Crypt: the crypt list structure, consists of the nickname, and the
|
||||
* encryption key
|
||||
*/
|
||||
typedef struct CryptStru
|
||||
{
|
||||
struct CryptStru *next;
|
||||
char *nick;
|
||||
char *key;
|
||||
} Crypt;
|
||||
|
||||
/* crypt_list: the list of nicknames and encryption keys */
|
||||
static Crypt *crypt_list = NULL;
|
||||
|
||||
/*
|
||||
* add_to_crypt: adds the nickname and key pair to the crypt_list. If the
|
||||
* nickname is already in the list, then the key is changed the the supplied
|
||||
* key.
|
||||
*/
|
||||
static void add_to_crypt(char *nick, char *key)
|
||||
{
|
||||
Crypt *new;
|
||||
|
||||
if ((new = (Crypt *) remove_from_list((List **) &crypt_list, nick)) != NULL)
|
||||
{
|
||||
new_free(&(new->nick));
|
||||
new_free(&(new->key));
|
||||
new_free((char **)&new);
|
||||
}
|
||||
new = (Crypt *) new_malloc(sizeof(Crypt));
|
||||
malloc_strcpy(&(new->nick), nick);
|
||||
malloc_strcpy(&(new->key), key);
|
||||
add_to_list((List **) &crypt_list, (List *) new);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_crypt: removes the given nickname from the crypt_list, returning 0
|
||||
* if successful, and 1 if not (because the nickname wasn't in the list)
|
||||
*/
|
||||
static int remove_crypt(char *nick)
|
||||
{
|
||||
Crypt *tmp;
|
||||
|
||||
if ((tmp = (Crypt *) list_lookup((List **) &crypt_list, nick, !USE_WILDCARDS, REMOVE_FROM_LIST)) != NULL)
|
||||
{
|
||||
new_free(&(tmp->nick));
|
||||
new_free(&(tmp->key));
|
||||
new_free((char **)&tmp);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* is_crypted: looks up nick in the crypt_list and returns the encryption key
|
||||
* if found in the list. If not found in the crypt_list, null is returned.
|
||||
*/
|
||||
char * is_crypted(char *nick)
|
||||
{
|
||||
Crypt *tmp;
|
||||
|
||||
if (!crypt_list)
|
||||
return NULL;
|
||||
if ((tmp = (Crypt *) list_lookup((List **) &crypt_list, nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)) != NULL)
|
||||
return (tmp->key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* encrypt_cmd: the ENCRYPT command. Adds the given nickname and key to the
|
||||
* encrypt list, or removes it, or list the list, you know.
|
||||
*/
|
||||
BUILT_IN_COMMAND(encrypt_cmd)
|
||||
{
|
||||
char *nick,
|
||||
*key;
|
||||
|
||||
if ((nick = next_arg(args, &args)) != NULL)
|
||||
{
|
||||
if ((key = next_arg(args, &args)) != NULL)
|
||||
{
|
||||
add_to_crypt(nick, key);
|
||||
say("%s added to the crypt with key %s", nick, key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (remove_crypt(nick))
|
||||
say("No such nickname in the crypt: %s", nick);
|
||||
else
|
||||
say("%s removed from the crypt", nick);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (crypt_list)
|
||||
{
|
||||
Crypt *tmp;
|
||||
|
||||
say("The crypt:");
|
||||
for (tmp = crypt_list; tmp; tmp = tmp->next)
|
||||
put_it("%s with key %s", tmp->nick, tmp->key);
|
||||
}
|
||||
else
|
||||
say("The crypt is empty");
|
||||
}
|
||||
}
|
||||
|
||||
extern void BX_my_encrypt (char *str, int len, char *key)
|
||||
{
|
||||
int key_len,
|
||||
key_pos,
|
||||
i;
|
||||
char mix,
|
||||
tmp;
|
||||
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
key_len = strlen(key);
|
||||
key_pos = 0;
|
||||
mix = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tmp = str[i];
|
||||
str[i] = mix ^ tmp ^ key[key_pos];
|
||||
mix ^= tmp;
|
||||
key_pos = (key_pos + 1) % key_len;
|
||||
}
|
||||
str[i] = (char) 0;
|
||||
}
|
||||
|
||||
extern void BX_my_decrypt(char *str, int len, char *key)
|
||||
{
|
||||
int key_len,
|
||||
key_pos,
|
||||
i;
|
||||
char mix,
|
||||
tmp;
|
||||
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
key_len = strlen(key);
|
||||
key_pos = 0;
|
||||
/* mix = key[key_len-1]; */
|
||||
mix = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tmp = mix ^ str[i] ^ key[key_pos];
|
||||
str[i] = tmp;
|
||||
mix ^= tmp;
|
||||
key_pos = (key_pos + 1) % key_len;
|
||||
}
|
||||
str[i] = (char) 0;
|
||||
}
|
||||
|
||||
static char *do_crypt(char *str, char *key, int flag)
|
||||
{
|
||||
int c;
|
||||
char *ptr = NULL;
|
||||
|
||||
c = strlen(str);
|
||||
if (flag)
|
||||
{
|
||||
my_encrypt(str, c, key);
|
||||
ptr = ctcp_quote_it(str, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = ctcp_unquote_it(str, &c);
|
||||
my_decrypt(ptr, c, key);
|
||||
}
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* crypt_msg: Executes the encryption program on the given string with the
|
||||
* given key. If flag is true, the string is encrypted and the returned
|
||||
* string is ready to be sent over irc. If flag is false, the string is
|
||||
* decrypted and the returned string should be readable
|
||||
*/
|
||||
char *crypt_msg(char *str, char *key)
|
||||
{
|
||||
char buffer[CRYPT_BUFFER_SIZE + 1];
|
||||
char thing[6] = "";
|
||||
char *ptr;
|
||||
|
||||
sprintf(thing, "%cSED ", CTCP_DELIM_CHAR);
|
||||
*buffer = (char) 0;
|
||||
if ((ptr = do_crypt(str, key, 1)))
|
||||
{
|
||||
strmcat(buffer, thing, CRYPT_BUFFER_SIZE);
|
||||
strmcat(buffer, ptr, CRYPT_BUFFER_SIZE-1);
|
||||
strmcat(buffer, CTCP_DELIM_STR, CRYPT_BUFFER_SIZE);
|
||||
new_free(&ptr);
|
||||
}
|
||||
else
|
||||
strmcat(buffer, str, CRYPT_BUFFER_SIZE);
|
||||
|
||||
return (m_strdup(buffer));
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a CTCP SED argument 'str', it attempts to unscramble the text
|
||||
* into something more sane. If the 'key' is not the one used to scramble
|
||||
* the text, the results are unpredictable. This is probably the point.
|
||||
*
|
||||
* Note that the retval MUST be at least 'BIG_BUFFER_SIZE + 1'. This is
|
||||
* not an oversight -- the retval is passed is to do_ctcp() which requires
|
||||
* a big buffer to scratch around (The decrypted text could be a CTCP UTC
|
||||
* which could expand to a larger string of text.)
|
||||
*/
|
||||
char *decrypt_msg (char *str, char *key)
|
||||
{
|
||||
char *buffer = (char *)new_malloc(BIG_BUFFER_SIZE + 1);
|
||||
char *ptr;
|
||||
|
||||
if ((ptr = do_crypt(str, key, 0)) != NULL)
|
||||
{
|
||||
strmcpy(buffer, ptr, CRYPT_BUFFER_SIZE);
|
||||
new_free(&ptr);
|
||||
}
|
||||
else
|
||||
strmcat(buffer, str, CRYPT_BUFFER_SIZE);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
1453
source/exec.c
Normal file
1453
source/exec.c
Normal file
File diff suppressed because it is too large
Load Diff
1901
source/expr.c
Normal file
1901
source/expr.c
Normal file
File diff suppressed because it is too large
Load Diff
1840
source/expr2.c
Normal file
1840
source/expr2.c
Normal file
File diff suppressed because it is too large
Load Diff
288
source/files.c
Normal file
288
source/files.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* files.c -- allows you to read/write files. Wow.
|
||||
*
|
||||
* (C) 1995 Jeremy Nelson (ESL)
|
||||
* See the COPYRIGHT file for more information
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: files.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(files_c)
|
||||
#include "ircaux.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
/* Here's the plan.
|
||||
* You want to open a file.. you can READ it or you can WRITE it.
|
||||
* unix files can be read/written, but its not the way you expect.
|
||||
* so we will only alllow one or the other. If you try to write to
|
||||
* read only file, it punts, and if you try to read a writable file,
|
||||
* you get a null.
|
||||
*
|
||||
* New functions: open(FILENAME <type>)
|
||||
* <type> is 0 for read, 1 for write, 0 is default.
|
||||
* Returns fd of opened file, -1 on error
|
||||
* read (fd)
|
||||
* Returns line for given fd, as long as fd is
|
||||
* opened via the open() call, -1 on error
|
||||
* write (fd text)
|
||||
* Writes the text to the file pointed to by fd.
|
||||
* Returns the number of bytes written, -1 on error
|
||||
* close (fd)
|
||||
* closes file for given fd
|
||||
* Returns 0 on OK, -1 on error
|
||||
* eof (fd)
|
||||
* Returns 1 if fd is at EOF, 0 if not. -1 on error
|
||||
*/
|
||||
|
||||
struct FILE___ {
|
||||
FILE *file;
|
||||
struct FILE___ *next;
|
||||
};
|
||||
typedef struct FILE___ File;
|
||||
|
||||
static File *FtopEntry = NULL;
|
||||
|
||||
File *new_file (void)
|
||||
{
|
||||
File *tmp = FtopEntry;
|
||||
File *tmpfile = (File *)new_malloc(sizeof(File));
|
||||
|
||||
if (FtopEntry == NULL)
|
||||
FtopEntry = tmpfile;
|
||||
else
|
||||
{
|
||||
while (tmp->next)
|
||||
tmp = tmp->next;
|
||||
tmp->next = tmpfile;
|
||||
}
|
||||
return tmpfile;
|
||||
}
|
||||
|
||||
void remove_file (File *file)
|
||||
{
|
||||
File *tmp = FtopEntry;
|
||||
|
||||
if (file == FtopEntry)
|
||||
FtopEntry = file->next;
|
||||
else
|
||||
{
|
||||
while (tmp->next && tmp->next != file)
|
||||
tmp = tmp->next;
|
||||
if (tmp->next)
|
||||
tmp->next = tmp->next->next;
|
||||
}
|
||||
fclose(file->file);
|
||||
new_free((char **)&file);
|
||||
}
|
||||
|
||||
|
||||
int open_file_for_read (char *filename)
|
||||
{
|
||||
char *dummy_filename = NULL;
|
||||
FILE *file;
|
||||
|
||||
malloc_strcpy(&dummy_filename, filename);
|
||||
file = uzfopen(&dummy_filename, ".", 0);
|
||||
new_free(&dummy_filename);
|
||||
if (file)
|
||||
{
|
||||
File *nfs = new_file();
|
||||
nfs->file = file;
|
||||
nfs->next = NULL;
|
||||
return fileno(file);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int open_file_for_write (char *filename)
|
||||
{
|
||||
/* patch by Scott H Kilau so expand_twiddle works */
|
||||
char *expand = NULL;
|
||||
FILE *file;
|
||||
|
||||
if (!(expand = expand_twiddle(filename)))
|
||||
malloc_strcpy(&expand, filename);
|
||||
file = fopen(expand, "a");
|
||||
new_free(&expand);
|
||||
if (file)
|
||||
{
|
||||
File *nfs = new_file();
|
||||
nfs->file = file;
|
||||
nfs->next = NULL;
|
||||
return fileno(file);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int open_file_for_bwrite (char *filename)
|
||||
{
|
||||
/* patch by Scott H Kilau so expand_twiddle works */
|
||||
char *expand = NULL;
|
||||
FILE *file;
|
||||
|
||||
if (!(expand = expand_twiddle(filename)))
|
||||
malloc_strcpy(&expand, filename);
|
||||
file = fopen(expand, "wb");
|
||||
new_free(&expand);
|
||||
if (file)
|
||||
{
|
||||
File *nfs = new_file();
|
||||
nfs->file = file;
|
||||
nfs->next = NULL;
|
||||
return fileno(file);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
File *lookup_file (int fd)
|
||||
{
|
||||
File *ptr = FtopEntry;
|
||||
|
||||
while (ptr)
|
||||
{
|
||||
if (fileno(ptr->file) == fd)
|
||||
return ptr;
|
||||
else
|
||||
ptr = ptr -> next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int file_write (int fd, char *stuff)
|
||||
{
|
||||
File *ptr = lookup_file(fd);
|
||||
int ret;
|
||||
if (!ptr)
|
||||
return -1;
|
||||
ret = fprintf(ptr->file, "%s\n", stuff);
|
||||
fflush(ptr->file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int file_writeb (int fd, char *stuff)
|
||||
{
|
||||
File *ptr = lookup_file(fd);
|
||||
int ret;
|
||||
if (!ptr)
|
||||
return -1;
|
||||
ret = fwrite(stuff, 1, strlen(stuff), ptr->file);
|
||||
fflush(ptr->file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *file_read (int fd)
|
||||
{
|
||||
File *ptr = lookup_file(fd);
|
||||
if (!ptr)
|
||||
return m_strdup(empty_string);
|
||||
else
|
||||
{
|
||||
char blah[10240];
|
||||
if ((fgets(blah, 10239, ptr->file)))
|
||||
chop(blah, 1);
|
||||
else
|
||||
blah[0] = 0;
|
||||
return m_strdup(blah);
|
||||
}
|
||||
}
|
||||
|
||||
char *file_readb (int fd, int numb)
|
||||
{
|
||||
File *ptr = lookup_file(fd);
|
||||
if (!ptr)
|
||||
return m_strdup(empty_string);
|
||||
else
|
||||
{
|
||||
char *blah = (char *)new_malloc(numb+1);
|
||||
if ((fread(blah, 1, numb, ptr->file)))
|
||||
blah[numb] = 0;
|
||||
else
|
||||
blah[0] = 0;
|
||||
return blah;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int file_eof (int fd)
|
||||
{
|
||||
File *ptr = lookup_file (fd);
|
||||
if (!ptr)
|
||||
return -1;
|
||||
else
|
||||
return feof(ptr->file);
|
||||
}
|
||||
|
||||
int file_close (int fd)
|
||||
{
|
||||
File *ptr = lookup_file (fd);
|
||||
if (!ptr)
|
||||
return -1;
|
||||
else
|
||||
remove_file (ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** by: Walter Bright via Usenet C newsgroup
|
||||
**
|
||||
** modified by: Bob Stout based on a recommendation by Ray Gardner
|
||||
**
|
||||
** There is no point in going to asm to get high speed file copies. Since it
|
||||
** is inherently disk-bound, there is no sense (unless tiny code size is
|
||||
** the goal). Here's a C version that you'll find is as fast as any asm code
|
||||
** for files larger than a few bytes (the trick is to use large disk buffers):
|
||||
*/
|
||||
|
||||
int file_copy(int from,int to)
|
||||
{
|
||||
int bufsiz;
|
||||
if (from < 0)
|
||||
return 1;
|
||||
if (to < 0)
|
||||
return 1;
|
||||
|
||||
if (!fork())
|
||||
{
|
||||
/* Use the largest buffer we can get */
|
||||
for (bufsiz = 0x4000; bufsiz >= 128; bufsiz >>= 1)
|
||||
{
|
||||
register char *buffer;
|
||||
|
||||
buffer = (char *) malloc(bufsiz);
|
||||
if (buffer)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
register int n;
|
||||
|
||||
n = read(from,buffer,bufsiz);
|
||||
if (n == -1) /* if error */
|
||||
break;
|
||||
if (n == 0) /* if end of file */
|
||||
{
|
||||
free(buffer);
|
||||
_exit(0);
|
||||
}
|
||||
if (n != write(to,buffer,(unsigned) n))
|
||||
break;
|
||||
}
|
||||
free(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int file_valid (int fd)
|
||||
{
|
||||
if (lookup_file(fd))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
610
source/flood.c
Normal file
610
source/flood.c
Normal file
@@ -0,0 +1,610 @@
|
||||
/*
|
||||
* flood.c: handle channel flooding.
|
||||
*
|
||||
* This attempts to give you some protection from flooding. Basically, it keeps
|
||||
* track of how far apart (timewise) messages come in from different people.
|
||||
* If a single nickname sends more than 3 messages in a row in under a
|
||||
* second, this is considered flooding. It then activates the ON FLOOD with
|
||||
* the nickname and type (appropriate for use with IGNORE).
|
||||
*
|
||||
* Thanks to Tomi Ollila <f36664r@puukko.hut.fi> for this one.
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: flood.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(flood_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "alias.h"
|
||||
#include "hook.h"
|
||||
#include "ircaux.h"
|
||||
#include "ignore.h"
|
||||
#include "flood.h"
|
||||
#include "vars.h"
|
||||
#include "output.h"
|
||||
#include "list.h"
|
||||
#include "misc.h"
|
||||
#include "server.h"
|
||||
#include "userlist.h"
|
||||
#include "timer.h"
|
||||
#include "ignore.h"
|
||||
#include "status.h"
|
||||
#include "hash2.h"
|
||||
#include "cset.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
static char *ignore_types[] =
|
||||
{
|
||||
"",
|
||||
"MSG",
|
||||
"PUBLIC",
|
||||
"NOTICE",
|
||||
"WALL",
|
||||
"WALLOP",
|
||||
"CTCP",
|
||||
"INVITE",
|
||||
"CDCC",
|
||||
"ACTION",
|
||||
"NICK",
|
||||
"DEOP",
|
||||
"KICK",
|
||||
"JOIN"
|
||||
};
|
||||
|
||||
#define FLOOD_HASHSIZE 31
|
||||
HashEntry no_flood_list[FLOOD_HASHSIZE];
|
||||
HashEntry flood_list[FLOOD_HASHSIZE];
|
||||
|
||||
static int remove_oldest_flood_hashlist(HashEntry *, time_t, int);
|
||||
|
||||
|
||||
|
||||
|
||||
extern char *FromUserHost;
|
||||
extern unsigned int window_display;
|
||||
extern int from_server;
|
||||
|
||||
static double allow_flood = 0.0;
|
||||
static double this_flood = 0.0;
|
||||
|
||||
#define NO_RESET 0
|
||||
#define RESET 1
|
||||
|
||||
char *get_flood_types(unsigned int type)
|
||||
{
|
||||
int x = 0;
|
||||
while (type)
|
||||
{
|
||||
type = type >> 1;
|
||||
x++;
|
||||
}
|
||||
return ignore_types[x];
|
||||
}
|
||||
|
||||
#if 0
|
||||
int get_flood_rate(int type, ChannelList * channel)
|
||||
{
|
||||
int flood_rate = get_int_var(FLOOD_RATE_VAR);
|
||||
if (channel)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case JOIN_FLOOD:
|
||||
flood_rate = get_cset_int_var(channel->csets, JOINFLOOD_TIME_CSET);
|
||||
break;
|
||||
case PUBLIC_FLOOD:
|
||||
flood_rate = get_cset_int_var(channel->csets, PUBFLOOD_TIME_CSET);
|
||||
break;
|
||||
case NICK_FLOOD:
|
||||
flood_rate = get_cset_int_var(channel->csets, NICKFLOOD_TIME_CSET);
|
||||
break;
|
||||
case KICK_FLOOD:
|
||||
flood_rate = get_cset_int_var(channel->csets, KICKFLOOD_TIME_CSET);
|
||||
break;
|
||||
case DEOP_FLOOD:
|
||||
flood_rate = get_cset_int_var(channel->csets, DEOPFLOOD_TIME_CSET);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case CDCC_FLOOD:
|
||||
flood_rate = get_int_var(CDCC_FLOOD_RATE_VAR);
|
||||
break;
|
||||
case CTCP_FLOOD:
|
||||
flood_rate = get_int_var(CTCP_FLOOD_RATE_VAR);
|
||||
case CTCP_ACTION_FLOOD:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flood_rate;
|
||||
}
|
||||
|
||||
int get_flood_count(int type, ChannelList * channel)
|
||||
{
|
||||
int flood_count = get_int_var(FLOOD_AFTER_VAR);
|
||||
if (channel) {
|
||||
switch(type)
|
||||
{
|
||||
case JOIN_FLOOD:
|
||||
flood_count = get_cset_int_var(channel->csets, KICK_ON_JOINFLOOD_CSET);
|
||||
break;
|
||||
case PUBLIC_FLOOD:
|
||||
flood_count = get_cset_int_var(channel->csets, KICK_ON_PUBFLOOD_CSET);
|
||||
break;
|
||||
case NICK_FLOOD:
|
||||
flood_count = get_cset_int_var(channel->csets, KICK_ON_NICKFLOOD_CSET);
|
||||
break;
|
||||
case KICK_FLOOD:
|
||||
flood_count = get_cset_int_var(channel->csets, KICK_ON_KICKFLOOD_CSET);
|
||||
break;
|
||||
case DEOP_FLOOD:
|
||||
flood_count = get_cset_int_var(channel->csets, KICK_ON_DEOPFLOOD_CSET);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case CDCC_FLOOD:
|
||||
flood_count = get_int_var(CDCC_FLOOD_AFTER_VAR);
|
||||
break;
|
||||
case CTCP_FLOOD:
|
||||
flood_count = get_int_var(CTCP_FLOOD_AFTER_VAR);
|
||||
case CTCP_ACTION_FLOOD:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flood_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
void get_flood_val(ChannelList *chan, int type, int *flood_count, int *flood_rate)
|
||||
{
|
||||
*flood_count = get_int_var(FLOOD_AFTER_VAR);
|
||||
*flood_rate = get_int_var(FLOOD_RATE_VAR);
|
||||
if (chan)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case JOIN_FLOOD:
|
||||
*flood_count = get_cset_int_var(chan->csets, KICK_ON_JOINFLOOD_CSET);
|
||||
*flood_rate = get_cset_int_var(chan->csets, JOINFLOOD_TIME_CSET);
|
||||
break;
|
||||
case PUBLIC_FLOOD:
|
||||
*flood_count = get_cset_int_var(chan->csets, KICK_ON_PUBFLOOD_CSET);
|
||||
*flood_rate = get_cset_int_var(chan->csets, PUBFLOOD_TIME_CSET);
|
||||
break;
|
||||
case NICK_FLOOD:
|
||||
*flood_count = get_cset_int_var(chan->csets, KICK_ON_NICKFLOOD_CSET);
|
||||
*flood_rate = get_cset_int_var(chan->csets, NICKFLOOD_TIME_CSET);
|
||||
break;
|
||||
case KICK_FLOOD:
|
||||
*flood_count = get_cset_int_var(chan->csets, KICK_ON_KICKFLOOD_CSET);
|
||||
*flood_rate = get_cset_int_var(chan->csets, KICKFLOOD_TIME_CSET);
|
||||
break;
|
||||
case DEOP_FLOOD:
|
||||
*flood_count = get_cset_int_var(chan->csets, KICK_ON_DEOPFLOOD_CSET);
|
||||
*flood_rate = get_cset_int_var(chan->csets, DEOPFLOOD_TIME_CSET);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case CDCC_FLOOD:
|
||||
*flood_count = get_int_var(CDCC_FLOOD_AFTER_VAR);
|
||||
*flood_rate = get_int_var(CDCC_FLOOD_RATE_VAR);
|
||||
break;
|
||||
case CTCP_FLOOD:
|
||||
*flood_count = get_int_var(CTCP_FLOOD_AFTER_VAR);
|
||||
*flood_rate = get_int_var(CTCP_FLOOD_RATE_VAR);
|
||||
case CTCP_ACTION_FLOOD:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int set_flood(int type, time_t flood_time, int reset, NickList *tmpnick)
|
||||
{
|
||||
if (!tmpnick)
|
||||
return 0;
|
||||
switch(type)
|
||||
{
|
||||
case JOIN_FLOOD:
|
||||
if (reset == RESET)
|
||||
{
|
||||
tmpnick->joincount = 1;
|
||||
tmpnick->jointime = flood_time;
|
||||
} else tmpnick->joincount++;
|
||||
break;
|
||||
case PUBLIC_FLOOD:
|
||||
if (reset == RESET)
|
||||
{
|
||||
tmpnick->floodcount = 1;
|
||||
tmpnick->floodtime = tmpnick->idle_time = flood_time;
|
||||
} else tmpnick->floodcount++;
|
||||
break;
|
||||
case NICK_FLOOD:
|
||||
if (reset == RESET)
|
||||
{
|
||||
tmpnick->nickcount = 1;
|
||||
tmpnick->nicktime = flood_time;
|
||||
} else tmpnick->nickcount++;
|
||||
break;
|
||||
case KICK_FLOOD:
|
||||
if (reset == RESET)
|
||||
{
|
||||
tmpnick->kickcount = 1;
|
||||
tmpnick->kicktime = flood_time;
|
||||
} else tmpnick->kickcount++;
|
||||
break;
|
||||
case DEOP_FLOOD:
|
||||
if (reset == RESET)
|
||||
{
|
||||
tmpnick->dopcount = 1;
|
||||
tmpnick->doptime = flood_time;
|
||||
} else tmpnick->dopcount++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BX_is_other_flood(ChannelList *channel, NickList *tmpnick, int type, int *t_flood)
|
||||
{
|
||||
time_t diff = 0, flood_time = 0;
|
||||
int doit = 0;
|
||||
int count = 0;
|
||||
int flood_rate = 0, flood_count = 0;
|
||||
|
||||
flood_time = now;
|
||||
|
||||
|
||||
if (!channel || !tmpnick)
|
||||
return 0;
|
||||
if (isme(tmpnick->nick))
|
||||
return 0;
|
||||
if (find_name_in_genericlist(tmpnick->nick, no_flood_list, FLOOD_HASHSIZE, 0))
|
||||
return 0;
|
||||
set_flood(type, flood_time, NO_RESET, tmpnick);
|
||||
switch(type)
|
||||
{
|
||||
case JOIN_FLOOD:
|
||||
if (!get_cset_int_var(channel->csets, JOINFLOOD_CSET))
|
||||
break;
|
||||
diff = flood_time - tmpnick->jointime;
|
||||
count = tmpnick->joincount;
|
||||
doit = 1;
|
||||
break;
|
||||
case PUBLIC_FLOOD:
|
||||
if (!get_cset_int_var(channel->csets, PUBFLOOD_CSET))
|
||||
break;
|
||||
diff = flood_time - tmpnick->floodtime;
|
||||
count = tmpnick->floodcount;
|
||||
doit = 1;
|
||||
break;
|
||||
case NICK_FLOOD:
|
||||
if (!get_cset_int_var(channel->csets, NICKFLOOD_CSET))
|
||||
break;
|
||||
diff = flood_time - tmpnick->nicktime;
|
||||
count = tmpnick->nickcount;
|
||||
doit = 1;
|
||||
break;
|
||||
case DEOP_FLOOD:
|
||||
if (!get_cset_int_var(channel->csets, DEOPFLOOD_CSET))
|
||||
break;
|
||||
diff = flood_time - tmpnick->doptime;
|
||||
count = tmpnick->dopcount;
|
||||
doit = 1;
|
||||
break;
|
||||
case KICK_FLOOD:
|
||||
if (!get_cset_int_var(channel->csets, KICKFLOOD_CSET))
|
||||
break;
|
||||
diff = flood_time - tmpnick->kicktime;
|
||||
count = tmpnick->kickcount;
|
||||
doit = 1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
if (doit)
|
||||
{
|
||||
int is_user = 0;
|
||||
if (!get_int_var(FLOOD_PROTECTION_VAR))
|
||||
return 0;
|
||||
get_flood_val(channel, type, &flood_count, &flood_rate);
|
||||
if ((tmpnick->userlist && (tmpnick->userlist->flags & ADD_FLOOD)))
|
||||
is_user = 1;
|
||||
if (!is_user && (count >= flood_count))
|
||||
{
|
||||
int flooded = 0;
|
||||
if (count >= flood_count)
|
||||
{
|
||||
if (!diff || (flood_rate && (diff < flood_rate)))
|
||||
{
|
||||
*t_flood = diff;
|
||||
flooded = 1;
|
||||
do_hook(FLOOD_LIST, "%s %s %s %s", tmpnick->nick, get_flood_types(type),channel?channel->channel:zero, tmpnick->host);
|
||||
}
|
||||
set_flood(type, flood_time, RESET, tmpnick);
|
||||
return flooded;
|
||||
}
|
||||
else if (diff > flood_rate)
|
||||
set_flood(type, flood_time, RESET, tmpnick);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check_flooding: This checks for message flooding of the type specified for
|
||||
* the given nickname. This is described above. This will return 0 if no
|
||||
* flooding took place, or flooding is not being monitored from a certain
|
||||
* person. It will return 1 if flooding is being check for someone and an ON
|
||||
* FLOOD is activated.
|
||||
*/
|
||||
|
||||
int BX_check_flooding(char *nick, int type, char *line, char *channel)
|
||||
{
|
||||
static int users = 0,
|
||||
pos = 0;
|
||||
time_t flood_time = now,
|
||||
diff = 0;
|
||||
|
||||
Flooding *tmp;
|
||||
int flood_rate,
|
||||
flood_count;
|
||||
|
||||
|
||||
if (!(users = get_int_var(FLOOD_USERS_VAR)) || !*FromUserHost)
|
||||
return 1;
|
||||
if (find_name_in_genericlist(nick, no_flood_list, FLOOD_HASHSIZE, 0))
|
||||
return 1;
|
||||
if (!(tmp = find_name_in_floodlist(nick, FromUserHost, flood_list, FLOOD_HASHSIZE, 0)))
|
||||
{
|
||||
if (pos >= users)
|
||||
{
|
||||
pos -= remove_oldest_flood_hashlist(&flood_list[0], 0, (users + 1 - pos));
|
||||
}
|
||||
tmp = add_name_to_floodlist(nick, FromUserHost, channel, flood_list, FLOOD_HASHSIZE);
|
||||
tmp->type = type;
|
||||
tmp->cnt = 1;
|
||||
tmp->start = flood_time;
|
||||
tmp->flood = 0;
|
||||
pos++;
|
||||
return 1;
|
||||
}
|
||||
if (!(tmp->type & type))
|
||||
{
|
||||
tmp->type |= type;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
flood_count = get_flood_count(type, NULL); /* FLOOD_AFTER_VAR */
|
||||
flood_rate = get_flood_rate(type, NULL); /* FLOOD_RATE_VAR */
|
||||
#endif
|
||||
get_flood_val(NULL, type, &flood_count, &flood_rate);
|
||||
if (!flood_count || !flood_rate)
|
||||
return 1;
|
||||
tmp->cnt++;
|
||||
if (tmp->cnt > flood_count)
|
||||
{
|
||||
int ret;
|
||||
diff = flood_time - tmp->start;
|
||||
if (diff != 0)
|
||||
this_flood = (double)tmp->cnt / (double)diff;
|
||||
else
|
||||
this_flood = 0;
|
||||
allow_flood = (double)flood_count / (double)flood_rate;
|
||||
if (!diff || !this_flood || (this_flood > allow_flood))
|
||||
{
|
||||
if (tmp->flood == 0)
|
||||
{
|
||||
tmp->flood = 1;
|
||||
if ((ret = do_hook(FLOOD_LIST, "%s %s %s %s", nick, get_flood_types(type),channel?channel:zero, line)) != 1)
|
||||
return ret;
|
||||
switch(type)
|
||||
{
|
||||
case WALL_FLOOD:
|
||||
case MSG_FLOOD:
|
||||
case NOTICE_FLOOD:
|
||||
case CDCC_FLOOD:
|
||||
case CTCP_FLOOD:
|
||||
if (flood_prot(nick, FromUserHost, get_flood_types(type), type, get_int_var(IGNORE_TIME_VAR), channel))
|
||||
return 0;
|
||||
break;
|
||||
case CTCP_ACTION_FLOOD:
|
||||
if (flood_prot(nick, FromUserHost, get_flood_types(CTCP_FLOOD), type, get_int_var(IGNORE_TIME_VAR), channel))
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (get_int_var(FLOOD_WARNING_VAR))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_FLOOD_FSET), "%s %s %s %s %s", update_clock(GET_TIME), get_flood_types(type), nick, FromUserHost, channel?channel:"unknown"));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp->flood = 0;
|
||||
tmp->cnt = 1;
|
||||
tmp->start = flood_time;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void check_ctcp_ban_flood(char *channel, char *nick)
|
||||
{
|
||||
NickList *Nick = NULL;
|
||||
ChannelList *chan = NULL;
|
||||
for (chan = get_server_channels(from_server); chan; chan = chan->next)
|
||||
if ((Nick = find_nicklist_in_channellist(nick, chan, 0)))
|
||||
break;
|
||||
if (chan && chan->chop && get_cset_int_var(chan->csets, CTCP_FLOOD_BAN_CSET) && Nick)
|
||||
{
|
||||
if (!Nick->userlist || (Nick->userlist && !(Nick->userlist->flags & ADD_FLOOD)))
|
||||
{
|
||||
if (!nick_isop(Nick) || get_cset_int_var(chan->csets, KICK_OPS_CSET))
|
||||
{
|
||||
char *ban, *u, *h;
|
||||
u = alloca(strlen(Nick->host)+1);
|
||||
strcpy(u, Nick->host);
|
||||
h = strchr(u, '@');
|
||||
*h++ = 0;
|
||||
ban = ban_it(Nick->nick, u, h, Nick->ip);
|
||||
if (!ban_is_on_channel(ban, chan) && !eban_is_on_channel(ban, chan))
|
||||
send_to_server("MODE %s +b %s", chan->channel, ban);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BX_flood_prot (char *nick, char *userhost, char *type, int ctcp_type, int ignoretime, char *channel)
|
||||
{
|
||||
ChannelList *chan;
|
||||
NickList *Nick;
|
||||
char tmp[BIG_BUFFER_SIZE+1];
|
||||
char *uh;
|
||||
int old_window_display;
|
||||
int kick_on_flood = 1;
|
||||
|
||||
if ((ctcp_type == CDCC_FLOOD || ctcp_type == CTCP_FLOOD || ctcp_type == CTCP_ACTION_FLOOD) && !get_int_var(CTCP_FLOOD_PROTECTION_VAR))
|
||||
return 0;
|
||||
else if (!get_int_var(FLOOD_PROTECTION_VAR))
|
||||
return 0;
|
||||
else if (!my_stricmp(nick, get_server_nickname(from_server)))
|
||||
return 0;
|
||||
switch (ctcp_type)
|
||||
{
|
||||
case WALL_FLOOD:
|
||||
case MSG_FLOOD:
|
||||
break;
|
||||
case NOTICE_FLOOD:
|
||||
break;
|
||||
case PUBLIC_FLOOD:
|
||||
if (channel)
|
||||
{
|
||||
if ((chan = lookup_channel(channel, from_server, 0)))
|
||||
{
|
||||
kick_on_flood = get_cset_int_var(chan->csets, PUBFLOOD_CSET);
|
||||
if (kick_on_flood && (Nick = find_nicklist_in_channellist(nick, chan, 0)))
|
||||
{
|
||||
if (chan->chop && (!Nick->userlist || (Nick->userlist && !(Nick->userlist->flags & ADD_FLOOD))))
|
||||
if (!nick_isop(Nick) || get_cset_int_var(chan->csets, KICK_OPS_CSET))
|
||||
send_to_server("KICK %s %s :\002%s\002 flooder", chan->channel, nick, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CTCP_FLOOD:
|
||||
case CTCP_ACTION_FLOOD:
|
||||
check_ctcp_ban_flood(channel, nick);
|
||||
default:
|
||||
if (get_int_var(FLOOD_KICK_VAR) && kick_on_flood && channel)
|
||||
{
|
||||
for (chan = get_server_channels(from_server); chan; chan = chan->next)
|
||||
{
|
||||
if (chan->chop && (Nick = find_nicklist_in_channellist(nick, chan, 0)))
|
||||
{
|
||||
if ((!Nick->userlist || (Nick->userlist && !(Nick->userlist->flags & ADD_FLOOD))))
|
||||
if (!nick_isop(Nick) || get_cset_int_var(chan->csets, KICK_OPS_CSET))
|
||||
send_to_server("KICK %s %s :\002%s\002 flooder", chan->channel, nick, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ignoretime)
|
||||
return 0;
|
||||
uh = clear_server_flags(userhost);
|
||||
sprintf(tmp, "*!*%s", uh);
|
||||
old_window_display = window_display;
|
||||
window_display = 0;
|
||||
ignore_nickname(tmp, ignore_type(type, strlen(type)), 0);
|
||||
window_display = old_window_display;
|
||||
sprintf(tmp, "%d ^IGNORE *!*%s NONE", ignoretime, uh);
|
||||
timercmd("TIMER", tmp, NULL, NULL);
|
||||
bitchsay("Auto-ignoring %s for %d minutes [\002%s\002 flood]", nick, ignoretime/60, type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int remove_oldest_flood_hashlist(HashEntry *list, time_t timet, int count)
|
||||
{
|
||||
Flooding *ptr;
|
||||
register time_t t;
|
||||
int total = 0;
|
||||
register unsigned long x;
|
||||
t = now;
|
||||
if (!count)
|
||||
{
|
||||
for (x = 0; x < FLOOD_HASHSIZE; x++)
|
||||
{
|
||||
ptr = (Flooding *) (list + x)->list;
|
||||
if (!ptr || !*ptr->name)
|
||||
continue;
|
||||
while (ptr)
|
||||
{
|
||||
if ((ptr->start + timet) <= t)
|
||||
{
|
||||
if (!(ptr = find_name_in_floodlist(ptr->name, ptr->host, flood_list, FLOOD_HASHSIZE, 1)))
|
||||
continue;
|
||||
new_free(&(ptr->channel));
|
||||
new_free(&(ptr->name));
|
||||
new_free(&ptr->host);
|
||||
new_free((char **)&ptr);
|
||||
total++;
|
||||
ptr = (Flooding *) (list + x)->list;
|
||||
} else ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < FLOOD_HASHSIZE; x++)
|
||||
{
|
||||
Flooding *next = NULL;
|
||||
ptr = (Flooding *) (list + x)->list;
|
||||
if (!ptr || !*ptr->name)
|
||||
continue;
|
||||
while(ptr && count)
|
||||
{
|
||||
if ((ptr = find_name_in_floodlist(ptr->name, ptr->host, flood_list, FLOOD_HASHSIZE, 1)))
|
||||
{
|
||||
next = ptr->next;
|
||||
new_free(&(ptr->channel));
|
||||
new_free(&(ptr->name));
|
||||
new_free(&ptr->host);
|
||||
new_free((char **)&ptr);
|
||||
total++; count--;
|
||||
ptr = (Flooding *) (list + x)->list;
|
||||
ptr = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
void clean_flood_list()
|
||||
{
|
||||
remove_oldest_flood_hashlist(&flood_list[0], get_int_var(FLOOD_RATE_VAR)+1, 0);
|
||||
}
|
||||
1087
source/fset.c
Normal file
1087
source/fset.c
Normal file
File diff suppressed because it is too large
Load Diff
7414
source/functions.c
Normal file
7414
source/functions.c
Normal file
File diff suppressed because it is too large
Load Diff
435
source/funny.c
Normal file
435
source/funny.c
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* funny.c: Well, I put some stuff here and called it funny. So sue me.
|
||||
*
|
||||
* written by michael sandrof
|
||||
*
|
||||
* copyright(c) 1990
|
||||
*
|
||||
* see the copyright file, or do a help ircii copyright
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: funny.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(funny_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "ircaux.h"
|
||||
#include "hook.h"
|
||||
#include "vars.h"
|
||||
#include "funny.h"
|
||||
#include "names.h"
|
||||
#include "server.h"
|
||||
#include "lastlog.h"
|
||||
#include "ircterm.h"
|
||||
#include "output.h"
|
||||
#include "numbers.h"
|
||||
#include "parse.h"
|
||||
#include "status.h"
|
||||
#include "misc.h"
|
||||
#include "screen.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
static char *match_str = NULL;
|
||||
|
||||
static int funny_min;
|
||||
static int funny_max;
|
||||
static int funny_flags;
|
||||
|
||||
void funny_match(char *stuff)
|
||||
{
|
||||
malloc_strcpy(&match_str, stuff);
|
||||
}
|
||||
|
||||
void set_funny_flags(int min, int max, int flags)
|
||||
{
|
||||
funny_min = min;
|
||||
funny_max = max;
|
||||
funny_flags = flags;
|
||||
}
|
||||
|
||||
struct WideListInfoStru
|
||||
{
|
||||
char *channel;
|
||||
int users;
|
||||
};
|
||||
|
||||
typedef struct WideListInfoStru WideList;
|
||||
|
||||
static WideList **wide_list = NULL;
|
||||
static int wl_size = 0;
|
||||
static int wl_elements = 0;
|
||||
|
||||
static int funny_widelist_users (WideList **, WideList **);
|
||||
static int funny_widelist_names (WideList **, WideList **);
|
||||
|
||||
static int funny_widelist_users(WideList **left, WideList **right)
|
||||
{
|
||||
if ((**left).users > (**right).users)
|
||||
return -1;
|
||||
else if ((**right).users > (**left).users)
|
||||
return 1;
|
||||
else
|
||||
return my_stricmp((**left).channel, (**right).channel);
|
||||
}
|
||||
|
||||
static int funny_widelist_names(WideList **left, WideList **right)
|
||||
{
|
||||
int comp;
|
||||
|
||||
if (!(comp = my_stricmp((**left).channel, (**right).channel)))
|
||||
return comp;
|
||||
else if ((**left).users > (**right).users)
|
||||
return -1;
|
||||
else if ((**right).users > (**left).users)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void funny_print_widelist(void)
|
||||
{
|
||||
int i;
|
||||
char buffer1[BIG_BUFFER_SIZE];
|
||||
char buffer2[BIG_BUFFER_SIZE];
|
||||
char *ptr;
|
||||
|
||||
if (!wide_list)
|
||||
return;
|
||||
|
||||
if (funny_flags & FUNNY_NAME)
|
||||
qsort((void *) wide_list, wl_elements, sizeof(WideList *),
|
||||
(int (*) (const void *, const void *)) funny_widelist_names);
|
||||
else if (funny_flags & FUNNY_USERS)
|
||||
qsort((void *) wide_list, wl_elements, sizeof(WideList *),
|
||||
(int (*) (const void *, const void *)) funny_widelist_users);
|
||||
|
||||
set_display_target(NULL, LOG_CRAP);
|
||||
*buffer1 = '\0';
|
||||
for (i = 1; i < wl_elements; i++)
|
||||
{
|
||||
sprintf(buffer2, "%s(%d) ", wide_list[i]->channel,
|
||||
wide_list[i]->users);
|
||||
ptr = strchr(buffer1, '\0');
|
||||
if (strlen(buffer1) + strlen(buffer2) > current_term->TI_cols - 5)
|
||||
{
|
||||
if (do_hook(WIDELIST_LIST, "%s", buffer1))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_WIDELIST_FSET), "%s %s", update_clock(GET_TIME), buffer1));
|
||||
*buffer1 = 0;
|
||||
strcat(buffer1, buffer2);
|
||||
}
|
||||
else
|
||||
strcpy(ptr, buffer2);
|
||||
}
|
||||
if (*buffer1 && do_hook(WIDELIST_LIST, "%s", buffer1))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_WIDELIST_FSET), "%s %s", update_clock(GET_TIME), buffer1));
|
||||
|
||||
reset_display_target();
|
||||
for (i = 0; i < wl_elements; i++)
|
||||
{
|
||||
new_free(&wide_list[i]->channel);
|
||||
new_free((char **)&wide_list[i]);
|
||||
}
|
||||
new_free((char **)&wide_list);
|
||||
wl_elements = wl_size = 0;
|
||||
}
|
||||
|
||||
void funny_list(char *from, char **ArgList)
|
||||
{
|
||||
char *channel,
|
||||
*user_cnt,
|
||||
*line;
|
||||
WideList **new_list;
|
||||
int cnt;
|
||||
static char format[30];
|
||||
static int last_width = -1;
|
||||
|
||||
if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR))
|
||||
{
|
||||
if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0)
|
||||
snprintf(format, 25, "%%s %%-%u.%us %%-5s %%s", /*thing_ansi,*/
|
||||
(unsigned char) last_width,
|
||||
(unsigned char) last_width);
|
||||
else
|
||||
snprintf(format, 25, "%%s %%s %%-5s %%s"/*, thing_ansi*/);
|
||||
}
|
||||
channel = ArgList[0];
|
||||
user_cnt = ArgList[1];
|
||||
line = PasteArgs(ArgList, 2);
|
||||
if (funny_flags & FUNNY_TOPIC && !(line && *line))
|
||||
return;
|
||||
cnt = my_atol(user_cnt);
|
||||
if (funny_min && (cnt < funny_min))
|
||||
return;
|
||||
if (funny_max && (cnt > funny_max))
|
||||
return;
|
||||
if ((funny_flags & FUNNY_PRIVATE) && (*channel != '*'))
|
||||
return;
|
||||
if ((funny_flags & FUNNY_PUBLIC) && ((*channel == '*') || (*channel == '@')))
|
||||
return;
|
||||
if (match_str)
|
||||
{
|
||||
if (wild_match(match_str, channel) == 0)
|
||||
return;
|
||||
}
|
||||
if (funny_flags & FUNNY_WIDE)
|
||||
{
|
||||
if (wl_elements >= wl_size)
|
||||
{
|
||||
new_list = (WideList **) new_malloc(sizeof(WideList *) *
|
||||
(wl_size + 50));
|
||||
memset(new_list, 0, sizeof(WideList *) * (wl_size + 50));
|
||||
if (wl_size)
|
||||
memcpy(new_list, wide_list, sizeof(WideList *) * wl_size);
|
||||
wl_size += 50;
|
||||
new_free((char **)&wide_list);
|
||||
wide_list = new_list;
|
||||
}
|
||||
wide_list[wl_elements] = (WideList *)
|
||||
new_malloc(sizeof(WideList));
|
||||
wide_list[wl_elements]->channel = NULL;
|
||||
wide_list[wl_elements]->users = cnt;
|
||||
malloc_strcpy(&wide_list[wl_elements]->channel,
|
||||
(*channel != '*') ? channel : "Prv");
|
||||
wl_elements++;
|
||||
return;
|
||||
}
|
||||
set_display_target(channel, LOG_CRAP);
|
||||
if (do_hook(current_numeric, "%s %s %s %s", from, channel, user_cnt,
|
||||
line) && do_hook(LIST_LIST, "%s %s %s", channel, user_cnt, line))
|
||||
{
|
||||
if (channel && user_cnt)
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_LIST_FSET),"%s %s %s %s", update_clock(GET_TIME), *channel == '*'?"Prv":channel, user_cnt, line));
|
||||
}
|
||||
reset_display_target();
|
||||
}
|
||||
|
||||
void print_funny_names(char *line)
|
||||
{
|
||||
register char *t;
|
||||
int count = 0;
|
||||
char buffer[BIG_BUFFER_SIZE+1];
|
||||
char special = '\0';
|
||||
int cols = get_int_var(NAMES_COLUMNS_VAR);
|
||||
if (!cols)
|
||||
cols = 1;
|
||||
if (line && *line)
|
||||
{
|
||||
*buffer = 0;
|
||||
t = next_arg(line, &line);
|
||||
do {
|
||||
if (!count && fget_string_var(FORMAT_NAMES_BANNER_FSET))
|
||||
strcpy(buffer, convert_output_format(fget_string_var(FORMAT_NAMES_BANNER_FSET), NULL, NULL));
|
||||
if (*t == '@' || *t == '+' || *t == '~' || *t == '-')
|
||||
{
|
||||
special = *t;
|
||||
if (special == '+')
|
||||
strcat(buffer, convert_output_format(fget_string_var(FORMAT_NAMES_VOICECOLOR_FSET),"%c %s", special, ++t));
|
||||
else
|
||||
strcat(buffer, convert_output_format(fget_string_var(FORMAT_NAMES_OPCOLOR_FSET),"%c %s", special, ++t));
|
||||
}
|
||||
else
|
||||
strcat(buffer, convert_output_format(fget_string_var(FORMAT_NAMES_NICKCOLOR_FSET), "$ %s", t));
|
||||
strcat(buffer, space);
|
||||
if (count++ >= (cols - 1))
|
||||
{
|
||||
put_it("%s", buffer);
|
||||
*buffer = 0;
|
||||
count = 0;
|
||||
}
|
||||
} while ((t = next_arg(line, &line)));
|
||||
|
||||
if (buffer)
|
||||
put_it("%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void funny_namreply(char *from, char **Args)
|
||||
{
|
||||
char *type,
|
||||
*channel;
|
||||
static char format[40];
|
||||
static int last_width = -1;
|
||||
register char *ptr;
|
||||
register char *line;
|
||||
int user_count = 0;
|
||||
|
||||
PasteArgs(Args, 2);
|
||||
type = Args[0];
|
||||
channel = Args[1];
|
||||
line = Args[2];
|
||||
|
||||
/* protocol violation by server */
|
||||
if (!channel || !line)
|
||||
return;
|
||||
|
||||
ptr = line;
|
||||
while (*ptr)
|
||||
{
|
||||
while (*ptr && (*ptr != ' '))
|
||||
ptr++;
|
||||
user_count++;
|
||||
while (*ptr && (*ptr == ' '))
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (in_join_list(channel, from_server))
|
||||
{
|
||||
set_display_target(channel, LOG_CRAP);
|
||||
if (do_hook(current_numeric, "%s %s %s %s", from, type, channel,line)
|
||||
&& do_hook(NAMES_LIST, "%s %s", channel, line)
|
||||
&& get_int_var(SHOW_CHANNEL_NAMES_VAR))
|
||||
{
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NAMES_FSET), "%s %s %d",update_clock(GET_TIME), channel, user_count));
|
||||
print_funny_names(line);
|
||||
}
|
||||
if ((user_count == 1) && (*line == '@'))
|
||||
{
|
||||
ChannelList *chan;
|
||||
if ((chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
|
||||
if ((ptr = get_cset_str_var(chan->csets, CHANMODE_CSET)))
|
||||
my_send_to_server(from_server, "MODE %s %s", channel, ptr);
|
||||
}
|
||||
got_info(channel, from_server, GOTNAMES);
|
||||
reset_display_target();
|
||||
return;
|
||||
}
|
||||
if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR))
|
||||
{
|
||||
if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0)
|
||||
sprintf(format, "%%s: %%-%u.%us %%s",
|
||||
(unsigned char) last_width,
|
||||
(unsigned char) last_width);
|
||||
else
|
||||
strcpy(format, "%s: %s\t%s");
|
||||
}
|
||||
if (funny_min && (user_count < funny_min))
|
||||
return;
|
||||
else if (funny_max && (user_count > funny_max))
|
||||
return;
|
||||
if ((funny_flags & FUNNY_PRIVATE) && (*type == '='))
|
||||
return;
|
||||
if ((funny_flags & FUNNY_PUBLIC) && ((*type == '*') || (*type == '@')))
|
||||
return;
|
||||
if (type && channel)
|
||||
{
|
||||
if (match_str)
|
||||
{
|
||||
if (wild_match(match_str, channel) == 0)
|
||||
return;
|
||||
}
|
||||
if (do_hook(current_numeric, "%s %s %s %s", from, type, channel, line) && do_hook(NAMES_LIST, "%s %s", channel, line))
|
||||
{
|
||||
set_display_target(channel, LOG_CRAP);
|
||||
if (fget_string_var(FORMAT_NAMES_FSET))
|
||||
{
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NAMES_FSET), "%s %s %d", update_clock(GET_TIME), channel, user_count));
|
||||
print_funny_names(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (*type)
|
||||
{
|
||||
case '=':
|
||||
if (last_width &&(strlen(channel) > last_width))
|
||||
{
|
||||
channel[last_width-1] = '>';
|
||||
channel[last_width] = (char) 0;
|
||||
}
|
||||
put_it(format, "Pub", channel, line);
|
||||
break;
|
||||
case '*':
|
||||
put_it(format, "Prv", channel, line);
|
||||
break;
|
||||
case '@':
|
||||
put_it(format, "Sec", channel, line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
reset_display_target();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void funny_mode(char *from, char **ArgList)
|
||||
{
|
||||
char *mode, *channel;
|
||||
ChannelList *chan = NULL;
|
||||
|
||||
if (!ArgList[0]) return;
|
||||
|
||||
channel = ArgList[0];
|
||||
mode = ArgList[1];
|
||||
PasteArgs(ArgList, 1);
|
||||
|
||||
if((channel && in_join_list(channel, from_server)) || get_chan_from_join_list(from_server))
|
||||
{
|
||||
if (!channel)
|
||||
channel = get_chan_from_join_list(from_server);
|
||||
update_channel_mode(from, channel, from_server, mode, chan);
|
||||
update_all_status(current_window, NULL, 0);
|
||||
got_info(channel, from_server, GOTMODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (channel)
|
||||
{
|
||||
set_display_target(channel, LOG_CRAP);
|
||||
if (do_hook(current_numeric, "%s %s %s", from, channel, mode))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_MODE_CHANNEL_FSET), "%s %s %s %s %s", update_clock(GET_TIME), from, *FromUserHost ? FromUserHost:"ÿ", channel, mode));
|
||||
reset_display_target();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (do_hook(current_numeric, "%s %s", from, mode))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_MODE_CHANNEL_FSET), "%s %s %s %s", update_clock(GET_TIME), from, *FromUserHost ? FromUserHost:"ÿ", mode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_user_mode(char *modes)
|
||||
{
|
||||
int onoff = 1;
|
||||
char *p_umodes = get_possible_umodes(from_server);
|
||||
|
||||
for (; *modes; modes++)
|
||||
{
|
||||
if (*modes == '-')
|
||||
onoff = 0;
|
||||
else if (*modes == '+')
|
||||
onoff = 1;
|
||||
|
||||
else if ((*modes >= 'a' && *modes <= 'z')
|
||||
|| (*modes >= 'A' && *modes <= 'Z'))
|
||||
{
|
||||
size_t idx;
|
||||
int c = *modes;
|
||||
|
||||
idx = ccspan(p_umodes, c);
|
||||
if (p_umodes[idx] == 0)
|
||||
ircpanic("Invalid user mode referenced");
|
||||
set_server_flag(from_server, idx, onoff);
|
||||
|
||||
if (c == 'o' || c == 'O')
|
||||
set_server_operator(from_server, onoff);
|
||||
#if 0
|
||||
char c = tolower(*modes);
|
||||
size_t idx = (size_t) (strchr(umodes, c) - umodes);
|
||||
|
||||
set_server_flag(from_server, USER_MODE << idx, onoff);
|
||||
|
||||
if (c == 'o' || c == 'O')
|
||||
set_server_operator(from_server, onoff);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reinstate_user_modes (void)
|
||||
{
|
||||
char *modes = get_umode(from_server);
|
||||
if (modes && *modes)
|
||||
send_to_server("MODE %s +%s", get_server_nickname(from_server), modes);
|
||||
}
|
||||
852
source/glob.c
Normal file
852
source/glob.c
Normal file
@@ -0,0 +1,852 @@
|
||||
#include "defs.h"
|
||||
#include "config.h"
|
||||
|
||||
#if defined(NEED_GLOB)
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Guido van Rossum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* from: static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; */
|
||||
/* $Id: glob.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $ */
|
||||
|
||||
/*
|
||||
* glob(3) -- a superset of the one defined in POSIX 1003.2.
|
||||
*
|
||||
* The [!...] convention to negate a range is supported (SysV, Posix, ksh).
|
||||
*
|
||||
* Optional extra services, controlled by flags not defined by POSIX:
|
||||
*
|
||||
* GLOB_QUOTE:
|
||||
* Escaping convention: \ inhibits any special meaning the following
|
||||
* character might have (except \ at end of string is retained).
|
||||
* GLOB_MAGCHAR:
|
||||
* Set in gl_flags if pattern contained a globbing character.
|
||||
* GLOB_NOMAGIC:
|
||||
* Same as GLOB_NOCHECK, but it will only append pattern if it did
|
||||
* not contain any magic characters. [Used in csh style globbing]
|
||||
* GLOB_ALTDIRFUNC:
|
||||
* Use alternately specified directory access functions.
|
||||
* GLOB_TILDE:
|
||||
* expand ~user/foo to the /home/dir/of/user/foo
|
||||
* GLOB_BRACE:
|
||||
* expand {1,2}{a,b} to 1a 1b 2a 2b
|
||||
* gl_matchc:
|
||||
* Number of matches in the current invocation of glob.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifdef __EMX__
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bsdglob.h"
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "ircaux.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN PATHLEN
|
||||
#endif
|
||||
|
||||
#undef EOS
|
||||
|
||||
#define DOLLAR '$'
|
||||
#define DOT '.'
|
||||
#define EOS '\0'
|
||||
#define LBRACKET '['
|
||||
#define NOT '!'
|
||||
#define QUESTION '?'
|
||||
#define QUOTE '\\'
|
||||
#define RANGE '-'
|
||||
#define RBRACKET ']'
|
||||
#define SEP '/'
|
||||
#define STAR '*'
|
||||
#define TILDE '~'
|
||||
#define UNDERSCORE '_'
|
||||
#define LBRACE '{'
|
||||
#define RBRACE '}'
|
||||
#define SLASH '/'
|
||||
#define COMMA ','
|
||||
|
||||
#define M_QUOTE 0x8000
|
||||
#define M_PROTECT 0x4000
|
||||
#define M_ANYCASE 0x2000
|
||||
#define M_MASK 0xffff
|
||||
#define M_ASCII 0x00ff
|
||||
|
||||
#if 0
|
||||
#ifdef ULTRIX
|
||||
#define S_IFLNK 0120000 /* symbolic link */
|
||||
#define S_ISLNK( mode ) (((mode) & _S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef u_short Char;
|
||||
|
||||
#define CHAR(c) ((Char)((c)&M_ASCII))
|
||||
#define META(c) ((Char)((c)|M_QUOTE))
|
||||
#define M_ALL META('*')
|
||||
#define M_END META(']')
|
||||
#define M_NOT META('!')
|
||||
#define M_ONE META('?')
|
||||
#define M_RNG META('-')
|
||||
#define M_SET META('[')
|
||||
#define ismeta(c) (((c)&M_QUOTE) != 0)
|
||||
|
||||
|
||||
static int compare (const void *, const void *);
|
||||
static void g_Ctoc (const Char *, char *);
|
||||
static int g_lstat (Char *, struct stat *, glob_t *);
|
||||
static DIR * g_opendir (Char *, glob_t *);
|
||||
static Char * g_strchr (Char *, int);
|
||||
#ifdef S_ISLNK
|
||||
static int g_stat (Char *, struct stat *, glob_t *);
|
||||
#endif
|
||||
static int glob0 (const Char *, glob_t *);
|
||||
static int glob1 (Char *, glob_t *);
|
||||
static int glob2 (Char *, Char *, Char *, glob_t *);
|
||||
static int glob3 (Char *, Char *, Char *, Char *, glob_t *);
|
||||
static int globextend (const Char *, glob_t *);
|
||||
static const Char * globtilde (const Char *, Char *, glob_t *);
|
||||
static int globexp1 (const Char *, glob_t *);
|
||||
static int globexp2 (const Char *, const Char *, glob_t *, int *);
|
||||
static int match (Char *, Char *, Char *, int);
|
||||
|
||||
int BX_bsd_glob ( const char *pattern,
|
||||
int flags,
|
||||
int (*errfunc) (const char *, int),
|
||||
glob_t *pglob )
|
||||
{
|
||||
const u_char *patnext;
|
||||
int c;
|
||||
Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
|
||||
|
||||
#if defined(__EMX__) || defined(WINNT)
|
||||
strlwr((char *)pattern);
|
||||
#endif
|
||||
patnext = (u_char *) pattern;
|
||||
if (!(flags & GLOB_APPEND)) {
|
||||
pglob->gl_pathc = 0;
|
||||
pglob->gl_pathv = NULL;
|
||||
if (!(flags & GLOB_DOOFFS))
|
||||
pglob->gl_offs = 0;
|
||||
}
|
||||
pglob->gl_flags = flags & ~GLOB_MAGCHAR;
|
||||
pglob->gl_errfunc = errfunc;
|
||||
pglob->gl_matchc = 0;
|
||||
|
||||
bufnext = patbuf;
|
||||
bufend = bufnext + MAXPATHLEN;
|
||||
if (flags & GLOB_QUOTE) {
|
||||
/* Protect the quoted characters. */
|
||||
while (bufnext < bufend && (c = *patnext++) != EOS)
|
||||
if (c == QUOTE) {
|
||||
if ((c = *patnext++) == EOS) {
|
||||
c = QUOTE;
|
||||
--patnext;
|
||||
}
|
||||
*bufnext++ = c | M_PROTECT;
|
||||
}
|
||||
else
|
||||
*bufnext++ = c;
|
||||
}
|
||||
else
|
||||
while (bufnext < bufend && (c = *patnext++) != EOS)
|
||||
*bufnext++ = c;
|
||||
*bufnext = EOS;
|
||||
|
||||
if (flags & GLOB_BRACE)
|
||||
return globexp1(patbuf, pglob);
|
||||
else
|
||||
return glob0(patbuf, pglob);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand recursively a glob {} pattern. When there is no more expansion
|
||||
* invoke the standard globbing routine to glob the rest of the magic
|
||||
* characters
|
||||
*/
|
||||
static int globexp1 ( const Char *pattern,
|
||||
glob_t *pglob )
|
||||
{
|
||||
const Char* ptr = pattern;
|
||||
int rv;
|
||||
|
||||
/* Protect a single {}, for find(1), like csh */
|
||||
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
|
||||
return glob0(pattern, pglob);
|
||||
|
||||
while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
|
||||
if (!globexp2(ptr, pattern, pglob, &rv))
|
||||
return rv;
|
||||
|
||||
return glob0(pattern, pglob);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Recursive brace globbing helper. Tries to expand a single brace.
|
||||
* If it succeeds then it invokes globexp1 with the new pattern.
|
||||
* If it fails then it tries to glob the rest of the pattern and returns.
|
||||
*/
|
||||
static int globexp2 ( const Char *ptr,
|
||||
const Char *pattern,
|
||||
glob_t *pglob,
|
||||
int *rv )
|
||||
{
|
||||
int i;
|
||||
Char *lm, *ls;
|
||||
const Char *pe, *pm, *pl;
|
||||
Char patbuf[MAXPATHLEN + 1];
|
||||
|
||||
/* copy part up to the brace */
|
||||
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
|
||||
continue;
|
||||
ls = lm;
|
||||
|
||||
/* Find the balanced brace */
|
||||
for (i = 0, pe = ++ptr; *pe; pe++)
|
||||
if (*pe == LBRACKET)
|
||||
{
|
||||
/* Ignore everything between [] */
|
||||
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
|
||||
continue;
|
||||
if (*pe == EOS)
|
||||
{
|
||||
/*
|
||||
* We could not find a matching RBRACKET.
|
||||
* Ignore and just look for RBRACE
|
||||
*/
|
||||
pe = pm;
|
||||
}
|
||||
}
|
||||
else if (*pe == LBRACE)
|
||||
i++;
|
||||
else if (*pe == RBRACE)
|
||||
{
|
||||
if (i == 0)
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
|
||||
/* Non matching braces; just glob the pattern */
|
||||
if (i != 0 || *pe == EOS)
|
||||
{
|
||||
*rv = glob0(patbuf, pglob);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0, pl = pm = ptr; pm <= pe; pm++)
|
||||
switch (*pm)
|
||||
{
|
||||
case LBRACKET:
|
||||
/* Ignore everything between [] */
|
||||
for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
|
||||
continue;
|
||||
if (*pm == EOS)
|
||||
{
|
||||
/*
|
||||
* We could not find a matching RBRACKET.
|
||||
* Ignore and just look for RBRACE
|
||||
*/
|
||||
pm = pl;
|
||||
}
|
||||
break;
|
||||
|
||||
case LBRACE:
|
||||
i++;
|
||||
break;
|
||||
|
||||
case RBRACE:
|
||||
if (i)
|
||||
{
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case COMMA:
|
||||
if (i && *pm == COMMA)
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* Append the current string */
|
||||
for (lm = ls; (pl < pm); *lm++ = *pl++)
|
||||
continue;
|
||||
/*
|
||||
* Append the rest of the pattern after the
|
||||
* closing brace
|
||||
*/
|
||||
for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
|
||||
continue;
|
||||
|
||||
/* Expand the current pattern */
|
||||
*rv = globexp1(patbuf, pglob);
|
||||
|
||||
/* move after the comma, to the next string */
|
||||
pl = pm + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*rv = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* expand tilde from the passwd file.
|
||||
*/
|
||||
static const Char *globtilde ( const Char *pattern,
|
||||
Char *patbuf,
|
||||
glob_t *pglob )
|
||||
{
|
||||
struct passwd *pwd;
|
||||
char *h;
|
||||
const Char *p;
|
||||
Char *b;
|
||||
|
||||
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
|
||||
return pattern;
|
||||
|
||||
/* Copy up to the end of the string or / */
|
||||
for (p = pattern + 1, h = (char *) patbuf; *p && *p != SLASH;
|
||||
*h++ = *p++)
|
||||
continue;
|
||||
|
||||
*h = EOS;
|
||||
|
||||
if (((char *) patbuf)[0] == EOS) {
|
||||
/*
|
||||
* handle a plain ~ or ~/ by expanding $HOME
|
||||
* first and then trying the password file
|
||||
*/
|
||||
if ((h = getenv("HOME")) == NULL) {
|
||||
if ((pwd = getpwuid(getuid())) == NULL)
|
||||
return pattern;
|
||||
else
|
||||
h = pwd->pw_dir;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Expand a ~user
|
||||
*/
|
||||
if ((pwd = getpwnam((char*) patbuf)) == NULL)
|
||||
return pattern;
|
||||
else
|
||||
h = pwd->pw_dir;
|
||||
}
|
||||
|
||||
/* Copy the home directory */
|
||||
for (b = patbuf; *h; *b++ = *h++)
|
||||
continue;
|
||||
|
||||
/* Append the rest of the pattern */
|
||||
while ((*b++ = *p++) != EOS)
|
||||
continue;
|
||||
#if defined(__EMX__) || defined(WINNT)
|
||||
convert_unix((char *)patbuf);
|
||||
#endif
|
||||
return patbuf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main glob() routine: compiles the pattern (optionally processing
|
||||
* quotes), calls glob1() to do the real pattern matching, and finally
|
||||
* sorts the list (unless unsorted operation is requested). Returns 0
|
||||
* if things went well, nonzero if errors occurred. It is not an error
|
||||
* to find no matches.
|
||||
*/
|
||||
static int glob0 ( const Char *pattern,
|
||||
glob_t *pglob )
|
||||
{
|
||||
const Char *qpatnext;
|
||||
int c, err, oldpathc;
|
||||
Char *bufnext, patbuf[MAXPATHLEN+1];
|
||||
|
||||
qpatnext = globtilde(pattern, patbuf, pglob);
|
||||
oldpathc = pglob->gl_pathc;
|
||||
bufnext = patbuf;
|
||||
|
||||
/* We don't need to check for buffer overflow any more. */
|
||||
while ((c = *qpatnext++) != EOS)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case LBRACKET:
|
||||
c = *qpatnext;
|
||||
if (c == NOT)
|
||||
++qpatnext;
|
||||
if (*qpatnext == EOS || g_strchr((Char *) qpatnext+1, RBRACKET) == NULL)
|
||||
{
|
||||
*bufnext++ = LBRACKET;
|
||||
if (c == NOT)
|
||||
--qpatnext;
|
||||
break;
|
||||
}
|
||||
*bufnext++ = M_SET;
|
||||
if (c == NOT)
|
||||
*bufnext++ = M_NOT;
|
||||
c = *qpatnext++;
|
||||
do
|
||||
{
|
||||
*bufnext++ = CHAR(c);
|
||||
if (*qpatnext == RANGE && (c = qpatnext[1]) != RBRACKET)
|
||||
{
|
||||
*bufnext++ = M_RNG;
|
||||
*bufnext++ = CHAR(c);
|
||||
qpatnext += 2;
|
||||
}
|
||||
}
|
||||
while ((c = *qpatnext++) != RBRACKET);
|
||||
|
||||
pglob->gl_flags |= GLOB_MAGCHAR;
|
||||
*bufnext++ = M_END;
|
||||
break;
|
||||
case QUESTION:
|
||||
pglob->gl_flags |= GLOB_MAGCHAR;
|
||||
*bufnext++ = M_ONE;
|
||||
break;
|
||||
case STAR:
|
||||
pglob->gl_flags |= GLOB_MAGCHAR;
|
||||
/* collapse adjacent stars to one,
|
||||
* to avoid exponential behavior
|
||||
*/
|
||||
if (bufnext == patbuf || bufnext[-1] != M_ALL)
|
||||
*bufnext++ = M_ALL;
|
||||
break;
|
||||
default:
|
||||
*bufnext++ = CHAR(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
*bufnext = EOS;
|
||||
|
||||
if ((err = glob1(patbuf, pglob)) != 0)
|
||||
return(err);
|
||||
|
||||
/*
|
||||
* If there was no match we are going to append the pattern
|
||||
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
|
||||
* and the pattern did not contain any magic characters
|
||||
* GLOB_NOMAGIC is there just for compatibility with csh.
|
||||
*/
|
||||
if (pglob->gl_pathc == oldpathc &&
|
||||
((pglob->gl_flags & GLOB_NOCHECK) ||
|
||||
((pglob->gl_flags & GLOB_NOMAGIC) &&
|
||||
!(pglob->gl_flags & GLOB_MAGCHAR))))
|
||||
return(globextend(pattern, pglob));
|
||||
else if (!(pglob->gl_flags & GLOB_NOSORT))
|
||||
{
|
||||
if (pglob->gl_pathv)
|
||||
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
|
||||
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int compare ( const void *p,
|
||||
const void *q )
|
||||
{
|
||||
return(strcmp(*(char **)p, *(char **)q));
|
||||
}
|
||||
|
||||
static int glob1 ( Char *pattern,
|
||||
glob_t *pglob )
|
||||
{
|
||||
Char pathbuf[MAXPATHLEN+1];
|
||||
|
||||
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
|
||||
if (*pattern == EOS)
|
||||
return(0);
|
||||
return(glob2(pathbuf, pathbuf, pattern, pglob));
|
||||
}
|
||||
|
||||
/*
|
||||
* The functions glob2 and glob3 are mutually recursive; there is one level
|
||||
* of recursion for each segment in the pattern that contains one or more
|
||||
* meta characters.
|
||||
*/
|
||||
static int glob2 ( Char *pathbuf,
|
||||
Char *pathend,
|
||||
Char *pattern,
|
||||
glob_t *pglob )
|
||||
{
|
||||
struct stat sb;
|
||||
Char *p, *q;
|
||||
int anymeta;
|
||||
|
||||
/*
|
||||
* Loop over pattern segments until end of pattern or until
|
||||
* segment with meta character found.
|
||||
*/
|
||||
for (anymeta = 0;;)
|
||||
{
|
||||
if (*pattern == EOS) /* End of pattern? */
|
||||
{
|
||||
*pathend = EOS;
|
||||
if (g_lstat(pathbuf, &sb, pglob))
|
||||
return(0);
|
||||
|
||||
if (((pglob->gl_flags & GLOB_MARK) &&
|
||||
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
|
||||
#ifdef S_ISLNK
|
||||
|| (S_ISLNK(sb.st_mode) &&
|
||||
(g_stat(pathbuf, &sb, pglob) == 0) &&
|
||||
S_ISDIR(sb.st_mode))
|
||||
#endif
|
||||
))
|
||||
{
|
||||
*pathend++ = SEP;
|
||||
*pathend = EOS;
|
||||
}
|
||||
++pglob->gl_matchc;
|
||||
return(globextend(pathbuf, pglob));
|
||||
}
|
||||
|
||||
/* Find end of next segment, copy tentatively to pathend. */
|
||||
q = pathend;
|
||||
p = pattern;
|
||||
while (*p != EOS && *p != SEP)
|
||||
{
|
||||
if (ismeta(*p))
|
||||
anymeta = 1;
|
||||
*q++ = *p++;
|
||||
}
|
||||
|
||||
if (!anymeta) /* No expansion, do next segment. */
|
||||
{
|
||||
pathend = q;
|
||||
pattern = p;
|
||||
while (*pattern == SEP)
|
||||
*pathend++ = *pattern++;
|
||||
} else /* Need expansion, recurse. */
|
||||
return(glob3(pathbuf, pathend, pattern, p, pglob));
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int glob3 ( Char *pathbuf,
|
||||
Char *pathend,
|
||||
Char *pattern,
|
||||
Char *restpattern,
|
||||
glob_t *pglob )
|
||||
{
|
||||
register struct dirent *dp;
|
||||
DIR *dirp;
|
||||
int err;
|
||||
char buf[MAXPATHLEN];
|
||||
int nocase = 0;
|
||||
|
||||
/*
|
||||
* The readdirfunc declaration can't be prototyped, because it is
|
||||
* assigned, below, to two functions which are prototyped in glob.h
|
||||
* and dirent.h as taking pointers to differently typed opaque
|
||||
* structures.
|
||||
*/
|
||||
struct dirent *(*readdirfunc)();
|
||||
|
||||
*pathend = EOS;
|
||||
errno = 0;
|
||||
|
||||
if ((dirp = g_opendir(pathbuf, pglob)) == NULL)
|
||||
{
|
||||
/* TODO: don't call for ENOENT or ENOTDIR? */
|
||||
if (pglob->gl_errfunc)
|
||||
{
|
||||
g_Ctoc(pathbuf, buf);
|
||||
if (pglob->gl_errfunc(buf, errno) ||
|
||||
pglob->gl_flags & GLOB_ERR)
|
||||
return (GLOB_ABEND);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
/* Search directory for matching names. */
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
readdirfunc = pglob->gl_readdir;
|
||||
else
|
||||
readdirfunc = readdir;
|
||||
|
||||
|
||||
if (pglob->gl_flags & GLOB_INSENSITIVE)
|
||||
nocase = 1;
|
||||
|
||||
while ((dp = (*readdirfunc)(dirp)))
|
||||
{
|
||||
register u_char *sc;
|
||||
register Char *dc;
|
||||
|
||||
#if defined(__EMX__) || defined(WINNT)
|
||||
if(dp->d_name && *(dp->d_name))
|
||||
strlwr(dp->d_name);
|
||||
#endif
|
||||
|
||||
/* Initial DOT must be matched literally. */
|
||||
if (dp->d_name[0] == DOT && *pattern != DOT)
|
||||
continue;
|
||||
for (sc = (u_char *) dp->d_name, dc = pathend;
|
||||
(*dc++ = *sc++) != EOS;)
|
||||
continue;
|
||||
if (!match(pathend, pattern, restpattern, nocase))
|
||||
{
|
||||
*pathend = EOS;
|
||||
continue;
|
||||
}
|
||||
err = glob2(pathbuf, --dc, restpattern, pglob);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
(*pglob->gl_closedir)(dirp);
|
||||
else
|
||||
closedir(dirp);
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Extend the gl_pathv member of a glob_t structure to accomodate a new item,
|
||||
* add the new item, and update gl_pathc.
|
||||
*
|
||||
* This assumes the BSD realloc, which only copies the block when its size
|
||||
* crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
|
||||
* behavior.
|
||||
*
|
||||
* Return 0 if new item added, error code if memory couldn't be allocated.
|
||||
*
|
||||
* Invariant of the glob_t structure:
|
||||
* Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
|
||||
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
|
||||
*/
|
||||
static int globextend ( const Char *path,
|
||||
glob_t *pglob )
|
||||
{
|
||||
register char **pathv;
|
||||
register int i;
|
||||
u_int newsize;
|
||||
char *copy;
|
||||
const Char *p;
|
||||
|
||||
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
|
||||
pathv = pglob->gl_pathv ?
|
||||
(char **)realloc((char *)pglob->gl_pathv, newsize) :
|
||||
(char **)malloc(newsize);
|
||||
if (pathv == NULL)
|
||||
return(GLOB_NOSPACE);
|
||||
|
||||
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0)
|
||||
{
|
||||
/* first time around -- clear initial gl_offs items */
|
||||
pathv += pglob->gl_offs;
|
||||
for (i = pglob->gl_offs; --i >= 0; )
|
||||
*--pathv = NULL;
|
||||
}
|
||||
pglob->gl_pathv = pathv;
|
||||
|
||||
for (p = path; *p++;)
|
||||
continue;
|
||||
if ((copy = malloc(p - path)) != NULL)
|
||||
{
|
||||
g_Ctoc(path, copy);
|
||||
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
|
||||
}
|
||||
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
|
||||
return(copy == NULL ? GLOB_NOSPACE : 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pattern matching function for filenames. Each occurrence of the *
|
||||
* pattern causes a recursion level.
|
||||
*/
|
||||
static int match ( register Char *name,
|
||||
register Char *pat,
|
||||
register Char *patend,
|
||||
int nocase )
|
||||
{
|
||||
int ok, negate_range;
|
||||
Char c, k;
|
||||
|
||||
while (pat < patend)
|
||||
{
|
||||
c = *pat++;
|
||||
switch (c & M_MASK)
|
||||
{
|
||||
case M_ALL:
|
||||
if (pat == patend)
|
||||
return(1);
|
||||
do
|
||||
if (match(name, pat, patend, nocase))
|
||||
return(1);
|
||||
while (*name++ != EOS);
|
||||
return(0);
|
||||
case M_ONE:
|
||||
if (*name++ == EOS)
|
||||
return(0);
|
||||
break;
|
||||
case M_SET:
|
||||
ok = 0;
|
||||
if ((k = *name++) == EOS)
|
||||
return(0);
|
||||
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
|
||||
++pat;
|
||||
while (((c = *pat++) & M_MASK) != M_END)
|
||||
{
|
||||
if ((*pat & M_MASK) == M_RNG)
|
||||
{
|
||||
if (c <= k && k <= pat[1])
|
||||
ok = 1;
|
||||
pat += 2;
|
||||
} else if (c == k)
|
||||
ok = 1;
|
||||
}
|
||||
if (ok == negate_range)
|
||||
return(0);
|
||||
break;
|
||||
default:
|
||||
if (nocase)
|
||||
{
|
||||
if (toupper(CHAR(*name++)) != toupper(CHAR(c)))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*name++ != c)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(*name == EOS);
|
||||
}
|
||||
|
||||
/* Free allocated data belonging to a glob_t structure. */
|
||||
void BX_bsd_globfree ( glob_t *pglob )
|
||||
{
|
||||
register int i;
|
||||
register char **pp;
|
||||
|
||||
if (pglob->gl_pathv != NULL) {
|
||||
pp = pglob->gl_pathv + pglob->gl_offs;
|
||||
for (i = pglob->gl_pathc; i--; ++pp)
|
||||
if (*pp)
|
||||
free(*pp);
|
||||
free(pglob->gl_pathv);
|
||||
}
|
||||
}
|
||||
|
||||
static DIR *g_opendir ( register Char *str,
|
||||
glob_t *pglob )
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
if (!*str)
|
||||
strcpy(buf, ".");
|
||||
else
|
||||
g_Ctoc(str, buf);
|
||||
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
return((*pglob->gl_opendir)(buf));
|
||||
|
||||
return(opendir(buf));
|
||||
}
|
||||
|
||||
static int g_lstat ( register Char *fn,
|
||||
struct stat *sb,
|
||||
glob_t *pglob )
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
g_Ctoc(fn, buf);
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
return((*pglob->gl_lstat)(buf, sb));
|
||||
#if defined(__EMX__) || defined(__OPENNT)
|
||||
return(stat(buf, sb));
|
||||
#else
|
||||
return(lstat(buf, sb));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef S_ISLNK
|
||||
static int g_stat ( register Char *fn,
|
||||
struct stat *sb,
|
||||
glob_t *pglob )
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
g_Ctoc(fn, buf);
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
return((*pglob->gl_stat)(buf, sb));
|
||||
return(stat(buf, sb));
|
||||
}
|
||||
#endif
|
||||
|
||||
static Char *g_strchr ( Char *str,
|
||||
int ch )
|
||||
{
|
||||
do {
|
||||
if (*str == ch)
|
||||
return (str);
|
||||
} while (*str++);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void g_Ctoc ( register const Char *str,
|
||||
char *buf )
|
||||
{
|
||||
register char *dc;
|
||||
|
||||
for (dc = buf; (*dc++ = *str++) != EOS;)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
3372
source/gtkbitchx.c
Normal file
3372
source/gtkbitchx.c
Normal file
File diff suppressed because it is too large
Load Diff
881
source/hash.c
Normal file
881
source/hash.c
Normal file
@@ -0,0 +1,881 @@
|
||||
/************
|
||||
* hash.c *
|
||||
************
|
||||
*
|
||||
* My hash routines for hashing NickLists, and eventually ChannelList's
|
||||
* and WhowasList's
|
||||
*
|
||||
* These are not very robust, as the add/remove functions will have
|
||||
* to be written differently for each type of struct
|
||||
* (To DO: use C++, and create a hash "class" so I don't need to
|
||||
* have the functions different.)
|
||||
*
|
||||
*
|
||||
* Written by Scott H Kilau
|
||||
*
|
||||
* Copyright(c) 1997
|
||||
*
|
||||
* Modified by Colten Edwards for use in BitchX.
|
||||
* Added Whowas buffer hashing.
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: hash.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(hash_c)
|
||||
#include "struct.h"
|
||||
#include "ircaux.h"
|
||||
#include "hook.h"
|
||||
#include "vars.h"
|
||||
#include "output.h"
|
||||
#include "misc.h"
|
||||
#include "server.h"
|
||||
#include "list.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "hash2.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
/*
|
||||
* hash_nickname: for now, does a simple hash of the
|
||||
* nick by counting up the ascii values of the lower case, and
|
||||
* then %'ing it by NICKLIST_HASHSIZE (always a prime!)
|
||||
*/
|
||||
unsigned long hash_nickname(char *nick, unsigned int size)
|
||||
{
|
||||
register u_char *p = (u_char *) nick;
|
||||
unsigned long hash = 0, g;
|
||||
if (!nick) return -1;
|
||||
while (*p)
|
||||
{
|
||||
hash = (hash << 4) + ((*p >= 'A' && *p <= 'Z') ? (*p+32) : *p);
|
||||
if ((g = hash & 0xF0000000))
|
||||
hash ^= g >> 24;
|
||||
hash &= ~g;
|
||||
p++;
|
||||
}
|
||||
return (hash %= size);
|
||||
}
|
||||
|
||||
/*
|
||||
* move_link_to_top: used by find routine, brings link
|
||||
* to the top of the list in the specific array location
|
||||
*/
|
||||
static inline void move_link_to_top(NickList *tmp, NickList *prev, HashEntry *location)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
NickList *old_list;
|
||||
old_list = (NickList *) location->list;
|
||||
location->list = (void *) tmp;
|
||||
prev->next = tmp->next;
|
||||
tmp->next = old_list;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_link_from_list: used by find routine, removes link
|
||||
* from our chain of hashed entries.
|
||||
*/
|
||||
static inline void remove_link_from_list(NickList *tmp, NickList *prev, HashEntry *location)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
/* remove the link from the middle of the list */
|
||||
prev->next = tmp->next;
|
||||
}
|
||||
else {
|
||||
/* unlink the first link, and connect next one up */
|
||||
location->list = (void *) tmp->next;
|
||||
}
|
||||
/* set tmp's next to NULL, as its unlinked now */
|
||||
tmp->next = NULL;
|
||||
}
|
||||
|
||||
void BX_add_name_to_genericlist(char *name, HashEntry *list, unsigned int size)
|
||||
{
|
||||
List *nptr;
|
||||
unsigned long hvalue = hash_nickname(name, size);
|
||||
|
||||
nptr = (List *) new_malloc(sizeof(List));
|
||||
nptr->next = (List *) list[hvalue].list;
|
||||
nptr->name = m_strdup(name);
|
||||
|
||||
/* assign our new linked list into array spot */
|
||||
list[hvalue].list = (void *) nptr;
|
||||
/* quick tally of nicks in chain in this array spot */
|
||||
list[hvalue].links++;
|
||||
/* keep stats on hits to this array spot */
|
||||
list[hvalue].hits++;
|
||||
}
|
||||
|
||||
/*
|
||||
* move_link_to_top: used by find routine, brings link
|
||||
* to the top of the list in the specific array location
|
||||
*/
|
||||
static inline void move_gen_link_to_top(List *tmp, List *prev, HashEntry *location)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
List *old_list;
|
||||
old_list = (List *) location->list;
|
||||
location->list = (void *) tmp;
|
||||
prev->next = tmp->next;
|
||||
tmp->next = old_list;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_link_from_list: used by find routine, removes link
|
||||
* from our chain of hashed entries.
|
||||
*/
|
||||
static inline void remove_gen_link_from_list(List *tmp, List *prev, HashEntry *location)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
/* remove the link from the middle of the list */
|
||||
prev->next = tmp->next;
|
||||
}
|
||||
else {
|
||||
/* unlink the first link, and connect next one up */
|
||||
location->list = (void *) tmp->next;
|
||||
}
|
||||
/* set tmp's next to NULL, as its unlinked now */
|
||||
tmp->next = NULL;
|
||||
}
|
||||
|
||||
List *BX_find_name_in_genericlist(char *name, HashEntry *list, unsigned int size, int remove)
|
||||
{
|
||||
HashEntry *location;
|
||||
register List *tmp, *prev = NULL;
|
||||
unsigned long hvalue = hash_nickname(name, size);
|
||||
|
||||
location = &(list[hvalue]);
|
||||
|
||||
/* at this point, we found the array spot, now search
|
||||
* as regular linked list, or as ircd likes to say...
|
||||
* "We found the bucket, now search the chain"
|
||||
*/
|
||||
for (tmp = (List *) location->list; tmp; prev = tmp, tmp = tmp->next)
|
||||
{
|
||||
if (!my_stricmp(name, tmp->name))
|
||||
{
|
||||
if (remove != REMOVE_FROM_LIST)
|
||||
move_gen_link_to_top(tmp, prev, location);
|
||||
else
|
||||
{
|
||||
location->links--;
|
||||
remove_gen_link_from_list(tmp, prev, location);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_nicklist_to_channellist: This function will add the nicklist
|
||||
* into the channellist, ensuring that we hash the nicklist, and
|
||||
* insert the struct correctly into the channelist's Nicklist hash
|
||||
* array
|
||||
*/
|
||||
void BX_add_nicklist_to_channellist(NickList *nptr, ChannelList *cptr)
|
||||
{
|
||||
unsigned long hvalue = hash_nickname(nptr->nick, NICKLIST_HASHSIZE);
|
||||
|
||||
/* take this nicklist, and attach it as the HEAD pointer
|
||||
* in our chain at the hashed location in our array...
|
||||
* Note, by doing this, this ensures that the "most active"
|
||||
* users always remain at the top of the chain... ie, faster
|
||||
* lookups for active users, (and as a side note, makes
|
||||
* doing the add quite simple!)
|
||||
*/
|
||||
nptr->next = (NickList *) cptr->NickListTable[hvalue].list;
|
||||
|
||||
/* assign our new linked list into array spot */
|
||||
cptr->NickListTable[hvalue].list = (void *) nptr;
|
||||
/* quick tally of nicks in chain in this array spot */
|
||||
cptr->NickListTable[hvalue].links++;
|
||||
/* keep stats on hits to this array spot */
|
||||
cptr->NickListTable[hvalue].hits++;
|
||||
}
|
||||
|
||||
NickList *BX_find_nicklist_in_channellist(char *nick, ChannelList *cptr, int remove)
|
||||
{
|
||||
HashEntry *location;
|
||||
register NickList *tmp, *prev = NULL;
|
||||
unsigned long hvalue = hash_nickname(nick, NICKLIST_HASHSIZE);
|
||||
|
||||
if (!cptr)
|
||||
return NULL;
|
||||
location = &(cptr->NickListTable[hvalue]);
|
||||
|
||||
/* at this point, we found the array spot, now search
|
||||
* as regular linked list, or as ircd likes to say...
|
||||
* "We found the bucket, now search the chain"
|
||||
*/
|
||||
for (tmp = (NickList *) location->list; tmp; prev = tmp, tmp = tmp->next)
|
||||
{
|
||||
if (!my_stricmp(nick, tmp->nick))
|
||||
{
|
||||
if (remove != REMOVE_FROM_LIST)
|
||||
move_link_to_top(tmp, prev, location);
|
||||
else
|
||||
{
|
||||
location->links--;
|
||||
remove_link_from_list(tmp, prev, location);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Basically this makes the hash table "look" like a straight linked list
|
||||
* This should be used for things that require you to cycle through the
|
||||
* full list, ex. for finding ALL matching stuff.
|
||||
* : usage should be like :
|
||||
*
|
||||
* for (nptr = next_nicklist(cptr, NULL); nptr; nptr =
|
||||
* next_nicklist(cptr, nptr))
|
||||
* YourCodeOnTheNickListStruct
|
||||
*/
|
||||
NickList *BX_next_nicklist(ChannelList *cptr, NickList *nptr)
|
||||
{
|
||||
unsigned long hvalue = 0;
|
||||
if (!cptr)
|
||||
/* No channel! */
|
||||
return NULL;
|
||||
else if (!nptr)
|
||||
{
|
||||
/* wants to start the walk! */
|
||||
while ((NickList *) cptr->NickListTable[hvalue].list == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue >= NICKLIST_HASHSIZE)
|
||||
return NULL;
|
||||
}
|
||||
return (NickList *) cptr->NickListTable[hvalue].list;
|
||||
}
|
||||
else if (nptr->next)
|
||||
{
|
||||
/* still returning a chain! */
|
||||
return nptr->next;
|
||||
}
|
||||
else if (!nptr->next)
|
||||
{
|
||||
int hvalue;
|
||||
/* hit end of chain, go to next bucket */
|
||||
hvalue = hash_nickname(nptr->nick, NICKLIST_HASHSIZE) + 1;
|
||||
if (hvalue >= NICKLIST_HASHSIZE)
|
||||
{
|
||||
/* end of list */
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((NickList *) cptr->NickListTable[hvalue].list == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue >= NICKLIST_HASHSIZE)
|
||||
return NULL;
|
||||
}
|
||||
/* return head of next filled bucket */
|
||||
return (NickList *) cptr->NickListTable[hvalue].list;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* shouldn't ever be here */
|
||||
say ("HASH_ERROR: next_nicklist");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List *BX_next_namelist(HashEntry *cptr, List *nptr, unsigned int size)
|
||||
{
|
||||
unsigned long hvalue = 0;
|
||||
if (!cptr)
|
||||
/* No channel! */
|
||||
return NULL;
|
||||
else if (!nptr)
|
||||
{
|
||||
/* wants to start the walk! */
|
||||
while ((List *) cptr[hvalue].list == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue >= size)
|
||||
return NULL;
|
||||
}
|
||||
return (List *) cptr[hvalue].list;
|
||||
}
|
||||
else if (nptr->next)
|
||||
{
|
||||
/* still returning a chain! */
|
||||
return nptr->next;
|
||||
}
|
||||
else if (!nptr->next)
|
||||
{
|
||||
int hvalue;
|
||||
/* hit end of chain, go to next bucket */
|
||||
hvalue = hash_nickname(nptr->name, size) + 1;
|
||||
if (hvalue >= size)
|
||||
{
|
||||
/* end of list */
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((List *) cptr[hvalue].list == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue >= size)
|
||||
return NULL;
|
||||
}
|
||||
/* return head of next filled bucket */
|
||||
return (List *) cptr[hvalue].list;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* shouldn't ever be here */
|
||||
say ("HASH_ERROR: next_namelist");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void clear_nicklist_hashtable(ChannelList *cptr)
|
||||
{
|
||||
if (cptr)
|
||||
{
|
||||
memset((char *) cptr->NickListTable, 0,
|
||||
sizeof(HashEntry) * NICKLIST_HASHSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void show_nicklist_hashtable(ChannelList *cptr)
|
||||
{
|
||||
int count, count2;
|
||||
NickList *ptr;
|
||||
|
||||
for (count = 0; count < NICKLIST_HASHSIZE; count++)
|
||||
{
|
||||
if (cptr->NickListTable[count].links == 0)
|
||||
continue;
|
||||
say("HASH DEBUG: %d links %d hits %d",
|
||||
count,
|
||||
cptr->NickListTable[count].links,
|
||||
cptr->NickListTable[count].hits);
|
||||
|
||||
for (ptr = (NickList *) cptr->NickListTable[count].list,
|
||||
count2 = 0; ptr; count2++, ptr = ptr->next)
|
||||
{
|
||||
say("HASH_DEBUG: %d:%d %s!%s", count, count2,
|
||||
ptr->nick, ptr->host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void show_whowas_debug_hashtable(WhowasWrapList *cptr)
|
||||
{
|
||||
int count, count2;
|
||||
WhowasList *ptr;
|
||||
|
||||
for (count = 0; count < WHOWASLIST_HASHSIZE; count++)
|
||||
{
|
||||
if (cptr->NickListTable[count].links == 0)
|
||||
continue;
|
||||
say("HASH DEBUG: %d links %d hits %d",
|
||||
count,
|
||||
cptr->NickListTable[count].links,
|
||||
cptr->NickListTable[count].hits);
|
||||
|
||||
for (ptr = (WhowasList *) cptr->NickListTable[count].list,
|
||||
count2 = 0; ptr; count2++, ptr = ptr->next)
|
||||
{
|
||||
say("HASH_DEBUG: %d:%d %10s %s!%s", count, count2,
|
||||
ptr->channel, ptr->nicklist->nick, ptr->nicklist->host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(show_hash)
|
||||
{
|
||||
char *c;
|
||||
ChannelList *chan = NULL, *chan2;
|
||||
extern int from_server;
|
||||
extern WhowasWrapList whowas_userlist_list;
|
||||
extern WhowasWrapList whowas_reg_list;
|
||||
extern WhowasWrapList whowas_splitin_list;
|
||||
if (args && *args)
|
||||
c = next_arg(args, &args);
|
||||
else
|
||||
c = get_current_channel_by_refnum(0);
|
||||
if (c && from_server > -1)
|
||||
{
|
||||
chan2 = get_server_channels(from_server);
|
||||
chan = (ChannelList *)find_in_list((List **)&chan2, c, 0);
|
||||
}
|
||||
if (chan)
|
||||
show_nicklist_hashtable(chan);
|
||||
show_whowas_debug_hashtable(&whowas_userlist_list);
|
||||
show_whowas_debug_hashtable(&whowas_reg_list);
|
||||
show_whowas_debug_hashtable(&whowas_splitin_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* the following routines are written by Colten Edwards (panasync)
|
||||
* to hash the whowas lists that the client keeps.
|
||||
*/
|
||||
|
||||
static unsigned long hash_userhost_channel(char *userhost, char *channel, unsigned int size)
|
||||
{
|
||||
register const unsigned char *p = (const unsigned char *)userhost;
|
||||
unsigned long g, hash = 0;
|
||||
if (!userhost) return -1;
|
||||
while (*p)
|
||||
{
|
||||
hash = (hash << 4) + ((*p >= 'A' && *p <= 'Z') ? (*p+32) : *p);
|
||||
if ((g = hash & 0xF0000000))
|
||||
hash ^= g >> 24;
|
||||
hash &= ~g;
|
||||
p++;
|
||||
}
|
||||
p = (const unsigned char *)channel;
|
||||
if (p)
|
||||
{
|
||||
while (*p)
|
||||
{
|
||||
if (*p == ',')
|
||||
return -1;
|
||||
hash = (hash << 4) + ((*p >= 'A' && *p <= 'Z') ? (*p+32) : *p);
|
||||
if ((g = hash & 0xF0000000))
|
||||
hash ^= g >> 24;
|
||||
hash &= ~g;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return (hash % size);
|
||||
}
|
||||
|
||||
/*
|
||||
* move_link_to_top: used by find routine, brings link
|
||||
* to the top of the list in the specific array location
|
||||
*/
|
||||
static inline void move_link_to_top_whowas(WhowasList *tmp, WhowasList *prev, HashEntry *location)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
WhowasList *old_list;
|
||||
old_list = (WhowasList *) location->list;
|
||||
location->list = (void *) tmp;
|
||||
prev->next = tmp->next;
|
||||
tmp->next = old_list;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_link_from_list: used by find routine, removes link
|
||||
* from our chain of hashed entries.
|
||||
*/
|
||||
static inline void remove_link_from_whowaslist(WhowasList *tmp, WhowasList *prev, HashEntry *location)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
/* remove the link from the middle of the list */
|
||||
prev->next = tmp->next;
|
||||
}
|
||||
else {
|
||||
/* unlink the first link, and connect next one up */
|
||||
location->list = (void *) tmp->next;
|
||||
}
|
||||
/* set tmp's next to NULL, as its unlinked now */
|
||||
tmp->next = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_nicklist_to_channellist: This function will add the nicklist
|
||||
* into the channellist, ensuring that we hash the nicklist, and
|
||||
* insert the struct correctly into the channelist's Nicklist hash
|
||||
* array
|
||||
*/
|
||||
void BX_add_whowas_userhost_channel(WhowasList *wptr, WhowasWrapList *list)
|
||||
{
|
||||
unsigned long hvalue = hash_userhost_channel(wptr->nicklist->host, wptr->channel, WHOWASLIST_HASHSIZE);
|
||||
|
||||
/* take this nicklist, and attach it as the HEAD pointer
|
||||
* in our chain at the hashed location in our array...
|
||||
* Note, by doing this, this ensures that the "most active"
|
||||
* users always remain at the top of the chain... ie, faster
|
||||
* lookups for active users, (and as a side note, makes
|
||||
* doing the add quite simple!)
|
||||
*/
|
||||
wptr->next = (WhowasList *) list->NickListTable[hvalue].list;
|
||||
|
||||
/* assign our new linked list into array spot */
|
||||
list->NickListTable[hvalue].list = (void *) wptr;
|
||||
/* quick tally of nicks in chain in this array spot */
|
||||
list->NickListTable[hvalue].links++;
|
||||
/* keep stats on hits to this array spot */
|
||||
list->NickListTable[hvalue].hits++;
|
||||
list->total_links++;
|
||||
}
|
||||
|
||||
WhowasList *BX_find_userhost_channel(char *host, char *channel, int remove, WhowasWrapList *wptr)
|
||||
{
|
||||
HashEntry *location;
|
||||
register WhowasList *tmp, *prev = NULL;
|
||||
unsigned long hvalue;
|
||||
|
||||
hvalue = hash_userhost_channel(host, channel, WHOWASLIST_HASHSIZE);
|
||||
location = &(wptr->NickListTable[hvalue]);
|
||||
|
||||
/* at this point, we found the array spot, now search
|
||||
* as regular linked list, or as ircd likes to say...
|
||||
* "We found the bucket, now search the chain"
|
||||
*/
|
||||
for (tmp = (WhowasList *) (&(wptr->NickListTable[hvalue]))->list; tmp; prev = tmp, tmp = tmp->next)
|
||||
{
|
||||
if (!tmp->nicklist->host || !tmp->channel || !host || !channel)
|
||||
continue;
|
||||
if (!my_stricmp(host, tmp->nicklist->host) && !my_stricmp(channel, tmp->channel))
|
||||
{
|
||||
if (remove != REMOVE_FROM_LIST)
|
||||
move_link_to_top_whowas(tmp, prev, location);
|
||||
else
|
||||
{
|
||||
location->links--;
|
||||
remove_link_from_whowaslist(tmp, prev, location);
|
||||
wptr->total_unlinks++;
|
||||
}
|
||||
wptr->total_hits++;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Basically this makes the hash table "look" like a straight linked list
|
||||
* This should be used for things that require you to cycle through the
|
||||
* full list, ex. for finding ALL matching stuff.
|
||||
* : usage should be like :
|
||||
*
|
||||
* for (nptr = next_userhost(cptr, NULL); nptr; nptr =
|
||||
* next_userhost(cptr, nptr))
|
||||
* YourCodeOnTheWhowasListStruct
|
||||
*/
|
||||
WhowasList *BX_next_userhost(WhowasWrapList *cptr, WhowasList *nptr)
|
||||
{
|
||||
unsigned long hvalue = 0;
|
||||
if (!cptr)
|
||||
/* No channel! */
|
||||
return NULL;
|
||||
else if (!nptr)
|
||||
{
|
||||
/* wants to start the walk! */
|
||||
while ((WhowasList *) cptr->NickListTable[hvalue].list == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue >= WHOWASLIST_HASHSIZE)
|
||||
return NULL;
|
||||
}
|
||||
return (WhowasList *) cptr->NickListTable[hvalue].list;
|
||||
}
|
||||
else if (nptr->next)
|
||||
{
|
||||
/* still returning a chain! */
|
||||
return nptr->next;
|
||||
}
|
||||
else if (!nptr->next)
|
||||
{
|
||||
int hvalue;
|
||||
/* hit end of chain, go to next bucket */
|
||||
hvalue = hash_userhost_channel(nptr->nicklist->host, nptr->channel, WHOWASLIST_HASHSIZE) + 1;
|
||||
if (hvalue >= WHOWASLIST_HASHSIZE)
|
||||
{
|
||||
/* end of list */
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((WhowasList *) cptr->NickListTable[hvalue].list == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue >= WHOWASLIST_HASHSIZE)
|
||||
return NULL;
|
||||
}
|
||||
/* return head of next filled bucket */
|
||||
return (WhowasList *) cptr->NickListTable[hvalue].list;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* shouldn't ever be here */
|
||||
say ("WHOWAS_HASH_ERROR: next_userhost");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void show_whowas_hashtable(WhowasWrapList *cptr, char *list)
|
||||
{
|
||||
int count, count2 = 1;
|
||||
WhowasList *ptr;
|
||||
|
||||
say("WhoWas %s Cache Stats: %lu hits %lu links %lu unlinks", list, cptr->total_hits, cptr->total_links, cptr->total_unlinks);
|
||||
for (count = 0; count < WHOWASLIST_HASHSIZE; count++)
|
||||
{
|
||||
|
||||
if (cptr->NickListTable[count].links == 0)
|
||||
continue;
|
||||
for (ptr = (WhowasList *) cptr->NickListTable[count].list; ptr; count2++, ptr = ptr->next)
|
||||
put_it("%s", convert_output_format("%K[%W$[3]0%K] %Y$[10]1 %W$2%G!%c$3", "%d %s %s %s", count2, ptr->channel, ptr->nicklist->nick, ptr->nicklist->host));
|
||||
}
|
||||
}
|
||||
|
||||
int show_wholeft_hashtable(WhowasWrapList *cptr, time_t ltime, int *total, int *hook, char *list)
|
||||
{
|
||||
int count, count2;
|
||||
WhowasList *ptr;
|
||||
|
||||
for (count = 0; count < WHOWASLIST_HASHSIZE; count++)
|
||||
{
|
||||
|
||||
if (cptr->NickListTable[count].links == 0)
|
||||
continue;
|
||||
for (ptr = (WhowasList *) cptr->NickListTable[count].list, count2 = 1; ptr; count2++, ptr = ptr->next)
|
||||
{
|
||||
if (ptr->server1/* && ptr->server2*/)
|
||||
{
|
||||
if (!(*total)++ && (*hook = do_hook(WHOLEFT_HEADER_LIST, "%s %s %s %s %s %s", "Nick", "Host", "Channel", "Time", "Server", "Server")))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_WHOLEFT_HEADER_FSET), NULL));
|
||||
if (do_hook(WHOLEFT_LIST, "%s %s %s %ld %s %s", ptr->nicklist->nick, ptr->nicklist->host, ptr->channel, ltime-ptr->time, ptr->server1?ptr->server1:"Unknown", ptr->server2?ptr->server2:"Unknown"))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_WHOLEFT_USER_FSET), "%s %s %s %l %s", ptr->nicklist->nick, ptr->nicklist->host, ptr->channel, (long)ltime-ptr->time, ptr->server1?ptr->server1:empty_string));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*total)
|
||||
do_hook(WHOLEFT_FOOTER_LIST, "%s", "End of WhoLeft");
|
||||
return *hook;
|
||||
}
|
||||
|
||||
int BX_remove_oldest_whowas_hashlist(WhowasWrapList *list, time_t timet, int count)
|
||||
{
|
||||
WhowasList *ptr;
|
||||
int total = 0;
|
||||
register unsigned long x;
|
||||
if (!count)
|
||||
{
|
||||
for (x = 0; x < WHOWASLIST_HASHSIZE; x++)
|
||||
{
|
||||
ptr = (WhowasList *) (&(list->NickListTable[x]))->list;
|
||||
if (!ptr || !ptr->nicklist)
|
||||
continue;
|
||||
while (ptr)
|
||||
{
|
||||
if ((ptr->time + timet) <= now)
|
||||
{
|
||||
if (!(ptr = find_userhost_channel(ptr->nicklist->host, ptr->channel, 1, list)))
|
||||
break;
|
||||
new_free(&(ptr->nicklist->ip));
|
||||
new_free(&(ptr->nicklist->nick));
|
||||
new_free(&(ptr->nicklist->host));
|
||||
new_free(&(ptr->nicklist->server));
|
||||
new_free((char **)&(ptr->nicklist));
|
||||
new_free(&(ptr->channel));
|
||||
new_free(&(ptr->server1));
|
||||
new_free(&(ptr->server2));
|
||||
new_free((char **)&ptr);
|
||||
total++;
|
||||
ptr = (WhowasList *) (&(list->NickListTable[x]))->list;
|
||||
} else ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while((ptr = next_userhost(list, NULL)) && count)
|
||||
{
|
||||
x = hash_userhost_channel(ptr->nicklist->host, ptr->channel, WHOWASLIST_HASHSIZE);
|
||||
if (!(ptr = find_userhost_channel(ptr->nicklist->host, ptr->channel, 1, list)))
|
||||
break;
|
||||
if (ptr->nicklist)
|
||||
{
|
||||
new_free(&(ptr->nicklist->ip));
|
||||
new_free(&(ptr->nicklist->nick));
|
||||
new_free(&(ptr->nicklist->host));
|
||||
new_free(&(ptr->nicklist->server));
|
||||
new_free((char **)&(ptr->nicklist));
|
||||
}
|
||||
new_free(&(ptr->channel));
|
||||
new_free(&(ptr->server1));
|
||||
new_free(&(ptr->server2));
|
||||
new_free((char **)&ptr);
|
||||
total++; count--;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
int cmp_host (List *a, List *b)
|
||||
{
|
||||
NickList *a1 = (NickList *)a, *b1 = (NickList *)b;
|
||||
return strcmp(a1->host, b1->host);
|
||||
}
|
||||
|
||||
int cmp_time (List *a, List *b)
|
||||
{
|
||||
NickList *a1 = (NickList *)a, *b1 = (NickList *)b;
|
||||
if (a1->idle_time > b1->idle_time)
|
||||
return -1;
|
||||
if (a1->idle_time < b1->idle_time)
|
||||
return 1;
|
||||
return strcmp(a1->nick, b1->nick);
|
||||
}
|
||||
|
||||
|
||||
int cmp_ip (List *a, List *b)
|
||||
{
|
||||
NickList *a1 = (NickList *)a, *b1 = (NickList *)b;
|
||||
unsigned long at, bt;
|
||||
if (!a1->ip && !b1->ip)
|
||||
return -1;
|
||||
/* return strcmp(a1->nick, b1->nick);*/
|
||||
if (!a1->ip)
|
||||
return -1;
|
||||
if (!b1->ip)
|
||||
return 1;
|
||||
at = inet_addr(a1->ip); bt = inet_addr(b1->ip);
|
||||
if (at < bt)
|
||||
return 1;
|
||||
if (at > bt)
|
||||
return -1;
|
||||
return strcmp(a1->nick, b1->nick);
|
||||
}
|
||||
|
||||
int cmp_op (List *a, List *b)
|
||||
{
|
||||
NickList *a1 = (NickList *)a, *b1 = (NickList *)b;
|
||||
int a_isop, b_isop;
|
||||
a_isop = nick_isop(a1);
|
||||
b_isop = nick_isop(b1);
|
||||
if ((!a_isop && !b_isop))
|
||||
return strcmp(a1->nick, b1->nick);
|
||||
if (!a_isop)
|
||||
return 1;
|
||||
if (!b_isop)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmp_voice (List *a, List *b)
|
||||
{
|
||||
NickList *a1 = (NickList *)a, *b1 = (NickList *)b;
|
||||
int a_isvoice, b_isvoice;
|
||||
a_isvoice = nick_isvoice(a1);
|
||||
b_isvoice = nick_isvoice(b1);
|
||||
if ((!a_isvoice && !b_isvoice) || (a_isvoice && b_isvoice))
|
||||
return strcmp(a1->nick, b1->nick);
|
||||
if (!a_isvoice)
|
||||
return -1;
|
||||
if (!b_isvoice)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NickList *BX_sorted_nicklist(ChannelList *chan, int sort)
|
||||
{
|
||||
NickList *tmp, *l = NULL, *list = NULL, *last = NULL;
|
||||
for (tmp = next_nicklist(chan, NULL); tmp; tmp = next_nicklist(chan, tmp))
|
||||
{
|
||||
l = (NickList *)new_malloc(sizeof(NickList));
|
||||
memcpy(l, tmp, sizeof(NickList));
|
||||
l->next = NULL;
|
||||
switch(sort)
|
||||
{
|
||||
case NICKSORT_HOST:
|
||||
add_to_list_ext((List **)&list, (List *)l, cmp_host);
|
||||
break;
|
||||
case NICKSORT_OP:
|
||||
add_to_list_ext((List **)&list, (List *)l, cmp_op);
|
||||
break;
|
||||
case NICKSORT_VOICE:
|
||||
add_to_list_ext((List **)&list, (List *)l, cmp_voice);
|
||||
break;
|
||||
case NICKSORT_TIME:
|
||||
add_to_list_ext((List **)&list, (List *)l, cmp_time);
|
||||
break;
|
||||
case NICKSORT_IP:
|
||||
add_to_list_ext((List **)&list, (List *)l, cmp_ip);
|
||||
break;
|
||||
case NICKSORT_NONE:
|
||||
if (last)
|
||||
last->next = l;
|
||||
else
|
||||
list = l;
|
||||
break;
|
||||
default:
|
||||
case NICKSORT_NORMAL:
|
||||
add_to_list((List **)&list, (List *)l);
|
||||
break;
|
||||
}
|
||||
last = l;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void BX_clear_sorted_nicklist(NickList **list)
|
||||
{
|
||||
register NickList *t;
|
||||
while(*list)
|
||||
{
|
||||
t = (*list)->next;
|
||||
new_free((char **)&(*list));
|
||||
*list = t;
|
||||
}
|
||||
}
|
||||
|
||||
Flooding *BX_add_name_to_floodlist(char *name, char *host, char *channel, HashEntry *list, unsigned int size)
|
||||
{
|
||||
Flooding *nptr;
|
||||
unsigned long hvalue = hash_nickname(name, size);
|
||||
nptr = (Flooding *)new_malloc(sizeof(Flooding));
|
||||
nptr->next = (Flooding *) list[hvalue].list;
|
||||
nptr->name = m_strdup(name);
|
||||
nptr->host = m_strdup(host);
|
||||
list[hvalue].list = (void *) nptr;
|
||||
/* quick tally of nicks in chain in this array spot */
|
||||
list[hvalue].links++;
|
||||
/* keep stats on hits to this array spot */
|
||||
list[hvalue].hits++;
|
||||
return nptr;
|
||||
}
|
||||
|
||||
Flooding *BX_find_name_in_floodlist(char *name, char *host, HashEntry *list, unsigned int size, int remove)
|
||||
{
|
||||
HashEntry *location;
|
||||
register Flooding *tmp, *prev = NULL;
|
||||
unsigned long hvalue = hash_nickname(name, size);
|
||||
|
||||
location = &(list[hvalue]);
|
||||
|
||||
/* at this point, we found the array spot, now search
|
||||
* as regular linked list, or as ircd likes to say...
|
||||
* "We found the bucket, now search the chain"
|
||||
*/
|
||||
for (tmp = (Flooding *) location->list; tmp; prev = tmp, tmp = tmp->next)
|
||||
{
|
||||
if (!my_stricmp(name, tmp->name))
|
||||
{
|
||||
if (remove != REMOVE_FROM_LIST)
|
||||
move_gen_link_to_top((List *)tmp, (List *)prev, location);
|
||||
else
|
||||
{
|
||||
location->links--;
|
||||
remove_gen_link_from_list((List *)tmp, (List *)prev, location);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
259
source/hebrew.c
Normal file
259
source/hebrew.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* hebrew.c
|
||||
* by crisk
|
||||
*
|
||||
* MS-Windows like Hebrew process routine
|
||||
*
|
||||
* This first started as an ircII script.. the function was
|
||||
* ported almost 1 to 1 from the script, so you can excuse
|
||||
* the extreme mess.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
#include "ircaux.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#ifdef WANT_HEBREW
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
unsigned char *heb_reverse(char translate, unsigned char *str)
|
||||
{
|
||||
unsigned char tmp1,tmp2;
|
||||
int ind,len,transind;
|
||||
unsigned char *transloc;
|
||||
|
||||
unsigned char *transfrom = "()[]{}";
|
||||
unsigned char *transto = ")(][}{";
|
||||
|
||||
len = strlen(str)-1;
|
||||
|
||||
for (ind=0;ind<((len+1)/2);ind++)
|
||||
{
|
||||
tmp1 = *(str+ind);
|
||||
tmp2 = *(str+len-ind);
|
||||
|
||||
if (translate)
|
||||
{
|
||||
transloc = index(transfrom,tmp1);
|
||||
if (transloc != NULL)
|
||||
{
|
||||
transind = transloc-transfrom;
|
||||
tmp1 = *(transto+transind);
|
||||
}
|
||||
|
||||
transloc = index(transfrom,tmp2);
|
||||
if (transloc != NULL)
|
||||
{
|
||||
transind = transloc-transfrom;
|
||||
tmp2 = *(transto+transind);
|
||||
}
|
||||
}
|
||||
*(str+ind) = tmp2;
|
||||
*(str+len-ind) = tmp1;
|
||||
}
|
||||
|
||||
if (translate)
|
||||
if (len % 2)
|
||||
{
|
||||
ind = (len % 2)+1;
|
||||
transloc = index(transfrom,*(str+ind));
|
||||
if (transloc != NULL)
|
||||
{
|
||||
transind = transloc-transfrom;
|
||||
*(str+ind) = *(transto+transind);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
unsigned char *hebrew_process(unsigned char *str)
|
||||
{
|
||||
|
||||
#define hebrew_isheb(x) ((x >= 224) && (x <= 256))
|
||||
#define hebrew_iseng(x) (((x >= 'a') && (x <= 'z')) || ((x >= 'A') && (x <= 'Z')))
|
||||
#define hebrew_isnum(x) ((x >= '0') && (x <= '9'))
|
||||
|
||||
unsigned char *engspecial = "";
|
||||
unsigned char *numrelated = "+-/.,";
|
||||
|
||||
int len;
|
||||
|
||||
unsigned char *result;
|
||||
unsigned char let;
|
||||
unsigned char *tmpstr;
|
||||
unsigned char *tmpbuf;
|
||||
int pos;
|
||||
int p;
|
||||
int mode;
|
||||
int pnum;
|
||||
int pnumplus;
|
||||
int ppp;
|
||||
int j,j2;
|
||||
|
||||
if (!str || !*str)
|
||||
return empty_string;
|
||||
len = strlen(str);
|
||||
|
||||
result = (unsigned char *)new_malloc(len+2);
|
||||
tmpstr = (unsigned char *)new_malloc(len*2);
|
||||
tmpbuf = (unsigned char *)new_malloc(len*2);
|
||||
|
||||
pos = 0;
|
||||
p = 0;
|
||||
pnum = 0;
|
||||
mode = 0;
|
||||
|
||||
while (pos < len)
|
||||
{
|
||||
let = str[pos];
|
||||
pos++;
|
||||
tmpstr[0] = let;
|
||||
tmpstr[1] = '\0';
|
||||
|
||||
if ((hebrew_iseng(let)) || (index(engspecial,let) != NULL))
|
||||
{
|
||||
|
||||
strcat(tmpstr,tmpbuf);
|
||||
|
||||
strcat(tmpstr,result);
|
||||
strcpy(result,tmpstr);
|
||||
tmpbuf[0] = '\0';
|
||||
tmpstr[1] = '\0';
|
||||
|
||||
p = 0;
|
||||
mode = 1;
|
||||
pnum = 0;
|
||||
} else if (hebrew_isheb(let))
|
||||
{
|
||||
if (mode)
|
||||
{
|
||||
strcat(tmpbuf,result);
|
||||
strcpy(result,tmpbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpbuf = heb_reverse(1,tmpbuf);
|
||||
strcat(tmpbuf,tmpstr);
|
||||
strcpy(tmpstr,tmpbuf);
|
||||
}
|
||||
|
||||
mode = 0;
|
||||
|
||||
for (j=0;j<p;j++)
|
||||
*(tmpbuf+j) = *(result+j);
|
||||
|
||||
for (j2=0;j2<strlen(tmpstr);j2++)
|
||||
*(tmpbuf+j+j2) = *(tmpstr+j2);
|
||||
|
||||
for (j=j;j<=strlen(result);j++)
|
||||
*(tmpbuf+j+j2) = *(result+j);
|
||||
|
||||
*(tmpbuf+j+j2) = '\0';
|
||||
strcpy(result,tmpbuf);
|
||||
tmpbuf[0] = '\0';
|
||||
|
||||
p += strlen(tmpstr);
|
||||
pnum = 0;
|
||||
}
|
||||
else if (hebrew_isnum(let))
|
||||
{
|
||||
if (!mode)
|
||||
{
|
||||
tmpbuf = heb_reverse(1,tmpbuf);
|
||||
pnumplus = 0;
|
||||
|
||||
if (tmpbuf[0] != '\0')
|
||||
{
|
||||
if ((strlen(tmpbuf) == 1) && (index(numrelated,tmpbuf[0])))
|
||||
{
|
||||
strcat(tmpstr,tmpbuf);
|
||||
tmpbuf[0] = '\0';
|
||||
pnumplus = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pnum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
strcat(tmpbuf,tmpstr);
|
||||
strcpy(tmpstr,tmpbuf);
|
||||
|
||||
ppp = p-pnum;
|
||||
|
||||
for (j=0;j<ppp;j++)
|
||||
*(tmpbuf+j) = *(result+j);
|
||||
|
||||
for (j2=0;j2<strlen(tmpstr);j2++)
|
||||
*(tmpbuf+j+j2) = *(tmpstr+j2);
|
||||
|
||||
for (j=j;j<=strlen(result);j++)
|
||||
*(tmpbuf+j+j2) = *(result+j);
|
||||
|
||||
*(tmpbuf+j+j2) = '\0';
|
||||
|
||||
strcpy(result,tmpbuf);
|
||||
|
||||
tmpbuf[0] = '\0';
|
||||
|
||||
p += strlen(tmpstr);
|
||||
pnum++;
|
||||
pnum += pnumplus;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(tmpstr,tmpbuf);
|
||||
strcat(tmpstr,result);
|
||||
strcpy(result,tmpstr);
|
||||
tmpbuf[0]='\0';
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(tmpstr,tmpbuf);
|
||||
strcpy(tmpbuf,tmpstr);
|
||||
}
|
||||
}
|
||||
|
||||
mode = 1; /* MS-Hebrew behavior thing */
|
||||
|
||||
if (mode)
|
||||
{
|
||||
strcat(tmpbuf,result);
|
||||
strcpy(result,tmpbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpbuf = heb_reverse(1,tmpbuf);
|
||||
strcpy(tmpstr,tmpbuf);
|
||||
|
||||
for (j=0;j<p;j++)
|
||||
*(tmpbuf+j) = *(result+j);
|
||||
|
||||
for (j2=0;j2<strlen(tmpstr);j2++)
|
||||
*(tmpbuf+j+j2) = *(tmpstr+j2);
|
||||
|
||||
for (j=j;j<=strlen(result);j++)
|
||||
*(tmpbuf+j+j2) = *(result+j);
|
||||
|
||||
strcpy(result,tmpbuf);
|
||||
}
|
||||
|
||||
result = heb_reverse(0,result);
|
||||
|
||||
strcpy(str,result);
|
||||
|
||||
new_free(&result);
|
||||
new_free(&tmpstr);
|
||||
new_free(&tmpbuf);
|
||||
|
||||
return str;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
763
source/help.c
Normal file
763
source/help.c
Normal file
@@ -0,0 +1,763 @@
|
||||
/*
|
||||
* help.c: handles the help stuff for irc
|
||||
*
|
||||
* Written by Michael Sandrof
|
||||
* Extensively modified by Troy Rollo
|
||||
* Re-modified by Matthew Green
|
||||
*
|
||||
* Copyright(c) 1992
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
/*
|
||||
* This has been replaced almost entirely from the original by Michael
|
||||
* Sandrof in order to fit in with the multiple screen code.
|
||||
*
|
||||
* ugh, this wasn't easy to do, but I got there, after working out what
|
||||
* had been changed and why, by myself - phone, October 1992.
|
||||
*
|
||||
* And when I started getting /window create working, I discovered new
|
||||
* bugs, and there has been a few more major changes in here again.
|
||||
* It is invalid to call help from more than one screen, at the moment,
|
||||
* because there is to much to keep track of - phone, jan 1993.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static char rcsid[] = "@(#)$Id: help.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
#endif
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: help.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(help_c)
|
||||
|
||||
#ifdef WANT_EPICHELP
|
||||
#include "struct.h"
|
||||
#include "help.h"
|
||||
#include "input.h"
|
||||
#include "ircaux.h"
|
||||
#include "hook.h"
|
||||
#include "output.h"
|
||||
#include "screen.h"
|
||||
#include "server.h"
|
||||
#include "ircterm.h"
|
||||
#include "vars.h"
|
||||
#include "window.h"
|
||||
#include <sys/stat.h>
|
||||
#include "bsdglob.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
static void help_me (char *, char *);
|
||||
static void help_show_paused_topic (char *, char *);
|
||||
static void create_help_window (void);
|
||||
static void set_help_screen (Screen *);
|
||||
static void help_put_it (const char *topic, const char *format, ...);
|
||||
|
||||
/*
|
||||
* A few variables here - A lot added to get help working with
|
||||
* non - recursive calls to irc_io, and also have it still
|
||||
* reading things from the server(s), so not to ping timeout.
|
||||
*/
|
||||
static int dont_pause_topic = 0;
|
||||
static int entry_size;
|
||||
static int finished_help_paging = 0;
|
||||
static FILE * help_fp;
|
||||
#define HELP_PAUSED_LINES_MAX 500
|
||||
static int help_paused_lines = 0;
|
||||
static char * help_paused_topic[HELP_PAUSED_LINES_MAX]; /* Should be enough */
|
||||
static Screen *help_screen = (Screen *) 0;
|
||||
static int help_show_directory = 0;
|
||||
static char help_topic_list[BIG_BUFFER_SIZE + 1];
|
||||
static Window *help_window = (Window *) 0;
|
||||
static char no_help[] = "NOHELP";
|
||||
static char paused_topic[128];
|
||||
static char * this_arg;
|
||||
static int use_help_window = 0;
|
||||
|
||||
|
||||
/*
|
||||
* show_help: show's either a page of text from a help_fp, or the whole
|
||||
* thing, depending on the value of HELP_PAGER_VAR. If it gets to the end,
|
||||
* (in either case it will eventally), it closes the file, and returns 0
|
||||
* to indicate this.
|
||||
*/
|
||||
static int show_help (Window *window, char *name)
|
||||
{
|
||||
Window *old_target_window = target_window;
|
||||
int rows = 0;
|
||||
char line[256];
|
||||
|
||||
target_window = window ? window : current_window;
|
||||
|
||||
if (get_int_var(HELP_PAGER_VAR))
|
||||
rows = window->display_size;
|
||||
|
||||
while (rows)
|
||||
{
|
||||
if (!fgets(line, 255, help_fp))
|
||||
{
|
||||
fclose(help_fp);
|
||||
help_fp = NULL;
|
||||
target_window = old_target_window;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*(line + strlen(line) - 1) == '\n')
|
||||
*(line + strlen(line) - 1) = (char) 0;
|
||||
|
||||
/*
|
||||
* This is for compatability with ircII-4.4
|
||||
*/
|
||||
if (*line == '!' || *line == '#')
|
||||
continue;
|
||||
|
||||
help_put_it(name, "%s", line);
|
||||
rows--;
|
||||
}
|
||||
|
||||
target_window = old_target_window;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* help_prompt: The main procedure called to display the help file
|
||||
* currently being accessed. Using add_wait_prompt(), it sets it
|
||||
* self up to be recalled when the next page is asked for. If
|
||||
* called when we have finished paging the help file, we exit, as
|
||||
* there is nothing left to show. If line is 'q' or 'Q', exit the
|
||||
* help pager, clean up, etc.. If all is cool for now, we call
|
||||
* show_help, and either if its finished, exit, or prompt for the
|
||||
* next page. From here, if we've finished the help page, and
|
||||
* doing help prompts, prompt for the help..
|
||||
*/
|
||||
static void help_prompt (char *name, char *line)
|
||||
{
|
||||
if (finished_help_paging)
|
||||
{
|
||||
if (*paused_topic)
|
||||
help_show_paused_topic(paused_topic, empty_string);
|
||||
return;
|
||||
}
|
||||
|
||||
if (line && toupper(*line) == 'Q')
|
||||
{
|
||||
finished_help_paging = 1;
|
||||
#if 0
|
||||
help_paused_lines = 0; /* Thanks robo */
|
||||
#endif
|
||||
fclose(help_fp);
|
||||
help_fp = NULL;
|
||||
set_help_screen((Screen *) 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (show_help(help_window, name))
|
||||
{
|
||||
if (dumb_mode)
|
||||
help_prompt(name, NULL);
|
||||
else
|
||||
add_wait_prompt("*** Hit any key for more, 'q' to quit ***",
|
||||
help_prompt, name, WAIT_PROMPT_KEY, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
finished_help_paging = 1;
|
||||
if (help_fp)
|
||||
fclose(help_fp);
|
||||
help_fp = NULL;
|
||||
|
||||
if (help_show_directory)
|
||||
{
|
||||
if (get_int_var(HELP_PAGER_VAR))
|
||||
{
|
||||
if (dumb_mode)
|
||||
help_show_paused_topic(name, empty_string);
|
||||
else
|
||||
add_wait_prompt("*** Hit any key to end ***",
|
||||
help_show_paused_topic, paused_topic,
|
||||
WAIT_PROMPT_KEY, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
help_show_paused_topic(paused_topic, empty_string);
|
||||
set_help_screen((Screen *) 0);
|
||||
}
|
||||
help_show_directory = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (finished_help_paging)
|
||||
{
|
||||
if (get_int_var(HELP_PROMPT_VAR))
|
||||
{
|
||||
char tmp[BIG_BUFFER_SIZE + 1];
|
||||
|
||||
sprintf(tmp, "%s%sHelp? ", help_topic_list,
|
||||
*help_topic_list ? space : empty_string);
|
||||
if (!dumb_mode)
|
||||
add_wait_prompt(tmp, help_me, help_topic_list,
|
||||
WAIT_PROMPT_LINE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*paused_topic)
|
||||
help_show_paused_topic(paused_topic, empty_string);
|
||||
set_help_screen((Screen *) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* help_topic: Given a topic, we search the help directory, and try to
|
||||
* find the right file, if all is cool, and we can open it, or zcat it,
|
||||
* then we call help_prompt to get the actually displaying of the file
|
||||
* on the road.
|
||||
*/
|
||||
static void help_topic (char *path, char *name)
|
||||
{
|
||||
char *filename = NULL;
|
||||
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
/* what is the base name? */
|
||||
filename = m_sprintf("%s/%s", path, name);
|
||||
if (filename[strlen(filename)-1] == '/')
|
||||
chop(filename, 1);
|
||||
|
||||
/* let uzfopen have all the fun */
|
||||
if ((help_fp = uzfopen (&filename, path, 0)))
|
||||
{
|
||||
/* Isnt this a heck of a lot better then the kludge you were using? */
|
||||
help_put_it(name, "*** Help on %s", name);
|
||||
help_prompt(name, NULL);
|
||||
}
|
||||
else
|
||||
help_put_it (name, "*** No help available on %s: Use ? for list of topics", name);
|
||||
|
||||
new_free(&filename);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* help_pause_add_line: this procedure does a help_put_it() call, but
|
||||
* puts off the calling, until help_show_paused_topic() is called.
|
||||
* I do this because I need to create the list of help topics, but
|
||||
* not show them, until we've seen the whole file, so we called
|
||||
* help_show_paused_topic() when we've seen the file, if it is needed.
|
||||
*/
|
||||
static void help_pause_add_line (char *format, ...)
|
||||
{
|
||||
char buf[BIG_BUFFER_SIZE];
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
vsnprintf(buf, BIG_BUFFER_SIZE - 1, format, args);
|
||||
va_end (args);
|
||||
if ((help_paused_lines + 1) >= HELP_PAUSED_LINES_MAX)
|
||||
ircpanic("help_pause_add_line: would overflow the buffer");
|
||||
malloc_strcpy(&help_paused_topic[help_paused_lines++], buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* help_show_paused_topic: see above. Called when we've seen the
|
||||
* whole help file, and we have a list of topics to display.
|
||||
*/
|
||||
static void help_show_paused_topic (char *name, char *line)
|
||||
{
|
||||
static int i = 0;
|
||||
int j = 0;
|
||||
int rows;
|
||||
|
||||
if (!help_paused_lines)
|
||||
return;
|
||||
|
||||
if (toupper(*line) == 'Q')
|
||||
i = help_paused_lines + 1; /* just big enough */
|
||||
|
||||
rows = help_window->display_size;
|
||||
if (i < help_paused_lines)
|
||||
{
|
||||
for (j = 0; j < rows; j++)
|
||||
{
|
||||
help_put_it (name, "%s", help_paused_topic[i]);
|
||||
new_free(&help_paused_topic[i]);
|
||||
|
||||
/* if we're done, the recurse to break loop */
|
||||
if (++i >= help_paused_lines)
|
||||
break;
|
||||
}
|
||||
if (!dumb_mode)
|
||||
{
|
||||
if ((i < help_paused_lines) && get_int_var(HELP_PAGER_VAR))
|
||||
add_wait_prompt("[MORE]", help_show_paused_topic, name, WAIT_PROMPT_KEY, 1);
|
||||
}
|
||||
else
|
||||
help_show_paused_topic(name, line);
|
||||
}
|
||||
|
||||
/*
|
||||
* This cant be an else of the previous if because 'i' can
|
||||
* change in the previous if and we need to test it again
|
||||
*/
|
||||
if (i >= help_paused_lines)
|
||||
{
|
||||
if (get_int_var(HELP_PROMPT_VAR))
|
||||
{
|
||||
char buf[BIG_BUFFER_SIZE];
|
||||
|
||||
sprintf(buf, "%s%sHelp? ", name, (name && *name) ? space : empty_string);
|
||||
if (!dumb_mode)
|
||||
add_wait_prompt(buf, help_me, name, WAIT_PROMPT_LINE, 1);
|
||||
}
|
||||
else
|
||||
set_help_screen((Screen *) 0);
|
||||
|
||||
dont_pause_topic = 0;
|
||||
help_paused_lines = 0; /* Probably should reset this ;-) */
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* help_me: The big one. The help procedure that handles working out
|
||||
* what was actually requested, sets up the paused topic list if it is
|
||||
* needed, does pretty much all the hard work.
|
||||
*/
|
||||
static void help_me (char *topics, char *args)
|
||||
{
|
||||
char * ptr;
|
||||
glob_t g;
|
||||
int entries = 0,
|
||||
cnt,
|
||||
i,
|
||||
cols;
|
||||
struct stat stat_buf;
|
||||
char path[BIG_BUFFER_SIZE+1];
|
||||
int help_paused_first_call = 0;
|
||||
char * help_paused_path = (char *) 0;
|
||||
char * help_paused_name = (char *) 0;
|
||||
char * temp;
|
||||
char tmp[BIG_BUFFER_SIZE+1];
|
||||
char buffer[BIG_BUFFER_SIZE+1];
|
||||
char * pattern = NULL;
|
||||
|
||||
strcpy(help_topic_list, topics);
|
||||
ptr = get_string_var(HELP_PATH_VAR);
|
||||
|
||||
sprintf(path, "%s/%s", ptr, topics);
|
||||
for (ptr = path; (ptr = strchr(ptr, ' '));)
|
||||
*ptr = '/';
|
||||
|
||||
/*
|
||||
* first we check access to the help dir, whinge if we can't, then
|
||||
* work out we need to ask them for more help, else we check the
|
||||
* args list, and do the stuff
|
||||
*/
|
||||
if (help_show_directory)
|
||||
{
|
||||
help_show_paused_topic(paused_topic, empty_string);
|
||||
help_show_directory = 0;
|
||||
}
|
||||
|
||||
finished_help_paging = 0;
|
||||
if (access(path, R_OK|X_OK))
|
||||
{
|
||||
help_put_it(no_help, "*** Cannot access help directory!");
|
||||
set_help_screen((Screen *) 0);
|
||||
return;
|
||||
}
|
||||
|
||||
this_arg = next_arg(args, &args);
|
||||
if (!this_arg && *help_topic_list && get_int_var(HELP_PROMPT_VAR))
|
||||
{
|
||||
if ((temp = strrchr(help_topic_list, ' ')) != NULL)
|
||||
*temp = '\0';
|
||||
else
|
||||
*help_topic_list = '\0';
|
||||
|
||||
sprintf(tmp, "%s%sHelp? ", help_topic_list, *help_topic_list ? space : empty_string);
|
||||
|
||||
if (!dumb_mode)
|
||||
add_wait_prompt(tmp, help_me, help_topic_list, WAIT_PROMPT_LINE, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this_arg)
|
||||
{
|
||||
set_help_screen((Screen *) 0);
|
||||
return;
|
||||
}
|
||||
|
||||
create_help_window();
|
||||
|
||||
/*
|
||||
* This is just a bogus while loop which is intended to allow
|
||||
* the user to do '/help alias expressions' without having to
|
||||
* include a slash inbetween the topic and subtopic.
|
||||
*
|
||||
* If all goes well, we 'break' at the bottom of the loop.
|
||||
*/
|
||||
while (this_arg)
|
||||
{
|
||||
entries = 0;
|
||||
reset_display_target();
|
||||
|
||||
if (!*this_arg)
|
||||
help_topic(path, NULL);
|
||||
|
||||
if (strcmp(this_arg, "?") == 0)
|
||||
{
|
||||
this_arg = empty_string;
|
||||
if (!dont_pause_topic)
|
||||
dont_pause_topic = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* entry_size is set to the width of the longest help topic
|
||||
* (adjusted for compression extensions, of course.)
|
||||
*/
|
||||
entry_size = 0;
|
||||
|
||||
/*
|
||||
* Gather up the names of the files in the help directory.
|
||||
*/
|
||||
{
|
||||
#ifndef HAVE_FCHDIR
|
||||
char opath[MAXPATHLEN + 1];
|
||||
getcwd(opath, MAXPATHLEN);
|
||||
#else
|
||||
int cwd = open(".", O_RDONLY);
|
||||
#endif
|
||||
|
||||
chdir(path);
|
||||
pattern = alloca(strlen(path) + 2 +
|
||||
strlen(this_arg) + 3);
|
||||
strcpy(pattern, this_arg);
|
||||
strcat(pattern, "*");
|
||||
#ifdef GLOB_INSENSITIVE
|
||||
bsd_glob(pattern, GLOB_INSENSITIVE /* GLOB_MARK */, NULL, &g);
|
||||
#else
|
||||
bsd_glob(pattern, 0 /* GLOB_MARK */, NULL, &g);
|
||||
#endif
|
||||
#ifndef HAVE_FCHDIR
|
||||
chdir(opath);
|
||||
#else
|
||||
fchdir(cwd);
|
||||
close(cwd);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < g.gl_matchc; i++)
|
||||
{
|
||||
char *tmp = g.gl_pathv[i];
|
||||
int len = strlen(tmp);
|
||||
|
||||
if (!end_strcmp(tmp, ".gz", 3))
|
||||
len -= 3;
|
||||
else if (!end_strcmp(tmp, ".bz2", 4))
|
||||
len -= 4;
|
||||
entry_size = (len > entry_size) ? len : entry_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Right here we need to check for an 'exact match'.
|
||||
* An 'exact match' would be sitting in gl_pathv[0],
|
||||
* and it is 'exact' if it is identical to what we are
|
||||
* looking for, or if it is the same except that it has
|
||||
* a compression extension on it
|
||||
*/
|
||||
if (g.gl_matchc > 1)
|
||||
{
|
||||
char *str1 = g.gl_pathv[0];
|
||||
char *str2 = this_arg;
|
||||
int len1 = strlen(str1);
|
||||
int len2 = strlen(str2);
|
||||
|
||||
|
||||
if (len1 == len2 && !my_stricmp(str1, str2))
|
||||
entries = 1;
|
||||
else if (len1 - 3 == len2 && !my_strnicmp(str1, str2, len2) && !end_strcmp(str1, ".gz", 3))
|
||||
entries = 1;
|
||||
else if (len1 - 2 == len2 && !my_strnicmp(str1, str2, len2) && !end_strcmp(str1, ".Z", 2))
|
||||
entries = 1;
|
||||
else if (len1 - 2 == len2 && !my_strnicmp(str1, str2, len2) && !end_strcmp(str1, ".z", 2))
|
||||
entries = 1;
|
||||
}
|
||||
|
||||
if (!*help_topic_list)
|
||||
dont_pause_topic = 1;
|
||||
|
||||
/* reformatted */
|
||||
/*
|
||||
* entries: -1 means something really died, 0 means there
|
||||
* was no help, 1, means it wasn't a directory, and so to
|
||||
* show the help file, and the default means to add the
|
||||
* stuff to the paused topic list..
|
||||
*/
|
||||
if (!entries)
|
||||
entries = g.gl_matchc;
|
||||
|
||||
switch (entries)
|
||||
{
|
||||
case -1:
|
||||
{
|
||||
help_put_it(no_help, "*** Error during help function: %s", strerror(errno));
|
||||
set_help_screen(NULL);
|
||||
if (help_paused_first_call)
|
||||
{
|
||||
help_topic(help_paused_path, help_paused_name);
|
||||
help_paused_first_call = 0;
|
||||
new_free(&help_paused_path);
|
||||
new_free(&help_paused_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
help_put_it(this_arg, "*** No help available on %s: Use ? for list of topics", this_arg);
|
||||
if (!get_int_var(HELP_PROMPT_VAR))
|
||||
{
|
||||
set_help_screen(NULL);
|
||||
break;
|
||||
}
|
||||
sprintf(tmp, "%s%sHelp? ", help_topic_list, *help_topic_list ? space : empty_string);
|
||||
if (!dumb_mode)
|
||||
add_wait_prompt(tmp, help_me, help_topic_list, WAIT_PROMPT_LINE, 1);
|
||||
|
||||
if (help_paused_first_call)
|
||||
{
|
||||
help_topic(help_paused_path, help_paused_name);
|
||||
help_paused_first_call = 0;
|
||||
new_free(&help_paused_path);
|
||||
new_free(&help_paused_name);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
sprintf(tmp, "%s/%s", path, g.gl_pathv[0]);
|
||||
stat(tmp, &stat_buf);
|
||||
if (stat_buf.st_mode & S_IFDIR)
|
||||
{
|
||||
strcpy(path, tmp);
|
||||
if (*help_topic_list)
|
||||
strcat(help_topic_list, space);
|
||||
|
||||
strcat(help_topic_list, g.gl_pathv[0]);
|
||||
|
||||
if (!(this_arg = next_arg(args, &args)))
|
||||
{
|
||||
help_paused_first_call = 1;
|
||||
malloc_strcpy(&help_paused_path, path);
|
||||
malloc_strcpy(&help_paused_name, g.gl_pathv[0]);
|
||||
dont_pause_topic = -1;
|
||||
this_arg = "?";
|
||||
}
|
||||
bsd_globfree(&g);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
help_topic(path, g.gl_pathv[0]);
|
||||
finished_help_paging = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
help_show_directory = 1;
|
||||
strcpy(paused_topic, help_topic_list);
|
||||
help_pause_add_line("*** %s choices:", help_topic_list);
|
||||
entry_size += 2;
|
||||
cols = (current_term->TI_cols - 10) / entry_size;
|
||||
|
||||
strcpy(buffer, empty_string);
|
||||
cnt = 0;
|
||||
|
||||
for (i = 0; i < entries; i++)
|
||||
{
|
||||
if (!end_strcmp(g.gl_pathv[i], ".gz", 3))
|
||||
chop(g.gl_pathv[i], 3);
|
||||
else if (!end_strcmp(g.gl_pathv[i], ".bz2", 4))
|
||||
chop(g.gl_pathv[i], 4);
|
||||
strcat(buffer, g.gl_pathv[i]);
|
||||
|
||||
/*
|
||||
* Since we already know how many columns each
|
||||
* line will contain, we check to see if we have
|
||||
* accumulated that many entries. If we have, we
|
||||
* output the line to the screen.
|
||||
*/
|
||||
if (++cnt == cols)
|
||||
{
|
||||
help_pause_add_line("%s", buffer);
|
||||
strcpy(buffer, empty_string);
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have not finished this line, then we have
|
||||
* to pad the name length out to the expected width.
|
||||
* 'entry_size' is the column width. We also have
|
||||
* do adjust for compression extension.
|
||||
*/
|
||||
else
|
||||
strextend(buffer, ' ', entry_size - strlen(g.gl_pathv[i]));
|
||||
}
|
||||
|
||||
help_pause_add_line("%s", buffer);
|
||||
if (help_paused_first_call)
|
||||
{
|
||||
help_topic(help_paused_path, help_paused_name);
|
||||
help_paused_first_call = 0;
|
||||
new_free(&help_paused_path);
|
||||
new_free(&help_paused_name);
|
||||
}
|
||||
if (dont_pause_topic == 1)
|
||||
{
|
||||
help_show_paused_topic(paused_topic, empty_string);
|
||||
help_show_directory = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* end of reformatting */
|
||||
|
||||
|
||||
bsd_globfree(&g);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This one is for when there was never a topic and the prompt
|
||||
* never got a topic.. and help_screen was never reset..
|
||||
* phone, jan 1993.
|
||||
*/
|
||||
if (!*help_topic_list && finished_help_paging)
|
||||
set_help_screen((Screen *) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* help: the HELP command, gives help listings for any and all topics out
|
||||
* there
|
||||
*/
|
||||
BUILT_IN_COMMAND(epichelp)
|
||||
{
|
||||
char *help_path;
|
||||
|
||||
finished_help_paging = 0;
|
||||
help_show_directory = 0;
|
||||
dont_pause_topic = 0;
|
||||
use_help_window = 0;
|
||||
|
||||
/*
|
||||
* The idea here is to work out what sort of help we are using -
|
||||
* either the installed help files, or some help service, what
|
||||
* ever it maybe. Once we have worked this out, if we are using
|
||||
* a help window, set it up properly.
|
||||
*/
|
||||
help_path = get_string_var(HELP_PATH_VAR);
|
||||
|
||||
if (!help_path || !*help_path || access(help_path, R_OK | X_OK))
|
||||
{
|
||||
help_put_it(no_help, "*** HELP_PATH variable not set or set to an invalid path");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allow us to wait until help is finished */
|
||||
if (!my_strnicmp(args, "-wait", 2))
|
||||
{
|
||||
while (help_screen)
|
||||
io("help");
|
||||
return;
|
||||
}
|
||||
|
||||
if (help_path && help_screen && help_screen != current_window->screen)
|
||||
{
|
||||
say("You may not run help in two screens");
|
||||
return;
|
||||
}
|
||||
|
||||
help_screen = current_window->screen;
|
||||
help_window = (Window *) 0;
|
||||
help_me(empty_string, (args && *args) ? args : "?");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void create_help_window (void)
|
||||
{
|
||||
if (help_window)
|
||||
return;
|
||||
|
||||
if (!dumb_mode && get_int_var(HELP_WINDOW_VAR))
|
||||
{
|
||||
use_help_window = 1;
|
||||
help_window = new_window(current_window->screen);
|
||||
help_window->hold_mode = OFF;
|
||||
help_window->window_level = LOG_HELP;
|
||||
update_all_windows();
|
||||
}
|
||||
else
|
||||
help_window = current_window;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void set_help_screen (Screen *screen)
|
||||
{
|
||||
help_screen = screen;
|
||||
if (!help_screen && help_window)
|
||||
{
|
||||
if (use_help_window)
|
||||
{
|
||||
int display = window_display;
|
||||
|
||||
window_display = 0;
|
||||
delete_window(help_window);
|
||||
window_display = display;
|
||||
}
|
||||
help_window = (Window *) 0;
|
||||
update_all_windows();
|
||||
}
|
||||
}
|
||||
|
||||
static void help_put_it (const char *topic, const char *format, ...)
|
||||
{
|
||||
char putbuf[BIG_BUFFER_SIZE * 3 + 1];
|
||||
|
||||
if (format)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vsnprintf(putbuf, BIG_BUFFER_SIZE * 3, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (do_hook(HELP_LIST, "%s %s", topic, putbuf))
|
||||
{
|
||||
int old_level = who_level;
|
||||
Window *old_target_window = target_window;
|
||||
|
||||
/*
|
||||
* LOG_HELP is a completely bogus mode. We use
|
||||
* it only to make sure that the current level is
|
||||
* not LOG_CURRENT, so that the to_window will stick.
|
||||
*/
|
||||
who_level = LOG_HELP;
|
||||
if (help_window)
|
||||
target_window = help_window;
|
||||
add_to_screen(putbuf);
|
||||
target_window = old_target_window;
|
||||
who_level = old_level;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
378
source/history.c
Normal file
378
source/history.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* history.c: stuff to handle command line history
|
||||
*
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
*
|
||||
* Copyright(c) 1990
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: history.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(history_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "ircaux.h"
|
||||
#include "vars.h"
|
||||
#include "history.h"
|
||||
#include "output.h"
|
||||
#include "input.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
static char *history_match (char *);
|
||||
static void add_to_history_list (int, char *);
|
||||
static char *get_from_history_buffer (int);
|
||||
|
||||
typedef struct HistoryStru
|
||||
{
|
||||
int number;
|
||||
char *stuff;
|
||||
struct HistoryStru *next;
|
||||
struct HistoryStru *prev;
|
||||
} History;
|
||||
|
||||
/* command_history: pointer to head of command_history list */
|
||||
static History *command_history_head = NULL;
|
||||
static History *command_history_tail = NULL;
|
||||
static History *command_history_pos = NULL;
|
||||
|
||||
/* hist_size: the current size of the command_history array */
|
||||
static int hist_size = 0;
|
||||
|
||||
/* hist_count: the absolute counter for the history list */
|
||||
static int hist_count = 0;
|
||||
|
||||
/*
|
||||
* last_dir: the direction (next or previous) of the last get_from_history()
|
||||
* call.... reset by add to history
|
||||
*/
|
||||
static int last_dir = -1;
|
||||
|
||||
/*
|
||||
* history pointer
|
||||
*/
|
||||
static History *tmp = NULL;
|
||||
|
||||
/*
|
||||
* history_match: using wild_match(), this finds the latest match in the
|
||||
* history file and returns it as the function result. Returns null if there
|
||||
* is no match. Note that this sticks a '*' at the end if one is not already
|
||||
* there.
|
||||
*/
|
||||
static char *history_match (char *match)
|
||||
{
|
||||
char *ptr;
|
||||
char *match_str = NULL;
|
||||
|
||||
if (*(match + strlen(match) - 1) == '*')
|
||||
match_str = LOCAL_COPY(match);
|
||||
else
|
||||
{
|
||||
match_str = alloca(strlen(match) + 3);
|
||||
strcpy(match_str, match);
|
||||
strcat(match_str, "*");
|
||||
}
|
||||
if (get_int_var(HISTORY_VAR))
|
||||
{
|
||||
if ((last_dir == -1) || (tmp == NULL))
|
||||
tmp = command_history_head;
|
||||
else
|
||||
tmp = tmp->next;
|
||||
if (tmp)
|
||||
{
|
||||
for (; tmp; tmp = tmp->next)
|
||||
{
|
||||
ptr = tmp->stuff;
|
||||
while (ptr && strchr(get_string_var(CMDCHARS_VAR), *ptr))
|
||||
ptr++;
|
||||
|
||||
if (wild_match(match_str, ptr))
|
||||
{
|
||||
last_dir = PREV;
|
||||
return (tmp->stuff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
last_dir = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* shove_to_history: a key binding that saves the current line into
|
||||
* the history and then deletes the whole line. Useful for when you
|
||||
* are in the middle of a big line and need to "get out" to do something
|
||||
* else quick for just a second, and you dont want to have to retype
|
||||
* everything all over again
|
||||
*/
|
||||
extern void shove_to_history (char unused, char *not_used)
|
||||
{
|
||||
add_to_history(get_input());
|
||||
input_clear_line(unused, not_used);
|
||||
}
|
||||
|
||||
static void add_to_history_list(int cnt, char *stuff)
|
||||
{
|
||||
History *new;
|
||||
|
||||
if (get_int_var(HISTORY_VAR) == 0)
|
||||
return;
|
||||
if ((hist_size == get_int_var(HISTORY_VAR)) && command_history_tail)
|
||||
{
|
||||
if (hist_size == 1)
|
||||
{
|
||||
malloc_strcpy(&command_history_tail->stuff, stuff);
|
||||
return;
|
||||
}
|
||||
new = command_history_tail;
|
||||
command_history_tail = command_history_tail->prev;
|
||||
command_history_tail->next = NULL;
|
||||
new_free(&new->stuff);
|
||||
new_free((char **)&new);
|
||||
if (command_history_tail == NULL)
|
||||
command_history_head = NULL;
|
||||
}
|
||||
else
|
||||
hist_size++;
|
||||
new = (History *) new_malloc(sizeof(History));
|
||||
new->stuff = NULL;
|
||||
new->number = cnt;
|
||||
new->next = command_history_head;
|
||||
new->prev = NULL;
|
||||
malloc_strcpy(&(new->stuff), stuff);
|
||||
if (command_history_head)
|
||||
command_history_head->prev = new;
|
||||
command_history_head = new;
|
||||
if (command_history_tail == NULL)
|
||||
command_history_tail = new;
|
||||
command_history_pos = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_history_size: adjusts the size of the command_history to be size. If
|
||||
* the array is not yet allocated, it is set to size and all the entries
|
||||
* nulled. If it exists, it is resized to the new size with a realloc. Any
|
||||
* new entries are nulled.
|
||||
*/
|
||||
void set_history_size(Window *win, char *unused, int size)
|
||||
{
|
||||
int i,
|
||||
cnt;
|
||||
History *ptr;
|
||||
|
||||
if (size < hist_size)
|
||||
{
|
||||
cnt = hist_size - size;
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
ptr = command_history_tail;
|
||||
command_history_tail = ptr->prev;
|
||||
new_free(&(ptr->stuff));
|
||||
new_free((char **)&ptr);
|
||||
}
|
||||
if (command_history_tail == NULL)
|
||||
command_history_head = NULL;
|
||||
else
|
||||
command_history_tail->next = NULL;
|
||||
hist_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* add_to_history: adds the given line to the history array. The history
|
||||
* array is a circular buffer, and add_to_history handles all that stuff. It
|
||||
* automagically allocted and deallocated memory as needed
|
||||
*/
|
||||
void add_to_history(char *line)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
if (line && *line)
|
||||
{
|
||||
while (line && *line)
|
||||
{
|
||||
if ((ptr = sindex(line, "\n\r")) != NULL)
|
||||
*(ptr++) = '\0';
|
||||
add_to_history_list(hist_count, line);
|
||||
last_dir = PREV;
|
||||
hist_count++;
|
||||
line = ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *get_from_history_buffer(int which)
|
||||
{
|
||||
if ((get_int_var(HISTORY_VAR) == 0) || (hist_size == 0))
|
||||
return NULL;
|
||||
/*
|
||||
* if (last_dir != which) { last_dir = which; get_from_history(which); }
|
||||
*/
|
||||
if (which == NEXT)
|
||||
{
|
||||
if (command_history_pos)
|
||||
{
|
||||
if (command_history_pos->prev)
|
||||
command_history_pos = command_history_pos->prev;
|
||||
else
|
||||
command_history_pos = command_history_tail;
|
||||
}
|
||||
else
|
||||
{
|
||||
add_to_history(get_input());
|
||||
command_history_pos = command_history_tail;
|
||||
}
|
||||
return (command_history_pos->stuff);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (command_history_pos)
|
||||
{
|
||||
if (command_history_pos->next)
|
||||
command_history_pos = command_history_pos->next;
|
||||
else
|
||||
command_history_pos = command_history_head;
|
||||
}
|
||||
else
|
||||
{
|
||||
add_to_history(get_input());
|
||||
command_history_pos = command_history_head;
|
||||
}
|
||||
return (command_history_pos->stuff);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_history: gets the next history entry, either the PREV entry or the
|
||||
* NEXT entry, and sets it to the current input string
|
||||
*/
|
||||
extern void get_history (int which)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
if ((ptr = get_from_history(which)) != NULL)
|
||||
{
|
||||
set_input(ptr);
|
||||
update_input(UPDATE_ALL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
char *get_from_history(int which)
|
||||
{
|
||||
return(get_from_history_buffer(which));
|
||||
}
|
||||
|
||||
/* history: the /HISTORY command, shows the command history buffer. */
|
||||
BUILT_IN_COMMAND(history)
|
||||
{
|
||||
int cnt,
|
||||
max = 0;
|
||||
char *value;
|
||||
char *match = NULL;
|
||||
|
||||
if (get_int_var(HISTORY_VAR))
|
||||
{
|
||||
say("Command History:");
|
||||
if ((value = next_arg(args, &args)) != NULL)
|
||||
{
|
||||
if (my_strnicmp(value, "-CLEAR", 3))
|
||||
{
|
||||
for (tmp = command_history_head; command_history_head; tmp = command_history_head)
|
||||
{
|
||||
new_free(&tmp->stuff);
|
||||
command_history_head = tmp->next;
|
||||
new_free(&tmp);
|
||||
}
|
||||
hist_size = hist_count = 0;
|
||||
command_history_pos = NULL;
|
||||
command_history_tail = NULL;
|
||||
command_history_head = NULL;
|
||||
return;
|
||||
}
|
||||
if (isdigit((unsigned char)*value))
|
||||
{
|
||||
max = my_atol(value);
|
||||
if (max > get_int_var(HISTORY_VAR))
|
||||
max = get_int_var(HISTORY_VAR);
|
||||
}
|
||||
else
|
||||
match = value;
|
||||
}
|
||||
else
|
||||
max = get_int_var(HISTORY_VAR);
|
||||
for (tmp = command_history_tail, cnt = 0; tmp && (match || (cnt < max));
|
||||
tmp = tmp->prev, cnt++)
|
||||
{
|
||||
if (!match || (match && wild_match(match, tmp->stuff)))
|
||||
put_it("%d: %s", tmp->number, tmp->stuff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_history: This finds the given history entry in either the history file,
|
||||
* or the in memory history buffer (if no history file is given). It then
|
||||
* returns the found entry as its function value, or null if the entry is not
|
||||
* found for some reason. Note that this routine mallocs the string returned
|
||||
*/
|
||||
char *do_history (char *com, char *rest)
|
||||
{
|
||||
int hist_num;
|
||||
char *ptr, *ret = NULL;
|
||||
static char *last_com = NULL;
|
||||
|
||||
if (!com || !*com)
|
||||
{
|
||||
if (last_com)
|
||||
com = last_com;
|
||||
else
|
||||
com = empty_string;
|
||||
}
|
||||
else
|
||||
malloc_strcpy(&last_com, com);
|
||||
|
||||
if (!is_number(com))
|
||||
{
|
||||
if ((ptr = history_match(com)))
|
||||
{
|
||||
ret = m_strdup(ptr);
|
||||
m_s3cat_s(&ret, space, rest);
|
||||
return ret;
|
||||
}
|
||||
say("No Match");
|
||||
}
|
||||
else
|
||||
{
|
||||
hist_num = my_atol(com);
|
||||
if (hist_num > 0)
|
||||
{
|
||||
for (tmp = command_history_head; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (tmp->number == hist_num)
|
||||
{
|
||||
ret = m_strdup(tmp->stuff);
|
||||
m_s3cat_s(&ret, space, rest);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hist_num++;
|
||||
for (tmp = command_history_head; tmp && hist_num < 0; )
|
||||
tmp = tmp->next, hist_num++;
|
||||
if (tmp)
|
||||
{
|
||||
ret = m_strdup(tmp->stuff);
|
||||
m_s3cat_s(&ret, space, rest);
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
say("No such history entry: %d", hist_num);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
1858
source/hook.c
Normal file
1858
source/hook.c
Normal file
File diff suppressed because it is too large
Load Diff
744
source/if.c
Normal file
744
source/if.c
Normal file
@@ -0,0 +1,744 @@
|
||||
/*
|
||||
* if.c: handles the IF command for IRCII
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
*
|
||||
* Copyright(c) 1990, 1991
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: if.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(if_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "alias.h"
|
||||
#include "ircaux.h"
|
||||
#include "window.h"
|
||||
#include "vars.h"
|
||||
#include "output.h"
|
||||
#include "if.h"
|
||||
#include "commands.h"
|
||||
#include "misc.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
/*
|
||||
* next_expr finds the next expression delimited by brackets. The type
|
||||
* of bracket expected is passed as a parameter. Returns NULL on error.
|
||||
*/
|
||||
char *my_next_expr(char **args, char type, int whine)
|
||||
{
|
||||
char *ptr,
|
||||
*ptr2,
|
||||
*ptr3;
|
||||
|
||||
if (!*args)
|
||||
return NULL;
|
||||
ptr2 = *args;
|
||||
if (!*ptr2)
|
||||
return 0;
|
||||
if (*ptr2 != type)
|
||||
{
|
||||
if (whine)
|
||||
say("Expression syntax");
|
||||
return 0;
|
||||
} /* { */
|
||||
ptr = MatchingBracket(ptr2 + 1, type, (type == '(') ? ')' : '}');
|
||||
if (!ptr)
|
||||
{
|
||||
say("Unmatched '%c'", type);
|
||||
return 0;
|
||||
}
|
||||
*ptr = '\0';
|
||||
|
||||
do
|
||||
ptr2++;
|
||||
while (my_isspace(*ptr2));
|
||||
|
||||
ptr3 = ptr+1;
|
||||
while (my_isspace(*ptr3))
|
||||
ptr3++;
|
||||
*args = ptr3;
|
||||
if (*ptr2)
|
||||
{
|
||||
ptr--;
|
||||
while (my_isspace(*ptr))
|
||||
*ptr-- = '\0';
|
||||
}
|
||||
return ptr2;
|
||||
}
|
||||
|
||||
extern char *next_expr_failok (char **args, char type)
|
||||
{
|
||||
return my_next_expr (args, type, 0);
|
||||
}
|
||||
|
||||
extern char *next_expr (char **args, char type)
|
||||
{
|
||||
return my_next_expr (args, type, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* All new /if command -- (jfn, 1997)
|
||||
*
|
||||
* Here's the plan:
|
||||
*
|
||||
* if (expr) ......
|
||||
* if (expr) {......}
|
||||
* if (expr) {......} {......}
|
||||
* if (expr) {......} else {......}
|
||||
* if (expr) {......} elsif (expr2) {......}
|
||||
* etc.
|
||||
*/
|
||||
|
||||
BUILT_IN_COMMAND(ifcmd)
|
||||
{
|
||||
int unless_cmd;
|
||||
char *current_expr;
|
||||
char *current_expr_val;
|
||||
int result;
|
||||
char *current_line = NULL;
|
||||
int flag = 0;
|
||||
|
||||
unless_cmd = (*command == 'U');
|
||||
if (!subargs)
|
||||
subargs = empty_string;
|
||||
|
||||
while (args && *args)
|
||||
{
|
||||
while (my_isspace(*args))
|
||||
args++;
|
||||
|
||||
current_expr = next_expr(&args, '(');
|
||||
if (!current_expr)
|
||||
{
|
||||
error("IF: Missing expression");
|
||||
return;
|
||||
}
|
||||
current_expr_val = parse_inline(current_expr, subargs, &flag);
|
||||
if (internal_debug & DEBUG_EXPANSIONS && !in_debug_yell)
|
||||
debugyell("%s expression expands to: (%s)", command, current_expr_val);
|
||||
result = check_val(current_expr_val);
|
||||
new_free(¤t_expr_val);
|
||||
|
||||
if (*args == '{')
|
||||
{
|
||||
current_line = next_expr(&args, '{');
|
||||
}
|
||||
else
|
||||
current_line = args, args = NULL;
|
||||
|
||||
/* If the expression was FALSE for IF, and TRUE for UNLESS */
|
||||
if (unless_cmd == result)
|
||||
{
|
||||
if (args)
|
||||
{
|
||||
if (!my_strnicmp(args, "elsif ", 6))
|
||||
{
|
||||
args += 6;
|
||||
continue;
|
||||
}
|
||||
else if (!my_strnicmp(args, "else ", 5))
|
||||
args += 5;
|
||||
|
||||
while (my_isspace(*args))
|
||||
args++;
|
||||
|
||||
if (*args == '{')
|
||||
current_line = next_expr(&args, '{');
|
||||
else
|
||||
current_line = args, args = NULL;
|
||||
|
||||
}
|
||||
else
|
||||
current_line = NULL;
|
||||
}
|
||||
|
||||
if (current_line)
|
||||
parse_line(NULL, current_line, subargs, 0, 0, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(docmd)
|
||||
{
|
||||
char *body, *expr, *cmd, *ptr;
|
||||
char *newexp = NULL;
|
||||
int args_used = 0;
|
||||
int result;
|
||||
|
||||
if (*args == '{')
|
||||
{
|
||||
if (!(body = next_expr(&args, '{')))
|
||||
{
|
||||
error("DO: unbalanced {");
|
||||
return;
|
||||
}
|
||||
if (args && *args && (cmd = next_arg(args, &args)) &&
|
||||
!my_stricmp (cmd, "while"))
|
||||
{
|
||||
if (!(expr = next_expr(&args, '(')))
|
||||
{
|
||||
error("DO: unbalanced (");
|
||||
return;
|
||||
}
|
||||
will_catch_break_exceptions++;
|
||||
will_catch_return_exceptions++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
parse_line (NULL, body, subargs ? subargs : empty_string, 0, 0, 1);
|
||||
if (break_exception)
|
||||
{
|
||||
break_exception = 0;
|
||||
break;
|
||||
}
|
||||
if (continue_exception)
|
||||
{
|
||||
continue_exception = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (return_exception)
|
||||
break;
|
||||
malloc_strcpy(&newexp, expr);
|
||||
ptr = parse_inline(newexp, subargs ? subargs : empty_string,
|
||||
&args_used);
|
||||
result = check_val(ptr);
|
||||
new_free(&ptr);
|
||||
if (!result)
|
||||
break;
|
||||
}
|
||||
new_free(&newexp);
|
||||
will_catch_break_exceptions--;
|
||||
will_catch_continue_exceptions--;
|
||||
return;
|
||||
}
|
||||
/* falls through to here if its /do {...} */
|
||||
parse_line (NULL, body, subargs ? subargs : empty_string, 0, 0, 1);
|
||||
}
|
||||
/* falls through to here if it its /do ... */
|
||||
parse_line (NULL, args, subargs ? subargs : empty_string, 0, 0, 1);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
BUILT_IN_COMMAND(whilecmd)
|
||||
{
|
||||
char *exp = NULL,
|
||||
*ptr = NULL,
|
||||
*body = NULL,
|
||||
*newexp = NULL;
|
||||
int args_used; /* this isn't used here, but is passed
|
||||
* to expand_alias() */
|
||||
int whileval = !strcmp(command, "WHILE");
|
||||
|
||||
if (!(ptr = next_expr(&args, '(')))
|
||||
{
|
||||
error("WHILE: missing boolean expression");
|
||||
return;
|
||||
}
|
||||
exp = LOCAL_COPY(ptr);
|
||||
if ((ptr = next_expr_failok(&args, '{')) == (char *) 0)
|
||||
ptr = args;
|
||||
|
||||
body = LOCAL_COPY(ptr);
|
||||
|
||||
will_catch_break_exceptions++;
|
||||
will_catch_continue_exceptions++;
|
||||
make_local_stack(NULL);
|
||||
while (1)
|
||||
{
|
||||
newexp = LOCAL_COPY(exp);
|
||||
ptr = parse_inline(newexp, subargs ? subargs : empty_string, &args_used);
|
||||
if (check_val(ptr) != whileval)
|
||||
break;
|
||||
new_free(&ptr);
|
||||
parse_line(NULL, body, subargs ? subargs : empty_string, 0, 0, 0);
|
||||
if (continue_exception)
|
||||
{
|
||||
continue_exception = 0;
|
||||
continue;
|
||||
}
|
||||
if (break_exception)
|
||||
{
|
||||
break_exception = 0;
|
||||
break;
|
||||
}
|
||||
if (return_exception)
|
||||
break;
|
||||
}
|
||||
will_catch_break_exceptions--;
|
||||
will_catch_continue_exceptions--;
|
||||
destroy_local_stack();
|
||||
new_free(&ptr);
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(foreach)
|
||||
{
|
||||
char *struc = NULL,
|
||||
*ptr,
|
||||
*body = NULL,
|
||||
*var = NULL;
|
||||
char **sublist;
|
||||
int total;
|
||||
int i;
|
||||
int slen;
|
||||
int old_display;
|
||||
int list = VAR_ALIAS;
|
||||
int af;
|
||||
|
||||
while (args && my_isspace(*args))
|
||||
args++;
|
||||
|
||||
if (*args == '-')
|
||||
args++, list = COMMAND_ALIAS;
|
||||
|
||||
if ((ptr = new_next_arg(args, &args)) == NULL)
|
||||
{
|
||||
error("FOREACH: missing structure expression");
|
||||
return;
|
||||
}
|
||||
struc = upper(remove_brackets(ptr, subargs, &af));
|
||||
|
||||
if ((var = next_arg(args, &args)) == NULL)
|
||||
{
|
||||
new_free(&struc);
|
||||
error("FOREACH: missing variable");
|
||||
return;
|
||||
}
|
||||
while (my_isspace(*args))
|
||||
args++;
|
||||
|
||||
if ((body = next_expr(&args, '{')) == NULL) /* } */
|
||||
{
|
||||
new_free(&struc);
|
||||
error("FOREACH: missing statement");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sublist = get_subarray_elements(struc, &total, list)) == NULL)
|
||||
{
|
||||
new_free(&struc);
|
||||
return; /* Nothing there. */
|
||||
}
|
||||
|
||||
slen=strlen(struc);
|
||||
old_display=window_display;
|
||||
make_local_stack(NULL);
|
||||
for (i=0;i<total;i++)
|
||||
{
|
||||
window_display=0;
|
||||
add_local_alias(var, sublist[i]+slen+1);
|
||||
window_display=old_display;
|
||||
parse_line(NULL, body, subargs ? subargs:empty_string, 0, 0, 0);
|
||||
new_free(&sublist[i]);
|
||||
}
|
||||
destroy_local_stack();
|
||||
new_free((char **)&sublist);
|
||||
new_free(&struc);
|
||||
}
|
||||
|
||||
/*
|
||||
* FE: Written by Jeremy Nelson (jnelson@iastate.edu)
|
||||
*
|
||||
* FE: replaces recursion
|
||||
*
|
||||
* The thing about it is that you can nest variables, as this command calls
|
||||
* expand_alias until the list doesnt change. So you can nest lists in
|
||||
* lists, and hopefully that will work. However, it also makes it
|
||||
* impossible to have $s anywhere in the list. Maybe ill change that
|
||||
* some day.
|
||||
*/
|
||||
|
||||
BUILT_IN_COMMAND(fe)
|
||||
{
|
||||
char *list = NULL,
|
||||
*templist = NULL,
|
||||
*placeholder,
|
||||
*sa,
|
||||
*vars,
|
||||
*var[255],
|
||||
*word = NULL,
|
||||
*todo = NULL,
|
||||
fec_buffer[2];
|
||||
int ind, x, y, blah = 0, args_flag;
|
||||
int old_display;
|
||||
int doing_fe = !my_stricmp(command, "FE");
|
||||
|
||||
for (x = 0; x <= 254; var[x++] = NULL)
|
||||
;
|
||||
|
||||
list = next_expr(&args, '(');
|
||||
|
||||
if (!list)
|
||||
{
|
||||
error("%s: Missing List for /%s", command, command);
|
||||
return;
|
||||
}
|
||||
|
||||
sa = subargs ? subargs : space;
|
||||
|
||||
templist = expand_alias(list, sa, &args_flag, NULL);
|
||||
if (!templist || !*templist)
|
||||
{
|
||||
new_free(&templist);
|
||||
return;
|
||||
}
|
||||
|
||||
vars = args;
|
||||
if (!(args = strchr(args, '{'))) /* } */
|
||||
{
|
||||
error("%s: Missing commands", command);
|
||||
new_free(&templist);
|
||||
return;
|
||||
}
|
||||
if ((char *)var == (char *)args)
|
||||
{
|
||||
error("%s: You did not specify any variables", command);
|
||||
new_free(&templist);
|
||||
return;
|
||||
}
|
||||
args[-1] = '\0';
|
||||
ind = 0;
|
||||
|
||||
while ((var[ind++] = next_arg(vars, &vars)))
|
||||
{
|
||||
if (ind == 255)
|
||||
{
|
||||
error("%s: Too many variables", command);
|
||||
new_free(&templist);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ind = ind ? ind - 1: 0;
|
||||
|
||||
if (!(todo = next_expr(&args, '{'))) /* } { */
|
||||
{
|
||||
error("%s: Missing }", command);
|
||||
new_free(&templist);
|
||||
return;
|
||||
}
|
||||
|
||||
old_display = window_display;
|
||||
|
||||
if (!doing_fe)
|
||||
{ word = fec_buffer; word[1] = 0; }
|
||||
|
||||
blah = ((doing_fe) ? (word_count(templist)) : (strlen(templist)));
|
||||
placeholder = templist;
|
||||
|
||||
will_catch_break_exceptions++;
|
||||
will_catch_continue_exceptions++;
|
||||
|
||||
make_local_stack(NULL);
|
||||
for ( x = 0 ; x < blah ; )
|
||||
{
|
||||
window_display = 0;
|
||||
for ( y = 0 ; y < ind ; y++ )
|
||||
{
|
||||
if (doing_fe)
|
||||
word = ((x+y) < blah)
|
||||
? new_next_arg(templist, &templist)
|
||||
: empty_string;
|
||||
else
|
||||
word[0] = ((x+y) < blah)
|
||||
? templist[x+y] : 0;
|
||||
|
||||
add_local_alias(var[y], word);
|
||||
}
|
||||
window_display = old_display;
|
||||
x += ind;
|
||||
parse_line(NULL, todo, subargs?subargs:empty_string, 0, 0, 0);
|
||||
if (continue_exception)
|
||||
{
|
||||
continue_exception = 0;
|
||||
continue;
|
||||
}
|
||||
if (break_exception)
|
||||
{
|
||||
break_exception = 0;
|
||||
break;
|
||||
}
|
||||
if (return_exception)
|
||||
break;
|
||||
}
|
||||
|
||||
destroy_local_stack();
|
||||
will_catch_break_exceptions--;
|
||||
will_catch_continue_exceptions--;
|
||||
|
||||
window_display = old_display;
|
||||
new_free(&placeholder);
|
||||
}
|
||||
|
||||
/* FOR command..... prototype:
|
||||
* for (commence,evaluation,iteration)
|
||||
* in the same style of C's for, the for loop is just a specific
|
||||
* type of WHILE loop.
|
||||
*
|
||||
* IMPORTANT: Since ircII uses ; as a delimeter between commands,
|
||||
* commas were chosen to be the delimiter between expressions,
|
||||
* so that semicolons may be used in the expressions (think of this
|
||||
* as the reverse as C, where commas seperate commands in expressions,
|
||||
* and semicolons end expressions.
|
||||
*/
|
||||
/* I suppose someone could make a case that since the
|
||||
* foreach_handler() routine weeds out any for command that doesnt have
|
||||
* two commans, that checking for those 2 commas is a waste. I suppose.
|
||||
*/
|
||||
BUILT_IN_COMMAND(forcmd)
|
||||
{
|
||||
char *working = NULL;
|
||||
char *commence = NULL;
|
||||
char *evaluation = NULL;
|
||||
char *lameeval = NULL;
|
||||
char *iteration = NULL;
|
||||
char *sa = NULL;
|
||||
int argsused = 0;
|
||||
char *blah = NULL;
|
||||
char *commands = NULL;
|
||||
|
||||
/* Get the whole () thing */
|
||||
if ((working = next_expr(&args, '(')) == NULL) /* ) */
|
||||
{
|
||||
error("FOR: missing closing parenthesis");
|
||||
return;
|
||||
}
|
||||
commence = LOCAL_COPY(working);
|
||||
|
||||
/* Find the beginning of the second expression */
|
||||
|
||||
evaluation = strchr(commence, ',');
|
||||
if (!evaluation)
|
||||
{
|
||||
error("FOR: no components!");
|
||||
return;
|
||||
}
|
||||
do
|
||||
*evaluation++ = '\0';
|
||||
while (my_isspace(*evaluation));
|
||||
|
||||
/* Find the beginning of the third expression */
|
||||
iteration = strchr(evaluation, ',');
|
||||
if (!iteration)
|
||||
{
|
||||
error("FOR: Only two components!");
|
||||
return;
|
||||
}
|
||||
do
|
||||
{
|
||||
*iteration++ = '\0';
|
||||
}
|
||||
while (my_isspace(*iteration));
|
||||
|
||||
working = args;
|
||||
while (my_isspace(*working))
|
||||
*working++ = '\0';
|
||||
|
||||
if ((working = next_expr(&working, '{')) == NULL) /* } */
|
||||
{
|
||||
error("FOR: badly formed commands");
|
||||
return;
|
||||
}
|
||||
|
||||
make_local_stack(NULL);
|
||||
|
||||
commands = LOCAL_COPY(working);
|
||||
|
||||
sa = subargs?subargs:empty_string;
|
||||
parse_line(NULL, commence, sa, 0, 0, 0);
|
||||
|
||||
will_catch_break_exceptions++;
|
||||
will_catch_continue_exceptions++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
lameeval = LOCAL_COPY(evaluation);
|
||||
|
||||
blah = parse_inline(lameeval,sa,&argsused);
|
||||
if (!check_val(blah))
|
||||
{
|
||||
new_free(&blah);
|
||||
break;
|
||||
}
|
||||
|
||||
new_free(&blah);
|
||||
parse_line(NULL, commands, sa, 0, 0, 0);
|
||||
if (break_exception)
|
||||
{
|
||||
break_exception = 0;
|
||||
break;
|
||||
}
|
||||
if (continue_exception)
|
||||
continue_exception = 0; /* Dont continue here! */
|
||||
if (return_exception)
|
||||
break;
|
||||
parse_line(NULL, iteration, sa, 0, 0, 0);
|
||||
}
|
||||
|
||||
destroy_local_stack();
|
||||
will_catch_break_exceptions--;
|
||||
will_catch_continue_exceptions--;
|
||||
|
||||
new_free(&blah);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Need to support something like this:
|
||||
|
||||
switch (text to be matched)
|
||||
{
|
||||
(sample text)
|
||||
{
|
||||
...
|
||||
}
|
||||
(sample text2)
|
||||
(sample text3)
|
||||
{
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
How it works:
|
||||
|
||||
The command is technically made up a single (...) expression and
|
||||
a single {...} expression. The (...) expression is taken to be
|
||||
regular expando-text (much like the (...) body of /fe.
|
||||
|
||||
The {...} body is taken to be a series of [(...)] {...} pairs.
|
||||
The [(...)] expression is taken to be one or more consecutive
|
||||
(...) structures, which are taken to be text expressions to match
|
||||
against the header text. If any of the (...) expressions are found
|
||||
to match, then the commands in the {...} body are executed.
|
||||
|
||||
There may be as many such [(...)] {...} pairs as you need. However,
|
||||
only the *first* pair found to be matching is actually executed,
|
||||
and the others are ignored, so placement of your switches are
|
||||
rather important: Put your most general ones last.
|
||||
|
||||
*/
|
||||
BUILT_IN_COMMAND(switchcmd)
|
||||
{
|
||||
char *control, *body, *header, *commands;
|
||||
int af;
|
||||
int found_def = 0;
|
||||
char *def = NULL;
|
||||
|
||||
if (!(control = next_expr(&args, '(')))
|
||||
{
|
||||
error("SWITCH: String to be matched not found where expected");
|
||||
return;
|
||||
}
|
||||
|
||||
control = expand_alias(control, subargs, &af, NULL);
|
||||
if (internal_debug & DEBUG_EXPANSIONS && !in_debug_yell)
|
||||
debugyell("%s expression expands to: (%s)", command, control);
|
||||
|
||||
if (!(body = next_expr(&args, '{')))
|
||||
error("SWITCH: Execution body not found where expected");
|
||||
|
||||
make_local_stack(NULL);
|
||||
while (body && *body)
|
||||
{
|
||||
int hooked = 0;
|
||||
|
||||
while (*body == '(')
|
||||
{
|
||||
if (!(header = next_expr(&body, '(')))
|
||||
{
|
||||
error("SWITCH: Case label not found where expected");
|
||||
new_free(&control);
|
||||
return;
|
||||
}
|
||||
if (!strcmp(header, "default"))
|
||||
{
|
||||
if (def)
|
||||
{
|
||||
error("SWITCH: No more than one \"default\" case");
|
||||
new_free(&control);
|
||||
return;
|
||||
}
|
||||
found_def = 1;
|
||||
}
|
||||
header = expand_alias(header, subargs, &af, NULL);
|
||||
if (internal_debug & DEBUG_EXPANSIONS && !in_debug_yell)
|
||||
debugyell("%s expression expands to: (%s)", command, header);
|
||||
if (wild_match(header, control))
|
||||
hooked = 1;
|
||||
new_free(&header);
|
||||
if (*body == ';')
|
||||
body++; /* ugh. */
|
||||
}
|
||||
|
||||
if (!(commands = next_expr(&body, '{')))
|
||||
{
|
||||
error("SWITCH: case body not found where expected");
|
||||
break;
|
||||
}
|
||||
|
||||
if (hooked)
|
||||
{
|
||||
parse_line(NULL, commands, subargs, 0, 0, 0);
|
||||
def = NULL;
|
||||
break;
|
||||
}
|
||||
else if (!def && found_def)
|
||||
{
|
||||
def = LOCAL_COPY(commands);
|
||||
found_def = 0;
|
||||
}
|
||||
|
||||
if (*body == ';')
|
||||
body++; /* grumble */
|
||||
}
|
||||
if (def && *def)
|
||||
parse_line(NULL, def, subargs, 0, 0, 0);
|
||||
destroy_local_stack();
|
||||
new_free(&control);
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(repeatcmd)
|
||||
{
|
||||
char *num_expr = NULL;
|
||||
int value;
|
||||
|
||||
while (isspace((unsigned char)*args))
|
||||
args++;
|
||||
|
||||
if (*args == '(')
|
||||
{
|
||||
char *tmp_val;
|
||||
char *dumb_copy;
|
||||
int argsused;
|
||||
char *sa = subargs ? subargs : empty_string;
|
||||
|
||||
num_expr = next_expr(&args, '(');
|
||||
dumb_copy = LOCAL_COPY(num_expr);
|
||||
tmp_val = parse_inline(dumb_copy,sa,&argsused);
|
||||
value = my_atol(tmp_val);
|
||||
new_free(&tmp_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *tmp_val;
|
||||
int af;
|
||||
|
||||
num_expr = new_next_arg(args, &args);
|
||||
tmp_val = expand_alias(num_expr, subargs, &af, NULL);
|
||||
value = my_atol(tmp_val);
|
||||
new_free(&tmp_val);
|
||||
}
|
||||
|
||||
if (value <= 0)
|
||||
return;
|
||||
while (value--)
|
||||
parse_line(NULL, args, subargs ? subargs : empty_string, 0, 0, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
1088
source/ignore.c
Normal file
1088
source/ignore.c
Normal file
File diff suppressed because it is too large
Load Diff
2891
source/input.c
Normal file
2891
source/input.c
Normal file
File diff suppressed because it is too large
Load Diff
1694
source/irc.c
Normal file
1694
source/irc.c
Normal file
File diff suppressed because it is too large
Load Diff
3226
source/ircaux.c
Normal file
3226
source/ircaux.c
Normal file
File diff suppressed because it is too large
Load Diff
53
source/ircsig.c
Normal file
53
source/ircsig.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* ircsig.c: has a `my_signal()' that uses sigaction().
|
||||
*
|
||||
* written by matthew green, 1993.
|
||||
*
|
||||
* i stole bits of this from w. richard stevens' `advanced programming
|
||||
* in the unix environment' -mrg
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
#include "irc_std.h"
|
||||
|
||||
sigfunc * my_signal(int sig_no, sigfunc *sig_handler, int misc_flags)
|
||||
{
|
||||
/*
|
||||
* misc_flags is unused currently. it's planned to be used
|
||||
* to use some of the doovier bits of sigaction(), if at
|
||||
* some point we need them, -mrg
|
||||
*/
|
||||
|
||||
struct sigaction sa = {{ 0 }}, osa = {{ 0 }};
|
||||
|
||||
if (sig_no < 0)
|
||||
return NULL;
|
||||
|
||||
sa.sa_handler = sig_handler;
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaddset(&sa.sa_mask, sig_no);
|
||||
|
||||
/* this is ugly, but the `correct' way. i hate c. -mrg */
|
||||
sa.sa_flags = 0;
|
||||
#if defined(SA_RESTART) || defined(SA_INTERRUPT)
|
||||
if (SIGALRM == sig_no || SIGINT == sig_no)
|
||||
{
|
||||
# if defined(SA_INTERRUPT)
|
||||
sa.sa_flags |= SA_INTERRUPT;
|
||||
# endif /* SA_INTERRUPT */
|
||||
}
|
||||
else
|
||||
{
|
||||
# if defined(SA_RESTART)
|
||||
sa.sa_flags |= SA_RESTART;
|
||||
# endif /* SA_RESTART */
|
||||
}
|
||||
#endif /* SA_RESTART || SA_INTERRUPT */
|
||||
|
||||
if (0 > sigaction(sig_no, &sa, &osa))
|
||||
return ((sigfunc *)SIG_ERR);
|
||||
|
||||
return ((sigfunc *)osa.sa_handler);
|
||||
}
|
||||
1513
source/keys.c
Normal file
1513
source/keys.c
Normal file
File diff suppressed because it is too large
Load Diff
812
source/lastlog.c
Normal file
812
source/lastlog.c
Normal file
@@ -0,0 +1,812 @@
|
||||
/*
|
||||
* lastlog.c: handles the lastlog features of irc.
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
*
|
||||
* Copyright(c) 1990
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: lastlog.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(lastlog_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "lastlog.h"
|
||||
#include "window.h"
|
||||
#include "screen.h"
|
||||
#include "vars.h"
|
||||
#include "ircaux.h"
|
||||
#include "output.h"
|
||||
#include "misc.h"
|
||||
#include "hook.h"
|
||||
#include "status.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
extern int grab_http (char *, char *, char *);
|
||||
/*
|
||||
* lastlog_level: current bitmap setting of which things should be stored in
|
||||
* the lastlog. The LOG_MSG, LOG_NOTICE, etc., defines tell more about this
|
||||
*/
|
||||
static unsigned long lastlog_level;
|
||||
static unsigned long notify_level;
|
||||
|
||||
static unsigned long msglog_level = 0;
|
||||
unsigned long beep_on_level = 0;
|
||||
unsigned long new_server_lastlog_level = 0;
|
||||
unsigned long current_window_level = 0;
|
||||
|
||||
|
||||
FILE *logptr = NULL;
|
||||
|
||||
/*
|
||||
* msg_level: the mask for the current message level. What? Did he really
|
||||
* say that? This is set in the set_lastlog_msg_level() routine as it
|
||||
* compared to the lastlog_level variable to see if what ever is being added
|
||||
* should actually be added
|
||||
*/
|
||||
static unsigned long msg_level = LOG_CRAP;
|
||||
|
||||
static char *levels[] =
|
||||
{
|
||||
"CRAP", "PUBLIC", "MSGS", "NOTICES",
|
||||
"WALLS", "WALLOPS", "NOTES", "OPNOTES",
|
||||
"SNOTES", "ACTIONS", "DCC", "CTCP",
|
||||
"USERLOG1", "USERLOG2", "USERLOG3", "USERLOG4",
|
||||
"USERLOG5", "BEEP", "TCL", "SEND_MSG",
|
||||
"KILL", "MODEUSER", "MODECHAN", "KICK",
|
||||
"KICKUSER", "PARTS", "INVITES", "JOIN",
|
||||
"TOPIC", "HELP", "NOTIFY", "DEBUG"
|
||||
};
|
||||
|
||||
#define NUMBER_OF_LEVELS (sizeof(levels) / sizeof(char *))
|
||||
|
||||
|
||||
void reset_hold_mode(Window *win)
|
||||
{
|
||||
win->hold_mode = win->save_hold_mode;
|
||||
win->save_hold_mode = win->in_more = 0;
|
||||
}
|
||||
|
||||
/* set_lastlog_msg_level: sets the message level for recording in the lastlog */
|
||||
unsigned long BX_set_lastlog_msg_level(unsigned long level)
|
||||
{
|
||||
unsigned long old;
|
||||
|
||||
old = msg_level;
|
||||
msg_level = level;
|
||||
return (old);
|
||||
}
|
||||
|
||||
/*
|
||||
* bits_to_lastlog_level: converts the bitmap of lastlog levels into a nice
|
||||
* string format. Note that this uses the global buffer, so watch out
|
||||
*/
|
||||
char * bits_to_lastlog_level(unsigned long level)
|
||||
{
|
||||
static char buffer[481]; /* this *should* be enough for this */
|
||||
int i;
|
||||
unsigned long p;
|
||||
|
||||
if (level == LOG_ALL)
|
||||
strcpy(buffer, "ALL");
|
||||
else if (level == 0)
|
||||
strcpy(buffer, "NONE");
|
||||
else
|
||||
{
|
||||
*buffer = '\0';
|
||||
for (i = 0, p = 1; i < NUMBER_OF_LEVELS; i++, p <<= 1)
|
||||
{
|
||||
if (level & p)
|
||||
{
|
||||
if (*buffer)
|
||||
strmcat(buffer, space, 480);
|
||||
strmcat(buffer, levels[i],480);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (buffer);
|
||||
}
|
||||
|
||||
unsigned long parse_lastlog_level(char *str, int display)
|
||||
{
|
||||
char *ptr,
|
||||
*rest;
|
||||
int len,
|
||||
i;
|
||||
unsigned long p,
|
||||
level;
|
||||
int neg;
|
||||
|
||||
level = 0;
|
||||
while ((str = next_arg(str, &rest)) != NULL)
|
||||
{
|
||||
while (str)
|
||||
{
|
||||
if ((ptr = strchr(str, ',')) != NULL)
|
||||
*ptr++ = '\0';
|
||||
if ((len = strlen(str)) != 0)
|
||||
{
|
||||
if (my_strnicmp(str, "ALL", len) == 0)
|
||||
level = LOG_ALL;
|
||||
else if (my_strnicmp(str, "NONE", len) == 0)
|
||||
level = 0;
|
||||
else
|
||||
{
|
||||
if (*str == '-')
|
||||
{
|
||||
str++; len--;
|
||||
neg = 1;
|
||||
}
|
||||
else
|
||||
neg = 0;
|
||||
for (i = 0, p = 1; i < NUMBER_OF_LEVELS; i++, p <<= 1)
|
||||
{
|
||||
if (!my_strnicmp(str, levels[i], len))
|
||||
{
|
||||
if (neg)
|
||||
level &= (LOG_ALL ^ p);
|
||||
else
|
||||
level |= p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == NUMBER_OF_LEVELS)
|
||||
{
|
||||
if (display)
|
||||
say("Unknown lastlog level: %s", str);
|
||||
return LOG_ALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
str = ptr;
|
||||
}
|
||||
str = rest;
|
||||
}
|
||||
return (level);
|
||||
}
|
||||
|
||||
/*
|
||||
* set_lastlog_level: called whenever a "SET LASTLOG_LEVEL" is done. It
|
||||
* parses the settings and sets the lastlog_level variable appropriately. It
|
||||
* also rewrites the LASTLOG_LEVEL variable to make it look nice
|
||||
*/
|
||||
void set_lastlog_level(Window *win, char *str, int unused)
|
||||
{
|
||||
lastlog_level = parse_lastlog_level(str, 1);
|
||||
set_string_var(LASTLOG_LEVEL_VAR, bits_to_lastlog_level(lastlog_level));
|
||||
current_window->lastlog_level = lastlog_level;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_msglog_level: called whenever a "SET MSGLOG_LEVEL" is done. It
|
||||
* parses the settings and sets the msglog_level variable appropriately. It
|
||||
* also rewrites the MSGLOG_LEVEL variable to make it look nice
|
||||
*/
|
||||
void set_msglog_level(Window *win, char *str, int unused)
|
||||
{
|
||||
msglog_level = parse_lastlog_level(str, 1);
|
||||
set_string_var(MSGLOG_LEVEL_VAR, bits_to_lastlog_level(msglog_level));
|
||||
}
|
||||
|
||||
void set_new_server_lastlog_level (Window *win, char *str, int unused)
|
||||
{
|
||||
new_server_lastlog_level = parse_lastlog_level(str, 1);
|
||||
set_string_var(NEW_SERVER_LASTLOG_LEVEL_VAR,
|
||||
bits_to_lastlog_level(new_server_lastlog_level));
|
||||
}
|
||||
|
||||
void remove_from_lastlog(Window *window)
|
||||
{
|
||||
Lastlog *tmp, *end_holder;
|
||||
|
||||
if (window->lastlog_tail)
|
||||
{
|
||||
end_holder = window->lastlog_tail;
|
||||
tmp = window->lastlog_tail->prev;
|
||||
window->lastlog_tail = tmp;
|
||||
if (tmp)
|
||||
tmp->next = NULL;
|
||||
else
|
||||
window->lastlog_head = window->lastlog_tail;
|
||||
window->lastlog_size--;
|
||||
new_free(&end_holder->msg);
|
||||
new_free((char **)&end_holder);
|
||||
}
|
||||
else
|
||||
window->lastlog_size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_lastlog_size: sets up a lastlog buffer of size given. If the lastlog
|
||||
* has gotten larger than it was before, all previous lastlog entry remain.
|
||||
* If it get smaller, some are deleted from the end.
|
||||
*/
|
||||
void set_lastlog_size(Window *win_unused, char *unused, int size)
|
||||
{
|
||||
int i,
|
||||
diff;
|
||||
Window *win = NULL;
|
||||
|
||||
while ((traverse_all_windows(&win)))
|
||||
{
|
||||
if (win->lastlog_size > size)
|
||||
{
|
||||
diff = win->lastlog_size - size;
|
||||
for (i = 0; i < diff; i++)
|
||||
remove_from_lastlog(win);
|
||||
}
|
||||
win->lastlog_max = size;
|
||||
}
|
||||
}
|
||||
|
||||
void free_lastlog(Window *win)
|
||||
{
|
||||
Lastlog *ptr;
|
||||
for (ptr = win->lastlog_head; ptr;)
|
||||
{
|
||||
Lastlog *next = ptr->next;
|
||||
new_free(&ptr->msg);
|
||||
new_free(&ptr);
|
||||
ptr = next;
|
||||
}
|
||||
win->lastlog_head = NULL;
|
||||
win->lastlog_tail = NULL;
|
||||
win->lastlog_size = 0;
|
||||
}
|
||||
/*
|
||||
* lastlog: the /LASTLOG command. Displays the lastlog to the screen. If
|
||||
* args contains a valid integer, only that many lastlog entries are shown
|
||||
* (if the value is less than lastlog_size), otherwise the entire lastlog is
|
||||
* displayed
|
||||
*/
|
||||
BUILT_IN_COMMAND(lastlog)
|
||||
{
|
||||
int cnt,
|
||||
from = 0,
|
||||
p,
|
||||
i,
|
||||
level = 0,
|
||||
msg_level,
|
||||
len,
|
||||
mask = 0,
|
||||
header = 1,
|
||||
lines = 0,
|
||||
reverse = 0,
|
||||
time_log = 1,
|
||||
remove = 0;
|
||||
|
||||
Lastlog *start_pos;
|
||||
char *match = NULL,
|
||||
*arg;
|
||||
char *file_open[] = { "wt", "at" };
|
||||
int file_open_type = 0;
|
||||
char *blah = NULL;
|
||||
FILE *fp = NULL;
|
||||
|
||||
reset_display_target();
|
||||
cnt = current_window->lastlog_size;
|
||||
|
||||
while ((arg = new_next_arg(args, &args)) != NULL)
|
||||
{
|
||||
if (*arg == '-')
|
||||
{
|
||||
arg++;
|
||||
if (!(len = strlen(arg)))
|
||||
{
|
||||
header = 0;
|
||||
continue;
|
||||
}
|
||||
else if (!my_strnicmp(arg, "MAX", len))
|
||||
{
|
||||
char *ptr = NULL;
|
||||
ptr = new_next_arg(args, &args);
|
||||
if (ptr)
|
||||
lines = atoi(ptr);
|
||||
if (lines < 0)
|
||||
lines = 0;
|
||||
}
|
||||
else if (!my_strnicmp(arg, "LITERAL", len))
|
||||
{
|
||||
if (match)
|
||||
{
|
||||
say("Second -LITERAL argument ignored");
|
||||
(void) new_next_arg(args, &args);
|
||||
continue;
|
||||
}
|
||||
if ((match = new_next_arg(args, &args)) != NULL)
|
||||
continue;
|
||||
say("Need pattern for -LITERAL");
|
||||
return;
|
||||
}
|
||||
else if (!my_strnicmp(arg, "REVERSE", len))
|
||||
reverse = 1;
|
||||
else if (!my_strnicmp(arg, "TIME", len))
|
||||
time_log = 0;
|
||||
else if (!my_strnicmp(arg, "BEEP", len))
|
||||
{
|
||||
if (match)
|
||||
{
|
||||
say("-BEEP is exclusive; ignored");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
match = "\007";
|
||||
}
|
||||
else if (!my_strnicmp(arg, "CLEAR", len))
|
||||
{
|
||||
free_lastlog(current_window);
|
||||
say("Cleared lastlog");
|
||||
return;
|
||||
}
|
||||
else if (!my_strnicmp(arg, "APPEND", len))
|
||||
file_open_type = 1;
|
||||
else if (!my_strnicmp(arg, "FILE", len))
|
||||
{
|
||||
#ifdef PUBLIC_ACCESS
|
||||
bitchsay("This command has been disabled on a public access system");
|
||||
return;
|
||||
#else
|
||||
if (args && *args)
|
||||
{
|
||||
char *filename;
|
||||
filename = next_arg(args, &args);
|
||||
if (!(fp = fopen(filename, file_open[file_open_type])))
|
||||
{
|
||||
bitchsay("cannot open file %s", filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bitchsay("Filename needed for save");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (!my_strnicmp(arg, "MORE", len))
|
||||
{
|
||||
current_window->save_hold_mode = current_window->hold_mode;
|
||||
current_window->in_more = 1;
|
||||
reset_line_cnt(current_window, NULL, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*arg == '-')
|
||||
remove = 1, arg++;
|
||||
else
|
||||
remove = 0;
|
||||
|
||||
/*
|
||||
* Which can be combined with -ALL, which
|
||||
* turns on all levels. Use --MSGS or
|
||||
* whatever to turn off ones you dont want.
|
||||
*/
|
||||
if (!my_strnicmp(arg, "ALL", len))
|
||||
{
|
||||
if (remove)
|
||||
mask = 0;
|
||||
else
|
||||
mask = LOG_ALL;
|
||||
continue; /* Go to next arg */
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the lastlog level in our list.
|
||||
*/
|
||||
for (i = 0, p = 1; i < NUMBER_OF_LEVELS; i++, p *= 2)
|
||||
{
|
||||
if (!my_strnicmp(levels[i], arg, len))
|
||||
{
|
||||
if (remove)
|
||||
mask &= ~p;
|
||||
else
|
||||
mask |= p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == NUMBER_OF_LEVELS)
|
||||
{
|
||||
bitchsay("Unknown flag: %s", arg);
|
||||
reset_display_target();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (level == 0)
|
||||
{
|
||||
if (match || isdigit((unsigned char)*arg))
|
||||
{
|
||||
cnt = atoi(arg);
|
||||
level++;
|
||||
}
|
||||
else
|
||||
match = arg;
|
||||
}
|
||||
else if (level == 1)
|
||||
{
|
||||
from = atoi(arg);
|
||||
level++;
|
||||
}
|
||||
}
|
||||
}
|
||||
start_pos = current_window->lastlog_head;
|
||||
level = current_window->lastlog_level;
|
||||
msg_level = set_lastlog_msg_level(0);
|
||||
|
||||
if (!reverse)
|
||||
{
|
||||
for (i = 0; (i < from) && start_pos; start_pos = start_pos->next)
|
||||
if (!mask || (mask & start_pos->level))
|
||||
i++;
|
||||
|
||||
for (i = 0; (i < cnt) && start_pos; start_pos = start_pos->next)
|
||||
if (!mask || (mask & start_pos->level))
|
||||
i++;
|
||||
|
||||
start_pos = (start_pos) ? start_pos->prev : current_window->lastlog_tail;
|
||||
} else
|
||||
start_pos = current_window->lastlog_head;
|
||||
|
||||
/* Let's not get confused here, display a seperator.. -lynx */
|
||||
strip_ansi_in_echo = 0;
|
||||
if (header && !fp)
|
||||
say("Lastlog:");
|
||||
|
||||
if (match)
|
||||
{
|
||||
|
||||
blah = (char *) alloca(strlen(match)+4);
|
||||
sprintf(blah, "*%s*", match);
|
||||
}
|
||||
for (i = 0; (i < cnt) && start_pos; start_pos = (reverse ? start_pos->next : start_pos->prev))
|
||||
{
|
||||
if (!mask || (mask & start_pos->level))
|
||||
{
|
||||
i++;
|
||||
if (!match || wild_match(blah, start_pos->msg))
|
||||
{
|
||||
char *s = !get_int_var(LASTLOG_ANSI_VAR)?stripansicodes(start_pos->msg):start_pos->msg;
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
put_it("%s", !time_log ? s : convert_output_format(fget_string_var(FORMAT_LASTLOG_FSET), "%l %s", start_pos->time, s));
|
||||
grab_http("*", "*", start_pos->msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (time_log)
|
||||
{
|
||||
s = convert_output_format(fget_string_var(FORMAT_LASTLOG_FSET), "%l %s", start_pos->time, s);
|
||||
chop(s, 3);
|
||||
}
|
||||
fprintf(fp, "%s\n", s);
|
||||
}
|
||||
if (lines == 0)
|
||||
continue;
|
||||
else if (lines == 1)
|
||||
break;
|
||||
lines--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (header && !fp)
|
||||
say("End of Lastlog");
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
strip_ansi_in_echo = 1;
|
||||
current_window->lastlog_level = level;
|
||||
set_lastlog_msg_level(msg_level);
|
||||
}
|
||||
|
||||
Lastlog *get_lastlog_current_head(Window *win)
|
||||
{
|
||||
return win->lastlog_head;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_to_lastlog: adds the line to the lastlog. If the LASTLOG_CONVERSATION
|
||||
* variable is on, then only those lines that are user messages (private
|
||||
* messages, channel messages, wall's, and any outgoing messages) are
|
||||
* recorded, otherwise, everything is recorded
|
||||
*/
|
||||
void add_to_lastlog(Window *window, const char *line)
|
||||
{
|
||||
Lastlog *new;
|
||||
|
||||
if (window == NULL)
|
||||
window = current_window;
|
||||
if (window->lastlog_level & msg_level)
|
||||
{
|
||||
/* no nulls or empty lines (they contain "> ") */
|
||||
if (line && (strlen(line) > 2))
|
||||
{
|
||||
new = (Lastlog *) new_malloc(sizeof(Lastlog));
|
||||
new->next = window->lastlog_head;
|
||||
new->prev = NULL;
|
||||
new->level = msg_level;
|
||||
new->msg = NULL;
|
||||
new->time = now;
|
||||
new->msg = m_strdup(line);
|
||||
|
||||
if (window->lastlog_head)
|
||||
window->lastlog_head->prev = new;
|
||||
window->lastlog_head = new;
|
||||
|
||||
if (window->lastlog_tail == NULL)
|
||||
window->lastlog_tail = window->lastlog_head;
|
||||
|
||||
if (window->lastlog_size++ >= window->lastlog_max)
|
||||
remove_from_lastlog(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long real_notify_level(void)
|
||||
{
|
||||
return (notify_level);
|
||||
}
|
||||
|
||||
unsigned long real_lastlog_level(void)
|
||||
{
|
||||
return (lastlog_level);
|
||||
}
|
||||
|
||||
void set_notify_level(Window *win, char *str, int unused)
|
||||
{
|
||||
notify_level = parse_lastlog_level(str, 1);
|
||||
set_string_var(NOTIFY_LEVEL_VAR, bits_to_lastlog_level(notify_level));
|
||||
current_window->notify_level = notify_level;
|
||||
}
|
||||
|
||||
int logmsg(unsigned long log_type, char *from, int flag, char *format, ...)
|
||||
{
|
||||
#ifdef PUBLIC_ACCESS
|
||||
return 0;
|
||||
#else
|
||||
char *timestr;
|
||||
time_t t;
|
||||
char *filename = NULL;
|
||||
char *expand = NULL;
|
||||
char *type = NULL;
|
||||
unsigned char **lines = NULL;
|
||||
char msglog_buffer[BIG_BUFFER_SIZE+1];
|
||||
|
||||
|
||||
if (!get_string_var(MSGLOGFILE_VAR) || !get_string_var(CTOOLZ_DIR_VAR))
|
||||
return 0;
|
||||
|
||||
t = now;
|
||||
timestr = update_clock(GET_TIME);
|
||||
|
||||
|
||||
if (format)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vsnprintf(msglog_buffer, BIG_BUFFER_SIZE, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
switch (flag)
|
||||
{
|
||||
case 0:
|
||||
if (!(type = bits_to_lastlog_level(log_type)))
|
||||
type = "Unknown";
|
||||
if (msglog_level & log_type && format)
|
||||
{
|
||||
char *format;
|
||||
|
||||
if (!do_hook(MSGLOG_LIST, "%s %s %s %s", timestr, type, from, msglog_buffer))
|
||||
break;
|
||||
if (!logptr)
|
||||
return 0;
|
||||
if (!(format = fget_string_var(FORMAT_MSGLOG_FSET)))
|
||||
format = "[$[10]0] [$1] - $2-";
|
||||
lines = split_up_line(stripansicodes(convert_output_format(format, "%s %s %s %s", type, timestr, from, msglog_buffer)), 80);
|
||||
for ( ; *lines; lines++)
|
||||
{
|
||||
char *local_copy;
|
||||
int len = strlen(*lines) * 2 + 1;
|
||||
if (!*lines || !**lines) break;
|
||||
local_copy = alloca(len);
|
||||
strcpy(local_copy, *lines);
|
||||
|
||||
if (local_copy[strlen(local_copy)-1] == ALL_OFF)
|
||||
local_copy[strlen(local_copy)-1] = 0;
|
||||
if (logfile_line_mangler)
|
||||
mangle_line(local_copy, logfile_line_mangler, len);
|
||||
if (*local_copy)
|
||||
fprintf(logptr, "%s\n", local_copy);
|
||||
}
|
||||
fflush(logptr);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
malloc_sprintf(&filename, "%s/%s", get_string_var(CTOOLZ_DIR_VAR), get_string_var(MSGLOGFILE_VAR));
|
||||
expand = expand_twiddle(filename);
|
||||
new_free(&filename);
|
||||
if (!do_hook(MSGLOG_LIST, "%s %s %s %s", timestr, "On", expand, empty_string))
|
||||
{
|
||||
new_free(&expand);
|
||||
return 1;
|
||||
}
|
||||
if (logptr)
|
||||
{
|
||||
new_free(&expand);
|
||||
return 1;
|
||||
}
|
||||
if (!(logptr = fopen(expand, get_int_var(APPEND_LOG_VAR)?"at":"wt")))
|
||||
{
|
||||
set_int_var(MSGLOG_VAR, 0);
|
||||
new_free(&expand);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(logptr, "MsgLog started [%s]\n", my_ctime(t));
|
||||
fflush(logptr);
|
||||
if (format)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = logmsg(LOG_CURRENT, from, 0, "%s", msglog_buffer);
|
||||
return i;
|
||||
}
|
||||
bitchsay("Now logging messages to: %s", expand);
|
||||
new_free(&expand);
|
||||
break;
|
||||
case 2:
|
||||
if (!do_hook(MSGLOG_LIST, "%s %s %s %s", timestr, "Off", empty_string, empty_string))
|
||||
return 1;
|
||||
if (!logptr)
|
||||
return 1;
|
||||
fprintf(logptr, "MsgLog ended [%s]\n", my_ctime(t));
|
||||
fclose(logptr);
|
||||
logptr = NULL;
|
||||
break;
|
||||
case 3:
|
||||
return logptr ? 1 : 0;
|
||||
break;
|
||||
case 4:
|
||||
if (!logptr)
|
||||
return 1;
|
||||
fprintf(logptr, "[TimeStamp %s]\n", my_ctime(t));
|
||||
fflush(logptr);
|
||||
break;
|
||||
default:
|
||||
bitchsay("Bad Flag passed to logmsg");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_beep_on_msg (Window *win, char *str, int unused)
|
||||
{
|
||||
beep_on_level = parse_lastlog_level(str, 1);
|
||||
set_string_var(BEEP_ON_MSG_VAR, bits_to_lastlog_level(beep_on_level));
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(awaylog)
|
||||
{
|
||||
if (args && *args)
|
||||
{
|
||||
msglog_level = parse_lastlog_level(args, 1);
|
||||
set_string_var(MSGLOG_LEVEL_VAR, bits_to_lastlog_level(msglog_level));
|
||||
put_it("%s", convert_output_format("$G Away logging set to: $0-", "%s", get_string_var(MSGLOG_LEVEL_VAR)));
|
||||
}
|
||||
else
|
||||
put_it("%s", convert_output_format("$G Away logging currently: $0-", "%s", bits_to_lastlog_level(msglog_level)));
|
||||
}
|
||||
|
||||
#define EMPTY empty_string
|
||||
#define RETURN_EMPTY return m_strdup(EMPTY)
|
||||
#define RETURN_IF_EMPTY(x) if (empty( x )) RETURN_EMPTY
|
||||
#define GET_INT_ARG(x, y) {RETURN_IF_EMPTY(y); x = my_atol(safe_new_next_arg(y, &y));}
|
||||
#define GET_STR_ARG(x, y) {RETURN_IF_EMPTY((y)); x = new_next_arg((y), &(y));RETURN_IF_EMPTY((x));}
|
||||
#define RETURN_STR(x) return m_strdup(x ? x : EMPTY);
|
||||
|
||||
/*
|
||||
* $line(<line number> [window number])
|
||||
* Returns the text of logical line <line number> from the lastlog of
|
||||
* window <window number>. If no window number is supplied, the current
|
||||
* window will be used. If the window number is invalid, the function
|
||||
* will return the false value.
|
||||
*
|
||||
* Lines are numbered from 1, starting at the most recent line in the buffer.
|
||||
* Contributed by Crackbaby (Matt Carothers) on March 19, 1998.
|
||||
*/
|
||||
|
||||
BUILT_IN_FUNCTION(function_line)
|
||||
{
|
||||
int line = 0;
|
||||
char * windesc = zero;
|
||||
Lastlog *start_pos;
|
||||
Window *win;
|
||||
char *extra;
|
||||
int do_level = 0;
|
||||
|
||||
|
||||
GET_INT_ARG(line, input);
|
||||
|
||||
while (input && *input)
|
||||
{
|
||||
GET_STR_ARG(extra, input);
|
||||
|
||||
if (!my_stricmp(extra, "-LEVEL"))
|
||||
do_level = 1;
|
||||
else
|
||||
windesc = extra;
|
||||
}
|
||||
|
||||
/* Get the current window, default to current window */
|
||||
if (!(win = get_window_by_desc(windesc)))
|
||||
RETURN_EMPTY;
|
||||
|
||||
/* Make sure that the line request is within reason */
|
||||
if (line < 1 || line > win->lastlog_size)
|
||||
RETURN_EMPTY;
|
||||
|
||||
/* Get the line from the lastlog */
|
||||
for (start_pos = win->lastlog_head; line; start_pos = start_pos->next)
|
||||
line--;
|
||||
|
||||
if (!start_pos)
|
||||
start_pos = win->lastlog_tail;
|
||||
else
|
||||
start_pos = start_pos->prev;
|
||||
|
||||
if (do_level)
|
||||
return m_sprintf("%s %s", start_pos->msg,
|
||||
levels[start_pos->level]);
|
||||
else
|
||||
RETURN_STR(start_pos->msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* $lastlog(<window description> <lastlog levels>)
|
||||
* Returns all of the lastlog lines (suitable for use with $line()) on the
|
||||
* indicated window (0 for the current window) that have any of the lastlog
|
||||
* levels as represented by the lastlog levels. If the window number is
|
||||
* invalid, the function will return the false value.
|
||||
*/
|
||||
|
||||
BUILT_IN_FUNCTION(function_lastlog)
|
||||
{
|
||||
char * windesc = zero;
|
||||
char * pattern = NULL;
|
||||
char * retval = NULL;
|
||||
Lastlog *iter;
|
||||
Window *win;
|
||||
int levels;
|
||||
int line = 1;
|
||||
|
||||
GET_STR_ARG(windesc, input);
|
||||
GET_STR_ARG(pattern, input);
|
||||
levels = parse_lastlog_level(input, 0);
|
||||
|
||||
/* Get the current window, default to current window */
|
||||
if (!(win = get_window_by_desc(windesc)))
|
||||
RETURN_EMPTY;
|
||||
|
||||
for (iter = win->lastlog_head; iter; iter = iter->next, line++)
|
||||
{
|
||||
if (iter->level & levels)
|
||||
if (wild_match(pattern, iter->msg))
|
||||
m_s3cat(&retval, space, ltoa(line));
|
||||
}
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
RETURN_EMPTY;
|
||||
}
|
||||
|
||||
|
||||
224
source/list.c
Normal file
224
source/list.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* list.c: some generic linked list managing stuff
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
*
|
||||
* Copyright(c) 1990
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: list.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(list_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include "ircaux.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
static int add_list_stricmp (List *, List *);
|
||||
static int list_stricmp (List *, char *);
|
||||
static int list_match (List *, char *);
|
||||
|
||||
/*
|
||||
* These have now been made more general. You used to only be able to
|
||||
* order these lists by alphabetical order. You can now order them
|
||||
* arbitrarily. The functions are still called the same way if you
|
||||
* wish to use alphabetical order on the key string, and the old
|
||||
* function name now represents a stub function which calls the
|
||||
* new with the appropriate parameters.
|
||||
*
|
||||
* The new function name is the same in each case as the old function
|
||||
* name, with the addition of a new parameter, cmp_func, which is
|
||||
* used to perform comparisons.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
static int add_list_strcmp(List *item1, List *item2)
|
||||
{
|
||||
return strcmp(item1->name, item2->name);
|
||||
}
|
||||
*/
|
||||
|
||||
static int add_list_stricmp(List *item1, List *item2)
|
||||
{
|
||||
return my_stricmp(item1->name, item2->name);
|
||||
}
|
||||
|
||||
/*
|
||||
static int list_strcmp(List *item1, char *str)
|
||||
{
|
||||
return strcmp(item1->name, str);
|
||||
}
|
||||
*/
|
||||
|
||||
static int list_stricmp(List *item1, char *str)
|
||||
{
|
||||
return my_stricmp(item1->name, str);
|
||||
}
|
||||
|
||||
int list_strnicmp(List *item1, char *str)
|
||||
{
|
||||
return my_strnicmp(item1->name, str, strlen(str));
|
||||
}
|
||||
|
||||
static int list_wildstrcmp(List *item1, char *str)
|
||||
{
|
||||
if (wild_match(item1->name, str) || wild_match(str, item1->name))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int list_match(List *item1, char *str)
|
||||
{
|
||||
return wild_match(item1->name, str);
|
||||
}
|
||||
|
||||
/*
|
||||
* add_to_list: This will add an element to a list. The requirements for the
|
||||
* list are that the first element in each list structure be a pointer to the
|
||||
* next element in the list, and the second element in the list structure be
|
||||
* a pointer to a character (char *) which represents the sort key. For
|
||||
* example
|
||||
*
|
||||
* struct my_list{ struct my_list *next; char *name; <whatever else you want>};
|
||||
*
|
||||
* The parameters are: "list" which is a pointer to the head of the list. "add"
|
||||
* which is a pre-allocated element to be added to the list.
|
||||
*/
|
||||
void BX_add_to_list_ext(List **list, List *add, int (*cmp_func)(List *, List *))
|
||||
{
|
||||
register List *tmp;
|
||||
List *last;
|
||||
|
||||
if (!cmp_func)
|
||||
cmp_func = add_list_stricmp;
|
||||
last = NULL;
|
||||
for (tmp = *list; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (cmp_func(tmp, add) > 0)
|
||||
break;
|
||||
last = tmp;
|
||||
}
|
||||
if (last)
|
||||
last->next = add;
|
||||
else
|
||||
*list = add;
|
||||
add->next = tmp;
|
||||
}
|
||||
|
||||
void BX_add_to_list(List **list, List *add)
|
||||
{
|
||||
add_to_list_ext(list, add, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* find_in_list: This looks up the given name in the given list. List and
|
||||
* name are as described above. If wild is true, each name in the list is
|
||||
* used as a wild card expression to match name... otherwise, normal matching
|
||||
* is done
|
||||
*/
|
||||
List * BX_find_in_list_ext(register List **list, char *name, int wild, int (*cmp_func)(List *, char *))
|
||||
{
|
||||
register List *tmp;
|
||||
int best_match,
|
||||
current_match;
|
||||
|
||||
if (!cmp_func)
|
||||
cmp_func = wild ? list_match : list_stricmp;
|
||||
best_match = 0;
|
||||
|
||||
if (wild)
|
||||
{
|
||||
register List *match = NULL;
|
||||
|
||||
for (tmp = *list; tmp; tmp = tmp->next)
|
||||
{
|
||||
if ((current_match = cmp_func(tmp, name)) > best_match)
|
||||
{
|
||||
match = tmp;
|
||||
best_match = current_match;
|
||||
}
|
||||
}
|
||||
return (match);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (tmp = *list; tmp; tmp = tmp->next)
|
||||
if (cmp_func(tmp, name) == 0)
|
||||
return (tmp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List * BX_find_in_list(List **list, char *name, int wild)
|
||||
{
|
||||
return find_in_list_ext(list, name, wild, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_from_list: this remove the given name from the given list (again as
|
||||
* described above). If found, it is removed from the list and returned
|
||||
* (memory is not deallocated). If not found, null is returned.
|
||||
*/
|
||||
List *BX_remove_from_list_ext(List **list, char *name, int (*cmp_func)(List *, char *))
|
||||
{
|
||||
register List *tmp;
|
||||
List *last;
|
||||
|
||||
if (!cmp_func)
|
||||
cmp_func = list_stricmp;
|
||||
last = NULL;
|
||||
for (tmp = *list; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (!cmp_func(tmp, name))
|
||||
{
|
||||
if (last)
|
||||
last->next = tmp->next;
|
||||
else
|
||||
*list = tmp->next;
|
||||
return (tmp);
|
||||
}
|
||||
last = tmp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List *BX_remove_from_list(List **list, char *name)
|
||||
{
|
||||
return remove_from_list_ext(list, name, NULL);
|
||||
}
|
||||
|
||||
List *BX_removewild_from_list(List **list, char *name)
|
||||
{
|
||||
return remove_from_list_ext(list, name, list_wildstrcmp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* list_lookup: this routine just consolidates remove_from_list and
|
||||
* find_in_list. I did this cause it fit better with some already existing
|
||||
* code
|
||||
*/
|
||||
List *BX_list_lookup_ext(register List **list, char *name, int wild, int delete, int (*cmp_func)(List *, char *))
|
||||
{
|
||||
register List *tmp;
|
||||
|
||||
if (delete)
|
||||
tmp = remove_from_list_ext(list, name, cmp_func);
|
||||
else
|
||||
tmp = find_in_list_ext(list, name, wild, cmp_func);
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
List *BX_list_lookup(List **list, char *name, int wild, int delete)
|
||||
{
|
||||
return list_lookup_ext(list, name, wild, delete, NULL);
|
||||
}
|
||||
151
source/log.c
Normal file
151
source/log.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* log.c: handles the irc session logging functions
|
||||
*
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
*
|
||||
* Copyright(c) 1990
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: log.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(log_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "vars.h"
|
||||
#include "screen.h"
|
||||
#include "misc.h"
|
||||
#include "output.h"
|
||||
#include "ircaux.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
FILE *irclog_fp = NULL;
|
||||
|
||||
void do_log(int flag, char *logfile, FILE **fp)
|
||||
{
|
||||
#ifdef PUBLIC_ACCESS
|
||||
bitchsay("This command has been disabled on a public access system");
|
||||
return;
|
||||
#else
|
||||
time_t t = now;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
if (*fp)
|
||||
say("Logging is already on");
|
||||
else
|
||||
{
|
||||
if (!logfile)
|
||||
return;
|
||||
if (!(logfile = expand_twiddle(logfile)))
|
||||
{
|
||||
say("SET LOGFILE: No such user");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((*fp = fopen(logfile, get_int_var(APPEND_LOG_VAR)?"a":"w")) != NULL)
|
||||
{
|
||||
say("Starting logfile %s", logfile);
|
||||
chmod(logfile, S_IREAD | S_IWRITE);
|
||||
fprintf(*fp, "IRC log started %.24s\n", ctime(&t));
|
||||
fflush(*fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
say("Couldn't open logfile %s: %s", logfile, strerror(errno));
|
||||
*fp = NULL;
|
||||
}
|
||||
new_free(&logfile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*fp)
|
||||
{
|
||||
fprintf(*fp, "IRC log ended %.24s\n", ctime(&t));
|
||||
fflush(*fp);
|
||||
fclose(*fp);
|
||||
*fp = NULL;
|
||||
say("Logfile ended");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* logger: if flag is 0, logging is turned off, else it's turned on */
|
||||
void logger(Window *win, char *unused, int flag)
|
||||
{
|
||||
char *logfile;
|
||||
if ((logfile = get_string_var(LOGFILE_VAR)) == NULL)
|
||||
{
|
||||
say("You must set the LOGFILE variable first!");
|
||||
set_int_var(LOG_VAR, 0);
|
||||
return;
|
||||
}
|
||||
do_log(flag, logfile, &irclog_fp);
|
||||
if (!irclog_fp && flag)
|
||||
set_int_var(LOG_VAR, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* set_log_file: sets the log file name. If logging is on already, this
|
||||
* closes the last log file and reopens it with the new name. This is called
|
||||
* automatically when you SET LOGFILE.
|
||||
*/
|
||||
void set_log_file(Window *win, char *filename, int unused)
|
||||
{
|
||||
char *expanded;
|
||||
|
||||
if (filename)
|
||||
{
|
||||
if (strcmp(filename, get_string_var(LOGFILE_VAR)))
|
||||
expanded = expand_twiddle(filename);
|
||||
else
|
||||
expanded = expand_twiddle(get_string_var(LOGFILE_VAR));
|
||||
set_string_var(LOGFILE_VAR, expanded);
|
||||
new_free(&expanded);
|
||||
if (irclog_fp)
|
||||
{
|
||||
logger(current_window, NULL, 0);
|
||||
logger(current_window, NULL, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* add_to_log: add the given line to the log file. If no log file is open
|
||||
* this function does nothing.
|
||||
*/
|
||||
void BX_add_to_log(FILE *fp, time_t t, const char *line, int mangler)
|
||||
{
|
||||
#ifndef PUBLIC_ACCESS
|
||||
if (fp && !inhibit_logging)
|
||||
{
|
||||
char *local_line;
|
||||
int len = strlen(line) * 2 + 1;
|
||||
local_line = alloca(len);
|
||||
strcpy(local_line, line);
|
||||
|
||||
/* Do this first */
|
||||
if (mangler)
|
||||
mangle_line(local_line, mangler, len);
|
||||
else if (!get_int_var(MIRCS_VAR))
|
||||
{
|
||||
char *tmp = alloca(strlen(local_line) + 1);
|
||||
strip_control(local_line, tmp);
|
||||
strcpy(local_line, tmp);
|
||||
}
|
||||
|
||||
|
||||
fprintf(fp, "%s\n", local_line);
|
||||
fflush(fp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
290
source/mail.c
Normal file
290
source/mail.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Mail check routines. Based on EPIC's mail check
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: mail.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(mail_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "mail.h"
|
||||
#include "lastlog.h"
|
||||
#include "hook.h"
|
||||
#include "vars.h"
|
||||
#include "ircaux.h"
|
||||
#include "output.h"
|
||||
#include "window.h"
|
||||
#include "status.h"
|
||||
#include "misc.h"
|
||||
#include "module.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !defined(HAVE_QMAIL)
|
||||
static char *mail_path = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QMAIL)
|
||||
/*
|
||||
* count_maildir_mail: counts total # of mails (in cur and new)
|
||||
*/
|
||||
int count_maildir_mail(void)
|
||||
{
|
||||
int count = 0;
|
||||
DIR *dp;
|
||||
struct dirent *dir;
|
||||
char *mail_path, *m;
|
||||
|
||||
m = m_sprintf("%s/cur", UNIX_MAIL);
|
||||
mail_path = expand_twiddle(m);
|
||||
new_free(&m);
|
||||
|
||||
if ((dp = opendir(mail_path)))
|
||||
{
|
||||
while ((dir = readdir(dp)))
|
||||
{
|
||||
if (!dir->d_ino || (dir->d_name[0] == '.'))
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
}
|
||||
|
||||
new_free(&mail_path);
|
||||
m = m_sprintf("%s/new", UNIX_MAIL);
|
||||
mail_path = expand_twiddle(m);
|
||||
new_free(&m);
|
||||
|
||||
if ((dp = opendir(mail_path)))
|
||||
{
|
||||
while ((dir = readdir(dp)))
|
||||
{
|
||||
if (!dir->d_ino || (dir->d_name[0] == '.'))
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
}
|
||||
|
||||
new_free(&mail_path);
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef UNIX_MAIL
|
||||
#define UNIX_MAIL "/var/spool/mail"
|
||||
#endif
|
||||
|
||||
#ifndef MAIL_DELIMITER
|
||||
#define MAIL_DELIMITER "From "
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WANT_DLL
|
||||
#define check_ext_mail global_table[CHECK_EXT_MAIL]
|
||||
#define check_ext_mail_status global_table[CHECK_EXT_MAIL_STATUS]
|
||||
#endif
|
||||
|
||||
/*
|
||||
* check_mail_status: returns 0 if mail status has not changed, 1 if mail
|
||||
* status has changed
|
||||
*/
|
||||
#ifdef PUBLIC_ACCESS
|
||||
int check_mail_status(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int check_mail_status(void)
|
||||
{
|
||||
#if defined(HAVE_QMAIL)
|
||||
int count = 0;
|
||||
static int c = 0;
|
||||
#else
|
||||
static time_t old_stat = 0;
|
||||
struct stat stat_buf;
|
||||
#endif
|
||||
#ifdef WANT_DLL
|
||||
if (check_ext_mail)
|
||||
return (*check_ext_mail_status)();
|
||||
#endif
|
||||
if (!get_int_var(MAIL_VAR))
|
||||
{
|
||||
#if defined(HAVE_QMAIL)
|
||||
c = 0;
|
||||
#else
|
||||
old_stat = 0;
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(HAVE_QMAIL)
|
||||
count = count_maildir_mail();
|
||||
if (count > c)
|
||||
{
|
||||
c = count;
|
||||
return c;
|
||||
}
|
||||
if (count < c)
|
||||
{
|
||||
int diff;
|
||||
diff = count - c;
|
||||
c = count;
|
||||
return diff;
|
||||
}
|
||||
#else
|
||||
if (!mail_path)
|
||||
{
|
||||
char *tmp_mail_path;
|
||||
if ((tmp_mail_path = getenv("MAIL")) != NULL)
|
||||
mail_path = m_strdup(tmp_mail_path);
|
||||
else
|
||||
#ifdef __EMX__
|
||||
mail_path = m_sprintf("%s/mqueue", getenv("ETC"));
|
||||
#else
|
||||
mail_path = m_3dup(UNIX_MAIL, "/", username);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (stat(mail_path, &stat_buf) == -1)
|
||||
return 0;
|
||||
|
||||
if (stat_buf.st_ctime > old_stat)
|
||||
{
|
||||
old_stat = stat_buf.st_ctime;
|
||||
if (stat_buf.st_size)
|
||||
return 2;
|
||||
}
|
||||
if (stat_buf.st_size)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* check_mail: This here thing counts up the number of pieces of mail and
|
||||
* returns it as static string. If there are no mail messages, null is
|
||||
* returned.
|
||||
*/
|
||||
|
||||
char *check_mail (void)
|
||||
{
|
||||
static int old_count = 0;
|
||||
static char ret_str[12];
|
||||
static int i = 0;
|
||||
#ifdef WANT_DLL
|
||||
if (check_ext_mail)
|
||||
return (char *)(*check_ext_mail)();
|
||||
#endif
|
||||
switch (get_int_var(MAIL_VAR))
|
||||
{
|
||||
case 0:
|
||||
return NULL;
|
||||
case 1:
|
||||
{
|
||||
char this[] = "\\|/-";
|
||||
#if defined(HAVE_QMAIL)
|
||||
int count = check_mail_status();
|
||||
if (count > 0)
|
||||
{
|
||||
set_display_target(NULL, LOG_CRAP);
|
||||
if (do_hook(MAIL_LIST, "%s %s", "Mail", "Yes"))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_MAIL_FSET), "%s %s %s", update_clock(GET_TIME), "Mail", "Yes"));
|
||||
++i;
|
||||
reset_display_target();
|
||||
if (i == 4)
|
||||
i = 0;
|
||||
}
|
||||
sprintf(ret_str, "%c", this[i]);
|
||||
|
||||
return ret_str;
|
||||
#else
|
||||
switch(check_mail_status())
|
||||
{
|
||||
case 2:
|
||||
set_display_target(NULL, LOG_CRAP);
|
||||
if (do_hook(MAIL_LIST, "%s %s", "Mail", "Yes"))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_MAIL_FSET), "%s %s %s", update_clock(GET_TIME), "Mail", "Yes"));
|
||||
reset_display_target();
|
||||
if (i == 4)
|
||||
i = 0;
|
||||
sprintf(ret_str, "%c", this[i++]);
|
||||
case 1:
|
||||
if (!*ret_str)
|
||||
return NULL;
|
||||
return ret_str;
|
||||
case 0:
|
||||
i = 0;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
register int count = 0;
|
||||
#if defined(HAVE_QMAIL)
|
||||
count = count_maildir_mail();
|
||||
if (count == 0)
|
||||
{
|
||||
old_count = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (count > old_count)
|
||||
{
|
||||
set_display_target(NULL, LOG_CRAP);
|
||||
if (do_hook(MAIL_LIST, "%d %d", count - old_count, count))
|
||||
say("You have new email.");
|
||||
reset_display_target();
|
||||
}
|
||||
|
||||
old_count = count;
|
||||
sprintf(ret_str, "%d", old_count);
|
||||
return ret_str;
|
||||
#else
|
||||
FILE *mail;
|
||||
char buffer[255];
|
||||
switch(check_mail_status())
|
||||
{
|
||||
|
||||
case 0:
|
||||
old_count = 0;
|
||||
return NULL;
|
||||
case 2:
|
||||
{
|
||||
if (!(mail = fopen(mail_path, "r")))
|
||||
return NULL;
|
||||
|
||||
while (fgets(buffer, 254, mail))
|
||||
if (!strncmp(MAIL_DELIMITER, buffer, 5))
|
||||
count++;
|
||||
|
||||
fclose(mail);
|
||||
|
||||
if (count > old_count)
|
||||
{
|
||||
set_display_target(NULL, LOG_CRAP);
|
||||
if (do_hook(MAIL_LIST, "%d %d", count - old_count, count))
|
||||
say("You have new email.");
|
||||
reset_display_target();
|
||||
}
|
||||
|
||||
old_count = count;
|
||||
sprintf(ret_str, "%d", old_count);
|
||||
}
|
||||
case 1:
|
||||
if (*ret_str)
|
||||
return ret_str;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
5125
source/misc.c
Normal file
5125
source/misc.c
Normal file
File diff suppressed because it is too large
Load Diff
1385
source/modules.c
Normal file
1385
source/modules.c
Normal file
File diff suppressed because it is too large
Load Diff
2071
source/names.c
Normal file
2071
source/names.c
Normal file
File diff suppressed because it is too large
Load Diff
852
source/network.c
Normal file
852
source/network.c
Normal file
@@ -0,0 +1,852 @@
|
||||
/*
|
||||
* network.c -- handles stuff dealing with connecting and name resolving
|
||||
*
|
||||
* Written by Jeremy Nelson in 1995
|
||||
* See the COPYRIGHT file or do /help ircii copyright
|
||||
*/
|
||||
#define SET_SOURCE_SOCKET
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: network.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(network_c)
|
||||
#include "struct.h"
|
||||
#include "ircterm.h"
|
||||
|
||||
#include "ircaux.h"
|
||||
#include "output.h"
|
||||
#include "vars.h"
|
||||
|
||||
#include "struct.h"
|
||||
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_FILIO_H
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
#ifdef PARANOID
|
||||
/* NaiL^d0d: no hijack please, we need random bytes, in stdlib.h */
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
extern char hostname[NAME_LEN+1];
|
||||
extern int use_socks;
|
||||
char *socks_user = NULL;
|
||||
|
||||
#if !defined(WTERM_C) && !defined(STERM_C)
|
||||
|
||||
/*
|
||||
* Stuff pertaining to bouncing through socks proxies.
|
||||
*
|
||||
* written by Joshua J. Drake
|
||||
* on Nov. 4, 1998
|
||||
* last modified, nov. 14
|
||||
*/
|
||||
#define SOCKS_PORT 1080
|
||||
#define SOCKS4_VERSION 4
|
||||
#define SOCKS5_VERSION 5
|
||||
|
||||
/* auth types */
|
||||
#define AUTH_NONE 0x00
|
||||
#define AUTH_GSSAPI 0x01
|
||||
#define AUTH_PASSWD 0x02
|
||||
#define AUTH_CHAP 0x03
|
||||
|
||||
/* auth errors */
|
||||
#define AUTH_OK 0
|
||||
#define AUTH_FAIL -1
|
||||
|
||||
/* commands */
|
||||
#define SOCKS_CONNECT 1
|
||||
#define SOCKS_BIND 2
|
||||
#define SOCKS_UDP 3
|
||||
#define SOCKS_PING 0x80
|
||||
#define SOCKS_TRACER 0x81
|
||||
#define SOCKS_ANY 0xff
|
||||
|
||||
/* errors */
|
||||
#define SOCKS5_NOERR 0x00
|
||||
#define SOCKS5_RESULT 0x00
|
||||
#define SOCKS5_FAIL 0x01
|
||||
#define SOCKS5_AUTHORIZE 0x02
|
||||
#define SOCKS5_NETUNREACH 0x03
|
||||
#define SOCKS5_HOSTUNREACH 0x04
|
||||
#define SOCKS5_CONNREF 0x05
|
||||
#define SOCKS5_TTLEXP 0x06
|
||||
#define SOCKS5_BADCMND 0x07
|
||||
#define SOCKS5_BADADDR 0x08
|
||||
|
||||
/* flags */
|
||||
#define SOCKS5_FLAG_NONAME 0x01
|
||||
#define SOCKS5_FLAG_VERBOSE 0x02
|
||||
#define SOCKS5_IPV4ADDR 0x01
|
||||
#define SOCKS5_HOSTNAME 0x03
|
||||
#define SOCKS5_IPV6ADDR 0x04
|
||||
|
||||
char *socks4_error(char cd)
|
||||
{
|
||||
switch (cd)
|
||||
{
|
||||
case 91:
|
||||
return "rejected or failed";
|
||||
break;
|
||||
case 92:
|
||||
return "no identd";
|
||||
break;
|
||||
case 93:
|
||||
return "identd response != username";
|
||||
break;
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
char *socks5_error(char cd)
|
||||
{
|
||||
switch (cd)
|
||||
{
|
||||
case SOCKS5_FAIL:
|
||||
return "Rejected or failed";
|
||||
break;
|
||||
case SOCKS5_AUTHORIZE:
|
||||
return "Connection not allowed by ruleset";
|
||||
break;
|
||||
case SOCKS5_NETUNREACH:
|
||||
return "Network unreachable";
|
||||
break;
|
||||
case SOCKS5_HOSTUNREACH:
|
||||
return "Host unreachable";
|
||||
break;
|
||||
case SOCKS5_CONNREF:
|
||||
return "Connection refused";
|
||||
break;
|
||||
case SOCKS5_TTLEXP:
|
||||
return "Time to live expired";
|
||||
break;
|
||||
case SOCKS5_BADCMND:
|
||||
return "Bad command";
|
||||
break;
|
||||
case SOCKS5_BADADDR:
|
||||
return "Bad address";
|
||||
break;
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* try to negotiate a SOCKS4 connection.
|
||||
*
|
||||
*/
|
||||
int socks4_connect(int s, int portnum, struct sockaddr_in *server)
|
||||
{
|
||||
struct _sock_connect {
|
||||
char version;
|
||||
char type;
|
||||
unsigned short port;
|
||||
unsigned long address;
|
||||
char username[NAME_LEN+1];
|
||||
} sock4_connect;
|
||||
char socksreq[10];
|
||||
char *p;
|
||||
int red;
|
||||
|
||||
memset(&sock4_connect, 0, sizeof(sock4_connect));
|
||||
sock4_connect.version = SOCKS4_VERSION;
|
||||
sock4_connect.type = SOCKS_CONNECT;
|
||||
sock4_connect.port = server->sin_port;
|
||||
|
||||
strncpy(sock4_connect.username, socks_user? socks_user: getenv("USER") ? getenv("USER") : username, NAME_LEN);
|
||||
p = inet_ntoa(server->sin_addr);
|
||||
sock4_connect.address = inet_addr(p);
|
||||
if ((red = write(s, &sock4_connect, 8 + strlen(sock4_connect.username) + 1)) == -1)
|
||||
{
|
||||
bitchsay("Cannot write to socks proxy: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
alarm(get_int_var(CONNECT_TIMEOUT_VAR));
|
||||
if ((red = read(s, socksreq, 8)) == -1)
|
||||
{
|
||||
alarm(0);
|
||||
bitchsay("Cannot read from socks proxy: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
alarm(0);
|
||||
if (socksreq[1] != 90)
|
||||
{
|
||||
bitchsay("Cannot connect to SOCKS4 proxy: %s", socks4_error(socksreq[1]));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* try to negotiate a SOCKS5 connection. (with the socket/username, to the server)
|
||||
*/
|
||||
int socks5_connect(int s, int portnum, struct sockaddr_in *server)
|
||||
{
|
||||
struct _sock_connect {
|
||||
char version;
|
||||
char type;
|
||||
char authtype;
|
||||
char addrtype;
|
||||
unsigned long address;
|
||||
unsigned short port;
|
||||
char username[NAME_LEN+1];
|
||||
} sock5_connect;
|
||||
char tmpbuf[25], *p;
|
||||
struct in_addr tmpAddr;
|
||||
unsigned short tmpI;
|
||||
int red;
|
||||
|
||||
/* propose any authentication */
|
||||
memset(&sock5_connect, 0, sizeof(sock5_connect));
|
||||
sock5_connect.version = SOCKS5_VERSION;
|
||||
sock5_connect.type = SOCKS_CONNECT;
|
||||
sock5_connect.authtype = AUTH_NONE; /* AUTH_PASSWD, AUTH_GSSAPI, AUTH_CHAP */
|
||||
|
||||
if ((red = write(s, &sock5_connect, 4)) == -1)
|
||||
{
|
||||
bitchsay("Cannot write to proxy: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(tmpbuf, 0, sizeof(tmpbuf));
|
||||
alarm(get_int_var(CONNECT_TIMEOUT_VAR));
|
||||
if ((red = read(s, tmpbuf, sizeof(tmpbuf)-1)) == -1)
|
||||
{
|
||||
alarm(0);
|
||||
bitchsay("Cannot use SOCKS5 proxy, read failed during auth: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
alarm(0);
|
||||
/* report server desired authentication (if not none) */
|
||||
if (tmpbuf[1] != AUTH_NONE)
|
||||
{
|
||||
bitchsay("Cannot use SOCKS5 proxy, server wants type %x authentication.", tmpbuf[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* try to bounce to target */
|
||||
memset(&sock5_connect, 0, sizeof(sock5_connect));
|
||||
sock5_connect.version = SOCKS5_VERSION;
|
||||
sock5_connect.type = SOCKS_CONNECT;
|
||||
sock5_connect.addrtype = SOCKS5_IPV4ADDR;
|
||||
p = inet_ntoa(server->sin_addr);
|
||||
sock5_connect.address = inet_addr(p);
|
||||
sock5_connect.port = server->sin_port;
|
||||
|
||||
if ((red = write(s, &sock5_connect, 10)) == -1)
|
||||
{
|
||||
bitchsay("Cannot write to the proxy: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
memset(tmpbuf, 0, sizeof(tmpbuf)-1);
|
||||
alarm(get_int_var(CONNECT_TIMEOUT_VAR));
|
||||
if ((red = read(s, tmpbuf, sizeof(tmpbuf)-1)) == -1)
|
||||
{
|
||||
alarm(0);
|
||||
bitchsay("Cannot use SOCKS5 proxy, read failed during bounce: %s. Attempting SOCKS4", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
alarm(0);
|
||||
if (tmpbuf[0] != SOCKS5_VERSION)
|
||||
{
|
||||
bitchsay("This is not a SOCKS5 proxy.");
|
||||
return 0;
|
||||
}
|
||||
if (tmpbuf[1] != SOCKS5_NOERR)
|
||||
{
|
||||
bitchsay("Cannot use SOCKS5 proxy, server failed: %s", socks5_error(tmpbuf[1]));
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* read the rest of the response (depending on what type of address they use)
|
||||
*/
|
||||
alarm(get_int_var(CONNECT_TIMEOUT_VAR));
|
||||
switch (tmpbuf[3])
|
||||
{
|
||||
case 1:
|
||||
read(s, tmpbuf, 4);
|
||||
memcpy(&tmpAddr.s_addr, tmpbuf, 4);
|
||||
read(s, tmpbuf, 2);
|
||||
tmpbuf[3] = '\0';
|
||||
tmpI = atoi(tmpbuf);
|
||||
bitchsay("SOCKS5 bounce successful, your address will be: %s:%d", inet_ntoa(tmpAddr), ntohs(tmpI));
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
char buffer[256];
|
||||
read(s, tmpbuf, 1);
|
||||
tmpbuf[1] = '\0';
|
||||
tmpI = atoi(tmpbuf);
|
||||
read(s, tmpbuf, tmpI);
|
||||
tmpbuf[tmpI] = '\0';
|
||||
strncpy(buffer, tmpbuf, sizeof(buffer));
|
||||
read(s, tmpbuf, 2);
|
||||
tmpbuf[3] = '\0';
|
||||
tmpI = atoi(tmpbuf);
|
||||
bitchsay("SOCKS5 bounce successful, your address will be: %s:%d", buffer, ntohs(tmpI));
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
read(s, tmpbuf, 18);
|
||||
/* don't report address of ipv6 addresses. */
|
||||
bitchsay("SOCKS5 bounce successful. [ipv6]");
|
||||
break;
|
||||
default:
|
||||
bitchsay("error tmpbuf[3]: %x", tmpbuf[3]);
|
||||
alarm(0);
|
||||
return 0;
|
||||
}
|
||||
alarm(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int handle_socks(int fd, struct sockaddr_in addr, char *host, int portnum)
|
||||
{
|
||||
struct sockaddr_in proxy;
|
||||
struct hostent *hp;
|
||||
|
||||
memset(&proxy, 0, sizeof(proxy));
|
||||
if (!(hp = gethostbyname(host)))
|
||||
{
|
||||
bitchsay("Unable to resolve SOCKS proxy host address: %s", host);
|
||||
return -1;
|
||||
}
|
||||
bcopy(hp->h_addr, (char *)&proxy.sin_addr, hp->h_length);
|
||||
proxy.sin_family = AF_INET;
|
||||
proxy.sin_port = htons(portnum);
|
||||
alarm(get_int_var(CONNECT_TIMEOUT_VAR));
|
||||
if (connect(fd, (struct sockaddr *)&proxy, sizeof(proxy)) < 0)
|
||||
{
|
||||
alarm(0);
|
||||
bitchsay("Unable to connect to SOCKS5 proxy: %s", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
alarm(0);
|
||||
if (!socks5_connect(fd, portnum, &addr))
|
||||
{
|
||||
close(fd);
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
bitchsay("Unable to get socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
alarm(get_int_var(CONNECT_TIMEOUT_VAR));
|
||||
if (connect(fd, (struct sockaddr *)&proxy, sizeof(proxy)) < 0)
|
||||
{
|
||||
alarm(0);
|
||||
bitchsay("Unable to connect to SOCKS4 proxy: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
alarm(0);
|
||||
if (!socks4_connect(fd, portnum, &addr))
|
||||
{
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* connect_by_number: Wheeeee. Yet another monster function i get to fix
|
||||
* for the sake of it being inadequate for extension.
|
||||
*
|
||||
* we now take four arguments:
|
||||
*
|
||||
* - hostname - name of the host (pathname) to connect to (if applicable)
|
||||
* - portnum - port number to connect to or listen on (0 if you dont care)
|
||||
* - service - 0 - set up a listening socket
|
||||
* 1 - set up a connecting socket
|
||||
* - protocol - 0 - use the TCP protocol
|
||||
* 1 - use the UDP protocol
|
||||
*
|
||||
*
|
||||
* Returns:
|
||||
* Non-negative number -- new file descriptor ready for use
|
||||
* -1 -- could not open a new file descriptor or
|
||||
* an illegal value for the protocol was specified
|
||||
* -2 -- call to bind() failed
|
||||
* -3 -- call to listen() failed.
|
||||
* -4 -- call to connect() failed
|
||||
* -5 -- call to getsockname() failed
|
||||
* -6 -- the name of the host could not be resolved
|
||||
* -7 -- illegal or unsupported request
|
||||
* -8 -- no socks access
|
||||
*
|
||||
*
|
||||
* Credit: I couldnt have put this together without the help of BSD4.4-lite
|
||||
* User SupplimenTary Document #20 (Inter-process Communications tutorial)
|
||||
*/
|
||||
int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int protocol, int nonblocking)
|
||||
{
|
||||
int fd = -1;
|
||||
int is_unix = (hostn && *hostn == '/');
|
||||
int sock_type, proto_type;
|
||||
|
||||
#ifndef __OPENNT
|
||||
sock_type = (is_unix) ? AF_UNIX : AF_INET;
|
||||
#else
|
||||
sock_type = AF_INET;
|
||||
#endif
|
||||
|
||||
proto_type = (protocol == PROTOCOL_TCP) ? SOCK_STREAM : SOCK_DGRAM;
|
||||
|
||||
if ((fd = socket(sock_type, proto_type, 0)) < 0)
|
||||
return -1;
|
||||
|
||||
set_socket_options (fd);
|
||||
|
||||
/* Unix domain server */
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
if (is_unix)
|
||||
{
|
||||
struct sockaddr_un name;
|
||||
|
||||
memset(&name, 0, sizeof(struct sockaddr_un));
|
||||
name.sun_family = AF_UNIX;
|
||||
strcpy(name.sun_path, hostn);
|
||||
#ifdef HAVE_SUN_LEN
|
||||
# ifdef SUN_LEN
|
||||
name.sun_len = SUN_LEN(&name);
|
||||
# else
|
||||
name.sun_len = strlen(hostn) + 1;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (is_unix && (service == SERVICE_SERVER))
|
||||
{
|
||||
if (bind(fd, (struct sockaddr *)&name, strlen(name.sun_path) + sizeof(name.sun_family)))
|
||||
return close(fd), -2;
|
||||
if (protocol == PROTOCOL_TCP)
|
||||
if (listen(fd, 4) < 0)
|
||||
return close(fd), -3;
|
||||
}
|
||||
|
||||
/* Unix domain client */
|
||||
else if (service == SERVICE_CLIENT)
|
||||
{
|
||||
alarm(get_int_var(CONNECT_TIMEOUT_VAR));
|
||||
if (connect (fd, (struct sockaddr *)&name, strlen(name.sun_path) + 2) < 0)
|
||||
{
|
||||
alarm(0);
|
||||
return close(fd), -4;
|
||||
}
|
||||
alarm(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
/* Inet domain server */
|
||||
if (!is_unix && (service == SERVICE_SERVER))
|
||||
{
|
||||
int length;
|
||||
#ifdef IP_PORTRANGE
|
||||
int ports;
|
||||
#endif
|
||||
struct sockaddr_foobar name;
|
||||
#ifdef IPV6
|
||||
struct in6_addr any = { IN6ADDR_ANY_INIT };
|
||||
|
||||
memset(&name, 0, sizeof(struct sockaddr_foobar));
|
||||
name.sf_family = AF_INET6;
|
||||
memcpy(&name.sf_addr6, &any, sizeof(struct in6_addr));
|
||||
#else
|
||||
memset(&name, 0, sizeof(struct sockaddr_foobar));
|
||||
name.sf_family = AF_INET;
|
||||
name.sf_addr.s_addr = htonl(INADDR_ANY);
|
||||
#endif
|
||||
|
||||
name.sf_port = htons(*portnum);
|
||||
#ifdef PARANOID
|
||||
name.sf_port += (unsigned short)(rand() & 255);
|
||||
#endif
|
||||
|
||||
#ifdef IP_PORTRANGE
|
||||
if (getenv("EPIC_USE_HIGHPORTS"))
|
||||
{
|
||||
ports = IP_PORTRANGE_HIGH;
|
||||
setsockopt(fd, IPPROTO_IP, IP_PORTRANGE,
|
||||
(char *)&ports, sizeof(ports));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&name, sizeof(name)))
|
||||
return close(fd), -2;
|
||||
|
||||
length = sizeof (name);
|
||||
if (getsockname(fd, (struct sockaddr *)&name, &length))
|
||||
return close(fd), -5;
|
||||
|
||||
*portnum = ntohs(name.sf_port);
|
||||
|
||||
if (protocol == PROTOCOL_TCP)
|
||||
if (listen(fd, 4) < 0)
|
||||
return close(fd), -3;
|
||||
#ifdef NON_BLOCKING_CONNECTS
|
||||
if (nonblocking && set_non_blocking(fd) < 0)
|
||||
return close(fd), -4;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Inet domain client */
|
||||
else if (!is_unix && (service == SERVICE_CLIENT))
|
||||
{
|
||||
struct sockaddr_foobar server;
|
||||
struct hostent *hp;
|
||||
#ifdef WINNT
|
||||
char buf[BIG_BUFFER_SIZE+1];
|
||||
#endif
|
||||
#ifdef IPV6
|
||||
struct addrinfo hints, *res;
|
||||
struct sockaddr_foobar *sf = NULL;
|
||||
#else
|
||||
struct sockaddr_in localaddr;
|
||||
if (LocalHostName)
|
||||
{
|
||||
memset(&localaddr, 0, sizeof(struct sockaddr_in));
|
||||
localaddr.sin_family = AF_INET;
|
||||
localaddr.sin_addr = LocalHostAddr.sf_addr;
|
||||
localaddr.sin_port = 0;
|
||||
if (bind(fd, (struct sockaddr *)&localaddr, sizeof(localaddr)))
|
||||
return close(fd), -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&server, 0, sizeof(struct sockaddr_in));
|
||||
#ifndef WINNT
|
||||
|
||||
#ifdef IPV6
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
if (!getaddrinfo(hostn, NULL, &hints, &res) && res)
|
||||
{
|
||||
sf = (struct sockaddr_foobar*) res->ai_addr;
|
||||
|
||||
close(fd);
|
||||
|
||||
proto_type = (protocol == PROTOCOL_TCP) ? SOCK_STREAM : SOCK_DGRAM;
|
||||
if ((fd = socket(sf->sf_family, proto_type, 0)) < 0)
|
||||
return -1;
|
||||
set_socket_options (fd);
|
||||
|
||||
if ((server.sf_family = sf->sf_family) == AF_INET)
|
||||
memcpy(&server.sf_addr, &sf->sf_addr, sizeof(struct in_addr));
|
||||
else
|
||||
memcpy(&server.sf_addr6, &sf->sf_addr6, sizeof(struct in6_addr));
|
||||
server.sf_port = htons(*portnum);
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = res->ai_family;
|
||||
freeaddrinfo(res);
|
||||
|
||||
if (LocalHostName && !getaddrinfo(LocalHostName, NULL, &hints, &res) && res)
|
||||
{
|
||||
if (bind(fd, (struct sockaddr *) res->ai_addr, sizeof(struct sockaddr_foobar)))
|
||||
return close(fd), -2;
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
}
|
||||
else
|
||||
return close(fd), -6;
|
||||
|
||||
#else
|
||||
if (isdigit((unsigned char)hostn[strlen(hostn)-1]))
|
||||
inet_aton(hostn, (struct in_addr *)&server.sf_addr);
|
||||
else
|
||||
{
|
||||
if (!(hp = gethostbyname(hostn)))
|
||||
return close(fd), -6;
|
||||
memcpy(&server.sf_addr, hp->h_addr, hp->h_length);
|
||||
}
|
||||
server.sf_family = AF_INET;
|
||||
server.sf_port = htons(*portnum);
|
||||
#endif /* IPV6 */
|
||||
|
||||
#else
|
||||
/* for some odd reason resolv() fails on NT... */
|
||||
/* server = (*(struct sockaddr_in *) hostn);*/
|
||||
if (!hostn)
|
||||
{
|
||||
gethostname(buf, sizeof(buf));
|
||||
hostn = buf;
|
||||
}
|
||||
if ((server.sf_addr.s_addr = inet_addr(hostn)) == -1)
|
||||
{
|
||||
if ((hp = gethostbyname(hostn)) != NULL)
|
||||
{
|
||||
memset(&server, 0, sizeof(server));
|
||||
bcopy(hp->h_addr, (char *) &server.sf_addr,
|
||||
hp->h_length);
|
||||
server.sf_family = hp->h_addrtype;
|
||||
}
|
||||
else
|
||||
return (-2);
|
||||
}
|
||||
else
|
||||
server.sf_family = AF_INET;
|
||||
server.sf_port = (unsigned short) htons(*portnum);
|
||||
#endif /* WINNT */
|
||||
|
||||
#ifdef NON_BLOCKING_CONNECTS
|
||||
if (!use_socks && nonblocking && set_non_blocking(fd) < 0)
|
||||
return close(fd), -4;
|
||||
#endif
|
||||
|
||||
#if !defined(WTERM_C) && !defined(STERM_C) && !defined(IPV6)
|
||||
|
||||
if (use_socks && get_string_var(SOCKS_HOST_VAR))
|
||||
{
|
||||
|
||||
fd = handle_socks(fd, *((struct sockaddr_in*) &server), get_string_var(SOCKS_HOST_VAR), get_int_var(SOCKS_PORT_VAR));
|
||||
if (fd == -1)
|
||||
return -4;
|
||||
else
|
||||
return fd;
|
||||
}
|
||||
#endif
|
||||
alarm(get_int_var(CONNECT_TIMEOUT_VAR));
|
||||
if (connect (fd, (struct sockaddr *)&server, sizeof(server)) < 0)
|
||||
{
|
||||
alarm(0);
|
||||
#ifdef NON_BLOCKING_CONNECTS
|
||||
if (!nonblocking)
|
||||
#endif
|
||||
return close(fd), -4;
|
||||
}
|
||||
alarm(0);
|
||||
}
|
||||
|
||||
/* error */
|
||||
else
|
||||
return close(fd), -7;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int lame_resolv (const char *hostname, struct sockaddr_foobar *buffer)
|
||||
{
|
||||
#ifdef IPV6
|
||||
struct addrinfo *res;
|
||||
if (getaddrinfo(hostname, NULL, NULL, &res) && res)
|
||||
return -1;
|
||||
|
||||
memmove(buffer, res->ai_addr, res->ai_addrlen);
|
||||
return 0;
|
||||
#else
|
||||
struct hostent *hp;
|
||||
|
||||
if (!(hp = gethostbyname(hostname)))
|
||||
return -1;
|
||||
|
||||
buffer->sf_family = AF_INET;
|
||||
memmove(&buffer->sf_addr, hp->h_addr, hp->h_length);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef IPV6
|
||||
|
||||
extern struct sockaddr_foobar *BX_lookup_host (const char *host)
|
||||
{
|
||||
static struct sockaddr_foobar sf;
|
||||
struct addrinfo *res;
|
||||
|
||||
if (!getaddrinfo(host, NULL, NULL, &res) && res)
|
||||
{
|
||||
memcpy(&sf, res->ai_addr, sizeof(struct sockaddr_foobar));
|
||||
freeaddrinfo(res);
|
||||
|
||||
return &sf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern char *BX_host_to_ip (const char *host)
|
||||
{
|
||||
struct addrinfo *res;
|
||||
struct sockaddr_foobar *sf;
|
||||
static char ip[128];
|
||||
|
||||
if (!getaddrinfo(host, NULL, NULL, &res) && res)
|
||||
{
|
||||
sf = (struct sockaddr_foobar*) res->ai_addr;
|
||||
inet_ntop(sf->sf_family, (sf->sf_family == AF_INET) ?
|
||||
(void*) &sf->sf_addr : (void*) &sf->sf_addr6, ip, 128);
|
||||
freeaddrinfo(res);
|
||||
|
||||
return ip;
|
||||
}
|
||||
else
|
||||
return empty_string;
|
||||
}
|
||||
|
||||
extern char *BX_ip_to_host (const char *ip)
|
||||
{
|
||||
static char host[128];
|
||||
struct sockaddr_foobar sf;
|
||||
|
||||
if (inet_pton(AF_INET6, ip, &sf.sf_addr6))
|
||||
sf.sf_family = AF_INET6;
|
||||
else
|
||||
{
|
||||
inet_pton(AF_INET, ip, &sf.sf_addr);
|
||||
sf.sf_family = AF_INET;
|
||||
}
|
||||
|
||||
if (getnameinfo((struct sockaddr*)&sf, sizeof(struct sockaddr_foobar), host, 128, NULL, 0, 0))
|
||||
strncpy(host, ip, 128);
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
extern char *BX_one_to_another (const char *what)
|
||||
{
|
||||
if (isdigit(what[strlen(what)-1]) || strchr(what, ':'))
|
||||
return ip_to_host (what);
|
||||
else
|
||||
return host_to_ip (what);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
extern struct sockaddr_foobar *BX_lookup_host (const char *host)
|
||||
{
|
||||
struct hostent *he;
|
||||
static struct sockaddr_foobar sf;
|
||||
|
||||
alarm(1);
|
||||
he = gethostbyname(host);
|
||||
alarm(0);
|
||||
if (he)
|
||||
{
|
||||
sf.sf_family = AF_INET;
|
||||
memcpy(&sf.sf_addr, he->h_addr, sizeof(struct in_addr));
|
||||
return &sf;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern char *BX_host_to_ip (const char *host)
|
||||
{
|
||||
struct hostent *hep = gethostbyname(host);
|
||||
static char ip[30];
|
||||
|
||||
return (hep ? sprintf(ip,"%u.%u.%u.%u", hep->h_addr[0] & 0xff,
|
||||
hep->h_addr[1] & 0xff,
|
||||
hep->h_addr[2] & 0xff,
|
||||
hep->h_addr[3] & 0xff),
|
||||
ip : empty_string);
|
||||
}
|
||||
|
||||
extern char *BX_ip_to_host (const char *ip)
|
||||
{
|
||||
struct in_addr ia;
|
||||
struct hostent *he;
|
||||
static char host[101];
|
||||
|
||||
ia.s_addr = inet_addr(ip);
|
||||
he = gethostbyaddr((char*) &ia, sizeof(struct in_addr), AF_INET);
|
||||
|
||||
return (he ? strncpy(host, he->h_name, 100): empty_string);
|
||||
}
|
||||
|
||||
extern char *BX_one_to_another (const char *what)
|
||||
{
|
||||
|
||||
if (!isdigit((unsigned char)what[strlen(what)-1]))
|
||||
return host_to_ip (what);
|
||||
else
|
||||
return ip_to_host (what);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* It is possible for a race condition to exist; such that select()
|
||||
* indicates that a listen()ing socket is able to recieve a new connection
|
||||
* and that a later accept() call will still block because the connection
|
||||
* has been closed in the interim. This wrapper for accept() attempts to
|
||||
* defeat this by making the accept() call nonblocking.
|
||||
*/
|
||||
int my_accept (int s, struct sockaddr *addr, int *addrlen)
|
||||
{
|
||||
int retval;
|
||||
set_non_blocking(s);
|
||||
retval = accept(s, addr, addrlen);
|
||||
set_blocking(s);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int BX_set_non_blocking(int fd)
|
||||
{
|
||||
#ifdef NON_BLOCKING_CONNECTS
|
||||
int res;
|
||||
|
||||
#if defined(NBLOCK_POSIX)
|
||||
int nonb = 0;
|
||||
nonb |= O_NONBLOCK;
|
||||
#elif defined(NBLOCK_BSD)
|
||||
int nonb = 0;
|
||||
nonb |= O_NDELAY;
|
||||
#elif defined(NBLOCK_SYSV)
|
||||
res = 1;
|
||||
|
||||
if (ioctl (fd, FIONBIO, &res) < 0)
|
||||
return -1;
|
||||
#else
|
||||
#error no idea how to set an fd to non-blocking
|
||||
#endif
|
||||
#if (defined(NBLOCK_POSIX) || defined(NBLOCK_BSD)) && !defined(NBLOCK_SYSV)
|
||||
if ((res = fcntl(fd, F_GETFL, 0)) == -1)
|
||||
return -1;
|
||||
else if (fcntl(fd, F_SETFL, res | nonb) == -1)
|
||||
return -1;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BX_set_blocking(int fd)
|
||||
{
|
||||
#ifdef NON_BLOCKING_CONNECTS
|
||||
int res;
|
||||
|
||||
#if defined(NBLOCK_POSIX)
|
||||
int nonb = 0;
|
||||
nonb |= O_NONBLOCK;
|
||||
#elif defined(NBLOCK_BSD)
|
||||
int nonb = 0;
|
||||
nonb |= O_NDELAY;
|
||||
#elif defined(NBLOCK_SYSV)
|
||||
res = 0;
|
||||
|
||||
if (ioctl (fd, FIONBIO, &res) < 0)
|
||||
return -1;
|
||||
#else
|
||||
#error no idea how to return an fd blocking
|
||||
#endif
|
||||
#if (defined(NBLOCK_POSIX) || defined(NBLOCK_BSD)) && !defined(NBLOCK_SYSV)
|
||||
if ((res = fcntl(fd, F_GETFL, 0)) == -1)
|
||||
return -1;
|
||||
else if (fcntl(fd, F_SETFL, res &~ nonb) == -1)
|
||||
return -1;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
542
source/newio.c
Normal file
542
source/newio.c
Normal file
@@ -0,0 +1,542 @@
|
||||
/*
|
||||
* newio.c: This is some handy stuff to deal with file descriptors in a way
|
||||
* much like stdio's FILE pointers
|
||||
*
|
||||
* IMPORTANT NOTE: If you use the routines here-in, you shouldn't switch to
|
||||
* using normal reads() on the descriptors cause that will cause bad things
|
||||
* to happen. If using any of these routines, use them all
|
||||
*
|
||||
* Copyright 1990 Michael Sandrof
|
||||
* Copyright 1995 Matthew Green
|
||||
* Copyright 1997 EPIC Software Labs
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: newio.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(newio_c)
|
||||
#include "ircaux.h"
|
||||
#include "output.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef HAVE_SYS_FILIO_H
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#include "winbitchx.h"
|
||||
#endif
|
||||
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) && !defined(__EMX__)
|
||||
# define IO_ARRAYLEN sysconf(_SC_OPEN_MAX)
|
||||
#else
|
||||
# ifdef FD_SETSIZE
|
||||
# define IO_ARRAYLEN FD_SETSIZE
|
||||
# else
|
||||
# define IO_ARRAYLEN NFDBITS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNU__
|
||||
#undef IO_ARRAYLEN
|
||||
#define IO_ARRAYLEN 65535
|
||||
#endif
|
||||
|
||||
#define MAX_SEGMENTS 16
|
||||
|
||||
typedef struct myio_struct
|
||||
{
|
||||
char *buffer;
|
||||
size_t buffer_size;
|
||||
unsigned read_pos,
|
||||
write_pos;
|
||||
int segments;
|
||||
int error;
|
||||
} MyIO;
|
||||
|
||||
static MyIO **io_rec = NULL;
|
||||
int dgets_errno = 0;
|
||||
|
||||
/*
|
||||
* Get_pending_bytes: What do you think it does?
|
||||
*/
|
||||
size_t get_pending_bytes (int fd)
|
||||
{
|
||||
if (fd >= 0 && io_rec[fd] && io_rec[fd]->buffer)
|
||||
return strlen(io_rec[fd]->buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init_io (void)
|
||||
{
|
||||
static int first = 1;
|
||||
|
||||
if (first)
|
||||
{
|
||||
int c, max_fd = IO_ARRAYLEN;
|
||||
|
||||
io_rec = (MyIO **)new_malloc(sizeof(MyIO *) * max_fd);
|
||||
for (c = 0; c < max_fd; c++)
|
||||
io_rec[c] = (MyIO *) 0;
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
void SSL_show_errors(void)
|
||||
{
|
||||
char buf[1000];
|
||||
int sslerr;
|
||||
|
||||
while((sslerr = ERR_get_error()))
|
||||
{
|
||||
ERR_error_string(sslerr, buf);
|
||||
say("%s", buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* All new dgets -- no more trap doors!
|
||||
*
|
||||
* There are at least four ways to look at this function.
|
||||
* The most important variable is 'buffer', which determines if
|
||||
* we force line buffering. If it is on, then we will sit on any
|
||||
* incomplete lines until they get a newline. This is the default
|
||||
* behavior for server connections, because they *must* be line
|
||||
* delineated. However, when are getting input from an untrusted
|
||||
* source (eg, dcc chat, /exec'd process), we cannot assume that every
|
||||
* line will be newline delinated. So in those cases, 'buffer' is 0,
|
||||
* and we force a flush on whatever we can slurp, without waiting for
|
||||
* a newline.
|
||||
*
|
||||
* Return values:
|
||||
*
|
||||
* -1 -- something really died. Either a read error occured, the
|
||||
* fildesc wasnt really ready for reading, or the input buffer
|
||||
* for the filedesc filled up (8192 bytes)
|
||||
* 0 -- If the data read in from the file descriptor did not form a
|
||||
* complete line, then zero is always returned. This should be
|
||||
* considered a stopping condition. Do not call dgets() again
|
||||
* after it returns 0, because unless more data is avaiable on
|
||||
* the fd, it will return -1, which you would misinterpret as an
|
||||
* error condition.
|
||||
* If "buffer" is 0, then whatever we have available will be
|
||||
* returned in "str".
|
||||
* If "buffer" is not 0, then we will retain whatever we have
|
||||
* available, waiting for the newline to occur perhaps next time.
|
||||
* >0 -- If a full, newline terminated line was available, the length
|
||||
* of the line is returned.
|
||||
*/
|
||||
int BX_dgets (char *str, int des, int buffer, int buffersize, void *ssl_fd)
|
||||
{
|
||||
int cnt = 0, c;
|
||||
MyIO *ioe;
|
||||
int nbytes;
|
||||
|
||||
if (!io_rec)
|
||||
init_io();
|
||||
|
||||
ioe = io_rec[des];
|
||||
|
||||
if (ioe == NULL)
|
||||
{
|
||||
ioe = io_rec[des] = (MyIO *)new_malloc(sizeof(MyIO));
|
||||
ioe->buffer_size = IO_BUFFER_SIZE;
|
||||
ioe->buffer = (char *)new_malloc(ioe->buffer_size + 2);
|
||||
ioe->read_pos = ioe->write_pos = 0;
|
||||
}
|
||||
|
||||
if (ioe->read_pos == ioe->write_pos)
|
||||
{
|
||||
ioe->read_pos = ioe->write_pos = 0;
|
||||
ioe->buffer[0] = 0;
|
||||
ioe->segments = 0;
|
||||
}
|
||||
|
||||
if (!strchr(ioe->buffer + ioe->read_pos, '\n'))
|
||||
{
|
||||
if (ioe->read_pos)
|
||||
{
|
||||
ov_strcpy(ioe->buffer, ioe->buffer + ioe->read_pos);
|
||||
ioe->read_pos = 0;
|
||||
ioe->write_pos = strlen(ioe->buffer);
|
||||
ioe->segments = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dont try to read into a full buffer.
|
||||
*/
|
||||
if (ioe->write_pos >= ioe->buffer_size)
|
||||
{
|
||||
yell("***XXX*** Buffer for des [%d] is filled!", des);
|
||||
dgets_errno = ENOMEM; /* Cough */
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Check to see if any bytes are ready. If this fails,
|
||||
* then its almost always due to the filedesc being
|
||||
* bogus. Thats a fatal error.
|
||||
*/
|
||||
if (ioctl(des, FIONREAD, &nbytes) == -1)
|
||||
{
|
||||
*str = 0;
|
||||
dgets_errno = errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a quasi-EOF condition. If we get to this
|
||||
* point, then new_select() indicated that this fd is ready.
|
||||
* The fd is ready if either:
|
||||
* 1) A newline is in the buffer
|
||||
* 2) select(2) returned ready for the fd.
|
||||
*
|
||||
* If 1) is true, then write_pos will not be zero. So we can
|
||||
* use that as a cheap way to check for #1. If #1 is false,
|
||||
* then #2 must have been true, and if nbytes is 0, then
|
||||
* that indicates an EOF condition.
|
||||
*/
|
||||
else if (!nbytes && ioe->write_pos == 0)
|
||||
{
|
||||
*str = 0;
|
||||
dgets_errno = errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
else if (nbytes)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
int rc = 0;
|
||||
#endif
|
||||
|
||||
if (nbytes >= IO_BUFFER_SIZE)
|
||||
nbytes = IO_BUFFER_SIZE-1;
|
||||
#ifdef HAVE_SSL
|
||||
if(ssl_fd)
|
||||
{
|
||||
c = SSL_read((SSL *)ssl_fd, ioe->buffer + ioe->write_pos,
|
||||
ioe->buffer_size - ioe->write_pos);
|
||||
|
||||
if(c == -1 && (rc = SSL_get_error((SSL *)ssl_fd, c)) == SSL_ERROR_WANT_READ)
|
||||
{
|
||||
/* If SSL needs more data, then we need to call SSL_read again,
|
||||
* so we'll return with 0 bytes read, and hope we get called
|
||||
* again. :)
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
c = read(des, ioe->buffer + ioe->write_pos,
|
||||
ioe->buffer_size - ioe->write_pos);
|
||||
|
||||
if (x_debug & DEBUG_INBOUND)
|
||||
yell("FD [%d], should [%d] did [%d]",
|
||||
des, nbytes, c);
|
||||
|
||||
if (c <= 0)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(ssl_fd)
|
||||
{
|
||||
say("SSL_read() failed, SSL error %d", rc);
|
||||
SSL_show_errors();
|
||||
}
|
||||
#endif
|
||||
*str = 0;
|
||||
dgets_errno = (c == 0) ? -1 : errno;
|
||||
return -1;
|
||||
}
|
||||
ioe->buffer[ioe->write_pos + c] = 0;
|
||||
ioe->write_pos += c;
|
||||
ioe->segments++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* At this point nbytes is 0, and it doesnt
|
||||
* appear the socket is at EOF or ready to read.
|
||||
* Very little to do at this point but force the
|
||||
* issue and figure out what the heck went wrong.
|
||||
*/
|
||||
struct timeval t = { 0, 0 };
|
||||
fd_set testing;
|
||||
|
||||
FD_ZERO(&testing);
|
||||
FD_SET(des, &testing);
|
||||
switch (select(des + 1, &testing, NULL, NULL, &t))
|
||||
{
|
||||
case -1:
|
||||
{
|
||||
yell("Aberrant condition for des [%d], closing down the connection out of desperation.", des);
|
||||
*str = 0;
|
||||
dgets_errno = errno;
|
||||
return -1;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
yell("des [%d] passed to dgets(), but it isnt ready.", des);
|
||||
if (ioe->write_pos == 0)
|
||||
{
|
||||
yell("X*X*X*X*X*X*X*X*X ABANDON SHIP! X*X*X*X*X*X*X*X*X*X");
|
||||
ircpanic("write_pos is zero when it cant be.");
|
||||
}
|
||||
else
|
||||
{
|
||||
yell("But something is buffered. Flushing it to see if that helps.");
|
||||
ioe->buffer[ioe->write_pos++] = '\n';
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
errno = ECONNABORTED;
|
||||
*str = 0;
|
||||
dgets_errno = errno;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dgets_errno = 0;
|
||||
|
||||
/*
|
||||
* If the caller wants us to force line buffering, and if there
|
||||
* is no complete line, just stop right here.
|
||||
*/
|
||||
if (buffer && !strchr(ioe->buffer + ioe->read_pos, '\n'))
|
||||
{
|
||||
if (ioe->segments > MAX_SEGMENTS)
|
||||
{
|
||||
yell("*** Too many read()s on des [%d] without a newline!", des);
|
||||
*str = 0;
|
||||
dgets_errno = ECONNABORTED;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Slurp up the data that is available into 'str'.
|
||||
*/
|
||||
while (ioe->read_pos < ioe->write_pos)
|
||||
{
|
||||
if (((str[cnt] = ioe->buffer[ioe->read_pos++])) == '\n')
|
||||
break;
|
||||
cnt++;
|
||||
if (cnt >= buffersize-1)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate it
|
||||
*/
|
||||
str[cnt + 1] = 0;
|
||||
|
||||
/*
|
||||
* If we end in a newline, then all is well.
|
||||
* Otherwise, we're unbuffered, tell the caller.
|
||||
* The caller then would need to do a strlen() to get
|
||||
* the amount of data.
|
||||
*/
|
||||
if (str[cnt] == '\n')
|
||||
return cnt;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int global_max_fd = -1;
|
||||
|
||||
/*
|
||||
* new_select: works just like select(), execpt I trimmed out the excess
|
||||
* parameters I didn't need.
|
||||
*/
|
||||
int new_select (fd_set *rd, fd_set *wd, struct timeval *timeout)
|
||||
{
|
||||
int i,
|
||||
set = 0;
|
||||
fd_set new;
|
||||
struct timeval thetimeout;
|
||||
struct timeval *newtimeout = &thetimeout;
|
||||
|
||||
if (timeout)
|
||||
thetimeout = *timeout;
|
||||
else
|
||||
newtimeout = NULL;
|
||||
|
||||
if (!io_rec)
|
||||
ircpanic("new select called before io_rec init");
|
||||
if (newtimeout && newtimeout->tv_usec < 0)
|
||||
ircpanic("new select with < -1");
|
||||
|
||||
FD_ZERO(&new);
|
||||
for (i = 0; i <= global_max_fd; i++)
|
||||
{
|
||||
if (io_rec[i])
|
||||
{
|
||||
if ((io_rec[i]->read_pos < io_rec[i]->write_pos) &&
|
||||
strchr(io_rec[i]->buffer + io_rec[i]->read_pos, '\n'))
|
||||
{
|
||||
FD_SET(i, &new);
|
||||
set++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (set)
|
||||
{
|
||||
*rd = new;
|
||||
return set;
|
||||
}
|
||||
#ifdef WIN32
|
||||
memset(&thetimeout, 0, sizeof(struct timeval));
|
||||
thetimeout.tv_usec = 500;
|
||||
i = select(global_max_fd + 1, rd, wd, NULL, &thetimeout);
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
#else
|
||||
return (select(global_max_fd + 1, rd, wd, NULL, newtimeout));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a filedesc for readable events
|
||||
* Set up its input buffer
|
||||
*/
|
||||
int BX_new_open (int des)
|
||||
{
|
||||
if (des < 0)
|
||||
return des; /* Invalid */
|
||||
|
||||
if (!io_rec)
|
||||
init_io();
|
||||
|
||||
if (!FD_ISSET(des, &readables))
|
||||
FD_SET(des, &readables);
|
||||
if (des > global_max_fd)
|
||||
global_max_fd = des;
|
||||
|
||||
return des;
|
||||
}
|
||||
|
||||
int new_open_write (int des)
|
||||
{
|
||||
if (des < 0)
|
||||
return des; /* Invalid */
|
||||
|
||||
if (!io_rec)
|
||||
init_io();
|
||||
|
||||
if (!FD_ISSET(des, &writables))
|
||||
FD_SET(des, &writables);
|
||||
#if 0
|
||||
if (des > global_max_fd)
|
||||
global_max_fd = des;
|
||||
#endif
|
||||
return des;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unregister a filedesc for readable events
|
||||
* and close it down and free its input buffer
|
||||
*/
|
||||
int BX_new_close (int des)
|
||||
{
|
||||
if (des < 0)
|
||||
return -1;
|
||||
|
||||
if (FD_ISSET(des, &readables))
|
||||
FD_CLR(des, &readables);
|
||||
|
||||
if (io_rec && io_rec[des])
|
||||
{
|
||||
new_free(&(io_rec[des]->buffer));
|
||||
new_free((char **)&(io_rec[des]));
|
||||
}
|
||||
close(des);
|
||||
|
||||
/*
|
||||
* If we're closing the highest fd in use, then we
|
||||
* want to adjust global_max_fd downward to the next highest fd.
|
||||
*/
|
||||
if (des == global_max_fd)
|
||||
{
|
||||
do
|
||||
des--;
|
||||
while (des >= 0 && !FD_ISSET(des, &readables));
|
||||
|
||||
global_max_fd = des;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int new_close_write (int des)
|
||||
{
|
||||
if (des < 0)
|
||||
return -1;
|
||||
|
||||
if (FD_ISSET(des, &writables))
|
||||
FD_CLR(des, &writables);
|
||||
|
||||
if (io_rec && io_rec[des])
|
||||
{
|
||||
new_free(&(io_rec[des]->buffer));
|
||||
new_free((char **)&(io_rec[des]));
|
||||
}
|
||||
close(des);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* If we're closing the highest fd in use, then we
|
||||
* want to adjust global_max_fd downward to the next highest fd.
|
||||
*/
|
||||
if (des == global_max_fd)
|
||||
{
|
||||
do
|
||||
des--;
|
||||
while (!FD_ISSET(des, &writables));
|
||||
|
||||
global_max_fd = des;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set's socket options */
|
||||
void set_socket_options (int s)
|
||||
{
|
||||
int opt = 1;
|
||||
#ifndef NO_STRUCT_LINGER
|
||||
struct linger lin;
|
||||
|
||||
lin.l_onoff = lin.l_linger = 0;
|
||||
setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&lin, sizeof(struct linger));
|
||||
#endif
|
||||
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
|
||||
opt = 1;
|
||||
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, sizeof(opt));
|
||||
|
||||
#if notyet
|
||||
/* This is waiting for nonblock-aware code */
|
||||
info = fcntl(fd, F_GETFL, 0);
|
||||
info |= O_NONBLOCK;
|
||||
fcntl(fd, F_SETFL, info);
|
||||
#endif
|
||||
}
|
||||
|
||||
1232
source/notice.c
Normal file
1232
source/notice.c
Normal file
File diff suppressed because it is too large
Load Diff
969
source/notify.c
Normal file
969
source/notify.c
Normal file
@@ -0,0 +1,969 @@
|
||||
/*
|
||||
* notify.c: a few handy routines to notify you when people enter and leave irc
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
* Copyright(c) 1990
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*
|
||||
* Modified Colten Edwards 96
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: notify.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(notify_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "list.h"
|
||||
#include "notify.h"
|
||||
#include "ircaux.h"
|
||||
#include "who.h"
|
||||
#include "hook.h"
|
||||
#include "server.h"
|
||||
#include "output.h"
|
||||
#include "vars.h"
|
||||
#include "timer.h"
|
||||
#include "misc.h"
|
||||
#include "status.h"
|
||||
#include "userlist.h"
|
||||
#include "hash2.h"
|
||||
#include "cset.h"
|
||||
#include "server.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
extern Server *server_list;
|
||||
|
||||
#define NOTIFY_LIST(s) (&(server_list[s].notify_list))
|
||||
#define NOTIFY_MAX(s) (NOTIFY_LIST(s)->max)
|
||||
#define NOTIFY_ITEM(s, i) (NOTIFY_LIST(s)->list[i])
|
||||
|
||||
#define WATCH_LIST(s) (&(server_list[s].watch_list))
|
||||
#define WATCH_MAX(s) (WATCH_LIST(s)->max)
|
||||
#define WATCH_ITEM(s, i) (WATCH_LIST(s)->list[i])
|
||||
|
||||
void batch_notify_userhost (char *);
|
||||
void dispatch_notify_userhosts (void);
|
||||
void notify_userhost_dispatch (UserhostItem *, char *, char *);
|
||||
void notify_userhost_reply (char *, char *);
|
||||
|
||||
void rebuild_notify_ison (int server)
|
||||
{
|
||||
char *stuff;
|
||||
int i;
|
||||
if (from_server == -1)
|
||||
return;
|
||||
stuff = NOTIFY_LIST(from_server)->ison;
|
||||
|
||||
if (NOTIFY_LIST(from_server)->ison)
|
||||
NOTIFY_LIST(from_server)->ison[0] = 0;
|
||||
|
||||
for (i = 0; i < NOTIFY_MAX(from_server); i++)
|
||||
{
|
||||
m_s3cat(&(NOTIFY_LIST(from_server)->ison),
|
||||
space, NOTIFY_ITEM(from_server, i)->nick);
|
||||
}
|
||||
}
|
||||
|
||||
void rebuild_all_ison (void)
|
||||
{
|
||||
int i;
|
||||
int ofs = from_server;
|
||||
for (i = 0; i < server_list_size(); i++)
|
||||
{
|
||||
from_server = i;
|
||||
rebuild_notify_ison(i);
|
||||
}
|
||||
from_server = ofs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ison_notify(char *AskedFor, char *AreOn)
|
||||
{
|
||||
char *NextAsked;
|
||||
char *NextGot;
|
||||
|
||||
NextGot = next_arg(AreOn, &AreOn);
|
||||
while ((NextAsked = next_arg(AskedFor, &AskedFor)) != NULL)
|
||||
{
|
||||
if (NextGot && !my_stricmp(NextAsked, NextGot))
|
||||
{
|
||||
notify_mark(NextAsked, NULL, 1, 1);
|
||||
NextGot = next_arg(AreOn, &AreOn);
|
||||
}
|
||||
else
|
||||
notify_mark(NextAsked, NULL, 0, 1);
|
||||
}
|
||||
dispatch_notify_userhosts();
|
||||
}
|
||||
|
||||
|
||||
void add_to_notify_queue(char *buffer)
|
||||
{
|
||||
char *lame = LOCAL_COPY(buffer);
|
||||
isonbase(lame, ison_notify);
|
||||
}
|
||||
|
||||
void notify_count(int server, int *on, int *off)
|
||||
{
|
||||
NotifyItem *tmp;
|
||||
int i;
|
||||
if (server <= -1)
|
||||
return;
|
||||
|
||||
if (on) *on = 0;
|
||||
if (off) *off = 0;
|
||||
for (i = 0; i < NOTIFY_MAX(server); i++)
|
||||
{
|
||||
tmp = NOTIFY_ITEM(server, i);
|
||||
if (tmp->flag)
|
||||
{
|
||||
if (on) (*on)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (off) (*off)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Rewritten, -lynx */
|
||||
void show_notify_list(int all)
|
||||
{
|
||||
int count = 0;
|
||||
int i;
|
||||
char lastseen[20];
|
||||
char period[20];
|
||||
char timeson[20];
|
||||
NotifyItem *tmp;
|
||||
|
||||
if (from_server == -1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < NOTIFY_MAX(from_server); i++)
|
||||
{
|
||||
tmp = NOTIFY_ITEM(from_server, i);
|
||||
if (tmp->flag)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
if (do_hook(NOTIFY_HEADER_LIST, "%s", "Online users"))
|
||||
{
|
||||
put_it("%s", convert_output_format("$G Online Users", NULL, NULL));
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_ON_FSET), "%s %s %s %s %s", "Nick", "UserHost", "Times", "Period", "Last seen"));
|
||||
}
|
||||
}
|
||||
strcpy(period, ltoa(tmp->period));
|
||||
strcpy(timeson, ltoa(tmp->times));
|
||||
strcpy(lastseen, ltoa(now - tmp->added));
|
||||
if (do_hook(NOTIFY_LIST, "%s %s %d %s %s %s", tmp->nick, tmp->host?tmp->host:"unknown@unknown", tmp->flag, timeson, period, lastseen))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_ON_FSET), "%s %s %s %s %s", tmp->nick, tmp->host?tmp->host:tmp->looking, timeson, lastseen, "now" ));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
count = 0;
|
||||
for (i = 0; i < NOTIFY_MAX(from_server); i++)
|
||||
{
|
||||
tmp = NOTIFY_ITEM(from_server, i);
|
||||
if ((all && !tmp->flag) || (tmp->times && !tmp->flag))
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
if (do_hook(NOTIFY_HEADER_LIST, "%s", "Offline users"))
|
||||
{
|
||||
put_it("%s", convert_output_format("$G Offline Users", NULL, NULL));
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_OFF_FSET), "%s %s %s %s %s", "Nick", "UserHost", "Times", "Period", "Last seen"));
|
||||
}
|
||||
}
|
||||
strcpy(period, ltoa(tmp->period));
|
||||
strcpy(timeson, ltoa(tmp->times));
|
||||
strcpy(lastseen, ltoa(now - tmp->lastseen));
|
||||
if (do_hook(NOTIFY_LIST, "%s %s %d %s %s %s", tmp->nick, tmp->host?tmp->host:"unknown@unknown", tmp->flag, timeson, period, lastseen))
|
||||
{
|
||||
if (!tmp->times)
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_OFF_FSET), "%s %s %s %s %s", tmp->nick, tmp->host?tmp->host:tmp->looking, "never", "none", "n/a"));
|
||||
else
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_OFF_FSET), "%s %s %s %s %s", tmp->nick, tmp->host?tmp->host:tmp->looking, timeson, period, lastseen));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* notify: the NOTIFY command. Does the whole ball-o-wax */
|
||||
BUILT_IN_COMMAND(notify)
|
||||
{
|
||||
char *nick,
|
||||
*list = NULL,
|
||||
*ptr;
|
||||
int no_nicks = 1;
|
||||
int do_ison = 0;
|
||||
int servnum = from_server;
|
||||
int shown = 0;
|
||||
NotifyItem *new_n;
|
||||
|
||||
malloc_strcpy(&list, empty_string);
|
||||
while ((nick = next_arg(args, &args)))
|
||||
{
|
||||
for (no_nicks = 0; nick; nick = ptr)
|
||||
{
|
||||
char *host = NULL;
|
||||
shown = 0;
|
||||
if ((ptr = strchr(nick, ',')) != NULL)
|
||||
*ptr++ = 0;
|
||||
if ((host = strchr(nick, '!')))
|
||||
*host++ = 0;
|
||||
else
|
||||
host = "*@*";
|
||||
|
||||
if (*nick == '-')
|
||||
{
|
||||
nick++;
|
||||
|
||||
if (*nick)
|
||||
{
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
if ((new_n = (NotifyItem *)remove_from_array(
|
||||
(Array *)NOTIFY_LIST(servnum), nick)))
|
||||
{
|
||||
new_free(&new_n->nick);
|
||||
new_free(&new_n->host);
|
||||
new_free(&new_n->looking);
|
||||
new_free((char **)&new_n);
|
||||
|
||||
if (!shown)
|
||||
{
|
||||
bitchsay("%s!%s removed from notification list", nick, host);
|
||||
shown = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!shown)
|
||||
{
|
||||
bitchsay("%s!%s is not on the notification list", nick, host);
|
||||
shown = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
while ((new_n = (NotifyItem *)array_pop(
|
||||
(Array *)NOTIFY_LIST(servnum), 0)))
|
||||
{
|
||||
new_free(&new_n->nick);
|
||||
new_free(&new_n->host);
|
||||
new_free(&new_n->looking);
|
||||
new_free((char **)&new_n);
|
||||
}
|
||||
}
|
||||
bitchsay("Notify list cleared");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* compatibility */
|
||||
if (*nick == '+')
|
||||
nick++;
|
||||
|
||||
if (*nick)
|
||||
{
|
||||
int added = 0;
|
||||
if (strchr(nick, '*'))
|
||||
bitchsay("Wildcards not allowed in NOTIFY nicknames!");
|
||||
else
|
||||
{
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
|
||||
if ((new_n = (NotifyItem *)array_lookup(
|
||||
(Array *)NOTIFY_LIST(servnum), nick, 0, 0)))
|
||||
{
|
||||
malloc_strcpy(&new_n->looking, host);
|
||||
new_n->flag = 0;
|
||||
continue; /* Already there! */
|
||||
}
|
||||
|
||||
new_n = (NotifyItem *)new_malloc(sizeof(NotifyItem));
|
||||
new_n->nick = m_strdup(nick);
|
||||
new_n->looking = m_strdup(host);
|
||||
new_n->host = NULL;
|
||||
new_n->flag = 0;
|
||||
add_to_array((Array *)NOTIFY_LIST(servnum),
|
||||
(Array_item *)new_n);
|
||||
added = 1;
|
||||
}
|
||||
if (added)
|
||||
{
|
||||
m_s3cat(&list, space, new_n->nick);
|
||||
do_ison = 1;
|
||||
}
|
||||
bitchsay("%s!%s added to the notification list", nick, host);
|
||||
}
|
||||
} else
|
||||
show_notify_list(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_ison && get_int_var(NOTIFY_VAR))
|
||||
{
|
||||
int ofs = from_server;
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
from_server = servnum;
|
||||
if (is_server_connected(from_server) && list && *list)
|
||||
add_to_notify_queue(list);
|
||||
}
|
||||
from_server = ofs;
|
||||
}
|
||||
|
||||
new_free(&list);
|
||||
rebuild_all_ison();
|
||||
if (no_nicks)
|
||||
show_notify_list(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* do_notify: This simply goes through the notify list, sending out a WHOIS
|
||||
* for each person on it. This uses the fancy whois stuff in whois.c to
|
||||
* figure things out.
|
||||
*/
|
||||
void do_notify(void)
|
||||
{
|
||||
int old_from_server = from_server;
|
||||
int servnum;
|
||||
static time_t last_notify = 0;
|
||||
int interval = get_int_var(NOTIFY_INTERVAL_VAR);
|
||||
time_t current_time = time(NULL);
|
||||
|
||||
if (current_time < last_notify)
|
||||
last_notify = current_time;
|
||||
else if (!interval || interval > (current_time - last_notify))
|
||||
return; /* Not yet */
|
||||
|
||||
last_notify = current_time;
|
||||
|
||||
if (!server_list_size() || !get_int_var(NOTIFY_VAR))
|
||||
return;
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
if (is_server_connected(servnum) && !get_server_watch(servnum))
|
||||
{
|
||||
from_server = servnum;
|
||||
if (NOTIFY_LIST(servnum)->ison && *NOTIFY_LIST(servnum)->ison)
|
||||
{
|
||||
char *lame = LOCAL_COPY(NOTIFY_LIST(servnum)->ison);
|
||||
isonbase(lame, ison_notify);
|
||||
}
|
||||
}
|
||||
}
|
||||
from_server = old_from_server;
|
||||
return;
|
||||
}
|
||||
|
||||
void check_auto_invite(char *nick, char *userhost)
|
||||
{
|
||||
#ifdef WANT_USERLIST
|
||||
ChannelList *chan = NULL;
|
||||
UserList *tmp = NULL;
|
||||
for (chan = get_server_channels(from_server); chan; chan = chan->next)
|
||||
{
|
||||
if ((tmp = lookup_userlevelc("*", userhost, chan->channel, NULL)))
|
||||
{
|
||||
NickList *n = NULL;
|
||||
n = find_nicklist_in_channellist(nick, chan, 0);
|
||||
if (!n && chan->chop && get_cset_int_var(chan->csets, AINV_CSET) && (tmp->flags & ADD_INVITE) && get_cset_int_var(chan->csets, AINV_CSET))
|
||||
{
|
||||
bitchsay("Auto-inviting %s to %s", nick, chan->channel);
|
||||
send_to_server("NOTICE %s :Auto-invite from %s", nick, get_server_nickname(from_server));
|
||||
send_to_server("INVITE %s %s%s%s", nick, chan->channel, chan->key?space:empty_string, chan->key?chan->key:empty_string);
|
||||
}
|
||||
}
|
||||
tmp = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static char *batched_notify_userhosts = NULL;
|
||||
static int batched_notifies = 0;
|
||||
|
||||
void batch_notify_userhost (char *nick)
|
||||
{
|
||||
m_s3cat(&batched_notify_userhosts, space, nick);
|
||||
batched_notifies++;
|
||||
}
|
||||
|
||||
void dispatch_notify_userhosts (void)
|
||||
{
|
||||
if (batched_notify_userhosts)
|
||||
{
|
||||
if (x_debug & DEBUG_NOTIFY)
|
||||
yell("Dispatching notifies to server [%d], [%s]", from_server, batched_notify_userhosts);
|
||||
userhostbase(batched_notify_userhosts, notify_userhost_dispatch, 1, NULL);
|
||||
new_free(&batched_notify_userhosts);
|
||||
batched_notifies = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void notify_userhost_dispatch (UserhostItem *stuff, char *nick, char *text)
|
||||
{
|
||||
char userhost[BIG_BUFFER_SIZE + 1];
|
||||
|
||||
snprintf(userhost, BIG_BUFFER_SIZE, "%s@%s", stuff->user, stuff->host);
|
||||
notify_userhost_reply(stuff->nick, userhost);
|
||||
}
|
||||
|
||||
#if 0
|
||||
<MadHack> #0 0x809a571 in n_malloc_strcpy ()
|
||||
<MadHack> #1 0x80b400e in notify_userhost_reply ()
|
||||
<MadHack> #2 0x80b3f65 in notify_userhost_dispatch ()
|
||||
<MadHack> #3 0x80d2ef0 in userhost_returned ()
|
||||
<MadHack> #4 0x80b61bd in numbered_command ()
|
||||
hard_uh_notify is on
|
||||
#endif
|
||||
|
||||
void notify_userhost_reply (char *nick, char *userhost)
|
||||
{
|
||||
NotifyItem *tmp;
|
||||
|
||||
if ((tmp = (NotifyItem *)array_lookup(
|
||||
(Array *)NOTIFY_LIST(from_server), nick, 0, 0)))
|
||||
{
|
||||
set_display_target(nick, LOG_CRAP);
|
||||
malloc_strcpy(&tmp->nick, nick);
|
||||
if (userhost)
|
||||
{
|
||||
malloc_strcpy(&tmp->host, userhost);
|
||||
if (!wild_match(tmp->looking, userhost))
|
||||
{
|
||||
reset_display_target();
|
||||
return;
|
||||
}
|
||||
check_auto_invite(nick, userhost);
|
||||
}
|
||||
if ((do_hook(NOTIFY_SIGNON_LIST, "%s %s", tmp->nick, tmp->host?tmp->host:empty_string)))
|
||||
{
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_SIGNON_FSET), "%s %s %s",update_clock(GET_TIME),tmp->nick,tmp->host?tmp->host:empty_string));
|
||||
logmsg(LOG_NOTIFY, tmp->nick, 0, "%s(%s) has logged on", tmp->host ? tmp->host : empty_string, tmp->looking);
|
||||
}
|
||||
malloc_strcpy(&last_notify_nick, nick);
|
||||
reset_display_target();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* notify_mark: This marks a given person on the notify list as either on irc
|
||||
* (if flag is 1), or not on irc (if flag is 0). If the person's status has
|
||||
* changed since the last check, a message is displayed to that effect. If
|
||||
* the person is not on the noTify list, this call is ignored
|
||||
* doit if passed as 0 means it comes from a join, or a msg, etc, not from
|
||||
* an ison reply. 1 is the other..
|
||||
*/
|
||||
void notify_mark(char *nick, char *userhost, int flag, int doit)
|
||||
{
|
||||
NotifyItem *tmp;
|
||||
int count = 0;
|
||||
int loc = 0;
|
||||
|
||||
if ((tmp = (NotifyItem *)find_array_item(
|
||||
(Array *)NOTIFY_LIST(from_server), nick,
|
||||
&count, &loc)) && count < 0)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
if (tmp->host && !wild_match(tmp->looking, tmp->host))
|
||||
{
|
||||
tmp->flag = 0;
|
||||
return;
|
||||
}
|
||||
if (tmp->flag != 1)
|
||||
{
|
||||
batch_notify_userhost(nick);
|
||||
tmp->lastseen = 0;
|
||||
if (!tmp->added)
|
||||
tmp->added = now;
|
||||
tmp->times++;
|
||||
}
|
||||
tmp->flag = 1;
|
||||
if (!doit)
|
||||
dispatch_notify_userhosts();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmp->flag == 1)
|
||||
{
|
||||
const char *who = NULL;
|
||||
unsigned long level = 0;
|
||||
save_display_target(&who, &level);
|
||||
set_display_target(nick, LOG_NOTIFY);
|
||||
check_orig_nick(nick);
|
||||
if ((do_hook(NOTIFY_SIGNOFF_LIST, "%s %s", tmp->nick, tmp->host?tmp->host:empty_string)) && doit)
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_SIGNOFF_FSET), "%s %s %s",update_clock(GET_TIME),tmp->nick,tmp->host?tmp->host:empty_string));
|
||||
tmp->period += now - tmp->added;
|
||||
tmp->lastseen = now;
|
||||
logmsg(LOG_NOTIFY, tmp->nick, 0, "%s(%s) has logged off", tmp->host ? tmp->host : empty_string, tmp->looking);
|
||||
restore_display_target(who, level);
|
||||
}
|
||||
tmp->flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void save_notify(FILE *fp)
|
||||
{
|
||||
int i = 0;
|
||||
if (server_list_size() && NOTIFY_MAX(0))
|
||||
{
|
||||
fprintf(fp, "NOTIFY");
|
||||
for (i = 0; i < NOTIFY_MAX(0); i++)
|
||||
fprintf(fp, " %s!%s", NOTIFY_ITEM(0, i)->nick, NOTIFY_ITEM(0, i)->looking);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
if (NOTIFY_MAX(0) && do_hook(SAVEFILE_LIST, "Notify %d", NOTIFY_MAX(0)))
|
||||
bitchsay("Saved %d Notify entries", NOTIFY_MAX(0));
|
||||
}
|
||||
|
||||
/* I hate broken compilers -mrg */
|
||||
static char *vals[] = { "NOISY", "QUIET", "OLD", NULL };
|
||||
|
||||
void set_notify_handler(Window *win, char *value, int unused)
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
char *s;
|
||||
|
||||
if (!value)
|
||||
value = empty_string;
|
||||
for (i = 0, len = strlen(value); (s = vals[i]); i++)
|
||||
if (0 == my_strnicmp(value, s, len))
|
||||
break;
|
||||
set_string_var(NOTIFY_HANDLER_VAR, s);
|
||||
return;
|
||||
}
|
||||
|
||||
void make_notify_list (int servnum)
|
||||
{
|
||||
NotifyItem *tmp;
|
||||
char *list = NULL;
|
||||
int i;
|
||||
|
||||
server_list[servnum].notify_list.func = (alist_func)global[MY_STRICMP];
|
||||
server_list[servnum].notify_list.hash = HASH_INSENSITIVE;
|
||||
|
||||
if (!get_int_var(NOTIFY_VAR))
|
||||
return;
|
||||
for (i = 0; i < NOTIFY_MAX(0); i++)
|
||||
{
|
||||
tmp = (NotifyItem *)new_malloc(sizeof(NotifyItem));
|
||||
tmp->nick = m_strdup(NOTIFY_ITEM(0, i)->nick);
|
||||
tmp->looking = m_strdup(NOTIFY_ITEM(0, i)->looking);
|
||||
tmp->flag = 0;
|
||||
|
||||
add_to_array ((Array *)NOTIFY_LIST(servnum),
|
||||
(Array_item *)tmp);
|
||||
m_s3cat(&list, space, tmp->nick);
|
||||
}
|
||||
if (list)
|
||||
isonbase(list, ison_notify);
|
||||
new_free(&list);
|
||||
}
|
||||
|
||||
char *get_notify_nicks (int showserver, int showon, char *nick, int extra)
|
||||
{
|
||||
char *list = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (showserver < 0 || showserver >= server_list_size())
|
||||
return m_strdup(empty_string);
|
||||
|
||||
if (nick && *nick)
|
||||
{
|
||||
NotifyItem *tmp;
|
||||
for (i = 0; i < NOTIFY_MAX(showserver); i++)
|
||||
{
|
||||
if (my_stricmp(nick, NOTIFY_ITEM(showserver, i)->nick))
|
||||
continue;
|
||||
tmp = NOTIFY_ITEM(from_server, i);
|
||||
m_s3cat(&list, space, tmp->nick);
|
||||
m_s3cat(&list, space, tmp->host);
|
||||
m_s3cat(&list, space, ltoa(tmp->flag));
|
||||
m_s3cat(&list, space, ltoa(tmp->period));
|
||||
m_s3cat(&list, space, ltoa(tmp->times));
|
||||
m_s3cat(&list, space, ltoa(tmp->lastseen));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < NOTIFY_MAX(showserver); i++)
|
||||
{
|
||||
if (showon == -1 || showon == NOTIFY_ITEM(showserver, i)->flag)
|
||||
m_s3cat(&list, space, NOTIFY_ITEM(showserver, i)->nick);
|
||||
}
|
||||
}
|
||||
return list ? list : m_strdup(empty_string);
|
||||
}
|
||||
|
||||
|
||||
char *get_watch_nicks (int showserver, int showon, char *nick, int extra)
|
||||
{
|
||||
char *list = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (showserver < 0 || showserver >= server_list_size())
|
||||
return m_strdup(empty_string);
|
||||
|
||||
if (nick && *nick)
|
||||
{
|
||||
NotifyItem *tmp;
|
||||
for (i = 0; i < WATCH_MAX(showserver); i++)
|
||||
{
|
||||
if (my_stricmp(nick, WATCH_ITEM(showserver, i)->nick))
|
||||
continue;
|
||||
tmp = WATCH_ITEM(from_server, i);
|
||||
m_s3cat(&list, space, tmp->nick);
|
||||
m_s3cat(&list, space, tmp->host);
|
||||
m_s3cat(&list, space, ltoa(tmp->flag));
|
||||
m_s3cat(&list, space, ltoa(tmp->period));
|
||||
m_s3cat(&list, space, ltoa(tmp->times));
|
||||
m_s3cat(&list, space, ltoa(tmp->lastseen));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < WATCH_MAX(showserver); i++)
|
||||
{
|
||||
if (showon == -1 || showon == WATCH_ITEM(showserver, i)->flag)
|
||||
m_s3cat(&list, space, WATCH_ITEM(showserver, i)->nick);
|
||||
}
|
||||
}
|
||||
return list ? list : m_strdup(empty_string);
|
||||
}
|
||||
|
||||
|
||||
int iswatch(int serv, char *list, int all)
|
||||
{
|
||||
if (all)
|
||||
{
|
||||
int servnum;
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
if (get_server_watch(servnum) && is_server_connected(servnum))
|
||||
my_send_to_server(servnum, "WATCH %s", list);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (get_server_watch(serv) && is_server_connected(serv))
|
||||
my_send_to_server(serv, "WATCH %s", list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void make_watch_list (int servnum)
|
||||
{
|
||||
NotifyItem *tmp;
|
||||
char *list = NULL;
|
||||
int i;
|
||||
|
||||
server_list[servnum].watch_list.func = (alist_func)global[MY_STRICMP];
|
||||
server_list[servnum].watch_list.hash = HASH_INSENSITIVE;
|
||||
|
||||
for (i = 0; i < WATCH_MAX(0); i++)
|
||||
{
|
||||
if (!(tmp = (NotifyItem *)array_lookup((Array *)WATCH_LIST(servnum), WATCH_ITEM(0, i)->nick, 0, 0)))
|
||||
{
|
||||
tmp = (NotifyItem *)new_malloc(sizeof(NotifyItem));
|
||||
malloc_strcpy(&tmp->nick, WATCH_ITEM(0, i)->nick);
|
||||
add_to_array ((Array *)WATCH_LIST(servnum), (Array_item *)tmp);
|
||||
}
|
||||
tmp->flag = 0;
|
||||
if (!list)
|
||||
list = m_opendup(space_plus, tmp->nick, NULL);
|
||||
else
|
||||
m_s3cat(&list, space_plus, tmp->nick);
|
||||
}
|
||||
if (list)
|
||||
iswatch(servnum, list, 0);
|
||||
new_free(&list);
|
||||
}
|
||||
|
||||
|
||||
void show_watch_list(int all)
|
||||
{
|
||||
#if 0
|
||||
int i;
|
||||
char *list = NULL;
|
||||
if ((server != -1) && server < server_list_size() && WATCH_MAX(server))
|
||||
{
|
||||
put_it("Watch List");
|
||||
for (i = 0; i < WATCH_MAX(server); i++)
|
||||
m_s3cat(&list, space, WATCH_ITEM(server, i)->nick);
|
||||
put_it("%s", list);
|
||||
}
|
||||
new_free(&list);
|
||||
#endif
|
||||
int i, count = 0;
|
||||
char period[80], timeson[80], lastseen[80];
|
||||
NotifyItem *tmp;
|
||||
|
||||
if (from_server == -1)
|
||||
return;
|
||||
for (i = 0; i < WATCH_MAX(from_server); i++)
|
||||
{
|
||||
tmp = WATCH_ITEM(from_server, i);
|
||||
if (tmp->flag)
|
||||
{
|
||||
strcpy(period, ltoa(tmp->period));
|
||||
strcpy(timeson, ltoa(tmp->times));
|
||||
strcpy(lastseen, ltoa(now - tmp->added));
|
||||
if (do_hook(WATCH_LIST, "%s %s %d %s %s %s", tmp->nick, tmp->host?tmp->host:"unknown@unknown", tmp->flag, timeson, period, lastseen))
|
||||
{
|
||||
if (!count)
|
||||
{
|
||||
put_it("%s", convert_output_format("$G Online Users", NULL, NULL));
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_ON_FSET), "%s %s %s %s %s", "Nick", "UserHost", "Times", "Period", "Last seen"));
|
||||
}
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_ON_FSET), "%s %s %s %s %s", tmp->nick, tmp->host?tmp->host:tmp->looking, timeson, lastseen, "now" ));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
count = 0;
|
||||
for (i = 0; i < WATCH_MAX(from_server); i++)
|
||||
{
|
||||
tmp = WATCH_ITEM(from_server, i);
|
||||
if ((all && !tmp->flag) || (tmp->times && !tmp->flag))
|
||||
{
|
||||
strcpy(period, ltoa(tmp->period));
|
||||
strcpy(timeson, ltoa(tmp->times));
|
||||
strcpy(lastseen, ltoa(now - tmp->lastseen));
|
||||
if (do_hook(WATCH_LIST, "%s %s %d %s %s %s", tmp->nick, tmp->host?tmp->host:"unknown@unknown", tmp->flag, timeson, period, lastseen))
|
||||
{
|
||||
if (!count)
|
||||
{
|
||||
put_it("%s", convert_output_format("$G Offline Users", NULL, NULL));
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_OFF_FSET), "%s %s %s %s %s", "Nick", "UserHost", "Times", "Period", "Last seen"));
|
||||
}
|
||||
|
||||
if (!tmp->times)
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_OFF_FSET), "%s %s %s %s %s", tmp->nick, tmp->host?tmp->host:tmp->looking, "never", "none", "n/a"));
|
||||
else
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_NOTIFY_OFF_FSET), "%s %s %s %s %s", tmp->nick, tmp->host?tmp->host:tmp->looking, timeson, period, lastseen));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(watchcmd)
|
||||
{
|
||||
char *nick;
|
||||
char *list = NULL;
|
||||
int servnum = 0;
|
||||
if (args && *args)
|
||||
{
|
||||
while ((nick = next_arg(args, &args)))
|
||||
{
|
||||
NotifyItem *new_n;
|
||||
int shown = 0;
|
||||
if (*nick == '+')
|
||||
{
|
||||
int added = 0;
|
||||
nick++;
|
||||
if (!*nick)
|
||||
{
|
||||
show_watch_list(0);
|
||||
continue;
|
||||
}
|
||||
if (strchr(nick, '*'))
|
||||
bitchsay("Wildcards not allowed in WATCH nicknames!");
|
||||
else
|
||||
{
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
if ((new_n = (NotifyItem *)array_lookup(
|
||||
(Array *)WATCH_LIST(servnum), nick, 0, 0)))
|
||||
{
|
||||
new_n->flag = 0;
|
||||
continue; /* Already there! */
|
||||
}
|
||||
if (WATCH_MAX(servnum) >= (is_server_connected(servnum) ? get_server_watch(servnum) : 128))
|
||||
{
|
||||
bitchsay("Too many WATCH entries [%d]", get_server_watch(servnum));
|
||||
continue;
|
||||
}
|
||||
new_n = (NotifyItem *)new_malloc(sizeof(NotifyItem));
|
||||
new_n->nick = m_strdup(nick);
|
||||
new_n->flag = 0;
|
||||
add_to_array((Array *)WATCH_LIST(servnum),
|
||||
(Array_item *)new_n);
|
||||
added = 1;
|
||||
}
|
||||
if (added)
|
||||
{
|
||||
if (!list)
|
||||
list = m_opendup(space_plus, new_n->nick, NULL);
|
||||
else
|
||||
m_s3cat(&list, space_plus, new_n->nick);
|
||||
}
|
||||
bitchsay("%s added to the watch list", nick);
|
||||
}
|
||||
}
|
||||
else if (*nick == '-')
|
||||
{
|
||||
nick++;
|
||||
if (!*nick)
|
||||
continue;
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
if ((new_n = (NotifyItem *)remove_from_array(
|
||||
(Array *)WATCH_LIST(servnum), nick)))
|
||||
{
|
||||
if (!list)
|
||||
list = m_opendup(space_minus, nick, NULL);
|
||||
else
|
||||
m_s3cat(&list, space_minus, nick);
|
||||
new_free(&new_n->nick);
|
||||
new_free(&new_n->host);
|
||||
new_free(&new_n->looking);
|
||||
new_free((char **)&new_n);
|
||||
if (!shown)
|
||||
{
|
||||
bitchsay("%s removed from watch list", nick);
|
||||
shown = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!shown)
|
||||
{
|
||||
bitchsay("%s is not on the watch list", nick);
|
||||
shown = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (*nick == 'S')
|
||||
my_send_to_server(from_server, "%s S", command);
|
||||
else if (*nick == 'L')
|
||||
my_send_to_server(from_server, "%s L", command);
|
||||
else if (*nick == 'l')
|
||||
my_send_to_server(from_server, "%s l", command);
|
||||
else if (*nick == 'C')
|
||||
{
|
||||
for (servnum = 0; servnum < server_list_size(); servnum++)
|
||||
{
|
||||
if (!get_server_watch(servnum))
|
||||
continue;
|
||||
while ((new_n = (NotifyItem *)array_pop(
|
||||
(Array *)WATCH_LIST(servnum), 0)))
|
||||
{
|
||||
new_free(&new_n->nick);
|
||||
new_free(&new_n->looking);
|
||||
new_free(&new_n->host);
|
||||
new_free((char **)&new_n);
|
||||
}
|
||||
if (get_server_watch(servnum) && is_server_connected(servnum))
|
||||
my_send_to_server(servnum, "%s S", command);
|
||||
}
|
||||
bitchsay("Watch list cleared");
|
||||
}
|
||||
}
|
||||
if (list)
|
||||
iswatch(servnum, list, 1);
|
||||
new_free(&list);
|
||||
} else
|
||||
show_watch_list(1);
|
||||
}
|
||||
|
||||
void save_watch(FILE *fp)
|
||||
{
|
||||
int i = 0;
|
||||
if (server_list_size() && WATCH_MAX(0))
|
||||
{
|
||||
fprintf(fp, "WATCH");
|
||||
for (i = 0; i < WATCH_MAX(0); i++)
|
||||
fprintf(fp, " +%s", WATCH_ITEM(0, i)->nick);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
if (WATCH_MAX(0) && do_hook(SAVEFILE_LIST, "Watch %d", WATCH_MAX(0)))
|
||||
bitchsay("Saved %d Watch entries", WATCH_MAX(0));
|
||||
}
|
||||
|
||||
void show_watch_notify(char *from, int online, char **args)
|
||||
{
|
||||
NotifyItem *new_n;
|
||||
if ((new_n = (NotifyItem *)array_lookup((Array *)WATCH_LIST(from_server),
|
||||
args[0], 0, 0)))
|
||||
{
|
||||
if (online)
|
||||
{
|
||||
new_free(&new_n->host);
|
||||
new_n->host = m_opendup(args[1], "@", args[2], NULL);
|
||||
if (!new_n->flag)
|
||||
{
|
||||
new_n->lastseen = 0;
|
||||
if (!new_n->added)
|
||||
new_n->added = now;
|
||||
new_n->times++;
|
||||
logmsg(LOG_NOTIFY, new_n->nick, 0, "%s has logged on", new_n->host ? new_n->host : empty_string);
|
||||
}
|
||||
new_n->period = my_atol(args[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_n->flag)
|
||||
{
|
||||
new_n->period = now - new_n->added;
|
||||
new_n->lastseen = now;
|
||||
logmsg(LOG_NOTIFY, new_n->nick, 0, "%s has logged off", new_n->host ? new_n->host : empty_string);
|
||||
}
|
||||
}
|
||||
new_n->flag = online;
|
||||
put_it("%s", convert_output_format(fget_string_var(online?FORMAT_WATCH_SIGNON_FSET:FORMAT_WATCH_SIGNOFF_FSET), "%s %s %s %s", args[0], args[1], args[2], args[3]));
|
||||
}
|
||||
}
|
||||
|
||||
void send_watch(int server)
|
||||
{
|
||||
int i;
|
||||
char *list = NULL;
|
||||
NotifyItem *tmp;
|
||||
for (i = 0; i < WATCH_MAX(server); i++)
|
||||
{
|
||||
if (!(tmp = (NotifyItem *)array_lookup((Array *)WATCH_LIST(server), WATCH_ITEM(server, i)->nick, 0, 0)))
|
||||
{
|
||||
tmp = (NotifyItem *)new_malloc(sizeof(NotifyItem));
|
||||
malloc_strcpy(&tmp->nick, WATCH_ITEM(server, i)->nick);
|
||||
add_to_array ((Array *)WATCH_LIST(server), (Array_item *)tmp);
|
||||
}
|
||||
tmp->flag = 0;
|
||||
if (!list)
|
||||
list = m_opendup(space_plus, tmp->nick, NULL);
|
||||
else
|
||||
{
|
||||
if ((strlen(list) + strlen(tmp->nick)) > 490)
|
||||
{
|
||||
iswatch(server, list, 0);
|
||||
new_free(&list);
|
||||
list = m_opendup(space_plus, tmp->nick, NULL);
|
||||
}
|
||||
else
|
||||
m_s3cat(&list, space_plus, tmp->nick);
|
||||
}
|
||||
}
|
||||
if (list)
|
||||
iswatch(server, list, 0);
|
||||
new_free(&list);
|
||||
}
|
||||
1634
source/numbers.c
Normal file
1634
source/numbers.c
Normal file
File diff suppressed because it is too large
Load Diff
108
source/opendir.c
Normal file
108
source/opendir.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* opendir.c --
|
||||
*
|
||||
* This file provides dirent-style directory-reading procedures
|
||||
* for V7 Unix systems that don't have such procedures. The
|
||||
* origin of this code is unclear, but it seems to have come
|
||||
* originally from Larry Wall.
|
||||
*
|
||||
*
|
||||
* SCCS: @(#) opendir.c 1.3 96/02/15 12:08:21
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclPort.h"
|
||||
|
||||
#undef DIRSIZ
|
||||
#define DIRSIZ(dp) \
|
||||
((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
|
||||
|
||||
/*
|
||||
* open a directory.
|
||||
*/
|
||||
DIR *
|
||||
opendir(name)
|
||||
char *name;
|
||||
{
|
||||
register DIR *dirp;
|
||||
register int fd;
|
||||
char *myname;
|
||||
|
||||
myname = ((*name == '\0') ? "." : name);
|
||||
if ((fd = open(myname, 0, 0)) == -1)
|
||||
return NULL;
|
||||
if ((dirp = (DIR *)ckalloc(sizeof(DIR))) == NULL) {
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
dirp->dd_fd = fd;
|
||||
dirp->dd_loc = 0;
|
||||
return dirp;
|
||||
}
|
||||
|
||||
/*
|
||||
* read an old style directory entry and present it as a new one
|
||||
*/
|
||||
#ifndef pyr
|
||||
#define ODIRSIZ 14
|
||||
|
||||
struct olddirect {
|
||||
ino_t od_ino;
|
||||
char od_name[ODIRSIZ];
|
||||
};
|
||||
#else /* a Pyramid in the ATT universe */
|
||||
#define ODIRSIZ 248
|
||||
|
||||
struct olddirect {
|
||||
long od_ino;
|
||||
short od_fill1, od_fill2;
|
||||
char od_name[ODIRSIZ];
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* get next entry in a directory.
|
||||
*/
|
||||
struct dirent *
|
||||
readdir(dirp)
|
||||
register DIR *dirp;
|
||||
{
|
||||
register struct olddirect *dp;
|
||||
static struct dirent dir;
|
||||
|
||||
for (;;) {
|
||||
if (dirp->dd_loc == 0) {
|
||||
dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
|
||||
DIRBLKSIZ);
|
||||
if (dirp->dd_size <= 0)
|
||||
return NULL;
|
||||
}
|
||||
if (dirp->dd_loc >= dirp->dd_size) {
|
||||
dirp->dd_loc = 0;
|
||||
continue;
|
||||
}
|
||||
dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
|
||||
dirp->dd_loc += sizeof(struct olddirect);
|
||||
if (dp->od_ino == 0)
|
||||
continue;
|
||||
dir.d_ino = dp->od_ino;
|
||||
strncpy(dir.d_name, dp->od_name, ODIRSIZ);
|
||||
dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
|
||||
dir.d_namlen = strlen(dir.d_name);
|
||||
dir.d_reclen = DIRSIZ(&dir);
|
||||
return (&dir);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* close a directory.
|
||||
*/
|
||||
void
|
||||
closedir(dirp)
|
||||
register DIR *dirp;
|
||||
{
|
||||
close(dirp->dd_fd);
|
||||
dirp->dd_fd = -1;
|
||||
dirp->dd_loc = 0;
|
||||
ckfree((char *) dirp);
|
||||
}
|
||||
342
source/output.c
Normal file
342
source/output.c
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* output.c: handles a variety of tasks dealing with the output from the irc
|
||||
* program
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
*
|
||||
* Copyright(c) 1990
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: output.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(output_c)
|
||||
#include "struct.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "output.h"
|
||||
#include "vars.h"
|
||||
#include "input.h"
|
||||
#include "ircaux.h"
|
||||
#include "ircterm.h"
|
||||
#include "lastlog.h"
|
||||
#include "window.h"
|
||||
#include "screen.h"
|
||||
#include "server.h"
|
||||
#include "hook.h"
|
||||
#include "ctcp.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
int in_help = 0;
|
||||
|
||||
/* make this buffer *much* bigger than needed */
|
||||
|
||||
#define LARGE_BIG_BUFFER_SIZE BIG_BUFFER_SIZE * 10
|
||||
|
||||
static char *putbuf = NULL; /*[LARGE_BIG_BUFFER_SIZE + 1];*/
|
||||
extern LastMsg last_servermsg[];
|
||||
|
||||
char three_stars[4] = "***";
|
||||
|
||||
/* unflash: sends a ^[c to the screen */
|
||||
/* Must be defined to be useful, cause some vt100s really *do* reset when
|
||||
sent this command. >;-) */
|
||||
|
||||
/* functions which switch the character set on the console */
|
||||
/* ibmpc is not available on the xterm */
|
||||
|
||||
void charset_ibmpc (void)
|
||||
{
|
||||
fwrite("\033(U", 3, 1, current_ftarget); /* switch to IBM code page 437 */
|
||||
}
|
||||
|
||||
void charset_lat1 (void)
|
||||
{
|
||||
fwrite("\033(B", 3, 1, current_ftarget); /* switch to Latin-1 (ISO 8859-1) */
|
||||
}
|
||||
|
||||
void charset_cst(void)
|
||||
{
|
||||
fwrite("\033(K", 3, 1, current_ftarget); /* switch too user-defined */
|
||||
}
|
||||
|
||||
/* currently not used. */
|
||||
|
||||
|
||||
/* Now that you can send ansi sequences, this is much less inportant.. */
|
||||
void unflash (void)
|
||||
{
|
||||
#if !defined(WINNT) && !defined(__EMX__)
|
||||
|
||||
#if defined(HARD_UNFLASH) && !defined(CHARSET_CUSTOM)
|
||||
fwrite("\033c", 5, 1, current_ftarget); /* hard reset */
|
||||
#else
|
||||
fwrite("\033)0", 6, 1, current_ftarget); /* soft reset */
|
||||
#endif
|
||||
|
||||
#if defined(LATIN1)
|
||||
charset_lat1();
|
||||
#elif defined(CHARSET_CUSTOM)
|
||||
charset_cst();
|
||||
#else
|
||||
charset_ibmpc();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* refresh_screen: Whenever the REFRESH_SCREEN function is activated, this
|
||||
* swoops into effect
|
||||
*/
|
||||
void refresh_screen (unsigned char dumb, char *dumber)
|
||||
{
|
||||
extern int need_redraw;
|
||||
|
||||
#if !defined(WINNT) && !defined(__EMX__)
|
||||
term_clear_screen();
|
||||
unflash();
|
||||
#else
|
||||
xterm_settitle();
|
||||
term_clear_screen();
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for (tmp = screen_list; tmp; tmp = tmp->next)
|
||||
tmp->co = TI_cols, tmp->li = TI_lines;
|
||||
#endif
|
||||
if (term_resize())
|
||||
recalculate_windows(current_window->screen);
|
||||
else
|
||||
redraw_all_windows();
|
||||
if (need_redraw)
|
||||
need_redraw = 0;
|
||||
update_all_windows();
|
||||
update_input(UPDATE_ALL);
|
||||
}
|
||||
|
||||
/*
|
||||
* refresh_window_screen: Updates and redraws only the window's
|
||||
* screen that was passed as a parameter.
|
||||
*/
|
||||
|
||||
#ifdef GUI
|
||||
void refresh_window_screen(Window *window)
|
||||
{
|
||||
xterm_settitle();
|
||||
recalculate_windows(current_window->screen);
|
||||
update_all_windows();
|
||||
update_input(UPDATE_ALL);
|
||||
}
|
||||
#endif
|
||||
|
||||
int init_output(void)
|
||||
{
|
||||
if (!putbuf)
|
||||
putbuf = new_malloc(LARGE_BIG_BUFFER_SIZE+1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init_windows: */
|
||||
int init_screen (void)
|
||||
{
|
||||
extern int term_initialized;
|
||||
term_initialized = 1;
|
||||
term_clear_screen();
|
||||
term_resize();
|
||||
create_new_screen();
|
||||
new_window(main_screen);
|
||||
update_all_windows();
|
||||
term_move_cursor(0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void put_echo (char *str)
|
||||
{
|
||||
add_to_log(irclog_fp, 0, str, logfile_line_mangler);
|
||||
add_to_screen(str);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* put_it: the irc display routine. Use this routine to display anything to
|
||||
* the main irc window. It handles sending text to the display or stdout as
|
||||
* needed, add stuff to the lastlog and log file, etc. Things NOT to do:
|
||||
* Dont send any text that contains \n, very unpredictable. Tabs will also
|
||||
* screw things up. The calling routing is responsible for not overwriting
|
||||
* the 1K buffer allocated.
|
||||
*
|
||||
* For Ultrix machines, you can't call put_it() with floating point arguements.
|
||||
* It just doesn't work. - phone, jan 1993.
|
||||
*/
|
||||
void BX_put_it(const char *format, ...)
|
||||
{
|
||||
if (window_display && format)
|
||||
{
|
||||
va_list args;
|
||||
memset(putbuf, 0, 200);
|
||||
va_start (args, format);
|
||||
vsnprintf(putbuf, LARGE_BIG_BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
if (*putbuf)
|
||||
put_echo(putbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is an alternative form of put_it which writes three asterisks
|
||||
* before actually putting things out.
|
||||
*/
|
||||
void say (const char *format, ...)
|
||||
{
|
||||
int len = 0;
|
||||
if (window_display && format)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
if (thing_ansi)
|
||||
len = strlen(thing_ansi);
|
||||
else
|
||||
len = 3;
|
||||
vsnprintf(&(putbuf[len+1]), LARGE_BIG_BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
strcpy(putbuf, thing_ansi?thing_ansi:three_stars);
|
||||
putbuf[len] = ' ';
|
||||
if (strip_ansi_in_echo)
|
||||
{
|
||||
register char *ptr;
|
||||
for (ptr = putbuf + len; *ptr; ptr++)
|
||||
if (*ptr < 31 && *ptr > 13)
|
||||
if (*ptr != 15 && *ptr != 22)
|
||||
*ptr = (*ptr & 127) | 64;
|
||||
}
|
||||
put_echo(putbuf);
|
||||
}
|
||||
}
|
||||
|
||||
void BX_bitchsay (const char *format, ...)
|
||||
{
|
||||
int len;
|
||||
if (window_display && format)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
sprintf(putbuf, "%s \002%s\002: ", thing_ansi?thing_ansi:three_stars, version);
|
||||
len = strlen(putbuf);
|
||||
vsnprintf(&(putbuf[len]), LARGE_BIG_BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
if (strip_ansi_in_echo)
|
||||
{
|
||||
register char *ptr;
|
||||
for (ptr = putbuf+len; *ptr; ptr++)
|
||||
if (*ptr < 31 && *ptr > 13)
|
||||
if (*ptr != 15 && *ptr != 22)
|
||||
*ptr = (*ptr & 127) | 64;
|
||||
}
|
||||
put_echo(putbuf);
|
||||
}
|
||||
}
|
||||
|
||||
void BX_yell(const char *format, ...)
|
||||
{
|
||||
if (format)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
*putbuf = 0;
|
||||
vsnprintf(putbuf, LARGE_BIG_BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
if (*putbuf && do_hook(YELL_LIST, "%s", putbuf))
|
||||
put_echo(putbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void log_put_it (const char *topic, const char *format, ...)
|
||||
{
|
||||
if (format)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vsnprintf(putbuf, LARGE_BIG_BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
|
||||
in_help = 1;
|
||||
set_display_target(NULL, LOG_CURRENT);
|
||||
if (window_display)
|
||||
put_echo(putbuf);
|
||||
reset_display_target();
|
||||
in_help = 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *ov_server(int server)
|
||||
{
|
||||
char *c;
|
||||
char *d;
|
||||
static char tmpstr[61];
|
||||
char *string = get_server_itsname(server);
|
||||
|
||||
if (!string || !*string)
|
||||
string = get_server_name(server);
|
||||
if (!string || !*string)
|
||||
return empty_string;
|
||||
strmcpy(tmpstr, string, 60);
|
||||
if (!(c = strrchr(tmpstr,'.')))
|
||||
return(string);
|
||||
*c = 0;
|
||||
if (!(d = strrchr(tmpstr, '.')))
|
||||
d = ++c; /* Extract domain */
|
||||
d++;
|
||||
return(d);
|
||||
}
|
||||
|
||||
void serversay(int save, int from_server, const char *format, ...)
|
||||
{
|
||||
Window *old_target_window = target_window;
|
||||
char servername[200];
|
||||
int len = 0;
|
||||
char *out = NULL;
|
||||
if (get_int_var(OV_VAR))
|
||||
target_window = get_window_by_name("OPER_VIEW");
|
||||
if (window_display && format)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vsnprintf(putbuf, LARGE_BIG_BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
strmcpy(servername, convert_output_format(get_string_var(SERVER_PROMPT_VAR), "%s", ov_server(from_server)?ov_server(from_server):empty_string), 79);
|
||||
len = strlen(putbuf);
|
||||
out = alloca(strlen(servername)+len+5);
|
||||
len = strlen(servername);
|
||||
strcpy(out, servername); out[len] = ' '; out[len+1] = 0;
|
||||
strcat(out, putbuf);
|
||||
if (*out)
|
||||
put_echo(out);
|
||||
}
|
||||
target_window = old_target_window;
|
||||
if (save && out)
|
||||
add_last_type(&last_servermsg[0], MAX_LAST_MSG, NULL, NULL, NULL, out);
|
||||
}
|
||||
/*
|
||||
* Error is exactly like yell, except that if the error occured while
|
||||
* you were loading a script, it tells you where it happened.
|
||||
*/
|
||||
void error (const char *format, ...)
|
||||
{
|
||||
dump_load_stack(0);
|
||||
if (format)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
vsnprintf(putbuf, LARGE_BIG_BUFFER_SIZE, format, args);
|
||||
va_end(args);
|
||||
do_hook(YELL_LIST, "%s", putbuf);
|
||||
put_echo(putbuf);
|
||||
}
|
||||
}
|
||||
1928
source/parse.c
Normal file
1928
source/parse.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
source/pmbitchx.RES
Normal file
BIN
source/pmbitchx.RES
Normal file
Binary file not shown.
3742
source/pmbitchx.c
Normal file
3742
source/pmbitchx.c
Normal file
File diff suppressed because it is too large
Load Diff
3
source/pmbitchx.def
Normal file
3
source/pmbitchx.def
Normal file
@@ -0,0 +1,3 @@
|
||||
NAME WINDOWAPI
|
||||
|
||||
DESCRIPTION 'PMBitchX by panasync: PM by NuKe and rosmo'
|
||||
BIN
source/pmbitchx.ico
Normal file
BIN
source/pmbitchx.ico
Normal file
Binary file not shown.
155
source/pmbitchx.rc
Normal file
155
source/pmbitchx.rc
Normal file
@@ -0,0 +1,155 @@
|
||||
#define INCL_WINSYS
|
||||
#define INCL_WINSTDDLGS
|
||||
#define INCL_WINSTDSPIN
|
||||
#define INCL_NLS
|
||||
#define INCL_SW
|
||||
|
||||
#include <os2.h>
|
||||
#include "..\include\pmbitchx.h"
|
||||
|
||||
ICON IDM_MAINMENU "pmbitchx.ico"
|
||||
BITMAP IDM_LOGO "..\\doc\\bitch52.bmp"
|
||||
|
||||
DLGTEMPLATE FONTDIALOG
|
||||
BEGIN
|
||||
DIALOG "Change font", FONTDIALOG, 160, 170, 124, 143, FS_NOBYTEALIGN |
|
||||
FS_DLGBORDER | WS_CLIPSIBLINGS | WS_SAVEBITS | WS_VISIBLE,
|
||||
FCF_TITLEBAR | FCF_SYSMENU
|
||||
BEGIN
|
||||
CONTROL "OK", DID_OK, 9, 6, 51, 14, WC_BUTTON,
|
||||
BS_PUSHBUTTON | BS_DEFAULT |
|
||||
WS_TABSTOP | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Cancel", DID_CANCEL, 63, 6, 51, 14, WC_BUTTON,
|
||||
BS_PUSHBUTTON | WS_TABSTOP |
|
||||
WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Sample", LB_FONTLIST, 5, 53, 113, 85, WC_LISTBOX,
|
||||
WS_GROUP | WS_TABSTOP | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Save as default font", CB_DEFAULT, 9, 38, 108, 10, WC_BUTTON,
|
||||
BS_AUTOCHECKBOX | WS_GROUP |
|
||||
WS_TABSTOP | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Change for all windows", CB_CHANGEFORALL, 9, 25, 107, 10,
|
||||
WC_BUTTON, WS_TABSTOP | WS_TABSTOP |
|
||||
BS_AUTOCHECKBOX | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
END
|
||||
END
|
||||
|
||||
DLGTEMPLATE PROPNBK
|
||||
BEGIN
|
||||
DIALOG "PMBitchX Properties", PROPNBK, 54, 121, 306, 149, FS_NOBYTEALIGN |
|
||||
FS_DLGBORDER | WS_CLIPSIBLINGS | WS_SAVEBITS | WS_VISIBLE,
|
||||
FCF_TITLEBAR | FCF_SYSMENU
|
||||
PRESPARAMS PP_USER, "9.WarpSans Bold"
|
||||
BEGIN
|
||||
CONTROL "", ID_PROP, 4, 24, 298, 120, WC_NOTEBOOK,
|
||||
BKS_BACKPAGESTR | BKS_MAJORTABTOP |
|
||||
BKS_ROUNDEDTABS | 0x800 |
|
||||
BKS_STATUSTEXTLEFT |
|
||||
BKS_TABTEXTCENTER | BKS_SOLIDBIND |
|
||||
WS_TABSTOP | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans Bold"
|
||||
DEFPUSHBUTTON "Dismiss", DID_OK, 130, 5, 38, 12
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
|
||||
END
|
||||
END
|
||||
|
||||
DLGTEMPLATE NBKP_SETS1
|
||||
BEGIN
|
||||
DIALOG "", NBKP_SETS1, 0, 0, 275, 74, FS_NOBYTEALIGN | NOT FS_DLGBORDER
|
||||
PRESPARAMS PP_USER, "9.WarpSans Bold"
|
||||
BEGIN
|
||||
CONTROL "", SETS1, 10, 12, 113, 58, WC_LISTBOX,
|
||||
LS_NOADJUSTPOS | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Entry", EF_ENTRY1, 140, 51, 103, 10,
|
||||
WC_ENTRYFIELD, ES_MARGIN | ES_AUTOSCROLL |
|
||||
WS_TABSTOP | WS_VISIBLE | WS_DISABLED
|
||||
CTLDATA 8, 1023, 0, 0
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "On/Off", CB_ONOFF1, 140, 21, 38, 10, WC_BUTTON,
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP |
|
||||
WS_VISIBLE | WS_DISABLED
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
END
|
||||
END
|
||||
|
||||
DLGTEMPLATE NBKP_SETS2
|
||||
BEGIN
|
||||
DIALOG "", NBKP_SETS2, 0, 0, 275, 74, FS_NOBYTEALIGN | NOT FS_DLGBORDER
|
||||
PRESPARAMS PP_USER, "9.WarpSans Bold"
|
||||
BEGIN
|
||||
CONTROL "", SETS2, 10, 12, 113, 58, WC_LISTBOX,
|
||||
LS_NOADJUSTPOS | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Entry", EF_ENTRY2, 140, 51, 103, 10,
|
||||
WC_ENTRYFIELD, ES_MARGIN | ES_AUTOSCROLL |
|
||||
WS_TABSTOP | WS_VISIBLE | WS_DISABLED
|
||||
CTLDATA 8, 1023, 0, 0
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "On/Off", CB_ONOFF2, 140, 21, 38, 10, WC_BUTTON,
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP |
|
||||
WS_VISIBLE | WS_DISABLED
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
END
|
||||
END
|
||||
|
||||
DLGTEMPLATE NBKP_SETS3
|
||||
BEGIN
|
||||
DIALOG "", NBKP_SETS3, 0, 0, 275, 74, FS_NOBYTEALIGN | NOT FS_DLGBORDER
|
||||
PRESPARAMS PP_USER, "9.WarpSans Bold"
|
||||
BEGIN
|
||||
CONTROL "", SETS3, 10, 12, 113, 58, WC_LISTBOX,
|
||||
LS_NOADJUSTPOS | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Entry", EF_ENTRY3, 140, 51, 103, 10,
|
||||
WC_ENTRYFIELD, ES_MARGIN | ES_AUTOSCROLL |
|
||||
WS_TABSTOP | WS_VISIBLE | WS_DISABLED
|
||||
CTLDATA 8, 1023, 0, 0
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "On/Off", CB_ONOFF3, 140, 21, 38, 10, WC_BUTTON,
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP |
|
||||
WS_VISIBLE | WS_DISABLED
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
END
|
||||
END
|
||||
|
||||
DLGTEMPLATE NBKP_SETS4
|
||||
BEGIN
|
||||
DIALOG "", NBKP_SETS4, 0, 0, 275, 74, FS_NOBYTEALIGN | NOT FS_DLGBORDER
|
||||
PRESPARAMS PP_USER, "9.WarpSans Bold"
|
||||
BEGIN
|
||||
CONTROL "", SETS4, 10, 12, 113, 58, WC_LISTBOX,
|
||||
LS_NOADJUSTPOS | WS_VISIBLE
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Entry", EF_ENTRY4, 140, 51, 103, 10,
|
||||
WC_ENTRYFIELD, ES_MARGIN | ES_AUTOSCROLL |
|
||||
WS_TABSTOP | WS_VISIBLE | WS_DISABLED
|
||||
CTLDATA 8, 1023, 0, 0
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "On/Off", CB_ONOFF4, 140, 21, 38, 10, WC_BUTTON,
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP |
|
||||
WS_VISIBLE | WS_DISABLED
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
END
|
||||
END
|
||||
|
||||
DLGTEMPLATE NBKP_OSSETTINGS
|
||||
BEGIN
|
||||
DIALOG "", NBKP_OSSETTINGS, 0, 0, 275, 74, FS_NOBYTEALIGN |
|
||||
NOT FS_DLGBORDER
|
||||
PRESPARAMS PP_USER, "9.WarpSans Bold"
|
||||
BEGIN
|
||||
CONTROL "Long Filenames", CB_LFN, 20, 58, 97, 10, WC_BUTTON,
|
||||
BS_CHECKBOX | WS_TABSTOP |
|
||||
WS_VISIBLE | WS_DISABLED
|
||||
PRESPARAMS PP_FONTNAMESIZE, "9.WarpSans"
|
||||
CONTROL "Sound", CB_SOUND, 20, 45, 54, 10, WC_BUTTON,
|
||||
BS_CHECKBOX | WS_TABSTOP |
|
||||
WS_VISIBLE | WS_DISABLED
|
||||
END
|
||||
END
|
||||
363
source/queue.c
Normal file
363
source/queue.c
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* queue.c - The queue command
|
||||
*
|
||||
* Queues allow for future batch processing
|
||||
*
|
||||
* Syntax: /QUEUE -DO -SHOW -LIST -NO_FLUSH -DELETE -FLUSH <name> {commands}
|
||||
*
|
||||
* Written by Jeremy Nelson (nelson@cs.uwp.edu) (ESL)
|
||||
*
|
||||
* Copyright (C) 1993. See the copyright file and all that rot
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: queue.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(queue_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "alias.h"
|
||||
#include "commands.h"
|
||||
#include "ircaux.h"
|
||||
#include "queue.h"
|
||||
#include "output.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
extern char *next_expr (char **, char);
|
||||
|
||||
struct CmdListT;
|
||||
struct QueueT {
|
||||
struct QueueT *next;
|
||||
struct CmdListT *first;
|
||||
char *name;
|
||||
};
|
||||
struct CmdListT {
|
||||
struct CmdListT *next;
|
||||
char *what;
|
||||
};
|
||||
typedef struct QueueT Queue;
|
||||
typedef struct CmdListT CmdList;
|
||||
|
||||
static Queue *lookup_queue (Queue *, char *);
|
||||
static int add_commands_to_queue (Queue *, char *, char *);
|
||||
static void display_all_queues (Queue *);
|
||||
static CmdList *walk_commands (Queue *);
|
||||
static Queue *make_new_queue (Queue *, char *);
|
||||
static int delete_commands_from_queue (Queue *, int);
|
||||
static void flush_queue (Queue *);
|
||||
static void print_queue (Queue *);
|
||||
static int num_entries (Queue *);
|
||||
static Queue *remove_a_queue (Queue *);
|
||||
static Queue *do_queue (Queue *, int);
|
||||
|
||||
BUILT_IN_COMMAND(queuecmd)
|
||||
{
|
||||
Queue *tmp;
|
||||
char *arg = NULL,
|
||||
*name = NULL,
|
||||
*startcmds = NULL,
|
||||
*cmds = NULL;
|
||||
int noflush = 0, runit = 0,
|
||||
list = 0,
|
||||
flush = 0, remove_by_number = 0,
|
||||
commands = 1, number = 0;
|
||||
static Queue *Queuelist;
|
||||
|
||||
/*
|
||||
* If the queue list is empty, make an entry
|
||||
* Some OS's barf on writing to static strings...
|
||||
* I wish ultrix wasnt so darn forgiving...
|
||||
*/
|
||||
char this_sucks[4];
|
||||
strcpy(this_sucks,"Top");
|
||||
if (Queuelist == NULL)
|
||||
Queuelist = make_new_queue(NULL, this_sucks);
|
||||
|
||||
if ((startcmds = strchr(args, '{')) == NULL)
|
||||
commands = 0;
|
||||
else
|
||||
*(startcmds-1) = '\0';
|
||||
|
||||
while ((arg = upper(next_arg(args, &args))) != NULL)
|
||||
{
|
||||
if (*arg == '-' || *arg == '/')
|
||||
{
|
||||
*arg++ = '\0';
|
||||
if (!strcmp(arg, "NO_FLUSH"))
|
||||
noflush = 1;
|
||||
else if (!strcmp(arg, "SHOW"))
|
||||
{
|
||||
display_all_queues(Queuelist);
|
||||
return;
|
||||
}
|
||||
else if (!strcmp(arg, "LIST"))
|
||||
list = 1;
|
||||
else if (!strcmp(arg, "DO"))
|
||||
runit = 1;
|
||||
else if (!strcmp(arg, "DELETE"))
|
||||
remove_by_number = 1;
|
||||
else if (!strcmp(arg, "FLUSH"))
|
||||
flush = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name)
|
||||
number = atoi(arg);
|
||||
else
|
||||
name = arg;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
return;
|
||||
|
||||
/* Find the queue based upon the previous queue */
|
||||
tmp = lookup_queue(Queuelist, name);
|
||||
|
||||
/* if the next queue is empty, then we need to see if
|
||||
we should make it or output an error */
|
||||
if ((tmp->next) == NULL)
|
||||
{
|
||||
if (commands)
|
||||
tmp->next = make_new_queue(NULL, name);
|
||||
else
|
||||
{
|
||||
yell ("QUEUE: (%s) no such queue",name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (remove_by_number == 1)
|
||||
if (delete_commands_from_queue(tmp->next,number))
|
||||
tmp->next = remove_a_queue(tmp->next);
|
||||
|
||||
if (list == 1)
|
||||
print_queue(tmp->next);
|
||||
if (runit == 1)
|
||||
tmp->next = do_queue(tmp->next, noflush);
|
||||
if (flush == 1)
|
||||
tmp->next = remove_a_queue(tmp->next);
|
||||
|
||||
if (startcmds)
|
||||
{
|
||||
int booya;
|
||||
|
||||
if ((cmds = next_expr(&startcmds, '{')) == NULL)
|
||||
{
|
||||
yell ("QUEUE: missing closing brace");
|
||||
return;
|
||||
}
|
||||
booya = add_commands_to_queue (tmp->next, cmds, subargs);
|
||||
say ("QUEUED: %s now has %d entries",name, booya);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the queue BEFORE the queue we are looking for
|
||||
* returns the last queue if no match
|
||||
*/
|
||||
static Queue * lookup_queue (Queue *queue, char *what)
|
||||
{
|
||||
Queue *tmp = queue;
|
||||
|
||||
upper(what);
|
||||
|
||||
while (tmp->next)
|
||||
{
|
||||
if (!strcmp(tmp->next->name, what))
|
||||
return tmp;
|
||||
else
|
||||
if (tmp->next)
|
||||
tmp = tmp->next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* returns the last CmdList in a queue, useful for appending commands */
|
||||
static CmdList *walk_commands (Queue *queue)
|
||||
{
|
||||
CmdList *ctmp = queue->first;
|
||||
|
||||
if (ctmp)
|
||||
{
|
||||
while (ctmp->next)
|
||||
ctmp = ctmp->next;
|
||||
return ctmp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
/* Make a new queue, link it in, and return it. */
|
||||
static Queue *make_new_queue (Queue *afterqueue, char *name)
|
||||
{
|
||||
Queue *tmp = (Queue *)new_malloc(sizeof(Queue));
|
||||
|
||||
upper(name);
|
||||
|
||||
tmp->next = afterqueue;
|
||||
tmp->first = NULL;
|
||||
tmp->name = NULL;
|
||||
malloc_strcpy(&tmp->name, name);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* add a command to a queue, at the end of the list */
|
||||
/* expands the whole thing once and stores it */
|
||||
static int add_commands_to_queue (Queue *queue, char *what, char *subargs)
|
||||
{
|
||||
CmdList *ctmp = walk_commands(queue);
|
||||
char *list = NULL,
|
||||
*sa;
|
||||
int args_flag = 0;
|
||||
|
||||
sa = subargs ? subargs : space;
|
||||
list = expand_alias(what,sa,&args_flag, NULL);
|
||||
if (!ctmp)
|
||||
{
|
||||
queue->first = (CmdList *)new_malloc(sizeof(CmdList));
|
||||
ctmp = queue->first;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctmp->next = (CmdList *)new_malloc(sizeof(CmdList));
|
||||
ctmp = ctmp->next;
|
||||
}
|
||||
ctmp->what = NULL;
|
||||
malloc_strcpy(&ctmp->what, list);
|
||||
ctmp->next = NULL;
|
||||
new_free(&list);
|
||||
return num_entries(queue);
|
||||
}
|
||||
|
||||
|
||||
/* remove the Xth command from the queue */
|
||||
static int delete_commands_from_queue (Queue *queue, int which)
|
||||
{
|
||||
CmdList *ctmp = queue->first;
|
||||
CmdList *blah;
|
||||
int x;
|
||||
|
||||
if (which == 1)
|
||||
queue->first = ctmp->next;
|
||||
else
|
||||
{
|
||||
for (x=1;x<which-1;x++)
|
||||
{
|
||||
if (ctmp->next)
|
||||
ctmp = ctmp->next;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
blah = ctmp->next;
|
||||
ctmp->next = ctmp->next->next;
|
||||
ctmp = blah;
|
||||
}
|
||||
new_free(&ctmp->what);
|
||||
new_free((char **)&ctmp);
|
||||
if (queue->first == NULL)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* flush a queue, deallocate the memory, and return the next in line */
|
||||
static Queue *remove_a_queue (Queue *queue)
|
||||
{
|
||||
Queue *tmp;
|
||||
tmp = queue->next;
|
||||
flush_queue(queue);
|
||||
new_free((char **)&queue);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* walk through a queue, deallocating the entries */
|
||||
static void flush_queue (Queue *queue)
|
||||
{
|
||||
CmdList *tmp, *tmp2;
|
||||
tmp = queue->first;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
tmp2 = tmp;
|
||||
tmp = tmp2->next;
|
||||
if (tmp2->what != NULL)
|
||||
new_free(&tmp2->what);
|
||||
if (tmp2)
|
||||
new_free((char **)&tmp2);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* run the queue, and if noflush, then return the queue, else return the
|
||||
next queue */
|
||||
static Queue *do_queue (Queue *queue, int noflush)
|
||||
{
|
||||
CmdList *tmp;
|
||||
|
||||
tmp = queue->first;
|
||||
|
||||
do
|
||||
{
|
||||
if (tmp->what != NULL)
|
||||
parse_line("QUEUE", tmp->what, empty_string, 0, 0, 1);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
while (tmp != NULL);
|
||||
|
||||
if (!noflush)
|
||||
return remove_a_queue(queue);
|
||||
else
|
||||
return queue;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* output the contents of all the queues to the screen */
|
||||
static void display_all_queues (Queue *queue)
|
||||
{
|
||||
Queue *tmp = queue->next;
|
||||
while (tmp)
|
||||
{
|
||||
print_queue(tmp);
|
||||
if (tmp->next == NULL)
|
||||
return;
|
||||
else
|
||||
tmp = tmp->next;
|
||||
}
|
||||
yell("QUEUE: No more queues");
|
||||
}
|
||||
|
||||
/* output the contents of a queue to the screen */
|
||||
static void print_queue (Queue *queue)
|
||||
{
|
||||
CmdList *tmp;
|
||||
int x = 0;
|
||||
|
||||
tmp = queue->first;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (tmp->what)
|
||||
say ("<%s:%2d> %s",queue->name,++x,tmp->what);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
say ("<%s> End of queue",queue->name);
|
||||
}
|
||||
|
||||
/* return the number of entries in a queue */
|
||||
static int num_entries (Queue *queue)
|
||||
{
|
||||
int x = 1;
|
||||
CmdList *tmp;
|
||||
|
||||
if ((tmp = queue->first) == NULL)
|
||||
return 0;
|
||||
while (tmp->next)
|
||||
{
|
||||
x++;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
241
source/readlog.c
Normal file
241
source/readlog.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright Colten Edwards 1996
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: readlog.c,v 1.1.1.2 2003/05/17 07:00:23 root Exp $";
|
||||
CVS_REVISION(readlog_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "ircterm.h"
|
||||
#include "server.h"
|
||||
#include "vars.h"
|
||||
#include "ircaux.h"
|
||||
#include "input.h"
|
||||
#include "window.h"
|
||||
#include "screen.h"
|
||||
#include "output.h"
|
||||
#include "status.h"
|
||||
#include "misc.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
#ifdef WANT_HEBREW
|
||||
#include "hebrew.h"
|
||||
#endif
|
||||
|
||||
FILE * msg_fp = NULL;
|
||||
|
||||
static Window *msg_window = NULL;
|
||||
static int finished_msg_paging = 0;
|
||||
static Screen *msg_screen = NULL;
|
||||
static int use_msg_window = 0;
|
||||
static void log_prompt (char *name, char *line);
|
||||
static void set_msg_screen (Screen *);
|
||||
static char *(*read_log_func) (char *, int, FILE *);
|
||||
void log_put_it(const char *topic, const char *format, ...);
|
||||
|
||||
BUILT_IN_COMMAND(remove_log)
|
||||
{
|
||||
char *expand;
|
||||
char *filename = NULL;
|
||||
int old_display = window_display;
|
||||
|
||||
int reset_logptr = 0;
|
||||
|
||||
if ((get_string_var(MSGLOGFILE_VAR) == NULL) || (get_string_var(CTOOLZ_DIR_VAR) == NULL))
|
||||
return;
|
||||
malloc_sprintf(&filename, "%s/%s", get_string_var(CTOOLZ_DIR_VAR), get_string_var(MSGLOGFILE_VAR));
|
||||
expand = expand_twiddle(filename);
|
||||
new_free(&filename);
|
||||
window_display = 0;
|
||||
reset_logptr = logmsg(LOG_CURRENT, NULL, 3, NULL);
|
||||
log_toggle(0, NULL);
|
||||
window_display = old_display;
|
||||
if (unlink(expand))
|
||||
{
|
||||
bitchsay("Error unlinking: %s", expand);
|
||||
new_free(&expand);
|
||||
return;
|
||||
}
|
||||
window_display = 0;
|
||||
set_int_var(MSGCOUNT_VAR, 0);
|
||||
if (reset_logptr)
|
||||
log_toggle(1, NULL);
|
||||
window_display = old_display;
|
||||
bitchsay("Removed %s.", expand);
|
||||
status_update(1);
|
||||
new_free(&expand);
|
||||
}
|
||||
|
||||
static int in_read_log = 0;
|
||||
|
||||
BUILT_IN_COMMAND(readlog)
|
||||
{
|
||||
char *expand;
|
||||
struct stat stat_buf;
|
||||
char *filename = NULL;
|
||||
char buffer[BIG_BUFFER_SIZE + 1];
|
||||
|
||||
read_log_func = fgets;
|
||||
if (!get_string_var(MSGLOGFILE_VAR))
|
||||
if (!args || (args && !*args))
|
||||
return;
|
||||
if (msg_window)
|
||||
return;
|
||||
|
||||
if (command)
|
||||
{
|
||||
in_read_log = 1;
|
||||
if (my_stricmp(command, "MORE"))
|
||||
{
|
||||
if (args && !my_strnicmp(args, "-resume", 2))
|
||||
{
|
||||
next_arg(args, &args);
|
||||
read_log_func = (char *(*)(char *, int, FILE *))global[RFGETS];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (args && *args)
|
||||
malloc_sprintf(&filename, "%s", args);
|
||||
else
|
||||
malloc_sprintf(&filename, "%s/%s", get_string_var(CTOOLZ_DIR_VAR), get_string_var(MSGLOGFILE_VAR));
|
||||
|
||||
expand = expand_twiddle(filename);
|
||||
new_free(&filename);
|
||||
stat(expand, &stat_buf);
|
||||
strcpy(buffer, expand);
|
||||
|
||||
if (stat_buf.st_mode & S_IFDIR)
|
||||
return;
|
||||
|
||||
if ((msg_fp = fopen(expand, "r")) == NULL)
|
||||
{
|
||||
log_put_it(expand, "%s Error Opening Log file %s", thing_ansi, expand);
|
||||
new_free(&expand);
|
||||
msg_fp = NULL;
|
||||
return;
|
||||
}
|
||||
if (read_log_func == (char *(*)(char *, int, FILE *))global[RFGETS])
|
||||
fseek(msg_fp, 0, SEEK_END);
|
||||
new_free(&expand);
|
||||
msg_window = current_window;
|
||||
msg_screen = current_window->screen;
|
||||
log_prompt(buffer, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* show_help: show's either a page of text from a help_fp, or the whole
|
||||
* thing, depending on the value of HELP_PAGER_VAR. If it gets to the end,
|
||||
* (in either case it will eventally), it closes the file, and returns 0
|
||||
* to indicate this.
|
||||
*/
|
||||
static int show_log(Window *window, char *name)
|
||||
{
|
||||
Window *old_window;
|
||||
int rows = 0;
|
||||
char line[500];
|
||||
|
||||
if (window)
|
||||
{
|
||||
old_window = current_window;
|
||||
current_window = window;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_window = NULL;
|
||||
window = current_window;
|
||||
}
|
||||
if (get_int_var(HELP_PAGER_VAR))
|
||||
rows = window->display_size - (window->double_status + 2);
|
||||
while (--rows)
|
||||
{
|
||||
if ((*read_log_func)(line, 499, msg_fp))
|
||||
{
|
||||
if (*(line + strlen(line) - 1) == '\n')
|
||||
*(line + strlen(line) - 1) = (char) 0;
|
||||
#ifdef WANT_HEBREW
|
||||
if (get_int_var(HEBREW_TOGGLE_VAR))
|
||||
hebrew_process(line);
|
||||
#endif
|
||||
log_put_it(name, "%s", line);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msg_fp) fclose(msg_fp);
|
||||
set_msg_screen(NULL);
|
||||
msg_fp = NULL;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void remove_away_log(char *stuff, char *line)
|
||||
{
|
||||
if ((line && toupper(*line) == 'Y'))
|
||||
remove_log(NULL, NULL, NULL, NULL);
|
||||
in_read_log = 0;
|
||||
}
|
||||
|
||||
static void set_msg_screen(Screen *screen)
|
||||
{
|
||||
msg_screen = screen;
|
||||
if (!msg_screen && msg_window)
|
||||
{
|
||||
if (use_msg_window)
|
||||
{
|
||||
int display = window_display;
|
||||
|
||||
window_display = 0;
|
||||
delete_window(msg_window);
|
||||
window_display = display;
|
||||
}
|
||||
msg_window = NULL;
|
||||
update_all_windows();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* log_prompt: The main procedure called to display the log file
|
||||
* currently being accessed. Using add_wait_prompt(), it sets it
|
||||
* self up to be recalled when the next page is asked for. If
|
||||
* called when we have finished paging the log file, we exit, as
|
||||
* there is nothing left to show. If line is 'q' or 'Q', exit the
|
||||
* log pager, clean up, etc.. If all is cool for now, we call
|
||||
* show_help, and either if its finished, exit, or prompt for the
|
||||
* next page.
|
||||
*/
|
||||
|
||||
static void log_prompt(char *name, char *line)
|
||||
{
|
||||
|
||||
if (line && *line && (toupper(*line) == 'Q'))
|
||||
{
|
||||
finished_msg_paging = 1;
|
||||
if (msg_fp)
|
||||
fclose(msg_fp);
|
||||
msg_fp = NULL;
|
||||
set_msg_screen(NULL);
|
||||
if (!in_read_log)
|
||||
add_wait_prompt("Delete msg log [y/N]? ", remove_away_log, empty_string, WAIT_PROMPT_LINE,1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (show_log(msg_window, name))
|
||||
{
|
||||
add_wait_prompt("*** Hit any key for more, 'q' to quit ***",
|
||||
log_prompt, name, WAIT_PROMPT_KEY,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msg_fp)
|
||||
fclose(msg_fp);
|
||||
set_msg_screen(NULL);
|
||||
msg_fp = NULL;
|
||||
if (!in_read_log)
|
||||
add_wait_prompt("Delete msg log [y/N]? ", remove_away_log, empty_string, WAIT_PROMPT_LINE,1);
|
||||
}
|
||||
}
|
||||
|
||||
478
source/reg.c
Normal file
478
source/reg.c
Normal file
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* The original was spagetti. I have replaced Michael's code with some of
|
||||
* my own which is a thousand times more readable and can also handle '%',
|
||||
* which substitutes anything except a space. This should enable people
|
||||
* to position things better based on argument. I have also added '?', which
|
||||
* substitutes to any single character. And of course it still handles '*'.
|
||||
* this should be more efficient than the previous version too.
|
||||
*
|
||||
* Thus this whole file becomes:
|
||||
*
|
||||
* Written By Troy Rollo
|
||||
* Copyright(c) 1992
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: reg.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(reg_c)
|
||||
#include "ircaux.h"
|
||||
#include "output.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
/*
|
||||
* The following #define is here because we *know* its behaviour.
|
||||
* The behaviour of toupper tends to be undefined when it's given
|
||||
* a non lower case letter.
|
||||
* All the systems supported by IRCII should be ASCII
|
||||
*/
|
||||
#define mkupper(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 'a' + 'A') : c)
|
||||
|
||||
#if 0
|
||||
int old_match(const char *pattern, const char *string)
|
||||
{
|
||||
char type = 0;
|
||||
|
||||
while (*string && *pattern && *pattern != '*' && *pattern != '%')
|
||||
{
|
||||
if (*pattern == '\\' && pattern[1])
|
||||
{
|
||||
if (!*++pattern || !(mkupper(*pattern) == mkupper(*string)))
|
||||
return 0;
|
||||
else
|
||||
pattern++, string++, total_explicit++;
|
||||
continue; /* Erf! try $match(\\* *) */
|
||||
}
|
||||
|
||||
if (*pattern == '?')
|
||||
pattern++, string++;
|
||||
else if (mkupper(*pattern) == mkupper(*string))
|
||||
pattern++, string++, total_explicit++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (*pattern == '*' || *pattern == '%')
|
||||
{
|
||||
type = (*pattern++);
|
||||
while (*string)
|
||||
{
|
||||
if (old_match(pattern, string))
|
||||
return 1;
|
||||
else if (type == '*' || *string != ' ')
|
||||
string++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Slurp up any trailing *'s or %'s... */
|
||||
if (!*string && (type == '*' || type == '%'))
|
||||
while (*pattern && (*pattern == '*' || *pattern == '%'))
|
||||
pattern++;
|
||||
|
||||
if (!*string && !*pattern)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int new_match (const unsigned char *pattern, const unsigned char *string)
|
||||
{
|
||||
int count = 1;
|
||||
int asterisk = 0;
|
||||
int percent = 0;
|
||||
const char *last_asterisk_point = NULL;
|
||||
const char *last_percent_point = NULL;
|
||||
int last_asterisk_count = 0;
|
||||
int last_percent_count = 0;
|
||||
const char *after_wildcard = NULL;
|
||||
int sanity = 0;
|
||||
const char *old_pattern = pattern, *old_string = string;
|
||||
if (x_debug & DEBUG_REGEX_DEBUG)
|
||||
yell("Matching [%s] against [%s]", pattern, string);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (sanity++ > 100000)
|
||||
{
|
||||
yell("Infinite loop in match! pattern = [%s] string = [%s]", old_pattern, old_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the last character in the pattern was a *, then
|
||||
* we walk the string until we find the next instance int
|
||||
* string, of the character that was after the *.
|
||||
* If we get to the end of string, then obviously there
|
||||
* is no match. A * at the end of the pattern is handled
|
||||
* especially, so we dont need to consider that.
|
||||
*/
|
||||
if (asterisk)
|
||||
{
|
||||
/*
|
||||
* More pattern, no source. Obviously this
|
||||
* asterisk isnt going to cut it. Try again.
|
||||
* This replaces an 'always failure' case.
|
||||
* In 99% of the cases, we will try again and it
|
||||
* will fail anyhow, but 1% of the cases it would
|
||||
* have succeeded, so we need that retry.
|
||||
*/
|
||||
if (!*string)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* XXXX Skip over any backslashes...
|
||||
*/
|
||||
if (*pattern == '\\')
|
||||
{
|
||||
pattern++;
|
||||
if (tolower(*string) != tolower(*pattern))
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the character in the pattern immediately
|
||||
* following the asterisk is a qmark, then we
|
||||
* save where we're at and we allow the ? to be
|
||||
* matched. If we find it doesnt work later on,
|
||||
* then we will come back to here and try again.
|
||||
* OR
|
||||
* We've found the character we're looking for!
|
||||
* Save some state information about how to recover
|
||||
* if we dont match
|
||||
*/
|
||||
else if (*pattern == '?' ||
|
||||
(tolower(*string) == tolower(*pattern)))
|
||||
{
|
||||
asterisk = 0;
|
||||
last_asterisk_point = string;
|
||||
last_asterisk_count = count;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is not the character we're looking for.
|
||||
*/
|
||||
else
|
||||
string++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok. If we're dealing with a percent, but not a asterisk,
|
||||
* then we need to look for the character after the percent.
|
||||
* BUT, if we find a space, then we stop anyways.
|
||||
*/
|
||||
if (percent)
|
||||
{
|
||||
/*
|
||||
* Ran out of string. If there is more to the
|
||||
* pattern, then we failed. Otherwise if the %
|
||||
* was at the end of the pattern, we havent found
|
||||
* a space, so it succeeds!
|
||||
*/
|
||||
if (!*string)
|
||||
{
|
||||
if (*pattern)
|
||||
return 0;
|
||||
else
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXX Skip over any backslashes...
|
||||
*/
|
||||
if (*pattern == '\\')
|
||||
{
|
||||
pattern++;
|
||||
if (tolower(*string) != tolower(*pattern))
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we find a space, then we stop looking at the
|
||||
* percent. We're definitely done with it. We also
|
||||
* go back to normal parsing mode, presumably with
|
||||
* the space after the %.
|
||||
*/
|
||||
if (*string == ' ')
|
||||
{
|
||||
percent = 0;
|
||||
last_percent_point = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is not the char we're looking for, then
|
||||
* keep looking.
|
||||
*/
|
||||
else if (tolower(*string) != tolower(*pattern))
|
||||
string++;
|
||||
|
||||
/*
|
||||
* We found it! Huzzah!
|
||||
*/
|
||||
else
|
||||
{
|
||||
percent = 0;
|
||||
last_percent_point = string;
|
||||
last_percent_count = count;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ok. So at this point, we know we're not handling an
|
||||
* outstanding asterisk or percent request. So we look
|
||||
* to see what the next char is in the pattern and deal
|
||||
* with it.
|
||||
*/
|
||||
switch (*pattern)
|
||||
{
|
||||
|
||||
/*
|
||||
* If its an asterisk, then we just keep some info about
|
||||
* where we're at.
|
||||
*/
|
||||
case ('*') : case ('%') :
|
||||
{
|
||||
asterisk = 0, percent = 0;
|
||||
do
|
||||
{
|
||||
if (*pattern == '*')
|
||||
asterisk = 1;
|
||||
pattern++;
|
||||
}
|
||||
while (*pattern == '*' || *pattern == '%');
|
||||
|
||||
after_wildcard = pattern;
|
||||
if (asterisk)
|
||||
{
|
||||
last_asterisk_point = string;
|
||||
last_asterisk_count = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
percent = 1;
|
||||
last_percent_point = string;
|
||||
last_percent_count = count;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's nothing in the pattern after the
|
||||
* asterisk, then it slurps up the rest of string,
|
||||
* and we're definitely done!
|
||||
*/
|
||||
if (asterisk && !*pattern)
|
||||
return count;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If its a question mark, then we have to slurp up one
|
||||
* character from the pattern and the string.
|
||||
*/
|
||||
case ('?') :
|
||||
{
|
||||
pattern++;
|
||||
|
||||
/*
|
||||
* If there is nothing left in string, then we
|
||||
* definitely fail.
|
||||
*/
|
||||
if (!*string)
|
||||
return 0;
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* De-quote any \'s in the pattern.
|
||||
*/
|
||||
case ('\\') :
|
||||
{
|
||||
/*
|
||||
* ircII says that a single \ at the end of a pattern
|
||||
* is defined as a failure. (must quote SOMETHING)
|
||||
*/
|
||||
pattern++;
|
||||
if (!*pattern)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check to see if the dequoted character and
|
||||
* the next string character are the same.
|
||||
*/
|
||||
if (tolower(*pattern) != tolower(*string))
|
||||
return 0;
|
||||
|
||||
count++, string++, pattern++;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is nothing left in the pattern and string,
|
||||
* then we've definitely succeeded. Return the number of
|
||||
* non-wildcard characters.
|
||||
*/
|
||||
default:
|
||||
{
|
||||
if (!*pattern && !*string)
|
||||
return count;
|
||||
|
||||
/*
|
||||
* There are regular characters next in the pattern
|
||||
* and string. Are they the same? If they are, walk
|
||||
* past them and go to the next character.
|
||||
*/
|
||||
if (tolower(*pattern) == tolower(*string))
|
||||
{
|
||||
count++, pattern++, string++;
|
||||
}
|
||||
|
||||
/*
|
||||
* The two characters are not the same. If we're
|
||||
* currently trying to match a wildcard, go back to
|
||||
* where we started after the wildcard and try looking
|
||||
* again from there. If we are not currently matching
|
||||
* a wildcard, then the entire match definitely fails.
|
||||
*/
|
||||
else if (last_asterisk_point)
|
||||
{
|
||||
asterisk = 1;
|
||||
string = last_asterisk_point + 1;
|
||||
pattern = after_wildcard;
|
||||
count = last_asterisk_count;
|
||||
}
|
||||
else if (last_percent_point)
|
||||
{
|
||||
percent = 1;
|
||||
string = last_percent_point + 1;
|
||||
pattern = after_wildcard;
|
||||
count = last_percent_count;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* wild_match: calculate the "value" of str when matched against pattern.
|
||||
* The "value" of a string is always zero if it is not matched by the pattern.
|
||||
* In all cases where the string is matched by the pattern, then the "value"
|
||||
* of the match is 1 plus the number of non-wildcard characters in "str".
|
||||
*
|
||||
* \\[ and \\] handling done by Jeremy Nelson
|
||||
*/
|
||||
int BX_wild_match (register const unsigned char *p, register const unsigned char *str)
|
||||
{
|
||||
/*
|
||||
* Is there a \[ in the pattern to be expanded?
|
||||
*
|
||||
* This stuff here just reduces the \[ \] set into a series of
|
||||
* one-simpler patterns and then recurses over the options.
|
||||
*/
|
||||
if (strstr(p, "\\["))
|
||||
{
|
||||
char *pattern, *ptr, *ptr2, *arg, *placeholder;
|
||||
int nest = 0;
|
||||
|
||||
/*
|
||||
* Only make the copy if we're going to be tearing it apart.
|
||||
*/
|
||||
pattern = LOCAL_COPY(p);
|
||||
|
||||
/*
|
||||
* We will have to null this out, but not until we've used it
|
||||
*/
|
||||
placeholder = ptr = ptr2 = strstr(pattern, "\\[");
|
||||
|
||||
/*
|
||||
* Look for the matching \].
|
||||
*/
|
||||
do
|
||||
{
|
||||
switch (ptr[1])
|
||||
{
|
||||
/* step over it and add to nest */
|
||||
case '[' : ptr2 = ptr + 2 ;
|
||||
nest++;
|
||||
break;
|
||||
/* step over it and remove nest */
|
||||
case ']' : ptr2 = ptr + 2;
|
||||
nest--;
|
||||
break;
|
||||
default:
|
||||
ptr2 = ptr + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (nest && (ptr = strchr(ptr2, '\\')));
|
||||
|
||||
/*
|
||||
* Right now, we know that ptr points to a \] or to a NULL.
|
||||
* Remember that '&&' short circuits and that ptr will
|
||||
* not be set to NULL if (nest) is zero.
|
||||
*/
|
||||
if (ptr)
|
||||
{
|
||||
int best_total = 0;
|
||||
|
||||
*ptr = 0;
|
||||
ptr += 2;
|
||||
*placeholder = 0;
|
||||
placeholder += 2;
|
||||
|
||||
/*
|
||||
* grab words ("" sets or space words) one at a time
|
||||
* and attempt to match all of them. The best value
|
||||
* matched is the one used.
|
||||
*/
|
||||
while ((arg = new_next_arg(placeholder, &placeholder)))
|
||||
{
|
||||
int tmpval;
|
||||
char my_buff[BIG_BUFFER_SIZE + 1];
|
||||
|
||||
strlcpy(my_buff, pattern, BIG_BUFFER_SIZE);
|
||||
strlcat(my_buff, arg, BIG_BUFFER_SIZE);
|
||||
strlcat(my_buff, ptr, BIG_BUFFER_SIZE);
|
||||
|
||||
/*
|
||||
* The total_explicit we return is whatever
|
||||
* sub-pattern has the highest total_explicit
|
||||
*/
|
||||
if ((tmpval = wild_match(my_buff, str)))
|
||||
{
|
||||
if (tmpval > best_total)
|
||||
best_total = tmpval;
|
||||
}
|
||||
}
|
||||
|
||||
return best_total; /* end of expansion section */
|
||||
}
|
||||
|
||||
/*
|
||||
* Possibly an unmatched \[ \] set. Just wing it.
|
||||
*/
|
||||
else
|
||||
return new_match(pattern, str);
|
||||
}
|
||||
|
||||
/*
|
||||
* Trivial case -- No \[ \] sets, just do the match.
|
||||
*/
|
||||
else
|
||||
return new_match(p, str);
|
||||
}
|
||||
|
||||
649
source/scr-bx.c
Normal file
649
source/scr-bx.c
Normal file
@@ -0,0 +1,649 @@
|
||||
|
||||
/*
|
||||
* Copyright Colten Edwards (July 1/1998).
|
||||
* This code is for the purpose of re-attaching to a detached BitchX session.
|
||||
* The idea for this program was by kasper@efnet after I mentioned the trouble
|
||||
* I was having reconnecting to a detached terminal.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Version 1.0 released with BitchX 75
|
||||
* $Id: scr-bx.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
#include "struct.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#ifdef USING_CURSES
|
||||
#include <curses.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "ircterm.h"
|
||||
#include "screen.h"
|
||||
#include "ircaux.h"
|
||||
|
||||
#if defined(_ALL_SOURCE) || defined(__EMX__) || defined(__QNX__)
|
||||
#include <termios.h>
|
||||
#else
|
||||
#include <sys/termios.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
#include <dmalloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef TRANSLATE
|
||||
char translation = 0;
|
||||
unsigned char transToClient[256]; /* Server to client translation. */
|
||||
#endif
|
||||
|
||||
int dumb_mode = 0;
|
||||
int already_detached = 1;
|
||||
int do_check_pid = 0;
|
||||
char socket_path[500];
|
||||
char attach_ttyname[500];
|
||||
|
||||
|
||||
struct param
|
||||
{
|
||||
pid_t pgrp,
|
||||
pid;
|
||||
uid_t uid;
|
||||
int cols;
|
||||
int rows;
|
||||
char tty[80];
|
||||
char cookie[30];
|
||||
char password[80];
|
||||
char termid[81];
|
||||
};
|
||||
|
||||
struct param parm;
|
||||
char *old_pass = NULL;
|
||||
Screen *output_screen = NULL, *last_input_screen = NULL, *main_screen = NULL;
|
||||
char empty_string[] = "";
|
||||
int foreground = 0;
|
||||
int use_input = 1;
|
||||
int use_flow_control = 0;
|
||||
static int displays = 0;
|
||||
|
||||
#define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0))
|
||||
|
||||
#ifdef CLOAKED
|
||||
extern char proctitlestr[140];
|
||||
extern char **Argv; /* pointer to argument vector */
|
||||
extern char *LastArgv; /* end of argv */
|
||||
#endif
|
||||
|
||||
|
||||
char *n_m_strdup (const char *str, const char *module, const char *file, const int line)
|
||||
{
|
||||
char *ptr;
|
||||
if (!str)
|
||||
str = empty_string;
|
||||
ptr = (char *)malloc(strlen(str) + 1);
|
||||
return strcpy(ptr, str);
|
||||
}
|
||||
|
||||
void ircpanic(char *string, ...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int get_int_var(int var)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *ltoa (long foo)
|
||||
{
|
||||
static char buffer[BIG_BUFFER_SIZE/8+1];
|
||||
char *pos = buffer + BIG_BUFFER_SIZE/8-1;
|
||||
unsigned long absv;
|
||||
int negative;
|
||||
|
||||
absv = (foo < 0) ? (unsigned long)-foo : (unsigned long)foo;
|
||||
negative = (foo < 0) ? 1 : 0;
|
||||
|
||||
buffer[BIG_BUFFER_SIZE/8] = 0;
|
||||
for (; absv > 9; absv /= 10)
|
||||
*pos-- = (absv % 10) + '0';
|
||||
*pos = (absv) + '0';
|
||||
|
||||
if (negative)
|
||||
*--pos = '-';
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
char *lower(char *str)
|
||||
{
|
||||
register char *ptr = NULL;
|
||||
|
||||
if (str)
|
||||
{
|
||||
ptr = str;
|
||||
for (; *str; str++)
|
||||
{
|
||||
if (isupper(*str))
|
||||
*str = tolower(*str);
|
||||
}
|
||||
}
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
#ifndef HAVE_GETPASS
|
||||
char *getpass(char *);
|
||||
char *get_string_var(int var)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WINNT
|
||||
void refresh_screen(int i, char *u)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *find_tty_name(char *name)
|
||||
{
|
||||
static char tty[20];
|
||||
char *q, *s;
|
||||
*tty = 0;
|
||||
if ((q = strrchr(name, '/')))
|
||||
{
|
||||
q++;
|
||||
if ((q = strchr(q, '.')))
|
||||
{
|
||||
q++;
|
||||
if ((s = strchr(q, '.')))
|
||||
strncpy(tty, q, s-q);
|
||||
}
|
||||
}
|
||||
return tty;
|
||||
}
|
||||
|
||||
char *find_tty_path(char *name)
|
||||
{
|
||||
static char ttypath[200];
|
||||
char *q;
|
||||
*ttypath = 0;
|
||||
if ((q = strrchr(name, '/')))
|
||||
strncpy(ttypath, name, q - name);
|
||||
return ttypath;
|
||||
}
|
||||
|
||||
void display_socket_list(char *path, int unl, char *arg)
|
||||
{
|
||||
DIR *dptr;
|
||||
struct dirent *dir;
|
||||
struct stat st;
|
||||
char buffer[2000];
|
||||
char *new_path, *p;
|
||||
int count = 0;
|
||||
int doit = 0;
|
||||
|
||||
new_path = alloca(strlen(path)+1);
|
||||
strcpy(new_path, path);
|
||||
if ((p = strrchr(new_path, '/')))
|
||||
*p = 0;
|
||||
if (!(dptr = opendir(new_path)))
|
||||
{
|
||||
fprintf(stderr, "No such directory %s\r\n ", new_path);
|
||||
exit(1);
|
||||
}
|
||||
while ((dir = readdir(dptr)))
|
||||
{
|
||||
doit = 0;
|
||||
if (!dir->d_ino)
|
||||
continue;
|
||||
if (dir->d_name[0] == '.')
|
||||
continue;
|
||||
sprintf(buffer, "%s/%s", new_path, dir->d_name);
|
||||
if ((stat(buffer, &st) == -1))
|
||||
continue;
|
||||
if (arg && strstr(dir->d_name, arg))
|
||||
doit++;
|
||||
if (!count && !unl)
|
||||
fprintf(stderr, "There is more than one sockets available - \r\n");
|
||||
else if (!count)
|
||||
fprintf(stderr, "unlinking the following\r\n");
|
||||
count++;
|
||||
if (unl)
|
||||
{
|
||||
if (!((st.st_mode & 0700) == 0600) || doit)
|
||||
{
|
||||
fprintf(stderr, "%30s\r\n", dir->d_name);
|
||||
unlink(buffer);
|
||||
}
|
||||
}
|
||||
else if ((!doit && !arg) || (doit && arg))
|
||||
fprintf(stderr, "%30s %s\r\n", dir->d_name, ((st.st_mode & 0700) == 0600) ? "detached":"Attached or dead");
|
||||
}
|
||||
if (!count)
|
||||
fprintf(stderr, "No sockets to attach too\r\n");
|
||||
closedir(dptr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *find_detach_socket(char *path, char *name)
|
||||
{
|
||||
char *new_path;
|
||||
DIR *dptr;
|
||||
struct dirent *dir;
|
||||
struct stat st;
|
||||
char *ret = NULL, *p;
|
||||
int count = 0;
|
||||
new_path = alloca(strlen(path)+1);
|
||||
strcpy(new_path, path);
|
||||
if ((p = strrchr(new_path, '/')))
|
||||
*p = 0;
|
||||
else
|
||||
return NULL;
|
||||
if (!(dptr = opendir(new_path)))
|
||||
return NULL;
|
||||
ret = malloc(2000);
|
||||
*ret = 0;
|
||||
while ((dir = readdir(dptr)))
|
||||
{
|
||||
*ret = 0;
|
||||
if (!dir->d_ino)
|
||||
continue;
|
||||
if (dir->d_name[0] == '.')
|
||||
continue;
|
||||
sprintf(ret, "%s/%s", new_path, dir->d_name);
|
||||
p = strrchr(ret, '/'); p++;
|
||||
if ((stat(ret, &st) == -1) || (st.st_uid != getuid()) || S_ISDIR(st.st_mode))
|
||||
{
|
||||
*ret = 0;
|
||||
continue;
|
||||
}
|
||||
if (name)
|
||||
{
|
||||
char *pid, *n_tty, *h_name;
|
||||
pid = alloca(strlen(p)+1);
|
||||
strcpy(pid, p);
|
||||
n_tty = strchr(pid, '.'); *n_tty++ = 0;
|
||||
h_name = strchr(n_tty, '.'); *h_name++ = 0;
|
||||
if (strcmp(name, pid))
|
||||
{
|
||||
if (strcmp(n_tty, name))
|
||||
{
|
||||
if (strcmp(h_name, name))
|
||||
{
|
||||
if (strcmp(p, name))
|
||||
{
|
||||
if (!strstr(p, name))
|
||||
{
|
||||
*ret = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((st.st_mode & 0700) == 0600)
|
||||
break;
|
||||
count++;
|
||||
*ret = 0;
|
||||
}
|
||||
closedir(dptr);
|
||||
if (ret && !*ret)
|
||||
{
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
display_socket_list(path, 0, name);
|
||||
if (ret) free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void charset_ibmpc (void)
|
||||
{
|
||||
fwrite("\033(U", 3, 1, stdout); /* switch to IBM code page 437 */
|
||||
}
|
||||
|
||||
SIGNAL_HANDLER(handle_pipe)
|
||||
{
|
||||
|
||||
term_cr();
|
||||
term_clear_to_eol();
|
||||
term_reset2();
|
||||
fprintf(stdout, "\rdetached from %s. To re-attach type scr-bx %s\n\r", attach_ttyname, old_pass? "password":"");
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
SIGNAL_HANDLER(handle_hup)
|
||||
{
|
||||
term_cr();
|
||||
term_clear_to_eol();
|
||||
term_reset2();
|
||||
fprintf(stdout, "\r");
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
volatile int ctrl_c = 0;
|
||||
|
||||
SIGNAL_HANDLER(handle_ctrlc)
|
||||
{
|
||||
ctrl_c++;
|
||||
}
|
||||
|
||||
/* set's socket options */
|
||||
void set_socket_options (int s)
|
||||
{
|
||||
int opt = 1;
|
||||
int optlen = sizeof(opt);
|
||||
#ifndef NO_STRUCT_LINGER
|
||||
struct linger lin;
|
||||
|
||||
lin.l_onoff = lin.l_linger = 0;
|
||||
setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&lin, optlen);
|
||||
#endif
|
||||
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, optlen);
|
||||
opt = 1;
|
||||
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, optlen);
|
||||
}
|
||||
|
||||
|
||||
char *get_cookie(char *name)
|
||||
{
|
||||
static char cookie[80];
|
||||
FILE *fp = NULL;
|
||||
*cookie = 0;
|
||||
if ((fp = fopen(name, "r")))
|
||||
{
|
||||
fread(cookie, 40, 1, fp);
|
||||
fclose(fp);
|
||||
if (*cookie)
|
||||
cookie[strlen(cookie)-1] = 0;
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
|
||||
void reattach_tty(char *tty, char *password)
|
||||
{
|
||||
int s = -1;
|
||||
char *name;
|
||||
struct sockaddr_in addr;
|
||||
struct hostent *hp;
|
||||
int len = 0;
|
||||
fd_set rd_fd;
|
||||
struct timeval tm = {0};
|
||||
char chr_c[] = "\003";
|
||||
|
||||
/*
|
||||
* this buffer has to be big enough to handle a full screen of
|
||||
* information from the detached process.
|
||||
*/
|
||||
unsigned char buffer[6 * BIG_BUFFER_SIZE+1];
|
||||
char *p;
|
||||
int port = 0;
|
||||
#if defined (TIOCGWINSZ)
|
||||
struct winsize window;
|
||||
#endif
|
||||
memset(&parm, 0, sizeof(struct param));
|
||||
|
||||
if (!(name = find_detach_socket(socket_path, tty)))
|
||||
{
|
||||
fprintf(stderr, "No detached process to attach too\r\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
strcpy(parm.cookie, get_cookie(name));
|
||||
if (!*parm.cookie)
|
||||
_exit(1);
|
||||
if ((p = strrchr(name, '/')))
|
||||
p++;
|
||||
sscanf(p, "%d.%*s.%*s", &port);
|
||||
displays = 1;
|
||||
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
displays = 0;
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
chmod(name, SOCKMODE);
|
||||
set_socket_options(s);
|
||||
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_family = AF_INET;
|
||||
if((hp = gethostbyname("localhost")))
|
||||
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
|
||||
else
|
||||
inet_aton("127.0.0.1", (struct in_addr *)&addr.sin_addr);
|
||||
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
fprintf(stderr, "connection refused for %s\r\n", name);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
parm.pid = getpid();
|
||||
parm.pgrp = getpgrp();
|
||||
parm.uid = getuid();
|
||||
strcpy(parm.tty, ttyname(0));
|
||||
strncpy(parm.termid, getenv("TERM"), 80);
|
||||
if (password)
|
||||
strncpy(parm.password, password, 60);
|
||||
fprintf(stderr, "attempting to wakeup %s\r\n", find_tty_name(name));
|
||||
#if defined (TIOCGWINSZ)
|
||||
if (ioctl(0, TIOCGWINSZ, &window) > -1)
|
||||
{
|
||||
parm.cols = window.ws_col;
|
||||
parm.rows = window.ws_row;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
parm.cols = 79;
|
||||
parm.rows = 25;
|
||||
}
|
||||
write(s, &parm, sizeof(struct param));
|
||||
sleep(2);
|
||||
alarm(15);
|
||||
len = read(s, &parm, sizeof(struct param));
|
||||
alarm(0);
|
||||
if (len <= 0)
|
||||
{
|
||||
fprintf(stderr, "[1;37merror[0;37m reconnecting to %s\r\n", find_tty_name(name));
|
||||
displays = 0;
|
||||
chmod(name, SOCKMODE);
|
||||
exit(1);
|
||||
}
|
||||
unlink(name);
|
||||
|
||||
term_init(parm.termid);
|
||||
set_term_eight_bit(1);
|
||||
charset_ibmpc();
|
||||
term_clear_screen();
|
||||
term_resize();
|
||||
term_move_cursor(0,0);
|
||||
|
||||
my_signal(SIGPIPE, handle_pipe, 0);
|
||||
my_signal(SIGINT, handle_ctrlc, 0);
|
||||
my_signal(SIGHUP, handle_hup, 0);
|
||||
|
||||
/*
|
||||
* according to MHacker we need to set errno to 0 under BSD.
|
||||
* for some reason we get a address in use from a socket
|
||||
*
|
||||
*/
|
||||
errno = 0;
|
||||
while (1)
|
||||
{
|
||||
FD_ZERO(&rd_fd);
|
||||
FD_SET(0, &rd_fd);
|
||||
FD_SET(s, &rd_fd);
|
||||
tm.tv_sec = 2;
|
||||
|
||||
switch(select(s+1, &rd_fd, NULL, NULL, &tm))
|
||||
{
|
||||
case -1:
|
||||
if (ctrl_c)
|
||||
{
|
||||
write(s, chr_c, 1);
|
||||
ctrl_c = 0;
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
close(s);
|
||||
_exit(1);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (FD_ISSET(0, &rd_fd))
|
||||
{
|
||||
len = read(0, buffer, sizeof(buffer)-1);
|
||||
write(s, buffer, len);
|
||||
}
|
||||
if (FD_ISSET(s, &rd_fd))
|
||||
{
|
||||
len = read(s, buffer, sizeof(buffer)-1);
|
||||
write(1, buffer, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(s);
|
||||
fprintf(stderr, "Never should have got here");
|
||||
_exit(1);
|
||||
|
||||
return; /* error return */
|
||||
}
|
||||
|
||||
char *stripdev(char *ttynam)
|
||||
{
|
||||
if (ttynam == NULL)
|
||||
return NULL;
|
||||
#ifdef SVR4
|
||||
/* unixware has /dev/pts012 as synonym for /dev/pts/12 */
|
||||
if (!strncmp(ttynam, "/dev/pts", 8) && ttynam[8] >= '0' && ttynam[8] <= '9')
|
||||
{
|
||||
static char b[13];
|
||||
sprintf(b, "pts/%d", atoi(ttynam + 8));
|
||||
return b;
|
||||
}
|
||||
#endif /* SVR4 */
|
||||
if (!strncmp(ttynam, "/dev/", 5))
|
||||
return ttynam + 5;
|
||||
return ttynam;
|
||||
}
|
||||
|
||||
|
||||
void init_socketpath(void)
|
||||
{
|
||||
#if !defined(__EMX__) && !defined(WINNT)
|
||||
struct stat st;
|
||||
extern char socket_path[], attach_ttyname[];
|
||||
|
||||
sprintf(socket_path, "%s/.BitchX/screens", getenv("HOME"));
|
||||
if (access(socket_path, F_OK))
|
||||
return;
|
||||
if (stat(socket_path, &st) != -1)
|
||||
{
|
||||
char host[BIG_BUFFER_SIZE+1];
|
||||
char *ap;
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return;
|
||||
gethostname(host, BIG_BUFFER_SIZE);
|
||||
if ((ap = strchr(host, '.')))
|
||||
*ap = 0;
|
||||
ap = &socket_path[strlen(socket_path)];
|
||||
sprintf(ap, "/%%d.%s.%s", stripdev(attach_ttyname), host);
|
||||
ap++;
|
||||
for ( ; *ap; ap++)
|
||||
if (*ap == '/')
|
||||
*ap = '-';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
char *old_tty = NULL;
|
||||
void parse_args(int argc, char **argv)
|
||||
{
|
||||
int ac = 1;
|
||||
int disp_sock = 0;
|
||||
|
||||
for (; ac < argc; ac++)
|
||||
{
|
||||
|
||||
if (!strncasecmp(argv[ac], "tty", 3))
|
||||
{
|
||||
old_tty = malloc(strlen(argv[ac])+1);
|
||||
strcpy(old_tty, argv[ac]);
|
||||
}
|
||||
else if (argv[ac][0] == '-' && argv[ac][1] == 'p')
|
||||
{
|
||||
char *pass;
|
||||
pass = getpass("Enter password : ");
|
||||
old_pass = malloc(strlen(pass)+1);
|
||||
strcpy(old_pass, pass);
|
||||
}
|
||||
else if (argv[ac][0] == '-' && argv[ac][1] == 'h')
|
||||
{
|
||||
char *p;
|
||||
if ((p = strrchr(argv[0], '/')))
|
||||
p++;
|
||||
else
|
||||
p = argv[0];
|
||||
fprintf(stderr, "Usage %s: [tty] [-p] [-h] [-l]\r\n\t\ttty is the name of a tty\r\n\t\t-p to specify a password\r\n\t\t-l to list available sockets\r\n\t\t-w to wipe out dead sockets\r\n", p);
|
||||
exit(0);
|
||||
}
|
||||
else if (argv[ac][0] == '-' && argv[ac][1] == 'l')
|
||||
disp_sock = 1;
|
||||
else if (argv[ac][0] == '-' && argv[ac][1] == 'w')
|
||||
disp_sock = 2;
|
||||
else if (!old_tty)
|
||||
{
|
||||
old_tty = malloc(strlen(argv[ac])+1);
|
||||
strcpy(old_tty, argv[ac]);
|
||||
}
|
||||
}
|
||||
if (disp_sock)
|
||||
display_socket_list(socket_path, disp_sock - 1, old_tty);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
dmalloc_debug(0x1df47dfb);
|
||||
#endif
|
||||
*socket_path = 0;
|
||||
strcpy(attach_ttyname, ttyname(0));
|
||||
init_socketpath();
|
||||
parse_args(argc, argv);
|
||||
chdir(getenv("HOME"));
|
||||
reattach_tty(old_tty, old_pass);
|
||||
return 0;
|
||||
}
|
||||
2986
source/screen.c
Normal file
2986
source/screen.c
Normal file
File diff suppressed because it is too large
Load Diff
3736
source/server.c
Normal file
3736
source/server.c
Normal file
File diff suppressed because it is too large
Load Diff
241
source/stack.c
Normal file
241
source/stack.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* stack.c - does the handling of stack functions
|
||||
*
|
||||
* written by matthew green
|
||||
* finished by Jeremy Nelson (ESL)
|
||||
* modified Colten Edwards 1996 for BitchX
|
||||
* copyright (C) 1993.
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: stack.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(stack_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "vars.h"
|
||||
#include "stack.h"
|
||||
#include "window.h"
|
||||
#include "hook.h"
|
||||
#include "ircaux.h"
|
||||
#include "output.h"
|
||||
#include "list.h"
|
||||
#include "misc.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
AliasStack1 *set_stack = NULL;
|
||||
extern void do_stack_set (int, char *);
|
||||
|
||||
#ifdef OLD_HOOK
|
||||
static OnStack *on_stack = NULL;
|
||||
|
||||
extern void do_stack_on (int, char *);
|
||||
|
||||
extern int Add_Remove_Check (Hook *, char *);
|
||||
|
||||
static void do_stack_on (int type, char *args)
|
||||
{
|
||||
int len, cnt, i, which = 0;
|
||||
Hook *list = NULL;
|
||||
NumberMsg *nhook = NULL;
|
||||
char foo[10];
|
||||
|
||||
if (!on_stack && (type == STACK_POP || type == STACK_LIST))
|
||||
{
|
||||
say("ON stack is empty!");
|
||||
return;
|
||||
}
|
||||
if (!args || !*args)
|
||||
{
|
||||
say("Missing event type for STACK ON");
|
||||
return;
|
||||
}
|
||||
len = strlen(args);
|
||||
for (cnt = 0, i = 0; i < NUMBER_OF_LISTS; i++)
|
||||
{
|
||||
if (!my_strnicmp(args, hook_functions[i].name, len))
|
||||
{
|
||||
if (strlen(hook_functions[i].name) == len)
|
||||
{
|
||||
cnt = 1;
|
||||
which = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt++;
|
||||
which = i;
|
||||
}
|
||||
}
|
||||
else if (cnt)
|
||||
break;
|
||||
}
|
||||
if (!cnt)
|
||||
{
|
||||
if (is_number(args))
|
||||
{
|
||||
which = my_atol(args);
|
||||
if (which < 1 || which > 999)
|
||||
{
|
||||
say("Numerics must be between 001 and 999");
|
||||
return;
|
||||
}
|
||||
which = -which;
|
||||
}
|
||||
else
|
||||
{
|
||||
say("No such ON function: %s", args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (which < 0)
|
||||
{
|
||||
sprintf(foo, "%3.3u", -which);
|
||||
if ((nhook = find_name_in_hooklist(foo, numeric_list, 0, HOOKTABLE_SIZE)))
|
||||
list = nhook->list;
|
||||
}
|
||||
else
|
||||
list = hook_functions[which].list;
|
||||
|
||||
if (type == STACK_PUSH)
|
||||
{
|
||||
OnStack *new;
|
||||
|
||||
new = (OnStack *) new_malloc(sizeof(OnStack));
|
||||
new->next = on_stack;
|
||||
on_stack = new;
|
||||
new->which = which;
|
||||
new->list = list;
|
||||
if (which < 0)
|
||||
{
|
||||
|
||||
if (!nhook)
|
||||
return;
|
||||
nhook = find_name_in_hooklist(foo, numeric_list, 1, HOOKTABLE_SIZE);
|
||||
new_free(&nhook->name);
|
||||
new_free(&nhook);
|
||||
}
|
||||
else
|
||||
hook_functions[which].list = NULL;
|
||||
return;
|
||||
}
|
||||
else if (type == STACK_POP)
|
||||
{
|
||||
OnStack *p, *tmp = NULL;
|
||||
|
||||
for (p = on_stack; p; tmp = p, p = p->next)
|
||||
{
|
||||
if (p->which == which)
|
||||
{
|
||||
if (p == on_stack)
|
||||
on_stack = p->next;
|
||||
else
|
||||
tmp->next = p->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!p)
|
||||
{
|
||||
say("No %s on the stack", args);
|
||||
return;
|
||||
}
|
||||
if (which >= 0 && hook_functions[which].list)
|
||||
remove_hook(which, NULL, 0, 0, 1); /* free hooks */
|
||||
else if (which < 0 && nhook)
|
||||
{
|
||||
Hook *tmp, *next;
|
||||
if ((nhook = find_name_in_hooklist(foo, numeric_list, 1, HOOKTABLE_SIZE)))
|
||||
{
|
||||
new_free(&nhook->name);
|
||||
for (tmp = nhook->list; tmp; tmp = next)
|
||||
{
|
||||
next = tmp->next;
|
||||
tmp->not = 1;
|
||||
new_free(&(tmp->nick));
|
||||
new_free(&(tmp->stuff));
|
||||
new_free((char **)&tmp);
|
||||
}
|
||||
new_free(&nhook);
|
||||
}
|
||||
}
|
||||
if (which < 0)
|
||||
{
|
||||
/* look -- do we have any hooks already for this numeric? */
|
||||
if (p->list)
|
||||
{
|
||||
sprintf(foo, "%3.3u", -which);
|
||||
nhook = add_name_to_hooklist(foo, NULL, numeric_list, HOOKTABLE_SIZE);
|
||||
add_to_list_ext((List **)&nhook->list, (List *)p->list, (int (*)(List *, List *))Add_Remove_Check);
|
||||
}
|
||||
}
|
||||
else
|
||||
hook_functions[which].list = p->list;
|
||||
new_free((char **)&p);
|
||||
return;
|
||||
}
|
||||
else if (type == STACK_LIST)
|
||||
{
|
||||
int slevel = 0;
|
||||
OnStack *osptr;
|
||||
|
||||
for (osptr = on_stack; osptr; osptr = osptr->next)
|
||||
{
|
||||
if (osptr->which == which)
|
||||
{
|
||||
Hook *hptr;
|
||||
|
||||
slevel++;
|
||||
say("Level %d stack", slevel);
|
||||
for (hptr = osptr->list; hptr; hptr = hptr->next)
|
||||
show_hook(hptr, args);
|
||||
}
|
||||
}
|
||||
|
||||
if (!slevel)
|
||||
say("The STACK ON %s list is empty", args);
|
||||
return;
|
||||
}
|
||||
say("Unknown STACK ON type ??");
|
||||
}
|
||||
#endif
|
||||
|
||||
BUILT_IN_COMMAND(stackcmd)
|
||||
{
|
||||
char *arg;
|
||||
int len, type;
|
||||
|
||||
if ((arg = next_arg(args, &args)) != NULL)
|
||||
{
|
||||
len = strlen(arg);
|
||||
if (!my_strnicmp(arg, "PUSH", len))
|
||||
type = STACK_PUSH;
|
||||
else if (!my_strnicmp(arg, "POP", len))
|
||||
type = STACK_POP;
|
||||
else if (!my_strnicmp(arg, "LIST", len))
|
||||
type = STACK_LIST;
|
||||
else
|
||||
{
|
||||
say("%s is unknown stack verb", arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
if ((arg = next_arg(args, &args)) != NULL)
|
||||
{
|
||||
len = strlen(arg);
|
||||
if (!my_strnicmp(arg, "ON", len))
|
||||
do_stack_on(type, args);
|
||||
else if (!my_strnicmp(arg, "ALIAS", len))
|
||||
do_stack_alias(type, args, STACK_DO_ALIAS);
|
||||
else if (!my_strnicmp(arg, "ASSIGN", len))
|
||||
do_stack_alias(type, args, STACK_DO_ASSIGN);
|
||||
else if (!my_strnicmp(arg, "SET", len))
|
||||
do_stack_set(type, args);
|
||||
else
|
||||
{
|
||||
say("%s is not a valid STACK type", arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
1668
source/status.c
Normal file
1668
source/status.c
Normal file
File diff suppressed because it is too large
Load Diff
728
source/struct.c
Normal file
728
source/struct.c
Normal file
@@ -0,0 +1,728 @@
|
||||
/*
|
||||
* Written for BitchX by Colten Edwards (c) Feb 1999
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: struct.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(struct_c)
|
||||
#include "struct.h"
|
||||
#include "hash.h"
|
||||
#include "hash2.h"
|
||||
#include "misc.h"
|
||||
#include "names.h"
|
||||
#include "window.h"
|
||||
#include "server.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
|
||||
extern char *after_expando(char *, int, int *);
|
||||
|
||||
/* the types of IrcVariables (repeated in vars.h) */
|
||||
#define BOOL_TYPE_VAR 0
|
||||
#define CHAR_TYPE_VAR 1
|
||||
#define INT_TYPE_VAR 2
|
||||
#define STR_TYPE_VAR 3
|
||||
#define SPECIAL_TYPE_VAR 4
|
||||
|
||||
#define VAR_READ_WRITE 0
|
||||
#define VAR_READ_ONLY 1
|
||||
|
||||
static char *struct_name[] = {"WINDOW", "CHANNEL", "NICK", "DCC", "CSET", "USERLIST", "SHITLIST", "BANS", "EXEMPTBANS", "SERVER", "" };
|
||||
|
||||
#define WINDOW_LOOKUP 0
|
||||
#define CHANNEL_LOOKUP 1
|
||||
#define NICKLIST_LOOKUP 2
|
||||
#define DCC_LOOKUP 3
|
||||
#define CSET_LOOKUP 4
|
||||
#define USERLIST_LOOKUP 5
|
||||
#define SHITLIST_LOOKUP 6
|
||||
#define BANS_LOOKUP 7
|
||||
#define EXEMPT_LOOKUP 8
|
||||
#define SERVER_LOOKUP 9
|
||||
|
||||
typedef struct _lookup_struct
|
||||
{
|
||||
char *code;
|
||||
int offset;
|
||||
int type;
|
||||
int readwrite;
|
||||
} LookupStruct;
|
||||
|
||||
static LookupStruct server_struct[] = {
|
||||
{ "NAME", offsetof(Server, name), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "ITSNAME", offsetof(Server, itsname), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "PASSWORD", offsetof(Server, password), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "SNETWORK", offsetof(Server, snetwork), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "COOKIE", offsetof(Server, cookie), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "PORT", offsetof(Server, port), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
{ "NICKNAME", offsetof(Server, nickname), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "USERHOST", offsetof(Server, userhost), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "NICKNAME_PENDING", offsetof(Server, nickname_pending), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "ORIGNICK_PENDING", offsetof(Server, orignick_pending), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
{ "AWAY", offsetof(Server, away), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "AWAYTIME", offsetof(Server, awaytime), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "OPERATOR", offsetof(Server, operator), BOOL_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "SERVER2_8", offsetof(Server, server2_8), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "VERSION", offsetof(Server, version), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "VERSION_STRING", offsetof(Server, version_string), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
{ "UMODES", offsetof(Server, umodes), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "UMODE", offsetof(Server, umode), CHAR_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
{ "CONNECTED", offsetof(Server, connected), BOOL_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
{ "WRITE", offsetof(Server, write), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "READ", offsetof(Server, read), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "EOF", offsetof(Server, eof), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
|
||||
{ "CHANNEL", offsetof(Server, chan_list), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "ORIGNICK", offsetof(Server, orignick), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "LAG", offsetof(Server, lag), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static LookupStruct channel_struct[] = {
|
||||
{ "CHANNEL", offsetof(ChannelList, channel), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "SERVER", offsetof(ChannelList, server), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "MODE", offsetof(ChannelList, s_mode), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "TOPIC", offsetof(ChannelList, topic), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "TOPIC_LOCK", offsetof(ChannelList, topic_lock), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
|
||||
{ "LIMIT", offsetof(ChannelList, limit), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "KEY", offsetof(ChannelList, key), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "CHOP", offsetof(ChannelList, chop), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "HOP", offsetof(ChannelList, hop), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "VOICE", offsetof(ChannelList, voice), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "BOUND", offsetof(ChannelList, bound), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "CHANPASS", offsetof(ChannelList, chanpass), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "CONNECTED", offsetof(ChannelList, connected), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "REFNUM", offsetof(ChannelList, refnum), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "WINDOW", offsetof(ChannelList, window), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
{ "NICK", offsetof(ChannelList, NickListTable), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
{ "MAXIDLE", offsetof(ChannelList, max_idle), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "TOG_LIMIT", offsetof(ChannelList, tog_limit), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "CHECK_IDLE", offsetof(ChannelList, check_idle), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "DO_SCAN", offsetof(ChannelList, do_scan), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
#if 0
|
||||
struct timeval channel_create; /* time for channel creation */
|
||||
struct timeval join_time; /* time of last join */
|
||||
#endif
|
||||
|
||||
{ "STATS_OPS", offsetof(ChannelList, stats_ops), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_DOPS", offsetof(ChannelList, stats_dops), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_BANS", offsetof(ChannelList, stats_bans), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_UNBANS", offsetof(ChannelList, stats_unbans), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
|
||||
{ "STATS_SOPS", offsetof(ChannelList, stats_sops), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_SDOPS", offsetof(ChannelList, stats_sdops), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_SHOPS", offsetof(ChannelList, stats_shops), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_SDEHOPS", offsetof(ChannelList, stats_sdehops), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_SEBANS", offsetof(ChannelList, stats_sebans), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_SUNEBANS", offsetof(ChannelList, stats_sunebans), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_SBANS", offsetof(ChannelList, stats_sbans), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_SUNBANS", offsetof(ChannelList, stats_sunbans), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
|
||||
{ "STATS_TOPICS", offsetof(ChannelList, stats_topics), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_KICKS", offsetof(ChannelList, stats_kicks), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "STATS_PUBS", offsetof(ChannelList, stats_pubs), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STATS_PARTS", offsetof(ChannelList, stats_parts), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STATS_SIGNOFFS", offsetof(ChannelList, stats_signoffs), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STATS_JOINS", offsetof(ChannelList, stats_joins), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STATS_EBANS", offsetof(ChannelList, stats_ebans), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STATS_UNEBANS", offsetof(ChannelList, stats_unebans), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STATS_CHANPASS", offsetof(ChannelList, stats_chanpass), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STATS_HOPS", offsetof(ChannelList, stats_hops), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STATS_DHOPS", offsetof(ChannelList, stats_dhops), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "CSET", offsetof(ChannelList, csets), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
|
||||
|
||||
{ "MSGLOG", offsetof(ChannelList, msglog_on), BOOL_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "MSGLOG_FILE", offsetof(ChannelList, logfile), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
{ "TOTALNICKS", offsetof(ChannelList, totalnicks), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "MAXNICKS", offsetof(ChannelList, maxnicks), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "MAXNICKSTIME", offsetof(ChannelList, maxnickstime), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "TOTALBANS", offsetof(ChannelList, totalbans), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "MAXBANS", offsetof(ChannelList, maxbans), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "MAXBANSTIME", offsetof(ChannelList, maxbanstime), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "BANS", offsetof(ChannelList, bans), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "EXEMPTBANS", offsetof(ChannelList, exemptbans), SPECIAL_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static LookupStruct user_struct[] = {
|
||||
{ "NICK", offsetof(UserList, nick), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "HOST", offsetof(UserList, host), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "COMMENT", offsetof(UserList, comment), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "CHANNELS", offsetof(UserList, channels), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "PASSWORD", offsetof(UserList, password), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "FLAGS", offsetof(UserList, flags), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "TIME", offsetof(UserList, time), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static LookupStruct shit_struct[] = {
|
||||
{ "FILTER", offsetof(ShitList, filter), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "LEVEL", offsetof(ShitList, level), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "CHANNELS", offsetof(ShitList, channels), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "REASON", offsetof(ShitList, reason), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "TIME", offsetof(ShitList, time), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static LookupStruct bans_struct[] = {
|
||||
{ "BAN", offsetof(BanList, ban), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "SETBY", offsetof(BanList, setby), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "SENT_UNBAN", offsetof(BanList, sent_unban),INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "SENT_UNBAN_TIME", offsetof(BanList, sent_unban_time),INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "TIME", offsetof(BanList, time), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ "COUNT", offsetof(BanList, count), INT_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static LookupStruct dcc_struct[] = {
|
||||
{ "USER", offsetof(DCC_int, user), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "USERHOST", offsetof(DCC_int, userhost), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "SERVER", offsetof(DCC_int, server), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "ENCRYPT", offsetof(DCC_int, encrypt), STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "FILENAME", offsetof(DCC_int, filename), STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "OTHERNAME", offsetof(DCC_int, othername), STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "BYTES_READ", offsetof(DCC_int, bytes_read), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "BYTES_SENT", offsetof(DCC_int, bytes_sent), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "START_OFFSET", offsetof(DCC_int, transfer_orders.byteoffset), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "FILESIZE", offsetof(DCC_int, filesize), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "PACKETS", offsetof(DCC_int, packets), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "BLOCKSIZE", offsetof(DCC_int, blocksize), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "DCC_FAST", offsetof(DCC_int, dcc_fast), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "REMPORT", offsetof(DCC_int, remport), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "LOCALPORT", offsetof(DCC_int, localport), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "DCCNUM", offsetof(DCC_int, dccnum), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
static LookupStruct win_struct[] = {
|
||||
{ "NAME", offsetof(Window, name), STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "REFNUM", offsetof(Window, refnum), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "SERVER", offsetof(Window, server), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "TOP", offsetof(Window, top), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "BOTTOM", offsetof(Window, bottom), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "CURSOR", offsetof(Window, cursor), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "LINE_CNT", offsetof(Window, line_cnt), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "SCROLL", offsetof(Window, noscroll), BOOL_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "SCRATCH", offsetof(Window, scratch_line), BOOL_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "COLUMNS", offsetof(Window, columns), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "NOTIFY_LEVEL", offsetof(Window, notify_level), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "WINDOW_LEVEL", offsetof(Window, window_level), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "CURRENT_CHANNEL", offsetof(Window, current_channel),STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "WAITING_CHANNEL", offsetof(Window, waiting_channel),STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "BIND_CHANNEL", offsetof(Window, bind_channel), STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "QUERY_NICK", offsetof(Window, query_nick), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "QUERY_HOST", offsetof(Window, query_host), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "QUERY_CMD", offsetof(Window, query_cmd), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "LOG", offsetof(Window, log), BOOL_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "LOGFILE", offsetof(Window, logfile), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "LASTLOG_LEVEL", offsetof(Window, lastlog_level),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "LASTLOG_SIZE", offsetof(Window, lastlog_size), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "LASTLOG_MAX", offsetof(Window, lastlog_max), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "HOLD_MODE", offsetof(Window, hold_mode), BOOL_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "MANGLER", offsetof(Window, mangler), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "PROMPT", offsetof(Window, prompt), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
static LookupStruct nicklist_struct[] = {
|
||||
{ "NICK", offsetof(NickList, nick), STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "HOST", offsetof(NickList, host), STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "IP", offsetof(NickList, ip), STR_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "SERVER", offsetof(NickList, server), STR_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "IP_COUNT", offsetof(NickList, ip_count), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
|
||||
{ "USERLIST", offsetof(NickList, userlist), SPECIAL_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ "SHITLIST", offsetof(NickList, shitlist), SPECIAL_TYPE_VAR , VAR_READ_ONLY },
|
||||
|
||||
{ "FLAGS", offsetof(NickList, flags), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
|
||||
{ "IDLE_TIME", offsetof(NickList, idle_time), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
{ "FLOODCOUNT", offsetof(NickList, floodcount), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "FLOODTIME", offsetof(NickList, floodtime), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
{ "NICKCOUNT", offsetof(NickList, nickcount), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "NICKTIME", offsetof(NickList, nicktime), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
{ "KICKCOUNT", offsetof(NickList, kickcount), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "KICKTIME", offsetof(NickList, kicktime), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
{ "JOINCOUNT", offsetof(NickList, joincount), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "JOINTIME", offsetof(NickList, jointime), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
|
||||
{ "DOPCOUNT", offsetof(NickList, dopcount), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "DOPTIME", offsetof(NickList, doptime), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
{ "KICKCOUNT", offsetof(NickList, bancount), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "KICKTIME", offsetof(NickList, bantime), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
{ "CREATED", offsetof(NickList, created), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
|
||||
|
||||
{ "STAT_KICKS", offsetof(NickList, stat_kicks),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_DOPS", offsetof(NickList, stat_dops), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_OPS", offsetof(NickList, stat_ops), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_HOPS", offsetof(NickList, stat_hops), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_DHOPS", offsetof(NickList, stat_dhops),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_EBAN", offsetof(NickList, stat_eban), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_UNEBAN", offsetof(NickList, stat_uneban),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_BANS", offsetof(NickList, stat_bans), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_UNBANS", offsetof(NickList, stat_unbans),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_NICKS", offsetof(NickList, stat_nicks),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_PUB", offsetof(NickList, stat_pub), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "STAT_TOPICS", offsetof(NickList, stat_topics),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
|
||||
{ "SENT_REOP", offsetof(NickList, sent_reop), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "SENT_REOP_TIME", offsetof(NickList, sent_reop_time),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "SENT_VOICE", offsetof(NickList, sent_voice), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "SENT_VOICE_TIME", offsetof(NickList, sent_voice_time),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "SENT_DEOP", offsetof(NickList, sent_deop), INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "SENT_DEOP_TIME", offsetof(NickList, sent_deop_time),INT_TYPE_VAR , VAR_READ_WRITE },
|
||||
{ "NEED_USERHOST", offsetof(NickList, need_userhost), INT_TYPE_VAR , VAR_READ_ONLY },
|
||||
{ NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
static LookupStruct cset_struct[] = {
|
||||
{ "AINV", offsetof(CSetList, set_ainv), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "ANNOY_KICK", offsetof(CSetList, set_annoy_kick), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "AOP", offsetof(CSetList, set_aop), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "AUTO_JOIN_ON_INVITE",offsetof(CSetList, set_auto_join_on_invite), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "AUTO_LIMIT", offsetof(CSetList, set_auto_limit), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "AUTO_REJOIN", offsetof(CSetList, set_auto_rejoin), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "BANTIME", offsetof(CSetList, set_bantime), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "BITCH", offsetof(CSetList, bitch_mode), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "CHANMODE", offsetof(CSetList, chanmode), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
|
||||
{ "CHANNEL_LOG", offsetof(CSetList, channel_log), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "CHANNEL_LOG_FILE", offsetof(CSetList, channel_log_file), STR_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "CHANNEL_LOG_LEVEL", offsetof(CSetList, log_level), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
|
||||
{ "COMPRESS_MODES", offsetof(CSetList, compress_modes), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "CTCP_FLOOD_BAN", offsetof(CSetList, set_ctcp_flood_ban), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "DEOPFLOOD", offsetof(CSetList, set_deopflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "DEOPFLOOD_TIME", offsetof(CSetList, set_deopflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "DEOP_ON_DEOPFLOOD", offsetof(CSetList, set_deop_on_deopflood), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "DEOP_ON_KICKFLOOD", offsetof(CSetList, set_deop_on_kickflood), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "HACKING", offsetof(CSetList, set_hacking), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "JOINFLOOD", offsetof(CSetList, set_joinflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "JOINFLOOD_TIME", offsetof(CSetList, set_joinflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICKFLOOD", offsetof(CSetList, set_kickflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICKFLOOD_TIME", offsetof(CSetList, set_kickflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICK_IF_BANNED", offsetof(CSetList, set_kick_if_banned), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICK_ON_DEOPFLOOD", offsetof(CSetList, set_kick_on_deopflood), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICK_ON_JOINFLOOD", offsetof(CSetList, set_kick_on_joinflood), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICK_ON_KICKFLOOD", offsetof(CSetList, set_kick_on_kickflood), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICK_ON_NICKFLOOD", offsetof(CSetList, set_kick_on_nickflood), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICK_ON_PUBFLOOD", offsetof(CSetList, set_kick_on_pubflood), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "KICK_OPS", offsetof(CSetList, set_kick_ops), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "LAMEIDENT", offsetof(CSetList, set_lame_ident), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "LAMELIST", offsetof(CSetList, set_lamelist), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "NICKFLOOD", offsetof(CSetList, set_nickflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "NICKFLOOD_TIME", offsetof(CSetList, set_nickflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "PUBFLOOD", offsetof(CSetList, set_pubflood), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "PUBFLOOD_IGNORE_TIME",offsetof(CSetList, set_pubflood_ignore), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "PUBFLOOD_TIME", offsetof(CSetList, set_pubflood_time), INT_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "SHITLIST", offsetof(CSetList, set_shitlist), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "USERLIST", offsetof(CSetList, set_userlist), BOOL_TYPE_VAR, VAR_READ_WRITE },
|
||||
{ "CHANNEL", offsetof(CSetList, channel), STR_TYPE_VAR, VAR_READ_ONLY },
|
||||
{ NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
int find_structure(char *name)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; *struct_name[i]; i++)
|
||||
if (!my_stricmp(struct_name[i], name))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int setup_structure(char *name, char *which, Window **win, DCC_int **dcc, ChannelList **chan, NickList **nick, int *server)
|
||||
{
|
||||
int i;
|
||||
int serv = -1;
|
||||
i = find_structure(name);
|
||||
switch (i)
|
||||
{
|
||||
case WINDOW_LOOKUP:
|
||||
{
|
||||
*win = get_window_by_desc(which);
|
||||
if (!*win)
|
||||
*win = current_window;
|
||||
return WINDOW_LOOKUP;
|
||||
}
|
||||
case NICKLIST_LOOKUP:
|
||||
{
|
||||
char *ch = NULL;
|
||||
if (!*chan)
|
||||
{
|
||||
if (!(ch = get_current_channel_by_refnum(0)))
|
||||
return -1;
|
||||
if (!(*chan = lookup_channel(ch, current_window->server, 0)))
|
||||
return -1;
|
||||
}
|
||||
if (!ch && !*chan)
|
||||
return -1;
|
||||
*nick = find_nicklist_in_channellist(which, *chan, 0);
|
||||
return NICKLIST_LOOKUP;
|
||||
}
|
||||
case DCC_LOOKUP:
|
||||
{
|
||||
SocketList *s;
|
||||
DCC_int *n;
|
||||
int l = my_atol(which);
|
||||
s = get_socket(l);
|
||||
if (!s || !(n = (DCC_int *)s->info))
|
||||
break;
|
||||
*dcc = n;
|
||||
return DCC_LOOKUP;
|
||||
}
|
||||
case CHANNEL_LOOKUP:
|
||||
{
|
||||
char *ch = which;
|
||||
if (!*ch)
|
||||
{
|
||||
if (!(ch = get_current_channel_by_refnum(0)))
|
||||
return -1;
|
||||
}
|
||||
if (is_channel(ch))
|
||||
*chan = lookup_channel(ch, current_window->server, 0);
|
||||
else
|
||||
{
|
||||
if ((ch = make_channel(ch)))
|
||||
*chan = lookup_channel(ch, current_window->server, 0);
|
||||
}
|
||||
return CHANNEL_LOOKUP;
|
||||
}
|
||||
case SERVER_LOOKUP:
|
||||
if (*which && ((serv = my_atol(which)) != -1))
|
||||
*server = serv;
|
||||
return SERVER_LOOKUP;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static inline int get_offset_int(void *tmp, int offset)
|
||||
{
|
||||
int val = *(int *)((void *)tmp + offset);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline char *get_offset_str(void *tmp, int offset)
|
||||
{
|
||||
char *s = *(char **) ((void *)tmp + offset);
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline char *get_offset_char(void *tmp, int offset)
|
||||
{
|
||||
char *s = (char *) ((void *)tmp + offset);
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline void set_offset_int(void *tmp, int offset, int val)
|
||||
{
|
||||
int *ptr = (int *)((void *)tmp + offset);
|
||||
*ptr = val;
|
||||
}
|
||||
|
||||
static inline void set_offset_str(void *tmp, int offset, char *val)
|
||||
{
|
||||
char **ptr = (char **) ((void *)tmp + offset);
|
||||
if (val && *val)
|
||||
malloc_strcpy(ptr, val);
|
||||
else
|
||||
new_free(ptr);
|
||||
}
|
||||
|
||||
static inline void set_offset_char(void *tmp, int offset, char *val)
|
||||
{
|
||||
char *ptr = (char *) ((void *)tmp + offset);
|
||||
if (val && *val)
|
||||
strcpy(ptr, val);
|
||||
else
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
int lookup_code(LookupStruct *t, char *name)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; t[i].code; i++)
|
||||
{
|
||||
if (!my_stricmp(t[i].code, name))
|
||||
break;
|
||||
}
|
||||
if (!t[i].code)
|
||||
return -1;
|
||||
return i;
|
||||
}
|
||||
|
||||
char *return_structure(LookupStruct *name, void *user)
|
||||
{
|
||||
int j;
|
||||
char *ret = NULL;
|
||||
char *s;
|
||||
if (!user)
|
||||
return NULL;
|
||||
for (j = 0; name[j].code; j++)
|
||||
{
|
||||
if (name[j].type == INT_TYPE_VAR)
|
||||
m_s3cat(&ret, ",", ltoa(get_offset_int(user, name[j].offset)));
|
||||
else if (name[j].type == STR_TYPE_VAR)
|
||||
{
|
||||
s = get_offset_str(user, name[j].offset);
|
||||
m_s3cat(&ret, ",", s ? s : empty_string);
|
||||
}
|
||||
else if (name[j].type == BOOL_TYPE_VAR)
|
||||
m_s3cat(&ret, ",", on_off(get_offset_int(user, name[j].offset)));
|
||||
else if (name[j].type == CHAR_TYPE_VAR)
|
||||
m_s3cat(&ret, ",", get_offset_char(user, name[j].offset));
|
||||
else if (name[j].type == SPECIAL_TYPE_VAR)
|
||||
{
|
||||
s = LOCAL_COPY(name[j].code);
|
||||
lower(s);
|
||||
m_s3cat(&ret, ",", "<");
|
||||
malloc_strcat(&ret, s);
|
||||
malloc_strcat(&ret, ">");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *lookup_structure_item(int idx, LookupStruct *name, void *user, char *arg)
|
||||
{
|
||||
if (!user || (idx == -1))
|
||||
return NULL;
|
||||
switch (name[idx].type)
|
||||
{
|
||||
case STR_TYPE_VAR:
|
||||
if (arg && !name[idx].readwrite)
|
||||
set_offset_str(user, name[idx].offset, arg);
|
||||
return m_strdup(get_offset_str(user, name[idx].offset));
|
||||
case CHAR_TYPE_VAR:
|
||||
if (arg && !name[idx].readwrite)
|
||||
set_offset_char(user, name[idx].offset, arg);
|
||||
return m_strdup(get_offset_char(user, name[idx].offset));
|
||||
case INT_TYPE_VAR:
|
||||
if (arg && *arg && !name[idx].readwrite)
|
||||
set_offset_int(user, name[idx].offset, my_atol(arg));
|
||||
return m_strdup(ltoa(get_offset_int(user, name[idx].offset)));
|
||||
case BOOL_TYPE_VAR:
|
||||
if (arg && *arg && !name[idx].readwrite)
|
||||
{
|
||||
int val = 0;
|
||||
if (!my_stricmp(arg, "on"))
|
||||
val = 1;
|
||||
else if (!my_stricmp(arg, "off"))
|
||||
val = 0;
|
||||
else
|
||||
val = my_atol(arg);
|
||||
set_offset_int(user, name[idx].offset, val);
|
||||
}
|
||||
return m_strdup(on_off(get_offset_int(user, name[idx].offset)));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *lookup_structure_member(int type, char *name, char *rest, NickList *n, ChannelList *ch, Window *w, DCC_int *dcc, int serv)
|
||||
{
|
||||
LookupStruct *tmp = NULL;
|
||||
int i = -1;
|
||||
char *ret = NULL;
|
||||
void *user = NULL;
|
||||
int code = -1;
|
||||
switch (type)
|
||||
{
|
||||
case WINDOW_LOOKUP:
|
||||
tmp = win_struct;
|
||||
user = w;
|
||||
break;
|
||||
case NICKLIST_LOOKUP:
|
||||
tmp = nicklist_struct;
|
||||
user = n;
|
||||
break;
|
||||
case DCC_LOOKUP:
|
||||
tmp = dcc_struct;
|
||||
user = dcc;
|
||||
break;
|
||||
case CHANNEL_LOOKUP:
|
||||
tmp = channel_struct;
|
||||
user = ch;
|
||||
break;
|
||||
case CSET_LOOKUP:
|
||||
tmp = cset_struct;
|
||||
if (ch)
|
||||
user = ch->csets;
|
||||
break;
|
||||
case SERVER_LOOKUP:
|
||||
tmp = server_struct;
|
||||
if (serv != -1 && serv < server_list_size())
|
||||
{
|
||||
user = (void *)(get_server_list());
|
||||
user += (sizeof(Server) * serv);
|
||||
ch = ((Server *)user)->chan_list;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!tmp || !user)
|
||||
return NULL;
|
||||
if (!name || !*name)
|
||||
return return_structure(tmp, user);
|
||||
if ((i = lookup_code(tmp, name)) == -1)
|
||||
return NULL;
|
||||
switch(tmp[i].type)
|
||||
{
|
||||
case INT_TYPE_VAR:
|
||||
case STR_TYPE_VAR:
|
||||
case BOOL_TYPE_VAR:
|
||||
case CHAR_TYPE_VAR:
|
||||
{
|
||||
char *lparen;
|
||||
if (rest && !*rest)
|
||||
rest = NULL;
|
||||
#if 0
|
||||
if ((lparen = strchr(rest+1, '[')))
|
||||
{
|
||||
if ((rparen = MatchingBracket(lparen+1, '[', ']')))
|
||||
*rparen++ = 0;
|
||||
*lparen++ = 0;
|
||||
if (!*lparen)
|
||||
lparen = NULL;
|
||||
} else if (*rest)
|
||||
#endif
|
||||
lparen = rest;
|
||||
ret = lookup_structure_item(i, tmp, user, lparen);
|
||||
break;
|
||||
}
|
||||
case SPECIAL_TYPE_VAR:
|
||||
{
|
||||
code = find_structure(name);
|
||||
switch (code)
|
||||
{
|
||||
case NICKLIST_LOOKUP: /* this is a special case */
|
||||
tmp = nicklist_struct;
|
||||
n = sorted_nicklist(ch, NICKSORT_NONE);
|
||||
for (; n; n = n->next)
|
||||
if (!rest || !*rest)
|
||||
m_s3cat(&ret, ",", n->nick);
|
||||
else if (*rest == '>' && *(rest+1) && !my_stricmp(rest+1, n->nick))
|
||||
ret = return_structure(tmp, n);
|
||||
clear_sorted_nicklist(&n);
|
||||
return ret;
|
||||
break;
|
||||
case USERLIST_LOOKUP:
|
||||
tmp = user_struct;
|
||||
if (n)
|
||||
user = n->userlist;
|
||||
break;
|
||||
case SHITLIST_LOOKUP:
|
||||
tmp = shit_struct;
|
||||
if (n)
|
||||
user = n->shitlist;
|
||||
break;
|
||||
case CSET_LOOKUP:
|
||||
tmp = cset_struct;
|
||||
if (ch)
|
||||
user = ch->csets;
|
||||
break;
|
||||
case WINDOW_LOOKUP:
|
||||
tmp = win_struct;
|
||||
if (ch)
|
||||
user = ch->window;
|
||||
break;
|
||||
case EXEMPT_LOOKUP:
|
||||
tmp = bans_struct;
|
||||
if (ch)
|
||||
user = ch->exemptbans;
|
||||
break;
|
||||
case BANS_LOOKUP:
|
||||
{
|
||||
BanList *b;
|
||||
tmp = bans_struct;
|
||||
if (ch)
|
||||
user = ch->bans;
|
||||
for (b = ch->bans; b; b= b->next)
|
||||
if (!rest || !*rest)
|
||||
m_s3cat(&ret, ",", b->ban);
|
||||
else if (*rest == '>' && *(rest+1) && !my_stricmp(rest+1, b->ban))
|
||||
ret = return_structure(tmp, b);
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
case CHANNEL_LOOKUP:
|
||||
tmp = channel_struct;
|
||||
ch = ((Server *)user)->chan_list;
|
||||
for (; ch; ch = ch->next)
|
||||
if (!rest || !*rest)
|
||||
m_s3cat(&ret, ",", ch->channel);
|
||||
else if (*rest == '>' && *(rest+1) && !my_stricmp(rest+1, ch->channel))
|
||||
ret = return_structure(tmp, ch);
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
if (rest && *rest == '>' && *(rest + 1))
|
||||
{
|
||||
char *lparen, *rparen;
|
||||
if ((lparen = strchr(rest+1, '[')))
|
||||
{
|
||||
if ((rparen = MatchingBracket(lparen+1, '[', ']')))
|
||||
*rparen++ = 0;
|
||||
*lparen++ = 0;
|
||||
} else if (rest && !*rest)
|
||||
rest = NULL;
|
||||
i = lookup_code(tmp, rest+1);
|
||||
ret = lookup_structure_item(i, tmp, user, lparen);
|
||||
}
|
||||
else
|
||||
ret = return_structure(tmp, user);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char *call_structure_internal(char *name, char *args, char *rest, char *rest1)
|
||||
{
|
||||
Window *win = NULL;
|
||||
ChannelList *chan = NULL;
|
||||
DCC_int *dcc = NULL;
|
||||
NickList *nick = NULL;
|
||||
char *ret = NULL;
|
||||
int type = -1;
|
||||
int server = -1;
|
||||
char *lparen, *rparen;
|
||||
type = setup_structure(name, args, &win, &dcc, &chan, &nick, &server);
|
||||
if ((lparen = strchr(rest, '[')))
|
||||
{
|
||||
if ((rparen = MatchingBracket(lparen+1, '[', ']')))
|
||||
*rparen++ = 0;
|
||||
*lparen++ = 0;
|
||||
rest1 = lparen;
|
||||
}
|
||||
if (type != -1)
|
||||
ret = lookup_structure_member(type, rest, rest1, nick, chan, win ? win : current_window, dcc, server);
|
||||
return ret;
|
||||
}
|
||||
1569
source/tcl_public.c
Normal file
1569
source/tcl_public.c
Normal file
File diff suppressed because it is too large
Load Diff
2609
source/term.c
Normal file
2609
source/term.c
Normal file
File diff suppressed because it is too large
Load Diff
628
source/timer.c
Normal file
628
source/timer.c
Normal file
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* timer.c -- handles timers in ircII
|
||||
* Copyright 1993, 1996 Matthew Green
|
||||
* This file organized/adapted by Jeremy Nelson
|
||||
*
|
||||
* This used to be in edit.c, and it used to only allow you to
|
||||
* register ircII commands to be executed later. I needed more
|
||||
* generality then that, specifically the ability to register
|
||||
* any function to be called, so i pulled it all together into
|
||||
* this file and called it timer.c
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: timer.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(timer_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "ircaux.h"
|
||||
#include "lastlog.h"
|
||||
#include "window.h"
|
||||
#include "timer.h"
|
||||
#include "hook.h"
|
||||
#include "output.h"
|
||||
#include "commands.h"
|
||||
#include "misc.h"
|
||||
#include "vars.h"
|
||||
#include "server.h"
|
||||
#include "screen.h"
|
||||
#include "tcl_bx.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
static void show_timer (char *command);
|
||||
void BX_delete_all_timers (void);
|
||||
int timer_exists (char *);
|
||||
static TimerList *get_timer (char *ref);
|
||||
|
||||
#define RETURN_INT(x) return m_strdup(ltoa(x))
|
||||
|
||||
/*
|
||||
* timercmd: the bit that handles the TIMER command. If there are no
|
||||
* arguements, then just list the currently pending timers, if we are
|
||||
* give a -DELETE flag, attempt to delete the timer from the list. Else
|
||||
* consider it to be a timer to add, and add it.
|
||||
*/
|
||||
BUILT_IN_COMMAND(timercmd)
|
||||
{
|
||||
char *waittime,
|
||||
*flag;
|
||||
char *want = empty_string;
|
||||
char *ptr;
|
||||
double interval;
|
||||
long events = -2;
|
||||
int update = 0;
|
||||
int winref = current_window->refnum;
|
||||
|
||||
while (*args == '-' || *args == '/')
|
||||
{
|
||||
flag = next_arg(args, &args);
|
||||
if (!flag || !*flag)
|
||||
break;
|
||||
|
||||
if (!my_strnicmp(flag+1, "D", 1)) /* DELETE */
|
||||
{
|
||||
if (!(ptr = next_arg(args, &args)))
|
||||
say("%s: Need a timer reference number for -DELETE", command);
|
||||
else
|
||||
{
|
||||
if (timer_exists(ptr))
|
||||
delete_timer(ptr);
|
||||
else if (!my_strnicmp(ptr, "A", 1))
|
||||
delete_all_timers();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (!my_strnicmp(flag+1, "REP", 3))
|
||||
{
|
||||
char *na = next_arg(args, &args);
|
||||
if (!na || !*na)
|
||||
{
|
||||
say("%s: Missing argument to -REPEAT", command);
|
||||
return;
|
||||
}
|
||||
if (!strcmp(na, "*") || !strcmp(na, "-1"))
|
||||
events = -1;
|
||||
else if ((events = my_atol(na)) == 0)
|
||||
return;
|
||||
}
|
||||
else if (!my_strnicmp(flag+1, "REF", 3)) /* REFNUM */
|
||||
{
|
||||
want = next_arg(args, &args);
|
||||
if (!want || !*want)
|
||||
{
|
||||
say("%s: Missing argument to -REFNUM", command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!my_strnicmp(flag + 1, "L", 1))
|
||||
show_timer(command);
|
||||
else if (!my_strnicmp(flag + 1, "W", 1)) /* WINDOW */
|
||||
{
|
||||
char *na;
|
||||
|
||||
if ((na = next_arg(args, &args)))
|
||||
winref = get_winref_by_desc(na);
|
||||
|
||||
if (winref == -1 && my_stricmp(na, "-1"))
|
||||
{
|
||||
say("%s: That window doesnt exist!", command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!my_strnicmp(flag + 1, "UPDATE", 1)) /* UPDATE */
|
||||
update = 1;
|
||||
else
|
||||
say("%s: %s no such flag", command, flag);
|
||||
}
|
||||
|
||||
/* else check to see if we have no args -> list */
|
||||
|
||||
waittime = next_arg(args, &args);
|
||||
if (update || waittime)
|
||||
{
|
||||
if (update && !timer_exists(want))
|
||||
{
|
||||
say("%s: To use -UPDATE you must specify a valid refnum", command);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!waittime)
|
||||
interval = -1;
|
||||
else
|
||||
interval = atof(waittime) * 1000.0;
|
||||
|
||||
if (!update && events == -2)
|
||||
events = 1;
|
||||
else if (events == -2)
|
||||
events = -1;
|
||||
|
||||
add_timer(update, want, interval, events, NULL, args, subargs, winref, NULL);
|
||||
}
|
||||
else
|
||||
show_timer(command);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is put here on purpose -- we dont want any of the above functions
|
||||
* to have any knowledge of this struct.
|
||||
*/
|
||||
static TimerList *PendingTimers;
|
||||
static char *schedule_timer (TimerList *ntimer);
|
||||
|
||||
static char *current_exec_timer = empty_string;
|
||||
|
||||
/*
|
||||
* ExecuteTimers: checks to see if any currently pending timers have
|
||||
* gone off, and if so, execute them, delete them, etc, setting the
|
||||
* current_exec_timer, so that we can't remove the timer while its
|
||||
* still executing.
|
||||
*
|
||||
* changed the behavior: timers will not hook while we are waiting.
|
||||
*/
|
||||
extern void ExecuteTimers (void)
|
||||
{
|
||||
TimerList *current;
|
||||
static int parsingtimer = 0;
|
||||
int old_from_server = from_server;
|
||||
struct timeval now1;
|
||||
|
||||
/* We do NOT want to parse timers while waiting
|
||||
* cause it gets icky recursive
|
||||
*/
|
||||
if (!PendingTimers || parsingtimer)
|
||||
return;
|
||||
get_time(&now1);
|
||||
|
||||
parsingtimer = 1;
|
||||
while (PendingTimers && BX_time_diff(now1, PendingTimers->time) < 0)
|
||||
{
|
||||
int old_refnum = current_window->refnum;
|
||||
|
||||
current = PendingTimers;
|
||||
PendingTimers = current->next;
|
||||
|
||||
make_window_current_by_winref(current->window);
|
||||
/*
|
||||
* Restore from_server and curr_scr_win from when the
|
||||
* timer was registered
|
||||
*/
|
||||
|
||||
if (is_server_connected(current->server))
|
||||
from_server = current->server;
|
||||
else if (is_server_connected(get_window_server(0)))
|
||||
from_server = get_window_server(0);
|
||||
else
|
||||
from_server = -1;
|
||||
|
||||
/*
|
||||
* If a callback function was registered, then
|
||||
* we use it. If no callback function was registered,
|
||||
* then we use ''parse_line''.
|
||||
*/
|
||||
current_exec_timer = current->ref;
|
||||
if (current->callback)
|
||||
(*current->callback)(current->command, current->subargs);
|
||||
else
|
||||
parse_line("TIMER",(char *)current->command, current->subargs, 0, 0, 1);
|
||||
|
||||
current_exec_timer = empty_string;
|
||||
from_server = old_from_server;
|
||||
make_window_current_by_winref(old_refnum);
|
||||
|
||||
/*
|
||||
* Clean up or reschedule the timer
|
||||
*/
|
||||
switch (current->events)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
/* callback cleans up command */
|
||||
if (!current->callback)
|
||||
new_free(¤t->command);
|
||||
new_free(¤t->subargs);
|
||||
new_free(¤t->whom);
|
||||
new_free(¤t);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
current->events--;
|
||||
case -1:
|
||||
{
|
||||
#if 1
|
||||
double milli, seconds;
|
||||
milli = current->interval * 1000 * 1000 + current->time.tv_usec;
|
||||
seconds = current->time.tv_sec + (milli / 1000000);
|
||||
milli = ((unsigned long)current) % 1000000;
|
||||
current->time.tv_sec = seconds;
|
||||
current->time.tv_usec = milli;
|
||||
#else
|
||||
current->time.tv_usec += (current->interval * 1000);
|
||||
current->time.tv_sec += (current->time.tv_usec / 1000000);
|
||||
current->time.tv_usec %= 1000000;
|
||||
#endif
|
||||
schedule_timer(current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (current && current->delete)
|
||||
{
|
||||
if (!current->callback)
|
||||
new_free(¤t->command);
|
||||
new_free(¤t->subargs);
|
||||
new_free(¤t->whom);
|
||||
new_free(¤t);
|
||||
}
|
||||
}
|
||||
parsingtimer = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* show_timer: Display a list of all the TIMER commands that are
|
||||
* pending to be executed.
|
||||
*/
|
||||
static void show_timer (char *command)
|
||||
{
|
||||
TimerList *tmp;
|
||||
struct timeval current;
|
||||
double time_left;
|
||||
int count = 0;
|
||||
|
||||
for (tmp = PendingTimers; tmp; tmp = tmp->next)
|
||||
count++;
|
||||
|
||||
if (!count)
|
||||
{
|
||||
say("%s: No commands pending to be executed", command);
|
||||
return;
|
||||
}
|
||||
|
||||
get_time(¤t);
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_TIMER_FSET), "%s %s %s %s","Timer","Seconds","Events","Command"));
|
||||
for (tmp = PendingTimers; tmp; tmp = tmp->next)
|
||||
{
|
||||
char buf[40];
|
||||
time_left = BX_time_diff(current, tmp->time);
|
||||
if (time_left < 0)
|
||||
time_left = 0;
|
||||
sprintf(buf, "%0.3f", time_left);
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_TIMER_FSET), "%s %s %d %s %s", tmp->ref, buf, tmp->events, tmp->callback? "(internal callback)" : (tmp->command? tmp->command : ""), tmp->whom ? tmp->whom : empty_string ));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* create_timer_ref: returns the lowest unused reference number for a timer
|
||||
*
|
||||
* This will never return 0 for a refnum because that is what atol() returns
|
||||
* on case of error, so that it can never happen that a timer has a refnum
|
||||
* of zero which would be tripped if the user did say,
|
||||
* /TIMER -refnUm foobar 3 blah blah blah
|
||||
* which should elicit an error, not be silently punted.
|
||||
*/
|
||||
static int create_timer_ref (char *refnum_want, char *refnum_gets)
|
||||
{
|
||||
TimerList *tmp;
|
||||
int refnum = 0;
|
||||
|
||||
/* Max of 10 characters. */
|
||||
if (strlen(refnum_want) > REFNUM_MAX)
|
||||
refnum_want[REFNUM_MAX] = 0;
|
||||
|
||||
/* If the user doesnt care */
|
||||
if (!strcmp(refnum_want, empty_string))
|
||||
{
|
||||
/* Find the lowest refnum available */
|
||||
for (tmp = PendingTimers; tmp; tmp = tmp->next)
|
||||
{
|
||||
long ref;
|
||||
ref = my_atol(tmp->ref);
|
||||
if (refnum < ref)
|
||||
refnum = ref;
|
||||
}
|
||||
strmcpy(refnum_gets, ltoa(refnum+1), REFNUM_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* See if the refnum is available */
|
||||
for (tmp = PendingTimers; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (!my_stricmp(tmp->ref, refnum_want))
|
||||
return -1;
|
||||
}
|
||||
strmcpy(refnum_gets, refnum_want, REFNUM_MAX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes a refnum. This does cleanup only if the timer is a
|
||||
* user-defined timer, otherwise no clean up is done (the caller
|
||||
* is responsible to handle it) This shouldnt output an error,
|
||||
* it should be more general and return -1 and let the caller
|
||||
* handle it. Probably will be that way in a future release.
|
||||
*/
|
||||
extern int BX_delete_timer (char *ref)
|
||||
{
|
||||
TimerList *tmp,
|
||||
*prev;
|
||||
|
||||
if (current_exec_timer != empty_string)
|
||||
{
|
||||
say("You may not remove a TIMER from another TIMER");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (prev = tmp = PendingTimers; tmp; prev = tmp, tmp = tmp->next)
|
||||
{
|
||||
/* can only delete user created timers */
|
||||
if (!my_stricmp(tmp->ref, ref))
|
||||
{
|
||||
if (tmp == prev)
|
||||
PendingTimers = PendingTimers->next;
|
||||
else
|
||||
prev->next = tmp->next;
|
||||
if (!tmp->callback)
|
||||
new_free(&tmp->command);
|
||||
new_free(&tmp->subargs);
|
||||
new_free(&tmp->whom);
|
||||
new_free((char **)&tmp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
say("TIMER: Can't delete %s, no such refnum", ref);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int kill_timer(char *ref)
|
||||
{
|
||||
TimerList *tmp;
|
||||
for (tmp = PendingTimers; tmp; tmp = tmp->next)
|
||||
{
|
||||
/* can only delete user created timers */
|
||||
if (!my_stricmp(tmp->ref, ref))
|
||||
{
|
||||
tmp->delete = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int get_delete_timer(char *ref)
|
||||
{
|
||||
TimerList *tmp;
|
||||
for (tmp = PendingTimers; tmp; tmp = tmp->next)
|
||||
{
|
||||
/* can only delete user created timers */
|
||||
if (!my_stricmp(tmp->ref, ref))
|
||||
return tmp->delete;
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
void BX_delete_all_timers (void)
|
||||
{
|
||||
while (PendingTimers)
|
||||
delete_timer(PendingTimers->ref);
|
||||
return;
|
||||
}
|
||||
|
||||
int timer_exists (char *ref)
|
||||
{
|
||||
if (get_timer(ref))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BUILT_IN_FUNCTION(function_istimer)
|
||||
{
|
||||
char *timer = NULL;
|
||||
|
||||
if ((timer = next_arg(input, &input)))
|
||||
if (timer_exists(timer))
|
||||
RETURN_INT(1);
|
||||
RETURN_INT(0);
|
||||
}
|
||||
|
||||
int timer_callback_exists (void *ref)
|
||||
{
|
||||
TimerList *t;
|
||||
for (t = PendingTimers; t; t = t->next)
|
||||
{
|
||||
if (t->callback && ref == t->callback)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static TimerList *get_timer (char *ref)
|
||||
{
|
||||
TimerList *tmp;
|
||||
|
||||
for (tmp = PendingTimers; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (!my_stricmp(tmp->ref, ref) || (tmp->whom && !my_stricmp(tmp->whom, ref)))
|
||||
return tmp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *function_timer(char *n, char *args)
|
||||
{
|
||||
char *ref;
|
||||
char *out = NULL;
|
||||
TimerList *tmp;
|
||||
ref = next_arg(args, &args);
|
||||
if (ref && *ref && (tmp = get_timer(ref)))
|
||||
{
|
||||
double time_left;
|
||||
struct timeval current;
|
||||
char buf[40];
|
||||
get_time(¤t);
|
||||
time_left = BX_time_diff(current, tmp->time);
|
||||
if (time_left < 0)
|
||||
time_left = 0.0;
|
||||
sprintf(buf, "%0.3f", time_left);
|
||||
malloc_sprintf(&out, "%s %d %d %d %d %s %s %s", tmp->ref, tmp->server, tmp->window, tmp->interval, tmp->events, buf, tmp->callback? "(internal callback)" : (tmp->command? tmp->command : ""), tmp->whom ? tmp->whom : empty_string );
|
||||
return ref;
|
||||
}
|
||||
return m_strdup(empty_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* You call this to register a timer callback.
|
||||
*
|
||||
* The arguments:
|
||||
* refnum_want: The refnUm requested. This should only be sepcified
|
||||
* by the user, functions wanting callbacks should specify
|
||||
* the value -1 which means "dont care".
|
||||
* The rest of the arguments are dependant upon the value of "callback"
|
||||
* -- if "callback" is NULL then:
|
||||
* callback: NULL
|
||||
* what: some ircII commands to run when the timer goes off
|
||||
* subargs: what to use to expand $0's, etc in the 'what' variable.
|
||||
*
|
||||
* -- if "callback" is non-NULL then:
|
||||
* callback: function to call when timer goes off
|
||||
* what: argument to pass to "callback" function. Should be some
|
||||
* non-auto storage, perhaps a struct or a malloced char *
|
||||
* array. The caller is responsible for disposing of this
|
||||
* area when it is called, since the timer mechanism does not
|
||||
* know anything of the nature of the argument.
|
||||
* subargs: should be NULL, its ignored anyhow.
|
||||
*/
|
||||
char *BX_add_timer(int update, char *refnum_want, double when, long events, int (callback) (void *, char *), char *what, char *subargs, int winref, char *whom)
|
||||
{
|
||||
TimerList *ntimer, *otimer = NULL;
|
||||
char refnum_got[REFNUM_MAX+1] = "";
|
||||
double seconds = 0.0, milli = 0.0;
|
||||
extern double fmod(double, double);
|
||||
|
||||
ntimer = (TimerList *) new_malloc(sizeof(TimerList));
|
||||
|
||||
get_time(&ntimer->time);
|
||||
#if 1
|
||||
milli = when * 1000 + ntimer->time.tv_usec;
|
||||
seconds = ntimer->time.tv_sec + (milli / 1000000);
|
||||
|
||||
milli = ((unsigned long)milli) % 1000000;
|
||||
ntimer->time.tv_sec = seconds;
|
||||
ntimer->time.tv_usec = milli;
|
||||
#else
|
||||
ntimer->time.tv_usec += (unsigned long)when;
|
||||
ntimer->time.tv_sec += ((when + ntimer->time.tv_usec) / 1000);
|
||||
ntimer->time.tv_usec %= 1000;
|
||||
#endif
|
||||
|
||||
ntimer->interval = when / 1000;
|
||||
ntimer->events = events;
|
||||
ntimer->server = from_server;
|
||||
ntimer->window = winref;
|
||||
if (whom)
|
||||
ntimer->whom = m_strdup(whom);
|
||||
if (update)
|
||||
otimer = get_timer(refnum_want);
|
||||
|
||||
if (otimer)
|
||||
{
|
||||
if (when == -1)
|
||||
{
|
||||
ntimer->time = otimer->time;
|
||||
ntimer->interval = otimer->interval;
|
||||
}
|
||||
|
||||
if (events == -1)
|
||||
ntimer->events = otimer->events;
|
||||
|
||||
ntimer->callback = otimer->callback;
|
||||
if (what && *what)
|
||||
{
|
||||
ntimer->command = (void *)what;
|
||||
if (subargs)
|
||||
ntimer->subargs = m_strdup(subargs);
|
||||
}
|
||||
else
|
||||
{
|
||||
ntimer->command = m_strdup(otimer->command);
|
||||
ntimer->subargs = m_strdup(otimer->subargs);
|
||||
}
|
||||
|
||||
delete_timer(refnum_want);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ntimer->callback = callback) != NULL)
|
||||
ntimer->command = (void *)what;
|
||||
else
|
||||
ntimer->command = m_strdup(what);
|
||||
if (subargs)
|
||||
ntimer->subargs = m_strdup(subargs);
|
||||
}
|
||||
|
||||
if (create_timer_ref(refnum_want, refnum_got) == -1)
|
||||
{
|
||||
say("TIMER: Refnum %s already exists", refnum_want);
|
||||
new_free(&ntimer->command);
|
||||
new_free(&ntimer->subargs);
|
||||
new_free(&ntimer->whom);
|
||||
new_free(&ntimer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(ntimer->ref, refnum_got);
|
||||
|
||||
/* we've created it, now put it in order */
|
||||
return schedule_timer(ntimer);
|
||||
}
|
||||
|
||||
static char *schedule_timer (TimerList *ntimer)
|
||||
{
|
||||
TimerList **slot;
|
||||
|
||||
/* we've created it, now put it in order */
|
||||
for (slot = &PendingTimers; *slot; slot = &(*slot)->next)
|
||||
{
|
||||
if (BX_time_diff((*slot)->time, ntimer->time) < 0)
|
||||
break;
|
||||
}
|
||||
ntimer->next = *slot;
|
||||
*slot = ntimer;
|
||||
return ntimer->ref;
|
||||
}
|
||||
|
||||
static struct timeval current;
|
||||
|
||||
|
||||
/*
|
||||
* TimerTimeout: Called from irc_io to help create the timeout
|
||||
* part of the call to select.
|
||||
*/
|
||||
|
||||
time_t TimerTimeout (void)
|
||||
{
|
||||
time_t timeout_in;
|
||||
time_t t = MAGIC_TIMEOUT;
|
||||
|
||||
if (is_server_queue() && (t = get_int_var(QUEUE_SENDS_VAR)))
|
||||
;
|
||||
else
|
||||
t = MAGIC_TIMEOUT;
|
||||
get_time(¤t);
|
||||
if (!PendingTimers)
|
||||
timeout_in = tclTimerTimeout(MAGIC_TIMEOUT);
|
||||
else
|
||||
{
|
||||
timeout_in = (time_t)(BX_time_diff(current, PendingTimers->time) * 1000);
|
||||
timeout_in = (time_t)(tclTimerTimeout((timeout_in < 0) ? 0 : timeout_in));
|
||||
}
|
||||
|
||||
if (t < timeout_in)
|
||||
timeout_in = t * 1000;
|
||||
|
||||
return (timeout_in < 0) ? 0 : timeout_in + 100;
|
||||
}
|
||||
430
source/translat.c
Normal file
430
source/translat.c
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* translat.c: Stuff for handling character translation tables
|
||||
* and a digraph entry facility. Support an international IRC!
|
||||
*
|
||||
* I listen to Sex Pistols, so I assume everyone in this world,
|
||||
* and more specifically, all servers, are using ISO 8859/1
|
||||
* (Latin-1). And in case of doubt, please consult Jarkko 'Wiz'
|
||||
* Oikarinen's document "Internet Relay Chat Protocol" (doc/Comms
|
||||
* in the ircd package), paragraph 2.2. Besides, all of the sane
|
||||
* world has already converted to this set. (X-Windows, Digital,
|
||||
* MS-Windows, etc.)
|
||||
* If someone please would forward me some documentation on other
|
||||
* international sets, like 8859/2 - 8859/10 etc, please do so!
|
||||
* Moreover, feedback on the tables in the definition files would
|
||||
* be greatly appreciated!
|
||||
* Another idea, to be implemented some beautiful day, would be
|
||||
* to add transliteration of the Kanji/Katakana sets used in
|
||||
* the far east. 8-)
|
||||
* Tomten <tomten@solace.hsh.se> / <tomten@lysator.liu.se>
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: translat.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(translat_c)
|
||||
#include "struct.h"
|
||||
|
||||
#if defined(TRANSLATE) || defined(HEBREW)
|
||||
#include "vars.h"
|
||||
#include "translat.h"
|
||||
#include "ircaux.h"
|
||||
#include "window.h"
|
||||
#include "screen.h"
|
||||
#include "output.h"
|
||||
#include "hebrew.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
|
||||
#ifndef TRANSLATION_PATH
|
||||
/* we have this here as a safety feature if for some reason TRANSLATION_PATH
|
||||
* is not defined.
|
||||
*/
|
||||
#define TRANSLATION_PATH "/usr/local/lib/bx/translation"
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned char my_getarg (char **);
|
||||
|
||||
/* Globals */
|
||||
unsigned char transToClient[256]; /* Server to client translation. */
|
||||
unsigned char transFromClient[256]; /* Client to server translation. */
|
||||
char translation = 0; /* 0 for transparent (no) translation. */
|
||||
char digraph_changed = 0;
|
||||
|
||||
/*
|
||||
* dig_table_lo[] and dig_table_hi[] contain the character pair that
|
||||
* will result in the digraph in dig_table_di[]. To avoid searching
|
||||
* both tables, I take the lower character of the pair, and only
|
||||
* search dig_table_lo[]. Thus, dig_table_lo[] must always contain
|
||||
* the lower character of the pair.
|
||||
*
|
||||
* The digraph tables are based on those in the excellent editor Elvis,
|
||||
* with some additions for those, like me, who are used to VT320 or
|
||||
* VT420 terminals.
|
||||
*/
|
||||
|
||||
#define DiLo(x) x,
|
||||
#define DiHi(x)
|
||||
#define DiDi(x)
|
||||
|
||||
/*
|
||||
* Digraph tables. Note that, when adding a new digraph, the character
|
||||
* of the pair with the lowest value, *must* be in the DiLo column.
|
||||
* The higher of the pair goes in DiHi, and the digraph itself in DiDi.
|
||||
*/
|
||||
|
||||
unsigned char dig_table_lo[DIG_TABLE_SIZE] =
|
||||
{
|
||||
#include "digraph.inc"
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
#undef DiLo
|
||||
#undef DiHi
|
||||
#undef DiDi
|
||||
#define DiLo(x)
|
||||
#define DiHi(x) x,
|
||||
#define DiDi(x)
|
||||
|
||||
unsigned char dig_table_hi[DIG_TABLE_SIZE] =
|
||||
{
|
||||
#include "digraph.inc"
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
#undef DiLo
|
||||
#undef DiHi
|
||||
#undef DiDi
|
||||
#define DiLo(x)
|
||||
#define DiHi(x)
|
||||
#define DiDi(x) x,
|
||||
|
||||
unsigned char dig_table_di[DIG_TABLE_SIZE] =
|
||||
{
|
||||
#include "digraph.inc"
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* enter_digraph: The BIND function ENTER_DIGRAPH.
|
||||
*/
|
||||
void enter_digraph(char key, char *ptr)
|
||||
{
|
||||
last_input_screen->digraph_hit = 1; /* Just stuff away first character. */
|
||||
}
|
||||
|
||||
/*
|
||||
* get_digraph: Called by edit_char() when a digraph entry is activated.
|
||||
* Looks up a digraph given char c1 and the global char
|
||||
* last_input_screen->digraph_hit.
|
||||
*/
|
||||
unsigned char get_digraph(unsigned char c1)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char c,
|
||||
c2 = last_input_screen->digraph_first;
|
||||
|
||||
last_input_screen->digraph_hit = 0;
|
||||
if (c1 > c2) /* Make sure we have the lowest one in c1. */
|
||||
c = c1, c1 = c2, c2 = c;
|
||||
while (dig_table_lo[i])
|
||||
{ /* Find digraph and return it. */
|
||||
if ((dig_table_lo[i] == c1) && (dig_table_hi[i] == c2))
|
||||
return dig_table_di[i];
|
||||
i++;
|
||||
}
|
||||
return 0; /* Failed lookup. */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set_translation: Called when the TRANSLATION variable is SET.
|
||||
* Attempts to load a new translation table.
|
||||
*/
|
||||
void set_translation(Window *win, char *tablename, int unused)
|
||||
{
|
||||
FILE *table;
|
||||
unsigned char temp_table[512];
|
||||
char *filename = NULL, *s;
|
||||
int inputs[8];
|
||||
int j,
|
||||
c = 0;
|
||||
char buffer[BIG_BUFFER_SIZE + 1];
|
||||
|
||||
if (!tablename)
|
||||
{
|
||||
translation = 0;
|
||||
return;
|
||||
}
|
||||
for (s = tablename; *s; s++)
|
||||
{
|
||||
if (isspace((unsigned char)*s))
|
||||
{
|
||||
*s = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tablename = upper(tablename);
|
||||
|
||||
/* Check for transparent mode; ISO-8859/1, Latin-1 */
|
||||
if (!strcmp("LATIN_1", tablename))
|
||||
{
|
||||
translation = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Else try loading the translation table from disk. */
|
||||
malloc_strcpy(&filename, TRANSLATION_PATH "/");
|
||||
malloc_strcat(&filename, tablename);
|
||||
if ( !(table = uzfopen(&filename, ".", 0)) )
|
||||
{
|
||||
say("Cannot open character table definition \"%s\" !",
|
||||
tablename);
|
||||
set_string_var(TRANSLATION_VAR, NULL);
|
||||
new_free(&filename);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Any problems in the translation tables between hosts are
|
||||
* almost certain to be caused here.
|
||||
* many scanf implementations do not work as defined. In particular,
|
||||
* scanf should ignore white space including new lines (many stop
|
||||
* at the new line character, hence the fgets and sscanf workaround),
|
||||
* many fail to read 0xab as a hexadecimal number (failing on the
|
||||
* x) despite the 0x being defined as optionally existing on input,
|
||||
* and others zero out all the output variables if there is trailing
|
||||
* non white space in the format string which doesn't appear on the
|
||||
* input. Overall, the standard I/O libraries have a tendancy not
|
||||
* to be very standard.
|
||||
*/
|
||||
|
||||
while (fgets(buffer, 80, table))
|
||||
{
|
||||
sscanf(buffer, "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x",
|
||||
inputs+0, inputs+1, inputs+2, inputs+3,
|
||||
inputs+4, inputs+5, inputs+6, inputs+7);
|
||||
for (j = 0; j<8; j++)
|
||||
temp_table[c++] = (unsigned char) inputs[j];
|
||||
}
|
||||
fclose(table);
|
||||
new_free(&filename);
|
||||
if (c == 512)
|
||||
{
|
||||
for (c = 0; c <= 255; c++)
|
||||
{
|
||||
transToClient[c] = temp_table[c];
|
||||
transFromClient[c] = temp_table[c | 256];
|
||||
}
|
||||
#if 0
|
||||
for (c = 0; c <= 255; c++)
|
||||
transToClient[c] = c;
|
||||
#endif
|
||||
|
||||
translation = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
say("Error loading translation table \"%s\" !", tablename);
|
||||
set_string_var(TRANSLATION_VAR, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* digraph: The /DIGRAPH command with facilities.
|
||||
* This routine is *NOT* finished yet.
|
||||
*/
|
||||
|
||||
BUILT_IN_COMMAND(digraph)
|
||||
{
|
||||
char *arg;
|
||||
u_char c1,
|
||||
c2 = '\0',
|
||||
c3 = '\0';
|
||||
int len,
|
||||
i;
|
||||
|
||||
if ((arg = next_arg(args, &args)) && (*arg == '-'))
|
||||
{
|
||||
arg++;
|
||||
if ((len = strlen(arg)) == 0)
|
||||
{
|
||||
say("Unknown or missing flag.");
|
||||
return;
|
||||
}
|
||||
if (my_strnicmp(arg, "add", len) == 0)
|
||||
{
|
||||
/*
|
||||
* Add a digraph to the table.
|
||||
* I *know*. This *is* a kludge.
|
||||
*/
|
||||
if ((i = strlen((char *)dig_table_lo)) ==
|
||||
DIG_TABLE_SIZE - 1)
|
||||
say("Sorry, digraph table full.");
|
||||
else
|
||||
{
|
||||
while ((c1 = my_getarg(&args)) &&
|
||||
(c2 = my_getarg(&args)) &&
|
||||
(c3 = my_getarg(&args)))
|
||||
{
|
||||
/* Pass c1 to get_digraph() */
|
||||
last_input_screen->digraph_first = c1;
|
||||
if (get_digraph(c2) == 0)
|
||||
{
|
||||
dig_table_di[i] = c3;
|
||||
/* Make sure c1 <= c2 */
|
||||
if (c1 > c2)
|
||||
c3 = c1, c1 = c2, c2 = c3;
|
||||
dig_table_lo[i] = c1;
|
||||
dig_table_hi[i] = c2;
|
||||
i++;
|
||||
dig_table_lo[i] =
|
||||
dig_table_hi[i] =
|
||||
dig_table_di[i] =
|
||||
(unsigned char) 0;
|
||||
digraph_changed = 1;
|
||||
say("Digraph added to table.");
|
||||
}
|
||||
else
|
||||
{
|
||||
say("Digraph already defined in table.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!c2 || !c3)
|
||||
say("Unknown or missing argument.");
|
||||
}
|
||||
|
||||
}
|
||||
else if (my_strnicmp(arg, "remove", len) == 0)
|
||||
{
|
||||
|
||||
/* Remove a digraph from the table. */
|
||||
if ((i = strlen((char *)dig_table_lo)) == 0)
|
||||
say("Digraph table is already empty.");
|
||||
else
|
||||
{
|
||||
if ((c1 = my_getarg(&args)) &&
|
||||
(c2 = my_getarg(&args)))
|
||||
{
|
||||
i = 0;
|
||||
if (c1 > c2)
|
||||
c3 = c1, c1 = c2, c2 = c3;
|
||||
while (dig_table_lo[i])
|
||||
{
|
||||
if ((dig_table_lo[i] == c1) &&
|
||||
(dig_table_hi[i] == c2))
|
||||
/*
|
||||
* strcpy() is not guaranteed for
|
||||
* overlapping copying, but this one
|
||||
* is high -> low. Ought to be fixed.
|
||||
*/
|
||||
/* re-indent this block - phone, jan 1993. */
|
||||
{
|
||||
strcpy(((char *)dig_table_lo + i),
|
||||
(char *)(dig_table_lo + (i + 1)));
|
||||
strcpy((char *)(dig_table_hi + i),
|
||||
(char *)(dig_table_hi + (i + 1)));
|
||||
strcpy((char *)(dig_table_di + i),
|
||||
(char *)(dig_table_di + (i + 1)));
|
||||
digraph_changed = 1;
|
||||
put_it("Digraph removed from table.");
|
||||
return;
|
||||
}
|
||||
/* much better */
|
||||
i++;
|
||||
}
|
||||
say("Digraph not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (my_strnicmp(arg, "clear", len) == 0)
|
||||
{
|
||||
|
||||
/* Clear digraph table. */
|
||||
dig_table_lo[0] = dig_table_hi[0] = dig_table_di[0] =
|
||||
(unsigned char) 0;
|
||||
digraph_changed = 1;
|
||||
say("Digraph table cleared.");
|
||||
|
||||
}
|
||||
else
|
||||
say("Unknown flag.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Display digraph table. */
|
||||
char buffer1[8];
|
||||
char buffer2[192];
|
||||
|
||||
say("Digraph table:");
|
||||
buffer2[0] = (char) 0;
|
||||
i = 0;
|
||||
while(dig_table_lo[i])
|
||||
{
|
||||
sprintf(buffer1, "%c%c %c ", dig_table_lo[i],
|
||||
dig_table_hi[i], dig_table_di[i]);
|
||||
strcat(buffer2, buffer1);
|
||||
if ((++i % 10) == 0)
|
||||
{
|
||||
put_it(buffer2);
|
||||
buffer2[0] = (char) 0;
|
||||
}
|
||||
}
|
||||
if (buffer2[0])
|
||||
put_it(buffer2);
|
||||
sprintf(buffer2, "%d digraphs listed.", i);
|
||||
say(buffer2);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char my_getarg(char **args)
|
||||
{
|
||||
unsigned char *arg;
|
||||
|
||||
arg = (unsigned char *)next_arg(*args, args);
|
||||
if (!args || !*args || !arg)
|
||||
return '\0';
|
||||
/* Don't trust isdigit() with 8 bits. */
|
||||
if ((*arg <= '9') && (*arg >= '0'))
|
||||
{
|
||||
unsigned char i = *arg & 0x0f;
|
||||
while ( *(++arg) )
|
||||
i = (i * 10) + (*arg & 0x0f);
|
||||
return i;
|
||||
}
|
||||
else if ( (*arg == '!') && (*(arg + 1)) )
|
||||
return *(arg + 1) | 0x80;
|
||||
return *arg;
|
||||
}
|
||||
|
||||
void save_digraphs(FILE *fp)
|
||||
{
|
||||
if (digraph_changed)
|
||||
{
|
||||
|
||||
int i = 0;
|
||||
char *command = "\nDIGRAPH -ADD ";
|
||||
|
||||
fprintf(fp, "DIGRAPH -CLEAR");
|
||||
fprintf(fp, command);
|
||||
while(1)
|
||||
{
|
||||
fprintf(fp, "%d %d %d ", dig_table_lo[i],
|
||||
dig_table_hi[i], dig_table_di[i]);
|
||||
if (!dig_table_lo[++i])
|
||||
break;
|
||||
if (!(i % 5))
|
||||
fprintf(fp, command);
|
||||
}
|
||||
fputc('\n', fp);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
604
source/user.c
Normal file
604
source/user.c
Normal file
@@ -0,0 +1,604 @@
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: user.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(user_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "ircaux.h"
|
||||
#include "list.h"
|
||||
#include "hash.h"
|
||||
#include "struct.h"
|
||||
#include "userlist.h"
|
||||
#include "misc.h"
|
||||
#include "output.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
#define USERHOST_HASHSIZE 501
|
||||
#define USERCHAN_HASHSIZE 20
|
||||
|
||||
#ifdef WANT_USERLIST
|
||||
HashEntry UserListByHost_Table[USERHOST_HASHSIZE];
|
||||
HashEntry UserListByChannel_Table[USERCHAN_HASHSIZE];
|
||||
|
||||
UserList *user_list = NULL;
|
||||
|
||||
static long hash_name(char *str, unsigned int size)
|
||||
{
|
||||
const unsigned char *p = (const unsigned char *)str;
|
||||
unsigned long g, hash = 0;
|
||||
if (!p) return -1;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '*' || *p =='?' || *p == ',')
|
||||
return -1;
|
||||
hash = (hash << 4) + ((*p >= 'A' && *p <= 'Z') ? (*p+32) : *p);
|
||||
if ((g = hash & 0xF0000000))
|
||||
hash ^= g >> 24;
|
||||
hash &= ~g;
|
||||
p++;
|
||||
}
|
||||
return (hash % size);
|
||||
}
|
||||
|
||||
/* userlist entry can be put into our tier 1 */
|
||||
static inline void add_userlist_to_tier_1(UserList *ptr, unsigned long hvalue)
|
||||
{
|
||||
ptr->next = (UserList *) UserListByHost_Table[hvalue].list;
|
||||
/* assign our new linked list into array spot */
|
||||
UserListByHost_Table[hvalue].list = (void *) ptr;
|
||||
/* quick tally of userlists in chain in this array spot */
|
||||
UserListByHost_Table[hvalue].links++;
|
||||
}
|
||||
|
||||
static inline void add_userlist_to_tier_2(UserList *ptr, unsigned long hvalue)
|
||||
{
|
||||
ptr->next = (UserList *) UserListByChannel_Table[hvalue].list;
|
||||
/* assign our new linked list into array spot */
|
||||
UserListByChannel_Table[hvalue].list = (void *) ptr;
|
||||
/* quick tally of userlists in chain in this array spot */
|
||||
UserListByChannel_Table[hvalue].links++;
|
||||
}
|
||||
|
||||
static inline void add_userlist_to_tier_3(UserList *uptr)
|
||||
{
|
||||
add_to_list((List **)&user_list, (List *)uptr);
|
||||
}
|
||||
|
||||
void add_userlist(UserList *uptr)
|
||||
{
|
||||
char *ptr;
|
||||
long hvalue;
|
||||
if (!(ptr = strrchr(uptr->host, '@')))
|
||||
{
|
||||
add_userlist_to_tier_3(uptr);
|
||||
return;
|
||||
}
|
||||
if ((hvalue = hash_name(ptr, USERHOST_HASHSIZE)) != -1)
|
||||
{
|
||||
add_userlist_to_tier_1(uptr, hvalue);
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
if (!strchr(uptr->channels, '*'))
|
||||
{
|
||||
char *channel, *ptr;
|
||||
channel = alloca(strlen(uptr->channels)+1);
|
||||
strcpy(channel, uptr->channels);
|
||||
while ((ptr = next_in_comma_list(channel, &channel)))
|
||||
{
|
||||
if (!*ptr)
|
||||
return;
|
||||
hvalue = hash_name(ptr, USERCHAN_HASHSIZE);
|
||||
add_userlist_to_tier_2(uptr, hvalue);
|
||||
if (channel && *channel)
|
||||
{
|
||||
UserList *newptr;
|
||||
newptr = new_malloc(sizeof(UserList));
|
||||
memcpy(newptr, uptr, sizeof(UserList));
|
||||
uptr = newptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((hvalue = hash_name(uptr->channels, USERCHAN_HASHSIZE)) != -1)
|
||||
{
|
||||
add_userlist_to_tier_2(uptr, hvalue);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
add_userlist_to_tier_3(uptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* move_link_to_top: used by find routine, brings link
|
||||
* to the top of the list in the specific array location
|
||||
*/
|
||||
static inline void move_link_to_top(UserList *tmp, UserList *prev, HashEntry *location)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
UserList *old_list;
|
||||
old_list = (UserList *) location->list;
|
||||
location->list = (void *) tmp;
|
||||
prev->next = tmp->next;
|
||||
tmp->next = old_list;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_link_from_list: used by find routine, removes link
|
||||
* from our chain of hashed entries.
|
||||
*/
|
||||
static inline void remove_link_from_list(UserList *tmp, UserList *prev, HashEntry *location)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
/* remove the link from the middle of the list */
|
||||
prev->next = tmp->next;
|
||||
}
|
||||
else {
|
||||
/* unlink the first link, and connect next one up */
|
||||
location->list = (void *) tmp->next;
|
||||
}
|
||||
/* set tmp's next to NULL, as its unlinked now */
|
||||
tmp->next = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline UserList *find_userlist_tier3(char *host, char *channel, int remove)
|
||||
{
|
||||
register UserList *tmp;
|
||||
for (tmp = user_list; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (wild_match(tmp->host, host) || !my_stricmp(tmp->host, host))
|
||||
{
|
||||
if (check_channel_match(tmp->channels, channel) || !strcmp(tmp->channels, channel))
|
||||
{
|
||||
if (remove)
|
||||
tmp = (UserList *)remove_from_list((List **)&user_list, tmp->nick);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline UserList *find_userlist_tier1(char *userhost, char *channel, unsigned long hvalue, int remove)
|
||||
{
|
||||
HashEntry *location;
|
||||
register UserList *tmp, *prev = NULL;
|
||||
location = &UserListByHost_Table[hvalue];
|
||||
for (tmp = (UserList *)location->list; tmp; prev = tmp, tmp = tmp->next)
|
||||
{
|
||||
if ((wild_match(tmp->host, userhost) ||!my_stricmp(tmp->host, userhost)) && check_channel_match(tmp->channels, channel))
|
||||
{
|
||||
if (remove)
|
||||
{
|
||||
location->links--;
|
||||
remove_link_from_list(tmp, prev, location);
|
||||
} else
|
||||
move_link_to_top(tmp, prev, location);
|
||||
location->hits++;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline UserList *find_userlist_tier2(char *userhost,unsigned long hvalue, int remove)
|
||||
{
|
||||
HashEntry *location;
|
||||
register UserList *tmp, *prev = NULL;
|
||||
location = &UserListByChannel_Table[hvalue];
|
||||
for (tmp = (UserList *)location->list; tmp; prev = tmp, tmp = tmp->next)
|
||||
{
|
||||
if (wild_match(tmp->host, userhost) || !my_stricmp(tmp->host, userhost))
|
||||
{
|
||||
if (remove)
|
||||
{
|
||||
location->links--;
|
||||
remove_link_from_list(tmp, prev, location);
|
||||
} else
|
||||
move_link_to_top(tmp, prev, location);
|
||||
location->hits++;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UserList *find_userlist(char *userhost, char *channel, int remove)
|
||||
{
|
||||
char *ptr;
|
||||
long hvalue;
|
||||
/*char *host = clear_server_flags(userhost);*/
|
||||
char *host = userhost;
|
||||
if (!(ptr = strrchr(userhost, '@')))
|
||||
return find_userlist_tier3(host, channel, remove);
|
||||
if ((hvalue = hash_name(ptr, USERHOST_HASHSIZE)) != -1)
|
||||
{
|
||||
UserList *tmp;
|
||||
if ((tmp = find_userlist_tier1(host, channel, hvalue, remove)))
|
||||
return tmp;
|
||||
}
|
||||
if ((hvalue = hash_name(channel, USERCHAN_HASHSIZE)) != -1)
|
||||
{
|
||||
UserList *tmp;
|
||||
if ((tmp = find_userlist_tier2(host, hvalue, remove)))
|
||||
return tmp;
|
||||
}
|
||||
/* if we got here this is shitty */
|
||||
return find_userlist_tier3(host, channel, remove);
|
||||
}
|
||||
|
||||
UserList *create_sorted_userlist(void)
|
||||
{
|
||||
|
||||
UserList *tmp = NULL, *t, *new;
|
||||
int i;
|
||||
for (i = 0; i < USERHOST_HASHSIZE; i++)
|
||||
{
|
||||
t = (UserList *)UserListByHost_Table[i].list;
|
||||
while (t)
|
||||
{
|
||||
new = new_malloc(sizeof(UserList));
|
||||
memcpy(new, t, sizeof(UserList));
|
||||
add_to_list((List **)&tmp, (List *)new);
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < USERCHAN_HASHSIZE; i++)
|
||||
{
|
||||
t = (UserList *)UserListByChannel_Table[i].list;
|
||||
while (t)
|
||||
{
|
||||
new = new_malloc(sizeof(UserList));
|
||||
memcpy(new, t, sizeof(UserList));
|
||||
add_to_list((List **)&tmp, (List *)new);
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
for (t = user_list; t; t = t->next)
|
||||
{
|
||||
new = new_malloc(sizeof(UserList));
|
||||
memcpy(new, t, sizeof(UserList));
|
||||
add_to_list((List **)&tmp, (List *)new);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void destroy_sorted_userlist(UserList **uptr)
|
||||
{
|
||||
UserList *t;
|
||||
if (!uptr || !*uptr)
|
||||
return;
|
||||
while (*uptr)
|
||||
{
|
||||
t = (*uptr)->next;
|
||||
new_free(uptr);
|
||||
*uptr = t;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
UserHist *next_userlist(UserList *uptr, int *size)
|
||||
{
|
||||
long hvalue = -1;
|
||||
static HashEntry *location = NULL;
|
||||
|
||||
if (!uptr)
|
||||
{
|
||||
location = &UserListByHost_Table[0];
|
||||
*size = USERHOST_HASHSIZE;
|
||||
hvalue = 0;
|
||||
while(((UserList *)location[hvalue].list) == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue == USERHOST_HASHSIZE && *size == USERHOST_HASHSIZE)
|
||||
{
|
||||
location = &UserListByChannel_Table[0];
|
||||
hvalue = 0;
|
||||
*size = USERCHAN_HASHSIZE;
|
||||
}
|
||||
else if (hvalue == USERCHAN_HASHSIZE && *size == USERCHAN_HASHSIZE)
|
||||
{
|
||||
hvalue = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hvalue != -1 && location[hvalue].list != NULL)
|
||||
return ((UserHist *)location[hvalue].list);
|
||||
location = NULL;
|
||||
*size = -1;
|
||||
return (user_list);
|
||||
}
|
||||
if (uptr->next)
|
||||
return uptr->next;
|
||||
else if (location && !uptr->next)
|
||||
{
|
||||
if (*size > -1 && location)
|
||||
{
|
||||
if (*size == USERHOST_HASHSIZE)
|
||||
hvalue = hash_name(strrchr(uptr->host, '@'), *size);
|
||||
else if (*size == USERCHAN_HASHSIZE)
|
||||
hvalue = hash_name(uptr->channels, *size);
|
||||
if (hvalue == -1)
|
||||
{
|
||||
location = NULL;
|
||||
*size = -1;
|
||||
return user_list;
|
||||
}
|
||||
hvalue++;
|
||||
if (*size == USERHOST_HASHSIZE && hvalue >= USERHOST_HASHSIZE)
|
||||
{
|
||||
/* end of current list */
|
||||
location = &UserListByChannel_Table[0];
|
||||
*size = USERCHAN_HASHSIZE;
|
||||
}
|
||||
while (((UserList *)location[hvalue].list) == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue >= USERHOST_HASHSIZE)
|
||||
{
|
||||
location = &UserListByChannel_Table[0];
|
||||
hvalue = 0;
|
||||
*size = USERCHAN_HASHSIZE;
|
||||
}
|
||||
else if (*size == USERCHAN_HASHSIZE && hvalue == USERCHAN_HASHSIZE)
|
||||
break;
|
||||
}
|
||||
if (location[hvalue].list != NULL)
|
||||
return ((UserList *)location[hvalue].list);
|
||||
location = NULL;
|
||||
*size = -1;
|
||||
return user_list;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int check_best_passwd(char *passwd, char *test)
|
||||
{
|
||||
if (passwd && test)
|
||||
return !checkpass(test, passwd) ? 1 : 0;
|
||||
/* return !strcmp(passwd, test) ? 1 : 0;*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
UserList *find_bestmatch(char *nick, char *userhost, char *channel, char *passwd)
|
||||
{
|
||||
UserList *best = NULL;
|
||||
UserList *best_passwd = NULL;
|
||||
register UserList *tmp;
|
||||
long hvalue = 0;
|
||||
int best_user_match = 0,
|
||||
best_chan_match = 0;
|
||||
int chan_match,
|
||||
user_match,
|
||||
passwd_match = 0;
|
||||
char *check;
|
||||
|
||||
/*check = clear_server_flags(userhost);*/
|
||||
check = userhost;
|
||||
if ((hvalue = hash_name(strrchr(check, '@'), USERHOST_HASHSIZE)) != -1)
|
||||
{
|
||||
for (tmp = (UserList *)UserListByHost_Table[hvalue].list; tmp; tmp = tmp->next)
|
||||
{
|
||||
user_match = wild_match(tmp->host, check);
|
||||
chan_match = check_channel_match(tmp->channels, channel);
|
||||
if (user_match > best_user_match && chan_match > best_chan_match)
|
||||
{
|
||||
best_chan_match = chan_match;
|
||||
best_user_match = user_match;
|
||||
best = tmp;
|
||||
if ((passwd_match = check_best_passwd(tmp->password, passwd)))
|
||||
best_passwd = tmp;
|
||||
}
|
||||
else if (best_user_match && user_match == best_user_match)
|
||||
{
|
||||
if (chan_match > best_chan_match)
|
||||
{
|
||||
best_chan_match = chan_match;
|
||||
best_user_match = user_match;
|
||||
best = tmp;
|
||||
if ((passwd_match = check_best_passwd(tmp->password, passwd)))
|
||||
best_passwd = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((hvalue = hash_name(channel, USERCHAN_HASHSIZE)) != -1)
|
||||
{
|
||||
for (tmp = (UserList *)UserListByChannel_Table[hvalue].list; tmp; tmp = tmp->next)
|
||||
{
|
||||
user_match = wild_match(tmp->host, check);
|
||||
if (user_match > best_user_match)
|
||||
{
|
||||
best_user_match = user_match;
|
||||
best = tmp;
|
||||
if ((passwd_match = check_best_passwd(tmp->password, passwd)))
|
||||
best_passwd = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hvalue == -1)
|
||||
{
|
||||
for (hvalue = 0; hvalue < USERCHAN_HASHSIZE; hvalue++)
|
||||
{
|
||||
for (tmp = (UserList *)UserListByChannel_Table[hvalue].list; tmp; tmp = tmp->next)
|
||||
{
|
||||
user_match = wild_match(tmp->host, check);
|
||||
chan_match = check_channel_match(tmp->channels, channel);
|
||||
if (user_match > best_user_match && chan_match > best_chan_match)
|
||||
{
|
||||
best_user_match = user_match;
|
||||
best_chan_match = chan_match;
|
||||
best = tmp;
|
||||
if ((passwd_match = check_best_passwd(tmp->password, passwd)))
|
||||
best_passwd = tmp;
|
||||
}
|
||||
else if (best_user_match && user_match == best_user_match)
|
||||
{
|
||||
if (chan_match > best_chan_match)
|
||||
{
|
||||
best_chan_match = chan_match;
|
||||
best_user_match = user_match;
|
||||
best = tmp;
|
||||
if ((passwd_match = check_best_passwd(tmp->password, passwd)))
|
||||
best_passwd = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (tmp = user_list; tmp; tmp = tmp->next)
|
||||
{
|
||||
if ((chan_match = check_channel_match(tmp->channels, channel)) > 0)
|
||||
{
|
||||
user_match = wild_match(tmp->host, check);
|
||||
if (user_match > best_user_match && chan_match > best_chan_match)
|
||||
{
|
||||
best_chan_match = chan_match;
|
||||
best_user_match = user_match;
|
||||
best = tmp;
|
||||
if ((passwd_match = check_best_passwd(tmp->password, passwd)))
|
||||
best_passwd = tmp;
|
||||
}
|
||||
else if (best_user_match && user_match == best_user_match)
|
||||
{
|
||||
if (chan_match > best_chan_match)
|
||||
{
|
||||
best_chan_match = chan_match;
|
||||
best_user_match = user_match;
|
||||
best = tmp;
|
||||
if ((passwd_match = check_best_passwd(tmp->password, passwd)))
|
||||
best_passwd = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (passwd)
|
||||
{
|
||||
if (!best_passwd)
|
||||
return NULL;
|
||||
else if (best_passwd)
|
||||
return best_passwd;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
BUILT_IN_COMMAND(debug_user)
|
||||
{
|
||||
HashEntry *location;
|
||||
UserList *user;
|
||||
int i;
|
||||
int tier1 = 0, tier2 = 0, tier3 = 0;
|
||||
for (i = 0; i < USERHOST_HASHSIZE; i++)
|
||||
{
|
||||
user = (UserList *)UserListByHost_Table[i].list;
|
||||
location = &UserListByHost_Table[i];
|
||||
while (user)
|
||||
{
|
||||
tier1++;
|
||||
put_it("Tier1[%d] %d %d %s %s", i, location->links, location->hits, user->host, user->channels);
|
||||
user = user->next;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < USERCHAN_HASHSIZE; i++)
|
||||
{
|
||||
user = (UserList *)UserListByChannel_Table[i].list;
|
||||
location = &UserListByChannel_Table[i];
|
||||
while (user)
|
||||
{
|
||||
tier2++;
|
||||
put_it("Tier2[%d] %d %d %s %s", i, location->links, location->hits, user->host, user->channels);
|
||||
user = user->next;
|
||||
}
|
||||
}
|
||||
for (tier3 = 0, user = user_list; user; user = user->next, tier3++)
|
||||
put_it("Tier3[%d] %s %s", tier3, user->host, user->channels);
|
||||
put_it("Tier1 = [%d] Tier2 = [%d] Tier3 = [%d]", tier1, tier2, tier3);
|
||||
|
||||
}
|
||||
|
||||
UserList *next_userlist(UserList *uptr, int *size, void **location)
|
||||
{
|
||||
unsigned long hvalue = -1;
|
||||
/* we start iterating the list will a null pointer */
|
||||
if (!uptr)
|
||||
{
|
||||
*location = &UserListByHost_Table[0];
|
||||
*size = USERHOST_HASHSIZE;
|
||||
hvalue = 0;
|
||||
while(((UserList *)((HashEntry*)*location)[hvalue].list) == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue == USERHOST_HASHSIZE && *size == USERHOST_HASHSIZE)
|
||||
{
|
||||
*location = &UserListByChannel_Table[0];
|
||||
hvalue = 0;
|
||||
*size = USERCHAN_HASHSIZE;
|
||||
}
|
||||
else if (hvalue == USERCHAN_HASHSIZE && *size == USERCHAN_HASHSIZE)
|
||||
{
|
||||
hvalue = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hvalue != -1 && ((HashEntry *)*location)[hvalue].list != NULL)
|
||||
return ((UserList *)((HashEntry *)*location)[hvalue].list);
|
||||
*location = NULL;
|
||||
*size = -1;
|
||||
return (user_list);
|
||||
}
|
||||
else if (uptr->next)
|
||||
return uptr->next;
|
||||
else if (*location)
|
||||
{
|
||||
if (*size > -1)
|
||||
{
|
||||
if (*size == USERHOST_HASHSIZE)
|
||||
hvalue = hash_name(strrchr(uptr->host, '@'), *size);
|
||||
else if (*size == USERCHAN_HASHSIZE)
|
||||
hvalue = hash_name(uptr->channels, *size);
|
||||
if (hvalue == -1)
|
||||
{
|
||||
*location = NULL;
|
||||
*size = -1;
|
||||
return user_list;
|
||||
}
|
||||
hvalue++;
|
||||
if (*size == USERHOST_HASHSIZE && hvalue >= USERHOST_HASHSIZE)
|
||||
{
|
||||
/* end of current list */
|
||||
*location = &UserListByChannel_Table[0];
|
||||
*size = USERCHAN_HASHSIZE;
|
||||
}
|
||||
while (((UserList *)((HashEntry *)*location)[hvalue].list) == NULL)
|
||||
{
|
||||
hvalue++;
|
||||
if (hvalue >= USERHOST_HASHSIZE)
|
||||
{
|
||||
*location = &UserListByChannel_Table[0];
|
||||
hvalue = 0;
|
||||
*size = USERCHAN_HASHSIZE;
|
||||
}
|
||||
else if (*size == USERCHAN_HASHSIZE && hvalue >= USERCHAN_HASHSIZE)
|
||||
{
|
||||
hvalue = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hvalue != -1 && ((HashEntry *)*location)[hvalue].list != NULL)
|
||||
return ((UserList *)((HashEntry *)*location)[hvalue].list);
|
||||
*location = NULL;
|
||||
*size = -1;
|
||||
return user_list;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
1717
source/userlist.c
Normal file
1717
source/userlist.c
Normal file
File diff suppressed because it is too large
Load Diff
1722
source/vars.c
Normal file
1722
source/vars.c
Normal file
File diff suppressed because it is too large
Load Diff
1074
source/who.c
Normal file
1074
source/who.c
Normal file
File diff suppressed because it is too large
Load Diff
407
source/whowas.c
Normal file
407
source/whowas.c
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* whowas.c a linked list buffer of people who have left your channel
|
||||
* mainly used for ban prot and stats stuff.
|
||||
* Should even speed stuff up a bit too.
|
||||
*
|
||||
* Written by Scott H Kilau
|
||||
*
|
||||
* Copyright(c) 1995
|
||||
* Modified Colten Edwards 1996
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: whowas.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
CVS_REVISION(whowas_c)
|
||||
#include "struct.h"
|
||||
|
||||
#include "vars.h"
|
||||
#include "ircaux.h"
|
||||
#include "window.h"
|
||||
#include "who.h"
|
||||
#include "hook.h"
|
||||
#include "input.h"
|
||||
#include "names.h"
|
||||
#include "alias.h"
|
||||
#include "output.h"
|
||||
#include "numbers.h"
|
||||
#include "status.h"
|
||||
#include "screen.h"
|
||||
#include "commands.h"
|
||||
#include "config.h"
|
||||
#include "list.h"
|
||||
#include "userlist.h"
|
||||
#include "misc.h"
|
||||
#include "hash.h"
|
||||
#include "hash2.h"
|
||||
#define MAIN_SOURCE
|
||||
#include "modval.h"
|
||||
|
||||
/*
|
||||
#include "ctimers.h"
|
||||
#include "edit2.h"
|
||||
#include "edit3.h"
|
||||
#include "edit4.h"
|
||||
*/
|
||||
|
||||
#include "userlist.h"
|
||||
#include "whowas.h"
|
||||
|
||||
WhowasWrapList whowas_userlist_list = { 0 };
|
||||
WhowasWrapList whowas_reg_list = { 0 };
|
||||
WhowasWrapList whowas_splitin_list = { 0 };
|
||||
|
||||
WhowasChanList *whowas_chan_list = NULL;
|
||||
|
||||
static int whowas_userlist_count = 0;
|
||||
static int whowas_reg_count = 0;
|
||||
static int whowas_chan_count = 0;
|
||||
|
||||
extern WhowasList *check_whowas_buffer(char *nick, char *userhost, char *channel, int unlink)
|
||||
{
|
||||
WhowasList *tmp = NULL;
|
||||
if (!(tmp = find_userhost_channel(userhost, channel, unlink, &whowas_userlist_list)))
|
||||
tmp = find_userhost_channel(userhost, channel, unlink, &whowas_reg_list);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
extern WhowasList * check_whowas_nick_buffer(char *nick, char *channel, int unlink)
|
||||
{
|
||||
WhowasList *tmp = NULL, *last = NULL;
|
||||
for (tmp = next_userhost(&whowas_userlist_list, NULL); tmp; tmp = next_userhost(&whowas_userlist_list, tmp))
|
||||
{
|
||||
if (!my_stricmp(tmp->nicklist->nick, nick) && !my_stricmp(tmp->channel, channel))
|
||||
{
|
||||
if (unlink)
|
||||
{
|
||||
last = find_userhost_channel(tmp->nicklist->host, tmp->channel, 1, &whowas_userlist_list);
|
||||
tmp = NULL;
|
||||
}
|
||||
return last?last:tmp;
|
||||
}
|
||||
}
|
||||
for (tmp = next_userhost(&whowas_reg_list, NULL); tmp; tmp = next_userhost(&whowas_reg_list, tmp))
|
||||
{
|
||||
if (!my_stricmp(tmp->nicklist->nick, nick) && !my_stricmp(tmp->channel, channel))
|
||||
{
|
||||
if (unlink)
|
||||
{
|
||||
last = find_userhost_channel(tmp->nicklist->host, tmp->channel, 1, &whowas_reg_list);
|
||||
tmp = NULL;
|
||||
}
|
||||
return last?last:tmp;
|
||||
}
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
extern WhowasList * check_whosplitin_buffer(char *nick, char *userhost, char *channel, int unlink)
|
||||
{
|
||||
WhowasList *tmp = NULL;
|
||||
tmp = find_userhost_channel(userhost, channel, unlink, &whowas_splitin_list);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void add_to_whowas_buffer(NickList *nicklist, char *channel, char *server1, char *server2)
|
||||
{
|
||||
WhowasList *new;
|
||||
if (!nicklist || !nicklist->nick)
|
||||
return;
|
||||
|
||||
if (nicklist->userlist)
|
||||
{
|
||||
if (whowas_userlist_count >= whowas_userlist_max)
|
||||
{
|
||||
whowas_userlist_count -=
|
||||
remove_oldest_whowas(&whowas_userlist_list, 0,
|
||||
(whowas_userlist_max + 1) - whowas_userlist_count);
|
||||
}
|
||||
new = (WhowasList *) new_malloc(sizeof(WhowasList));
|
||||
new->has_ops = nick_isop(nicklist);
|
||||
new->nicklist = nicklist;
|
||||
malloc_strcpy(&(new->channel), channel);
|
||||
malloc_strcpy(&(new->server1), server1);
|
||||
if (server2)
|
||||
malloc_strcpy(&(new->server2), server2);
|
||||
new->time = now;
|
||||
add_whowas_userhost_channel(new, &whowas_userlist_list);
|
||||
whowas_userlist_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (whowas_reg_count >= whowas_reg_max)
|
||||
{
|
||||
whowas_reg_count -=
|
||||
remove_oldest_whowas(&whowas_reg_list, 0,
|
||||
(whowas_reg_max + 1) - whowas_reg_count);
|
||||
}
|
||||
new = (WhowasList *) new_malloc(sizeof(WhowasList));
|
||||
new->has_ops = nick_isop(nicklist);
|
||||
new->nicklist = (NickList *) nicklist;
|
||||
malloc_strcpy(&(new->channel), channel);
|
||||
malloc_strcpy(&(new->server1), server1);
|
||||
malloc_strcpy(&(new->server2), server2);
|
||||
new->time = now;
|
||||
add_whowas_userhost_channel(new, &whowas_reg_list);
|
||||
whowas_reg_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void add_to_whosplitin_buffer(NickList *nicklist, char *channel, char *server1, char *server2)
|
||||
{
|
||||
WhowasList *new;
|
||||
|
||||
new = (WhowasList *) new_malloc(sizeof(WhowasList));
|
||||
new->has_ops = nick_isop(nicklist);
|
||||
|
||||
new->nicklist = (NickList *)new_malloc(sizeof(NickList)); /*nicklist;*/
|
||||
new->nicklist->nick = m_strdup(nicklist->nick);
|
||||
new->nicklist->host = m_strdup(nicklist->host);
|
||||
|
||||
malloc_strcpy(&(new->channel), channel);
|
||||
malloc_strcpy(&(new->server1), server1);
|
||||
malloc_strcpy(&(new->server2), server2);
|
||||
new->time = now;
|
||||
add_whowas_userhost_channel(new, &whowas_splitin_list);
|
||||
|
||||
}
|
||||
|
||||
int remove_oldest_whowas(WhowasWrapList *list, time_t timet, int count)
|
||||
{
|
||||
int total = 0;
|
||||
/* if no ..count.. then remove ..time.. links */
|
||||
total = remove_oldest_whowas_hashlist(list, timet, count);
|
||||
return total;
|
||||
}
|
||||
|
||||
void clean_whowas_list(void)
|
||||
{
|
||||
if (whowas_userlist_count)
|
||||
whowas_userlist_count -= remove_oldest_whowas_hashlist(&whowas_userlist_list, 20 * 60, 0);
|
||||
if (whowas_reg_count)
|
||||
whowas_reg_count -= remove_oldest_whowas_hashlist(&whowas_reg_list, 10 * 60, 0);
|
||||
remove_oldest_whowas_hashlist(&whowas_splitin_list, 25 * 60 , 0);
|
||||
}
|
||||
|
||||
/* Used to rehash whowas listings for new users */
|
||||
void sync_whowas_adduser(UserList *added)
|
||||
{
|
||||
WhowasList *tmp;
|
||||
for (tmp = next_userhost(&whowas_userlist_list, NULL); tmp; tmp = next_userhost(&whowas_userlist_list, tmp))
|
||||
{
|
||||
if (check_channel_match(added->channels, tmp->channel))
|
||||
if (wild_match(added->host, tmp->nicklist->host) && wild_match(added->nick, tmp->nicklist->nick))
|
||||
tmp->nicklist->userlist = added;
|
||||
}
|
||||
for (tmp = next_userhost(&whowas_reg_list, NULL); tmp; tmp = next_userhost(&whowas_reg_list, tmp))
|
||||
{
|
||||
if (check_channel_match(added->channels, tmp->channel))
|
||||
if (wild_match(added->host, tmp->nicklist->host) && wild_match(added->nick, tmp->nicklist->nick))
|
||||
tmp->nicklist->userlist = added;
|
||||
}
|
||||
}
|
||||
|
||||
/* Used to rehash whowas listings for removed userlist entries */
|
||||
void sync_whowas_unuser(UserList *entry)
|
||||
{
|
||||
WhowasList *tmp;
|
||||
for (tmp = next_userhost(&whowas_userlist_list, NULL); tmp; tmp = next_userhost(&whowas_userlist_list, tmp))
|
||||
{
|
||||
if (!tmp->nicklist->userlist) continue;
|
||||
if (!my_stricmp(tmp->nicklist->userlist->host, entry->host) && !my_stricmp(tmp->nicklist->userlist->nick, entry->nick) &&
|
||||
check_channel_match(tmp->nicklist->userlist->channels, entry->channels))
|
||||
tmp->nicklist->userlist = NULL;
|
||||
}
|
||||
for (tmp = next_userhost(&whowas_reg_list, NULL); tmp; tmp = next_userhost(&whowas_reg_list, tmp))
|
||||
{
|
||||
if (!tmp->nicklist->userlist) continue;
|
||||
if (!my_stricmp(tmp->nicklist->userlist->host, entry->host) && !my_stricmp(tmp->nicklist->userlist->nick, entry->nick) &&
|
||||
check_channel_match(tmp->nicklist->userlist->channels, entry->channels))
|
||||
tmp->nicklist->userlist = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Used to rehash whowas listings for new shitlist entries */
|
||||
void sync_whowas_addshit(ShitList *added)
|
||||
{
|
||||
WhowasList *tmp;
|
||||
char user[BIG_BUFFER_SIZE];
|
||||
for (tmp = next_userhost(&whowas_userlist_list, NULL); tmp; tmp = next_userhost(&whowas_userlist_list, tmp))
|
||||
{
|
||||
if (check_channel_match(added->channels, tmp->channel))
|
||||
{
|
||||
sprintf(user, "%s!%s", tmp->nicklist->nick, tmp->nicklist->host);
|
||||
if (wild_match(added->filter, user))
|
||||
tmp->nicklist->shitlist = added;
|
||||
}
|
||||
}
|
||||
for (tmp = next_userhost(&whowas_reg_list, NULL); tmp; tmp = next_userhost(&whowas_reg_list, tmp))
|
||||
{
|
||||
if (check_channel_match(added->channels, tmp->channel))
|
||||
{
|
||||
sprintf(user, "%s!%s", tmp->nicklist->nick, tmp->nicklist->host);
|
||||
if (wild_match(added->filter, user))
|
||||
tmp->nicklist->shitlist = added;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Used to rehash whowas listings for removed shitlist entries */
|
||||
void sync_whowas_unshit(ShitList *entry)
|
||||
{
|
||||
WhowasList *tmp;
|
||||
for (tmp = next_userhost(&whowas_userlist_list, NULL); tmp; tmp = next_userhost(&whowas_userlist_list, tmp))
|
||||
{
|
||||
if (!tmp->nicklist->shitlist) continue;
|
||||
if (!my_stricmp(tmp->nicklist->shitlist->filter, entry->filter) &&
|
||||
check_channel_match(tmp->nicklist->shitlist->channels, entry->channels))
|
||||
tmp->nicklist->shitlist = NULL;
|
||||
}
|
||||
for (tmp = next_userhost(&whowas_reg_list, NULL); tmp; tmp = next_userhost(&whowas_reg_list, tmp))
|
||||
{
|
||||
if (!tmp->nicklist->shitlist) continue;
|
||||
if (!my_stricmp(tmp->nicklist->shitlist->filter, entry->filter) &&
|
||||
check_channel_match(tmp->nicklist->shitlist->channels, entry->channels))
|
||||
tmp->nicklist->shitlist = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* BELOW THIS MARK IS THE CHANNEL WHOWAS STUFF */
|
||||
|
||||
extern WhowasChanList *check_whowas_chan_buffer(char *channel, int refnum, int unlink)
|
||||
{
|
||||
WhowasChanList *tmp, *last = NULL;
|
||||
|
||||
for (tmp = whowas_chan_list; tmp; tmp = tmp->next) {
|
||||
if (!my_stricmp(tmp->channellist->channel, channel))
|
||||
{
|
||||
if ((refnum == -1) || (refnum == tmp->channellist->refnum))
|
||||
{
|
||||
if (unlink) {
|
||||
if (last)
|
||||
last->next = tmp->next;
|
||||
else
|
||||
whowas_chan_list = tmp->next;
|
||||
whowas_chan_count--;
|
||||
}
|
||||
return(tmp);
|
||||
}
|
||||
}
|
||||
last = tmp;
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
void add_to_whowas_chan_buffer(ChannelList *channel)
|
||||
{
|
||||
WhowasChanList *new;
|
||||
WhowasChanList **slot;
|
||||
|
||||
if (whowas_chan_count >= whowas_chan_max)
|
||||
{
|
||||
whowas_chan_count -=
|
||||
remove_oldest_chan_whowas(&whowas_chan_list, 0,
|
||||
(whowas_chan_max + 1) - whowas_chan_count);
|
||||
}
|
||||
new = (WhowasChanList *) new_malloc(sizeof(WhowasChanList));
|
||||
|
||||
new->channellist = channel;
|
||||
new->time = now;
|
||||
clear_nicklist_hashtable(channel);
|
||||
/* we've created it, now put it in order */
|
||||
for (slot = &whowas_chan_list; *slot; slot = &(*slot)->next)
|
||||
{
|
||||
if ((*slot)->time > new->time)
|
||||
break;
|
||||
}
|
||||
new->next = *slot;
|
||||
*slot = new;
|
||||
whowas_chan_count++;
|
||||
}
|
||||
|
||||
int remove_oldest_chan_whowas(WhowasChanList **list, time_t timet, int count)
|
||||
{
|
||||
WhowasChanList *tmp = NULL;
|
||||
time_t t;
|
||||
int total = 0;
|
||||
|
||||
/* if no ..count.. then remove ..time.. links */
|
||||
if (!count)
|
||||
{
|
||||
t = now;
|
||||
while (*list && ((*list)->time + timet) <= t)
|
||||
{
|
||||
tmp = *list;
|
||||
new_free(&(tmp->channellist->channel));
|
||||
new_free(&(tmp->channellist->topic));
|
||||
new_free(&(tmp->channellist->modelock_key));
|
||||
clear_bans(tmp->channellist);
|
||||
if (tmp->channellist->msglog_fp)
|
||||
fclose(tmp->channellist->msglog_fp);
|
||||
remove_csets_for_channel(tmp->channellist->csets);
|
||||
new_free((char **)&(tmp->channellist));
|
||||
*list = tmp->next;
|
||||
new_free((char **)&tmp);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*list && count)
|
||||
{
|
||||
tmp = *list;
|
||||
new_free(&(tmp->channellist->channel));
|
||||
new_free(&(tmp->channellist->topic));
|
||||
new_free(&(tmp->channellist->modelock_key));
|
||||
clear_bans(tmp->channellist);
|
||||
if (tmp->channellist->msglog_fp)
|
||||
fclose(tmp->channellist->msglog_fp);
|
||||
remove_csets_for_channel(tmp->channellist->csets);
|
||||
new_free((char **)&(tmp->channellist));
|
||||
*list = tmp->next;
|
||||
new_free((char **)&tmp);
|
||||
total++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
void clean_whowas_chan_list(void)
|
||||
{
|
||||
whowas_chan_count -= remove_oldest_chan_whowas(&whowas_chan_list, 24 * 60 * 60, 0);
|
||||
}
|
||||
|
||||
void clear_whowas(void)
|
||||
{
|
||||
whowas_chan_count -= remove_oldest_chan_whowas(&whowas_chan_list, 0, 0);
|
||||
if (whowas_userlist_count)
|
||||
whowas_userlist_count -= remove_oldest_whowas_hashlist(&whowas_userlist_list, 0, 0);
|
||||
if (whowas_reg_count)
|
||||
whowas_reg_count -= remove_oldest_whowas_hashlist(&whowas_reg_list, 0, 0);
|
||||
remove_oldest_whowas_hashlist(&whowas_splitin_list, 0 , 0);
|
||||
}
|
||||
|
||||
void show_whowas(void)
|
||||
{
|
||||
reset_display_target();
|
||||
show_whowas_hashtable(&whowas_userlist_list, "Userlist");
|
||||
show_whowas_hashtable(&whowas_reg_list, "Reglist");
|
||||
}
|
||||
|
||||
void show_wholeft(char *channel)
|
||||
{
|
||||
int count = 0;
|
||||
int hook = 0;
|
||||
time_t ltime = now;
|
||||
reset_display_target();
|
||||
#if 0
|
||||
hook = show_wholeft_hashtable(&whowas_splitin_list, ltime, &count, &hook, "SplitList");
|
||||
#endif
|
||||
hook = show_wholeft_hashtable(&whowas_userlist_list, ltime, &count, &hook, "Splitin");
|
||||
hook = show_wholeft_hashtable(&whowas_reg_list, ltime, &count, &hook, "Splitin");
|
||||
if (count && hook && fget_string_var(FORMAT_WHOLEFT_FOOTER_FSET))
|
||||
put_it("%s", convert_output_format(fget_string_var(FORMAT_WHOLEFT_FOOTER_FSET), NULL));
|
||||
}
|
||||
3415
source/winbitchx.c
Normal file
3415
source/winbitchx.c
Normal file
File diff suppressed because it is too large
Load Diff
5009
source/window.c
Normal file
5009
source/window.c
Normal file
File diff suppressed because it is too large
Load Diff
352
source/words.c
Normal file
352
source/words.c
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* words.c -- right now it just holds the stuff i wrote to replace
|
||||
* that beastie arg_number(). Eventually, i may move all of the
|
||||
* word functions out of ircaux and into here. Now wouldnt that
|
||||
* be a beastie of a patch! Beastie! Beastie!
|
||||
*
|
||||
* Oh yea. This file is beastierighted (C) 1994 by the beastie author.
|
||||
* Right now the only author is Jeremy "Beastie" Nelson. See the
|
||||
* beastieright file for beastie info.
|
||||
*/
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: words.c,v 1.1.1.1 2003/04/11 01:09:08 dan Exp $";
|
||||
CVS_REVISION(words_c)
|
||||
#include "ircaux.h"
|
||||
#include "modval.h"
|
||||
|
||||
/*
|
||||
* search() looks for a character forward or backward from mark
|
||||
*/
|
||||
extern char *BX_search(register char *start, char **mark, char *chars, int how)
|
||||
{
|
||||
if (!mark || !*mark)
|
||||
*mark = start;
|
||||
|
||||
if (how > 0) /* forward search */
|
||||
{
|
||||
*mark = sindex(*mark, chars);
|
||||
how--;
|
||||
for (;(how > 0) && *mark && **mark;how--)
|
||||
*mark = sindex(*mark+1, chars);
|
||||
}
|
||||
|
||||
else if (how == 0)
|
||||
return (char *) 0;
|
||||
|
||||
else /* how < 0 */
|
||||
{
|
||||
*mark = rsindex(*mark, start, chars, -how);
|
||||
#if 0
|
||||
how++;
|
||||
for (;(how < 0) && *mark && **mark;how++)
|
||||
*mark = rsindex(*mark-1, start, chars);
|
||||
#endif
|
||||
}
|
||||
|
||||
return *mark;
|
||||
}
|
||||
|
||||
/* Move to an absolute word number from start */
|
||||
/* First word is always numbered zero. */
|
||||
extern char *BX_move_to_abs_word (const register char *start, char **mark, int word)
|
||||
{
|
||||
register char *pointer = (char *)start;
|
||||
register int counter = word;
|
||||
|
||||
/* This fixes a bug that counted leading spaces as
|
||||
* a word, when theyre really not a word....
|
||||
* (found by Genesis K.)
|
||||
*
|
||||
* The stock client strips leading spaces on both
|
||||
* the cases $0 and $-0. I personally think this
|
||||
* is not the best choice, but im not going to stick
|
||||
* my foot in this one... im just going to go with
|
||||
* what the stock client does...
|
||||
*/
|
||||
while (pointer && *pointer && my_isspace(*pointer))
|
||||
pointer++;
|
||||
|
||||
for (;counter > 0 && *pointer;counter--)
|
||||
{
|
||||
while (*pointer && !my_isspace(*pointer))
|
||||
pointer++;
|
||||
while (*pointer && my_isspace(*pointer))
|
||||
pointer++;
|
||||
}
|
||||
|
||||
if (mark)
|
||||
*mark = pointer;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/* Move a relative number of words from the present mark */
|
||||
extern char *BX_move_word_rel (const register char *start, char **mark, int word)
|
||||
{
|
||||
register char *pointer = *mark;
|
||||
register int counter = word;
|
||||
char *end = (char *)start + strlen((char *)start);
|
||||
|
||||
if (end == start) /* null string, return it */
|
||||
return (char *)start;
|
||||
|
||||
/*
|
||||
* XXXX - this is utterly pointless at best, and
|
||||
* totaly wrong at worst.
|
||||
*/
|
||||
|
||||
if (counter > 0)
|
||||
{
|
||||
for (;counter > 0 && pointer;counter--)
|
||||
{
|
||||
while (*pointer && !my_isspace(*pointer))
|
||||
pointer++;
|
||||
while (*pointer && my_isspace(*pointer))
|
||||
pointer++;
|
||||
}
|
||||
}
|
||||
else if (counter == 0)
|
||||
pointer = *mark;
|
||||
else /* counter < 0 */
|
||||
{
|
||||
for (;counter < 0 && pointer > start;counter++)
|
||||
{
|
||||
while (pointer >= start && my_isspace(*pointer))
|
||||
pointer--;
|
||||
while (pointer >= start && !my_isspace(*pointer))
|
||||
pointer--;
|
||||
}
|
||||
pointer++; /* bump up to the word we just passed */
|
||||
}
|
||||
|
||||
if (mark)
|
||||
*mark = pointer;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/*
|
||||
* extract2 is the word extractor that is used when its important to us
|
||||
* that 'firstword' get special treatment if it is negative (specifically,
|
||||
* that it refer to the "firstword"th word from the END). This is used
|
||||
* basically by the ${n}{-m} expandos and by function_rightw().
|
||||
*
|
||||
* Note that because of a lot of flak, if you do an expando that is
|
||||
* a "range" of words, unless you #define STRIP_EXTRANEOUS_SPACES,
|
||||
* the "n"th word will be backed up to the first character after the
|
||||
* first space after the "n-1"th word. That apparantly is what everyone
|
||||
* wants, so thats whatll be the default. Those of us who may not like
|
||||
* that behavior or are at ambivelent can just #define it.
|
||||
*/
|
||||
#undef STRIP_EXTRANEOUS_SPACES
|
||||
extern char *BX_extract2(const char *start, int firstword, int lastword)
|
||||
{
|
||||
/* If firstword or lastword is negative, then
|
||||
we take those values from the end of the string */
|
||||
char *mark;
|
||||
char *mark2;
|
||||
char *booya = NULL;
|
||||
|
||||
/* If firstword is EOS, then the user wants the last word */
|
||||
if (firstword == EOS)
|
||||
{
|
||||
mark = (char *)start + strlen(start);
|
||||
mark = move_word_rel(start, &mark, -1);
|
||||
#ifndef NO_CHEATING
|
||||
/*
|
||||
* Really. the only case where firstword == EOS is
|
||||
* when the user wants $~, in which case we really
|
||||
* dont need to do all the following crud. Of
|
||||
* course, if there ever comes a time that the
|
||||
* user would want to start from the EOS (when??)
|
||||
* we couldnt make this assumption.
|
||||
*/
|
||||
return m_strdup(mark);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* SOS is used when the user does $-n, all leading spaces
|
||||
* are retained
|
||||
*/
|
||||
else if (firstword == SOS)
|
||||
mark = (char *)start;
|
||||
|
||||
/* If the firstword is positive, move to that word */
|
||||
else if (firstword >= 0)
|
||||
{
|
||||
move_to_abs_word(start, &mark, firstword);
|
||||
if (!*mark)
|
||||
return m_strdup(empty_string);
|
||||
}
|
||||
/* Otherwise, move to the firstwords from the end */
|
||||
else
|
||||
{
|
||||
mark = (char *)start + strlen((char *)start);
|
||||
move_word_rel(start, &mark, firstword);
|
||||
}
|
||||
|
||||
#ifndef STRIP_EXTRANEOUS_SPACES
|
||||
/* IF the user did something like this:
|
||||
* $n- $n-m
|
||||
* then include any leading spaces on the 'n'th word.
|
||||
* this is the "old" behavior that we are attempting
|
||||
* to emulate here.
|
||||
*/
|
||||
#ifndef NO_CHEATING
|
||||
if (lastword == EOS || (lastword > firstword))
|
||||
#else
|
||||
if (((lastword == EOS) && (firstword != EOS)) || (lastword > firstword))
|
||||
#endif
|
||||
{
|
||||
while (mark > start && my_isspace(mark[-1]))
|
||||
mark--;
|
||||
if (mark > start)
|
||||
mark++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When we find the last word, we need to move to the
|
||||
* END of the word, so that word 3 to 3, would include
|
||||
* all of word 3, so we sindex to the space after the word
|
||||
*/
|
||||
if (lastword == EOS)
|
||||
mark2 = mark + strlen(mark);
|
||||
|
||||
else
|
||||
{
|
||||
if (lastword >= 0)
|
||||
move_to_abs_word(start, &mark2, lastword+1);
|
||||
else
|
||||
{
|
||||
mark2 = (char *)start + strlen(start);
|
||||
move_word_rel(start, &mark2, lastword);
|
||||
}
|
||||
|
||||
while (mark2 > start && my_isspace(mark2[-1]))
|
||||
mark2--;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the end is before the string, then there is nothing
|
||||
* to extract (this is perfectly legal, btw)
|
||||
*/
|
||||
if (mark2 < mark)
|
||||
booya = m_strdup(empty_string);
|
||||
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
/* Otherwise, copy off the string we just isolated */
|
||||
char tmp;
|
||||
tmp = *mark2;
|
||||
*mark2 = '\0';
|
||||
booya = m_strdup(mark);
|
||||
*mark2 = tmp;
|
||||
#endif
|
||||
booya = new_malloc(mark2 - mark + 1);
|
||||
strmcpy(booya, mark, (mark2 - mark));
|
||||
}
|
||||
|
||||
return booya;
|
||||
}
|
||||
|
||||
/*
|
||||
* extract is a simpler version of extract2, it is used when we dont
|
||||
* want special treatment of "firstword" if it is negative. This is
|
||||
* typically used by the word/list functions, which also dont care if
|
||||
* we strip out or leave in any whitespace, we just do what is the
|
||||
* fastest.
|
||||
*/
|
||||
extern char *BX_extract(char *start, int firstword, int lastword)
|
||||
{
|
||||
/*
|
||||
* firstword and lastword must be zero. If they are not,
|
||||
* then they are assumed to be invalid However, please note
|
||||
* that taking word set (-1,3) is valid and contains the
|
||||
* words 0, 1, 2, 3. But word set (-1, -1) is an empty_string.
|
||||
*/
|
||||
char *mark;
|
||||
char *mark2;
|
||||
char *booya = NULL;
|
||||
|
||||
/*
|
||||
* before we do anything, we strip off leading and trailing
|
||||
* spaces.
|
||||
*
|
||||
* ITS OK TO TAKE OUT SPACES HERE, AS THE USER SHOULDNT EXPECT
|
||||
* THAT THE WORD FUNCTIONS WOULD RETAIN ANY SPACES. (That is
|
||||
* to say that since the word/list functions dont pay attention
|
||||
* to the whitespace anyhow, noone should have any problem with
|
||||
* those ops removing bothersome whitespace when needed.)
|
||||
*/
|
||||
while (my_isspace(*start))
|
||||
start++;
|
||||
remove_trailing_spaces(start);
|
||||
|
||||
if (firstword == EOS)
|
||||
{
|
||||
mark = start + strlen(start);
|
||||
mark = move_word_rel(start, &mark, -1);
|
||||
}
|
||||
|
||||
/* If the firstword is positive, move to that word */
|
||||
else if (firstword >= 0)
|
||||
move_to_abs_word(start, &mark, firstword);
|
||||
|
||||
/* Its negative. Hold off right now. */
|
||||
else
|
||||
mark = start;
|
||||
|
||||
|
||||
/* When we find the last word, we need to move to the
|
||||
END of the word, so that word 3 to 3, would include
|
||||
all of word 3, so we sindex to the space after the word
|
||||
*/
|
||||
/* EOS is a #define meaning "end of string" */
|
||||
if (lastword == EOS)
|
||||
mark2 = start + strlen(start);
|
||||
else
|
||||
{
|
||||
if (lastword >= 0)
|
||||
move_to_abs_word(start, &mark2, lastword+1);
|
||||
else
|
||||
/* its negative -- thats not valid */
|
||||
return m_strdup(empty_string);
|
||||
|
||||
while (mark2 > start && my_isspace(mark2[-1]))
|
||||
mark2--;
|
||||
}
|
||||
|
||||
/* Ok.. now if we get to here, then lastword is positive, so
|
||||
* we sanity check firstword.
|
||||
*/
|
||||
if (firstword < 0)
|
||||
firstword = 0;
|
||||
if (firstword > lastword) /* this works even if fw was < 0 */
|
||||
return m_strdup(empty_string);
|
||||
|
||||
/* If the end is before the string, then there is nothing
|
||||
* to extract (this is perfectly legal, btw)
|
||||
*/
|
||||
#if 0
|
||||
booya = NULL;
|
||||
#endif
|
||||
if (mark2 < mark)
|
||||
return m_strdup(empty_string);
|
||||
|
||||
booya = new_malloc(mark2 - mark + 1);
|
||||
strmcpy(booya, mark, (mark2 - mark));
|
||||
#if 0
|
||||
malloc_strcpy(&booya, empty_string);
|
||||
else
|
||||
{
|
||||
/* Otherwise, copy off the string we just isolated */
|
||||
char tmp;
|
||||
tmp = *mark2;
|
||||
*mark2 = '\0';
|
||||
malloc_strcpy(&booya, mark);
|
||||
*mark2 = tmp;
|
||||
}
|
||||
#endif
|
||||
return booya;
|
||||
}
|
||||
134
source/wserv.c
Normal file
134
source/wserv.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* wserv.c - little program to be a pipe between a screen or
|
||||
* xterm window to the calling ircII process.
|
||||
*
|
||||
* Written by Troy Rollo, Copyright 1992 Troy Rollo
|
||||
* Finished by Matthew Green, Copyright 1993 Matthew Green
|
||||
* Support for 4.4BSD by Jeremy Nelson, Copyright 1997 EPIC Software Labs
|
||||
*
|
||||
* Works by opening up the unix domain socket that ircII bind's
|
||||
* before calling wserv, and which ircII also deleted after the
|
||||
* connection has been made.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static char rcsid[] = "@(#)$Id: wserv.c,v 1.1.1.1 2003/04/11 01:09:08 dan Exp $";
|
||||
#endif
|
||||
|
||||
#include "defs.h"
|
||||
#include "config.h"
|
||||
#include "irc.h"
|
||||
#include "struct.h"
|
||||
|
||||
#include "ircterm.h"
|
||||
#include "ircaux.h"
|
||||
#define WTERM_C
|
||||
#include "modval.h"
|
||||
#include <errno.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
static int s;
|
||||
static char buffer[256];
|
||||
|
||||
void my_exit(int);
|
||||
void ignore (int value);
|
||||
|
||||
#ifdef CLOAKED
|
||||
extern char proctitlestr[140];
|
||||
extern char **Argv;
|
||||
extern char *LastArgv;
|
||||
#endif
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
fd_set reads;
|
||||
int nread;
|
||||
unsigned short port;
|
||||
char *host;
|
||||
char *tmp;
|
||||
int t;
|
||||
char stuff[100];
|
||||
|
||||
#ifndef WINNT
|
||||
my_signal(SIGWINCH, SIG_IGN, 0);
|
||||
#endif
|
||||
my_signal(SIGHUP, SIG_IGN, 0);
|
||||
my_signal(SIGQUIT, SIG_IGN, 0);
|
||||
my_signal(SIGINT, ignore, 0);
|
||||
|
||||
if (argc != 3) /* no socket is passed */
|
||||
my_exit(1);
|
||||
|
||||
host = argv[1];
|
||||
port = (unsigned short)atoi(argv[2]);
|
||||
if (!port)
|
||||
my_exit(2); /* what the hey */
|
||||
|
||||
s = connect_by_number(host, &port, SERVICE_CLIENT, PROTOCOL_TCP, 0);
|
||||
if (s < 0)
|
||||
my_exit(23);
|
||||
|
||||
/*
|
||||
* first line from a wserv program is the tty. this is so ircii
|
||||
* can grab the size of the tty, and have it changed.
|
||||
*/
|
||||
tmp = ttyname(0);
|
||||
sprintf(stuff, "%s\n", tmp);
|
||||
t = write(s, stuff, strlen(stuff));
|
||||
term_init(NULL);
|
||||
printf("t is %d", t);
|
||||
|
||||
/*
|
||||
* The select call.. reads from the socket, and from the window..
|
||||
* and pipes the output from out to the other.. nice and simple
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
FD_ZERO(&reads);
|
||||
FD_SET(0, &reads);
|
||||
FD_SET(s, &reads);
|
||||
if (select(s + 1, &reads, NULL, NULL, NULL) <= 0)
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(0, &reads))
|
||||
{
|
||||
if ((nread = read(0, buffer, sizeof(buffer))))
|
||||
write(s, buffer, nread);
|
||||
else
|
||||
my_exit(3);
|
||||
}
|
||||
if (FD_ISSET(s, &reads))
|
||||
{
|
||||
if ((nread = read(s, buffer, sizeof(buffer))))
|
||||
write(1, buffer, nread);
|
||||
else
|
||||
my_exit(4);
|
||||
}
|
||||
}
|
||||
|
||||
my_exit(8);
|
||||
}
|
||||
|
||||
void ignore (int value)
|
||||
{
|
||||
/* send a ^C */
|
||||
char foo = 3;
|
||||
write(s, &foo, 1);
|
||||
}
|
||||
|
||||
void my_exit(int value)
|
||||
{
|
||||
printf("exiting with %d!\n", value);
|
||||
printf("errno is %d (%s)\n", errno, strerror(errno));
|
||||
exit(value);
|
||||
}
|
||||
|
||||
/* These are here so we can link with network.o */
|
||||
char *LocalHostName = NULL;
|
||||
struct sockaddr_foobar LocalHostAddr;
|
||||
char empty_string[] = "";
|
||||
int get_int_var (enum VAR_TYPES unused) { return 5; }
|
||||
void set_socket_options (int s) { }
|
||||
|
||||
/* End of file */
|
||||
Reference in New Issue
Block a user