From 54dd4cd1c8dc4c7322b6ae2cf42c4c3f969f8d32 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Thu, 9 Feb 1995 17:27:11 +0000 Subject: [PATCH] Initial version of email gateway under CVS control. --- Makefile | 55 +++++ include/gw-log.h | 103 +++++++++ include/gw-res.h | 99 +++++++++ include/iso2709.h | 15 ++ include/iso2709p.h | 47 +++++ res+log/ChangeLog | 10 + res+log/Makefile | 53 +++++ res+log/README | 31 +++ res+log/adam.res | 3 + res+log/big.res | 354 +++++++++++++++++++++++++++++++ res+log/default.res | 13 ++ res+log/gw-log-test.c | 37 ++++ res+log/gw-log.c | 153 ++++++++++++++ res+log/gw-res-test.c | 155 ++++++++++++++ res+log/gw-res.c | 552 +++++++++++++++++++++++++++++++++++++++++++++++++ res+log/gw-resp.h | 53 +++++ util/Makefile | 49 +++++ util/iso2709.c | 178 ++++++++++++++++ util/iso2709dump.c | 28 +++ 19 files changed, 1988 insertions(+) create mode 100644 Makefile create mode 100644 include/gw-log.h create mode 100644 include/gw-res.h create mode 100644 include/iso2709.h create mode 100644 include/iso2709p.h create mode 100644 res+log/ChangeLog create mode 100644 res+log/Makefile create mode 100644 res+log/README create mode 100644 res+log/adam.res create mode 100644 res+log/big.res create mode 100644 res+log/default.res create mode 100644 res+log/gw-log-test.c create mode 100644 res+log/gw-log.c create mode 100644 res+log/gw-res-test.c create mode 100644 res+log/gw-res.c create mode 100644 res+log/gw-resp.h create mode 100644 util/Makefile create mode 100644 util/iso2709.c create mode 100644 util/iso2709dump.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a422291 --- /dev/null +++ b/Makefile @@ -0,0 +1,55 @@ +# Top level Makefile for Email gateway. +# Europagate, 1994-1995. +# +# $Log: Makefile,v $ +# Revision 1.1.1.1 1995/02/09 17:27:11 adam +# Initial version of email gateway under CVS control. +# +SHELL=/bin/sh +MAKE=make +SUBDIR=res+log util +CFLAGS=-Wall -g -pedantic -ansi +CC=gcc + +all: + for i in $(SUBDIR); do cd $$i; if $(MAKE) CFLAGS="$(CFLAGS)" CC="$(CC)"; then cd ..; else exit 1; fi; done + +dep depend: + for i in $(SUBDIR); do cd $$i; if $(MAKE) depend; then cd ..; else exit 1; fi; done + +clean: + rm -f lib/* + for i in $(SUBDIR); do (cd $$i; $(MAKE) clean); done + +cleanup: + rm -f lib `find $(SUBDIR) -name "*.[oa]" -print` + rm -f `find $(SUBDIR) -name "core" -print` + rm -f `find $(SUBDIR) -name "errlist" -print` + rm -f `find $(SUBDIR) -name "a.out" -print` + +distclean: cleanup clean + for i in $(SUBDIR); do (cd $$i; \ + mv Makefile Makefile.old; \ + sed '/^#Depend/q' Makefile; \ + rm Makefile.old); done + +usedepend1: + for i in $(SUBDIR); do (cd $$i; \ + mv Makefile Makefile.tmp; \ + sed 's/^if/#if/' Makefile; \ + rm Makefile.tmp); done + +usedepend2: + for i in $(SUBDIR); do (cd $$i; \ + mv Makefile Makefile.tmp; \ + sed '/^#Depend/q' Makefile; \ + rm Makefile.tmp); done + +wc: + wc `find . -name '*.[ch]'` + diff --git a/include/gw-log.h b/include/gw-log.h new file mode 100644 index 0000000..4c8649d --- /dev/null +++ b/include/gw-log.h @@ -0,0 +1,103 @@ +/* + gw-log.h: Logging facilities. + + Europagate, 1994-1995. + + $Log: gw-log.h,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + + Initial: Dec 7, 94 (Adam Dickmeiss) + Last update: Dec 13, 94 (Adam Dickmeiss) + */ + +#ifndef GW_LOG_H +#define GW_LOG_H +/* The log level is an unsigned integer value with at least 16 bits */ + +/* The log levels are defined below */ +#define GW_LOG_FATAL 0x01 +#define GW_LOG_WARN 0x02 +#define GW_LOG_ACCT 0x04 +#define GW_LOG_STAT 0x08 + +/* All debug levels */ +#define GW_LOG_DEBUG 0xfff0 +/* Individual debug levels, x sould be in range 0-11 */ +#define GW_LOG_DEBUGN(x) (0x10<<(x)) + +/* All levels on / All levels except debugging */ +#define GW_LOG_ALL 0xffff +#define GW_LOG_DEFAULT 0x0f + +void gw_log_init (const char *app_name); +/* + Initialises the log-system. Application name is given by 'app_name' - + could be specified as argv[0]. The application name should not + contain blanks! + + All log messages are directed to stderr on return from this function. + Override this behaviour by using the gw_log_file function. + + The log level is set to GW_LOG_DEFAULT. Override this with the + gw_log_level function. + + The session id is set to 0. Use gw_log_session to change this. + */ + +void gw_log_level (unsigned level); +/* + Sets the log to 'level' by using the GW_LOG_xxxx masks as described + above. + */ + +void gw_log_session (int session); +/* + Sets the session id to 'session'. + */ + +int gw_log_file (unsigned level, const char *fname); +/* + Specifies that output given by 'level' should be appended to file 'fname'. + Thus, all log messages can be written to one file or several files. + If 'level' is GW_LOG_ALL all output is appended to the same file. + If 'fname' is NULL it means that the output is written to stderr. + If 'fname' is "" it means the output is written to stdout. + + This function returns 0 on success; -1 on failure. + */ + +int gw_log (unsigned level, const char *event_type, const char *format, ...); +/* + Append log message to one or more files. The value of parameter + 'level' and the value given by the last gw_log_level call are bitwise + AND'ed. This value represents the log level for this message. + If this value is non-zero the 'event_type' and 'format' are used to + create the log entries which are appended to the log files specified by + the gw_log_file call(s). + + The 'event_type' should not contain blanks. + This function returns 0 on success; -1 on failure. + */ + +char *gw_strdup (const char *s); +/* + Works as strdup, which is not defined by ANSI. + */ + + +/* log file format: + + + Assuming that a 'token' is separated by one or more blanks we have: + + one token + one token + five tokens (Tue Dec 6 11:34:21 1994) + one token + one token + + zero or more tokens. + */ +#endif diff --git a/include/gw-res.h b/include/gw-res.h new file mode 100644 index 0000000..566913d --- /dev/null +++ b/include/gw-res.h @@ -0,0 +1,99 @@ +/* + gw-res.h: Resource management. + + Europagate, 1994-1995. + + $Log: gw-res.h,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + + Initial: Dec 7, 94 (Adam Dickmeiss) + Last update: Dec 13, 94 (Adam Dickmeiss) + */ +#ifndef GW_RES_H +#define GW_RES_H + +typedef struct Gw_res_info *GwRes; /* Gateway resource handle */ + +GwRes gw_res_init (void); +/* + A resource handle is returned by this function describing + the empty resource. + */ + +void gw_res_close (GwRes id); +/* + The resources described by 'id' are freed. No further references + to 'id' are allowed. + */ + +int gw_res_merge (GwRes id, const char *filename); +/* + The resources described by 'id' are merged by the contents of + 'filename'. If a resource is duplicated (in both resources 'id' and + the file) the resource is set to the value specified in 'filename'. + + This function returns 0 on success; -1 on failure ('filename' + could not be read) + */ + +const char *gw_res_get (GwRes id, const char *name, const char *def); +/* + The resource with name 'name' is checked in the resources represented + by 'id'. If the resource is present a pointer to the value (null- + terminated string) is returned. If the value is not present the + value of 'def' is returned. + */ + +int gw_res_put (GwRes id, const char *name, const char *value, + const char *fname); +/* + Change a resource - modify if it exists - add if not already + there. The resource will have impact on the file name 'fname'. + Use gw_res_commit (see below) to actually write to the + resource file. + */ + +int gw_res_commit (GwRes id, const char *fname); +/* + Rewrite the resource file 'fname'. If resources are modified/added + then these will be written now. + */ + + +int gw_res_trav (GwRes id, const char *fname, void (*tf)(const char *name, + const char *value)); +/* + Traverse resources associated with file 'fname'. For each resource + the handler 'tf' is invoked with name and value. + */ + +/* + GwRes file format. + + A resource name must begin on column 0 on a line. The name is followed + by colon. The value of the resource comes after the colon. A value may + span over several lines. Subsequent value lines are preceeded by one or + more blanks (tab/space). Empty/blank lines are ignored. Lines beginning + with # are treated as comments. + + Example + # Comment. Ignored + + # Single line resource + MaxSize: 1000 + # Multi line resource + FatalMsg: A serious error + occured. Aborting. + # Yet another (danish): + Warning: Advarsel, taenk + dig om - inden du foretager dig noget. + + The FatalMsg resource has the value "A serious error occured. Aborting.", + and the Warning resource has the value + "Advarsel, taenk dig om - inden du foretager dig noget." Note + that all blanks used to separate subsequent lines are treated as exactly + one blank. +*/ +#endif diff --git a/include/iso2709.h b/include/iso2709.h new file mode 100644 index 0000000..274b476 --- /dev/null +++ b/include/iso2709.h @@ -0,0 +1,15 @@ +/* + Record management + + Europagate, 1994-1995. + + $Log: iso2709.h,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + */ + +typedef struct iso2709_rec *Iso2709Rec; + +char *iso2709_read (FILE *inf); +Iso2709Rec iso2709_cvt (const char *buf); diff --git a/include/iso2709p.h b/include/iso2709p.h new file mode 100644 index 0000000..2266e71 --- /dev/null +++ b/include/iso2709p.h @@ -0,0 +1,47 @@ +/* + Record management + + Europagate, 1994-1995. + + $Log: iso2709p.h,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + */ + +#include + +struct iso2709_field { + char *indicator; + char *identifier; + char *data; + struct iso2709_field *next; +}; + +struct iso2709_dir { + char tag[4]; + int length; + int offset; + struct iso2709_dir *next; + struct iso2709_field *fields; +}; + +struct iso2709_rec { + int record_length; + char record_status[2]; + char implementation_codes[5]; + int indicator_length; + int identifier_length; + int base_address; + char user_systems[4]; + + int length_data_entry; + int length_starting; + int length_implementation; + char future_use[2]; + + struct iso2709_dir *directory; +}; + +#define ISO2709_FS 036 +#define ISO2709_IDFS 037 diff --git a/res+log/ChangeLog b/res+log/ChangeLog new file mode 100644 index 0000000..6fca9d9 --- /dev/null +++ b/res+log/ChangeLog @@ -0,0 +1,10 @@ +#$Log: ChangeLog,v $ +#Revision 1.1.1.1 1995/02/09 17:27:11 adam +#Initial version of email gateway under CVS control. +# +# +Dec 19 1994 + Advisory file locking used in merge/commit functions. + Makefile edited. +Dec 14 1994 + First version diff --git a/res+log/Makefile b/res+log/Makefile new file mode 100644 index 0000000..e9fd7dd --- /dev/null +++ b/res+log/Makefile @@ -0,0 +1,53 @@ +# Makefile for resource management/logging facilities. +# Europagate, 1994-1995. +# +# $Log: Makefile,v $ +# Revision 1.1.1.1 1995/02/09 17:27:11 adam +# Initial version of email gateway under CVS control. +# +SHELL=/bin/sh +INCLUDE=-I../include +CFLAGS=-Wall -pedantic -ansi +CPP=gcc -E +CC=gcc +TPROG1=gw-log-test +TPROG2=gw-res-test +LIB=../lib/libres+log.a +PO=gw-log.o gw-res.o +DEFS=$(INCLUDE) + +all: $(TPROG1) $(TPROG2) + +$(TPROG1): $(TPROG1).o $(LIB) + $(CC) $(CFLAGS) -o $(TPROG1) $(TPROG1).o $(LIB) + +$(TPROG2): $(TPROG2).o $(LIB) + $(CC) $(CFLAGS) -o $(TPROG2) $(TPROG2).o $(LIB) + +$(LIB): $(PO) + rm -f $(LIB) + ar qc $(LIB) $(PO) + ranlib $(LIB) + +.c.o: + $(CC) -c $(DEFS) $(CFLAGS) $< + +clean: + rm -f *.log *.[oa] $(TPROG1) $(TPROG2) core mon.out gmon.out errlist *~ + +depend: depend2 + +depend1: + mv Makefile Makefile.tmp + sed '/^#Depend/q' Makefile + $(CPP) $(INCLUDE) -M *.c >>Makefile + -rm Makefile.tmp + +depend2: + $(CPP) $(INCLUDE) -M *.c >.depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + +#Depend --- DOT NOT DELETE THIS LINE diff --git a/res+log/README b/res+log/README new file mode 100644 index 0000000..ca62fdb --- /dev/null +++ b/res+log/README @@ -0,0 +1,31 @@ +Wed Dec 14 1994 + +Resource management + logging system, Europagate 1994 + +File Description + +Makefile Makefile - use 'make all' / 'make clean' +gw-res.c Resource management - implementation. +gw-resp.h Resource management - private header file. +gw-res.h Resource management - public header file. +gw-log.c Logging system - implementation. +gw-log.h Logging system - public header file. +gw-log-test.c Small test example that uses the logging system. +gw-res-test.c Small interactive test program that uses the resources. +*.res Some resource files. + +A 'make all' will create: + +libres+log.a Library with logging+resource functions. +gw-log-test Small test program that uses the logging system. +gw-res-test Small test program that uses both logging+resource. + Starting the program with no parameters will invoke + a small interactive resource management shell. + +Normal applications should include gw-res.h and gw-log.h. Link +with the library libres+log.a. + +The API is described in gw-res.h and gw-log.h. + +Adam Dickmeiss + diff --git a/res+log/adam.res b/res+log/adam.res new file mode 100644 index 0000000..02c149c --- /dev/null +++ b/res+log/adam.res @@ -0,0 +1,3 @@ +# $Id: adam.res,v 1.1.1.1 1995/02/09 17:27:12 adam Exp $ +a: 3 +c: 45 diff --git a/res+log/big.res b/res+log/big.res new file mode 100644 index 0000000..42c3e54 --- /dev/null +++ b/res+log/big.res @@ -0,0 +1,354 @@ +# Personal X setup : ~/.Xdefaults, ~/.Xresources +# Adam Dickmeiss +# $Id: big.res,v 1.1.1.1 1995/02/09 17:27:12 adam Exp $ + +# This file specifies the default resources used by Emacs. +# Colors and backgrounds. +# ====================== +# The contrasts of these colors will cause them to map to the appropriate +# one of "black" or "white" on monochrome systems. +# +# The valid color names on your system can be found by looking in the file +# `rgb.txt', usually found in /usr/lib/X11/ or /usr/openwin/lib/X11/. + + +# Set the foreground and background colors. This will apply to all +# elements of Emacs, except those that specifically override them. +# Emacs*Foreground: Black +# Emacs*Background: #d3d3d3 + +# Set the color of the text cursor. + +# Set the color of the mouse pointer. + +# Set the menubar colors. This overrides the default foreground and +# background colors specified above. + +# Specify the colors of popup menus. + +# Specify the colors of the various sub-widgets of the dialog boxes. +# #A5C0C1 is a shade of blue + + +# If you want to turn off scrollbars, or change the default pixel width +# of the scrollbars, do it like this (0 width means no scrollbars): +# +# +# To change it for a particular screen, do this: +# +# Emacs*SCREEN-NAME.scrollBarWidth: 0 + + +# To have the Motif scrollbars on the left instead of the right, do this: +# +# Emacs*scrollBarPlacement: BOTTOM_LEFT +# +# The default is BOTTOM_RIGHT. There is no way to change the placement of +# the Athena scrollbars (all Athena programs put the scrollbars on the left.) + + +# Fonts. +# ====== +# Emacs requires the use of XLFD (X Logical Font Description) format font +# names, which look like +# +# *-courier-medium-r-*-*-*-120-*-*-*-*-*-* +# +# if you use any of the other, less strict font name formats, some of which +# look like +# lucidasanstypewriter-12 +# and fixed +# and 9x13 +# +# then Emacs won't be able to guess the names of the bold and italic versions. +# All X fonts can be referred to via XLFD-style names, so you should use those +# forms. See the man pages for X(1), xlsfonts(1), and xfontsel(1). + + +# The default font for the text area of lemacs is chosen at run-time +# by lisp code which tries a number of different possibilities in order +# of preference. If you wish to override it, use this: +# +# Emacs*default.attributeFont: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-* + +# If you choose a font which does not have an italic version, you can specify +# some other font to use for it here: +# +# +# And here is how you would set the background color of the `highlight' face, +# but only on the screen named `debugger': +# +# +# See the NEWS file (C-h n) for a more complete description of the resource +# syntax of faces. + + +# Font of the menubar and pop-up menus. +# Note that these do not use the `face' syntax, since they are outside the +# domain of Emacs proper, and in the domain of the X toolkit widgets: +# + +# Font in the Motif dialog boxes. +# (Motif uses `fontList' while most other things use `font' - if you don't +# know why you probably don't want to.) +# + + +# Dialog box translations. +# ======================= + +# This accelerator binds in a dialog box to on button1 + +# Translations to make the TextField widget behave more like Emacs + +# With the Emacs typeahead it's better to not have space be bound to +# ArmAndActivate() for buttons that appear in dialog boxes. This is +# not 100% Motif compliant but the benefits far outweight the +# compliancy problem. +# +# Mosaic defaults +# + + + + + + + +xfig*customization: -color +XRn.nntpServer: puff +XRn*index*Background: gray35 +XRn*index*Foreground: white +XRn*articleText*Background: gray35 +XRn*articleText*Foreground: white +XRn*indexinfo*Background: #5f9ea0 +XRn*textinfo*Background: #5f9ea0 +XRn*Foreground: black +XRn*Background: #d3d3d3 +XRn*Command.font: 8x13 +XRn.Geometry: 680x600 +Scrollbar.JumpCursor: True +Seyon.modem: /dev/ttyS3 +Seyon*Foreground: black +Seyon*Background: #5f9ea0 +Seyon*Label.Background: #d3d3d3 +Seyon*Command.Background: #d3d3d3 +XSysinfo*BarGauge.background: white +XSysinfo*background: #537483 +XSysinfo*font: fixed +Clock*hour: yellow +Clock*jewel: indianred1 +Clock*minute: yellow +xbiff*background: #537483 +xbiff*foreground: black +XTerm*SimpleMenu*Background: #d3d3d3 +XTerm*SimpleMenu*Foreground: black +XTerm*Background: gray35 +XTerm*Foreground: white +XTerm*cursorColor: IndianRed1 +XTerm*ScrollLines: 400 +Seyon.vt100*Foreground: white +Seyon.vt100*Background: gray36 +Seyon.vt100*ScrollLines: 400 +Xmris.Throw: return +Xmris.Right: s +Xmris.Left: a +Xmris.Down: comma +Xmris.Up: l +OpenWindows.AutoRaiseDelay: 200000 +OpenWindows.ShowResizeGeometry: True +OpenWindows.SetInput: followmouse +OpenWindows.VirtualBackgroundColor: Tan +OpenWindows.KeyboardCommands: Basic +OpenWindows.IconLocation: left +OpenWindows.ScrollbarPlacement: right +OpenWindows.Use3DFrames: True +OpenWindows.WindowColor: #98bfbf +OpenWindows.Beep: notices +OpenWindows.MinimalDecor: xclock xsysinfo olvwm +OpenWindows.VirtualFontColor: Black +OpenWindows.Use3DResize: False +OpenWindows.SelectDisplaysMenu: False +OpenWindows.ShowMoveGeometry: True +OpenWindows.AutoRaise: false +OpenWindows.MultiClickTimeout: 4 +OpenWindows.InvertFocusHighlighting: true +OpenWindows.DragRightDistance: 100 +OpenWindows.PopupJumpCursor: True +OpenWindows.WorkspaceColor: #7f7f7f +OpenWindows.VirtualForegroundColor: White +OpenWindows.PaintWorkSpace: false +olvwm.BackGround: green +olvwm.Foreground: black +olvwm.VirtualDesktop: 3x2 +olvwm.VirtualGeometry: +810+0 +*VT100.Translations: #override F1: string(0x01) string("1")\n\ F2: + string(0x01) string("2")\n +*customization: -color +*basicLocale: C +*numeric: C +*inputLang: C +*displayLang: C +*timeFormat: C +Emacs*Foreground: white +Emacs*Background: gray35 +Emacs*cursorColor: indianred1 +Emacs*pointerColor: indianred1 +Emacs*menubar*Foreground: Black +Emacs*menubar*Background: #5f9ea0 +Emacs*popup*Foreground: Black +Emacs*popup*Background: Gray75 +Emacs*dialog*Foreground: Black +Emacs*dialog*Background: #A5C0C1 +Emacs*dialog*XmTextField*Background: WhiteSmoke +Emacs*dialog*XmText*Background: WhiteSmoke +Emacs*dialog*XmList*Background: WhiteSmoke +Emacs*scrollBarWidth: 8 +Emacs*Font: -misc-fixed-medium-r-semicondensed--0-0-75-75-c-0-iso8859-1 +Emacs*default.attributeFont: -misc-fixed-medium-r-semicondensed--0-0-75-75-c-0-iso8859-1 +Emacs*italic.attributeFont: -*-courier-medium-o-*-*-*-120-*-*-*-*-iso8859-* +Emacs*debugger.highlight.attributeBackground: PaleTurquoise +Emacs*menubar*Font: -*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-* +Emacs*popup*Font: -*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-* +Emacs*XmDialogShell*FontList: -*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-* +Emacs*XmTextField*FontList: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-* +Emacs*XmText*FontList: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-* +Emacs*XmList*FontList: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-* +Emacs*dialog*button1.accelerators: #override\ +Return: ArmAndActivate()\n\ +KP_Enter: ArmAndActivate()\n\ +Ctrlm: ArmAndActivate()\n +Emacs*XmTextField.translations: #override\n\ + !osfBackSpace: delete-previous-character()\n\ + !osfDelete: delete-previous-character()\n\ !Ctrlh: + delete-previous-character()\n\ !Ctrld: delete-next-character()\n\ + !MetaosfDelete: delete-previous-word()\n\ + !MetaosfBackSpace: delete-previous-word()\n\ + !Metad: delete-next-word()\n\ !Ctrlk: delete-to-end-of-line()\n\ + !Ctrlg: process-cancel()\n\ !Ctrlb: backward-character()\n\ + !osfLeft: backward-character()\n\ !Ctrlf: forward-character()\n\ + !osfRight: forward-character()\n\ !Metab: backward-word()\n\ + !MetaLeft: backward-word()\n\ !MetaosfLeft: backward-word()\n\ + !Metaf: forward-word()\n\ |MetaRight: forward-word()\n\ + !MetaosfRight: forward-word()\n\ !Ctrle: end-of-line()\n\ + !Ctrla: beginning-of-line()\n\ !Ctrlw: cut-clipboard()\n\ + !Metaw: copy-clipboard()\n\ : copy-primary()\n +Emacs*dialog*XmPushButton.translations: #override\n\ : Arm()\n\ + ,: Activate()\ Disarm()\n\ (2+): MultiArm()\n\ + (2+): MultiActivate()\n\ : Activate()\ Disarm()\n\ + osfSelect: ArmAndActivate()\n\ osfActivate: ArmAndActivate()\n\ + osfHelp: Help()\n\ ~Shift ~Meta ~Alt Return: ArmAndActivate()\n\ + : Enter()\n\ : Leave()\n +Mosaic*XmLabel*fontList: -*-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*XmLabelGadget*fontList: -*-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*XmScale*fontList: -*-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*XmBulletinBoard*labelFontList: -*-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*optionmenu.XmLabelGadget*fontList: -*-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*XmPushButton*fontList: -*-helvetica-medium-r-normal-*-14-*-iso8859-1 +Mosaic*XmPushButtonGadget*fontList: -*-helvetica-medium-r-normal-*-14-*-iso8859-1 +Mosaic*XmToggleButton*fontList: -*-helvetica-medium-r-normal-*-14-*-iso8859-1 +Mosaic*XmToggleButtonGadget*fontList: -*-helvetica-medium-r-normal-*-14-*-iso8859-1 +Mosaic*optionmenu*fontList: -*-helvetica-medium-r-normal-*-14-*-iso8859-1 +Mosaic*XmIconGadget*fontList: -*-helvetica-medium-r-normal-*-14-*-iso8859-1 +Mosaic*XmBulletinBoard*buttonFontList: -*-helvetica-medium-r-normal-*-14-*-iso8859-1 +Mosaic*menubar*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmMenuShell*XmPushButton*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmMenuShell*XmLabelGadget*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmMenuShell*XmPushButtonGadget*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmMenuShell*XmCascadeButton*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmMenuShell*XmCascadeButtonGadget*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmCascadeButton*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmCascadeButtonGadget*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmMenuShell*XmToggleButton*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmMenuShell*XmToggleButtonGadget*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*pulldownmenu*fontList: -*-helvetica-bold-o-normal-*-14-*-iso8859-1 +Mosaic*XmList*fontList: -*-helvetica-medium-r-normal-*-14-*-iso8859-1 +Mosaic*XmText.fontList: -*-lucidatypewriter-medium-r-normal-*-14-*-iso8859-1 +Mosaic*XmTextField.fontList: -*-lucidatypewriter-medium-r-normal-*-14-*-iso8859-1 +Mosaic*optionmenu*marginHeight: 0 +Mosaic*optionmenu*marginTop: 5 +Mosaic*optionmenu*marginBottom: 5 +Mosaic*optionmenu*marginWidth: 5 +Mosaic*pulldownmenu*XmPushButton*marginHeight: 1 +Mosaic*pulldownmenu*XmPushButton*marginWidth: 1 +Mosaic*pulldownmenu*XmPushButton*marginLeft: 3 +Mosaic*pulldownmenu*XmPushButton*marginRight: 3 +Mosaic*XmList*listMarginWidth: 3 +Mosaic*menubar*marginHeight: 1 +Mosaic*menubar.marginHeight: 0 +Mosaic*menubar*marginLeft: 1 +Mosaic*menubar.spacing: 7 +Mosaic*XmMenuShell*marginLeft: 3 +Mosaic*XmMenuShell*marginRight: 4 +Mosaic*XmMenuShell*XmToggleButtonGadget*spacing: 2 +Mosaic*XmMenuShell*XmToggleButtonGadget*marginHeight: 0 +Mosaic*XmMenuShell*XmToggleButtonGadget*indicatorSize: 12 +Mosaic*XmMenuShell*XmLabelGadget*marginHeight: 4 +Mosaic*XmToggleButtonGadget*spacing: 4 +Mosaic*XmToggleButton*spacing: 4 +Mosaic*XmScrolledWindow*spacing: 0 +Mosaic*XmScrollBar*width: 18 +Mosaic*XmScrollBar*height: 18 +Mosaic*XmScale*scaleHeight: 20 +Mosaic*XmText*marginHeight: 4 +Mosaic*fsb*XmText*width: 420 +Mosaic*fsb*XmTextField*width: 420 +Mosaic*fsb*XmText*height: 500 +Mosaic*fsb*XmTextField*height: 500 +Mosaic*fillOnSelect: True +Mosaic*visibleWhenOff: True +Mosaic*XmText*highlightThickness: 0 +Mosaic*XmTextField*highlightThickness: 0 +Mosaic*XmPushButton*highlightThickness: 0 +Mosaic*XmScrollBar*highlightThickness: 0 +Mosaic*highlightThickness: 0 +Mosaic*keyboardFocusPolicy: pointer +Mosaic*TitleFont: -adobe-times-bold-r-normal-*-24-*-*-*-*-*-iso8859-1 +Mosaic*Font: -adobe-times-medium-r-normal-*-17-*-*-*-*-*-iso8859-1 +Mosaic*ItalicFont: -adobe-times-medium-i-normal-*-17-*-*-*-*-*-iso8859-1 +Mosaic*BoldFont: -adobe-times-bold-r-normal-*-17-*-*-*-*-*-iso8859-1 +Mosaic*FixedFont: -adobe-courier-medium-r-normal-*-17-*-*-*-*-*-iso8859-1 +Mosaic*FixedboldFont: -adobe-courier-bold-r-normal-*-17-*-*-*-*-*-iso8859-1 +Mosaic*FixeditalicFont: -adobe-courier-medium-o-normal-*-17-*-*-*-*-*-iso8859-1 +Mosaic*Header1Font: -adobe-times-bold-r-normal-*-24-*-*-*-*-*-iso8859-1 +Mosaic*Header2Font: -adobe-times-bold-r-normal-*-18-*-*-*-*-*-iso8859-1 +Mosaic*Header3Font: -adobe-times-bold-r-normal-*-17-*-*-*-*-*-iso8859-1 +Mosaic*Header4Font: -adobe-times-bold-r-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*Header5Font: -adobe-times-bold-r-normal-*-12-*-*-*-*-*-iso8859-1 +Mosaic*Header6Font: -adobe-times-bold-r-normal-*-10-*-*-*-*-*-iso8859-1 +Mosaic*AddressFont: -adobe-times-medium-i-normal-*-17-*-*-*-*-*-iso8859-1 +Mosaic*PlainFont: -adobe-courier-medium-r-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*PlainboldFont: -adobe-courier-bold-r-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*PlainitalicFont: -adobe-courier-medium-o-normal-*-14-*-*-*-*-*-iso8859-1 +Mosaic*ListingFont: -adobe-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1 +Mosaic*Foreground: #000000000000 +Mosaic*XmScrollBar*Foreground: #afafafafafaf +Mosaic*Background: #d3d3d3 +Mosaic*XmList*Background: #d3d3d3 +Mosaic*XmText*Background: #d3d3d3 +Mosaic*TroughColor: #545454545454 +Mosaic*XmSelectionBox*Background: #545454545454 +Mosaic*XmMessageBox*Background: #d3d3d3 +Mosaic*XmLabel*Foreground: #1d1d15155b5b +Mosaic*XmToggleButton*Foreground: #1d1d15155b5b +Mosaic*XmPushButton*Foreground: #5b5b00000000 +Mosaic*logo*Foreground: #1d1d15155b5b +Mosaic*XmTextField*Background: #5f9ea0 +Mosaic*SelectColor: #ffffffff0000 +Mosaic*HighlightColor: #afafafafafaf +Mosaic*TopShadowColor: #efefefefefef +Mosaic*XmList*TopShadowColor: #efefefefefef +Mosaic*XmText*TopShadowColor: #efefefefefef +Mosaic*XmSelectionBox*TopShadowColor: #efefefefefef +Mosaic*XmMessageBox*TopShadowColor: #efefefefefef +Mosaic*visitedAnchorColor: #272705055b5b +Mosaic*anchorColor: #00000000b0b0 +Mosaic*activeAnchorFG: #ffff00000000 +Mosaic*activeAnchorBG: #d3d3d3 +Mosaic*AnchorUnderlines: 1 +Mosaic*VisitedAnchorUnderlines: 1 +Mosaic*DashedVisitedAnchorUnderlines: True +Mosaic*VerticalScrollOnRight: True +Mosaic*HomeDocument: http://puff.index.dk/ +Mosaic*ConfirmExit: False +loopvar: 200 diff --git a/res+log/default.res b/res+log/default.res new file mode 100644 index 0000000..5b4f8de --- /dev/null +++ b/res+log/default.res @@ -0,0 +1,13 @@ +# This is default.res +# $Log: default.res,v $ +# Revision 1.1.1.1 1995/02/09 17:27:12 adam +# Initial version of email gateway under CVS control. +# + +a: 1 +b: 2 +long_resource: Makefile adam.res all.log big.res default.res default.res.w + gw-log-test* gw-log-test.c gw-log-test.o gw-log.c gw-log.h gw-log.o + gw-res-test* gw-res-test.c gw-res-test.o gw-res.c gw-res.c~ gw-res.h + gw-res.o gw-resp.h libres+log.a +# End of file diff --git a/res+log/gw-log-test.c b/res+log/gw-log-test.c new file mode 100644 index 0000000..8e647e9 --- /dev/null +++ b/res+log/gw-log-test.c @@ -0,0 +1,37 @@ +/* + gw-log-test.c: Test of logging facilities. + + Europagate, 1994-1995. + + $Log: gw-log-test.c,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + + Initial: Dec 7, 94 (Adam Dickmeiss) + Last update: Dec 13, 94 (Adam Dickmeiss) + + */ + +#include +#include +#include +#include + +#include + +int main (int argc, char **argv) +{ + gw_log_init (*argv); + + gw_log_file (GW_LOG_ALL, "all.log"); + + gw_log (GW_LOG_ALL, "Msg", "Hi all, a"); + gw_log (GW_LOG_STAT, "Msg", "Hi stat, a"); + gw_log_file (GW_LOG_WARN, "warn.log"); + gw_log_file (GW_LOG_FATAL, NULL); + gw_log (GW_LOG_ALL, "Msg", "Hi all, b"); + gw_log (GW_LOG_STAT, "Msg", "Hi stat, b"); + gw_log (GW_LOG_WARN, "Msg", "Hi warn, b"); + exit (0); +} diff --git a/res+log/gw-log.c b/res+log/gw-log.c new file mode 100644 index 0000000..9f8f30d --- /dev/null +++ b/res+log/gw-log.c @@ -0,0 +1,153 @@ +/* + gw-log.c: Implementation of logging facilities. + + Europagate, 1994-1995. + + $Log: gw-log.c,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + + Initial: Dec 7, 94 (Adam Dickmeiss) + Last update: Dec 13, 94 (Adam Dickmeiss) + + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +static char *app_name = NULL; +static unsigned level = GW_LOG_DEFAULT; +static int session = 0; + +struct file_mask { + unsigned mask; /* level mask for this file entry */ + int fd; /* file descriptor for this file */ + char *fname; /* name of file ("" if stdout) */ + struct file_mask *next; /* next file in chain */ +}; + +struct file_mask *file_mask_list = NULL; + +char *gw_strdup (const char *s) +{ + char *n = malloc (strlen(s)+1); + if (n) + strcpy (n, s); + return n; +} + +void gw_log_init (const char *app_name_a) +{ + struct file_mask *list, *list1; + + app_name = gw_strdup (app_name_a); + level = GW_LOG_DEFAULT; + session = 0; + + /* clean up all output file masks... */ + for (list = file_mask_list; list; list = list1) + { + if (list->fd > 2) /* avoid closing stdout/stderr */ + close (list->fd); + free (list->fname); + list1 = list->next; + free (list); + } + file_mask_list = NULL; +} + +void gw_log_level (unsigned level_a) +{ + level = level_a; +} + +void gw_log_session (int session_a) +{ + session = session_a; +} + +int gw_log_file (unsigned level_a, const char *fname_a) +{ + struct file_mask **listp, *new_file_mask; + listp = &file_mask_list; + + /* go through file mask list and close files already associated */ + /* on new level */ + while (*listp) + { + if (!((*listp)->mask &= ~level_a)) /* any levels left on this one? */ + { + if ((*listp)->fd > 2) /* close if not stdout/stderr */ + close ((*listp)->fd); + free ((*listp)->fname); + *listp = (*listp)->next; + } + listp = &(*listp)->next; + } + if (!fname_a) /* stderr? */ + return 0; /* stderr doesn't appear on list */ + new_file_mask = malloc (sizeof(*new_file_mask)); + if (!new_file_mask) + return -1; + new_file_mask->mask = level_a; + new_file_mask->next = file_mask_list; + file_mask_list = new_file_mask; + if (!(file_mask_list->fname = gw_strdup (fname_a))) + return -1; + if (*fname_a == '\0') /* stdout? */ + new_file_mask->fd = 1; + else /* no, open as usual */ + { + new_file_mask->fd = open (fname_a, O_WRONLY|O_CREAT|O_APPEND, 0666); + if (new_file_mask->fd == -1) + return -1; + } + return 0; +} + +int gw_log (unsigned level_a, const char *event_type, const char *format, ...) +{ + static char emit_str[2048]; + struct file_mask *list; + va_list ap; + unsigned e_level = level_a & level; + int count; + int err = 0; + time_t time_now; + char *cp; + + if (!e_level) /* any effective level(s)? */ + return 0; + + va_start (ap, format); + time (&time_now); + sprintf (emit_str, "%s %d %s %d %s ", app_name, session, + ctime (&time_now), e_level, event_type); + if ((cp = strchr (emit_str, '\n'))) /* remove \n from ctime-str */ + *cp = ' '; + count = strlen (emit_str); + vsprintf (emit_str+count, format, ap); + strcat (emit_str, "\n"); + count = strlen (emit_str); + + /* go through file mask list... */ + for (list = file_mask_list; list; list = list->next) + if (list->mask & e_level) /* output this one? */ + { + e_level &= ~list->mask; /* remove from effective level */ + if (write (list->fd, emit_str, count) != count) + err = 1; + } + if (e_level) /* bits left on effective level? */ + write (2, emit_str, count); + va_end (ap); + return err; +} diff --git a/res+log/gw-res-test.c b/res+log/gw-res-test.c new file mode 100644 index 0000000..5e9b2b1 --- /dev/null +++ b/res+log/gw-res-test.c @@ -0,0 +1,155 @@ +/* + gw-res-test.c: Test of resource management. + + Europagate, 1994-1995. + + $Log: gw-res-test.c,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + + Initial: Dec 7, 94 (Adam Dickmeiss) + Last update: Dec 13, 94 (Adam Dickmeiss) + + */ + +#include +#include +#include +#include + +#include +#include + +static GwRes res; + +static void showf (const char *name, const char *value) +{ + printf ("%s: %s\n", name, value); +} + +static void interactive (void) +{ + char buffer[128]; + char arg[3][128]; + int no_arg; + int r; + + while (1) + { + char *cp; + const char *value; + + putc ('>', stdout); + fflush (stdout); + if (!(fgets (buffer, sizeof(buffer)-1, stdin))) + break; + while ((cp = strchr (buffer, '\n'))) + *cp = '\0'; + if (*buffer == '\0') + continue; + no_arg = sscanf (buffer+1, "%s %s %s", arg[0], arg[1], arg[2]); + r = -10; + switch (*buffer) + { + case 'm': + if (no_arg == 1) + r = gw_res_merge (res, arg[0]); + break; + case 'p': + if (no_arg == 3) + r = gw_res_put (res, arg[0], arg[1], arg[2]); + break; + case 'g': + if (no_arg == 1) + { + value = gw_res_get (res, arg[0], ""); + printf ("%s has value `%s'\n", arg[0], value); + r = 0; + } + break; + case 's': + if (no_arg == 1) + r = gw_res_trav (res, arg[0], showf); + else if (no_arg <= 0) + r = gw_res_trav (res, NULL, showf); + break; + case 'c': + if (no_arg == 1) + r = gw_res_commit (res, arg[0]); + break; + case 'h': + printf ("m merge\n" + "g get\n" + "p put\n" + "s [] show\n" + "c commit\n" + "q quit\n"); + r = 0; + break; + case 'q': + return; + } + if (r == -10) + printf ("syntax, type 'h' for help\n"); + else if (r) + printf ("returned %d\n", r); + else + printf ("ok\n"); + } +} + +static void do_intensive (void) +{ + int i; + for (i = 0; i<100; i++) + { + const char *cp; + char new_val[12]; + res = gw_res_init (); + + gw_res_merge (res, "big.res"); + gw_res_merge (res, "default.res"); + gw_res_merge (res, "adam.res"); + + cp = gw_res_get (res, "loopvar", "0"); + sprintf (new_val, "%d", atoi(cp)+1); + gw_res_put (res, "loopvar", new_val, "big.res"); + + gw_res_commit (res, "big.res"); + gw_res_close (res); + } +} + +int main (int argc, char **argv) +{ + gw_log_init (*argv); + + while (--argc > 0) + { + if (**++argv == '-') + { + switch (*++*argv) + { + case 'd': + gw_log_level (GW_LOG_ALL); + continue; + case 't': + do_intensive (); + return 0; + default: + gw_log (GW_LOG_FATAL, "Fatal", "Unknown option %s", + *argv); + exit (1); + } + } + } + gw_log_file (GW_LOG_ALL, "all.log"); + + res = gw_res_init (); + + interactive (); + + gw_res_close (res); + exit (0); +} diff --git a/res+log/gw-res.c b/res+log/gw-res.c new file mode 100644 index 0000000..fc7c334 --- /dev/null +++ b/res+log/gw-res.c @@ -0,0 +1,552 @@ +/* + gw-res.c: Implementation of resource management. + + Europagate, 1994-1995. + + $Log: gw-res.c,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + + Initial: Dec 8, 94 (Adam Dickmeiss) + Last update: Dec 19, 94 (Adam Dickmeiss) + + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_FLOCK +#include +#else +#include +#endif + +#include +#include "gw-resp.h" + +/* + symtab_open: Create empty symbol table. + symbol table handle is returned. + */ + +static struct res_symtab *symtab_open (void) +{ + struct res_symtab *symtab; + + symtab = malloc (sizeof(*symtab)); + if (!symtab) + return NULL; + symtab->next = NULL; + return symtab; +} + +/* + symtab_close: Delete symbol table. + */ +static void symtab_close (struct res_symtab *symtab) +{ + struct res_sym_entry *entry, *entry1; + + for (entry = symtab->next; entry; entry = entry1) + { + entry1 = entry->next; + free (entry); + } + free (symtab); +} + +/* + symtab_override: Add symbol to table. 'rl' holds symbol + table entry info. If the symbol is already present it + will override old info. + */ +static int symtab_override (struct res_symtab *symtab, + struct res_line_info *rl) +{ + struct res_sym_entry *entry; + + for (entry = symtab->next; entry; entry=entry->next) + if (!strcmp (entry->info->name, rl->name)) + { + entry->info = rl; + return 1; + } + entry = malloc (sizeof(*entry)); + if (!entry) + return -1; + entry->next = symtab->next; + symtab->next = entry; + entry->info = rl; + return 0; +} + +/* + symtab_lookup: Symbol table lookup. If successful info is returned; + otherwise NULL is returned. + */ +static struct res_line_info *symtab_lookup (struct res_symtab *symtab, + const char *name) +{ + struct res_sym_entry *entry; + + for (entry = symtab->next; entry; entry=entry->next) + if (!strcmp (entry->info->name, name)) + return entry->info; + return NULL; +} + +/* + lock_file: File locking using fcntl. + */ +#if !HAVE_FLOCK +static void lock_file (int fd, int type) +{ + struct flock area; + area.l_type = type; + area.l_whence = SEEK_SET; + area.l_start = 0L; + area.l_len = 0L; + fcntl (fd, F_SETLKW, &area); +} +#endif + +/* + gw_res_init: A resource handle is returned by this function + describing empty resources. + */ +GwRes gw_res_init (void) +{ + GwRes p; + + if (!(p = malloc (sizeof(*p)))) + return p; + p->files = NULL; + p->symtab = symtab_open (); + if (!p->symtab) + { + free (p); + return NULL; + } + return p; +} + +/* + gw_res_close: The resources described by 'id' are freed. + No further references to 'id' are allowed. + */ +void gw_res_close (GwRes id) +{ + struct res_line_info *rl, *rl1; + struct res_file_info *rf, *rf1; + + assert (id); + + symtab_close (id->symtab); + for (rf = id->files; rf; rf = rf1) + { + for (rl = rf->lines; rl; rl = rl1) + { + free (rl->name); + free (rl->value); + rl1 = rl->next; + free (rl); + } + free (rf->fname); + rf1 = rf->next; + free (rf); + } + free (id); +} + +/* + add_name: add a node with line information. + */ +static struct res_line_info *add_name (enum res_kind kind, + const char *name, const char *value) +{ + struct res_line_info *rl; + + if (!(rl = malloc (sizeof(*rl)))) + return NULL; + rl->next = NULL; + rl->kind = kind; + if (name) + { + rl->name = gw_strdup (name); + if (!rl->name) + { + free (rl); + return NULL; + } + } + else + rl->name = NULL; + if (value) + { + rl->value = gw_strdup (value); + if (!rl->value) + { + free (rl->name); + free (rl); + return NULL; + } + } + else + rl->value = NULL; + return rl; +} + +/* + gw_res_merge: The resources described by 'id' are merged by the contents + of 'filename'. If a resource is duplicated (in both resources 'id' + and the file) the resource is set to the value specified in 'filename'. + This function returns 0 on success; -1 on failure ('filename' + could not be read) + */ +int gw_res_merge (GwRes id, const char *filename) +{ + FILE *inf; + char buffer[1024]; + char value[2048]; + struct res_file_info *ri; + struct res_line_info **rlp, *rl; + struct res_line_info *rl_last = NULL; + int err = 0; + + assert (id); + + gw_log (GW_LOG_DEBUG, "res", "gw_res_merge"); + gw_log (GW_LOG_DEBUG, "res", "checking %s", filename); + if (!(inf = fopen (filename, "r"))) + return -1; +#if HAVE_FLOCK + flock (fileno(inf), LOCK_SH); +#else + lock_file (fileno (inf), F_RDLCK); +#endif + if (!(ri = malloc (sizeof (*ri)))) + { + fclose (inf); + return -1; + } + if (!(ri->fname = gw_strdup (filename))) + { + free (ri); + fclose (inf); + return -2; + } + gw_log (GW_LOG_DEBUG, "res", "reading %s", filename); + ri->next = id->files; + id->files = ri; + rlp = &ri->lines; + ri->lines = NULL; + while (fgets (buffer, sizeof(buffer)-1, inf)) + { + char *cp; + while ((cp = strchr (buffer, '\n'))) + *cp = '\0'; + if (*buffer == '#') + { /* comment line */ + rl = add_name (comment, NULL, buffer); + if (!rl) + { + err = -2; + break; + } + *rlp = rl; + rlp = &rl->next; + } + else if (*buffer == '\0' || *buffer == ' ' || *buffer == '\t') + { + int i = 0; + while (buffer[i] == ' ' || buffer[i] == '\t') + i++; + if (buffer[i] == '\0') + { /* empty line */ + rl = add_name (blank, NULL, NULL); + if (!rl) + { + err = -2; + break; + } + *rlp = rl; + rlp = &rl->next; + } + else + { /* continuation line */ + int j = strlen (buffer)-1; + /* strip trailing blanks */ + while (buffer[j] == '\t' || buffer[j] == ' ') + --j; + buffer[j+1] = '\0'; + if (rl_last) + { + if (strlen(value)+strlen(buffer+i) >= sizeof(value)-2) + { + gw_log (GW_LOG_WARN, "res", "Resource `%s' is " + " truncated", rl_last->name); + } + else + { + /* effectively add one blank, then buffer */ + strcat (value, " "); + strcat (value, buffer+i); + } + } + else + gw_log (GW_LOG_WARN, "res", "Resource file has bad " + "continuation line"); + } + } + else + { /* resource line */ + int i = 0; + if (rl_last) + { + rl_last->value = gw_strdup (value); + rl_last = NULL; + } + while (buffer[i] && buffer[i] != ':') + i++; + if (buffer[i] == ':') + { + int j = strlen(buffer)-1; + buffer[i++] = '\0'; /* terminate name */ + while (buffer[i] == ' ' || buffer[i] == '\t') + i++; /* skip blanks before */ + while (buffer[j] == '\t' || buffer[j] == ' ') + --j; /* skip blanks after */ + buffer[j+1] = '\0'; /* terminate value */ + strcpy (value, buffer+i); + rl_last = add_name (resource, buffer, NULL); + if (!rl_last) + err = -2; + else + { + *rlp = rl_last; + rlp = &rl_last->next; + } + } + } + } + if (rl_last) + rl_last->value = gw_strdup (value); +#if HAVE_FLOCK + flock (fileno (inf), LOCK_UN); +#else + lock_file (fileno (inf), F_UNLCK); +#endif + fclose (inf); + gw_log (GW_LOG_DEBUG, "res", "close of %s", filename); + for (rl = ri->lines; rl; rl = rl->next) + { + switch (rl->kind) + { + case comment: + gw_log (GW_LOG_DEBUG, "res", "%s", rl->value); + break; + case resource: + gw_log (GW_LOG_DEBUG, "res", "%s: %s", rl->name, rl->value); + if (symtab_override (id->symtab, rl) < 0) + err = -2; + break; + case blank: + gw_log (GW_LOG_DEBUG, "res", ""); + break; + default: + assert (0); + } + } + gw_log (GW_LOG_DEBUG, "res", "gw_res_merge returned %d", err); + return err; +} + +/* + gw_res_get: The resource with name 'name' is checked in the resources + represented by 'id'. If the resource is present a pointer to the + value (null-terminated string) is returned. If the value is not + present the value of 'def' is returned. + */ +const char *gw_res_get (GwRes id, const char *name, const char *def) +{ + struct res_line_info *rl; + + assert (id); + rl = symtab_lookup (id->symtab, name); + if (!rl) + return def; + return rl->value; +} + +/* + gw_res_put: Change a resource - modify if it exists - add if not + already there. The resource will have impact on the file name + 'fname'. Use gw_res_commit (see below) to actually write to the + resource file. + */ +int gw_res_put (GwRes id, const char *name, const char *value, + const char *fname) +{ + struct res_file_info *ri; + struct res_line_info **rlp; + assert (id); + assert (fname); + + for (ri = id->files; ri; ri = ri->next) + if (!strcmp (ri->fname, fname)) + break; + if (!ri) + { + if (!(ri = malloc (sizeof (*ri)))) + return -1; + if (!(ri->fname = gw_strdup (fname))) + { + free (ri); + return -1; + } + ri->next = id->files; + id->files = ri; + ri->lines = NULL; + } + for (rlp = &ri->lines; *rlp; rlp = &(*rlp)->next) + if (!strcmp ((*rlp)->name, name)) + break; + if (*rlp) + { + char *new_val = gw_strdup (value); + if (!new_val) + return -1; + free ((*rlp)->value); + (*rlp)->value = new_val; + } + else + { + *rlp = add_name (resource, name, value); + if (!*rlp) + return -1; + (*rlp)->next = NULL; + if (symtab_override (id->symtab, *rlp) < 0) + return -1; + } + return 0; +} + +/* + gw_res_commit: Write the resource file 'fname'. If resources + are modified/added then these will be written now. + */ +int gw_res_commit (GwRes id, const char *fname) +{ + struct res_file_info *ri; + struct res_line_info *rl; + FILE *out; + int i, pos; + + assert (id); + assert (fname); + + for (ri = id->files; ri; ri = ri->next) + if (!strcmp (ri->fname, fname)) + break; + if (!ri) + return -1; + if (!(out = fopen (fname, "w"))) + return -1; +#if HAVE_FLOCK + flock (fileno (out), LOCK_EX); +#else + lock_file (fileno (out), F_WRLCK); +#endif + for (rl = ri->lines; rl; rl = rl->next) + switch (rl->kind) + { + case comment: + fputs (rl->value, out); + case blank: + fputc ('\n', out); + break; + case resource: + fprintf (out, "%s: ", rl->name); + pos = strlen(rl->name)+2; + i = 0; + while (1) + { + int left = 78-pos; + if (strlen(rl->value+i) <= left) + break; + while (left > 0) + { + if (rl->value[i+left] == ' ') + break; + + --left; + } + if (left > 0) + { + int j; + for (j = 0; jvalue[i+j], out); + i += left+1; + } + else + break; + fprintf (out, "\n "); + pos = 2; + } + fprintf (out, "%s\n", rl->value+i); + break; + default: + assert (0); + } + fflush (out); +#if HAVE_FLOCK + flock (fileno (out), LOCK_UN); +#else + lock_file (fileno (out), F_UNLCK); +#endif + fclose (out); + return 0; +} + +/* + gw_res_trav: Traverse resources associated with file 'fname'. For + each resource the handler 'tf' is invoked with name and value. + */ +int gw_res_trav (GwRes id, const char *fname, void (*tf)(const char *name, + const char *value)) +{ + assert (id); + assert (tf); + + if (fname) + { + struct res_file_info *ri; + struct res_line_info *rl; + + for (ri = id->files; ri; ri = ri->next) + if (!strcmp (ri->fname, fname)) + break; + if (!ri) + return -1; + for (rl = ri->lines; rl; rl = rl->next) + if (rl->kind == resource) + (*tf) (rl->name, rl->value); + } + else + { + struct res_sym_entry *entry; + + for (entry = id->symtab->next; entry; entry=entry->next) + (*tf) (entry->info->name, entry->info->value); + } + return 0; +} + + + diff --git a/res+log/gw-resp.h b/res+log/gw-resp.h new file mode 100644 index 0000000..6827143 --- /dev/null +++ b/res+log/gw-resp.h @@ -0,0 +1,53 @@ +/* + gw-res.h: Private header file for resource management. + + Europagate, 1994-1995. + + $Log: gw-resp.h,v $ + Revision 1.1.1.1 1995/02/09 17:27:12 adam + Initial version of email gateway under CVS control. + + + Initial: Dec 7, 94 (Adam Dickmeiss) + Last update: Dec 13, 94 (Adam Dickmeiss) + */ + +#include + +enum res_kind { + comment, + blank, + resource +}; + +/* information about each line */ +struct res_line_info { + enum res_kind kind; + char *name; + char *value; + struct res_line_info *next; +}; + +/* information about each file */ +struct res_file_info { + char *fname; + struct res_line_info *lines; + struct res_file_info *next; +}; + +/* symbol table entry */ +struct res_sym_entry { + struct res_line_info *info; + struct res_sym_entry *next; +}; + +/* symbol table */ +struct res_symtab { + struct res_sym_entry *next; +}; + +/* all resource information */ +struct Gw_res_info { + struct res_file_info *files; + struct res_symtab *symtab; +}; diff --git a/util/Makefile b/util/Makefile new file mode 100644 index 0000000..4de78c2 --- /dev/null +++ b/util/Makefile @@ -0,0 +1,49 @@ +# Makefile for Email gateway utilities +# Europagate, 1995 +# +# $Log: Makefile,v $ +# Revision 1.1.1.1 1995/02/09 17:27:11 adam +# Initial version of email gateway under CVS control. +# +SHELL=/bin/sh +INCLUDE=-I../include +CFLAGS=-g -Wall -pedantic -ansi +CC=gcc +TPROG1=iso2709dump +LIB=../lib/util.a +PO=iso2709.o +CPP=cc -E +DEFS=$(INCLUDE) + +all: $(TPROG1) + +$(TPROG1): $(TPROG1).o $(LIB) + $(CC) $(CFLAGS) -o $(TPROG1) $(TPROG1).o $(LIB) + +$(LIB): $(PO) + rm -f $(LIB) + ar qc $(LIB) $(PO) + ranlib $(LIB) + +.c.o: + $(CC) -c $(DEFS) $(CFLAGS) $< + +clean: + rm -f *.log *.[oa] $(TPROG1) $(TPROG2) core mon.out gmon.out errlist *~ + +depend: depend2 + +depend1: + mv Makefile Makefile.tmp + sed '/^#Depend/q' Makefile + $(CPP) $(INCLUDE) -M *.c >>Makefile + -rm Makefile.tmp + +depend2: + $(CPP) $(INCLUDE) -M *.c >.depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + +#Depend --- DOT NOT DELETE THIS LINE diff --git a/util/iso2709.c b/util/iso2709.c new file mode 100644 index 0000000..19e0486 --- /dev/null +++ b/util/iso2709.c @@ -0,0 +1,178 @@ +/* + gw-res.c: Iso2709 record management + + Europagate, 1994-1995. + + $Log: iso2709.c,v $ + Revision 1.1.1.1 1995/02/09 17:27:11 adam + Initial version of email gateway under CVS control. + + */ + +#include +#include +#include +#include +#include + +#include + +static int atoin (const char *buf, int n) +{ + int val = 0; + while (--n >= 0) + { + if (isdigit(*buf)) + val = val*10 + (*buf - '0'); + buf++; + } + return val; +} + +static void strncpyx (char *d, const char *s, int n) +{ + while (--n >= 0 && *s) + if (*s != ISO2709_IDFS) + *d++ = *s++; + else + { + *d++ = ' '; + s++; + } + *d = '\0'; +#if 0 + strncpy (d, s, n); + d[n] = '\0'; +#endif +} + +char *iso2709_read (FILE *inf) +{ + char length_str[5]; + int size; + char *buf; + + if (fread (length_str, 1, 5, inf) != 5) + return NULL; + size = atoin (length_str, 5); + if (size <= 6) + return NULL; + if (!(buf = malloc (size+1))) + return NULL; + if (fread (buf+5, 1, size-5, inf) != (size-5)) + { + free (buf); + return NULL; + } + memcpy (buf, length_str, 5); + buf[size] = '\0'; + return buf; +} + +Iso2709Rec iso2709_cvt (const char *buf) +{ + struct iso2709_dir **dpp, *dp; + int pos = 24; + Iso2709Rec p; + + if (!(p = malloc (sizeof(*p)))) + return NULL; + + p->record_length = atoin (buf, 5); + strncpyx (p->record_status, buf+5, 1); + strncpyx (p->implementation_codes, buf+6, 4); + p->indicator_length = atoin (buf+10, 1); + p->identifier_length = atoin (buf+11, 1); + p->base_address = atoin (buf+12, 4); + strncpyx (p->user_systems, buf+17, 3); + + p->length_data_entry = atoin (buf+20, 1); + p->length_starting = atoin (buf+21, 1); + p->length_implementation = atoin (buf+22, 1); + strncpyx (p->future_use, buf+23, 1); + + dpp = &p->directory; + + *dpp = NULL; + while (buf[pos] != ISO2709_FS) + { + *dpp = malloc (sizeof(**dpp)); + (*dpp)->next = NULL; + strncpyx ((*dpp)->tag, buf+pos, 3); + pos += 3; + (*dpp)->length = atoin (buf+pos, p->length_data_entry); + pos += p->length_data_entry; + (*dpp)->offset = atoin (buf+pos, p->length_starting); + pos += p->length_starting + p->length_implementation; + + dpp = &(*dpp)->next; + } + pos++; +#if 0 + fprintf (stderr, "indicator_len=%d, identifier_len=%d\n", + p->indicator_length, p->identifier_length); +#endif + for (dp = p->directory; dp; dp = dp->next) + { + int tag00; + struct iso2709_field **fpp; + int dpos = pos+dp->offset; + char *save_indicator = NULL; + + fpp = &dp->fields; + + *fpp = malloc (sizeof(**fpp)); + (*fpp)->next = NULL; + if (p->indicator_length && memcmp (dp->tag, "00", 2)) + { + (*fpp)->indicator = malloc (p->indicator_length+1); + strncpyx ((*fpp)->indicator, buf+dpos, p->indicator_length); + dpos += p->indicator_length; + } + else + (*fpp)->indicator = NULL; + + if (memcmp (dp->tag, "00", 2)) + tag00 = 0; + else + tag00 = 1; + fprintf (stderr, "%s", dp->tag); + while (1) + { + int dpos_n; + if (p->identifier_length && !tag00) + { + (*fpp)->identifier = malloc (p->identifier_length+1); + strncpyx ((*fpp)->identifier, buf+dpos+1, + p->identifier_length-1); + dpos += p->identifier_length; + } + else + (*fpp)->identifier = NULL; + + dpos_n = dpos; + while (buf[dpos_n] != ISO2709_FS && buf[dpos_n] != ISO2709_IDFS) + dpos_n++; + + (*fpp)->data = malloc (dpos_n - dpos + 1); + strncpyx ((*fpp)->data, buf+dpos, dpos_n - dpos); + dpos = dpos_n; + + if (!save_indicator && (*fpp)->indicator) + fprintf (stderr, " %s", (*fpp)->indicator); + if ((*fpp)->identifier) + fprintf (stderr, " *%s", (*fpp)->identifier); + fprintf (stderr, " %s", (*fpp)->data); + if (buf[dpos] == ISO2709_FS) + break; + + save_indicator = (*fpp)->indicator; + fpp = &(*fpp)->next; + *fpp = malloc (sizeof(**fpp)); + (*fpp)->next = NULL; + (*fpp)->indicator = save_indicator; + } + fprintf (stderr, "\n"); + } + return p; +} diff --git a/util/iso2709dump.c b/util/iso2709dump.c new file mode 100644 index 0000000..d10db97 --- /dev/null +++ b/util/iso2709dump.c @@ -0,0 +1,28 @@ +/* + gw-res.c: Iso2709 record management + + Europagate, 1994-1995. + + $Log: iso2709dump.c,v $ + Revision 1.1.1.1 1995/02/09 17:27:11 adam + Initial version of email gateway under CVS control. + + */ + +#include +#include + +#include + +int main (int argc, char **argv) +{ + char *buf; + Iso2709Rec rec; + + while ((buf = iso2709_read (stdin))) + { + rec = iso2709_cvt (buf); + free (buf); + } + return 0; +} -- 1.7.10.4