diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000000000000000000000000000000000000..e1791c5c6d1712aee1c214c509388a9a94c50df2
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,382 @@
+Tue Mar  5 17:13:25 1991  Per Cederqvist  (ceder at lave)
+
+	* Depend.make: Bytt -MM mot -M, eftersom vi har includefiler inom
+	  <> som {ndrar p} sig.
+
+Thu Feb 14 03:39:16 1991  Linus Tolke  (linus at laila)
+
+	* include/kom-types.h: Lagt till EMPTY_CONF_NO_LIST_i och
+	  EMPTY_CONF_NO_LIST.
+
+Sat Dec 15 20:46:41 1990  Per Cederqvist  (ceder at laila)
+
+	* Depend.make: Jag bytte @\{63\} mot @@@* som {r mer portabelt.
+
+Tue Sep 18 20:46:42 1990  Per Cederqvist  (ceder at lave)
+
+	* get_time(): nytt format. Se services.h.
+
+Thu Sep 13 21:32:41 1990  Per Cederqvist  (ceder at lave)
+
+	* Ny port: 4894. Jag vill kunna k|ra nya ramkomd och gamla ramkomd
+	  p} lave samtidigt...
+
+Tue Aug 28 13:53:36 1990  Per Cederqvist  (ceder at lave)
+
+	* Datafilerna heter nu ramkomd-data-2 och ramkomd-backup-2. De
+	  anv{nds av den nya servern och inneh}ller de nya formaten p}
+	  tider och textstatusar.
+
+	  De gamla filerna ramkomd-data och ramkomd-backup finns
+	  fortfarande kvar och anv{nds av den gamla servern. Personer som
+	  skapas i den kommer inte att finnas i den nya servern...
+
+Sun Aug 26 16:40:58 1990  Per Cederqvist  (ceder at lage)
+
+	* En klient i elisp har p}b|rjats. Den ligger under
+	  2kom/elisp-client/.
+
+	* [ndringar p}g}r i servern. Just nu g}r den inte att k|ra. Jag
+	  byter externt format p} Text_stat och time_t. I forts{ttningen
+	  blir det en struct tm som |verf|rs.
+
+Tue Aug 21 19:27:07 1990  Per Cederqvist  (ceder at lave)
+
+	* get_text() tar nu tv} nya parametrar som anger f|rsta och sista
+	  tecken i texten som man h{mtar. (Normalt torde det l|na sig att
+	  h{mta hela texten p} en g}ng. Det {r nog bara om man k|r |ver
+	  atlantlinan som det kanske blir segt.)
+
+Sat Aug 11 00:31:32 1990  Per Cederqvist  (ceder at lave)
+
+	* Nya funktioner: get_membership(), get_created_texts()
+	  och get_members().
+
+	* Namnbyte: query_unread() heter nu query_read_texts(). S}
+	  sm}ningom kommer jag att skriva en annan query_unread() som
+	  returnerar antalet ol{sta brev en person har.
+
+	* Till slut s} lyckades jag f} allt genom kompilatorn. Det gick }t
+	  en del tid efter alla odokumenterade omorganisationer... Nu {r 
+	  bara fr}gan hur mycket som fungerar i verkligheten...
+
+	* kom-types.c {r flyttad till server/ resp. isc-client/. Det gick inte
+	  att ha det i samma fil l{ngre.
+
+Thu Aug  9 05:20:20 1990  Thomas Bellman  (bellman at laila)
+
+	* Makefilen {nnu mer f|rb{ttrad.  Make depend mycket snyggare,
+	  anv{nder ${MAKE} i st f make direkt.
+
+	* Makefilen i toppdirret f|rb{ttrad, likaledes ig}r.  Make clean i
+	  toppdirret g}r nu ner och g|r make clean i underdirren ocks}.
+	  Diverse andra f|rb{ttringar ocks} gjorda.
+
+	* Lite omorganisationer gjorda ig}r.  En del grejer nedflyttade i
+	  directories f|r att f} ett renare toppdir.
+
+Fri Jul 27 01:21:45 1990  Per Cederqvist  (ceder at lage)
+
+	* Nu {r funktionerna i services.h dokumenterade, i alla fall lite
+	  grann. Kommentarerna finns i server/services.c. De borde v{l
+	  kopieras till services.h ocks}. Vi f}r v{l se om jag hinner det
+	  n}gon g}ng p} denna sida ny}r...
+
+Wed Jul 25 14:35:52 1990  Per Cederqvist  (ceder at lave)
+
+	* F|ljande filer installerade:
+
+		   /usr/local/etc/ramkomd
+		   /usr/local/etc/updateLysKOM
+		   /usr/local/bin/kompost
+		   /usr/local/bin/komlisten
+
+	* ramkomd sparar numera alla texter, m|ten och personer var 15:e
+	  minut. Det {r programmet /usr/local/etc/updateLysKOM som kopplar
+	  upp sig och skickar anropet kom_sync() som vem som helst kan
+	  g|ra. (Man beh|ver inte ens vara inloggad). updateLysKOM startas
+	  fr}n min crontab p} lave. stdout skickas till 2kom/stdout,
+	  stderr till 2kom/stderr. Alla logg-meddelanden kommer till
+	  stderr.
+
+	  Om ramkomd inte {r ig}ng f|rs|ker updateLysKOM starta om
+	  ramkomd. 
+
+	  Data lagras i filerna /usr/local/src/2kom/db/ramkomd-data och
+	  ramkomd-backup.
+
+Tue Jul 24 13:37:03 1990  Per Cederqvist  (ceder at lave)
+
+	* komlisten - ett program f|r att lyssna p} de asynkrona
+	  meddelanden som skickas. 'komlisten lave 5 pw' eller 'komlisten
+	  lave'. Den f|rsta varianten loggar in som person nummer 5 med
+	  l|sen 'pw'. P} s} s{tt f}r den se alla texter som skapas i m|ten
+	  d{r p 5 {r medlem.
+
+Mon Jul 23 04:01:55 1990  Per Cederqvist  (ceder at lave)
+
+	* kompost - ett program f|r att kolla om man har n}gon post i kom.
+	  'kompost lave 5' ser efter hur m}nga ol{sta brev person 5 har p}
+	  det kom som k|r p} lave.
+
+Sun Jul 22 02:17:57 1990  Per Cederqvist  (ceder at lave)
+
+	* I kom/isc-client/ ligger k{llkoden till klient-sidan. Synopsis:
+
+	  #define CLIENT
+	  #include "/usr/local/2kom/services.h"
+
+	  cc main.o ...  -L/usr/local/2kom -lyskom
+
+	* isc b|rjar bli klart (tror jag). Jag har i alla fall lyckats
+	  koppla upp en micro-klient mot servern och skapat en person och
+	  ett m|tet, och l}tit personen g} med i m|tet.
+
+Fri Jul 20 01:00:00 1990  Thomas Bellman  (bellman at laila)
+
+	* Backup tagen av hela LysKOM p} Inge Wallins optiska disk.
+	  F|rhoppningsvis {r det helt i on|dan...
+
+Tue Jul 17 15:19:29 1990  Per Cederqvist  (ceder at lave)
+
+	* kom-types.h: Sista (?) {ndringen i Person-structen:
+	  confs och no_of_confs har slagits ihop till
+	  Membership_list conferences.
+
+	  Nu har vi inga pekare i Person-structen. Alla 'array/listor'
+	  ligger inbakade i en list-typ. Det {r bara f|rvirrande att ha
+	  det p} olika s{tt. Jag har just suttit i ett halvt dygn och
+	  letat felet innan jag kom p} att confs pekade p} en variabel
+	  lista...
+
+Sun Jul 15 04:43:20 1990  Thomas Bellman  (bellman at laila)
+
+	* Eftersom serverskrivarna (l{s Ceder) hade en del underliga
+	  |nskem}l om att f} anv{nda konstiga funktioner som smalloc och
+	  annat f|r minneshantering {ven i str{ngfunktionerna, tvingar jag
+	  dem nu att anropa funktionen s_set_storage_management() f|r att
+	  ange vilka funktioner som ska anv{ndas i st{llet f|r de vanliga.
+	  Tyv{rr m}ste jag sj{lv g|ra det ocks}, men det {r betydligt
+	  snyggare {n det s{tt som det l|stes p} innan.
+
+Fri Jul 13 13:12:23 1990  Per Cederqvist  (ceder at laila)
+
+	* kom-types.h: Jag lade till ett antal bitar i Personal_flags och
+	  Priv_bits f|r framtida bruk.
+
+	* kom-types.h: Person-structen: f{ltet 'texts' har bytt namn och
+	  typ till 'Text_list created_texts'.
+
+	* OMORGANISATION!!!  Saker som l}g i kom-types.h som ska se
+	  olika ut f|r server och klient, {r flyttade fr}n
+	  client/client-types.h resp. server/server-types.h tillbaka till
+	  kom-types.h. client/client-types.h och server/server-types.h {r
+	  borttagna.
+
+Sat Jul  7 07:44:45 1990  Per Cederqvist  (ceder at lave)
+
+	* Det gick inte alls bra. Tydligen m}ste filerna som man cat:ar
+	  ihop utg} fr}n samma directory... :-(
+
+	* TAGS-filerna: I varje directory g|rs en TAGS-fil p} de filer som
+	  finns d{r. I kom:/ g|rs en total TAGS-fil genom att cat:a ihop
+	  dom. Jag {r inte helt s{ker p} att det {r s} smart, men vi f}r
+	  se hur det g}r.
+
+Thu Jul  5 13:13:41 1990  Per Cederqvist  (ceder at laila)
+
+	* services.h: Ny funktion: delete_text(Text_no text_no);
+
+Tue Jul  3 01:12:50 1990  Thomas Bellman  (bellman at laila)
+
+	* services.h:  Ny maskbit f|r get_person_stat(), GETP_READ_TEXTS,
+	  som inneb{r att man vill ha listorna av l{sta texter tillsammans
+	  med medlemskapslistan.  Dessa ska inte skickas med om man inte
+	  explicit ber om det; det finns query_unread().
+
+Wed Jun 27 05:13:01 1990  Thomas Bellman  (bellman at lave)
+
+	* services.h:  Alla funktionsdeklarationer {r omg{rdade av makrot
+	  KOM_ som ser till att funktionerna heter 'kom_foo' p}
+	  klientsidan och 'foo' p} serversidan.  Detta {r beroende p} om
+	  makrona CLIENT respektive SERVER {r definierade.  Detta f|r att
+	  vi ska slippa ha tv} services.h att underh}lla.
+
+Wed Jun  6 00:14:35 1990  Per Cederqvist  (ceder at laila)
+
+	* services.h: [ndrade 'String' till 'const String' i alla 
+	  funktionshuvuden.
+
+	* glue: Directory som inneh}ller klister f|r att klistra ihop en
+	  klient med servern.
+
+	* services.h: Alla funktioner som f|rut hette 'foo' heter nu
+	  'kom_foo'. Anledningen {r att man vill kunna l{nka ihop klienten
+	  och servern och f} ett singeluserkom innan Peter {r klar med
+	  sitt paket... ;-)
+
+Tue May 29 16:17:53 1990  Per Cederqvist  (ceder at lave)
+
+	* services.h {r nu splittrad. server/services.h inneh}ller
+	  funktionerna som de ser ut p} server-sidan, services.h som de
+	  ser ut f|r klienten.
+
+Mon May 28 23:02:24 1990  Thomas Bellman  (bellman at laila)
+
+	* Summarize-Headers:  Shell-script f|r att sammanfatta inneh}llet
+	  i en .h-fil.
+
+	* (Egentligen den 26:e)  FileList inf|rd!  En fil som inneh}ller
+	  beskrivningar p} alla filer i ett dir.  Shell-scriptet
+	  List-Files f|r att lista vilka filer som inte {r beskrivna.
+
+	* s-string.[ch]: Fler funktioner: s_skip_blanks(), s_strtol().
+
+Sat May 26 15:02:48 1990  Per Cederqvist  (ceder at laila)
+
+	* Mailinglist: Ny fil som inneh}ller email-adresser p} alla de som
+	  svarat p} mitt inl{gg i Linus-kom om mailinglistan. Det vore
+	  fint om n}gon skickar ett mail till dom n{r LysKom {r ig}ng...
+	  Tills vidare tar jag p} mig ansvaret f|r utskicken.
+
+Sat May 26 01:36:02 1990  Thomas Bellman  (bellman at laila)
+
+	* s-string.[hc]:  Nya funktioner s_strhead() och s_usr_strhead().
+	  Testar om en str{ng {r en b|rjan p} en annan.
+
+Fri May 25 02:37:55 1990  Per Cederqvist  (ceder at lave)
+
+	* s-string.h: Nytt macro s_empty(str) som returnerar TRUE omm str
+	  {r tom.
+
+	* kom-types.h: Tog bort f{ltet 'Conf_type type' ur
+	  Membership-structen. Det visar sig att det {r b{ttre att cacha
+	  Conf_type tillsammans med namnet.
+
+Tue May 15 17:49:47 1990  Per Cederqvist  (ceder at laila)
+
+	* kom-types.h: Info_type och Info_datum: Ny typ: sent_at.
+	  S} att man vet n{r en text {r skickad n{r den skickas i efterhand.
+
+Mon May 14 08:59:14 1990  Thomas Bellman  (bellman at laila)
+
+	* Biblioteket kom:/ansi-include skapat.  Detta bibliotek
+	  genoms|kes av cpp enligt Makefile (Template).  I biblioteket
+	  finns {n s} l{nge stdio.h, malloc.h och string.h.  Strunta i
+	  filen kom:/ansi.h.  NU ska vi v{l {ntligen slippa ifr}n alla
+	  problem vi haft med include-filer och odeklarerade funktioner.
+	  Fyll g{rna p} med fler generella .h-filer.
+
+Sun May 13 23:12:23 1990  Per Cederqvist  (ceder at lage)
+
+	* kom-errno.[hc]: s} heter den nu.
+
+Sun May 13 23:05:23 1990  Thomas Bellman  (bellman at laila)
+
+	* s-string.[ch]:  Skapad.  V}r egen str{ngtyp (String) samt
+	  funktioner f|r att manipulera dessa.  
+
+Thu May 10 16:27:35 1990  Per Cederqvist  (ceder at lage)
+
+	* config.h:  DEFENSIVE_CHECKS - definierad om vi {r defensiva.
+
+Wed May  9 17:34:31 1990  Linus Tolke  (linus at laila)
+
+	* Person-strukten anv{nder String och Mark_list ist{llet f|r
+	  char * och Mark
+
+	* Jag justerade ordningen f|r filerna som argument till etags.
+	  Jag vill n{mligen n} typen Person p} mindre {n 3 steg!
+
+Tue May  8 19:36:44 1990  Per Cederqvist  (ceder at lage)
+
+	* bool heter numera Bool.
+
+	* Ny typ: Success. Att anv{ndas av alla funktioner som returnerar 
+	  OK eller FAILURE.
+
+Fri May  4 01:25:23 1990  Per Cederqvist  (ceder at lage)
+
+	* services.h: create_conf tar nu {ven Conf_type type som argument.
+	  P} s} vis kan ett hemligt m|te vara hemligt fr}n b|rjan.
+
+Thu May  3 00:56:35 1990  Per Cederqvist  (ceder at lage)
+
+	* kom-types.h: Nytt f{lt i Membership: Conf_type type
+
+	* jin_errno heter numera kom_errno.
+
+	* query_unread_mail heter numera query_unread och {r lite mer
+	  flexibel - man kan fr}ga hur mycket ol{sta en viss person har
+	  i ett visst m|te.
+
+Thu Apr 26 01:52:51 1990  Thomas Bellman  (bellman at lage)
+
+	* P{rm f|r listningar inskaffad.  Gamla listningar av 2kom/ och
+	  2kom/client/ finns insatta.  N{r ni tar ut listningar, s{tt in
+	  dem i p{rmen.  Den ligger i hyllan ovanf|r LLL.  En gul p{rm
+	  m{rkt "LysKOM".  Observera att listningarna som sitter i den
+	  just nu {r inaktuella, p g a....
+
+	* OMORGANISATION!!!  Saker som l}g i kom-types.h som ska se
+	  olika ut f|r server och klient, {r flyttade till
+	  client/client-types.h resp. server/server-types.h.  Samtidigt
+	  togs types.h bort.
+
+	* Listor i Person- och Conference-structarna {r nu egna typer.
+
+	* 'get_person_stat()' och 'get_conf_stat()' tar numera en pekare
+	  till en area d{r resultatet ska l{ggas.  Dessutom skickar man
+	  med en mask som talar om hur mycket information man vill ha.
+
+Wed Apr 25 02:38:32 1990  Thomas Bellman  (bellman at laila)
+
+	* Lade till 'footnote to' och 'footnote in' i misc_info.
+
+	* Skapade 'kom-types.c' som typiskt inneh}ller konstanter och
+	  annat som man tycker borde ligga i en .h-fil, men som inte kan
+	  g|ra det om filen inkluderas i mer {n en k{llkodsfil.
+
+Wed Apr 25 00:49:01 1990  Per Cederqvist  (ceder at laila)
+
+	* services.h: add_member tar numera tv} parametrar f|r att ange
+	  prioritet p} m|tet. add_member anv{nds {ven f|r att {ndra
+	  prioritet p} ett m|te man redan {r med i.
+
+Sat Apr 21 13:52:12 1990  Per Cederqvist  (ceder at lave)
+
+	* Fixade en Makefile som generarar en TAGS-fil som inneh}ller allt
+	  till servern.
+
+	* kom-types.h: Nya privilegiebitar: admin och statistic.
+
+Fri Apr 20 14:09:26 1990  Per Cederqvist  (ceder at lage)
+
+	* kom-types.h: Ny typ Conf_nos.
+
+	* services.h: Ny definition av lookup_name. Nu returneras en lista
+	  med alla konferenser som matchar argumentet.
+
+	* P} beg{ran av Bellman {r nu jin_errno en enum.
+
+Thu Apr 19 02:47:05 1990  Per Cederqvist  (ceder at lave)
+
+	* kom-types.h: Conf_type: nytt f{lt "no_stat".
+		       Sec_bits: ny typ som anger vad en person vill h}lla
+				 hemligt.
+		       Person: nytt f{lt "flags".
+
+Wed Apr 18 00:08:22 1990  Per Cederqvist  (ceder at lage)
+
+	* services.h: get_marks har nu ingen parameter. Man kan bara titta
+		      p} sina egna markeringar.
+
+	* kom-types.h inkluderar nu {ven <stddef.h>
+
+	* Skapade jin_errno.h.
+
+	* services.h: alla funktioner som returnerade en struct
+		      returnerar nu en pekare till motsvarande struct. 
+
+	* Ny funktion i services: query_unread_mail. (Se m 230)
+
diff --git a/FileList b/FileList
new file mode 100644
index 0000000000000000000000000000000000000000..55815ac0e3a0363bb4cd0ac8d93a7d71b21fc742
--- /dev/null
+++ b/FileList
@@ -0,0 +1,136 @@
+(Hey, Emacs, this is a -*- Indented-text -*- file!)
+
+*  ansi-include/
+   Directory containing ANSI-fied header files for the standard
+   libraries.
+
+
+*  ChangeLog
+   Log file where the progressing work and changes are sporadically
+   documented.  You are encouraged to add an entry in this file
+   whenever you change something in this directory.
+
+
+*  client/
+   Directory containing a TTY-based client for LysKOM, very similar to
+   the original KOM program from QZ.
+
+
+*  config.h
+   Configuration parameters for compiling.  Contains among other
+   things all the stupid limits you really want to be without, all the
+   smart limits that has to be there to make it impossible to crash
+   the server, and lots of constants and configuration options.
+
+
+*  debug.h
+   Some #defines for debugging purposes.
+
+
+*  doc/
+   Documentation of LysKOM; both internal and external.  Also some
+   random thoughts members of the development team wanted to write
+   down during development.
+
+
+*  FileList
+   This file, describing all the files.
+
+
+*  kom-errno.c
+   Defines the variable 'kom_errno' and the function 'kom_perror()'.
+   Used for error handling in LysKOM.
+
+
+*  kom-errno.h
+   Defines the type 'Kom_err' and declares the variable 'kom_errno'.
+   The server sets the value of 'kom_errno' when an error occurs.
+   The function 'kom_perror()' is declared.
+
+
+*  kom-types.h
+   Declares the types used by LysKOM.  Here are the types that are
+   common to both the server and the client.  Types that look
+   different to the server and the client, are found in
+   'server/server-types.h' and 'client/client-types.h' respectively.
+
+
+*  ldb/
+   Directory containing the low-level database routines for the LysKOM
+   server.  'ldb' stands for Lyskom DataBase.
+
+
+*  List-Files
+   Shell script to list the files in this directory not documented in
+   the file 'FileList' (the one you are reading now).
+
+
+*  Mailinglist
+   List of mail addresses of people who want to be informed of the
+   progress of LysKOM.
+
+
+*  Makefile
+   Exactly what the name says.
+
+
+*  misc-types.h
+   Miscellaneous types and constants that are useful in many places in
+   LysKOM, but are not very LysKOM-specific.
+
+
+*  s-collat-tables.c
+   Collating tables used for the 's_usr_strcmp()' and
+   's_usr_strhead()' functions in 's-string.h'
+
+
+*  s-collat-tables.h
+   Header file for 's-collat-tables.c'
+
+
+*  s-string.c
+   Routines for manipulating objects of type String as defined in
+   's-string.h'
+
+
+*  s-string.h
+   Header file for 's-string.c'
+   Definies our own string type 'String', and declares the functions
+   in 's-string.c'
+
+
+*  server/
+   Directory containing the LysKOM server, except for the low-level
+   database routines, which for historical reasons are in the separate
+   directory 'ldb/'.
+
+
+*  services.h
+   Declares all the services available from the LysKOM server.
+
+
+*  Summarize-Headers
+   Since we write our .h files with documentation in line, they
+   tend to get rather long, and it gets somewhat difficult to get
+   a quick overview of what functions are declared in the file.
+   This script cuts out all the "unnecessary" information: all
+   comments and all preprocessor lines (starting with #).
+
+
+*  TAGS
+   Tags table for use with Emacs.
+
+
+*  Template
+   Template for automatically generating 'Makefile'.  'Makefile' is
+   updated with the command 'make depend'.  This should be given
+   whenever a change to 'Template' is done, or any new files are
+   added, or any dependecies are changed.  Dependencies for normal C
+   files are generated automatically by this.
+   If 'Makefile' should become garbled, copy 'Template' to 'Makefile'
+   and do a 'make depend'.
+
+
+*  test-services/
+   Directory containing programs to test parts of the server.  Used by
+   ceder, and should not be distributed.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ab919c7b51111390a9a004422ceb557b403440cc
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,71 @@
+#  Makefile for LysKOM
+#
+###############################################################################
+#
+#  SPECIAL CONSIDERATIONS:
+#
+#  -  Requires GNU make.
+#  -  CC, OPTIMIZE-FLAGS and other make variables are passed down 
+#     in the environment.
+#  -  C compiler must be ANSI conformant.
+#
+###############################################################################
+#
+#  SPECIAL TARGETS:
+###############################################################################
+
+# Directories that you might want to override via the environment.
+
+ifndef TOPDIR
+TOPDIR := $(shell pwd)
+endif
+
+ifndef SCRIPTDIR
+SCRIPTDIR = $(TOPDIR)/scripts
+endif
+
+include $(SCRIPTDIR)/import.make
+
+
+# All directories that make should traverse to when doing clean etc.
+
+SUBDIRS = doc include junk lib scripts src
+
+all:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making all in directory $$i; \
+		(cd $$i; $(MAKE) all)	\
+	done
+
+
+install:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making install in directory $$i; \
+		(cd $$i; $(MAKE) install)	\
+	done
+
+depend:
+	(cd src/include; make install)
+	(cd src/libraries; make install-headers)
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making depend in directory $$i; \
+		(cd $$i; $(MAKE) depend);	\
+	done
+
+
+clean:
+	rm -vf *~ core
+	for i in $(SUBDIRS); \
+	do \
+	   echo making clean in directory $$i; \
+	   (cd $$i; $(MAKE) clean) \
+	done
+		
+war:
+	@echo "Thou shalt not make war.  Makest love instead!"
+
+love:
+	@clear; cat /usr/local/lib/makelove
diff --git a/doc/man/man3/isc3.x b/doc/man/man3/isc3.x
new file mode 100644
index 0000000000000000000000000000000000000000..aec549f6ec54f74a3c7d5eeef597cf75afdc78bd
--- /dev/null
+++ b/doc/man/man3/isc3.x
@@ -0,0 +1,186 @@
+.\" $Copyright:	$
+.\" Copyright (c) 1991 Lysator Computer Club, Linkoping University, Sweden
+.\" All rights reserved
+...
+.V= $Header: /home/ceder/convert-lyskomd/cvsroot/lyskom-server/doc/man/man3/Attic/isc3.x,v 0.1 1991/08/12 17:39:55 ceder Exp $
+.TH ISC 3X "\*(V)" "LUNATIX"
+.SH NAME
+isc_initialize, isc_shutdown, isc_listen, isc_unlisten,
+isc_opentcp, isc_openfile, isc_openfd, isc_close,
+isc_sessions, isc_getnextevent, isc_dispose, 
+isc_flush, isc_write, isc_putc, isc_printf,
+isc_allocmsg, isc_reallocmsg, isc_freemsg, isc_mkstrmsg,
+isc_setmaxmsgsize, isc_setallocfn, isc_setlogfn, isc_setabortfn
+.SH FUNCTIONS
+.nf
+.B IscMaster *
+.B "    isc_initialize (IscConfig *cfg)"
+.PP
+.B void
+.B "    isc_shutdown(IscMaster *mcb)"
+.PP
+.B int
+.B "    isc_listen(IscMaster *mcb, int port);"
+.PP
+.B void
+.B "    isc_unlisten(IscMaster *mcb, int port);"
+.PP
+.B "IscSession *"
+.B "    isc_opentcp(IscMaster *mcb, const char *host, int port)"
+.PP
+.B "IscSession *"
+.B "    isc_openfile(IscMaster *mcb, const char *path, int mode)"
+.PP
+.B "IscSession *"
+.B "    isc_openfd(IscMaster *mcb, int fd)"
+.PP
+.B "void"
+.B "    isc_close (IscSession *scb)"
+.PP
+.B "int"
+.B "    isc_sessions (IscMaster *mcb)"
+.PP
+.B "IscEvent *"
+.B "    isc_getnextevent (IscMaster *mcb, long timeout)"
+.PP
+.B "void"
+.B "    isc_dispose (IscEvent *ecb)"
+.PP
+.B "void"
+.B "    isc_flush (IscSession *scb)"
+.PP
+.B "int"
+.B "    isc_write (IscSession *scb, const void *buf, size_t len)"
+.PP
+.B "int"
+.B "    isc_printf (IscSession *scb, const char *format, ...)"
+.PP
+.B "int"
+.B "    isc_putc (int chr, IscSession *scb)"
+.PP
+.B "IscMessage *"
+.B "    isc_allocmsg(size_t size);"
+.PP
+.B "IscMessage *"
+.B "    isc_reallocmsg(IscMessage *msg, size_t size);"
+.PP
+.B "void"
+.B "    isc_freemsg(IscMessage *msg);"
+.PP
+.B "IscMessage *"
+.B "    isc_mkstrmsg(const char *str);"
+.PP
+.B "void"
+.B "    isc_setmaxmsgsize (IscMaster *mcb, size_t size)"
+.PP
+.B "void"
+.B "    isc_setlogfn (void (*logfnp)(const char *fmt, va_list AP))"
+.PP
+.B "void"
+.B "    isc_setallocfn (void * (*mallocfn)(size_t size),"
+.B "                    void * (*reallocfn)(void *buf, size_t size),"
+.B "                    void   (*freefn)(void *buf))"
+.PP
+.B "void"
+.B "    isc_setabortfn (void (*abortfn)(const char *msg))"
+.SH TYPES
+.nf
+.B typedef void IscConfig;
+.PP
+.B typedef enum 
+.B {
+.B "    ISC_EVENT_ERROR,"
+.B "    ISC_EVENT_TIMEOUT,"
+.B "    ISC_EVENT_LOGIN,"
+.B "    ISC_EVENT_LOGOUT,"
+.B "    ISC_EVENT_MESSAGE,"
+.B "} IscEventType;"
+.PP
+.B typedef enum
+.B {
+.B "  ISC_TYPE_UNKNOWN,"
+.B "  ISC_TYPE_TCP,"
+.B "  ISC_TYPE_FILE"
+.B "} IscSessionType;"
+.PP
+.B typedef struct isc_msg
+.B {
+.B "  int size;"
+.B "  int length;"
+.B "  char *buffer;"
+.B } IscMessage;
+.PP
+.B typedef struct isc_mcb
+.B {
+.B "  int port;"
+.B "  int fd;"
+.B "  int maxmsgsize;"
+.B "  int maxqueuedsize;"
+.B "  int maxdequeuelen;"
+.B "  struct isc_scb *sessions;"
+.B } IscMaster;
+.PP
+.B typedef struct isc_scb
+.B {
+.B "    struct isc_scb  * prev;"
+.B "    struct isc_scb  * next;"
+.B "    IscMaster       * mcb;"
+.B "    IscSessionType    type;"
+.B "    int               fd;
+.B "    IscMsgQueue     * rd_msg_q;"
+.B "    IscMsgQueue     * wr_msg_q;"
+.B "    char              sendbuf[2048];"
+.B "    int               sendindex;"
+.B "    union"
+.B "    {"
+.B "      struct"
+.B "      {"
+.B "        char  * hostname;"
+.B "        int     rport;"
+.B "        int     lport;"
+.B "      } tcp;"
+.B "      struct"
+.B "      {"
+.B "	    char * pathname;"
+.B "	    int    openmode;"
+.B "      } file;"
+.B "    } info;"
+.B "    int               kill_him;"
+.B "    time_t            logintime;"
+.B "    struct"
+.B "    {"
+.B "      struct"
+.B "      {"
+.B "        long bytes;"
+.B "        long packets;"
+.B "      } rx, tx;"
+.B "    } stats;"
+.B ""
+.B "    ISC_UDGTYPE  * udg;   /* Reserved for user defined usage */"
+.B "} IscSession;"
+.PP
+.B typedef struct isc_ecb
+.B {
+.B "  IscEventType    event;"
+.B "  IscSession    * session;"
+.B "  IscMessage    * msg;"
+.B } IscEvent;
+.SH DESCRIPTION
+These functions implement an interface to the TCP/IP streams facitiliy.
+The functions are obtained with the loader option
+.BR \-lisc .
+(More to come here...)
+.PP
+.SH DIAGNOSTICS
+(And here... :\-)
+.PP
+.SH BUGS
+Hehe... I'm sure they exists...
+.SH GUILTY
+Peter Eriksson <pen@lysator.liu.se> &
+Per Cederqvist <ceder@lysator.liu.se>
+
+
+ISC is Copyright (c) 1991 Lysator Computer Club, Linkoping University, Sweden,
+in cooperation with the International Syndicate of Computation.
+All rights reserved.
diff --git a/foo b/foo
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/scripts/Depend.make b/scripts/Depend.make
new file mode 100644
index 0000000000000000000000000000000000000000..7f21f9e84f1c20ca4dc1d13084df038596c18398
--- /dev/null
+++ b/scripts/Depend.make
@@ -0,0 +1,19 @@
+depend:
+	${SED} '/^# OBJECTS: @@@* #$$/q' Makefile	> temp-Makefile
+	echo '# This line is generated by "make depend"'>>temp-Makefile
+	echo -n 'OBJECTS = '				>>temp-Makefile
+	ls *.c | ${AWK} 'BEGIN	{	pos = 10;	}		\
+				{	sub(/\.c$$/, ".o");		\
+					pos += length($$0) + 1;		\
+					if (pos >= 75)			\
+					{	printf("\\\n\t");	\
+						pos = 9 + length($$0);	\
+					}				\
+					printf ("%s ", $$0);		\
+				 }'			>>temp-Makefile
+	echo						>>temp-Makefile
+	${SED} '/^# RULES: @@@* #$$/,/^# DEPENDENCIES: @@@* #$$/!d' \
+		Makefile				>>temp-Makefile
+	echo						>>temp-Makefile
+	gcc -M -DCLIENT ${INCLUDES}  *.c		>>temp-Makefile
+	mv temp-Makefile Makefile
diff --git a/scripts/List-Files b/scripts/List-Files
new file mode 100755
index 0000000000000000000000000000000000000000..292acbf6a0c160fe9e0371385776f653d8fad09f
--- /dev/null
+++ b/scripts/List-Files
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+#  Lists the differences between the file 'FileList' and what's 
+#  actually in the current directory.
+
+#  Change to the directory specified as first parameter.
+cd ${1-.}
+
+#  Get the names of some temporary files.
+FILE1=/tmp/LysKOM.$$.fl		# The files in 'FileList'
+FILE2=/tmp/LysKOM.$$.ls		# The files in this directory
+
+#  First find out what files are described in 'FileList'.
+egrep '^\*' FileList | sed 's/^\*  //' >$FILE1
+
+#  Find the files in this directory that we are interested in.
+#  Remove trailing *'s, since those are generated by 'ls -F'
+#  Files ending in .o and ~ are not interesting either.
+ls -F  | sed 's/\*$//' | egrep -v '\.o$|~$' | sort -f >$FILE2
+
+#  Then compare that list to the output from 'ls(1)'
+diff $FILE1 $FILE2
+
+#  Clean up
+rm $FILE1 $FILE2
diff --git a/scripts/Makefile b/scripts/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..b23b3f02449b28289324f4381e8b007d2f1bf017
--- /dev/null
+++ b/scripts/Makefile
@@ -0,0 +1,6 @@
+all:;
+depend:;
+install:;
+
+clean:
+	rm -vf *~ core
diff --git a/scripts/Parallell-depend.make b/scripts/Parallell-depend.make
new file mode 100644
index 0000000000000000000000000000000000000000..b3e9f6af9951da44cf66e6064ed14ca69ff12ae9
--- /dev/null
+++ b/scripts/Parallell-depend.make
@@ -0,0 +1,28 @@
+# temp-B-Makefile temp-C-Makefile \
+#		temp-D-Makefile temp-E-Makefile
+
+depend: temp-A-Makefile
+	rm -f dependencies
+	cat temp-?-Makefile				>dependencies
+	rm temp-?-Makefile temp-?-files
+	echo depend ready.
+
+temp-A-Makefile: c-indexes specials
+	-$(CC) -M ${TARGET} ${INCLUDES} `cat temp-A-files`     >temp-A-Makefile
+
+temp-B-Makefile: c-indexes specials
+	-$(CC) -M ${TARGET} ${INCLUDES} `cat temp-B-files`     >temp-B-Makefile
+
+temp-C-Makefile: c-indexes specials
+	-$(CC) -M ${TARGET} ${INCLUDES} `cat temp-C-files`     >temp-C-Makefile
+
+temp-D-Makefile: c-indexes specials
+	-$(CC) -M ${TARGET} ${INCLUDES} `cat temp-D-files`     >temp-D-Makefile
+
+temp-E-Makefile: c-indexes specials
+	-$(CC) -M ${TARGET} ${INCLUDES} `cat temp-E-files`     >temp-E-Makefile
+
+c-indexes: 
+	ls *.c|${AWK} '{ a[i++] = $$1; }				\
+	   END { for ( j = 0; j < i; j++ )				\
+		   print a[j] > sprintf("temp-%c-files", 65 + j % 5); }
diff --git a/scripts/RCS-depend.make b/scripts/RCS-depend.make
new file mode 100644
index 0000000000000000000000000000000000000000..328384275a588c9854cfca92d22e8fb617cf16bd
--- /dev/null
+++ b/scripts/RCS-depend.make
@@ -0,0 +1,27 @@
+depend: temp-A-Makefile temp-B-Makefile temp-C-Makefile temp-D-Makefile \
+		temp-E-Makefile
+	rcs -l dependencies
+	rm -f dependencies
+	cat temp-?-Makefile				>dependencies
+	rm temp-?-Makefile temp-?-files
+	echo " " | ci dependencies
+
+temp-A-Makefile: c-indexes
+	gcc -M ${TARGET} ${INCLUDES} `cat temp-A-files`	>temp-A-Makefile
+
+temp-B-Makefile: c-indexes
+	gcc -M ${TARGET} ${INCLUDES} `cat temp-B-files`	>temp-B-Makefile
+
+temp-C-Makefile: c-indexes
+	gcc -M ${TARGET} ${INCLUDES} `cat temp-C-files`	>temp-C-Makefile
+
+temp-D-Makefile: c-indexes
+	gcc -M ${TARGET} ${INCLUDES} `cat temp-D-files`	>temp-D-Makefile
+
+temp-E-Makefile: c-indexes
+	gcc -M ${TARGET} ${INCLUDES} `cat temp-E-files`	>temp-E-Makefile
+
+c-indexes: sources
+	echo ${SRCS}|tr " " \\012 |${AWK} '{ a[i++] = $$1; }				\
+	   END { for ( j = 0; j < i; j++ )				\
+		   print a[j] > sprintf("temp-%c-files", 65 + j % 5); }
diff --git a/scripts/Summarize-Headers b/scripts/Summarize-Headers
new file mode 100755
index 0000000000000000000000000000000000000000..ca5a05c320b46a2fbd01ae8b022d2d4fbe9d4269
--- /dev/null
+++ b/scripts/Summarize-Headers
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+#  Summarize a .h file
+
+#  Since we write our .h files with documentation in line, they
+#  tend to get rather long, and it gets somewhat difficult to get
+#  a quick overview of what functions are declared in the file.
+#  This script cuts out all the "unnecessary" information.
+
+AWK=gawk
+
+$AWK   '/^[ \t]*#[ \t]*define/ { print $0 ;
+				define = 1 ;
+				next ;
+			}
+	define != 0	{	if (substr($0, length(), 1) == "\\")
+				{
+					printf ("\n") ;
+					next ;
+				}
+				else  {
+					printf ("\n") ;
+					define = 0 ;
+					next ;
+				}
+			}
+	/^\/\*/,/\*\/$/	{	printf ("\n") ;
+				next ;
+			}
+	/\/\//		{	next ;				}
+	(define == 0) &&	\
+  	(comment == 0) 	{	print $0 ;			}
+	/\/\*/		{	comment = 1 ;			}
+	/\*\//		{	comment = 0 ;			}
+'  $1 |
+$AWK   'BEGIN		{	blank_lines = 0;		}
+	$1 == ""	{		if (blank_lines++ == 0)
+					print $0;
+			}
+	$1 != ""	{	print $0;
+				blank_lines = 0;
+			}
+'
diff --git a/scripts/import.make b/scripts/import.make
new file mode 100644
index 0000000000000000000000000000000000000000..2e39c9213cac0eb6d9ef6076cc4193733c1d74e7
--- /dev/null
+++ b/scripts/import.make
@@ -0,0 +1,67 @@
+# This file is included by all Makefiles in the LysKOM hierarchy.
+# It gives default values for all variables that is normally used. 
+# TOPDIR and SCRIPTDIR must be set before this file is included.
+# If any of the variables are defined in the environment, that value
+# will override the value that is set here.
+#
+# ceder is guilty.
+#
+
+ifndef SHELL
+SHELL=/bin/sh
+endif
+
+ifndef INCLUDEDIR
+INCLUDEDIR = $(TOPDIR)/include
+endif
+
+ifndef LIBDIR
+LIBDIR = $(TOPDIR)/lib
+endif
+
+ifndef ANSIDIR
+ANSIDIR = $(INCLUDEDIR)/ansi
+endif
+
+# Used programs.
+
+ifndef AWK
+AWK = gawk
+endif
+
+ifndef SED
+SED = /usr/bin/sed
+endif
+
+ifndef CC
+CC = /usr/gnu/bin/gcc -ansi
+endif
+
+ifndef RM
+RM = /usr/gnu/bin/rm -vf
+endif
+
+# Flags to the C compiler
+
+ifndef INCLUDES
+INCLUDES = -I$(ANSIDIR) -I$(INCLUDEDIR)
+endif
+
+ifndef OPTIMIZE-FLAGS
+OPTIMIZE-FLAGS = -O
+endif
+
+ifndef MISC-CFLAGS
+MISC-CFLAGS = -g -Wall
+endif
+
+ifndef LDFLAGS
+# -h flag makes NULL pointer references generate runtime errors
+LDFLAGS = -h -L$(LIBDIR)
+endif
+
+# Force CFLAGS to always follow the settings of INCLUDES,
+# OPTIMIZE-FLAGS and MISC-CFLAGS.
+# Set PIPE=-pipe if you want to.
+
+CFLAGS =  $(INCLUDES)  $(OPTIMIZE-FLAGS)  $(MISC-CFLAGS) $(PIPE) $(TARGET)
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..338aeb482fc124575cb8ee3192b81f58848dba22
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,38 @@
+# All directories that make should traverse to when doing clean etc.
+# Note htat libraries MUST be made before the rest. Otherwise you will
+# be linking with old versions...
+
+SUBDIRS = include libraries server komutils clients
+
+all:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making all in directory $$i; \
+		(cd $$i; $(MAKE) all)	\
+	done
+
+
+install:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making install in directory $$i; \
+		(cd $$i; $(MAKE) install)	\
+	done
+
+
+depend:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making depend in directory $$i; \
+		(cd $$i; $(MAKE) depend)	\
+	done
+
+
+clean:
+	rm -vf *~ core
+	for i in $(SUBDIRS); \
+	do \
+	   echo making clean in directory $$i; \
+	   (cd $$i; $(MAKE) clean) \
+	done
+		
diff --git a/src/include/Makefile b/src/include/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..45a81015942abedc44931b87cfa9cac8e16f1fbe
--- /dev/null
+++ b/src/include/Makefile
@@ -0,0 +1,76 @@
+#  Makefile for LysKOM
+#
+###############################################################################
+#
+#  SPECIAL CONSIDERATIONS:
+#
+#  -  Requires GNU make.
+#  -  CC, OPTIMIZE-FLAGS and other make variables are passed down 
+#     in the environment.
+#  -  C compiler must be ANSI conformant.
+#
+###############################################################################
+#
+#  SPECIAL TARGETS:
+###############################################################################
+
+# Directories that you might want to override via the environment.
+
+ifndef TOPDIR
+TOPDIR = /usr/lyskom/src
+endif
+
+ifndef SCRIPTDIR
+SCRIPTDIR = $(TOPDIR)/scripts
+endif
+
+TARGET = -DCLIENT
+
+include $(SCRIPTDIR)/import.make
+
+
+# All directories that make should traverse to when doing clean etc.
+
+SUBDIRS = ansi server 
+
+INSTALL-HDRS = $(wildcard *.h)
+
+all:
+	for i in $(SUBDIRS); \
+	do	\
+		echo making all in directory $$i; \
+		(cd $$i; $(MAKE) all); \
+	done
+
+
+
+.PHONY : install
+install:
+	(cd $(INCLUDEDIR); $(RM) $(INSTALL-HDRS))
+	cp $(INSTALL-HDRS) $(INCLUDEDIR)/
+	for i in $(SUBDIRS); \
+	do	\
+		echo making install in directory $$i; \
+		(cd $$i; $(MAKE) install); \
+	done
+
+clean:
+	rm -vf ${OBJECTS} *~ core temp-Makefile Distfile *.o
+	for i in $(SUBDIRS); \
+	do	\
+		echo making clean in directory $$i; \
+		(cd $$i; $(MAKE) clean); \
+	done
+
+
+depend:
+	for i in $(SUBDIRS); \
+	do	\
+		echo making depend in directory $$i; \
+		(cd $$i; $(MAKE) depend); \
+	done
+	>dependencies
+
+specials:;
+
+include dependencies
diff --git a/src/include/compiler.h b/src/include/compiler.h
new file mode 100644
index 0000000000000000000000000000000000000000..ceeb6583d160ab8117cd75a17d2dbffc794f67ab
--- /dev/null
+++ b/src/include/compiler.h
@@ -0,0 +1,41 @@
+/*
+ *  compiler.h
+ *		Defines different macros depending on the compiler to
+ *		portably use features of different compilers, like the
+ *		'__inline__' keyword in GCC.
+ *
+ *
+ *  Copyright (C) 1990	Lysator Computer Club,
+ *			Linkoping University,  Sweden
+ *
+ *  Everyone is granted permission to copy, modify and redistribute
+ *  this code, provided the people they give it to can.
+ *
+ *
+ *  Author:	Thomas Bellman
+ *		Lysator Computer Club
+ *		Linkoping University
+ *		Sweden
+ *
+ *  email:	Bellman@Lysator.LiU.SE
+ */
+
+
+#ifndef  SPECIAL_H_ALREADY_INCLUDED__
+#define  SPECIAL_H_ALREADY_INCLUDED__
+
+
+#ifdef __GNUC__
+
+#	define	Inline		__inline__	/* Inline function */
+#	define	Volatile	volatile	/* Function does not return */
+
+#else
+
+#	define	Inline
+#	define	Volatile
+
+#endif
+
+
+#endif  /*  SPECIAL_H_ALREADY_INCLUDED__  */
diff --git a/src/include/config.h b/src/include/config.h
new file mode 100644
index 0000000000000000000000000000000000000000..171752e255a067706ebf7583d8fb75dc9954713f
--- /dev/null
+++ b/src/include/config.h
@@ -0,0 +1,133 @@
+/*
+ *  config.h
+ *
+ *  Configuration parameters for compiling.  Contains among other
+ *  things all the stupid limits you really want to be without, all the
+ *  smart limits that has to be there to make it impossible to crash
+ *  the server, and lots of constants and configuration options.
+ */
+
+
+#define DEBUG			/* We're still debugging and want traces. */
+
+/*
+ * Add some checks that really shouldn't be necessary.
+ */
+#define DEFENSIVE_CHECKS
+
+
+/* Collating sequence used. */
+#define DEFAULT_COLLAT_TAB	swedish_collate_tab
+
+
+
+/* The file kom_perror prints to.  */
+/* Yes! This should be stdout. At least during testing and debugging! /ceder */
+
+#define kom_errout	stdout
+
+/*
+ * Security options (these must be #defines since they are used inside a
+ *		     'const' definition in kom-types.c).
+ */
+#define ANYONE_CAN_CREATE_NEW_PERSONS TRUE /* Can a created person */
+					   /* create other persons? */
+#define CREATE_PERSON_BEFORE_LOGIN  TRUE /* Can a person create himself? */
+#define ANYONE_CAN_CREATE_NEW_CONFS TRUE
+#define DEFAULT_CHANGE_NAME	    TRUE /* Everyone is normally allowed */
+					 /* to change their own name. */
+
+/*
+ * The following are constants which can not be changed without rewriting
+ * some of the code.
+ */
+#define PROTOCOL_NUMBER_BASE 10	/* The number base used in all communication
+				 * between server and clients. */
+
+
+/* Where to save things. These are used by ramkomd. */
+
+extern const char *DEFAULT_DBASE_DIR;
+extern const char *DATAFILE_NAME;
+extern const char *BACKUPFILE_NAME;
+extern const char *TEXTFILE_NAME;
+extern const char *STATISTIC_NAME;
+extern const char *PID_NAME;
+extern const char *MEMUSE_NAME;
+
+/* Communications */
+
+extern const char * DEFAULT_CLIENT_SERVICE;
+extern const char * DEFAULT_MUX_SERVICE;
+
+#if 0
+extern const int IN_CLIENT_PORT;	/* Which port does LysKOM listen to? */
+extern const int IN_MUX_PORT;	        /* Which port does LysKOM listen to? */
+#endif
+
+/*
+ * The following should always be true:
+ * SYNCTIMEOUT <= GARBTIMEOUT <= TIMEOUT
+ * Times in milliseconds.
+ */
+extern const int TIMEOUT;	/* Timeout to select() when totally idle. */
+extern const int GARBTIMEOUT;	/* Timeout to select() when garbing texts
+				   but not syncing. */
+extern const int SYNCTIMEOUT;	/* Timeout to select() when syncing. */
+
+extern const int GARB_INTERVAL;	/* In minutes. */
+extern const int SYNC_INTERVAL;	/* In minutes. */
+extern const int SYNC_RETRY_INTERVAL;	/* In minutes. */
+
+/* Size of the cache. (only applies to diskomd). */
+
+extern const int CACHE_CONFERENCES;
+extern const int CACHE_PERSONS;
+extern const int CACHE_TEXT_STATS;
+
+/* String limits */
+
+extern const int CONF_NAME_LEN;	/* Conference (and Person) name */
+extern const int PWD_LEN;	/* Password. It is not guaranteed that all
+				   chars are significant. */
+extern const int WHAT_DO_LEN;	/* what_am_i_doing */
+extern const int USERNAME_LEN;	/* Max login-id from clients */
+extern const int TEXT_LEN;	/* Max len of a text. */
+extern const int BROADCAST_LEN;	/* Max len of a broadcast message */
+
+/* Text_stat limits */
+
+extern const int MAX_MARKS_PERSON; /* Max marks per person */
+extern const int MAX_MARKS_TEXT;  /* Max marks per text */
+extern const int MAX_RECIPIENTS;  /* Max recipients/cc_recipients per text */
+extern const int MAX_COMM;	  /* Max number of comments to a text */
+extern const int MAX_FOOT;	  /* Max number of footnotes to a text */
+extern const int MAX_CREA_MISC;   /* Sum of recipients, cc_recipients, comm_to
+				   * and footn_to must not exceed MAX_CREA_MISC
+				   * when the text is created. */
+
+/*
+ * Some other limits
+ */
+extern const int MAX_NO_OF_CONNECTIONS;	/* the maximum number of persons
+					 * that can use Kom simultaneously */
+extern const int MARK_AS_READ_CHUNK;	/* You can't mark more than this many
+					 * texts as read in one call. */
+
+/*
+ * Max number of nested super_confs a message will be forwarded before
+ * the server gives up.
+ */
+extern const int MAX_SUPER_CONF_LOOP;
+
+
+extern const int DEFAULT_NICE;	/* Number of days a text normally lives. */
+
+/* Max entries in the per-client transmit queue */
+extern const int MAXQUEUEDSIZE;
+
+/* Max entries in the per-client transmit queue to send at any one time */
+extern const int MAXDEQUEUELEN;
+
+/* What is whitespace? */
+extern const unsigned char *WHITESPACE;
diff --git a/src/include/debug.h b/src/include/debug.h
new file mode 100644
index 0000000000000000000000000000000000000000..312a3ec966cf6c2feaadcb4caca19dd5e852b635
--- /dev/null
+++ b/src/include/debug.h
@@ -0,0 +1,14 @@
+#include "config.h"		/* DEBUG is defined there */
+#ifdef DEBUG
+#define BUG(s)  if (buglevel > 0) printf s ;
+#define VBUG(s) if (buglevel > 1) printf s ;
+#define BUGSTR(str) if (buglevel > 0) s_puts(str)
+#define VBUGSTR(str) if (buglevel > 1) s_puts(str)
+#define BUGDECL extern int buglevel
+#else
+#define BUG(s)
+#define VBUG(s)
+#define BUGSTR(str)
+#define VBUGSTR(str)
+#define BUGDECL
+#endif
diff --git a/src/include/dependencies b/src/include/dependencies
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/include/kom-errno.h b/src/include/kom-errno.h
new file mode 100644
index 0000000000000000000000000000000000000000..4588c5dc5d24aaf3bba1ffdca73bb9863134c867
--- /dev/null
+++ b/src/include/kom-errno.h
@@ -0,0 +1,86 @@
+/*
+ * kom_errno.h
+ *
+ * Created by ceder 1990-04-18
+ *
+ * The values that kom_errno can take.
+ */
+
+
+#ifndef  _KOM_ERRNO_ALREADY_INCLUDED__
+#define  _KOM_ERRNO_ALREADY_INCLUDED__
+
+#include <sys/types.h>
+
+
+typedef enum 
+{
+    KOM_NO_ERROR = 0,		/* No error has occured */
+    KOM_NOT_IMPL = 2,		/* Not implemented yet */
+    KOM_OBSOLETE = 3,		/* No longer implemented */
+    KOM_PWD = 4,			/* Wrong/illegal password */
+    KOM_LONG_STR = 5,		/* String too long */
+    KOM_LOGIN = 6,			/* Not logged in. */
+    KOM_LOGIN_DISALLOWED = 7,	/* System is in 'singel-user mode' */
+    KOM_CONF_ZERO = 8,		/* Attempt to use conference number 0. */
+    KOM_UNDEF_CONF = 9,		/* Undefined or secret conference */
+    KOM_UNDEF_PERS = 10,		/* Undefined or secret person */
+    KOM_ACCESS = 11,		 	/* No 'read/write permission' */
+    KOM_PERM = 12,			/* No permission */
+    KOM_NOT_MEMBER = 13,             /* Not member in conf */
+    KOM_NO_SUCH_TEXT = 14,		/* No such global text_no, or no access */
+    KOM_TEXT_ZERO = 15,		/* Can't use text no 0 */
+    KOM_NO_SUCH_LOCAL_TEXT = 16,	/* No such local text_no */
+    KOM_LOCAL_TEXT_ZERO = 17,	/* Can't use local text no 0 */
+    KOM_BAD_NAME = 18,		/* Too short/long or contains illegal chars */
+    KOM_INDEX_OUT_OF_RANGE = 19,	/*  */
+    KOM_CONF_EXISTS = 20,		/* Already exists */
+    KOM_PERS_EXISTS = 21,		/* Already exists */
+    KOM_SECRET_PUBLIC = 22,		/* Cannot be secret and !rd_prot */
+    KOM_LETTER_BOX = 23,		/* Cannot change letter_box flag */
+    KOM_LDB_ERR = 24,		/* Should never happen, unless Willf|r makes
+				 * a mistake. */
+    KOM_ILL_MISC = 25,		/* Illegal misc field.
+				   err_stat holds field no */
+
+    KOM_ILLEGAL_INFO_TYPE = 26,	/* Info_type parameter was illegal. This
+				   means that there is a bug in the client. */
+    KOM_ALREADY_RECIPIENT = 27,	/* Already recipient to this text. */
+    KOM_ALREADY_COMMENT = 28,	/* Already comment to this text. */
+    KOM_ALREADY_FOOTNOTE = 29,	/* Already footnote to this text. */
+    KOM_NOT_RECIPIENT = 30,		/* Not recipient */
+    KOM_NOT_COMMENT = 31,		/* Not comment to this text. */
+    KOM_NOT_FOOTNOTE = 32,		/* Not footnote to this text. */
+    KOM_RECIPIENT_LIMIT = 33,	/* Too many recipients */
+    KOM_COMM_LIMIT = 34,		/* Too many comments */
+    KOM_FOOT_LIMIT = 35,		/* Too many footnotes */
+    KOM_MARK_LIMIT = 36,		/* Too many marks. */
+    KOM_NOT_AUTHOR = 37,		/* Only the author may add footnotes or
+				   delete texts. */
+
+
+    KOM_NO_CONNECT = 38,		/* Can't connect to specified server */
+    KOM_OUT_OF_MEMORY = 39,		/* Couldn't get memory for result */
+    KOM_SERVER_IS_CRAZY = 40,	/* Client can't understand server */
+    KOM_CLIENT_IS_CRAZY = 41,	/* Client thinks that server says it can't
+				 * understand client. */
+    KOM_UNDEF_SESSION = 42,	/* No such session exists. */
+    not_used			/* Det {r jobbigt att flytta kommatecknet hela
+				   tiden... :-) /ceder */
+} Kom_err;
+
+
+extern Kom_err kom_errno;
+
+
+extern u_long err_stat;		/* Additional information about the error */
+
+/*
+ * print a short description of the error to stdout
+ */
+  
+void
+kom_perror(void);
+
+
+#endif  /* _KOM_ERRNO_ALREADY_INCLUDED__ */
diff --git a/src/include/kom-types.h b/src/include/kom-types.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b41a07e7226fc37c9bf878c3902effa91c29799
--- /dev/null
+++ b/src/include/kom-types.h
@@ -0,0 +1,533 @@
+/*
+ *  KOM-types.h  --  Types used by both server and client of LysKOM
+ *
+ *
+ *  Copyright (C) 1990	Lysator Computer Club,
+ *			Linkoping University,  Sweden
+ *
+ *  Everyone is granted permission to copy, modify and redistribute
+ *  this code, provided the people they give it to can.
+ *
+ *
+ *  Author:	Thomas Bellman
+ *		Lysator Computer Club
+ *		Linkoping University
+ *		Sweden
+ *
+ *  email:	Bellman@Lysator.LiU.SE
+ */
+
+
+
+#ifndef  KOM_TYPES_H_ALREADY_INCLUDED__
+
+#define  KOM_TYPES_H_ALREADY_INCLUDED__
+
+#ifndef SERVER
+# ifndef CLIENT
+#  error must define SERVER or CLIENT
+# endif
+#else
+# ifdef CLIENT
+#  error must not define both SERVER and CLIENT
+# endif
+#endif /* !SERVER */
+
+#include <sys/types.h>
+#include <limits.h>
+#include <time.h>
+
+#include <s-string.h>
+#include "misc-types.h"
+
+
+typedef		u_short 	Pers_no;
+typedef		u_short		Conf_no;
+typedef 	u_long		Text_no;
+typedef		u_long		Local_text_no;
+typedef		u_long		Session_no;
+
+#define	MAX_PERS_NO		((Pers_no) USHRT_MAX)
+#define MAX_CONF_NO		((Conf_no) USHRT_MAX)
+#define MAX_TEXT_NO		((Text_no) ULONG_MAX)
+#define	MAX_LOCAL_TEXT_NO	((Local_text_no) ULONG_MAX)
+
+
+
+#ifdef  SERVER
+	#define		PASSWD_LEN	64
+	typedef 	char		Password[PASSWD_LEN];
+	typedef		off_t		Text_index;
+	typedef		time_t		Time;
+#  define NULL_TIME_i	((Time) 0)
+
+#else	/* CLIENT */
+	typedef		struct tm	Time;
+#  define NULL_TIME_i	((Time) { 0 })
+
+#endif
+
+
+
+/*
+ * The privilige bits:  says what priviliges a person has.  E g
+ *  if he is allowed to read texts he normally shouldn't be allowed
+ *  to read. See file doc/security-levels.txt
+ */
+typedef	struct {
+	u_int	wheel	: 1;
+	u_int	admin	: 1;
+	u_int	statistic : 1;
+	u_int	create_pers: 1;
+	u_int	create_conf: 1;
+	u_int	change_name: 1;
+	u_int	flg7	: 1;	/* For future use. */
+	u_int	flg8	: 1;
+	u_int	flg9    : 1;
+	u_int	flg10   : 1;
+	u_int	flg11   : 1;
+	u_int	flg12	: 1;
+	u_int	flg13	: 1;
+	u_int	flg14	: 1;
+	u_int	flg15	: 1;
+	u_int	flg16	: 1;
+} Priv_bits;
+
+#ifdef SERVER
+#	define DEFAULT_PRIV_BITS_i	((Priv_bits)		\
+	{	0, 0, 0, ANYONE_CAN_CREATE_NEW_PERSONS,		\
+		ANYONE_CAN_CREATE_NEW_CONFS,			\
+		DEFAULT_CHANGE_NAME, 0, 0, 0, 0, 0,		\
+		0, 0, 0, 0, 0					\
+	})
+#else
+#	define DEFAULT_PRIV_BITS_i	((Priv_bits)		\
+	{	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		\
+		0, 0, 0, 0, 0					\
+	})
+#endif
+extern  const Priv_bits		DEFAULT_PRIV_BITS;
+
+
+
+/*
+ * Flags in the Person struct.
+ */
+typedef struct {
+    u_int  unread_is_secret : 1;/* FALSE if everyone is allowed to ask how */
+    				/* many unread texts you have.	*/
+    u_int  flg2	: 1;
+    u_int  flg3	: 1;
+    u_int  flg4	: 1;
+    u_int  flg5	: 1;
+    u_int  flg6	: 1;
+    u_int  flg7	: 1;
+    u_int  flg8	: 1;
+} Personal_flags;
+
+#define DEFAULT_PERSONAL_FLAGS_i	((Personal_flags)		\
+					 { 0, 0, 0, 0, 0, 0, 0, 0 })
+extern const Personal_flags DEFAULT_PERSONAL_FLAGS;
+
+
+
+/* See file doc/misc_items */
+typedef enum {	recpt     = 0,	/* 0 Recipient (conference) */
+		cc_recpt  = 1,	/* 1 Carbon Copy recipient (extra kopia) */
+#if 0
+		..._recpt =10,	/* 10 ...recipient (F|r k{nnedom) */
+/*		    Vad ska det heta p} engelska? */
+/* Please let this be a comment otherwise etags voids this file. */
+#endif
+		comm_to   = 2,	/* 2 Comment to (text) */
+		comm_in   = 3,	/* 3 Commented in (text) */
+		footn_to  = 4,	/* 4 This is a footnote to (text) */
+		footn_in  = 5,	/* 5 Footnote to this text in (text) */
+
+    
+		loc_no    = 6,	/* 6 Sequence number within conference */
+		rec_time  = 7,	/* 7 Received at (time) */
+		sent_by   = 8,	/* 8 Sent by (person) */
+		sent_at   = 9		/* 9 Sent at (time) */
+} Info_type;
+
+typedef	union {
+		Conf_no		recipient;
+		Conf_no		cc_recipient;
+		Local_text_no	local_no;
+		Time		received_at;
+		Text_no		comment_to;
+		Text_no		commented_in;
+		Text_no		footnote_to;
+		Text_no		footnoted_in;
+		Pers_no		sender;
+		Time		sent_at;
+} Info_datum;
+
+
+/*  This struct contains miscellaneous information about a text.  */
+typedef	struct {
+	Info_type	type;
+	Info_datum	datum;
+} Misc_info;
+
+
+/*  Fields of this type is supposed to tell the garbage collector
+ *  which texts it should remove first.
+ */
+typedef u_long	Garb_nice;
+
+
+/*  Struct for text status  */
+typedef struct {
+	Time		  creation_time;
+#ifdef SERVER
+        long              file_pos; /* Start of the text in the text file. */
+#endif
+	Pers_no		  author;
+	u_short		  no_of_lines;
+	String_size	  no_of_chars;
+	u_short		  no_of_marks;	/* Antal markeringar */
+	u_short		  no_of_misc;	/* Recipients, times, comments, ... */
+	Misc_info	* misc_items;	/* List of miscellaneous info. */
+} Text_stat;
+
+#ifdef SERVER
+#define	EMPTY_TEXT_STAT_i	((Text_stat)				\
+				 {  NULL_TIME_i, 0, 0, 0, 0, 0, 0, NULL  })
+#else
+#define	EMPTY_TEXT_STAT_i	((Text_stat)				\
+				 {  NULL_TIME_i, 0, 0, 0, 0, 0, NULL  })
+#endif
+
+extern const Text_stat EMPTY_TEXT_STAT;
+
+
+
+typedef	struct {
+	u_int		rd_prot	: 1;	/* !(Can anyone become a member?) */
+	u_int		original : 1;	/* Comments forbidden? */
+	u_int		secret : 1;	/* Secret conference? */
+					/* Note: if a letterbox is secret it
+					 * will be very hard for that person
+					 * to log in, since he can't map his
+					 * name to a pers_no. He must either
+					 * know his pers_no, or have another
+					 * identity which is his supervisor.
+					 */
+	u_int		letter_box : 1;	/* Is this a letter box? */
+} Conf_type;
+
+#define	NULL_CONF_TYPE_i	((Conf_type) {  0, 0, 0, 0  })
+extern  const Conf_type	NULL_CONF_TYPE;
+
+
+
+typedef struct {
+	Pers_no		member;
+} Member;
+
+
+
+/* Struct for marks */
+typedef struct {
+	Text_no		text_no;
+	u_char		mark_type;	/* It's up to the clients to decide the
+					   meaning of this field. */
+} Mark;
+
+
+
+/*  Information about a person's membership in a conference  */
+typedef struct {
+	Conf_no		conf_no;
+	u_char		priority;	/* Interrupt priority */
+	Time		last_time_read;	/* Updated every time a text in this
+					   conf. is marked as read.	*/
+	Local_text_no	last_text_read;	/* All texts before and inclusive this
+					   are read	*/
+	u_short		no_of_read;
+	Local_text_no * read_texts;	/* Texts after last_text_read. Sorted
+					   in ascending order */
+} Membership;
+
+#define	EMPTY_MEMBERSHIP_i	((Membership)		\
+			{  0, 0, NULL_TIME_i, 0, 0, NULL  })
+extern  const Membership EMPTY_MEMBERSHIP;
+
+
+
+/* Some structs to handle variable-sized arrays. */
+
+typedef struct {
+	u_short	  no_of_marks;
+	Mark	* marks;		/* Pointer to an array of marks. */
+} Mark_list;
+
+#define	EMPTY_MARK_LIST_i	((Mark_list) {  0, NULL  })
+extern const Mark_list EMPTY_MARK_LIST;
+
+
+typedef struct {
+    u_short no_of_confs;
+    Conf_no  *conf_nos;
+} Conf_no_list;
+
+#define EMPTY_CONF_NO_LIST_i	((Conf_no_list) { 0, NULL  })
+extern const Conf_no_list EMPTY_CONF_NO_LIST;
+   
+
+typedef struct {
+	u_short	  no_of_members;
+	Member	* members;
+} Member_list;
+
+#define EMPTY_MEMBER_LIST_i	((Member_list) {  0, NULL  })
+extern const Member_list EMPTY_MEMBER_LIST;
+
+
+
+typedef  struct {
+	Local_text_no	  first_local_no;
+    	u_long		  no_of_texts;
+	Text_no		* texts;
+}  Text_list;
+
+#define EMPTY_TEXT_LIST_i	((Text_list) {  1, 0, NULL  })
+extern const Text_list	EMPTY_TEXT_LIST;
+
+
+
+/*  A list of conference numbers, also telling if it is a
+ *  mailbox (i e a person) or an ordinary conference.	*/
+/* Delete this ugly variant as soon as possible! */
+typedef struct {
+	u_long		  no_of_conf_nos;
+	Conf_no		* conf_nos;
+	Conf_type	* type_of_conf;
+} Conf_list_old;
+/* This is the way it should look! */
+typedef struct {
+	Conf_no   conf_no;
+	Conf_type type;
+} Micro_conf;
+
+typedef struct {
+	u_long       no_of_confs;
+	Micro_conf * confs;
+} Conf_list;
+
+
+#define EMPTY_CONF_LIST_OLD_i	((Conf_list_old) {  0, NULL, NULL  })
+extern const Conf_list_old	EMPTY_CONF_LIST_OLD;
+
+#define EMPTY_CONF_LIST_i	((Conf_list) {  0, NULL  })
+extern const Conf_list		EMPTY_CONF_LIST;
+
+
+/*  A list of person numbers  */
+typedef struct {
+	u_long		  no_of_persons;
+	Pers_no		* persons;
+} Pers_list;
+
+#define EMPTY_PERS_LIST_i	((Pers_list) {  0, NULL  })
+extern  const Pers_list		EMPTY_PERS_LIST;
+
+
+
+typedef struct {
+	u_short	      no_of_confs;
+	Membership  * confs;
+} Membership_list;
+
+#define EMPTY_MEMBERSHIP_LIST_i		((Membership_list) {  0, NULL  })
+extern  const Membership_list		EMPTY_MEMBERSHIP_LIST;
+
+
+
+/* The Info struct */
+typedef struct {
+	long		version;
+	Conf_no		conf_pres_conf; /* Presentation of new confs */
+	Conf_no		pers_pres_conf;	/* Presentation of new persons */
+	Conf_no		motd_conf; 	/* Conf that receive motds */
+	Conf_no		kom_news_conf;  /* News about kom */
+	Text_no		motd_of_lyskom; /* To be displayed after login */
+	/* and maybe more... */
+} Info;
+
+
+
+typedef	struct {
+	Pers_no		creator;
+	Time		creation_time;
+	Text_no		presentation;
+	Conf_no		supervisor;	/* Organisat|r f|r m|tet */
+	Conf_no		permitted_submitters;	/* People who are allowed
+					   to submit texts to this conf. 
+					   0 -> anyone may submit. */
+	Conf_no		super_conf;	/* Send unallowed submissions to
+					   the super_conf. 
+					   0 -> unallowed submissions bounce */
+	Conf_type	type;		/* secret, rd_prot etc */
+	Time		last_written;	/* Time of latest text in this conf. */
+	Text_no		msg_of_day;	/* Message to be displayed when this
+					   conf is referenced by the user. */
+	Garb_nice	nice;		/* How long do texts in this
+					   conf live? */
+	String		name;		/* Name of conference */
+#ifdef CLIENT
+	u_short		no_of_members;
+	Local_text_no	first_local_no;
+	u_long		no_of_texts;
+#else
+	Member_list	members;	/* List of members in conf */
+	Text_list	texts;		/* List of texts */
+#endif
+} Conference;
+
+
+#ifdef CLIENT
+#	define	EMPTY_CONFERENCE_i	((Conference)		\
+	{	0, NULL_TIME_i, 0, 0, 0, 0, NULL_CONF_TYPE_i,	\
+		NULL_TIME_i, 0, 0, EMPTY_STRING_i, 0, 0, 0	\
+	})
+#else	/* SERVER */
+#	define	EMPTY_CONFERENCE_i	((Conference)		\
+	{	0, NULL_TIME_i, 0, 0, 0, 0, NULL_CONF_TYPE_i,	\
+		NULL_TIME_i, 0, 0, EMPTY_STRING_i,		\
+		EMPTY_MEMBER_LIST_i, EMPTY_TEXT_LIST_i		\
+	})
+#endif	/* SERVER */
+extern const Conference	EMPTY_CONFERENCE;
+
+
+#ifdef SERVER
+typedef struct {
+	String		name;		/* Name of conference */
+	Conf_type	type;		/* secret, rd_prot etc */
+	Local_text_no	highest_local_no; /* highest local text no */
+	Garb_nice	nice;	        /* Number of days to live */
+} Small_conf;
+
+#define EMPTY_SMALL_CONF_i ((Small_conf){EMPTY_STRING_i, NULL_CONF_TYPE_i, \
+					     0, 0});
+
+extern const Small_conf EMPTY_SMALL_CONF;
+#endif	
+	
+
+/*  Struct for persons  */
+typedef struct {
+	Text_no		user_area;	/* Misc info the clients might want to
+					   store. 0 = not used. */
+	Priv_bits	privileges;
+	Personal_flags	flags;
+	Time		last_login; 	/* Or logout */
+	u_long		total_time_present; /* Number of seconds. */
+	u_long		sessions;	/* Number of sessions */
+	u_long		created_lines;	/* No. of created lines (statistics) */
+	u_long		created_bytes;	/* No. of created bytes (statistics) */
+	u_long		read_texts;	/* No. of read texts (statistics) */
+	u_long		no_of_text_fetches; /* (statistics) */
+	u_short		created_persons; /* (statistics) */
+	u_short		created_confs;	/* (statistics) */
+	String		username;	/* User-name & hostname */
+#ifdef CLIENT
+	Local_text_no	first_created_text; /* The first text that still
+					     * exists. */
+	u_long		no_of_created_texts;
+	u_short		no_of_marks;	/* This many marked texts */
+	u_short		no_of_confs;	/* Member in this many confs */
+#else	/* SERVER */
+	Text_list	created_texts;
+	Mark_list	marks;		/* List of marked texts */
+	Membership_list conferences;	/* List of conferences the person is
+					 * a member in. */
+	Password	pwd;		/* Encrypted password */
+#endif
+} Person;
+
+#ifdef SERVER
+#	define EMPTY_PERSON_i	((Person)			\
+	{	0, DEFAULT_PRIV_BITS_i,				\
+		DEFAULT_PERSONAL_FLAGS_i, NULL_TIME_i, 0, 0,	\
+		0, 0, 0, 0, 0, 0, EMPTY_STRING_i,		\
+		EMPTY_TEXT_LIST_i, EMPTY_MARK_LIST_i,		\
+		EMPTY_MEMBERSHIP_LIST_i, "\001password"		\
+	})
+#else
+#	define EMPTY_PERSON_i	((Person)			\
+	{	0, DEFAULT_PRIV_BITS_i,				\
+		DEFAULT_PERSONAL_FLAGS_i, NULL_TIME_i, 0, 0,	\
+		0, 0, 0, 0, 0, 0, EMPTY_STRING_i, 0, 0, 0, 0	\
+	})
+#endif
+extern  const Person	EMPTY_PERSON;
+
+
+
+/*
+ * This struct is returned from the 'who_is_on' call.
+ */
+typedef struct {
+	Pers_no		person;
+	String		what_am_i_doing;
+	Conf_no		working_conference;
+} Who_info_old;
+
+typedef struct {
+	Pers_no		person;
+	String		what_am_i_doing;
+	String		username;           /* Userid and hostname. */
+	Conf_no		working_conference;
+	Session_no	session_no;         /* Serial number of connection. */
+} Who_info;
+
+typedef struct {
+	Pers_no		person;
+	String		what_am_i_doing;
+	String		username;            /* Userid and hostname. */
+	Conf_no		working_conference;
+	Session_no	session;             /* Serial number of connection. */
+	Time		connection_time;     /* Not logintime. */
+	u_long		idle_time; 	     /* Seconds. */
+} Session_info;
+
+#define EMPTY_SESSION_INFO_i	((Session_info) { 0, EMPTY_STRING_i,    \
+						  EMPTY_STRING_i, 0, 0, \
+						  NULL_TIME_i, 0 })
+
+extern const Session_info	EMPTY_SESSION_INFO;
+
+#define	EMPTY_WHO_INFO_OLD_i	((Who_info_old) {  0, EMPTY_STRING_i, 0 })
+
+#define	EMPTY_WHO_INFO_i	((Who_info) {  0, EMPTY_STRING_i, \
+						   EMPTY_STRING_i, 0, 0 })
+
+extern const Who_info_old	EMPTY_WHO_INFO_OLD;
+
+extern const Who_info		EMPTY_WHO_INFO;
+
+
+
+typedef struct {
+	int		  no_of_persons;
+    	Who_info_old	* info;
+} Who_info_list_old;	
+
+#define EMPTY_WHO_INFO_LIST_OLD_i ((Who_info_list_old) {  0, NULL  })
+extern const Who_info_list_old	EMPTY_WHO_INFO_LIST_OLD;
+
+
+typedef struct {
+	int		  no_of_persons;
+    	Who_info	* info;
+} Who_info_list;	
+
+#define EMPTY_WHO_INFO_LIST_i	((Who_info_list) {  0, NULL  })
+extern const Who_info_list	EMPTY_WHO_INFO_LIST;
+
+
+#endif	/*  ifndef  KOM_TYPES_H_ALREADY_INCLUDED__  */
diff --git a/src/include/misc-types.h b/src/include/misc-types.h
new file mode 100644
index 0000000000000000000000000000000000000000..87b110ea45e7755c3976f38de65783f82668d4df
--- /dev/null
+++ b/src/include/misc-types.h
@@ -0,0 +1,34 @@
+/*
+ *  misc-types.h  --  Miscellaneous types and constants that are useful
+ *		      in many places in LysKOM, but are not very LysKOM-
+ *		      specific.
+ *
+ *
+ *  Copyright (C) 1990	Lysator Computer Club,
+ *			Linkoping University,  Sweden
+ *
+ *  Everyone is granted permission to copy, modify and redistribute
+ *  this code, provided the people they give it to can.
+ *
+ *
+ *  Author:	Thomas Bellman
+ *		Lysator Computer Club
+ *		Linkoping University
+ *		Sweden
+ *
+ *  email:	Bellman@Lysator.LiU.SE
+ *
+ */
+
+
+#ifndef  _MISC_TYPES_ALREADY_INCLUDED__
+#define  _MISC_TYPES_ALREADY_INCLUDED__
+
+
+typedef	enum { FALSE = 0, TRUE = 1 }	Bool;
+
+typedef enum { OK = 017, FAILURE = 17 }    Success;
+
+#define NO_TIME ((time_t) 0)
+
+#endif  /* _MISC_TYPES_ALREADY_INCLUDED__ */
diff --git a/src/include/server/Makefile b/src/include/server/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..51573620b14b06f5a9ea6c6df4d83e19cfc601eb
--- /dev/null
+++ b/src/include/server/Makefile
@@ -0,0 +1,54 @@
+#  Makefile for LysKOM
+#
+###############################################################################
+#
+#  SPECIAL CONSIDERATIONS:
+#
+#  -  Requires GNU make.
+#  -  CC, OPTIMIZE-FLAGS and other make variables are passed down 
+#     in the environment.
+#  -  C compiler must be ANSI conformant.
+#
+###############################################################################
+#
+#  SPECIAL TARGETS:
+###############################################################################
+
+# Directories that you might want to override via the environment.
+
+ifndef TOPDIR
+TOPDIR = /usr/lyskom/src
+endif
+
+ifndef SCRIPTDIR
+SCRIPTDIR = $(TOPDIR)/scripts
+endif
+
+TARGET = -DCLIENT
+
+include $(SCRIPTDIR)/import.make
+
+
+# All directories that make should traverse to when doing clean etc.
+
+
+INSTALL-HDRS = smalloc.h
+
+all:;
+
+
+.PHONY : install
+install:
+	-mkdir $(INCLUDEDIR)/server
+	(cd $(INCLUDEDIR)/server; $(RM) $(INSTALL-HDRS))
+	cp $(INSTALL-HDRS) $(INCLUDEDIR)/server/
+
+clean:
+	rm -vf ${OBJECTS} *~ core temp-Makefile Distfile *.o
+
+depend:
+	>dependencies
+
+specials:;
+
+include dependencies
diff --git a/src/include/server/dependencies b/src/include/server/dependencies
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/include/server/smalloc.h b/src/include/server/smalloc.h
new file mode 100644
index 0000000000000000000000000000000000000000..155eb678a67ad1f2c027e8c1778b89f06f53858d
--- /dev/null
+++ b/src/include/server/smalloc.h
@@ -0,0 +1,57 @@
+/*
+ * smalloc.h
+ *
+ * Contains memory allocator routines
+ *
+ */
+
+/*
+ * The servers "general" memory handler.
+ */
+
+
+#define SMALLOC_MAGIC_ALLOC 0x12FE56A0
+#define SMALLOC_MAGIC_FREE  0xCA348E63
+
+/*
+ * "safe" malloc. Handles the case when malloc returns NULL.
+ * smalloc cannot fail.
+ */
+extern void *
+smalloc(size_t size);
+
+
+extern void
+sfree(void * ptr);	/* it is legal to sfree a NULL pointer */
+
+extern void *
+srealloc(void * ptr, size_t size); /* Never fails. It is legal to
+				      realloc the NULL ptr. */
+
+/*
+ * Allocate temporary memory, which is automatically freed after this
+ * atomic call.
+ */
+void *
+tmp_alloc(u_long size);
+
+/*
+ * Free all core which is allocated with tmp_alloc(). This is called from
+ * end_of_atomic().
+ */
+void
+free_tmp(void);
+
+/*
+ * Free all memory used internally in tmp_alloc().
+ */
+void
+free_all_tmp(void);
+
+
+/*
+ * Write statistics of memory usage.
+ */
+
+void
+dump_smalloc_counts(FILE *stat_file);
diff --git a/src/include/services.h b/src/include/services.h
new file mode 100644
index 0000000000000000000000000000000000000000..e847d03c14d76437f68274e02d55bc237915a16d
--- /dev/null
+++ b/src/include/services.h
@@ -0,0 +1,477 @@
+/*
+ *  services.h  --  All the services the LysKOM server makes available
+ *		    for clients.
+ *
+ *  Requires kom-types.h
+ *
+ *  Created by ceder 1990-03-23
+ */
+
+
+#ifndef  _SERVICES_H_ALREADY_INCLUDED__
+#define  _SERVICES_H_ALREADY_INCLUDED__
+
+
+#if defined (CLIENT)
+#	if defined (SERVER)
+#		error Both CLIENT and SERVER defined!
+#	endif
+#	define	KOM_(function)		kom_ ## function
+#	define	CONST			const
+#elif defined (SERVER)
+#	define	KOM_(function)		function
+#	define	CONST
+#else
+#	error	Neither CLIENT nor SERVER defined!
+#endif
+
+
+
+
+/*
+ * Session control
+ */
+#ifdef CLIENT
+extern  Success
+KOM_( open_connection (const char	* server ));
+
+extern  void
+KOM_( set_storage_management (malloc_function	new_malloc,
+			      realloc_function	new_realloc,
+			      free_function	new_free));
+
+#endif
+
+
+extern  Success
+KOM_( login (Pers_no		person,
+	     const String	passwd ));
+
+extern  Success
+KOM_( logout (void));	/* can never fail */
+
+/* Change Conference */
+extern  Success
+KOM_( pepsi (Conf_no	conference ));
+
+
+/* Change name of a person or conference. */
+extern  Success
+KOM_( change_name (Conf_no	  conf_no,
+		   const String	  new_name));
+
+extern  Success
+KOM_( change_what_i_am_doing (CONST String  what_am_i_doing ));
+
+
+/* Get info about a session */
+
+extern  Success
+KOM_( get_session_info  (Session_no session_no,
+			 Session_info *result) );
+
+/*
+ * Disconnect a session. You can disconnect your own session (even if
+ * you are not logged in) and any session where you are supervisor of
+ * the user that is logged in on that session.
+ */
+extern  Success
+KOM_( disconnect (Session_no session_no));
+
+/*
+ * Returns your session number
+ */
+extern  Success
+KOM_( who_am_i (Session_no *session_no));
+
+
+/******************************
+*     Person-related calls    *
+******************************/
+
+/*
+ *  Create a new person.  Returns 0 if any error occured.
+ */
+extern  Pers_no
+KOM_( create_person (const String  name,
+		     const String  passwd ));
+
+
+/* Obsolete call; use get_person_stat instead. */
+extern  Success
+KOM_( get_person_stat_old (Pers_no		  person,
+			   int			  mask,
+			   Person		* result ));
+
+extern  Success
+KOM_( get_person_stat (Pers_no		  person,
+		       Person		* result ));
+
+
+
+extern  Success
+KOM_( get_created_texts (Pers_no	  person,
+			 Local_text_no	  first,
+			 u_long		  no_of_texts,
+			 Text_list	* created_texts ));
+
+extern  Success
+KOM_( get_membership (Pers_no		  person,
+		      u_short		  first,
+		      u_short		  no_of_confs,
+		      Bool		  want_read_texts,
+		      Membership_list	* memberships ));
+
+
+
+extern  Success
+KOM_( set_priv_bits (Pers_no	person,
+		     Priv_bits	privileges ));
+
+
+/*  Set the password of PERSON to NEW_PWD.  OLD_PWD is the password
+ *  of the person who does the set.  This is not necessarily the
+ *  same as the one who gets it set.	*/
+extern  Success
+KOM_( set_passwd (Pers_no	 person,
+		  const String   old_pwd,
+		  const String   new_pwd ));
+
+
+/* You can query for unread texts without logging in. */
+extern  Success
+KOM_( query_read_texts (Pers_no	     pers_no,
+			Conf_no	     conf_no,
+			Membership * result   ));
+
+
+extern Success
+KOM_( get_unread_confs(Pers_no       pers_no,
+		       Conf_no_list *result));
+
+extern Success
+KOM_( set_user_area(Pers_no	pers_no,
+		    Text_no	user_area));
+
+
+/****************************************
+*	Conference-related calls	*
+****************************************/
+
+
+extern  Conf_no
+KOM_( create_conf (const String	  name,
+		   Conf_type	  type ));
+
+
+/*  Delete a conference.  Also used to delete persons.  */
+extern  Success
+KOM_( delete_conf (Conf_no	conf ));
+
+
+/*
+ *  Map conference name to number.  Returns a list of the conferences
+ *  that match the name NAME. Can be done without logging in.
+ */
+#ifdef SERVER
+extern  Success
+KOM_( lookup_name (const String	 name,
+		   Conf_list_old *result));
+#else
+extern  Success
+KOM_( lookup_name (const String	 name,
+		   Conf_list	*result));
+#endif
+
+extern  Success
+KOM_( get_conf_stat_old (Conf_no	conf_no,
+			 int		mask,
+			 Conference   * result ));
+
+extern  Success
+KOM_( get_conf_stat (Conf_no		  conf_no,
+		     Conference		* result ));
+
+extern  Success
+KOM_( get_members (Conf_no	  conf,
+		   u_short	  first,
+		   u_short	  no_of_members,
+		   Member_list	* members	));
+
+
+
+/* add_member is also used to change the priority of a conference */
+extern  Success
+KOM_( add_member (Conf_no	conf_no,
+		  Pers_no	pers_no,
+		  u_char	priority,
+		  u_short	where	)); /* Range of where is [0..] */
+
+
+extern  Success
+KOM_( sub_member (Conf_no	conf_no,
+		  Pers_no	pers_no ));
+
+
+/*
+ * Tell the server that I want to mark/unmark texts as read so that I
+ * get no_of_unread unread texts in conf_no.
+ */
+extern  Success
+KOM_( set_unread (Conf_no   conf_no,
+		  Text_no   no_of_unread));
+
+/*
+ * set_presentation and set_etc_motd also does some magic with the
+ * no_of_marks field in the Text_stat structure of the old and new text.
+ */ 
+
+extern  Success
+KOM_( set_presentation (Conf_no   conf_no,
+			Text_no   text_no )); /* 0 to delete pres. */
+
+extern  Success
+KOM_( set_etc_motd (Conf_no	  conf_no,
+		    Text_no	  text_no ));
+
+
+extern  Success
+KOM_( set_supervisor (Conf_no	  conf_no,
+		      Conf_no	  admin	));
+
+extern  Success
+KOM_( set_permitted_submitters (Conf_no	  conf_no,
+				Conf_no	  perm_sub ));
+
+extern  Success
+KOM_( set_super_conf (Conf_no	  conf_no,
+		      Conf_no	  super_conf ));
+
+extern  Success
+KOM_( set_conf_type (Conf_no	  conf_no,
+		     Conf_type	  type	));
+
+extern  Success
+KOM_( set_garb_nice (Conf_no	  conf_no,
+		     Garb_nice	  nice	)); /* number of days */
+
+
+
+/********************************
+*     Calls to handle marks     *
+********************************/
+
+
+extern  Success
+KOM_( get_marks (Mark_list *result ));
+
+
+
+/*
+ *  Will fail if the user is not allowed to read the text.
+ */
+extern  Success
+KOM_( mark_text (Text_no	  text,
+		 u_char		  mark_type ));
+
+
+
+
+/*******************************
+*     Calls to handle texts    *
+*******************************/
+
+
+extern  Success
+KOM_( get_text (Text_no	 	  text,
+		String_size	  start_char,
+		String_size	  end_char,
+		String		* result));
+
+
+extern  Success
+KOM_( get_text_stat (Text_no    text,
+		     Text_stat *result));
+
+extern  Success
+KOM_( mark_as_read (Conf_no		    conference,
+		    int			    no_of_texts,
+		    const Local_text_no	  * text_arr   ));
+
+
+/* Returns 0 on error */
+extern  Text_no
+KOM_( create_text (CONST String		  message,
+		   u_short		  no_of_misc,
+		   CONST Misc_info	* misc	     ));
+
+extern Success
+KOM_( delete_text( Text_no text_no ));
+
+
+
+extern  Success
+KOM_( add_recipient (Text_no	  text_no,
+		     Conf_no	  conf_no,
+		     Info_type	  type	)); /* recpt or cc_recpt */
+
+extern  Success
+KOM_( sub_recipient (Text_no	  text_no,
+		     Conf_no	  conf_no ));
+
+
+extern  Success
+KOM_( add_comment (Text_no	  comment,
+		   Text_no 	  comment_to ));
+
+
+/*
+ *  Make the text COMMENT to not be a comment to text COMMENT_TO
+ */
+extern  Success
+KOM_( sub_comment (Text_no	  comment,
+		   Text_no	  comment_to ));
+
+extern Success
+KOM_( add_footnote (Text_no	footnote,
+		    Text_no 	footnote_to ));
+
+extern Success
+KOM_( sub_footnote (Text_no	footnote,
+		    Text_no	parent ));
+
+extern  Success
+KOM_( get_map (Conf_no		  conf_no,
+	       Local_text_no	  first_local_no,
+	       u_long		  no_of_texts,
+	       Text_list	* result));
+
+
+/*
+ *  Ask what the server thinks the time is. This
+ *  might differ if on two different machines.
+ */
+#ifdef SERVER
+extern  Success
+KOM_( get_time (time_t *time));
+#else				/* CLIENT */
+extern  Success
+KOM_( get_time (struct tm *clock));
+#endif
+
+
+/*
+ * Who is logged on now?
+ */
+extern  Success
+KOM_( who_is_on_old (Who_info_list_old	* result ));
+
+extern  Success
+KOM_( who_is_on (Who_info_list	* result ));
+
+
+/*
+ *  Return various information about the server
+ */
+extern  Success
+KOM_( get_info (Info *result ));
+
+/*
+ *  Wait for asynchronous message from client, or input on any of
+ *  the file-descriptors in opt_set. Returns FAILURE if nothing
+ *  happened in msec milliseconds or an error occurs. (kom_errno ==
+ *  KOM_NO_ERR if the return was due to a timeout). Returns OK if
+ *  there was an asynchronous message or input on any of the fd's in
+ *  opt_set.
+ *
+ *  Set opt_set to NULL if you don't want to wait on any other input
+ *  than a message.
+ *
+ *  To wait for a message or input on stdin the following code can be used:
+ *
+ *  fd_set read_set;
+ *
+ *  FD_ZERO(&read_set);
+ *  FD_SET(fileno(stdin), &read_set);
+ *  if ( kom_wait(read_set, 1000) == OK )
+ *  {
+ *	if ( FD_ISSET(fileno(stdin), &read_set) )
+ *	    handle_stdin_input();
+ *	else
+ *	    handle_asynchronous_message();
+ *  }
+ *  else
+ *	time_out();
+ *
+ *  (The handler is called from kom_wait and not handle_asynchronous_message,
+ *   but there might be more to do afterwards since a handler cannot call
+ *   functions that communicate with the server.)
+ */
+#ifdef CLIENT
+extern  Success
+KOM_( wait (fd_set *opt_set,
+	    int     msec));
+#endif
+
+/*
+ * Privileged calls.
+ */
+
+extern Success
+KOM_( set_motd_of_lyskom (Text_no motd));
+
+/*
+ * Set ena_level. 0 means don't use any privileges.
+ */
+extern Success
+KOM_( enable (u_char ena_level));
+
+/*
+ * Make LysKOM sync its files.
+ */
+extern Success
+KOM_( sync (void) );
+
+/*
+ * Close LysKOM.
+ */
+extern Success
+KOM_( shutdown (int exit_val) );
+
+/*
+ * Send a message to all clients. This is obsoleted by send_message()
+ * and will soon go away.
+ */
+extern Success
+KOM_( broadcast (const String message) );
+
+/*
+ * Send a message to a person, or all persons. If recipient == 0 all
+ * connections will receive the message.
+ */
+extern Success
+KOM_( send_message (Pers_no recipient,
+		    const String message) );
+
+
+/*
+ * Asynchronous messages.
+ */
+#ifdef CLIENT
+void
+register_new_text(void (*async_new_text)(Text_no    text_no, 
+					 Text_stat  text_s));
+
+void
+register_i_am_on(void (*async_i_am_on)(Who_info info));
+
+void
+register_i_am_off (void (*async_i_am_off)(Pers_no pers_no));
+
+void
+register_new_name(void (*async_new_name)(Conf_no  conf_no,
+					 String   old_name,
+					 String   new_name));
+#endif	/* CLIENT */
+    
+#endif	/*  _SERVICES_H_ALREADY_INCLUDED__  */
diff --git a/src/libraries/Makefile b/src/libraries/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d69235845cdf4cbac6e639520c369d354ac0fdde
--- /dev/null
+++ b/src/libraries/Makefile
@@ -0,0 +1,46 @@
+# All directories that make should traverse to when doing clean etc.
+# Note that client-support depends on libmisc.
+
+SUBDIRS = libansi libmisc libisc libcommon client-support
+
+all:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making all in directory $$i; \
+		(cd $$i; $(MAKE) all)	\
+	done
+
+
+depend:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making depend in directory $$i; \
+		(cd $$i; $(MAKE) depend);	\
+		echo make depend in directory $$i ready.; \
+	done
+
+
+install:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making install in directory $$i; \
+		(cd $$i; $(MAKE) install)	\
+	done
+
+
+install-headers:
+	for i in $(SUBDIRS) ;	\
+	do	\
+		echo making install-headers in directory $$i; \
+		(cd $$i; $(MAKE) install-headers)	\
+	done
+
+
+clean:
+	rm -vf *~ core
+	for i in $(SUBDIRS); \
+	do \
+	   echo making clean in directory $$i; \
+	   (cd $$i; $(MAKE) clean) \
+	done
+		
diff --git a/src/libraries/libansi/Makefile b/src/libraries/libansi/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..3f63c0e258fd92db01169e73919a45c830bb8123
--- /dev/null
+++ b/src/libraries/libansi/Makefile
@@ -0,0 +1,67 @@
+#  Makefile for LysKOM
+#
+###############################################################################
+#
+#  SPECIAL CONSIDERATIONS:
+#
+#  -  Requires GNU make.
+#  -  CC, OPTIMIZE-FLAGS and other make variables are passed down 
+#     in the environment.
+#  -  C compiler must be ANSI conformant.
+#
+###############################################################################
+#
+#  SPECIAL TARGETS:
+###############################################################################
+
+# Directories that you might want to override via the environment.
+
+ifndef TOPDIR
+TOPDIR = /usr/lyskom/src
+endif
+
+ifndef SCRIPTDIR
+SCRIPTDIR = $(TOPDIR)/scripts
+endif
+
+TARGET = -DCLIENT
+
+include $(SCRIPTDIR)/import.make
+
+
+# All directories that make should traverse to when doing clean etc.
+
+
+LIBNAME = libansi.a
+
+LIBOBJS = strerror.o
+
+all:	$(LIBNAME)
+
+libmisc.a: $(LIBOBJS)
+	rm -f $(LIBNAME)
+	ar qc $(LIBNAME) $(LIBOBJS)
+	ranlib $(LIBNAME)
+
+install-headers:;
+
+install: $(LIBNAME)
+	$(RM) $(LIBDIR)/$(LIBNAME)
+	cp $(LIBNAME) $(LIBDIR)/$(LIBNAME)
+	ranlib $(LIBDIR)/$(LIBNAME)
+
+
+clean:
+	rm -vf ${LIBOBJS} *~ core temp-Makefile Distfile *.o
+
+
+# Recreate the Makefile
+include $(SCRIPTDIR)/Parallell-depend.make
+
+
+tags:
+	etags -t *.[hc]	
+
+specials:;
+
+include dependencies
diff --git a/src/libraries/libansi/README b/src/libraries/libansi/README
new file mode 100644
index 0000000000000000000000000000000000000000..e721d6dd83cf552b0ba584869d15fb17f1883c8f
--- /dev/null
+++ b/src/libraries/libansi/README
@@ -0,0 +1,5 @@
+Detta {r t{nkt att bli ett bibliotek med divers rutiner som beh|vs
+f|r de stackare utan ANSI bibliotek.. (Alla n{stan).
+
+/pen
+
diff --git a/src/libraries/libansi/config.h b/src/libraries/libansi/config.h
new file mode 100644
index 0000000000000000000000000000000000000000..9fe0eaccb0b468492fcd545ace08e347f9109505
--- /dev/null
+++ b/src/libraries/libansi/config.h
@@ -0,0 +1,8 @@
+/*
+** config.h
+**
+** System: SunOS 4.1.1
+*/
+
+
+/* #define HAVE_STRERROR /* */
diff --git a/src/libraries/libansi/dependencies b/src/libraries/libansi/dependencies
new file mode 100644
index 0000000000000000000000000000000000000000..00b32730b77072831534c7517dc2c393a9df1e19
--- /dev/null
+++ b/src/libraries/libansi/dependencies
@@ -0,0 +1 @@
+strerror.o : strerror.c config.h 
diff --git a/src/libraries/libansi/libansi.a b/src/libraries/libansi/libansi.a
new file mode 100644
index 0000000000000000000000000000000000000000..da20a4f3e62e290cd2381b772fd4d11db21625e9
Binary files /dev/null and b/src/libraries/libansi/libansi.a differ
diff --git a/src/libraries/libansi/strerror.c b/src/libraries/libansi/strerror.c
new file mode 100644
index 0000000000000000000000000000000000000000..dfbc8776f815ee16d81999340dde1c6f371b8c5b
--- /dev/null
+++ b/src/libraries/libansi/strerror.c
@@ -0,0 +1,23 @@
+/*
+** strerror.c
+*/
+#include "config.h"
+
+#ifndef HAVE_STRERROR
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char *strerror(int eno)
+{
+  static char buf[20];
+
+  if (eno < 0 || eno >= sys_nerr)
+  {
+    sprintf(buf, "Error %d", eno);
+    return buf;
+  }
+  else
+    return sys_errlist[eno];
+}
+#endif
diff --git a/src/libraries/libcommon/ChangeLog b/src/libraries/libcommon/ChangeLog
new file mode 100644
index 0000000000000000000000000000000000000000..f17c43a9314993368574937ab27df9bc3d0545c5
--- /dev/null
+++ b/src/libraries/libcommon/ChangeLog
@@ -0,0 +1,15 @@
+Sat Jul  6 06:15:40 1991  Per Cederqvist  (ceder at lysator)
+
+	* Fixade makefilen s} att den kan generera b}de liblyskom-server.a
+	  och liblyskom-client.a. (Den ena kompilerad med SERVER
+	  definierad, den andra med CLIENT definierad). "make depend"
+	  kr{ver i nul{get manuella efterjusteringar.
+
+	* misc-parser.h: "time_t" bytt mot "Time" (som {r "struct tm" i
+	  klienten och "time_t" i servern).
+
+	* [ndrade "typedef struct {...} Matching_info" till "typedef
+	  struct matching_info {...} Matching_info".
+
+	* parser.h: s-collat-tables.h -> s-collat-tabs.h.
+
diff --git a/src/libraries/libcommon/Makefile b/src/libraries/libcommon/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ea6bd2331a8dbcb10c7cda79ceaa949efb321ebd
--- /dev/null
+++ b/src/libraries/libcommon/Makefile
@@ -0,0 +1,98 @@
+#  Makefile for LysKOM
+#
+###############################################################################
+#
+#  SPECIAL CONSIDERATIONS:
+#
+#  -  Requires GNU make.
+#  -  CC, OPTIMIZE-FLAGS and other make variables are passed down 
+#     in the environment.
+#  -  C compiler must be ANSI conformant.
+#
+###############################################################################
+#
+#  SPECIAL TARGETS:
+###############################################################################
+
+
+# Directories that you might want to override via the environment.
+
+ifndef TOPDIR
+TOPDIR = /usr/lyskom/src
+endif
+
+ifndef SCRIPTDIR
+SCRIPTDIR = $(TOPDIR)/scripts
+endif
+
+TARGET = -DCLIENT
+
+include $(SCRIPTDIR)/import.make
+
+
+# All directories that make should traverse to when doing clean etc.
+
+
+LIBOBJS = kom-errno.o misc-parser.o parser.o
+HDRS = misc-parser.h parser.h
+LIBRARIES = liblyskom-server.a liblyskom-client.a
+
+all: $(LIBRARIES)
+
+client-dir:
+	mkdir client-dir
+	ln -s `echo $(LIBOBJS) $(HDRS) dependencies| tr ' ' '\012' | \
+	sed 's/.o$$/.c/' | sed 's:^:\.\./:' ` client-dir/
+
+server-dir:
+	mkdir server-dir
+	ln -s `echo $(LIBOBJS) $(HDRS) dependencies| tr ' ' '\012' | \
+	sed 's/.o$$/.c/' | sed 's:^:\.\./:' ` server-dir/
+
+.PHONY: liblyskom-server.a
+liblyskom-server.a: server-dir
+	(cd server-dir; make -f ../Makefile ../$@ TARGET=-DSERVER)
+	ranlib $@
+
+
+../liblyskom-server.a: $(LIBOBJS) 
+	$(AR) $(ARFLAGS) $@ $?
+
+.PHONY: liblyskom-client.a
+liblyskom-client.a: client-dir
+	(cd client-dir; make -f ../Makefile ../$@ TARGET=-DCLIENT)
+	ranlib $@
+
+
+../liblyskom-client.a: $(LIBOBJS) 
+	$(AR) $(ARFLAGS) $@ $?
+
+
+clean:
+	$(RM) -r *.o core Distfile *~ client-dir server-dir $(LIBRARIES)
+
+install: all install-headers
+	(cd $(LIBDIR); $(RM)  $(LIBRARIES))
+	cp $(LIBRARIES) $(LIBDIR)
+	(cd $(LIBDIR); ranlib -t $(LIBRARIES))
+
+.PHONY: install-headers
+install-headers:
+	(cd $(INCLUDEDIR); $(RM) $(HDRS))
+	cp $(HDRS) $(INCLUDEDIR)
+
+tags:
+	etags -t $(INCLUDEDIR)/*.h *.[hc]	
+
+#rdist: clean
+#	echo "(/usr/local/src/2kom/common) -> (nanny.lysator.liu.se)" >Distfile
+#	echo "install;"						     >>Distfile
+#	rdist
+
+# Recreate the Makefile from Makefile
+
+include $(SCRIPTDIR)/Parallell-depend.make
+
+specials:;
+
+include dependencies
diff --git a/src/libraries/libcommon/README b/src/libraries/libcommon/README
new file mode 100644
index 0000000000000000000000000000000000000000..3f695f0c4329e9ff06bf83757ade10d6d5428cd8
--- /dev/null
+++ b/src/libraries/libcommon/README
@@ -0,0 +1,2 @@
+All utveckling i detta bibliotek sker p} LLL.
+H{r ligger saker som anv{nds b}de i servern och tty-klienten.
diff --git a/src/libraries/libcommon/dependencies b/src/libraries/libcommon/dependencies
new file mode 100644
index 0000000000000000000000000000000000000000..a88cc83be419c0c8c24983011a73bb0c9f1065db
--- /dev/null
+++ b/src/libraries/libcommon/dependencies
@@ -0,0 +1,6 @@
+kom-errno.o : kom-errno.c /users/ceder/gurka/lyskom/include/ansi/stdio.h \
+  /users/ceder/gurka/lyskom/include/config.h \
+  /users/ceder/gurka/lyskom/include/kom-errno.h \
+  /usr/gnu/lib/gcc-include/sys/types.h /usr/include/sys/types.h \
+  /usr/gnu/lib/gcc-include/sys/stdtypes.h /usr/include/sys/stdtypes.h \
+  /usr/include/sys/sysmacros.h 
diff --git a/src/libraries/libcommon/kom-errno.c b/src/libraries/libcommon/kom-errno.c
new file mode 100644
index 0000000000000000000000000000000000000000..16d9a2954d3585d76ab1d460dd3edf607ce0540b
--- /dev/null
+++ b/src/libraries/libcommon/kom-errno.c
@@ -0,0 +1,175 @@
+/*
+ * kom_errno.c
+ *
+ * Created by ceder 1990-05-13
+ *
+ */
+
+
+#include <stdio.h>
+
+#include <config.h>
+
+#include <kom-errno.h>
+
+
+Kom_err	kom_errno;
+
+/* Additional information about the error */
+u_long 	err_stat;
+
+/* Note that kom_errout is defined in config.h */
+
+void
+kom_perror(void)
+{
+    switch (kom_errno)
+    {
+    case  KOM_NO_ERROR:
+	fprintf (kom_errout, "Why am I called? There was no error!\n");
+	break;
+
+    case KOM_NOT_IMPL:
+	fprintf(kom_errout, "Not implemented yet\n");
+	break;
+	
+    case KOM_PWD:
+	fprintf(kom_errout, "Wrong/illegal password\n");
+	break;
+	
+    case KOM_LOGIN:
+	fprintf(kom_errout, "Not logged in.\n");
+	break;
+	
+    case KOM_LOGIN_DISALLOWED:
+	fprintf(kom_errout, "System is in 'singel-user mode'\n");
+	break;
+	
+    case KOM_CONF_ZERO:
+	fprintf(kom_errout, "Attempt to use conference number 0.\n");
+	break;
+	
+    case KOM_UNDEF_CONF:
+	fprintf(kom_errout, "Undefined or secret conference\n");
+	break;
+	
+    case KOM_UNDEF_PERS:
+	fprintf(kom_errout, "Undefined or secret person\n");
+	break;
+	
+    case KOM_ACCESS:
+	fprintf(kom_errout, "No 'read/write permission'\n");
+	break;
+
+    case KOM_SECRET_PUBLIC:
+	fprintf(kom_errout, "Cannot be secret and !rd_prot\n");
+	break;
+
+    case KOM_LETTER_BOX:
+	fprintf(kom_errout, "Cannot change letter_box flag\n");
+	break;
+
+    case KOM_PERM:
+	fprintf(kom_errout, "No permission\n");
+	break;
+	
+    case KOM_NOT_MEMBER:
+	fprintf(kom_errout, "Not member in conf\n");
+	break;
+
+    case KOM_NO_SUCH_TEXT:
+	fprintf(kom_errout, "No such global text as %ld or no access\n",
+			    err_stat);
+	break;
+	
+    case KOM_NO_SUCH_LOCAL_TEXT:
+	fprintf(kom_errout, "No such local text as %ld\n", err_stat);
+	break;
+
+    case KOM_INDEX_OUT_OF_RANGE:
+	fprintf(kom_errout, "Index out of range\n");
+	break;
+	
+    case KOM_BAD_NAME:
+	fprintf(kom_errout, "To short/long or contains illegal chars\n");
+	break;
+	
+    case KOM_CONF_EXISTS:
+	fprintf(kom_errout, "Already exists\n");
+	break;
+	
+    case KOM_PERS_EXISTS:
+	fprintf(kom_errout, "Already exists\n");
+	break;
+	
+    case KOM_LDB_ERR:
+	fprintf(kom_errout, "LDB_err\n");
+	break;
+	
+    case KOM_ILL_MISC:
+	fprintf(kom_errout, "Illegal misc field at %ld.\n", err_stat);
+	break;
+	
+    case KOM_ILLEGAL_INFO_TYPE:
+	fprintf(kom_errout, "Info_type parameter illegal. Client is buggy.\n");
+	break;
+	
+    case KOM_ALREADY_RECIPIENT:
+	fprintf(kom_errout, "Already recipient to this text.\n");
+	break;
+
+    case KOM_NOT_RECIPIENT:
+	fprintf(kom_errout, "Not recipient.\n");
+	break;
+	
+    case KOM_RECIPIENT_LIMIT:
+	fprintf(kom_errout, "Too many recipients.\n");
+	break;
+	
+    case KOM_COMM_LIMIT:
+	fprintf(kom_errout, "Too many comments.\n");
+	break;
+	
+    case KOM_FOOT_LIMIT:
+	fprintf(kom_errout, "Too many footnotes.\n");
+	break;
+	
+    case KOM_NOT_AUTHOR:
+	fprintf(kom_errout, "Only the author may add footnotes.\n");
+	break;
+
+    case  KOM_OBSOLETE:
+	fprintf (kom_errout, "Servern {r inte kompatibel med mig.\n");
+	break;
+
+    case  KOM_LONG_STR:
+	fprintf (kom_errout, "F|r l}ng str{ng.\n");
+	break;
+
+    case  KOM_NO_CONNECT:
+	fprintf (kom_errout, "Kan ej f} kontakt med servern.\n");
+	break;
+
+    case  KOM_OUT_OF_MEMORY:
+	fprintf (kom_errout, "Dumma Emacs! Fattar du inte att du inte ska "
+		 "bryta en\nrad inuti en str{ng bara f|r att man anv{nder "
+		 "} och {???\n");
+	break;
+
+    case  KOM_SERVER_IS_CRAZY:
+	fprintf (kom_errout, "Hmm, jag tror servern har b|rjat tala i "
+		 "tungom}l...\n");
+	break;
+
+    case  KOM_CLIENT_IS_CRAZY:
+	fprintf (kom_errout, "Hoppschan. Jag har vischt b|rjat schluddra.\n");
+	break;
+	
+#ifndef COMPILE_CHECKS
+    default:
+	fprintf(kom_errout, "Unknown error %d\n", kom_errno);
+	break;
+#endif
+    }
+}
+
diff --git a/src/libraries/libcommon/misc-parser.c b/src/libraries/libcommon/misc-parser.c
new file mode 100644
index 0000000000000000000000000000000000000000..e32561b500373c0c374c0e6a4e7024b73b061008
--- /dev/null
+++ b/src/libraries/libcommon/misc-parser.c
@@ -0,0 +1,182 @@
+/*
+ *  misc-parser.c
+ *		Parse a list of misc-items for LysKOM texts.
+ *
+ *
+ *  Copyright (C) 1990	Lysator Computer Club,
+ *			Linkoping University,  Sweden
+ *
+ *  Everyone is granted permission to copy, modify and redistribute
+ *  this code, provided the people they give it to can.
+ *
+ *
+ *  Author:	Thomas Bellman
+ *		Lysator Computer Club
+ *		Linkoping University
+ *		Sweden
+ *
+ *  email:	Bellman@Lysator.LiU.SE
+ *
+ *
+ *  Any opinions expressed in this code are the author's PERSONAL opinions,
+ *  and does NOT, repeat NOT, represent any official standpoint of Lysator,
+ *  even if so stated.
+ */
+
+
+
+#include "misc-parser.h"
+
+#define EXPORT
+
+
+/*
+ *  Return TRUE if the next misc-item exist, and it is of type
+ *  MTYPE, FALSE otherwise.  Can only be used within the function
+ *  parse_next_misc().
+ */
+#define NEXT_IS(mtype)						\
+    (*info < stop_pointer && (*info)->type == (mtype))
+
+
+#define BARF	{  result.type = m_error;  return  result;  }
+
+
+/*
+ *  Parse out a "group" of misc-items from a list of them pointed
+ *  to by *INFO.  *STOP_POINTER must point to the item directly
+ *  after the last in the list.  **INFO will be incremented to
+ *  point to the item after the recently parsed out group.  The
+ *  return value will have the TYPE field set to 'm_end_of_list'
+ *  when the end of the list has been reached.
+ */
+EXPORT  Misc_info_group
+parse_next_misc (const Misc_info	** info,
+		 const Misc_info	 * stop_pointer)
+
+{
+    Misc_info_group	  result;
+
+    
+	
+    /* Clear the 'result' struct */
+    result.type = m_error;
+    result.recipient = 0;
+    result.cc_recipient = 0;
+    result.local_no = 0;
+    result.is_received = FALSE;
+    result.comment_to = 0;
+    result.commented_in = 0;
+    result.footnote_to = 0;
+    result.footnoted_in = 0;
+    result.sender = 0;
+    result.is_sent = 0;
+
+
+    if (*info >= stop_pointer)
+    {
+	result.type = m_end_of_list;
+	return  result;
+    }
+
+    
+    /* Now, do the real work... */
+    switch ((*info)->type)
+    {
+    case  recpt:	/* These two are so similar that they can */
+    case  cc_recpt:	/* Be handled in the same clause	  */
+	if ((*info)->type == recpt)
+	{
+	    result.type = m_recpt;
+	    result.recipient = (*(*info)++).datum.recipient;
+	}
+	else
+	{
+	    result.type = m_cc_recpt;
+	    result.cc_recipient = (*(*info)++).datum.cc_recipient;
+	}
+	
+	/* There should follow a 'Local no', but check nevertheless */
+	if (! NEXT_IS (loc_no))
+	    { BARF }
+	else
+	    result.local_no = (*(*info)++).datum.local_no;
+
+	if (NEXT_IS (rec_time))
+	{
+	    result.is_received = TRUE;
+	    result.received_at = (*(*info)++).datum.received_at;
+	}
+
+	if (NEXT_IS (sent_by))
+	{
+	    result.sender = (*(*info)++).datum.sender;
+	    /* There _should_ be a 'sent_at' here... */
+	    if (! NEXT_IS (sent_at))
+		{ BARF }
+	    /* Let the following if clause insert the 'sent_at' data. */
+	}
+	if (NEXT_IS (sent_at))
+	{
+	    result.is_sent = TRUE;
+	    result.sent_at = (*(*info)++).datum.sent_at;
+	}
+
+	break;
+
+
+    case  comm_to:
+	result.type = m_comm_to;
+	result.comment_to = (*(*info)++).datum.comment_to;
+
+	if (NEXT_IS (sent_by))
+	{
+	    result.sender = (*(*info)++).datum.sender;
+	    /* There _should_ be a 'sent_at' here. */
+	    if (! NEXT_IS (sent_at))
+		{ BARF }
+	    /* Let the following if clause insert the 'sent_at' data. */
+	}
+	if (NEXT_IS (sent_at))
+	{
+	    result.is_sent = TRUE;
+	    result.sent_at = (*(*info)++).datum.sent_at;
+	}
+
+	break;
+
+
+    case  footn_to:
+	result.type = m_footn_to;
+	result.footnote_to = (*(*info)++).datum.footnote_to;
+
+	if (NEXT_IS (sent_at))
+	{
+	    result.is_sent = TRUE;
+	    result.sent_at = (*(*info)++).datum.sent_at;
+	}
+
+	break;
+
+
+    case  comm_in:
+	result.type = m_comm_in;
+	result.commented_in = (*(*info)++).datum.commented_in;
+	break;
+
+
+    case  footn_in:
+	result.type = m_footn_in;
+	result.footnoted_in = (*(*info)++).datum.footnoted_in;
+	break;
+
+
+#ifndef COMPILE_CHECKS
+    default:
+	result.type = m_error;
+	break;
+#endif
+    }
+
+    return  result;
+}
diff --git a/src/libraries/libcommon/misc-parser.h b/src/libraries/libcommon/misc-parser.h
new file mode 100644
index 0000000000000000000000000000000000000000..f5b1b18796e4e71d9482d88f6ffb9c20c711d949
--- /dev/null
+++ b/src/libraries/libcommon/misc-parser.h
@@ -0,0 +1,76 @@
+/*
+ *  misc-parser.h
+ *		Parse a list of "misc-item":s for a text in LysKOM
+ *
+ *
+ *  Copyright (C) 1990	Lysator Computer Club,
+ *			Linkoping University,  Sweden
+ *
+ *  Everyone is granted permission to copy, modify and redistribute
+ *  this code, provided the people they give it to can.
+ *
+ *
+ *  Author:	Thomas Bellman
+ *		Lysator Computer Club
+ *		Linkoping University
+ *		Sweden
+ *
+ *  email:	Bellman@Lysator.LiU.SE
+ */
+
+
+
+#include <kom-types.h>
+
+
+
+typedef  enum  {
+	m_recpt,
+	m_cc_recpt,
+	m_comm_to,
+	m_comm_in,
+	m_footn_to,
+	m_footn_in,
+	m_end_of_list,	/* End of list reached	*/
+	m_error		/* Bad misc-items found */
+}  Misc_struct_type;
+
+
+typedef  struct  {
+	Misc_struct_type	type;
+	Conf_no			recipient;
+	Conf_no			cc_recipient;
+	Local_text_no		local_no;
+	Time			received_at;
+	Text_no			comment_to;
+	Text_no			commented_in;
+	Text_no			footnote_to;
+	Text_no			footnoted_in;
+	Pers_no			sender;
+	Time			sent_at;
+	Bool			is_received;
+	Bool			is_sent;
+}  Misc_info_group;
+
+
+
+#define is_received(mstruct)	((mstruct).is_received != FALSE)
+#define is_sent_by(mstruct)	((mstruct).sender != 0)
+#define is_sent(mstruct)	((mstruct).is_sent != FALSE)
+
+
+/*
+ *  Parse out a "group" of misc-items from a list of them pointed
+ *  to by *INFO.  *STOP_POINTER must point to the item directly
+ *  after the last in the list.  **INFO will be incremented to
+ *  point to the item after the recently parsed out group.  The
+ *  return value will have the TYPE field set to 'm_end_of_list'
+ *  when the end of the list has been reached.
+ *
+ *  If the has a bad format, the TYPE field will be 'm_error',
+ *  and **INFO_POINTER will point to the item before the bad (or
+ *  missing) item.
+ */
+extern  Misc_info_group
+parse_next_misc (const Misc_info	** info_pointer,
+		 const Misc_info	 * stop_pointer);
diff --git a/src/libraries/libcommon/parser.c b/src/libraries/libcommon/parser.c
new file mode 100644
index 0000000000000000000000000000000000000000..fd445f717c840aa2c5b723323bd1c10ecf488cd0
--- /dev/null
+++ b/src/libraries/libcommon/parser.c
@@ -0,0 +1,418 @@
+/*
+ *  client/parser.c  --  Routines to parse commands
+ *
+ *
+ *  Copyright (C) 1990	Lysator Computer Club,
+ *			Linkoping University,  Sweden
+ *
+ *  Everyone is granted permission to copy, modify and redistribute
+ *  this code, provided the people they give it to can.
+ *
+ *
+ *  Author:	Thomas Bellman
+ *		Lysator Computer Club
+ *		Linkoping University
+ *		Sweden
+ *
+ *  email:	Bellman@Lysator.LiU.SE
+ *
+ *
+ *  Any opinions expressed in this code are the author's PERSONAL opinions,
+ *  and does NOT, repeat NOT, represent any official standpoint of Lysator,
+ *  even if so stated.
+ */
+
+
+
+#include <stddef.h>
+
+#include <s-string.h>
+#include <s-collat-tabs.h>
+
+#include <misc-types.h>
+
+#include "parser.h"
+
+
+#define EXPORT			/* To emphasize export of objects */
+#define PRIVATE		static
+
+
+#if defined (SERVER)
+#	include <server/smalloc.h>
+#	define	MALLOC	smalloc
+#	define	REALLOC	srealloc
+#	define	FREE	sfree
+#elif defined (CLIENT)
+#	include	<zmalloc.h>
+#	define	MALLOC	zmalloc
+#	define	REALLOC	zrealloc
+#	define	FREE	zfree
+#else
+#	include	<malloc.h>
+#	define  MALLOC  malloc
+#	define  REALLOC realloc
+#	define  FREE	free
+#endif
+
+
+
+/*
+ *  Remove paranthesized "expressions" from the string STR.
+ *  E g if STR is "Foo (Bar (vfslck)) Gazonk", then it is reduced
+ *  to "Foo _ Gazonk", where '_' is the character in SEPARATOR.
+ *  Superflous close paranthesis are disregarded.
+ */
+EXPORT  void
+remove_parenthesis (String	* str,
+		    char	  blanker)
+
+{
+    String_size		  i;	/* Index in loop */
+    int			  nesting_depth;
+    
+
+    /* Match parantheses.  Remove text inside parantheses. */
+    nesting_depth = 0;
+    for ( i = 0 ;  i < s_strlen(*str) ;  i++ )
+    {
+	if (str->string[i] == '(')
+	    nesting_depth++;
+
+	if (str->string[i] == ')')
+	{
+	    nesting_depth--;
+	    str->string[i] = blanker;		/* Don't forget that... */
+	    if (nesting_depth < 0)
+		nesting_depth = 0;
+	}
+
+	if (nesting_depth > 0)
+	    str->string[i] = blanker;
+    }
+
+    return;
+}
+
+
+
+
+/*
+ *  Convert a String to a list of tokens (words).  This list is
+ *  easier to parse than a string (since the string would have to
+ *  be tokenized first anyway).  The last entry is EMPTY_STRING.
+ *  Returns NULL if any error occured (couldn't allocate memory).
+ */
+EXPORT  Parse_token *
+tokenize (const String	  source,
+	  const String	  separators)
+
+{
+    Parse_token		* tokens		= NULL;
+    Parse_token		* temp_list;		/* Temporary */
+    String		  work_string		= EMPTY_STRING;
+    String		  a_token;
+    String		  a_temp_token;		/* More temporaries... */
+    int			  no_of_tokens;
+    int			  list_size;
+    String_size		  pos_in_string;
+    const int		  chunk_size		= 10;
+
+
+
+    /* Copy string to working area */
+    if (s_strcpy(&work_string, source) == FAILURE)
+    {
+	/* Couldn't allocate space for temporary string. */
+	return  NULL;
+    }
+
+    remove_parenthesis (&work_string, separators.string[0]);
+
+    no_of_tokens = 0;
+    list_size = 0;
+    pos_in_string = 0;
+
+    while ( ! s_empty(a_token
+		      = s_strtok (work_string, &pos_in_string,
+				  separators)))
+    {
+	/* Make the token point into the original source string
+	 * instead of the working string			*/
+	a_temp_token = s_fsubstr (source,
+				  pos_in_string - s_strlen (a_token),
+				  pos_in_string - 1);
+#if 0
+// *	/* Get a real copy of the word */
+// *	a_temp_token = EMPTY_STRING;
+// *	if (s_strcpy(&a_temp_token, a_token) == FAILURE)
+// *	{
+// *	    /* Grumble... */
+// *	    free_tokens (tokens);
+// *	    s_clear(&work_string);
+// *	    return  NULL;
+// *	}
+#endif
+
+	/* Is the allocated list large enough? */
+	if (no_of_tokens++ >= list_size)
+	{
+	    /* No, allocate more */
+	    temp_list = REALLOC (tokens, (list_size += chunk_size)
+					  * sizeof(Parse_token));
+	    if (temp_list == NULL)
+	    {
+		/* Sigh. Out of memory. */
+		free_tokens (tokens);
+		s_clear (&work_string);
+		return  NULL;
+	    }
+	    else
+	    {
+		/* OK, we got what we asked for */
+		tokens = temp_list;
+	    }
+	}
+
+	/* Insert the new token in the list */
+	tokens [no_of_tokens-1].word = a_temp_token;
+	tokens [no_of_tokens-1].start_in_string =
+	    pos_in_string - s_strlen(a_temp_token);
+    }
+
+    s_clear (&work_string);
+
+    /* Is there room in the list for the 'stop' element? */
+    if (list_size <= no_of_tokens)
+    {
+	/* No, get some more memory */
+	temp_list = REALLOC (tokens, (++list_size) * sizeof(Parse_token));
+	if (temp_list == NULL)
+	{
+	    /* Sigh. Out of memory. */
+	    free_tokens (tokens);
+	    return  NULL;
+	}
+	else
+	{
+	    /* OK, we got what we asked for */
+	    tokens = temp_list;
+	}
+    }
+
+    /* OK, insert the 'stop' element. */
+    tokens [no_of_tokens].word = EMPTY_STRING;
+    tokens [no_of_tokens].start_in_string = END_OF_STRING;
+
+    return  tokens;
+}
+
+
+
+
+/*
+ *  Count the number of tokens (words) in TOKEN_LIST.  Used to
+ *  set the NUMBER_OF_WORDS field in a 'Matching_info' object.
+ */
+extern  int
+count_words (const Parse_token   * token_list)
+
+{
+    int		no_of_words;
+
+    no_of_words = 0;
+    while (! s_empty(token_list++ -> word))
+	no_of_words++;
+
+    return  no_of_words;
+}
+
+
+
+
+/*
+ *  Free the list of tokens (// and the strings they are pointing to //).
+ *  Free:ing NULL is a no-op.
+ */
+EXPORT  void
+free_tokens (Parse_token   * token_list)
+
+{
+    if (token_list != NULL)
+    {
+	FREE (token_list);
+    }
+}
+
+
+
+
+/*
+ *  Returns the number of the first word of SOURCE that does
+ *  not match PATTERN.  A word "foo" in SOURCE matches "foobar"
+ *  in PATTERN, but not vice versa.
+ */
+EXPORT  int
+match (Parse_token	* source,
+       Parse_token	* pattern,
+       char		  collat_tab [ COLLAT_TAB_SIZE ] )
+
+{
+    int		word_no;
+
+    word_no = 0;
+    while (   (! s_streq (pattern[word_no].word, EMPTY_STRING))
+	   && (! s_streq (source[word_no].word, EMPTY_STRING))
+	   && (s_usr_strhead (source[word_no].word,
+			      pattern[word_no].word,
+			      collat_tab)))
+    {
+	word_no++;
+    }
+
+    return  word_no;
+}
+
+
+
+
+/*
+ *  Searches for a matching string in the table 'match_table'.
+ *  Some weird pattern matching is done.
+ *  parse().no_of_matches is -1 if an error occured (out of
+ *  memory).
+ *
+ *  What?  You want a description of how it matches?  Forget it!   BUG!
+ *  Try for yourself, and you'll find out!
+ */
+
+EXPORT  Parse_info
+parse (String		  source_string,
+       Matching_info	* match_table,
+       Bool		  allow_trailing_words,
+       Bool		  number_of_words_must_match,
+       String		  separators,
+       char		  collat_tab [ COLLAT_TAB_SIZE ] )
+
+{
+    Parse_info		  answer;
+    int			* temp_indexes;
+    int			  index;
+    int			  size_of_index_list;
+    Parse_token		* source_words;
+    int			  no_of_source_words;
+    int			  first_non_matching;
+    int			  best_match;
+    int			  highest_priority;
+
+    const int		  chunk_size	= 20;
+
+    
+
+    source_words = tokenize(source_string, separators);
+    if (source_words == NULL)
+    {
+	answer.no_of_matches = -1;
+	return  answer;
+    }
+
+    no_of_source_words = count_words(source_words);
+
+    /* Check if SOURCE_STRING was empty of words */
+    if (no_of_source_words == 0)
+    {
+	answer.indexes = MALLOC (1 * sizeof(int));
+	if (answer.indexes == NULL)
+	{
+	    /* Gahh! Someone eats memory! */
+	    answer.no_of_matches = -1;
+	    return  answer;
+	}
+	answer.indexes[0] = -1;
+	answer.no_of_matches = 1;
+	return  answer;
+    }
+
+
+    answer.no_of_matches = 0;
+    answer.indexes = NULL;
+    size_of_index_list = 0;
+    index = -1;
+    best_match = 1;			/* At least one word */
+    highest_priority = 1;
+    while (! s_empty (match_table[++index].name))
+    {
+	first_non_matching = match (source_words, match_table[index].tokens,
+				    collat_tab);
+
+	if (   (    ! allow_trailing_words
+		&&  first_non_matching < no_of_source_words)
+	    || (    number_of_words_must_match
+		&&  first_non_matching != count_words (match_table[index].tokens)))
+	{
+	    continue;			/* Try next entry in table */
+	}
+
+	if (first_non_matching < best_match)
+	    continue;			/* Try next entry in table */
+
+	if (    first_non_matching == best_match
+	    &&  highest_priority > match_table[index].priority)
+	    continue;
+
+	/*  If we reach this far, then we have a match that should be
+	 *  inserted in the table.  But if it is a better match than any
+	 *  before, then we clear the table first.			*/
+	if (    first_non_matching > best_match
+	    ||  match_table[index].priority > highest_priority)
+	{
+	    highest_priority = match_table[index].priority;
+	    best_match = first_non_matching;
+	    answer.no_of_matches = 0;
+	}
+
+	/* Insert the match in the table */
+
+	/* Increase the size if necessary */
+	if (answer.no_of_matches >= size_of_index_list)
+	{
+	    temp_indexes = REALLOC (answer.indexes,
+				    (size_of_index_list += chunk_size)
+				    * sizeof(answer.indexes));
+	    if (temp_indexes == NULL)
+	    {
+		/* Grumble!  Out of memory. */
+		FREE (answer.indexes);
+		answer.no_of_matches = -1;
+		return  answer;
+	    }
+
+	    answer.indexes = temp_indexes;
+	}
+
+	highest_priority = match_table [index].priority;
+	answer.indexes[answer.no_of_matches] = index;
+	/*  Find out where the arguments start.
+	 *  This value should not be used if more than one match is found.
+	 */
+	/* Special hack needed if no parameters */
+	if (s_empty (source_words [first_non_matching].word))
+	    answer.arguments = EMPTY_STRING;
+	else
+	    answer.arguments =
+		s_fsubstr(source_string,
+			  source_words[first_non_matching].
+			  start_in_string,
+			  END_OF_STRING);
+	answer.no_of_matches++;
+    }
+
+    /* All matches found by now */
+
+    /* Strip trailing blanks from the argument */
+    if (answer.no_of_matches == 1)
+	answer.arguments = s_strip_trailing (answer.arguments, separators);
+
+    return  answer;
+
+}   /* END: parse() */
diff --git a/src/libraries/libcommon/parser.h b/src/libraries/libcommon/parser.h
new file mode 100644
index 0000000000000000000000000000000000000000..922bb4416e9fe7ba4a42295f4ef54c3999e3aaff
--- /dev/null
+++ b/src/libraries/libcommon/parser.h
@@ -0,0 +1,147 @@
+/*
+ *  client/parser.h  --  Header file for LysKOM command parsing routines
+ *
+ *
+ *  Copyright (C) 1990	Lysator Computer Club,
+ *			Linkoping University,  Sweden
+ *
+ *  Everyone is granted permission to copy, modify and redistribute
+ *  this code, provided the people they give it to can.
+ *
+ *
+ *  Author:	Thomas Bellman
+ *		Lysator Computer Club
+ *		Linkoping University
+ *		Sweden
+ *
+ *  e-mail:	Bellman@Lysator.LiU.SE
+ */
+
+
+#ifndef  PARSER_H_ALREADY_INCLUDED__
+#define  PARSER_H_ALREADY_INCLUDED__
+
+
+#include <misc-types.h>
+#include <s-string.h>
+#include <s-collat-tabs.h>
+
+
+
+/*
+ *  Information about one word.  If the field 'word' is
+ *  EMPTY_STRING, then the struct is considered to be the last
+ *  in an "array".		BUG: "array" is wrong word
+ */
+typedef	struct {
+	String		word;
+	String_size	start_in_string;
+} Parse_token;
+
+
+/*
+ *  Information about one string to match against during parse().
+ *  A list of these should be passed to parse() as the CMD_TABLE
+ *  parameter.  The 'tokens' field is set by doing
+ *	I.tokens = tokenize(I.name, Separators);
+ */
+typedef	struct matching_info {
+	String		   name;	/* Name to match against */
+	Parse_token	 * tokens;	/* Tokenized version of name */
+	int		   priority;	/* Normally in interval 1..15 */
+} Matching_info;
+
+
+
+/*
+ *  Remove paranthesized "expressions" from the string STR by
+ *  replacing them with the character SEPARATOR.
+ *  Superflous close paranthesis are disregarded.
+ */
+extern  void
+remove_parenthesis (String	* str,
+		    char	  separator);
+
+
+
+/*
+ *  Convert a String to a list of tokens (words).  This list is
+ *  easier to parse than a string (since the string would have to
+ *  be tokenized first anyway).
+ *  Returns NULL if any error occured (couldn't allocate memory).
+ */
+extern  Parse_token *
+tokenize (const String	  source,
+	  const String	  separators);
+
+
+
+/*
+ *  Count the number of tokens (words) in TOKEN_LIST.  Used to
+ *  set the NUMBER_OF_WORDS field in a 'Matching_info' object.
+ */
+extern  int
+count_words (const Parse_token   * token_list);
+
+
+
+/*
+ *  Free the list of tokens (// and the strings they are pointing to //).
+ *  Free:ing NULL is a no-op.
+ */
+extern  void
+free_tokens (Parse_token   * token_list);
+
+
+
+/*
+ *  Returns the number of the first word of SOURCE that does
+ *  not match PATTERN.  A word "foo" in SOURCE matches "foobar"
+ *  in PATTERN, but not vice versa.
+ */
+extern  int
+match (Parse_token	* source,
+       Parse_token	* pattern,
+       char		  collat_tab [ COLLAT_TAB_SIZE ] );
+
+
+
+/*
+ *  Contains the result of a parse().
+ */
+typedef struct {
+	int	  no_of_matches;	/* Number of found matches */
+	int	* indexes;		/* List of indexes */
+	String	  arguments;		/* The arguments... */
+} Parse_info;
+
+
+/*
+ *  Searches for a matching string in the table 'match_table'.
+ *  Some weird pattern matching is done.  The 'ARGUMENTS' field of
+ *  the result is not a separate String, but points into
+ *  SOURCE_STRING.
+ *  If ALLOW_TRAILING_WORDS is false, then SOURCE_STRING may not
+ *  contain any trailing words.
+ *  If NUMBER_OF_WORDS_MUST_MATCH is true, then all the words
+ *  in from the entry in MATCH_TABLE must be present (possibly
+ *  abbrevated) in SOURCE_STRING.
+ *  parse().no_of_matches is -1 if an error occured (out of
+ *  memory).
+ *  If SOURCE_STRING is empty, i e does not contain any words,
+ *  the 'no_of_matches' field is 1, and indexes[0] is -1.
+ *
+ *  What?  You want a description of how it matches?  Forget it!  BUG!
+ *  Try for yourself, and you'll find out!
+ */
+
+extern  Parse_info
+parse (String		  source_string,
+       Matching_info	* match_table,
+       Bool		  allow_trailing_words,
+       Bool		  number_of_words_must_match,
+       String		  separators,
+       char		  collat_tab [ COLLAT_TAB_SIZE ] );
+
+
+#endif	/*  PARSER_H_ALREADY_INCLUDED__  */
diff --git a/src/libraries/libmisc/Makefile b/src/libraries/libmisc/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..cba454931e4816ba31a4457181930112b07c98c0
--- /dev/null
+++ b/src/libraries/libmisc/Makefile
@@ -0,0 +1,76 @@
+#  Makefile for LysKOM
+#
+###############################################################################
+#
+#  SPECIAL CONSIDERATIONS:
+#
+#  -  Requires GNU make.
+#  -  CC, OPTIMIZE-FLAGS and other make variables are passed down 
+#     in the environment.
+#  -  C compiler must be ANSI conformant.
+#
+###############################################################################
+#
+#  SPECIAL TARGETS:
+###############################################################################
+
+# Directories that you might want to override via the environment.
+
+ifndef TOPDIR
+TOPDIR = /usr/lyskom/src
+endif
+
+ifndef SCRIPTDIR
+SCRIPTDIR = $(TOPDIR)/scripts
+endif
+
+TARGET = -DCLIENT
+
+include $(SCRIPTDIR)/import.make
+
+
+# All directories that make should traverse to when doing clean etc.
+
+
+LIBNAME = libmisc.a
+
+LIBOBJS = pom.o s-collat-tabs.o s-string.o zmalloc.o
+
+INSTALL-HDRS = pom.h s-collat-tabs.h s-string.h zmalloc.h
+
+#OBJECTS = numlist.o numlist2.o pom.o s-collat-tabs.o s-string.o \
+#	testnumlist.o zmalloc.o 
+
+all:	$(LIBNAME)
+
+$(LIBNAME): $(LIBOBJS)
+	ar r $(LIBNAME) $?
+	ranlib $(LIBNAME)
+
+install: $(LIBNAME) install-headers
+	$(RM) $(LIBDIR)/$(LIBNAME)
+	cp $(LIBNAME) $(LIBDIR)/$(LIBNAME)
+	ranlib -t $(LIBDIR)/$(LIBNAME)
+
+install-headers:
+	(cd $(INCLUDEDIR); $(RM) $(INSTALL-HDRS))
+	cp $(INSTALL-HDRS) $(INCLUDEDIR)/
+
+testnumlist: testnumlist.o numlist.o
+	$(CC) -o testnumlist testnumlist.o numlist.o
+
+
+clean:
+	rm -vf ${OBJECTS} *~ core temp-Makefile Distfile *.o
+
+
+# Recreate the Makefile
+include $(SCRIPTDIR)/Parallell-depend.make
+
+
+tags:
+	etags -t $(INCLUDEDIR)/*.h *.[hc]	
+
+specials:;
+
+include dependencies
diff --git a/src/libraries/libmisc/README b/src/libraries/libmisc/README
new file mode 100644
index 0000000000000000000000000000000000000000..922de6f141ccd00be6669372c76c34856d027ba6
--- /dev/null
+++ b/src/libraries/libmisc/README
@@ -0,0 +1,2 @@
+All utveckling i detta bibliotek sker p} LLL.
+H{r ligger includefiler som {r gemensamma f|r server och klient.
diff --git a/src/libraries/libmisc/dependencies b/src/libraries/libmisc/dependencies
new file mode 100644
index 0000000000000000000000000000000000000000..370b62eafdad342cec263d8289646ef942f43deb
--- /dev/null
+++ b/src/libraries/libmisc/dependencies
@@ -0,0 +1,15 @@
+numlist.o : numlist.c /users/ceder/gurka/lyskom/include/ansi/stdio.h \
+  /users/ceder/gurka/lyskom/include/ansi/stdlib.h \
+  /users/ceder/gurka/lyskom/include/ansi/stddef.h \
+  /usr/gnu/lib/gcc-include/sys/types.h /usr/include/sys/types.h \
+  /usr/gnu/lib/gcc-include/sys/stdtypes.h /usr/include/sys/stdtypes.h \
+  /usr/include/sys/sysmacros.h /users/ceder/gurka/lyskom/include/misc-types.h \
+  numlist.h 
+testnumlist.o : testnumlist.c \
+  /users/ceder/gurka/lyskom/include/ansi/stdio.h \
+  /users/ceder/gurka/lyskom/include/ansi/stdlib.h \
+  /users/ceder/gurka/lyskom/include/ansi/stddef.h \
+  /usr/gnu/lib/gcc-include/sys/types.h /usr/include/sys/types.h \
+  /usr/gnu/lib/gcc-include/sys/stdtypes.h /usr/include/sys/stdtypes.h \
+  /usr/include/sys/sysmacros.h /users/ceder/gurka/lyskom/include/misc-types.h \
+  numlist.h 
diff --git a/src/libraries/libmisc/numlist.c b/src/libraries/libmisc/numlist.c
new file mode 100644
index 0000000000000000000000000000000000000000..fe5caa4ec988f6ed5701c15dcf966ed320bf53d6
--- /dev/null
+++ b/src/libraries/libmisc/numlist.c
@@ -0,0 +1,615 @@
+/*
+ * File: numlist.c
+ * 
+ * A numlist is supposed to be an efficient implementation of 
+ * a list of numbers. One of the big features is intervals.
+ *
+ * Author: Inge Wallin
+ *
+ * Three plus signs (+++) denote places where more work may be needed.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <misc-types.h>
+
+#include "numlist.h"
+
+
+/* ================================================================ */
+/*                        Some useful macros                        */
+
+
+#define IS_INTERVAL_START(x)  (((x) & INTERVAL_MASK) == INTERVAL_START)
+#define IS_INTERVAL_END(x)    (((x) & INTERVAL_MASK) == INTERVAL_END)
+
+#define NUMBER_OF(x)          ((x) & NUMBER_MASK)
+
+#define MAKE_INTERVAL_START(x)  ((x) | INTERVAL_START)
+#define MAKE_INTERVAL_END(x)    ((x) | INTERVAL_END)
+
+
+/* ================================================================ */
+/*                           Numlist_node                           */
+
+
+static Numlist_node *
+numlist_node_create()
+{
+    Numlist_node  * nln;
+
+    nln = (Numlist_node *) malloc(sizeof(Numlist_node));
+    if (nln == NULL) {
+	fprintf(stderr, "Virtual memory exhausted");
+	abort();
+    }
+
+    nln->num_numbers = 0;
+    nln->next = NULL;
+    
+    return nln;
+}
+
+
+
+/*
+ * Insert the number NUM at index INDEX in the numlist node NLN.
+ * All numbers starting at index INDEX and subsequent are moved
+ * one step back.
+ */
+
+static void
+numlist_node_insert_num(Numlist_node  * nln,
+			int             index,
+			u_long          num)
+{
+    int   i;
+
+    for (i = nln->num_numbers; i > index; --i)
+	nln->numbers[i] = nln->numbers[i - 1];
+    nln->numbers[index] = num;
+    ++nln->num_numbers;
+}
+
+
+
+/*
+ * Delete the number with index INDEX from the node NODE. If this
+ * was the last number in the node, delete the entire node. PREV_NODE
+ * points to the node just before NODE and NL is the Numlist they
+ * both belong to.
+ */
+
+static void
+numlist_node_del_num(Numlist       * nl,
+		     Numlist_node  * node,
+		     Numlist_node  * prev_node,
+		     int             index)
+{
+    int   i;
+
+    /* Delete the number from this node. */
+    for (i = index; i < node->num_numbers - 1; ++i)
+	node->numbers[i] = node->numbers[i + 1];
+    --(node->num_numbers);
+
+    /* If this node became empty, delete it and fix all pointers. */
+    if (node->num_numbers == 0) {
+	if (prev_node == NULL) {
+	    nl->first = node->next;
+	    if (nl->first == NULL)
+		nl->last = NULL;
+	} else {
+	    prev_node->next = node->next;
+	    if (nl->last == node)
+		nl->last = prev_node;
+	}
+	free(node);
+    }
+}
+
+
+
+/*
+ * Split the node NODE into two nodes.  The numbers starting with the
+ * index INDEX is put in the second (new) node and the other remain
+ * in the old one.  NL points to the Numlist the node belongs to.
+ */
+
+static void
+numlist_node_split(Numlist       * nl,
+		   Numlist_node  * node,
+		   int             index)
+{
+    Numlist_node  * new_node;
+    int             i;
+
+    new_node = numlist_node_create();
+    new_node->next = node->next;
+    node->next = new_node;
+
+    for (i = index; i < node->num_numbers; ++i)
+	new_node->numbers[i - index] = node->numbers[i];
+
+    new_node->num_numbers = node->num_numbers - index;
+    node->num_numbers = index;
+
+    if (nl->last == node)
+	nl->last = new_node;
+}
+
+
+/* ================================================================ */
+/*                              Numlist                             */
+
+
+/*
+ * Create a new, empty Numlist and return a pointer to it.
+ */
+
+Numlist *
+numlist_create()
+{
+    Numlist  * nl;
+
+    nl = (Numlist *) malloc(sizeof(Numlist));
+    if (nl == NULL) {
+	fprintf(stderr, "Virtual memory exhausted");
+	abort();
+    }
+
+    nl->first = NULL;
+    nl->last = NULL;
+    nl->last_num = NUMLIST_NO_NUMBER;
+    
+    return nl;
+}
+
+
+
+/*
+ * Return TRUE if the Numlist NL is empty, otherwise return FALSE.
+ */
+
+Bool
+numlist_isempty(Numlist *nl)
+{
+    return nl->first == NULL;
+}
+
+
+
+/*
+ * return TRUE if NUM is a member of the numlist NL, otherwise
+ * return FALSE.
+ */
+
+Bool
+numlist_member(Numlist *nl, u_long num)
+{
+    Numlist_node  * nln;
+    u_long          last;
+    int             i;
+
+    /* If num is bigger than the last number, return FALSE immediately. */
+    last = numlist_last(nl);
+    if (last == NUMLIST_ERR || num > last)
+	return FALSE;
+
+    nln = nl->first;
+    while (nln != NULL) {
+	if (num <= NUMBER_OF(nln->numbers[nln->num_numbers - 1])) {
+	    for (i = 0; i < nln->num_numbers; ++i) {
+
+		/* Check if we can abort the loop. */
+		if (num < NUMBER_OF(nln->numbers[i]))
+		    return FALSE;
+
+		/* Take care of an interval. */
+		if (IS_INTERVAL_START(nln->numbers[i])) {
+		    if (NUMBER_OF(nln->numbers[i]) <= num
+			&& num <= NUMBER_OF(nln->numbers[i + 1]))
+			return TRUE;
+		    ++i;
+		} else {
+		    if (nln->numbers[i] == num)
+			return TRUE;
+		}
+	    }
+	}
+
+	nln = nln->next;
+    }
+    return FALSE;
+}
+
+
+
+/*
+ * Return the first number in the numlist NL. Also store a pointer
+ * to the first node, the index to this particular cell and the
+ * first number itself in the numlist. This makes it more efficient
+ * to get the next number later.
+ *
+ * If NL is empty, return the constant NUMLIST_ERR.
+ */
+
+u_long
+numlist_first(Numlist *nl)
+{
+    u_long   first;
+
+    if (numlist_isempty(nl)) {
+	return NUMLIST_ERR;
+    } else {
+	first = NUMBER_OF(nl->first->numbers[0]);
+	nl->last_num = first;
+	nl->last_node = nl->first;
+	nl->last_index = 0;
+
+	return first;
+    }
+}
+
+
+
+/*
+ * Return the last number in the numlist NL.  If NL is empty, 
+ * return the constant NUMLIST_ERR.
+ * 
+ * Unlike numlist_first(), this routine does NOT set last_num 
+ * and the other cache fields in NL.
+ */
+
+u_long
+numlist_last(Numlist *nl)
+{
+    Numlist_node  * last;
+
+    if (numlist_isempty(nl)) {
+	return NUMLIST_ERR;
+    } else {
+	last = nl->last;
+	return NUMBER_OF(last->numbers[last->num_numbers - 1]);
+    }
+}
+
+
+
+/*
+ * Return the first number that is a member of the numlist NL and
+ * bigger than NUM. If there is no such number, the constant
+ * NUMLIST_ERR is returned.
+ */
+
+u_long
+numlist_next(Numlist *nl, u_long num)
+{    
+    Numlist_node  * nln;
+    int             index;
+    int             i;
+
+    /* If we got NUM the last time, we have cached some info about */
+    /* where to find the next entry. Use that info. */
+    if (num == nl->last_num) {
+	nln = nl->last_node;
+	index = nl->last_index;
+	if (IS_INTERVAL_START(nln->numbers[index])) {
+
+	    /* Last number was in an interval. */
+	    if (num < NUMBER_OF(nln->numbers[index + 1])) {
+		nl->last_num = num + 1;
+		return num + 1;
+	    } else {
+		++index;
+	    }
+	} 
+
+	++index;
+	if (index < nln->num_numbers) {
+	    nl->last_num = NUMBER_OF(nln->numbers[index]);
+	    nl->last_index = index;
+	    return nl->last_num;
+	}
+
+	/* If we get here the next number is not in this node */
+	/* but in the next. */
+	nln = nln->next;
+	if (nln == NULL) {
+	    nl->last_num = NUMLIST_NO_NUMBER;
+	    return NUMLIST_ERR;
+	} else {
+	    nl->last_num = NUMBER_OF(nln->numbers[0]);
+	    nl->last_node = nln;
+	    nl->last_index = 0;
+
+	    return nl->last_num;
+	}
+    }
+	
+    /* ...otherwise find NUM in the list and return the next number.  */
+    nln = nl->first;
+    ++num;
+    while (nln != NULL) {
+	if (num <= NUMBER_OF(nln->numbers[nln->num_numbers - 1])) {
+	    for (i = 0; i < nln->num_numbers; ++i) {
+
+		if (num <= NUMBER_OF(nln->numbers[i])) {
+		    nl->last_num = NUMBER_OF(nln->numbers[i]);
+		    nl->last_node = nln;
+		    nl->last_index = i;
+		    return nl->last_num;
+		}
+
+		/* Take care of an interval. */
+		if (IS_INTERVAL_START(nln->numbers[i])) {
+		    if (num <= NUMBER_OF(nln->numbers[i + 1])) {
+			nl->last_num = num;
+			nl->last_node = nln;
+			nl->last_index = i;
+
+			return num;
+		    } else {
+			++i;
+		    }
+		}
+	    }
+	}
+	nln = nln->next;
+    }
+
+    return NUMLIST_ERR;
+}
+
+
+
+/*
+ * Enter the number NUM into the numlist NL. If NL is already in
+ * NL, do nothing.
+ */
+
+void
+numlist_insert(Numlist *nl, u_long num)
+{
+    Numlist_node  * nln;
+    Numlist_node  * last;
+    int             last_num;
+    int             i;
+    int             j;
+
+    nl->last_num = NUMLIST_NO_NUMBER;
+
+    last_num = numlist_last(nl);
+    if (last_num != NUMLIST_ERR && num <= last_num) {
+	nln = nl->first;
+	while (nln != NULL) {
+	    if (num <= NUMBER_OF(nln->numbers[nln->num_numbers - 1])) {
+		for (i = 0; i < nln->num_numbers; ++i) {
+		    if (num <= NUMBER_OF(nln->numbers[i]))
+			goto found;
+		}
+	    }
+	    nln = nln->next;
+	}
+    }
+    
+    /* If we get here, num is not found. It is also the case that num */
+    /* is bigger than all numbers in the numlist. */
+    last = nl->last;
+    if (last == NULL) {
+
+	/* Empty numlist. */
+	nl->first = nl->last = numlist_node_create();
+	nl->first->num_numbers = 1;
+	nl->first->numbers[0] = num;
+
+    } else if ((NUMBER_OF(last->numbers[last->num_numbers - 1]) == num - 1)
+	       && IS_INTERVAL_END(last->numbers[last->num_numbers - 1])) {
+	/* Enter num into last interval */
+	last->numbers[last->num_numbers - 1] = MAKE_INTERVAL_END(num);
+    
+    } else if (last->num_numbers < NUM_LONGS_IN_NUMLIST) {
+	/* There is room for num in the last Numlist_node. */
+	if (last->numbers[last->num_numbers - 1] == num - 1) {
+	    last->numbers[last->num_numbers - 1]
+		= MAKE_INTERVAL_START(num - 1);
+	    last->numbers[last->num_numbers++] = MAKE_INTERVAL_END(num);
+	} else
+	    last->numbers[last->num_numbers++] = num;
+	
+	
+    } else {
+	/* We have to create a new Numlist_node to host num. */
+	nl->last = numlist_node_create();
+	last->next = nl->last;
+	nl->last->num_numbers = 1;
+	nl->last->numbers[0] = num;
+    }
+    return;
+
+  found:
+    /* Here we have found a number that is bigger than num. */
+    /* nln points to the Numlist_node and i is the index to it. */
+    
+    /* If num is already in the list, do nothing. */
+    if (NUMBER_OF(nln->numbers[i]) == num
+	|| IS_INTERVAL_END(nln->numbers[i]))
+	return;
+
+    /* Step through the different cases and take appropriate action. */
+    if (IS_INTERVAL_START(nln->numbers[i])
+	&& NUMBER_OF(nln->numbers[i]) == num + 1) {
+
+	/* Enter num into the next interval. */
+	nln->numbers[i] = MAKE_INTERVAL_START(num);
+
+	/* +++Take care of the case that two intervals could be */
+	/*    collapsed into one, e.g. like 17-21, 22-31 => 17-31. */
+
+    } else if (i > 0 
+	       && IS_INTERVAL_END(nln->numbers[i - 1])
+	       && NUMBER_OF(nln->numbers[i - 1]) == num - 1) {
+
+	/* Enter num into the previous interval. */
+	nln->numbers[i - 1] = MAKE_INTERVAL_END(num);
+
+    } else if (nln->num_numbers < NUM_LONGS_IN_NUMLIST) {
+
+	/* Squeeze in num. There is room in this Numlist_node. */
+	for (j = nln->num_numbers; j > i; --j)
+	    nln->numbers[j] = nln->numbers[j - 1];
+	if (i > 0 && nln->numbers[i - 1] == num - 1) {
+	    nln->numbers[i - 1] = MAKE_INTERVAL_START(num - 1);
+	    nln->numbers[i] = MAKE_INTERVAL_END(num);
+	} else if (i < nln->num_numbers - 1 
+		   && nln->numbers[i + 1] == num + 1) {
+	    nln->numbers[i] = MAKE_INTERVAL_START(num);
+	    nln->numbers[i + 1] = MAKE_INTERVAL_END(num + 1);
+	} else {
+	    nln->numbers[i] = num;
+	}
+
+	nln->num_numbers++;
+
+    } else {
+	/* Squeeze in num. There is no room in this Numlist_node. */
+	/* +++This implementation is a bit crude. We should split */
+	/*    the node as evenly as possible. */
+
+	numlist_node_split(nl, nln, i);
+	nln->numbers[nln->num_numbers++] = num;
+    }
+
+    /* +++We never take care of the case that two intervals in adjacent */
+    /*    nodes could be collapsed into one. Should we? */
+    return;
+}
+
+
+
+/*
+ * Delete the number NUM from the Numlist NL. If NUM is not
+ * a member of NL, do nothing.
+ */
+
+void
+numlist_delete(Numlist *nl, u_long num)
+{
+    Numlist_node  * nln1;
+    Numlist_node  * nln2;
+    int             last_num;
+    int             i;
+    int             j;
+
+    nl->last_num = NUMLIST_NO_NUMBER;
+
+    last_num = numlist_last(nl);
+    if (last_num == NUMLIST_ERR || num > last_num)
+	return;
+
+    nln1 = nl->first;
+    nln2 = NULL;
+    while (nln1 != NULL) {
+	if (num <= NUMBER_OF(nln1->numbers[nln1->num_numbers - 1])) {
+	    for (i = 0; i < nln1->num_numbers; ++i) {
+		if (num == nln1->numbers[i] /* An ordinary number */
+		    || (IS_INTERVAL_START(nln1->numbers[i])
+			&& NUMBER_OF(nln1->numbers[i]) <= num
+			&& num <= NUMBER_OF(nln1->numbers[++i])))
+		    goto found;
+
+		/* If we are already past the number, it is not here */
+		/*  ==> return. */
+		if (num < NUMBER_OF(nln1->numbers[i]))
+		    return;
+	    }
+	}
+	nln2 = nln1;
+	nln1 = nln1->next;
+    }
+    return;
+    
+    /* When we get here, nln1 points to the node where the number */
+    /* resides, nln2 points to the node before if not NULL, and i */
+    /* i is the index into the node. If the number is within an */
+    /* interval, i points to the end of the interval (++i above). */
+  found:
+    if ((nln1->numbers[i] & INTERVAL_MASK) == 0) {
+	/* An ordinary number. */
+	numlist_node_del_num(nl, nln1, nln2, i);
+	
+    } else {
+	/* An interval. */
+	if (NUMBER_OF(nln1->numbers[i]) == num) {
+	    /* The number is at the end of the interval. */
+	    --(nln1->numbers[i]);
+	    if (NUMBER_OF(nln1->numbers[i])
+		== NUMBER_OF(nln1->numbers[i - 1])) {
+
+		numlist_node_del_num(nl, nln1, nln2, i);
+		nln1->numbers[i - 1] &= NUMBER_MASK;
+	    }
+
+	} else if (NUMBER_OF(nln1->numbers[i - 1]) == num) {
+	    /* The number is at the start of the interval. */
+	    ++(nln1->numbers[i - 1]);
+	    if (NUMBER_OF(nln1->numbers[i])
+		== NUMBER_OF(nln1->numbers[i - 1])) {
+
+		numlist_node_del_num(nl, nln1, nln2, i);
+		nln1->numbers[i - 1] &= NUMBER_MASK;
+	    }
+	    
+	} else if (NUMBER_OF(nln1->numbers[i - 1]) == num - 1
+		   && NUMBER_OF(nln1->numbers[i]) == num + 1) {
+	    /* The interval is only 3 numbers */
+	    nln1->numbers[i - 1] &= NUMBER_MASK;
+	    nln1->numbers[i] &= NUMBER_MASK;
+
+	} else {
+	    /* The number is within the interval. We must split it. */
+	    if (IS_INTERVAL_END(nln1->numbers[i]))
+		--i;
+
+	    /* If there is not room for two new numbers, split the node. */
+	    if (nln1->num_numbers > NUM_LONGS_IN_NUMLIST - 2) {
+		if (i < NUM_LONGS_IN_NUMLIST / 2) {	
+		    /* Split the node after the interval and keep it here. */
+		    numlist_node_split(nl, nln1, i + 2);
+		} else {
+		    /* Split the node before the interval */
+		    /* and use the new node. */
+		    numlist_node_split(nl, nln1, i);
+		    nln1 = nln1->next;
+		    i = 0;
+		}
+	    }
+
+	    /* Now nln1 points to the node with the interval and */
+	    /* i is the index to the start of the interval. */
+	    if (NUMBER_OF(nln1->numbers[i]) == num - 1) {
+		/* NUM is second element ==> leave only one to the left. */
+		numlist_node_insert_num(nln1, i,
+					NUMBER_OF(nln1->numbers[i]));
+		nln1->numbers[i + 1] += 2;
+
+	    } else if (NUMBER_OF(nln1->numbers[i + 1]) == num + 1) {
+		/* NUM is second last element ==> leave only one to */
+		/* the right. */
+		numlist_node_insert_num(nln1, i + 2,
+					NUMBER_OF(nln1->numbers[i + 1]));
+		nln1->numbers[i + 1] -= 2;
+
+	    } else {
+		/* NUM is deep inside the interval */
+		/*   ==> Make 2 new intervals. */
+		for (j = nln1->num_numbers + 1; j >= i + 2; --j)
+		    nln1->numbers[j] = nln1->numbers[j - 2];
+		nln1->numbers[i + 1] = MAKE_INTERVAL_END(num - 1);
+		nln1->numbers[i + 2] = MAKE_INTERVAL_START(num + 1);
+		nln1->num_numbers += 2;
+	    }
+	}
+    }
+}
diff --git a/src/libraries/libmisc/numlist.h b/src/libraries/libmisc/numlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0f4c0f94b20f52fc44b319bf52ee7f8965c7513
--- /dev/null
+++ b/src/libraries/libmisc/numlist.h
@@ -0,0 +1,92 @@
+/*
+ * File: numlist.h
+ * 
+ * A numlist is an ordered list of numbers. One of the big features 
+ * of this implementation is intervals.
+ *
+ * Author: Inge Wallin
+ */
+
+
+#ifndef NUMLIST__H
+#define NUMLIST__H
+
+#include <sys/types.h>
+
+
+#define INTERVAL_MASK    0xc0000000
+#define NUMBER_MASK      0x3fffffff
+#define INTERVAL_START   0x80000000
+#define INTERVAL_END     0x40000000
+
+
+/* This constant is returned whenever there are no more fitting values */
+/* for a call, e.g. when numlist_first() is called with an empty Numlist. */
+
+#define NUMLIST_ERR      0xffffffff
+
+
+/* This constant is stored in the field last_num when no previous */
+/* number is stored. */
+
+#define NUMLIST_NO_NUMBER   0xffffffff
+
+
+/*
+ * One int + 13 longs + one pointer + the length info that 
+ * malloc adds makes 64 bytes. This should make allocation fairly
+ * efficient.
+ */
+
+/* #define NUM_LONGS_IN_NUMLIST  13 */
+#define NUM_LONGS_IN_NUMLIST  5
+
+
+typedef struct numlist_node   Numlist_node;
+typedef struct numlist        Numlist;
+
+struct numlist_node {
+    int             num_numbers;
+    u_long          numbers[NUM_LONGS_IN_NUMLIST];
+    Numlist_node  * next;
+};
+
+
+struct numlist {
+    Numlist_node  * first;
+    Numlist_node  * last;
+    
+    /* The following info is used only for speeding up numlist_next(). */
+    u_long          last_num;	/* The last number returned. */
+    Numlist_node  * last_node;	/* The node containing the last number... */
+    int             last_index;	/* ...and the index to it. */
+};
+
+
+/* ================================================================ */
+/*    Prototypes for all global functions in the numlist package.   */
+
+
+Numlist *numlist_create(void);
+Bool     numlist_isempty(Numlist *);
+Bool     numlist_member(Numlist *, u_long);
+u_long   numlist_first(Numlist *);
+u_long   numlist_last(Numlist *);
+u_long   numlist_next(Numlist *, u_long);
+void     numlist_insert(Numlist *, u_long);
+void     numlist_delete(Numlist *, u_long);
+
+/*
+ * Useful (?) but not yet implemented:
+ *
+ * void     numlist_destroy(Numlist *);
+ * void     numlist_insert_interval(Numlist *, u_long, u_long);
+ * void     numlist_delete_interval(Numlist *, u_long, u_long);
+ * Numlist *numlist_union(Numlist *, Numlist *);
+ * Numlist *numlist_intersection(Numlist *, Numlist *);
+ * Numlist *numlist_difference(Numlist *, Numlist *);
+ * void     numlist_print(FILE *, Numlist *);
+ * void     numlist_read(FILE *, Numlist *);
+ */
+
+#endif   /* NUMLIST__H */
diff --git a/src/libraries/libmisc/numlist2.c b/src/libraries/libmisc/numlist2.c
new file mode 100644
index 0000000000000000000000000000000000000000..2124a45400692a7ae1bdf578960744b3ddd5298c
--- /dev/null
+++ b/src/libraries/libmisc/numlist2.c
@@ -0,0 +1,99 @@
+/*
+ * File: numlist2.c
+ * 
+ * This file is supposed to be a reference while testing numlist.
+ *
+ * Author: Inge Wallin
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <misc-types.h>
+
+#include "numlist2.h"
+
+
+Numlist *
+Numlist_create()
+{
+    Numlist  * nl;
+    int        i;
+
+    nl = (Numlist *) malloc(sizeof(Numlist));
+    if (nl == NULL) {
+	fprintf(stderr, "Virtual memory exhausted");
+	abort();
+    }
+
+    for (i = 0; i < NUM_CELLS; ++i)
+	nl->cells[i] = 0;
+    
+    return nl;
+}
+
+
+Bool
+numlist_isempty(Numlist *nl)
+{
+    int   i;
+
+    for (i = 0; i < NUM_CELLS; ++i)
+	if (nl->cells[i] != 0)
+	    return FALSE;
+    
+    return TRUE;
+}
+
+
+Bool
+numlist_member(Numlist *nl, u_long num)
+{
+    return (nl->cells[num / 32] & ((u_long) 1 << (num & 31))) != 0;
+}
+
+
+u_long
+numlist_first(Numlist *nl)
+{
+    int   i;
+    int   j;
+
+    if (numlist_isempty(nl))
+	return NUMLIST_ERR;
+
+    for (i = 0; i < NUM_CELLS; ++i) {
+	if (nl->cells[i] != 0) {
+	    for (j = 31; j >= 0; --j) {
+		if ((nl->cells[i] & ((u_long) 1 << j)) != 0)
+		    return i * 32 + j;
+	    }
+	}
+    }
+    
+    return NUMLIST_ERR;
+}
+
+
+u_long
+numlist_next(Numlist *nl, u_long num)
+{
+    /* NYI */
+    return NUMLIST_ERR;
+}
+
+
+void
+numlist_insert(Numlist *nl, u_long num)
+{
+    nl->cells[num / 32] |= ((u_long) 1 << (num & 31));
+}
+
+
+void
+numlist_delete(Numlist *nl, u_long num)
+{
+    nl->cells[num / 32] &= ~((u_long) 1 << (num & 31));
+}
+
diff --git a/src/libraries/libmisc/numlist2.h b/src/libraries/libmisc/numlist2.h
new file mode 100644
index 0000000000000000000000000000000000000000..da0a594120bd80d0535c2a8b4e2e0090803725ad
--- /dev/null
+++ b/src/libraries/libmisc/numlist2.h
@@ -0,0 +1,35 @@
+/*
+ * File: numlist2.h
+ * 
+ * This file is supposed to be a reference while testing numlist.
+ *
+ * Author: Inge Wallin
+ */
+
+
+#ifndef NUMLIST2__H
+#define NUMLIST2__H
+
+#include <sys/types.h>
+
+
+#define NUMLIST_ERR      0xffffffff
+
+#define MAX_NUMS   131072
+#define NUM_CELLS  (MAX_NUMS / 32)
+
+typedef struct {
+    u_long   cells[NUM_CELLS];
+} Numlist;
+
+
+Numlist *numlist_create(void);
+Bool     numlist_isempty(Numlist *);
+Bool     numlist_member(Numlist *, u_long);
+u_long   numlist_first(Numlist *);
+u_long   numlist_next(Numlist *, u_long);
+void     numlist_insert(Numlist *, u_long);
+void     numlist_delete(Numlist *, u_long);
+
+
+#endif   /* NUMLIST2__H */
diff --git a/src/libraries/libmisc/testnumlist b/src/libraries/libmisc/testnumlist
new file mode 100755
index 0000000000000000000000000000000000000000..103245d0a3816fd38dda3481d15c1add2871998a
Binary files /dev/null and b/src/libraries/libmisc/testnumlist differ
diff --git a/src/libraries/libmisc/testnumlist.c b/src/libraries/libmisc/testnumlist.c
new file mode 100644
index 0000000000000000000000000000000000000000..e63e154732a8f90777901d4febe4e3242719cf63
--- /dev/null
+++ b/src/libraries/libmisc/testnumlist.c
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <misc-types.h>
+
+#include "numlist.h"
+
+
+/* ================================================================ */
+/*                        Some useful macros                        */
+
+
+#define IS_INTERVAL_START(x)  (((x) & INTERVAL_MASK) == INTERVAL_START)
+#define IS_INTERVAL_END(x)    (((x) & INTERVAL_MASK) == INTERVAL_END)
+
+#define NUMBER_OF(x)          ((x) & NUMBER_MASK)
+
+#define MAKE_INTERVAL_START(x)  ((x) | INTERVAL_START)
+#define MAKE_INTERVAL_END(x)    ((x) | INTERVAL_END)
+
+
+/* ================================================================ */
+
+
+void
+numlist_node_print(Numlist_node *nln)
+{
+    int      i;
+    u_long   num;
+
+    putchar('[');
+    for (i = 0; i < NUM_LONGS_IN_NUMLIST; ++i) {
+	if (i < nln->num_numbers) {
+	    num = nln->numbers[i];
+	    printf("%c%5U%c,", IS_INTERVAL_START(num) ? '<' : ' ',
+		   NUMBER_OF(num), IS_INTERVAL_END(num) ? '>' : ' ');
+	} else {
+	    printf("       ,");
+	}
+    }
+    putchar(']');
+    putchar('\n');
+}
+
+
+
+void
+numlist_print(Numlist *nl)
+{
+    Numlist_node  * nln;
+
+    printf("last_num   = %U\n", nl->last_num);
+    printf("last_index = %U\n", nl->last_index);
+    nln = nl->first;
+    while (nln != NULL) {
+	numlist_node_print(nln);
+	nln = nln->next;
+    }
+    putchar('\n');
+}
+
+
+
+int
+main()
+{
+    Numlist  * nl;
+    Bool       finished;
+
+    nl = numlist_create();
+    puts("Empty numlist:");
+    numlist_print(nl);
+
+    finished = FALSE;
+    while (!finished) {
+	char     command;
+	u_long   num;
+
+	scanf("\n%c%U", &command, &num);
+	switch (command) {
+	  case 'i':
+	    numlist_insert(nl, num);
+	    printf("%U inserted\n", num);
+	    numlist_print(nl);
+	    break;
+
+	  case 'd':
+	    numlist_delete(nl, num);
+	    printf("%U deleted\n", num);
+	    numlist_print(nl);
+	    break;
+
+	  case 'q':
+	    finished = TRUE;
+	    break;
+
+	  case ' ':
+	  case '\n': 
+	    break;
+
+	  default:
+	    printf("Unrecognized command: %c\n", command);
+	    break;
+	}
+    }
+    
+    return 0;
+}
+
diff --git a/src/server/Makefile b/src/server/Makefile
new file mode 100755
index 0000000000000000000000000000000000000000..d09543a8a3cd7122b780ec0765151870718aaf0c
--- /dev/null
+++ b/src/server/Makefile
@@ -0,0 +1,168 @@
+#  Makefile for LysKOM
+#
+###############################################################################
+#
+#  SPECIAL CONSIDERATIONS:
+#
+#  -  Requires GNU make.
+#  -  CC, OPTIMIZE-FLAGS and other make variables are passed down 
+#     in the environment.
+#  -  C compiler must be ANSI conformant.
+#
+###############################################################################
+#
+#  SPECIAL TARGETS:
+###############################################################################
+
+# Directories that you might want to override via the environment.
+
+ifndef TOPDIR
+TOPDIR := /usr/lyskom/src
+endif
+
+ifndef SCRIPTDIR
+SCRIPTDIR := $(TOPDIR)/scripts
+endif
+
+include $(SCRIPTDIR)/import.make
+
+
+DESTDIR = /usr/lyskom/bin
+
+HDRS = admin.h isc-parse.h prot-a-output.h async.h isc.h \
+	prot-a-parse.h cache.h limits.h prot-a-send-async.h connections.h \
+	log.h prot-a.h dbck-cache.h lyskomd.h ram-output.h disk-cache.h \
+	manipulate.h ram-parse.h end-of-atomic.h memory.h send-async.h exp.h \
+	minmax.h smalloc.h internal-connections.h mux-parse.h \
+	std-disclaimer.h internal-services.h mux.h text-garb.h \
+	version.incl cache-node.h
+
+# LIBS = -L/usr/local/lib -ldebug-malloc -lisc -lresolv
+# /usr/local/lib is searched normally, and the -L flag is not supported by
+# DYNIX. /ceder
+
+LIBS = -lisc -lmisc -llyskom-server -lansi
+
+TARGET = -DSERVER
+
+
+# Files that implements protocol A.
+PROTA =  prot-a-output.o prot-a-parse-arg.o prot-a-parse.o prot-a.o \
+	 prot-a-send-async.o
+
+PROTA_SRCS = prot-a-output.c prot-a-parse-arg.c prot-a-parse.c prot-a.c \
+	     prot-a-send-async.c
+
+MUX = mux.o mux-parse.o
+
+MUX_SRCS = mux.c mux-parse.c
+# Implementations of the atomic calls.
+
+ATOMS = text.o membership.o person.o conference.o session.o admin.o
+ATOMS_SRCS = text.c membership.c person.c conference.c session.c admin.c
+
+# These files are needed by all versions of the LysKOM server.
+GENOBJS = connections.o log.o $(ATOMS) \
+          kom-types.o \
+          send-async.o config.o text-garb.o \
+          missing-ansi.o isc-parse.o memory.o $(PROTA) $(MUX) \
+	  internal-connections.o
+
+GEN_SRCS = connections.c log.c $(ATOMS_SRCS) \
+          kom-types.c \
+          send-async.c config.c text-garb.c \
+          missing-ansi.c isc-parse.c memory.c $(PROTA_SRCS) $(MUX_SRCS) \
+	  internal-connections.c
+
+# Files that are necessary for ramkomd. 
+
+RAMOBJS = ramkomd.o ram-smalloc.o ram-cache.o ram-parse.o ram-output.o \
+	end-of-atomic.o string-malloc.o
+RAM_SRCS = ramkomd.c ram-smalloc.c ram-cache.c ram-parse.c ram-output.c \
+	end-of-atomic.c string-malloc.c
+
+# Files for diskomd.
+
+DISKOBJS = ramkomd.o ram-smalloc.o simple-cache.o ram-parse.o ram-output.o \
+	disk-end-of-atomic.o cache-node.o string-malloc.o
+
+DISK_SRCS = ramkomd.c ram-smalloc.c simple-cache.c ram-parse.c ram-output.c \
+	disk-end-of-atomic.c cache-node.c string-malloc.c
+
+# Files that are necessary for lyskomd.
+LYSOBJS = cache.o lyskomd.o smalloc.o
+LYS_SRCS = cache.c lyskomd.c smalloc.c
+
+DBCK = dbck.o dbck-cache2.o ram-smalloc.o ram-parse.o config.o\
+	kom-types.o\
+	missing-ansi.o ram-output.o memory.o
+
+DBCK_SRCS = dbck.c dbck-cache2.c ram-smalloc.c ram-parse.c config.c\
+	kom-types.c\
+	missing-ansi.c ram-output.c memory.c
+
+
+SPECIALS = call-switch.incl com.h fnc-def-init.incl prot-a-parse-arg.c\
+	prot-a-parse-arg.h fncdef-no-str-limit.txt
+
+SRCS = $(GEN_SRCS) $(RAM_SRCS) $(DISK_SRCS) $(LYS_SRCS) $(DBCK_SRCS)
+
+PROGRAMS = ramkomd diskomd dbck
+
+
+all: $(PROGRAMS)
+
+ramkomd: $(RAMOBJS) $(GENOBJS)
+	$(CC) $(LDFLAGS) -o ramkomd $(RAMOBJS) $(GENOBJS) $(LIBS)
+
+diskomd: $(DISKOBJS) $(GENOBJS)
+	$(CC) $(LDFLAGS) -o diskomd $(DISKOBJS) $(GENOBJS) $(LIBS)
+
+lyskomd: 
+	$(CC) $(CFLAGS) -o lyskomd
+
+dbck: $(DBCK)
+	$(CC) $(LDFLAGS) -o dbck $(DBCK) $(LIBS)
+
+call-switch.incl: call-switch.awk fncdef-no-str-limit.txt
+	$(AWK) -f call-switch.awk fncdef-no-str-limit.txt > call-switch.incl
+
+com.h: com-h.awk fncdef-no-str-limit.txt
+	$(AWK) -f com-h.awk fncdef-no-str-limit.txt > com.h
+
+fnc-def-init.incl: fnc-def-init.awk fncdef-no-str-limit.txt
+	$(AWK) -f fnc-def-init.awk fncdef-no-str-limit.txt > fnc-def-init.incl
+
+prot-a-parse-arg.c: prot-a-parse-arg-c.awk fncdef.txt prot-a-parse-arg.h
+	$(AWK) -f prot-a-parse-arg-c.awk fncdef.txt > prot-a-parse-arg.c
+
+prot-a-parse-arg.h: prot-a-parse-arg-h.awk fncdef-no-str-limit.txt
+	$(AWK) -f prot-a-parse-arg-h.awk fncdef-no-str-limit.txt > \
+		prot-a-parse-arg.h
+
+fncdef-no-str-limit.txt: fncdef.txt
+	(echo \# Do not edit this file! It is generated from fncdef.txt.;\
+	cat fncdef.txt) | sed 's/([^)]*)//g' > fncdef-no-str-limit.txt
+
+
+install:  $(PROGRAMS)
+	echo Server not installed.
+#	cp diskomd $(DESTDIR)/ramkomd	# The utilites wants ramkomd.
+#	cp dbck $(DESTDIR)/
+#	strip $(DESTDIR)/dbck
+# Don't strip ramkomd - we want debugging info!
+
+clean:
+	rm -vf *.o *~ core $(PROGRAMS) $(SPECIALS) TAGS
+
+specials: $(SPECIALS)
+
+tags: $(SRCS) $(HDRS)
+	rcs -l TAGS
+	rm -f TAGS
+	etags -t $(INCLUDEDIR)/*.h *.[hc]
+	echo " " | ci TAGS
+
+include $(SCRIPTDIR)/Parallell-depend.make
+
+include dependencies
diff --git a/src/server/free.gdb b/src/server/free.gdb
new file mode 100644
index 0000000000000000000000000000000000000000..278acd9058cc89eda508a4fb78f424eba06a472e
--- /dev/null
+++ b/src/server/free.gdb
@@ -0,0 +1,11 @@
+break sfree if ptr != 0
+commands 
+silent
+echo --- sfree ---\n
+echo Arg: 
+output ptr
+echo \n
+bt
+echo =========\n
+cont
+end
diff --git a/src/server/malloc.gdb b/src/server/malloc.gdb
new file mode 100644
index 0000000000000000000000000000000000000000..e76fc55dd572526429e267c5a65d8e604b683f26
--- /dev/null
+++ b/src/server/malloc.gdb
@@ -0,0 +1,12 @@
+commands 
+silent
+echo --- smalloc ---\n
+echo Arg: 
+output size
+echo \nVal: 
+output p
+echo \n
+bt
+echo =========\n
+cont
+end
diff --git a/src/server/realloc.gdb b/src/server/realloc.gdb
new file mode 100644
index 0000000000000000000000000000000000000000..a65ad2e765e8b6acfa42a93d14ad07032207c81f
--- /dev/null
+++ b/src/server/realloc.gdb
@@ -0,0 +1,14 @@
+commands 
+silent
+echo --- srealloc ---\n
+echo Arg: 
+output size
+echo \nVal: 
+output new_ptr
+echo \nOld: 
+output ptr
+echo \n
+bt
+echo =========\n
+cont
+end