Short: syslog like logging for the driver
From: Christian Welzel <gawain@wh9.tu-dresden.de>
Date: Mon, 28 Jan 2002 11:44:56 +0100
Type: Feature
State: New

Hallo Lars!

Hier mal al anhang der aktuelle stand des Logsystems. 
Es ist jetzt soweit: man kann endlich damit loggen :)
Allerdings untersttzt es noch keine shared libs...

-- 
 Bye, Gawain (ICQ: 81736439)

            					  ###
     \|/           www           _``'_           #####
    (o o)          @ @           (O-O)          /(o o)\
 ooO-(_)-Ooo---oOO-(_)-OOo---oOO--(_)--OOo---oOO==(_)==OOo

PGP-Key: http://www.wh9.tu-dresden.de/~gawain/key.asc (there is a new key!)
Fingerprint: 4F50 19BF 3346 36A6 CFA9  DBDC C268 6D24 70A1 AD15

linux... it's like a wigwam - no gates, no windows and an apache inside.

 --o00-00o-------o0--0o---------o0--0o----------o0o-o0o---

diff -Naur 3-2-dev.orig/mudlib/sys/driver_hook.h 3-2-dev/mudlib/sys/driver_hook.h
--- 3-2-dev.orig/mudlib/sys/driver_hook.h	Sun Nov 18 03:38:53 2001
+++ 3-2-dev/mudlib/sys/driver_hook.h	Mon Jan 28 11:12:14 2002
@@ -24,8 +24,9 @@
 #define H_COMMAND               17
 #define H_SEND_NOTIFY_FAIL      18
 #define H_AUTO_INCLUDE          19
+#define H_MODIFY_SYSLOG         20
 
-#define NUM_DRIVER_HOOKS        20  /* Number of hooks */
+#define NUM_DRIVER_HOOKS        21  /* Number of hooks */
 
 #endif /* LPC_DRIVER_HOOK_ */
 
diff -Naur 3-2-dev.orig/mudlib/sys/syslog.h 3-2-dev/mudlib/sys/syslog.h
--- 3-2-dev.orig/mudlib/sys/syslog.h	Thu Jan  1 01:00:00 1970
+++ 3-2-dev/mudlib/sys/syslog.h	Mon Jan 28 11:12:14 2002
@@ -0,0 +1,79 @@
+#ifndef _SYS_SYSLOG_H
+#define _SYS_SYSLOG_H 1
+
+/*
+ * priorities (these are ordered)
+ */
+#define	LOG_EMERG	0	/* system is unusable */
+#define	LOG_ALERT	1	/* action must be taken immediately */
+#define	LOG_CRIT	2	/* critical conditions */
+#define	LOG_ERR		3	/* error conditions */
+#define	LOG_WARNING	4	/* warning conditions */
+#define	LOG_NOTICE	5	/* normal but significant condition */
+#define	LOG_INFO	6	/* informational */
+#define	LOG_DEBUG	7	/* debug-level messages */
+
+#define LOG_NLEVELS     8	/* number of levels */
+
+/* facility codes */
+#define	LOG_KERN	0	/* kernel messages */
+#define	LOG_USER	1	/* random user-level messages */
+#define	LOG_MAIL	2	/* mail system */
+#define	LOG_DAEMON	3	/* system daemons */
+#define	LOG_AUTH	4	/* security/authorization messages */
+#define	LOG_SYSLOG	5	/* messages generated internally by syslogd */
+#define	LOG_LPR		6	/* line printer subsystem */
+#define	LOG_NEWS	7	/* network news subsystem */
+#define	LOG_UUCP	8	/* UUCP subsystem */
+#define	LOG_CRON	9	/* clock daemon */
+#define	LOG_AUTHPRIV	10	/* security/authorization messages (private) */
+#define	LOG_FTP		11	/* ftp daemon */
+
+#define	LOG_NFACILITIES	12	/* current number of facilities */
+
+#ifndef __DRIVER_SOURCE__
+
+/* Set the log mask level.  */
+int setlogmask (mapping mask);
+mapping getlogmask();
+
+/* Generate a log message using given string. */
+int syslog (int facility, int level, string message);
+
+#endif
+
+#ifdef __DRIVER_SOURCE__
+
+CODE levelnames[] =
+{
+    { "alert", LOG_ALERT },
+    { "crit", LOG_CRIT },
+    { "debug", LOG_DEBUG },
+    { "emerg", LOG_EMERG },
+    { "err", LOG_ERR },
+    { "info", LOG_INFO },
+    { "notice", LOG_NOTICE },
+    { "warning", LOG_WARNING },
+    { NULL, -1 }
+};
+
+CODE facilitynames[] =
+{
+    { "auth", LOG_AUTH },
+    { "authpriv", LOG_AUTHPRIV },
+    { "cron", LOG_CRON },
+    { "daemon", LOG_DAEMON },
+    { "ftp", LOG_FTP },
+    { "kern", LOG_KERN },
+    { "lpr", LOG_LPR },
+    { "mail", LOG_MAIL },
+    { "news", LOG_NEWS },
+    { "syslog", LOG_SYSLOG },
+    { "user", LOG_USER },
+    { "uucp", LOG_UUCP },
+    { NULL, -1 }
+};
+
+#endif
+
+#endif /* syslog.h */
diff -Naur 3-2-dev.orig/src/Makefile.in 3-2-dev/src/Makefile.in
--- 3-2-dev.orig/src/Makefile.in	Sun Nov 25 01:47:44 2001
+++ 3-2-dev/src/Makefile.in	Mon Jan 28 11:12:14 2002
@@ -83,13 +83,13 @@
       lex.c main.c mapping.c md5.c mempools.c object.c otable.c parse.c \
       parser.c parse_old.c pkg-mysql.c port.c ptrtable.c \
       random.c regexp.c rxcache.c simulate.c simul_efun.c stdstrings.c \
-      stralloc.c strfuns.c sprintf.c swap.c wiz_list.c xalloc.c
+      stralloc.c strfuns.c sprintf.c swap.c syslog.c wiz_list.c xalloc.c
 OBJ = access_check.o actions.o array.o backend.o call_out.o closure.o comm.o \
       dumpstat.o ed.o efuns.o gcollect.o hash.o heartbeat.o interpret.o \
       lex.o main.o mapping.o md5.o mempools.o object.o otable.o parse.o \
       parser.o parse_old.o pkg-mysql.o port.o ptrtable.o \
       random.o regexp.o rxcache.o simulate.o simul_efun.o stdstrings.o \
-      stralloc.o strfuns.o sprintf.o swap.o wiz_list.o xalloc.o @ALLOCA@
+      stralloc.o strfuns.o sprintf.o swap.o syslog.o wiz_list.o xalloc.o @ALLOCA@
 
 driver: $(OBJ)
 	$(CC) @OPTIMIZE_LINKING@ $(LDFLAGS) $(OBJ) -o $@ $(LIBS)
@@ -417,6 +417,9 @@
     ./hosts/amiga/socket_sim_protos.h hosts/unix.h hosts/be/be.h \
     hosts/amiga/amiga.h hosts/amiga/patchfloat.h machine.h \
     ./hosts/amiga/ixfile.h
+
+syslog.o : svalue.h machine.h syslog.h mapping.h array.h ../mudlib/sys/syslog.h \
+    ../mudlib/sys/driver_hook.h config.h
 
 wiz_list.o : xalloc.h svalue.h stralloc.h stdstrings.h object.h mapping.h \
     main.h interpret.h gcollect.h backend.h array.h ../mudlib/sys/wizlist.h \
diff -Naur 3-2-dev.orig/src/func_spec 3-2-dev/src/func_spec
--- 3-2-dev.orig/src/func_spec	Thu Jan 24 05:02:23 2002
+++ 3-2-dev/src/func_spec	Mon Jan 28 11:12:14 2002
@@ -491,7 +491,6 @@
 %tefuns
 
         /* Miscellaneous */
-
 mixed   copy(mixed);
 mixed   deep_copy(mixed);
 mixed   max(mixed|mixed*, ...);
@@ -576,6 +575,10 @@
 
         /* Driver and System functions */
 
+int     syslog(int,int,string);
+mixed   setlogmask(mapping|void);
+mixed   getlogmask(void);
+mixed   getlogfiles(void);
 mixed   debug_info(int, ...);
 void    debug_message(string, int default: F_CONST0);
 string  expand_define(string, string default: F_CONST0);
diff -Naur 3-2-dev.orig/src/lex.c 3-2-dev/src/lex.c
--- 3-2-dev.orig/src/lex.c	Fri Jan 18 08:07:13 2002
+++ 3-2-dev/src/lex.c	Mon Jan 28 11:12:14 2002
@@ -63,6 +63,7 @@
 #include "strfuns.h"
 #include "wiz_list.h" /* wizlist_name[] */
 #include "xalloc.h"
+#include "syslog.h"
 
 #include "../mudlib/sys/driver_hook.h"
 
diff -Naur 3-2-dev.orig/src/main.c 3-2-dev/src/main.c
--- 3-2-dev.orig/src/main.c	Wed Jan  2 07:49:08 2002
+++ 3-2-dev/src/main.c	Mon Jan 28 11:12:14 2002
@@ -121,6 +121,8 @@
 char *mud_lib;                /* Path to the mudlib */
 char master_name[100] = "";   /* Name of the master object */
 
+char *syslog_config = NULL;
+
 static int new_mudlib = 0;    /* True: mudlib directory was specified */
 static int no_erq_demon = 0;  /* True: don't start the erq */
 
@@ -251,6 +253,7 @@
     if (getargs(argc, argv, eval_arg))
       exit(1);
 
+
     /* Change to the mudlib dir early so that the debug.log file
      * is opened in the right place.
      * If a mudlib dir has been given by command option, we are already
@@ -324,6 +327,11 @@
         mud_lib = string_copy(path);
     }
 
+    if (!ldopenlog()) {
+        fprintf(stderr, "Could not open %s as syslog config file\nor failure during init of syslog system.\n", syslog_config);
+        exit(2);
+    }
+
 #ifdef ERQ_DEMON
     /* Make sure that erq_file contains a complete absolute pathname. */
 
@@ -451,6 +459,7 @@
 #if defined(AMIGA) && !defined(__GNUC__)
     amiga_end();
 #endif
+    ldcloselog();
     
     return 0; /* TODO: There are constants for this */
 } /* main() */
@@ -853,6 +862,7 @@
  , cSwapVars        /* --swap-variables     */
  , cSwapFile        /* --swap-file          */
  , cSwapCompact     /* --swap-compact       */
+ , cSyslogConfig    /* --syslog-config      */
  , cWizlistFile     /* --wizlist-file       */
  , cNoWizlistFile   /* --no-wizlist-file    */
 #ifdef GC_SUPPORT
@@ -940,6 +950,7 @@
     , { "swap-variables",     cSwapVars,       MY_TRUE }
     , { "swap-file",          cSwapFile,       MY_TRUE }
     , { "swap-compact",       cSwapCompact,    MY_FALSE }
+    , { "syslog-config",      cSyslogConfig,   MY_TRUE }
     , { "wizlist-file",       cWizlistFile,    MY_TRUE }
     , { "no-wizlist-file",    cNoWizlistFile,  MY_FALSE }
 #ifdef GC_SUPPORT
@@ -1391,6 +1402,7 @@
 #ifdef CHECK_STRINGS
 "  --check-strings\n"
 #endif
+"  --syslog-config <filename>\n"
 "  -V|--version\n"
 "  --options\n"
 "  --longhelp\n"
@@ -1581,6 +1593,9 @@
 "    SLOW!\n"
 "\n"
 #endif
+"  --syslog-config <filename>\n"
+"    Read the configuration of the syslog system from file <filename>.\n"
+"\n"
 "  -V|--version\n"
 "    Print the version of the driver, then exit.\n"
 "\n"
@@ -1900,6 +1915,12 @@
             free(debug_file);
         debug_file = strdup(pValue);
         break;
+
+    case cSyslogConfig:
+	if (syslog_config != NULL)
+	    free(syslog_config);
+	syslog_config = strdup(pValue);
+	break;
 
     case cRandomSeed:
         random_seed = strtoul(pValue, (char **)0, 0);
diff -Naur 3-2-dev.orig/src/syslog.c 3-2-dev/src/syslog.c
--- 3-2-dev.orig/src/syslog.c	Thu Jan  1 01:00:00 1970
+++ 3-2-dev/src/syslog.c	Mon Jan 28 11:12:14 2002
@@ -0,0 +1,376 @@
+/******************************************************************************
+ * syslog.c - part of ldmud to provide a simple but flexible api for logging  *
+ *            texts into files or other datasinks.                            *
+ * written by gawain@camlann.de (gawain@Regenbogen)                           *
+ ******************************************************************************/
+ 
+/* Concept:
+ * 
+ * the ldmud driver logs all its messages with the private function ldsyslog().
+ * this private ldsyslog() then does the real logging with the help of buildin
+ * printf()s/puts() or with external shared-libs. ldsyslog() also calls a mudlib
+ * driverhook (H_MODIFY_SYSLOG) to allow direct processing of messages by the lib.
+ * whether the hook is called or not is determined with help of a mapping
+ * given to the fun f_setlogmask(). for all facilities/levels given in this
+ * mapping H_SYSLOG is called. if the hook returns a value !=0 the message is logged,
+ * else it is not.
+ * the function ldsyslog_memsafe() is a wrapper for ldsyslog and parses its printf
+ * style parameters on its own. so it is garanteed that no more memory than OUTPUT_MAXLEN
+ * will be used. this is important in low memory situations. a amount of OUTPUT_MAXLEN 
+ * bytes is allocated during driver startup (its hold until shutdown).
+ * there are two auxiliary functions: ldopenlog() and ldcloselog()
+ * ldopenlog() is used to init the logging system (eg. loding the external libs)
+ * and ldcloselog() is used to shut it down (eg. unload external libs) 
+ * the two efuns f_syslog() and f_setlogmask() serve as interface from the mudlib
+ * to the loggingsystem. f_getlogmask() returns a copy of the currently installed logmask
+ * mapping. f_getlogfiles() returns a copy of the currently installed logfiles mapping.
+ */
+
+/* Config-File:
+ *
+ * The configuration of the syslog system ist divided into several parts.
+ * Each part begins with a line [<part>] where <part> is the name of this
+ * part (e.g. [main], [mysql], etc). The name must not exceed 10 characters.
+ * The path to the config file can be given by driver option --syslog-config.
+ * Each modul must parse its part in this configfile
+ * on its own. This gives the possibility to extend the config file format.
+ * The section [main] is used by the driver-part.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "config.h"
+
+#include "machine.h"
+#include "svalue.h"
+#include "mapping.h"
+#include "xalloc.h"
+#include "stralloc.h"
+
+#include "syslog.h"			// prototypes
+#include "../mudlib/sys/syslog.h"	// defines for facility and level
+#include "../mudlib/sys/driver_hook.h"  // defines for the hook numbers
+
+#define TYPE_TESTV1(arg1,type1) if ((arg1)->type != type1) bad_xefun_vararg(1, sp);
+#define TYPE_TESTV2(arg1,type1) if ((arg1)->type != type1) bad_xefun_vararg(2, sp);
+#define TYPE_TESTV3(arg1,type1) if ((arg1)->type != type1) bad_xefun_vararg(3, sp);
+
+extern svalue_t driver_hook[NUM_DRIVER_HOOKS];
+extern svalue_t *inter_sp;
+extern object_t dummy_current_object_for_loads;
+extern object_t *current_object;
+extern char *syslog_config;
+
+//*****************
+// Driver Functions
+//*****************
+
+static char *output     = NULL;
+static char *output2    = NULL;
+static mapping_t *map   = NULL;
+static mapping_t *files = NULL;
+static int inited       = 0;
+
+static char module[10]  = "none";
+static char path[100]   = "./";
+static char logfile[20]	= "mud.log";
+static char file[200]   = "";
+
+/* Close desriptor used to write to system logger.  */
+void ldcloselog () {
+    if(output)  free(output);
+    if(output2) free(output2);
+    if(map)     free_mapping(map);
+    if(files)   free_mapping(files);
+    output = output2 = NULL;
+    map = files = NULL;
+    inited = 0;
+}
+
+/* convert a facility or level string to its int value */
+/* what .. 0=facility, 1=level */
+/* negative return value indicates invalid string */
+static 
+int ldstr2int(char *str, int what) {
+    int value = -1, i;
+    char *t;
+
+    i = strtol(str, &t, 10);
+    if(str!=t) return i;
+
+    if(what) { // level
+	i = 0;
+	while(levelnames[i].c_name && strcmp(levelnames[i].c_name, str) != 0) i++;
+	value = levelnames[i].c_val;
+    }
+    else { // facility
+	i = 0;
+	while(facilitynames[i].c_name && strcmp(facilitynames[i].c_name, str) != 0) i++;
+	value = facilitynames[i].c_val;
+    }
+
+    return value;
+}
+
+/* (re)read config file */
+static 
+int ldreadconfig(char *file) {
+    FILE *c;
+    char section[100], item[100], value[100], fac[100], lev[100], mem[100];
+    char *t;
+    int ifac, ilev;
+    svalue_t *res, arg;
+
+    if(c=fopen(file, "r")) {
+	while(!feof(c)) {
+	    fgets(mem, 100, c);
+	    if(sscanf(mem, "#%100s", item) == 1) ;
+	    else if(sscanf(mem, "[%100[^] ]]", section) == 1) ;
+	    else if(sscanf(mem, "%100[^=.]=%100s", item, value) == 2) {
+		if(strcmp(section, "main") == 0) {
+		    if     (strcmp(item, "module")  == 0) strncpy(module, value, 10);
+		    else if(strcmp(item, "path")    == 0) strncpy(path, value, 100);
+		    else if(strcmp(item, "log")     == 0) strncpy(logfile, value, 20);
+		}
+	    }
+	    else if(sscanf(mem, "%100[^.].%100[^.].%100[^=]=%100s", item, fac, lev, value) == 4) {
+		if(strcmp(section, "main") == 0) {
+		    ifac = ldstr2int(fac, 0);
+		    ilev = ldstr2int(lev, 1);
+
+		    if     (strcmp(item, "log")     == 0) {
+			put_number(&arg, ifac);
+			res = get_map_lvalue(files, &arg);
+			t = make_shared_string(value);
+			put_string(&res[ilev], t);
+		    }
+		    else if(strcmp(item, "callhook") == 0) {
+			put_number(&arg, ifac);
+			res = get_map_lvalue(map, &arg);
+			put_number(&res[ilev], 1);
+		    }
+		} // Sektion main
+	    } // Pattern sss=s
+	} // run through file
+        fclose(c);
+    } // open file
+    else return 0;
+
+    return 1;
+}
+
+/* Open connection to system logger.  */
+/* When using external shared libs, load the libs and init them */
+/* or open the logfiles when using internal filelogging */
+int ldopenlog () {
+    int stat = 1;
+
+    if(inited) return -1;
+
+    if(!output) output = xalloc(OUTPUT_MAXLEN);
+    if(!output) return 0;
+
+    current_object = &dummy_current_object_for_loads; // for allocate_mapping()
+    if(!files)  files = ref_mapping(allocate_mapping(1, LOG_NLEVELS));
+    if(!map)    map   = ref_mapping(allocate_mapping(1, LOG_NLEVELS));
+    if(!files || !map)  { ldcloselog(); return 0; }
+
+    if(syslog_config) stat = ldreadconfig(syslog_config);
+    if(!stat) { ldcloselog(); return 0; }
+
+    inited = 1;
+    return 1;
+}
+
+/* Generate a log message using the string given as 3th argument.  */
+/* this function does the real logging while the other two are only */
+/* wrapper funs because of the different argument types. */
+/* the driverhook H_MODIFY_SYSLOG will be called if an entry for the */
+/* facility/level pair is found in mapping map */
+int ldsyslog(int facility, int level, const char *out) {
+
+    FILE *file2log;
+    svalue_t query, *result;
+    int ok = 1, num = 0;
+    char *name = logfile;
+
+    put_number(&query, facility);
+
+    if(map) { // only when logmask is initialised
+	result = get_map_value(map, &query);
+	if(result) {
+	    // facility found in logmask-mapping -> yeah!
+	    if(result[level].type==T_NUMBER && result[level].u.number) {
+		// level found, call hook, if it is set up
+		if (NULL != driver_hook[H_MODIFY_SYSLOG].u.lambda ) {
+		    push_number(facility);
+		    push_number(level);
+		    push_string_malloced(out);
+		    call_lambda(&driver_hook[H_MODIFY_SYSLOG], 3);
+		    ok = inter_sp->u.number; // 0 to suppress output to file
+		    free_svalue(inter_sp); 
+		    inter_sp--;
+		}
+	    } // result[level]...
+	} // result && ...
+    } // if(map...
+
+    // is it ok, to log it? or has the hook said "no!" ?
+    if(ok) { // its ok -> log it (default)
+	result = get_map_value(files, &query);
+	if(result) { // special logfile set ?
+	    if(result[level].type==T_STRING) { // Yes!
+		name = result[level].u.string;
+	    }
+	}
+
+	xstrncpy(file, path, 200);
+	strcat(file, name);
+	if(file2log = fopen(file, "a")) {
+    	    num = fputs(out, file2log);
+	    fclose(file2log);
+	}
+	return num; // 0 on error, > 0 on success
+    }
+    else // do not log it, return -1 to indicate this
+	return -1;
+}
+
+static char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+/* Generate a log message using FMT string and option arguments.  */
+/* directly useable function in printf style */
+/* enable format-checking with -Wformat (gcc >2.5) */
+int ldsyslog_memsafe (int facility, int level, const char *fmt, ...) {
+    va_list ap;
+    int d, j, x;
+    const char *tmp = fmt;
+    char *out = output;
+    char *t;
+
+    va_start(ap, fmt);
+    while(*tmp && out<output+OUTPUT_MAXLEN-1) {
+	if(*tmp=='%')
+	    switch(*(++tmp)) {
+		default : *out++ = '%'; 
+			  *out++ = *tmp; 
+			  break;
+		case 's': t = va_arg(ap, char *); 
+			  while(out<output+OUTPUT_MAXLEN-1 && (*out = *t++)) 
+			      out++; 
+			  break;
+		case 'x': d = va_arg(ap, int);
+			  *out++ = '0'; *out++ = 'x'; 
+			  for (x= j= 2 * sizeof d; --j >= 0; d >>= 4) {
+			      *(out+j) = hex[d & 0xF];
+			  }
+		          out+=x;
+			  break;
+		case 'd': d = va_arg(ap, int);
+			  for (j = 1000000000; j > d; j /= 10) NOOP;
+			  if (!j) j = 1;
+		          do {
+		    	      *out++ = (char)((d / j) % 10 + '0');
+		    	      j /= 10;
+			  } while (j > 0 && out<output+OUTPUT_MAXLEN-1);
+			  break;
+	    }
+	else *out++ = *tmp;
+	tmp++;
+    }
+    *out = '\0';
+    va_end(ap);
+
+    return ldsyslog(facility, level, output);
+}
+
+
+//***********
+// efuns
+//***********
+
+/* Set the log mask level.  */
+/* VEFUN */
+/* int setlogmask(mapping logmask) */
+svalue_t *
+f_setlogmask (svalue_t *sp, int num_arg) {
+
+    if(num_arg > 1)
+	error("Too many arguments to setlogmask.\n");
+
+    if(num_arg) {
+	TYPE_TESTV1(sp, T_MAPPING)
+	if(map) free_mapping(map);
+	check_map_for_destr(sp->u.map);
+	map = ref_mapping(copy_mapping(sp->u.map));
+    }
+    else {
+	if(map) free_mapping(map);
+	map = NULL;
+	sp++;
+	put_number(sp, 0);
+    }
+
+    return sp;
+}
+
+/* Return the mapping with the currently active logmask */
+/* EFUN */
+/* mapping getlogmask(void) */
+svalue_t *
+f_getlogmask (svalue_t *sp, int num_arg) {
+
+    if(num_arg)
+	error("Too many arguments to getlogmask().\n");
+
+    sp++;
+    if(map) put_mapping(sp, ref_mapping(copy_mapping(map)));
+    else put_number(sp, 0);
+    return sp;
+}
+
+/* Return the mapping with the currently active logfiles */
+/* EFUN */
+/* mapping getlogfiles(void) */
+svalue_t *
+f_getlogfiles (svalue_t *sp, int num_arg) {
+
+    if(num_arg)
+	error("Too many arguments to getlogfiles().\n");
+
+    sp++;
+    if(files) put_mapping(sp, ref_mapping(copy_mapping(files)));
+    else put_number(sp, 0);
+    return sp;
+}
+
+/* converts the given lpc-types to normal c-types and call ldsyslog() */
+/* EFUN */
+/* int syslog (int facility, int level, string message); */
+svalue_t *
+f_syslog (svalue_t *sp) {
+    svalue_t *argp;
+    int f, l;
+    const char *str;
+
+    argp = sp - 2;
+
+    TYPE_TESTV1(argp  , T_NUMBER)
+    TYPE_TESTV2(argp+1, T_NUMBER)
+    TYPE_TESTV3(argp+2, T_STRING)
+
+    f   = (argp  )->u.number;
+    l   = (argp+1)->u.number;
+    str = (argp+2)->u.string;
+
+    if(f >= LOG_NFACILITIES) error("Bad argument 1 to syslog(): illegal value %d.\n", f);
+    if(l >= LOG_NLEVELS) error("Bad argument 2 to syslog(): illegal value %d.\n", l);
+
+    put_number(argp, ldsyslog(f, l, str));
+
+    free_svalue(argp+1);
+    free_svalue(argp+2);
+
+    return argp;
+}
diff -Naur 3-2-dev.orig/src/syslog.h 3-2-dev/src/syslog.h
--- 3-2-dev.orig/src/syslog.h	Thu Jan  1 01:00:00 1970
+++ 3-2-dev/src/syslog.h	Mon Jan 28 11:12:14 2002
@@ -0,0 +1,32 @@
+#ifndef SYSLOG_H__
+#define SYSLOG_H__ 1
+
+#include <stdarg.h>
+#include "svalue.h"
+
+#define OUTPUT_MAXLEN 1024
+
+typedef struct _code {
+    char    *c_name;
+    int     c_val;
+} CODE;
+
+/* Close desriptor used to write to system logger.  */
+extern void ldcloselog ();
+
+/* Init logger system. must be called before logging happends!  */
+extern int ldopenlog ();
+
+/* Generate a log message using FMT string and option arguments.  */
+/* this function does the format parsing on its own. */
+extern int ldsyslog_memsafe (int facility, int level, const char *fmt, ...)
+     __attribute__ ((__format__ (__printf__, 3, 4))) ;
+
+/* use with normal strings or preparsed strings (e.g. sprintf) */
+extern int ldsyslog(int facility, int level, const char *output);
+
+extern svalue_t *f_setlogmask(svalue_t *sp, int num_arg);
+extern svalue_t *f_getlogmask(svalue_t *sp, int num_arg);
+extern svalue_t *f_syslog(svalue_t *sp);
+
+#endif /* syslog.h */

 --o00-00o-------o0--0o---------o0--0o----------o0o-o0o---

From: Christian Welzel <gawain@wh9.tu-dresden.de>
Date: Sun, 2 Dec 2001 17:46:53 +0100

Am Mittwoch, 28. November 2001 04:08 schrieben Sie:

> Die "Roadmap" sieht erstmal so aus, dass ich 3.2.9 crashfrei bekomme (oder
> zumindest zwei Wochen lang keine Crashmeldungen bekomme). Danach habe ich
> vor, PCRE und structs einzubauen - da sollte sich das Logging dann mit
> erledigen lassen.

Also hier schonmal so eine art von skelett fuer das system...
das include sollte man nach driver-defines und mudlib defines splitten,
wobei dann der driversrc auch das .h aus der mudlib einbinden muss...
(fuer die werte der defines). ausserdem muessen noch sinnvolle defines 
gefunden und definiert werden :)
ansonsten hoffe ich, dass es einen einblick in meine vorstellung gibt :)

 --o00-00o-------o0--0o---------o0--0o----------o0o-o0o---

