--- /dev/null
+# 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.old >Makefile; \
+ rm Makefile.old); done
+
+usedepend1:
+ for i in $(SUBDIR); do (cd $$i; \
+ mv Makefile Makefile.tmp; \
+ sed 's/^if/#if/' <Makefile.tmp|sed 's/^include/#include/'| \
+ sed 's/^endif/#endif/' | \
+ sed 's/^depend: depend2/depend: depend1/g' >Makefile; \
+ rm Makefile.tmp); done
+
+usedepend2:
+ for i in $(SUBDIR); do (cd $$i; \
+ mv Makefile Makefile.tmp; \
+ sed '/^#Depend/q' <Makefile.tmp| \
+ sed 's/^#if/if/' |sed 's/^#include/include/'| \
+ sed 's/^#endif/endif/' | \
+ sed 's/^depend: depend1/depend: depend2/g' >Makefile; \
+ rm Makefile.tmp); done
+
+wc:
+ wc `find . -name '*.[ch]'`
+
--- /dev/null
+/*
+ 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:
+ <appname> <session> <date> <level> <type> <parameter>
+
+ Assuming that a 'token' is separated by one or more blanks we have:
+
+ <appname> one token
+ <session> one token
+ <date> five tokens (Tue Dec 6 11:34:21 1994)
+ <level> one token
+ <type> one token
+
+ <parameter> zero or more tokens.
+ */
+#endif
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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);
--- /dev/null
+/*
+ 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 <iso2709.h>
+
+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
--- /dev/null
+#$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
--- /dev/null
+# 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.tmp >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
--- /dev/null
+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
+
--- /dev/null
+# $Id: adam.res,v 1.1.1.1 1995/02/09 17:27:12 adam Exp $
+a: 3
+c: 45
--- /dev/null
+# 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 <return> in a dialog box to <activate> 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 <Key>F1: string(0x01) string("1")\n\ <Key>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\
+<KeyPress>Return: ArmAndActivate()\n\
+<KeyPress>KP_Enter: ArmAndActivate()\n\
+Ctrl<KeyPress>m: ArmAndActivate()\n
+Emacs*XmTextField.translations: #override\n\
+ !<Key>osfBackSpace: delete-previous-character()\n\
+ !<Key>osfDelete: delete-previous-character()\n\ !Ctrl<Key>h:
+ delete-previous-character()\n\ !Ctrl<Key>d: delete-next-character()\n\
+ !Meta<Key>osfDelete: delete-previous-word()\n\
+ !Meta<Key>osfBackSpace: delete-previous-word()\n\
+ !Meta<Key>d: delete-next-word()\n\ !Ctrl<Key>k: delete-to-end-of-line()\n\
+ !Ctrl<Key>g: process-cancel()\n\ !Ctrl<Key>b: backward-character()\n\
+ !<Key>osfLeft: backward-character()\n\ !Ctrl<Key>f: forward-character()\n\
+ !<Key>osfRight: forward-character()\n\ !Meta<Key>b: backward-word()\n\
+ !Meta<Key>Left: backward-word()\n\ !Meta<Key>osfLeft: backward-word()\n\
+ !Meta<Key>f: forward-word()\n\ |Meta<Key>Right: forward-word()\n\
+ !Meta<Key>osfRight: forward-word()\n\ !Ctrl<Key>e: end-of-line()\n\
+ !Ctrl<Key>a: beginning-of-line()\n\ !Ctrl<Key>w: cut-clipboard()\n\
+ !Meta<Key>w: copy-clipboard()\n\ <Btn2Up>: copy-primary()\n
+Emacs*dialog*XmPushButton.translations: #override\n\ <Btn1Down>: Arm()\n\
+ <Btn1Down>,<Btn1Up>: Activate()\ Disarm()\n\ <Btn1Down>(2+): MultiArm()\n\
+ <Btn1Up>(2+): MultiActivate()\n\ <Btn1Up>: Activate()\ Disarm()\n\
+ <Key>osfSelect: ArmAndActivate()\n\ <Key>osfActivate: ArmAndActivate()\n\
+ <Key>osfHelp: Help()\n\ ~Shift ~Meta ~Alt <Key>Return: ArmAndActivate()\n\
+ <EnterWindow>: Enter()\n\ <LeaveWindow>: 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
--- /dev/null
+# 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
--- /dev/null
+/*
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <gw-log.h>
+
+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);
+}
--- /dev/null
+/*
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <gw-log.h>
+
+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;
+}
--- /dev/null
+/*
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <gw-log.h>
+#include <gw-res.h>
+
+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], "<unknown>");
+ 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 <file> merge\n"
+ "g <name> get\n"
+ "p <name> <value> <file> put\n"
+ "s [<file>] show\n"
+ "c <file> 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);
+}
--- /dev/null
+/*
+ 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+
+#if HAVE_FLOCK
+#include <sys/file.h>
+#else
+#include <sys/types.h>
+#endif
+
+#include <gw-log.h>
+#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; j<left; j++)
+ fputc (rl->value[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;
+}
+
+
+
--- /dev/null
+/*
+ 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 <gw-res.h>
+
+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;
+};
--- /dev/null
+# 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.tmp >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
--- /dev/null
+/*
+ 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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <iso2709p.h>
+
+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;
+}
--- /dev/null
+/*
+ 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 <stdio.h>
+#include <stdlib.h>
+
+#include <iso2709.h>
+
+int main (int argc, char **argv)
+{
+ char *buf;
+ Iso2709Rec rec;
+
+ while ((buf = iso2709_read (stdin)))
+ {
+ rec = iso2709_cvt (buf);
+ free (buf);
+ }
+ return 0;
+}