diff --git a/ChangeLog b/ChangeLog
index 2cb38ed34db01293b3acde6e9bb85bc5342d39f4..d0757533b0731a0966b75718369c00d55adb23d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,38 @@
 	lyskomd.0/08.exp.
 	* src/server/testsuite/lyskomd.0/08.exp: New file.
 
+1999-05-18  David Byers  <davby@ida.liu.se>
+
+	* doc/lyskomd.texi: Merged dbck.texi and hacking.texi into
+	lyskomd.texi.
+
+	* src/server/testsuite/lyskomd.0/03.exp: Updated
+	query-predefined-aux-items result.
+
+	* src/server/testsuite/lyskomd.0/01.exp: Updated
+	query-predefined-aux-items result.
+
+	* src/server/aux-items.c (undelete_aux_item_list): Fixed
+	conference/text mixup
+	(delete_aux_item_list): Same here.
+	(undelete_aux_item_list): Save kom_errno and err_stat across call.
+
+	* src/server/aux-item-def-parse.y: Deal with disabled definitions
+	in a more sensible manner.
+
+	* src/server/aux-items.c (aux_item_add_perm): Check the disabled
+	field of the aux-item definition.
+
+	* src/server/aux-items.h: Added disabled field.
+
+1999-05-17  David Byers  <davby@ida.liu.se>
+
+	* src/server/aux-items.c (aux_item_list_add_items): New utility
+	function.
+	(system_add_aux_item_list): Use aux_item_list_add_items.
+	(text_stat_add_aux_item_list): Use aux_item_list_add_items.
+	(conf_stat_add_aux_item_list): Use aux_item_list_add_items.
+
 1999-05-16  Per Cederqvist  <ceder@lysator.liu.se>
 
 	Use a global variable to store the current time, so that it is
@@ -111,6 +143,24 @@
 	* src/server/ram-smalloc.c: Don't test USE_GNU_MALLOC; that symbol
 	was removed 1998-08-09.
 
+1999-05-16  David Byers  <davby@ida.liu.se>
+
+	* src/server/aux-items.c (prepare_aux_item): Don't clear the link
+	field of the aux item.
+	(aux_inherit_items): Clear the link in the copied item before
+	calling add triggers.
+	(aux_item_link_items): New function.
+	(aux_item_trigger_mirror_faq): Use aux_item_link_items.
+	(aux_item_trigger_link_item): Use aux_item_link_items.
+	(aux_item_call_add_triggers): Fix the trigger data after calling
+	each trigger since one of them might move the aux item list in 
+	memory.
+
+1999-05-15  David Byers  <davby@ida.liu.se>
+
+	* src/server/aux-items.c (aux_item_trigger_link_item): New
+	function for debugging linking aux items.
+
 1999-05-14  Per Cederqvist  <ceder@lysator.liu.se>
 
 	Fixes to the test suite.
@@ -143,6 +193,116 @@
 	(lyskomd_fail_start): Likewise.  Find the database files relative
 	to top_srcdir.
 
+1999-05-14  David Byers  <davby@ida.liu.se>
+
+	* src/server/text.c (do_create_text): Return long-array if there
+	are too many misc items.
+	(modify_text_info): Set err_stat to max length when returning
+	KOM_LONG_ARRAY.
+
+	* src/include/kom-types.h (Info_datum): Added unknown_type to
+	union.
+
+	* src/server/text.c (find_recipient): Add unknown_info to the
+	switch. Stop the server if COMPILE_CHECKS is undefined.
+	(is_member_in_recpt): Same here.
+	(do_delete_misc): Same here.
+	(do_sub_recpt): Same here.
+	(sender): Same here.
+	(is_sender): Same here.
+	(is_comm_sender): Same here.
+	(skip_recp): Same here.
+	(recp_sent_by): Same here.
+	(filter_secret_info): Same here.
+	(do_delete_text): Same here. 
+	(check_double_subm): Same here.
+	(check_double_comm): Same here.
+	(create_text_check_misc): Return an illegal-info-typye if we see
+	an unknown info. Set err_stat to the index of the bad item when
+	returning a KOM_ILL_MISC.
+	(create_text_add_miscs): Same here.
+
+	* src/server/prot-a.c (prot_a_destruct): Free the misc_info_list
+	field of the connection.
+
+	* src/server/membership.c (add_rec_time): Handle unknown_info and
+	other unknown misc info types by shutting down the server.
+
+	* src/server/call-switch.awk: Add support for misc_info_list in
+	fncdef.txt.
+
+	* src/server/text.c (create_text_old): Changed parameter list to
+	use Misc_info_list instead of an integer and a Misc_info pointer.
+	(create_text): Same here.
+	(create_anonymous_text): Same here.
+	(create_anonymous_text_old): Same here.
+
+	* src/server/fncdef.txt: Changed all "num c_misc_info_p" to
+	misc_info_list. 
+
+	* src/server/prot-a-parse-arg-c.awk: The aux_item type works again.
+	Allow misc_info_list as a type name.
+
+	* src/server/prot-a-parse.c (prot_a_parse_misc_info_list): New
+	function. 
+
+	* src/server/prot-a.c (prot_a_init): Initialize the misc_info_list 
+	field.
+
+	* src/server/internal-connections.c (kill_client): Use
+	misc_info_list field of Connection.
+
+	* src/server/connections.c (free_parsed): Clear the misc_info_list 
+	field.
+
+	* src/include/kom-types.h (Misc_info_list): New type
+
+	* src/server/internal-connections.c (init_connection): Initialize
+	hunt_parse_pos, array_hunt_depth and array_hunt_num. Initialize
+	misc_info_list. 
+
+	* src/server/prot-a-parse.c (prot_a_hunt_array_end): New function
+	hunts for the end of an array.c
+
+	* src/server/prot-a.c (prot_a_init): Initialize hunt_parse_pos and 
+	array_hunt_num.
+
+
+	* src/include/kom-types.h (Info_type): Added unknown info type. 
+
+	* src/server/prot-a-parse.c (prot_a_parse_misc_info): Parse all
+	misc-info types that the server knows about. Unknown types
+	generate a protocol error.
+
+	* src/server/testsuite/lyskomd.0/prot-a-parse-cov.exp (1021):
+	Expcet long-array and not protocol-error.
+
+	* src/server/prot-a-parse.c (prot_a_parse_aux_item_list): Discard
+	the part of the list that is longer than the max rather than send
+	a protocol error.
+
+1999-05-13  David Byers  <davby@ida.liu.se>
+
+	* src/server/testsuite/lyskomd.0/prot-a-parse-cov.exp
+	(protocol_error): Removed expected failure.
+
+	* src/server/admin.c (modify_server_info): Return KOM_LONG_ARRAY
+ 	when we see a long array.
+
+	* src/server/conference.c (modify_conf_info): Return
+ 	KOM_LONG_ARRAY when we see a long array.
+
+	* src/server/text.c (modify_text_info): Return KOM_LONG_ARRAY when 
+	we see a long array.
+
+	* src/server/prot-a-parse.c (prot_a_parse_num_list): Truncate a
+	parsed array to one more than the maximum length and skip all
+	other elements.
+
+	* src/server/aux-items.c (undelete_aux_item_list): Log if the link 
+	type is undefined and do not attempt to undelete.
+	(delete_aux_item_list): Likewise.
+
 1999-05-13  Per Cederqvist  <ceder@gratia>
 
 	Distribute the leaks tests, and run them during "make check".
diff --git a/TODO b/TODO
index 4d654f99d13dfce8215856e9b97df74adebe7457..5c56e84f1d67440c792f528028ff4cbe76476524 100644
--- a/TODO
+++ b/TODO
@@ -9,11 +9,13 @@ Testfall f
 
 * Showstoppers
 
-** Make sure that there are no "expected failures" in the test suite.
-
 ** Consider changing many paths so that it is safe to install lyskomd
    with prefix=/usr/local.
 
+        How about saving this for the next release and then support
+        various other path conventions?
+
+
 ** Consider removing the pid file on exit.
 
 ** Consider locking the database, so that dbck cannot do harm, and so
@@ -29,25 +31,36 @@ Testfall f
 
 ** Documentation Issues
 
-*** Document "%%Unsupported protocol" message
-
-*** Document "%% No connections left" message
-
 *** Remove the text "In all likelihood, the implementation of this flag 
     is screwed up." from lyskomd.texi after checking that
     supervisor-only works properly.
 
-*** Move dbck.texi, hacking.tex and lyskomdb.texi into lyskomd.texi.  
-    Two reasons: there are too many manuals, and automake apparently
-    doesn't allow more than one file to include version.texi.
+*** Document updateLysKOM in lyskomd.texi.
+    There should be an "Invoking updateLysKOM" node.
+    updateLysKOM should use the "Status file" parameter (and other
+    parameters). (DONE)
+    Use parameters in src/server/updateLysKOM.c`savecore(). (DONE)
+    I will do this --ceder
 
-*** Fix doc/lyskomdb.texi (Version 1) (see FIXME comments).
+*** Document komrunning in lyskomd.texi.
+    There should be an "Invoking komrunning" node.
+    komrunning should be rewritten i C; it only works with BSD-style ps
+    programs. (DONE, but it no longer displays the process)
+    I am doing this --ceder
 
 *** Dump all little doc files into the texinfo manuals.
+    Remaining: 
+        disc-cache.spec                 lyskomd.texi        �vers�tt, uppdatera
+        local-to-global.doc             lyskomd.texi        ceder?
+        prot-a-tankar                   *
+        prot_a                          *
+        security-levels.txt             Protocol-A.texi     DONE
+        what-is-unread.swe              Protocol-A.texi     DONE
     I will do this --DCB
 
 *** Fix the node structure of Protocol-A.texi (3228867).
     I will do this --DCB
+    Looks done...
 
 *** Update/rewrite README.
 
@@ -62,8 +75,6 @@ Testfall f
 *** The protocol revision section of Protocol-A.info is incomplete.
     I will do this --ceder
 
-*** Document that session number 0 can be used in call 55.
-
 ** Build Issues
 
 *** Check that texinfo.tex is included in a proper place by automake.
@@ -76,6 +87,12 @@ Testfall f
 
 ** Testing
 
+*** Try sending in negative lengths whenever we can send an array.
+        DONE for misc-info-list, add-aux delete-aux
+
+*** Check that we don't leak memory when truncating a long
+    aux_item_list send from the client. 
+
 *** In prot_a_get_token, what is an insane token length?
 
 *** Test validation of regexps containing groups. Try "X\\(YZ\\)?X".
@@ -87,13 +104,6 @@ Testfall f
 
 *** Should anyone be able to set their letterbox to secret?
 
-*** There is no way to set the Personal_flags. It's not even obvious
-    where it gets its initial value! This is Not Good At All.
-
-*** If we try to create a pers or conf and have reached the limit
-    of how many confs we can create, lyskomd just dies. Nasty. It
-    should return index-out-of-range, like create-text.
-
 *** Timestamps of various things are not synchronized. 
     This is seen easily when lyskomd executes really slowly. 
     Known cases: last-written does not match text-stat (FIXED)
@@ -671,6 +681,59 @@ Testfall f
    removed. (1108039).
 	REJECT: too much work to be worth it.
 
+*** Document "%%Unsupported protocol" message
+    DONE.
+
+*** Document "%% No connections left" message
+    DONE.
+
+*** Fix doc/lyskomdb.texi (Version 1) (see FIXME comments).
+    DONE.
+
+*** Document that session number 0 can be used in call 55.
+    DONE.
+
+*** There is no way to set the Personal_flags. It's not even obvious
+    where it gets its initial value! This is Not Good At All.
+    DONE.
+
+*** If we try to create a pers or conf and have reached the limit
+    of how many confs we can create, lyskomd just dies. Nasty. It
+    should return index-out-of-range, like create-text.
+    DONE.
+
+** When we pass a read-only misc item in create-text we get a protocol 
+   error. We should get an illegal-misc. We can't just pass it through 
+   since create_text_add_miscs will abort if it sees one of these misc 
+   items.
+        DONE.
+
+** Parsing arrays that are longer than the maximum length is not
+   handled very well. Right now we return a protocol error most of the 
+   time, but perhaps it would be better to return a protocol error
+   only when the array is insanely long, not just when it is longer
+   than the max. So we could have a global max array length parameter.
+        DONE.
+
+** Make sure that there are no "expected failures" in the test suite.
+        DONE.
+
+** Try sending a too-long aux-item list
+        DONE.
+
+** Send a too-long misc-item list
+        DONE.
+
+** Sending a too-long delete or add list crashes the server.
+        DONE.
+
+** Call add-recipient with really bogus info type
+        DONE.
+
+*** Move dbck.texi, hacking.tex and lyskomdb.texi into lyskomd.texi.  
+    Two reasons: there are too many manuals, and automake apparently
+    doesn't allow more than one file to include version.texi.
+        DONE.
 
 * In progress 
 
diff --git a/doc/Protocol-A.texi b/doc/Protocol-A.texi
index b3d1d1b9e9041e49f32bc643ad584a6c0791c6c2..c9b9eb2718b4a07e95ad89e2dd17d224c64f0c1b 100644
--- a/doc/Protocol-A.texi
+++ b/doc/Protocol-A.texi
@@ -2,7 +2,7 @@
 @c
 @c FIXME: Explain how the garb works with nice and keep-commented
 @c
-@c $Id: Protocol-A.texi,v 1.63 1999/05/13 11:35:24 ceder Exp $
+@c $Id: Protocol-A.texi,v 1.64 1999/05/18 13:06:18 byers Exp $
 @c %**start of header
 @setfilename protocol-a.info
 @settitle LysKOM Protocol A
@@ -61,7 +61,7 @@ another language under the same conditions as for modified versions.
 @end titlepage
 
 @ifinfo
-@node Top
+@node Top, Overview, (dir), (dir)
 @top LysKOM Protocol A
 
 This document specifies version 10 of LysKOM Protocol A.
@@ -87,7 +87,7 @@ publication.
 @end menu
 @end ifinfo
 
-@node Overview
+@node Overview, Introduction, Top, Top
 @chapter Overview
 
 LysKOM is a conferencing system@footnote{Or in modern terms, enabling
@@ -132,7 +132,7 @@ The LysKOM developers can be reached by email to @code{lyskom@@lysator.liu.se}.
 * Notation::                    
 @end menu
 
-@node Document Revision History
+@node Document Revision History, Protocol Version History, Overview, Overview
 @section Document Revision History
 
 @table @asis
@@ -170,7 +170,7 @@ Per Cederqvist started using version control for documentation.
 Lars Aronsson documented the protocol that was in use at the time.
 @end table
 
-@node Protocol Version History
+@node Protocol Version History, Notation, Document Revision History, Overview
 @section Protocol Version History
 
 @subsection Protocol version 10 (first implemented in lyskomd 2.0.0)
@@ -412,7 +412,7 @@ All calls from 0--56.
 @end table
 
 
-@node Notation
+@node Notation,  , Protocol Version History, Overview
 @section Notation
 
 This specification uses a BNF-like grammar to describe the protocol and
@@ -435,7 +435,7 @@ literal strings. There is to be no whitespace before or after literal
 strings unless there is whitespace in the literal itself.
 
 
-@node Introduction
+@node Introduction, Data Types, Overview, Top
 @chapter Introduction
 
 This chapter introduces the concepts used in LysKOM, such as articles,
@@ -452,7 +452,7 @@ conferences and sessions.
 @end menu
 
 
-@node Articles
+@node Articles, Conferences, Introduction, Introduction
 @section Articles
 
 An article is represented as a value of the type @code{Text-Stat} and a
@@ -482,7 +482,7 @@ The server call @code{local-to-global} does this.
 
 
 
-@node Conferences
+@node Conferences, The Misc-Info List, Articles, Introduction
 @section Conferences
 
 Conferences hold articles. They are represented in the protocol as a
@@ -535,7 +535,7 @@ changed to this type, preexisting secret members remain secret.
 * Persons and Sessions::        
 @end menu
 
-@node Persons and Sessions
+@node Persons and Sessions,  , Conferences, Conferences
 @subsection Persons and Sessions
 
 Persons are represented in the protocol by values of the type
@@ -553,7 +553,7 @@ the network connection is closed; a user can log in and out repeatedly
 in a single session.
 
 
-@node The Misc-Info List
+@node The Misc-Info List, The Aux-Item List, Conferences, Introduction
 @section The Misc-Info List
 
 The @code{Misc-Info} list contains tagged data. The fields are sent in
@@ -702,7 +702,7 @@ article number which is a footnote to this article.
 @end table
 
 
-@node The Aux-Item List
+@node The Aux-Item List, Security, The Misc-Info List, Introduction
 @section The Aux-Item List
 
 The aux-item list is used as a generic extension mechanism in the LysKOM
@@ -716,7 +716,7 @@ server and in protocol A.
 * Defining New Aux-Item Types::  
 @end menu
 
-@node About Aux-Items
+@node About Aux-Items, Predefined Aux-Item Types, The Aux-Item List, The Aux-Item List
 @subsection About Aux-Items
 
 Aux-items were introduced in protocol version 10 as a mechanism for
@@ -748,7 +748,7 @@ no understanding of the contents can successfully parse the item anyway
 
 
 
-@node Predefined Aux-Item Types
+@node Predefined Aux-Item Types, Client-Specific Aux-Item Types, About Aux-Items, The Aux-Item List
 @subsection Predefined Aux-Item Types
 
 Predefined Aux-Item types are part of Protocol A, and clients should
@@ -1065,7 +1065,7 @@ collection.
 @end table
 
 
-@node Client-Specific Aux-Item Types
+@node Client-Specific Aux-Item Types, Experimental Aux-Item Types, Predefined Aux-Item Types, The Aux-Item List
 @subsection Client-Specific Aux-Item Types
 
 Client-specific items do not cause the server to perform any magic. All
@@ -1087,7 +1087,7 @@ If you want a range of numbers, send e-mail to the LysKOM development
 group.
 
 
-@node Experimental Aux-Item Types
+@node Experimental Aux-Item Types, Defining New Aux-Item Types, Client-Specific Aux-Item Types, The Aux-Item List
 @subsection Experimental Aux-Item Types
 
 Experimental numbers are free for all. Use 'em any way you want. All
@@ -1095,7 +1095,7 @@ numbers in the range 20000-29999 are for experimental use.
 
 
 
-@node Defining New Aux-Item Types
+@node Defining New Aux-Item Types,  , Experimental Aux-Item Types, The Aux-Item List
 @subsection Defining New Aux-Item Types
 
 If you want a new predefined item type, just document what it does, what
@@ -1121,7 +1121,7 @@ much less painful process than adding new calls.
 
 
 
-@node Security
+@node Security, Membership and Reading, The Aux-Item List, Introduction
 @section Security
 
 Security in LysKOM is based on two components. Each person has a set of
@@ -1195,7 +1195,7 @@ Create persons
 @end table
 
 
-@node Membership and Reading
+@node Membership and Reading, Client-Server Dialog, Security, Introduction
 @section Membership and Reading
 
 Persons' memberships in conferences are represented in the protocol as
@@ -1242,7 +1242,7 @@ global text numbers. If the server does not implement the
 efficient but perfectly serviceable @pxref{get-map} call instead.
 
 
-@node Client-Server Dialog
+@node Client-Server Dialog,  , Membership and Reading, Introduction
 @section Client-Server Dialog
 
 The client-server dialog consists of two phases, establishing the connection
@@ -1259,7 +1259,7 @@ the user connecting is followed by a newline character.
 
 When the server has accepted the connection its reply is
 protocol-dependent. Protocol A servers will reply with the string
-@code{LysKOM} on a single line.
+@code{LysKOM} on a single line if the connection attampt is successful.
 
 @example
         % telnet kom.lysator.liu.se 4894
@@ -1270,6 +1270,17 @@ protocol-dependent. Protocol A servers will reply with the string
         LysKOM
 @end example
 
+Besides the string "LysKOM", the server may respond with "%%Unsupported
+protocol" or "%% No connections left.". 
+
+The "%%Unsupported protocol" reply is sent if the server does not
+understand the requested protocol.
+
+The "%% No connections left" reply is sent if the server is not
+accepting additional connections. This error is transient. The next
+connection attempt may succeed. Clients should wait a few seconds before 
+attempting to make another connection after receiving this error.
+
 After connecting, calls to the server can be made. Most calls require
 the user to log in, but some calls can be made without a log-in. Calls
 to the server are made by sending a reference number followed by the
@@ -1288,7 +1299,7 @@ request or an error code preceded by an indicator and the reference
 number.
 
 @example
-        server-reply ::= ok-reply | error-reply;
+        server-reply ::= ok-reply | error-reply | protocol-error;
 
         ok-reply ::=
                 ( "="
@@ -1304,6 +1315,8 @@ number.
                 )
 
         error-no ::= INT32;
+
+        protocol-error ::= "%% LysKOM protocol error."
 @end example
 
 Our notation is not flexible enough to specify the two-way nature of the
@@ -1311,8 +1324,8 @@ communication. @code{ref-no} in the reply is always the same as
 @code{ref-no} in the corresponding request. @code{reply-data} depends on
 which request was made and is specified together with each request.
 
-Please note that there is no whitespace after the initial indicator in
-the reply.
+Note that there is no whitespace after the initial indicator in the
+reply.
 
 Error reporting is covered in more detail in chapter @ref{Error Codes}.
 
@@ -1327,8 +1340,14 @@ and understand requests using the older conventions, but clients must
 conform to the current convention of separating data elements with
 spaces and terminating all requests with a linefeed character.
 
+If the request is syntactically incorrect, the server will respond with
+the string "%% LysKOM protocol error." The server will attempt to
+recover from the error, but in some cases complete recovery may not be
+possible, which may result in one or more subsequent requests being
+lost.
+
 
-@node Data Types
+@node Data Types, Protocol Requests, Introduction, Top
 @chapter Data Types
 
 The data types in protocol A come in two flavors. The first (vanilla)
@@ -1342,7 +1361,7 @@ while complex data types include things such as conferences and people.
 * Name Expansion::              
 @end menu
 
-@node Simple Data Types
+@node Simple Data Types, LysKOM Data Types, Data Types, Data Types
 @section Simple Data Types
 
 @subsection Integers
@@ -1531,7 +1550,7 @@ corresponding @code{<type>} is its type.
 Structures are transmitted as a sequence of their fields.
 
 
-@node LysKOM Data Types
+@node LysKOM Data Types, Name Expansion, Simple Data Types, Data Types
 @section LysKOM Data Types
 
 In this section the data types specific to LysKOM are defined. Most of
@@ -2711,7 +2730,7 @@ The dynamic session flags (see above.)
 What the client is doing. This string is set by the client.
 @end table
 
-@node Name Expansion
+@node Name Expansion,  , LysKOM Data Types, Data Types
 @section Name Expansion
 
 Names in LysKOM can be expanded according to two rules, regexp matching
@@ -2756,7 +2775,7 @@ equivalent according to swascii rules.
 
 
 
-@node Protocol Requests
+@node Protocol Requests, Asynchronous Messages, Data Types, Top
 @chapter Protocol Requests
 
 This chapter documents all calls that can be made to the server. All
@@ -2893,10 +2912,9 @@ in the example.
 * local-to-global::             r Map local text numbers to global ones   (103)
 * map-created-texts::           r Map texts created by a person to glogal (104)
 * set-keep-commented::          r Set how new comments protect old texts  (105)
-* set-pers-flags::              r Set the flags on a person               (106)
 @end menu
 
-@node login-old
+@node login-old, logout, Protocol Requests, Protocol Requests
 @section login-old (1) Obsolete
 
 @findex login-old
@@ -2922,7 +2940,7 @@ error-status indicates the person number.
 
 @end table
 
-@node logout
+@node logout, change-conference, login-old, Protocol Requests
 @section logout (1) Recommended
 
 @findex logout
@@ -2946,7 +2964,7 @@ places less load on the server than does creating new sessions.
 This call never fails.
 
 
-@node change-conference
+@node change-conference, change-name, logout, Protocol Requests
 @section change-conference (1) Recommended
 
 @findex change-conference
@@ -2975,7 +2993,7 @@ The user currently logged in is not a member of @code{conference}.
 @end table
 
 
-@node change-name
+@node change-name, change-what-i-am-doing, change-conference, Protocol Requests
 @section change-name (1) Recommended
 
 @findex change-name
@@ -3018,7 +3036,7 @@ There are invalid characters in @code{new-name}.
 @end table
 
 
-@node change-what-i-am-doing
+@node change-what-i-am-doing, create-person-old, change-name, Protocol Requests
 @section change-what-i-am-doing (1) Recommended
 
 @findex change-what-i-am-doing
@@ -3040,7 +3058,7 @@ using LysKOM. Clients are encouraged to use this call creatively.
 
 
 
-@node create-person-old
+@node create-person-old, get-person-stat-old, change-what-i-am-doing, Protocol Requests
 @section create-person-old (1) Obsolete (10)
 
 @findex create-person-old
@@ -3092,7 +3110,7 @@ The string @code{passwd} is not a valid password.
 
 
 
-@node get-person-stat-old
+@node get-person-stat-old, set-priv-bits, create-person-old, Protocol Requests
 @section get-person-stat-old (1) Obsolete
 
 @findex get-person-stat-old
@@ -3122,7 +3140,7 @@ Conference @code{person} does not exist or is secret.
 @code{conference} is zero.
 @end table
 
-@node set-priv-bits
+@node set-priv-bits, set-passwd, get-person-stat-old, Protocol Requests
 @section set-priv-bits (1) Recommended
 
 @findex set-priv-bits
@@ -3167,7 +3185,7 @@ and privilege level set to 6 or higher.
 @end table
 
 
-@node set-passwd
+@node set-passwd, query-read-texts-old, set-priv-bits, Protocol Requests
 @section set-passwd (1) Recommended
 
 @findex set-passwd
@@ -3214,7 +3232,7 @@ privilege level 7 or higher enabled.
 
 
 
-@node query-read-texts-old
+@node query-read-texts-old, create-conf-old, set-passwd, Protocol Requests
 @section query-read-texts-old (1) Obsolete (10)
 
 @findex query-read-texts-old
@@ -3264,7 +3282,7 @@ Conference @code{conference} does not exist, or is secret.
 
 
 
-@node create-conf-old
+@node create-conf-old, delete-conf, query-read-texts-old, Protocol Requests
 @section create-conf-old (1) Obsolete (10)
 
 @findex create-conf-old
@@ -3348,7 +3366,7 @@ The conference type has the @code{secret} bit set, but the
 
 
 
-@node delete-conf
+@node delete-conf, lookup-name, create-conf-old, Protocol Requests
 @section delete-conf (1) Recommended
 
 @findex delete-conf
@@ -3397,7 +3415,7 @@ is corrupt.)
 @end table
 
 
-@node lookup-name
+@node lookup-name, get-conf-stat-older, delete-conf, Protocol Requests
 @section lookup-name (1) Obsolete
 
 @findex lookup-name
@@ -3434,7 +3452,7 @@ has been broken into three lines to fit on the page.)
 This call always succeeds.
 
 
-@node get-conf-stat-older
+@node get-conf-stat-older, add-member-old, lookup-name, Protocol Requests
 @section get-conf-stat-older (1) Obsolete
 
 @findex get-conf-stat-older
@@ -3466,7 +3484,7 @@ returned instead of the name.
 
 
 
-@node add-member-old
+@node add-member-old, sub-member, get-conf-stat-older, Protocol Requests
 @section add-member-old (1) Obsolete (10)
 
 @i{Example:}
@@ -3534,7 +3552,7 @@ privileges to change the priorities of person @code{pers-no}.
 
 
 
-@node sub-member
+@node sub-member, set-presentation, add-member-old, Protocol Requests
 @section sub-member (1) Recommended
 
 @findex sub-member
@@ -3590,7 +3608,7 @@ Not supervisor of conference @code{conf-no} or not supervisor of person
 
 
 
-@node set-presentation
+@node set-presentation, set-etc-motd, sub-member, Protocol Requests
 @section set-presentation (1) Recommended
 
 @findex set-presentation
@@ -3656,7 +3674,7 @@ marks.
 
 
 
-@node set-etc-motd
+@node set-etc-motd, set-supervisor, set-presentation, Protocol Requests
 @section set-etc-motd (1) Recommended
 
 @findex set-etc-motd
@@ -3718,7 +3736,7 @@ marks.
 
 
 
-@node set-supervisor
+@node set-supervisor, set-permitted-submitters, set-etc-motd, Protocol Requests
 @section set-supervisor (1) Recommended
 
 @findex set-supervisor
@@ -3781,7 +3799,7 @@ conference @code{conf-no}.
 
 
 
-@node set-permitted-submitters
+@node set-permitted-submitters, set-super-conf, set-supervisor, Protocol Requests
 @section set-permitted-submitters (1) Recommended
 
 @findex set-permitted-submitters
@@ -3842,7 +3860,7 @@ Not enough permissions to change the permitted submitters of conference
 
 
 
-@node set-super-conf
+@node set-super-conf, set-conf-type, set-permitted-submitters, Protocol Requests
 @section set-super-conf (1) Recommended
 
 @findex set-super-conf
@@ -3882,7 +3900,7 @@ Not enough permissions to change super-conference of conference
 
 
 
-@node set-conf-type
+@node set-conf-type, set-garb-nice, set-super-conf, Protocol Requests
 @section set-conf-type (1) Recommended
 
 @findex set-conf-type
@@ -3935,7 +3953,7 @@ membership type.
 @end table
 
 
-@node set-garb-nice
+@node set-garb-nice, get-marks, set-conf-type, Protocol Requests
 @section set-garb-nice (1) Recommended
 
 @findex set-garb-nice
@@ -3979,7 +3997,7 @@ Not enough permissions to change the expiration time for conference
 
 
 
-@node get-marks
+@node get-marks, mark-text-old, set-garb-nice, Protocol Requests
 @section get-marks (1) Recommended
 
 @findex get-marks
@@ -4009,7 +4027,7 @@ Login required before issuing this call.
 
 
 
-@node mark-text-old
+@node mark-text-old, get-text, get-marks, Protocol Requests
 @section mark-text-old (1) Obsolete
 
 @findex mark-text-old
@@ -4047,7 +4065,7 @@ many marks, or cause the text to have too many marks.
 
 
 
-@node get-text
+@node get-text, get-text-stat-old, mark-text-old, Protocol Requests
 @section get-text (1) Recommended
 
 @findex get-text
@@ -4098,7 +4116,7 @@ Attempt to retrieve text number 0.
 
 
 
-@node get-text-stat-old
+@node get-text-stat-old, mark-as-read, get-text, Protocol Requests
 @section get-text-stat-old (1) Obsolete (10)
 
 @findex get-text-stat-old
@@ -4139,7 +4157,7 @@ Attempt to retrieve text number 0.
 
 
 
-@node mark-as-read
+@node mark-as-read, create-text-old, get-text-stat-old, Protocol Requests
 @section mark-as-read (1) Recommended
 
 @findex mark-as-read
@@ -4201,7 +4219,7 @@ One of the numbers in @code{text} is zero.
 
 
 
-@node create-text-old
+@node create-text-old, delete-text, mark-as-read, Protocol Requests
 @section create-text-old (1) Obsolete (10)
 
 @findex create-text-old
@@ -4277,7 +4295,7 @@ an unknown misc item in the misc-info list.
 
 
 
-@node delete-text
+@node delete-text, add-recipient, create-text-old, Protocol Requests
 @section delete-text (1) Recommended
 
 @findex delete-text
@@ -4311,7 +4329,7 @@ author.
 
 
 
-@node add-recipient
+@node add-recipient, sub-recipient, delete-text, Protocol Requests
 @section add-recipient (1) Recommended
 
 @findex add-recipient
@@ -4395,7 +4413,7 @@ super conf chain.
 
 
 
-@node sub-recipient
+@node sub-recipient, add-comment, add-recipient, Protocol Requests
 @section sub-recipient (1) Recommended
 
 @findex sub-recipient
@@ -4451,7 +4469,7 @@ Not supervisor of text author or conference, and not sender of text to
 @end table
 
 
-@node add-comment
+@node add-comment, sub-comment, sub-recipient, Protocol Requests
 @section add-comment (1) Recommended
 
 @findex add-comment
@@ -4503,7 +4521,7 @@ The text @code{comment-to} already has the maximum number of comments.
 
 
 
-@node sub-comment
+@node sub-comment, get-map, add-comment, Protocol Requests
 @section sub-comment (1) Obsolete (10)
 
 @findex sub-comment
@@ -4554,7 +4572,7 @@ anyway.
 
 
 
-@node get-map
+@node get-map, get-time, sub-comment, Protocol Requests
 @section get-map (1) Recommended
 
 @findex get-map
@@ -4655,7 +4673,7 @@ ever has existed in this conference.
 
 
 
-@node get-time
+@node get-time, get-info-old, get-map, Protocol Requests
 @section get-time (1) Recommended
 
 @findex get-time
@@ -4683,7 +4701,7 @@ This call always succeeds
 
 
 
-@node get-info-old
+@node get-info-old, add-footnote, get-time, Protocol Requests
 @section get-info-old (1) Obsolete (10)
 
 @findex get-info-old
@@ -4719,7 +4737,7 @@ This call always succeeds.
 
 
 
-@node add-footnote
+@node add-footnote, sub-footnote, get-info-old, Protocol Requests
 @section add-footnote (1) Recommended
 
 @findex add-footnote
@@ -4772,7 +4790,7 @@ Text @code{text-no} is already a footnote to @code{footnote-to}.
 
 
 
-@node sub-footnote
+@node sub-footnote, who-is-on-old, add-footnote, Protocol Requests
 @section sub-footnote (1) Recommended
 
 @findex sub-footnote
@@ -4820,7 +4838,7 @@ set and enabled to complete call anyway.
         
 
 
-@node who-is-on-old
+@node who-is-on-old, set-unread, sub-footnote, Protocol Requests
 @section who-is-on-old (1) Obsolete
 
 @findex who-is-on-old
@@ -4844,7 +4862,7 @@ This call always succeeds.
 
 
 
-@node set-unread
+@node set-unread, set-motd-of-lyskom, who-is-on-old, Protocol Requests
 @section set-unread (1) Recommended
 
 @findex set-unread
@@ -4890,7 +4908,7 @@ Not a member of conference @code{conf-no}.
 
 
 
-@node set-motd-of-lyskom
+@node set-motd-of-lyskom, enable, set-unread, Protocol Requests
 @section set-motd-of-lyskom (1) Recommended
 
 @findex set-motd-of-lyskom
@@ -4930,7 +4948,7 @@ The text @code{text-no} already has the maximum number of marks.
 @end table
 
 
-@node enable
+@node enable, sync-kom, set-motd-of-lyskom, Protocol Requests
 @section enable (1) Recommended
 
 @findex enable
@@ -4963,7 +4981,7 @@ Login required before issuing this call.
 @end table
 
 
-@node sync-kom
+@node sync-kom, shutdown-kom, enable, Protocol Requests
 @section sync-kom (1) Recommended
 
 @findex sync-kom
@@ -5001,7 +5019,7 @@ Administrator bit not set or privileges not enabled.
 @end table
 
 
-@node shutdown-kom
+@node shutdown-kom, broadcast, sync-kom, Protocol Requests
 @section shutdown-kom (1) Recommended
 
 @findex shutdown-kom
@@ -5035,7 +5053,7 @@ Administrator bit not set or privileges not enabled.
 @end table
 
 
-@node broadcast
+@node broadcast, get-membership-old, shutdown-kom, Protocol Requests
 @section broadcast (1) Obsolete
 
 @findex broadcast
@@ -5059,7 +5077,7 @@ Messages have been disabled.
 @end table
 
 
-@node get-membership-old
+@node get-membership-old, get-created-texts, broadcast, Protocol Requests
 @section get-membership-old (1) Obsolete (10)
 
 @findex get-membership-old
@@ -5124,7 +5142,7 @@ person's membership list.
 
 
 
-@node get-created-texts
+@node get-created-texts, get-members-old, get-membership-old, Protocol Requests
 @section get-created-texts (1) Obsolete (10)
 
 @findex get-created-texts
@@ -5196,7 +5214,7 @@ text.
 
 
 
-@node get-members-old
+@node get-members-old, get-person-stat, get-created-texts, Protocol Requests
 @section get-members-old (1) Obsolete (10)
 
 @findex get-members-old
@@ -5238,7 +5256,7 @@ The conference @code{conf} does not exist or is secret.
 
 
 
-@node get-person-stat
+@node get-person-stat, get-conf-stat-old, get-members-old, Protocol Requests
 @section get-person-stat (1) Recommended
 
 @findex get-person-stat
@@ -5275,7 +5293,7 @@ The conference @code{pers-no} does not exist or is secret.
 @end table
 
 
-@node get-conf-stat-old
+@node get-conf-stat-old, who-is-on, get-person-stat, Protocol Requests
 @section get-conf-stat-old (1) Obsolete (10)
 
 @findex get-conf-stat-old
@@ -5320,7 +5338,7 @@ The conference @code{conf-no} does not exist or is secret.
 
 
 
-@node who-is-on
+@node who-is-on, get-unread-confs, get-conf-stat-old, Protocol Requests
 @section who-is-on (1) Obsolete (9)
 
 @findex who-is-on
@@ -5342,7 +5360,7 @@ structure is described elsewhere (@pxref{LysKOM Data Types}.)
 This call always succeeds.
 
 
-@node get-unread-confs
+@node get-unread-confs, send-message, who-is-on, Protocol Requests
 @section get-unread-confs (1) Recommended
 
 @findex get-unread-confs
@@ -5387,7 +5405,7 @@ Person @code{pers-no} does not exist or is secret.
 
 
 
-@node send-message
+@node send-message, get-session-info, get-unread-confs, Protocol Requests
 @section send-message (1) Recommended
 
 @findex send-message
@@ -5434,7 +5452,7 @@ message.
 @end table
 
 
-@node get-session-info
+@node get-session-info, disconnect, send-message, Protocol Requests
 @section get-session-info (1) Obsolete
 
 @findex get-session-info
@@ -5459,7 +5477,7 @@ The session @code{session-no} does not exist.
 
 
 
-@node disconnect
+@node disconnect, who-am-i, get-session-info, Protocol Requests
 @section disconnect (1) Recommended
 
 @findex disconnect
@@ -5473,6 +5491,10 @@ server. A session can always disconnect itself, even without logging in.
 If the session is logged in as user @i{foo} it can also disconnect any
 session logged in as a person for which @i{foo} is the supervisor.
 
+Session number zero is always interpreted as the session making the
+call, so the easiest way to disconnect the current session is to
+disconnect session zero.
+
 @example
         1 56
         @t{=1 7}
@@ -5483,10 +5505,11 @@ session logged in as a person for which @i{foo} is the supervisor.
 @end example
 
 In this example the client asks for its own session number, then
-disconnects itself. The asynchronous message sent just before the
-session is disconnected is the logout message for the user that was
-logged on in the session. The ``Connection closed by foreign host.'' is
-not part of the server output. This message was generated by telnet. 
+disconnects itself (disconnection session 0 would have had the same
+effect.) The asynchronous message sent just before the session is
+disconnected is the logout message for the user that was logged on in
+the session. The ``Connection closed by foreign host.'' is not part of
+the server output. This message was generated by telnet.
 
 @unnumberedsubsec Error codes
 
@@ -5503,7 +5526,7 @@ The session @code{session-no} does not exist.
 @end table
 
 
-@node who-am-i
+@node who-am-i, set-user-area, disconnect, Protocol Requests
 @section who-am-i (1) Recommended
 
 @findex who-am-i
@@ -5529,7 +5552,7 @@ This call always succeeds.
 
 
 
-@node set-user-area
+@node set-user-area, get-last-text, who-am-i, Protocol Requests
 @section set-user-area (2) Recommended
 
 @findex set-user-area
@@ -5571,7 +5594,7 @@ Not enough access to person @code{pers-no} to complete the call.
 @end table
 
 
-@node get-last-text
+@node get-last-text, create-anonymous-text-old, set-user-area, Protocol Requests
 @section get-last-text (3) Recommended
 
 @findex get-last-text
@@ -5614,7 +5637,7 @@ This call never fails.
 
 
 
-@node create-anonymous-text-old
+@node create-anonymous-text-old, find-next-text-no, get-last-text, Protocol Requests
 @section create-anonymous-text-old (3) Obsolete (10)
 
 @findex create-anonymous-text-old
@@ -5688,7 +5711,7 @@ an unknown misc item in the misc-info list.
 
 
 
-@node find-next-text-no
+@node find-next-text-no, find-previous-text-no, create-anonymous-text-old, Protocol Requests
 @section find-next-text-no (3) Recommended
 
 @findex find-next-text-no
@@ -5721,7 +5744,7 @@ There is no text following text @code{start}.
 @end table
 
 
-@node find-previous-text-no
+@node find-previous-text-no, login, find-next-text-no, Protocol Requests
 @section find-previous-text-no (3) Recommended
 
 @findex find-previous-text-no
@@ -5755,7 +5778,7 @@ There is no text preceding text @code{start}.
 
 
 
-@node login
+@node login, who-is-on-ident, find-previous-text-no, Protocol Requests
 @section login (4) Recommended
 
 @findex login
@@ -5815,7 +5838,7 @@ Attempt to log in as person number 0.
 
 
 
-@node who-is-on-ident
+@node who-is-on-ident, get-session-info-ident, login, Protocol Requests
 @section who-is-on-ident (4) Obsolete (9)
 
 @findex who-is-on-ident
@@ -5833,7 +5856,7 @@ sessions.
 This call always succeeds.
 
 
-@node get-session-info-ident
+@node get-session-info-ident, re-lookup-person, who-is-on-ident, Protocol Requests
 @section get-session-info-ident (4) Obsolete (9)
 
 @findex get-session-info-ident
@@ -5855,7 +5878,7 @@ The session @code{session-no} does not exist.
 @end table
 
 
-@node re-lookup-person
+@node re-lookup-person, re-lookup-conf, get-session-info-ident, Protocol Requests
 @section re-lookup-person (5) Obsolete
 
 @findex re-lookup-person
@@ -5878,7 +5901,7 @@ not a correct regexp.
 @end table
 
 
-@node re-lookup-conf
+@node re-lookup-conf, lookup-person, re-lookup-person, Protocol Requests
 @section re-lookup-conf (5) Obsolete
 
 @findex re-lookup-conf
@@ -5903,7 +5926,7 @@ not a correct regexp.
 
 
 
-@node lookup-person
+@node lookup-person, lookup-conf, re-lookup-conf, Protocol Requests
 @section lookup-person (6) Obsolete
 
 @findex lookup-person
@@ -5924,7 +5947,7 @@ This call always succeeds.
 
 
 
-@node lookup-conf
+@node lookup-conf, set-client-version, lookup-person, Protocol Requests
 @section lookup-conf (6) Obsolete
 
 @findex lookup-conf
@@ -5945,7 +5968,7 @@ This call always succeeds.
 
 
 
-@node set-client-version
+@node set-client-version, get-client-name, lookup-conf, Protocol Requests
 @section set-client-version (6) Recommended
 
 @findex set-client-version
@@ -5993,7 +6016,7 @@ is undefined.
 
 @end table
 
-@node get-client-name
+@node get-client-name, get-client-version, set-client-version, Protocol Requests
 @section get-client-name (6) Recommended
 
 @findex get-client-name
@@ -6020,7 +6043,7 @@ The session @code{session} does not exist.
 @end table
 
 
-@node get-client-version
+@node get-client-version, mark-text, get-client-name, Protocol Requests
 @section get-client-version (6) Recommended
 
 @findex get-client-version
@@ -6048,7 +6071,7 @@ The session @code{session} does not exist.
 
 
 
-@node mark-text
+@node mark-text, unmark-text, get-client-version, Protocol Requests
 @section mark-text (4) Recommended
 
 @findex mark-text
@@ -6096,7 +6119,7 @@ Already the maximum number of marks on text @code{text}.
 
 
 
-@node unmark-text
+@node unmark-text, re-z-lookup, mark-text, Protocol Requests
 @section unmark-text (4) Recommended
 
 @findex unmark-text
@@ -6132,7 +6155,7 @@ The text @code{text-no} was not marked.
 @end table
 
 
-@node re-z-lookup
+@node re-z-lookup, get-version-info, unmark-text, Protocol Requests
 @section re-z-lookup (7) Recommended
 
 @findex re-z-lookup
@@ -6184,7 +6207,7 @@ not a correct regexp.
 
 
 
-@node get-version-info
+@node get-version-info, lookup-z-name, re-z-lookup, Protocol Requests
 @section get-version-info (7) Recommended
 
 @findex get-version-info
@@ -6212,7 +6235,7 @@ This call always succeeds.
 
 
 
-@node lookup-z-name
+@node lookup-z-name, set-last-read, get-version-info, Protocol Requests
 @section lookup-z-name (7) Recommended
 
 @findex lookup-z-name
@@ -6256,7 +6279,7 @@ and persons matching the pattern ``T C''.
 This call always succeeds.
 
 
-@node set-last-read
+@node set-last-read, get-uconf-stat, lookup-z-name, Protocol Requests
 @section set-last-read (8) Recommended
 
 @findex set-last-read
@@ -6298,7 +6321,7 @@ Not a member of conference @code{conference}.
 
 
 
-@node get-uconf-stat
+@node get-uconf-stat, set-info, set-last-read, Protocol Requests
 @section get-uconf-stat (8) Recommended
 
 @findex get-uconf-stat
@@ -6346,7 +6369,7 @@ The conference @code{conference} does not exist or is secret.
 
 
 
-@node set-info
+@node set-info, accept-async, get-uconf-stat, Protocol Requests
 @section set-info (9) Recommended
 
 @findex set-info
@@ -6398,7 +6421,7 @@ day, and the current implementation of the server does accept MOTD to be
 0.
 @end table
 
-@node accept-async
+@node accept-async, query-async, set-info, Protocol Requests
 @section accept-async (9) Recommended
 
 @findex accept-async
@@ -6454,7 +6477,7 @@ overrun.
 @end table
 
 
-@node query-async
+@node query-async, user-active, accept-async, Protocol Requests
 @section query-async (9) Recommended
 
 @findex query-async
@@ -6489,7 +6512,7 @@ list of asynchronous messages that servers should preselect.
 This call always succeeds.
 
 
-@node user-active
+@node user-active, who-is-on-dynamic, query-async, Protocol Requests
 @section user-active (9) Recommended
 
 @findex user-active
@@ -6513,7 +6536,7 @@ avoid excessive network and server load.
 This call always succeeds.
 
 
-@node who-is-on-dynamic
+@node who-is-on-dynamic, get-static-session-info, user-active, Protocol Requests
 @section who-is-on-dynamic (9) Recommended
 
 @findex who-is-on-dynamic
@@ -6548,7 +6571,7 @@ have the proper visibility).
 This call always succeeds.
 
 
-@node get-static-session-info
+@node get-static-session-info, get-collate-table, who-is-on-dynamic, Protocol Requests
 @section get-static-session-info (9) Recommended
 
 @findex get-static-session-info
@@ -6573,7 +6596,7 @@ The session @code{session-no} does not exist.
 
 
 
-@node get-collate-table
+@node get-collate-table, create-text, get-static-session-info, Protocol Requests
 @section get-collate-table (10) Recommended
 
 @findex get-collate-table
@@ -6598,7 +6621,7 @@ This call always succeeds.
 
 
 
-@node create-text
+@node create-text, create-anonymous-text, get-collate-table, Protocol Requests
 @section create-text (10) Recommended
 
 @findex create-text
@@ -6662,10 +6685,12 @@ One of the aux-items in @code{aux-items} is illegal. The tag might be
 out of range, the item not applicable to texts or whatever
 @item aux-item-permission
 One of the items looks valid but could not be created anyway.
+@item long-array
+Too many misc-items or aux-items were specified.
 @end table
 
 
-@node create-anonymous-text
+@node create-anonymous-text, create-conf, create-text, Protocol Requests
 @section create-anonymous-text (10) Recommended
 
 @findex create-anonymous-text
@@ -6730,7 +6755,7 @@ One of the items looks valid but could not be created anyway.
 
 
 
-@node create-conf
+@node create-conf, create-person, create-anonymous-text, Protocol Requests
 @section create-conf (10) Recommended
 
 @findex create-conf
@@ -6786,7 +6811,7 @@ One of the items looks valid but could not be created anyway.
 
 
 
-@node create-person
+@node create-person, get-text-stat, create-conf, Protocol Requests
 @section create-person (10) Recommended
 
 @findex create-person
@@ -6844,7 +6869,7 @@ One of the items looks valid but could not be created anyway.
 
 
 
-@node get-text-stat
+@node get-text-stat, get-conf-stat, create-person, Protocol Requests
 @section get-text-stat (10) Recommended
 
 @findex get-text-stat
@@ -6872,7 +6897,7 @@ Attempt to retrieve text number 0.
 
 
 
-@node get-conf-stat
+@node get-conf-stat, modify-text-info, get-text-stat, Protocol Requests
 @section get-conf-stat (10) Recommended
 
 @findex get-conf-stat
@@ -6893,7 +6918,7 @@ The conference @code{conf-no} does not exist or is secret.
 
 
 
-@node modify-text-info
+@node modify-text-info, modify-conf-info, get-conf-stat, Protocol Requests
 @section modify-text-info (10) Recommended
 
 @findex modify-text-info
@@ -6927,7 +6952,7 @@ One of the items in @code{add} is illegal for some reason.
 
 
 
-@node modify-conf-info
+@node modify-conf-info, get-info, modify-text-info, Protocol Requests
 @section modify-conf-info (10) Recommended
 
 @findex modify-conf-info
@@ -6960,7 +6985,7 @@ One of the items in @code{add} is illegal for some reason.
 
 
 
-@node get-info
+@node get-info, modify-system-info, modify-conf-info, Protocol Requests
 @section get-info (10) Recommended
 
 @findex get-info
@@ -6981,7 +7006,7 @@ This call always succeeds.
 
 
 
-@node modify-system-info
+@node modify-system-info, query-predefined-aux-items, get-info, Protocol Requests
 @section modify-system-info (10) Recommended
 
 @findex modify-system-info
@@ -7009,7 +7034,7 @@ Attempt to delete an undeletable item or create an uncreateable item.
 @end table
 
 
-@node query-predefined-aux-items
+@node query-predefined-aux-items, set-expire, modify-system-info, Protocol Requests
 @section query-predefined-aux-items (10) Recommended
 
 @findex query-predefined-aux-items
@@ -7029,7 +7054,7 @@ This call always succeeds.
 
 
 
-@node set-expire
+@node set-expire, query-read-texts, query-predefined-aux-items, Protocol Requests
 @section set-expire (10) Recommended
 
 @findex set-expire
@@ -7055,7 +7080,7 @@ Not supervisor of conference @code{conf-no} and not privileged enough to
 complete the call anyway.
 @end table
 
-@node query-read-texts
+@node query-read-texts, get-membership, set-expire, Protocol Requests
 @section query-read-texts (10) Recommended
 
 @findex query-read-texts
@@ -7106,7 +7131,7 @@ privileges to find out if @code{person} is a member.
 @end table
 
 
-@node get-membership
+@node get-membership, add-member, query-read-texts, Protocol Requests
 @section get-membership (10) Recommended
 
 @findex get-membership
@@ -7170,7 +7195,7 @@ person's membership list.
 @end table
 
 
-@node add-member
+@node add-member, get-members, get-membership, Protocol Requests
 @section add-member (10) Recommended
 
 @findex add-member
@@ -7244,7 +7269,7 @@ privileges to change the priorities of person @code{pers-no}.
 
 
 
-@node get-members
+@node get-members, set-membership-type, add-member, Protocol Requests
 @section get-members (10) Recommended
 
 @findex get-members
@@ -7289,7 +7314,7 @@ The conference @code{conf} does not exist or is secret.
 @end table
 
 
-@node set-membership-type
+@node set-membership-type, local-to-global, get-members, Protocol Requests
 @section set-membership-type (10) Recommended
 
 @findex set-membership-type
@@ -7335,7 +7360,7 @@ restrictions set on the server or on the conference @code{conf}
 @end table
 
 
-@node local-to-global
+@node local-to-global, map-created-texts, set-membership-type, Protocol Requests
 @section local-to-global (10) Recommended
 
 @findex local-to-global
@@ -7432,7 +7457,7 @@ ever existed in the conference.
 
 @end table
 
-@node map-created-texts
+@node map-created-texts, set-keep-commented, local-to-global, Protocol Requests
 @section map-created-texts (10) Recommended
 
 @findex map-created-texts
@@ -7482,7 +7507,7 @@ information about the texts in the conference.
 
 @end table
 
-@node set-keep-commented
+@node set-keep-commented,  , map-created-texts, Protocol Requests
 @section set-keep-commented (10) Recommended
 
 @findex set-keep-commented
@@ -7509,7 +7534,11 @@ complete the call anyway.
 @end table
 
 
-@node set-pers-flags, , set-keep-commented, Protocol Requests
+@menu
+* set-pers-flags::              
+@end menu
+
+@node set-pers-flags,  , set-keep-commented, set-keep-commented
 @subsection set-pers-flags (10) Recommended
 
 @findex set-pers-flags
@@ -7538,7 +7567,7 @@ flags.
 @end table
 
 
-@node Asynchronous Messages
+@node Asynchronous Messages, Error Codes, Protocol Requests, Top
 @chapter Asynchronous Messages
 
 Asynchronous messages are information messages sent from the server to
@@ -7594,7 +7623,7 @@ reject them if a client uses it as an argument to
 -------------------------------------------------------------------------------
 @end menu
 
-@node async-new-text-old
+@node async-new-text-old, async-i-am-off, Asynchronous Messages, Asynchronous Messages
 @section async-new-text-old (1) Obsolete (10)
 
 @example
@@ -7610,7 +7639,7 @@ In protocol version 10 this call has been superceded by @ref{async-new-text}.
 
 
 
-@node async-i-am-off
+@node async-i-am-off, async-i-am-on-obsolete, async-new-text-old, Asynchronous Messages
 @section async-i-am-off (1) Obsolete
 
 @example
@@ -7622,7 +7651,7 @@ call @code{Async logout}.
 
 
 
-@node async-i-am-on-obsolete
+@node async-i-am-on-obsolete, async-new-name, async-i-am-off, Asynchronous Messages
 @section async-i-am-on-obsolete (1) Obsolete
 
 @example
@@ -7637,7 +7666,7 @@ working conference. It has been replaced by call number 6,
 
 
 
-@node async-new-name
+@node async-new-name, async-i-am-on, async-i-am-on-obsolete, Asynchronous Messages
 @section async-new-name (1) Recommended
 
 @example
@@ -7653,7 +7682,7 @@ old name in @code{old-name} and the new name in @code{new-name}.
 
 
 
-@node async-i-am-on
+@node async-i-am-on, async-sync-db, async-new-name, Asynchronous Messages
 @section async-i-am-on (1) Recommended
 
 @example
@@ -7667,7 +7696,7 @@ FIXME: can the username change?
 
 
 
-@node async-sync-db
+@node async-sync-db, async-leave-conf, async-i-am-on, Asynchronous Messages
 @section async-sync-db (1) Recommended
 
 @example
@@ -7680,7 +7709,7 @@ difference between the two cases.
 
 
 
-@node async-leave-conf
+@node async-leave-conf, async-login, async-sync-db, Asynchronous Messages
 @section async-leave-conf (1) Recommended
 
 @example
@@ -7710,7 +7739,7 @@ This message is not sent if a membership is transformed from an active
 to a passive membership.
 
 
-@node async-login
+@node async-login, async-broadcast, async-leave-conf, Asynchronous Messages
 @section async-login (1) Recommended
 
 @example
@@ -7724,7 +7753,7 @@ logging in is sent in @code{pers-no}.
 
 
 
-@node async-broadcast
+@node async-broadcast, async-rejected-connection, async-login, Asynchronous Messages
 @section async-broadcast (1) Obsolete
 
 @example
@@ -7739,7 +7768,7 @@ to all LysKOM users, but is no longer used.
 
 
 
-@node async-rejected-connection
+@node async-rejected-connection, async-send-message, async-broadcast, Asynchronous Messages
 @section async-rejected-connection (1) Recommended
 
 @example
@@ -7753,7 +7782,7 @@ to allow more connections.
 
 
 
-@node async-send-message
+@node async-send-message, async-logout, async-rejected-connection, Asynchronous Messages
 @section async-send-message (1) Recommended
 
 @example
@@ -7771,7 +7800,7 @@ of the mailbox conference.
 
 
 
-@node async-logout
+@node async-logout, async-deleted-text, async-send-message, Asynchronous Messages
 @section async-async-logout (1) Recommended
 
 @example
@@ -7786,7 +7815,7 @@ if there is nobody logged on in the session.
 
 
 
-@node async-deleted-text
+@node async-deleted-text, async-new-text, async-logout, Asynchronous Messages
 @section async-deleted-text (10) Recommended
 
 @example
@@ -7800,7 +7829,7 @@ deleted is sent in @code{text-no} and the text stat in @code{text-stat.}
 
 
 
-@node async-new-text
+@node async-new-text, async-new-recipient, async-deleted-text, Asynchronous Messages
 @section async-new-text (10) Recommended
 
 @example
@@ -7813,7 +7842,7 @@ number @code{text-no}, and the text stat is @code{text-stat}. The
 message is sent to all logged-in members of any recipient of the text.
 
 
-@node async-new-recipient
+@node async-new-recipient, async-sub-recipient, async-new-text, Asynchronous Messages
 @section async-new-recipient (10) Recommended
 
 @example
@@ -7830,7 +7859,7 @@ recipient.
 
 
 
-@node async-sub-recipient
+@node async-sub-recipient, async-new-membership, async-new-recipient, Asynchronous Messages
 @section async-sub-recipient (10) Recommended
 
 @example
@@ -7846,7 +7875,7 @@ recipients of the text that are permitted to know about the new
 recipient.
 
 
-@node async-new-membership
+@node async-new-membership,  , async-sub-recipient, Asynchronous Messages
 @section async-new-membership (10) Recommended
 
 @example
@@ -7863,7 +7892,7 @@ See also @pxref{async-leave-conf}.
 
 
 
-@node Error Codes
+@node Error Codes, LysKOM Content Types, Asynchronous Messages, Top
 @chapter Error Codes
 
 
@@ -7872,16 +7901,28 @@ error reply, as defined below and earlier (@pxref{Client-Server
 Dialog}).
 
 @example
-        error-reply ::=
+        error-reply ::= normal-error | special-error
+
+        normal-error ::=
                 ( "%"
                   ref-no        :       INT32;
                   error-no      :       Error-No;
                   error-status  :       INT32;
                 )
 
+        special-error ::=   "%% LysKOM protocol error."
+                        |   "%%Insane token length."
+                        |   "%%Insane array size."
+                        |   "%%No connections left."
+
         error-no ::= INT32;
 @end example
 
+The server may return two different types of errors. Normal errors are
+replies to syntactically correct calls to the server. Special errors are 
+replies to syntactically incorrect calls and responses to exceptional
+conditions. 
+
 A client should be prepared for any error code in response to any call,
 no matter if the response makes any sense or not. The value returned in
 @code{error-status} was more or less undefined before protocol version
@@ -7903,6 +7944,58 @@ completely since bugs might cause the wrong error message to be sent or
 new errors might be added later on.
 
 
+@menu
+* Special Errors::              
+* Normal Errors::               
+@end menu
+
+@node Special Errors, Normal Errors, Error Codes, Error Codes
+@section Special Errors
+
+Special errors are sent in reply to syntactically incorrect calls to the 
+server. With the exception of the "No connections left" message, these
+should never appear in the client-server dialog. If they do, there is
+probably a bug in the client. 
+
+@table @asis
+@item "%% LysKOM protocol error."
+The client has sent a request that does not comply with protocol A. The
+server will attempt to recover from this error, but additional calls may 
+be silently lost, and the server may send replies that the client does
+not expect. This error is also returned when the client sends an array
+that is longer than the maximum allowed by the server.
+
+@item "%%No connections left."
+This error is only sent when the client attempts to connect to the
+server. It indicates that the server is not accepting additional
+connections. This error is transient: the client may be able to connect
+later. Clients should not attempt to connect immediately after
+receiving this message.
+
+@item "%%Insane token length."
+The client has sent a single token that is insanely long. Typically this 
+means that the client has sent several kilobytes worth of digits, or
+something similar. This is never returned for long strings. The server
+will automatically disconnect a client who sends a token with an insane
+length.
+
+@item "%%Insane array size."
+The client has send an array with a negative length. The server is not
+easily fooled. The server will automatically disconnect a client who
+sends an array with an insane length.
+
+@end table
+
+
+@node Normal Errors,  , Special Errors, Error Codes
+@section Normal Errors
+
+Normal errors are sent in reply to syntactically correct calls to the
+server. The client should accept any error code in response to any call, 
+even if the error code in question is not listed in the description of
+the call, and even if the error code in question is not defined in the
+protocol specification yet.
+
 @table @code
 
 @item no-error (0)
@@ -8011,7 +8104,7 @@ index of the illegal item.
 
 @item illegal-info-type (26)
 Attempt to use a Misc-Info type that the server knows nothing about.
-@code{error-status} is undefined.
+@code{error-status} is the type.
 
 @item already-recipient (27)
 Attempt to add a recipient that is already a recipient of the same type.
@@ -8143,7 +8236,7 @@ specific call.
 
 
 
-@node LysKOM Content Types
+@node LysKOM Content Types, The User Area, Error Codes, Top
 @chapter LysKOM Content Types
 
 LysKOM defines a few special content types for texts. They are all
@@ -8157,7 +8250,7 @@ text/html.
 * Conference Lists (x-kom/conflist)::  
 @end menu
 
-@node Reformattable Text (x-kom/basic)
+@node Reformattable Text (x-kom/basic), The User Area (x-kom/user-area), LysKOM Content Types, LysKOM Content Types
 @section Reformattable Text
 
 This type of content corresponds to the mime type x-kom/basic. It is raw
@@ -8181,13 +8274,13 @@ that matched that regexp is to be prefixed to all lines of the
 paragraph.
 @end itemize
 
-@node The User Area (x-kom/user-area)
+@node The User Area (x-kom/user-area), Conference Lists (x-kom/conflist), Reformattable Text (x-kom/basic), LysKOM Content Types
 @section The User Area
 
-@node Conference Lists (x-kom/conflist)
+@node Conference Lists (x-kom/conflist),  , The User Area (x-kom/user-area), LysKOM Content Types
 @section Conference Lists
 
-@node The User Area
+@node The User Area, Writing Clients, LysKOM Content Types, Top
 @chapter The User Area
 
 The user area is a regular text that is used to store client-specific
@@ -8307,7 +8400,7 @@ The default mark to set on marked texts.
 
 
 
-@node Writing Clients
+@node Writing Clients, Importing and Exporting E-Mail, The User Area, Top
 @chapter Writing Clients
 
 This chapter is not really part of the protocol specification, but
@@ -8318,7 +8411,7 @@ it contains some information that may be useful for client writers.
 * Client Conventions::          Conventions clients should follow.
 @end menu
 
-@node Common Commands
+@node Common Commands, Client Conventions, Writing Clients, Writing Clients
 @section Common Commands
 
 Most clients will implement certain commands. This main purpose of this
@@ -8331,17 +8424,71 @@ to answer some questions that seem to come up over and over again.
 * Review the last N by FOO to BAR::  
 @end menu
 
-@node What do I have unread
+@node What do I have unread, Only read the most recent N texts, Common Commands, Common Commands
 @subsection What do I have unread
 
-@node Only read the most recent N texts
+Each person has a membership list containing the conferences the persin
+is a member of. Each element is an object of type Membership. Among
+other things it contains the number of the conference, the priority of
+the membership, when the person most recently marked a text as read in
+the conference, and which texts the person has read.
+
+The list of read texts consists of two parts: a local text number called
+@code{last-text-read} and a list of local text numbers called
+@code{read-texts}. The person has marked all texts up to and including
+@code{last-text-read} as read, and also the texts listed in
+@code{read-texts}. All other texts in the conference are unread. Clients
+can use either the @code{@ref{query-read-texts}} or
+@code{@ref{get-membership}} calls to get membership data.
+
+The standard procedure for finding out which texts are unread is the
+following:
+
+@enumerate
+@item Call @code{@ref{get-unread-confs}} for the person. 
+This returns a list of conferences in which the person may have unread
+texts. This call may return conferences that do not contain any unread
+texts, but it will never forget to return a conference that does contain 
+an unread text.
+
+@item Call @code{@ref{query-read-texts}} for each conference returned in 
+the previous step. This will return the membership data for all the
+conferences that may contain unread texts.
+
+@item Call @code{@ref{get-conf-stat}} for each conference returned in
+the first step. The conference status will be needed shortly. Repeat the 
+following steps for each conference.
+
+@item Compare the highest existing local number in the conference (from
+the conference status) with the @code{last-text-read} field for the
+corresponding membership. If the highest existing local text is higher
+than @code{last-text-read}, the conference may contain unread texts.
+
+@item Get part of the local to global map from the conference starting
+at @code{last-text-read} and ending at the highest existing local
+number. Every local number in the map that is not read according to the
+membership data and that has a mapping to a global number is an unread
+text. You might say that you remove the read texts from the map to get
+the unread texts.
+
+@end enumerate
+
+Take care not to call get-map or get-membership too much since they tend 
+to be expensive operations. Use @code{get-unread-confs} and
+@code{query-read-texts} to minimize the work. Another point to remember
+is that the server will send asynchronous messages with information
+about new texts. Clients need to listen to these messages.
+
+
+
+@node Only read the most recent N texts, Review the last N by FOO to BAR, What do I have unread, Common Commands
 @subsection Only read the most recent N texts
 
 
-@node Review the last N by FOO to BAR
+@node Review the last N by FOO to BAR,  , Only read the most recent N texts, Common Commands
 @subsection Review the last N by FOO to BAR
 
-@node Client Conventions
+@node Client Conventions,  , Common Commands, Writing Clients
 @section Client Conventions
 
 There are certain conventions that most clients follow, and that users
@@ -8356,7 +8503,7 @@ will go away when the protocol is updated to correct these deficiencies.
 @end menu
 
 
-@node Text formatting
+@node Text formatting, Content type specification, Client Conventions, Client Conventions
 @subsection Text formatting
 
 Traditionally the only clients for LysKOM were text-based and only
@@ -8384,7 +8531,7 @@ The same conventions apply to messages sent with the
 @pxref{send-message} call.
 
 
-@node Content type specification
+@node Content type specification, Remote control, Text formatting, Client Conventions
 @subsection Content type specification
 
 This convention is understood by all popular clients. If the first line
@@ -8397,7 +8544,7 @@ aux-items to specify content type instead.
 
 
 
-@node Remote control
+@node Remote control,  , Content type specification, Client Conventions
 @subsection Remote control
 
 This convention is only implemented by the Emacs-Lisp client, but since
@@ -8406,7 +8553,7 @@ between clients, transferred by messages sent using
 @pxref{send-message}.
 
 
-@node Importing and Exporting E-Mail
+@node Importing and Exporting E-Mail, Type Index, Writing Clients, Top
 @chapter Importing and Exporting E-Mail
 
 E-mail importing and exporting is not implemented. This chapter contains 
@@ -8579,12 +8726,12 @@ function exporter ()
 
 
 
-@node Type Index
+@node Type Index, Request Index, Importing and Exporting E-Mail, Top
 @chapter Type Index
 
 @printindex tp
 
-@node Request Index
+@node Request Index,  , Type Index, Top
 @chapter Request Index
 
 @printindex fn
diff --git a/doc/lyskomd.texi b/doc/lyskomd.texi
index 3c1b81421439d8be2b8995cff944d4721462da07..33ac9b7ae9355dd2ddb17ae122ed52da7c0b9f96 100644
--- a/doc/lyskomd.texi
+++ b/doc/lyskomd.texi
@@ -1,5 +1,5 @@
 \input texinfo
-@c $Id: lyskomd.texi,v 1.16 1999/05/16 19:12:10 ceder Exp $
+@c $Id: lyskomd.texi,v 1.17 1999/05/18 13:06:21 byers Exp $
 @c %**start of header
 @setfilename lyskomd.info
 @include version.texi
@@ -50,7 +50,7 @@ another language under the same conditions as for modified versions.
 @end titlepage
 
 @ifinfo
-@node Top
+@node Top, Copying, (dir), (dir)
 @top lyskomd
 
 lyskomd is a server for the LysKOM conferencing system. This info file
@@ -65,12 +65,14 @@ documents version @value{VERSION} of lyskomd.
 * Invoking updateLysKOM::       How to run updateLysKOM.
 * Invoking komrunning::         How to run komrunning.
 * Administration::              Administering a LysKOM server.
-* Bugs::                        Known bugs.
+* Bugs::                        Known bugs in lyskomd.
+* DBCK Reference::              Checking and repairing the database.
+* Hacking::                     Notes for server developers.
 @end menu
 
 @end ifinfo
 
-@node Copying
+@node Copying, Overview, Top, Top
 @chapter Copying
 
 lyskomd is free software. It is distributed under the Gnu General Public 
@@ -78,7 +80,7 @@ License version 2. The file COPYING in the top level of the distribution
 contains the text of the license.
 
 
-@node Overview
+@node Overview, Installation, Copying, Top
 @chapter Overview
 
 LysKOM is a conferencing system@footnote{Or in modern terms, enabling
@@ -117,7 +119,7 @@ future.
 
 
 
-@node Installation
+@node Installation, Configuration, Overview, Top
 @chapter Installation
 
 Instructions for compiling and installing lyskomd are in the file
@@ -125,7 +127,7 @@ INSTALL, located in the top level of the lyskomd distribution.
 Installation should be straightforward on most platforms.
 
 
-@node Configuration
+@node Configuration, Running lyskomd, Installation, Top
 @chapter Configuration
 
 There are two configuration files for lyskomd. One defines the server
@@ -138,7 +140,7 @@ Aux-Item List,The Aux-Item List}.
 @end menu
 
 
-@node Server Configuration File
+@node Server Configuration File, Aux-Item Definition File, Configuration, Configuration
 @section Server Configuration File
 
 The server reads its configuration from a configuration file. The
@@ -156,7 +158,7 @@ ignored.
 * Parameters::                  Valid configuration parameters.
 @end menu
 
-@node Parameter Types
+@node Parameter Types, Parameters, Server Configuration File, Server Configuration File
 @subsection Parameter Types
 
 Every parameter has a type. The legal types are:
@@ -189,7 +191,7 @@ text number or perhaps a timeout.
 @end table
 
 
-@node Parameters
+@node Parameters,  , Parameter Types, Server Configuration File
 @subsection Parameters
 
 @table @code
@@ -601,7 +603,7 @@ status file.  Actually, it is the age of the status file (named with
 @end table
 
 
-@node Aux-Item Definition File
+@node Aux-Item Definition File,  , Server Configuration File, Configuration
 @section Aux-Item Definition File
 
 The default aux-item definition file should not be changed unless it is
@@ -794,7 +796,7 @@ validation function.
 
 
 
-@node Running lyskomd
+@node Running lyskomd, Invoking updateLysKOM, Configuration, Top
 @chapter Running lyskomd
 
 This section explains how to run lyskomd, the files it uses and how it
@@ -807,7 +809,7 @@ can be controlled while running.
 @end menu
 
 
-@node Invoking lyskomd
+@node Invoking lyskomd, Signals, Running lyskomd, Running lyskomd
 @section Invoking lyskomd
 
 @example
@@ -828,7 +830,7 @@ The optional @var{config-file} argument can be used to specify the server
 configuration file. @xref{Server Configuration File}.
 
 
-@node Signals
+@node Signals, Files, Invoking lyskomd, Running lyskomd
 @section Signals
 
 It is possible to control some aspects of lyskomd using Unix signals.
@@ -852,7 +854,7 @@ until the child is done and then continues.
 @end table
 
 
-@node Files
+@node Files,  , Signals, Running lyskomd
 @section Files Used by lyskomd
 
 All file names can be changed in the server configuration file.
@@ -894,7 +896,7 @@ the server configuration file.
 @end table
 
 
-@node Invoking updateLysKOM
+@node Invoking updateLysKOM, Invoking komrunning, Running lyskomd, Top
 @chapter Invoking updateLysKOM
 
 @example
@@ -915,7 +917,7 @@ number and exit.
 @code{updateLysKOM} is normally run from @code{cron};
 @pxref{Administration}.
 
-@node Invoking komrunning
+@node Invoking komrunning, Administration, Invoking updateLysKOM, Top
 @chapter Invoking komrunning
 
 @example
@@ -944,7 +946,7 @@ the boot sequence.
 @samp{-v} and @samp{-V} causes @code{komrunning} to report its version
 number and exit.
 
-@node Administration
+@node Administration, Bugs, Invoking komrunning, Top
 @chapter Administration
 
 The first thing you will have to do is to follow the instructions in the
@@ -1015,7 +1017,8 @@ by @code{updateLysKOM} the next time it is run.  @code{komrunning} only
 removes the lock file.
 
 
-@node Bugs
+@node Bugs, DBCK Reference, Administration, Top
+@comment  node-name,  next,  previous,  up
 @chapter Known Bugs
 
 @itemize @bullet
@@ -1036,5 +1039,1358 @@ the edges.
 
 
 
+
+@c ======================================================================
+@c ======================================================================
+@c ==                                                                  ==
+@c ==                            DBCK REFERENCE                        ==
+@c ==                                                                  ==
+@c ======================================================================
+@c ======================================================================
+
+@node DBCK Reference, Hacking, Bugs, Top
+@comment  node-name,  next,  previous,  up
+@chapter DBCK Reference
+
+dbck is a program that can is used for minor database maintenance tasks
+and for repairing a corrupt lyskomd database.
+
+@menu
+* DBCK Overview::               Overview of dbck.
+* Invoking dbck::               How to run dbck.
+* DBCK Notes::                  Notes about running dbck.
+* DBCK Files::                  Files used by dbck.
+* DBCK Bugs::                   Known bugs in dbck.
+@end menu
+
+
+@node DBCK Overview, Invoking dbck, DBCK Reference, DBCK Reference
+@comment  node-name,  next,  previous,  up
+@section Overview
+
+The dbck program is used for minor maintenance of the LysKOM database
+and for repairing corrupt databases. In brief it performs the following
+functions:
+
+@itemize @bullet
+@item Compact the text file to remove deleted texts.
+@item Repair inconsistent membership information.
+@item Repair invalid recipients
+@item Repair inconsistent comment links
+@item Correct invalid local text numbers
+@item Correct invalid text maps
+@item Set special conferences
+@item Convert between database formats
+@end itemize
+
+
+@node Invoking dbck, DBCK Notes, DBCK Overview, DBCK Reference
+@comment  node-name,  next,  previous,  up
+@section Invoking dbck
+
+The functionality of dbck is controlled through command-line switches.
+These are documented below.
+
+If @code{dbck} is invoked without any options it will read the database
+and report on its integrity.  No files will be modified.
+
+@menu
+* General Options::             Controlling the overall behavior of dbck.
+* Database Repair Options::     Repairing errors in the LysKOM database.
+* Format Conversion Options::   Converting the database file to a new format.
+* Database Maintenance Options::  Options for database maintenance.
+* Reporting Options::           Options controlling status reports.
+@end menu
+
+
+@node General Options, Database Repair Options, Invoking dbck, Invoking dbck
+@comment  node-name,  next,  previous,  up
+@subsection General Options
+
+These options control the general behavior of lyskomd.
+
+@table @asis
+@item @code{-h} or @code{--help}
+Give a usage message (which includes the version number and the
+compiled-in default location of the config file) and exit immediately.
+
+@item @code{-v} or @code{--verbose}
+Verbose mode. Report not only errors but the status of the database.
+
+@item @code{-F} or @code{--force-output}
+This option forces dbck to write the database file. Normally @code{dbck} 
+will only write a new database file if changes have been made for some
+other reason. If you want to simply convert a database from one version
+to another, you will probably have to give this option.
+@end table
+
+
+@node Database Repair Options, Format Conversion Options, General Options, Invoking dbck
+@comment  node-name,  next,  previous,  up
+@subsection Database Repair Options
+
+The following options control database repair.
+
+@table @asis
+@item @code{-i} or @code{--interactive}
+Run interactively. If any inconsistency is found, a remedial cure will
+be suggested and the user must confirm the correction.
+
+@item @code{-r} or @code{--auto-repair}
+Repair simple errors without asking.
+
+@item @code{-c} or @code{--set-change-name}
+Consider it an error if the @code{change-name} capability of a person is 
+not set. Due to a bug that capability was never set for newly created
+persons in release 1.6.1 of lyskomd. This option can be used to repair
+the damage.
+@end table
+
+
+@node Format Conversion Options, Database Maintenance Options, Database Repair Options, Invoking dbck
+@comment  node-name,  next,  previous,  up
+@subsection Format Conversion Options
+
+dbck can be used to conver the LysKOM database from one storage format
+to another. This is necessary only when moving the database to a new
+server version.
+
+@table @asis
+@item @code{-F} or @code{--force-output}
+This option forces dbck to write the database file. Normally @code{dbck} 
+will only write a new database file if changes have been made for some
+other reason. If you want to simply convert a database from one version
+to another, you will probably have to give this option.
+
+@item @code{-o} or @code{--output-version}
+This option is used to set the output version of the database. This
+option will normally be used in conjunction with the @code{-F} option.
+
+Version 1.9 of @code{lyskomd} requires database version 1; version 2.0
+requires database version 2. Versions of @code{lyskomd} prior to 1.9
+requires database version 0. Note that information is irrevocably lost
+when converting from a higher to a lower database version. This options
+requires an argument: the output format version.
+@end table
+
+
+@node Database Maintenance Options, Reporting Options, Format Conversion Options, Invoking dbck
+@comment  node-name,  next,  previous,  up
+@subsection Database Update Options
+
+dbck can be used to update certain aspects of the database that either
+were impossible to update in early versions of protocol A or that are
+inconvenient in all protocol versions.
+
+@table @asis
+@item @code{-g} or @code{--compact-text-mass}
+Do garbage collection on the texts part of the database. This removes
+all unreferenced texts from the database. 
+
+@item @code{-P} or @code{--clear-password}
+Clear the password of a specified user. This option is silently ignored
+if the user does not exist. This option requires an argument: the ID of
+the person whose password is to be cleared.
+
+@item @code{-G} or @code{--grant-all}
+Grant all privileges to the specified user. This option is silently
+ignored if the user does not exist. This option requires an argument:
+the ID of the person who is to be granted all privileges.
+
+@item @code{--pers-pres-conf}
+Set the person presentation conference of the server to the specified
+conference. Since version 1.9 of lyskomd the @code{set-info} call can be 
+used to do this.
+
+@item @code{--conf-pres-conf}
+Set the conference presentation conference of the server to the specified
+conference. Since version 1.9 of lyskomd the @code{set-info} call can be 
+used to do this.
+
+@item @code{--motd-conf}
+Set the message-of-the-day conference of the server to the specified
+conference. Since version 1.9 of lyskomd the @code{set-info} call can be 
+used to do this.
+
+@item @code{--kom-news-conf}
+Set the news-about-lyskom conference of the server to the specified
+conference. Since version 1.9 of lyskomd the @code{set-info} call can be 
+used to do this.
+
+@item @code{--motd-of-kom}
+Set the message of the day of the server to the specified text. Since
+version 1.9 of lyskomd the @code{set-info} call can be used to do this.
+@end table
+
+
+@node Reporting Options,  , Database Maintenance Options, Invoking dbck
+@comment  node-name,  next,  previous,  up
+@subsection Reporting Options
+
+These options control reporting of information about the database.
+
+@table @asis
+@item @code{-s} or @code{--print-statistics}
+Gather statistics about the lengths of texts. A table containing the
+frequence of all lengths that are currently present is printed.
+
+@item @code{-t} or @code{--list-text-no}
+Print ``Checking @i{text-no}'' for every text that examined.
+@b{Warning:} This produces lots of output.
+@end table
+
+
+@node DBCK Notes, DBCK Files, Invoking dbck, DBCK Reference
+@comment  node-name,  next,  previous,  up
+@section Notes for DBCK
+
+The messages ``Conference @var{conf-no} has a bad Text-list. Starts with
+0'' and ``Person @var{pers-no} has created @var{num} conferences, not
+@var{num} (as said in person-stat).'' are normal. If you get them when
+you specify the @code{-g} option, let @code{dbck} repair them and run
+@code{dbck -g} again.
+
+
+@node DBCK Files, DBCK Bugs, DBCK Notes, DBCK Reference
+@comment  node-name,  next,  previous,  up
+@section Files Used by dbck
+
+dbck uses the same files as @code{lyskomd} (@xref{(lyskomd)}.)
+
+All file names can be changed in the server configuration file.
+@xref{(lyskomd)Parameters}.
+
+@table @file
+@item /usr/lyskom
+Default value of @code{Prefix}. The default of this value is set at compile 
+time, but it can be changed in the server configuration file.
+@xref{(lyskomd)Parameters}.
+
+@item @code{Prefix}/db/lyskomd-data
+Half of the database: all status information.
+
+@item @code{Prefix}/db/lyskomd-texts
+The other half of the database: the actual texts.
+
+@item @code{Prefix}/db/lyskomd-backup
+A backup copy of @code{lyskomd-data}. Never, ever delete this file
+unless you know what you are doing, or you may lose the entire data
+base. Most of the time this is the only complete database file!
+
+@end table
+
+
+@node DBCK Bugs,  , DBCK Files, DBCK Reference
+@comment  node-name,  next,  previous,  up
+@section Known Bugs
+
+@itemize @bullet
+@item Does not lock the database.
+@item Never checks if the database is locked.
+@item Should have an unlock database option.
+@item Does not check that the data file and text file are consistent.
+@end itemize
+
+
+
+
+
+@c ======================================================================
+@c ======================================================================
+@c ==                                                                  ==
+@c ==                       LYSKOMD HACKING GUIDE                      ==
+@c ==                                                                  ==
+@c ======================================================================
+@c ======================================================================
+
+
+@node Hacking,  , DBCK Reference, Top
+@comment  node-name,  next,  previous,  up
+@chapter Hacking lyskomd
+
+
+@menu
+* The Database::                
+* Adding Configuration Parameters::  How to add configuration options.
+* Adding Asynchronous Messages::  Adding protocol A messages.
+* Adding a New Protocol Request::  Adding protocol A calls.
+* Adding Aux-Item Types::       Adding predefined aux item types.
+* Modifying Stored Types::      Modifying types stored in the DB.
+* Notes::                       Mixed notes.
+* Debugging and Testing::       How to test and debug the server.
+@end menu
+
+@node The Database, Adding Configuration Parameters, Hacking, Hacking
+@comment  node-name,  next,  previous,  up
+@section The Database
+
+@c FIXME: ramkomd �r d�d! L�nge leve LysKOM!
+@c FIXME: 
+@c FIXME: Jag har tillsammans med Inge kommit p� ett s�tt att dels f� ner
+@c FIXME: v�ntetiden i samband med syncningar till <1 sekund, dels f� ner
+@c FIXME: storleken p� serverprocessen till mer rimliga niv�er. Denna l�sning
+@c FIXME: lider dock av det stora problemet att den kr�ver dubbelt s� mycket
+@c FIXME: diskutrymme som den egentligen beh�ver. Det g�r �ven ramkomd, s� det
+@c FIXME: �r ingen f�rs�mring i det avseendet. Dock �r detta bara en tempor�r
+@c FIXME: l�sning i v�ntan p� ldb.
+@c FIXME: 
+@c FIXME: Varf�r spara allt p� en g�ng? Varf�r inte spara en liten del av filen
+@c FIXME: i taget, och utf�ra n�gra atomiska anrop mellan varje liten
+@c FIXME: delsynkning? Ungef�r s� t�nkte jag n�r jag kom p� f�ljande schema f�r
+@c FIXME: hur man kan g�ra det hela b�ttre �n det �r nu.
+@c FIXME: 
+@c FIXME: Den databas som ligger p� fil �r en �gonblickbild (snapshot) av det
+@c FIXME: som finns i LysKOM. S� �r det i ramkomd; s� blir det i diskomd.
+@c FIXME: (B�ttre namn, n�gon? lyskomd tycker jag �r reserverat f�r den version
+@c FIXME: som har en riktig cache&ldb.) I ramkomd skrivs allt ut p� disk
+@c FIXME: samtidigt. I diskomd minns man bara vad som skall sparas, och sparar
+@c FIXME: bara en bit i taget.
+@c FIXME: 
+@c FIXME: I ramkomd finns allt inne i ram-minnet (i teorin. I praktiken �r det
+@c FIXME: mesta utswappat - n�got som m�rks varje g�ng det �r dags att synca!).
+@c FIXME: I diskomd ligger det mesta p� disk. I minnet finns dels det som har
+@c FIXME: anv�nts nyligen, dels det som �r �ndrat och �nnu ej syncat. Diskomd
+@c FIXME: har alltid minst en, ofta tv�, databasfiler �ppna:
+@c FIXME: 
+@c FIXME:         Fil A		Senaste kompletta fil.
+@c FIXME:         Fil B		Fil under uppbyggnad.
+@c FIXME: 
+@c FIXME: (Dessutom textmassefilen, precis som ramkomd nuf�rtiden.)
+@c FIXME: 
+@c FIXME: S� till detaljerna:
+@c FIXME: 
+@c FIXME: Det finns tre typer av objekt som ber�rs av den h�r �ndringen:
+@c FIXME: Text_stat, Person och Conference. Jag anv�nder Person som ett exempel
+@c FIXME: nedan.
+@c FIXME: 
+@c FIXME: I ram-cache.c finns en array 
+@c FIXME: 
+@c FIXME:         Person *pers_arr[ MAX_CONF ];
+@c FIXME: 
+@c FIXME: Den byts mot
+@c FIXME: 
+@c FIXME:         Cache_node *pers_arr[ MAX_CONF ];
+@c FIXME: 
+@c FIXME: typedef struct cache_node �
+@c FIXME:         Bool	exists;
+@c FIXME:         Bool	exists_b;
+@c FIXME:         Bool	dirty;		/* �r *ptr modifierad? */
+@c FIXME:         void   *snap_shot;
+@c FIXME:         void   *ptr;
+@c FIXME:         off_t   pos;
+@c FIXME:         off_t   pos_b;
+@c FIXME:         struct cache_node *lru_link;
+@c FIXME:         int	lock_cnt;
+@c FIXME: � Cache_node;
+@c FIXME: 
+@c FIXME: 
+@c FIXME: 
+@c FIXME: UPPSTART
+@c FIXME: 
+@c FIXME: N�r servern startas scannar den igenom datafilen (fil A) och fyller i
+@c FIXME: f�ltet exists till TRUE/FALSE och pos till att peka p� b�rjan av det
+@c FIXME: st�lle i filen d�r data ligger. �vriga f�lt s�tts till FALSE/NULL/0.
+@c FIXME: 
+@c FIXME: 
+@c FIXME: 
+@c FIXME: CACHE_GET_PERSON
+@c FIXME: 
+@c FIXME: N�r ovanliggande rutiner vill l�sa en person h�nder f�ljande:
+@c FIXME: 
+@c FIXME: !exists			Returnera NULL
+@c FIXME: ptr != NULL		L�gg noden f�rst i lru_link. Returnera ptr.
+@c FIXME: snap_shot != NULL	Kopiera snap_shot till ptr. L�gg noden f�rst i
+@c FIXME:                         lru_link. Returnera ptr.
+@c FIXME: annars			L�s in fr�n fil A, s�tt ptr till den inl�sta
+@c FIXME:                         structen, l�gg noden f�rst i lru_link,
+@c FIXME:                         returnera ptr.
+@c FIXME: 
+@c FIXME: 
+@c FIXME: MARK_PERSON_AS_CHANGED
+@c FIXME: 
+@c FIXME: N�r n�got har �ndrats s�tts dirty-flaggan till TRUE.
+@c FIXME: 
+@c FIXME: 
+@c FIXME: CREATE_PERSON
+@c FIXME: 
+@c FIXME: S�tt exists=TRUE, dirty=TRUE, ptr och lru.
+@c FIXME: 
+@c FIXME: 
+@c FIXME: DELETE_PERSON
+@c FIXME: 
+@c FIXME: S�tt exists=FALSE. ptr=NULL. Troligtvis error om lock_cnt != 0.
+@c FIXME: 
+@c FIXME: 
+@c FIXME: 
+@c FIXME: THROW-OUT
+@c FIXME: 
+@c FIXME: F�r att inte diskomd ska bli f�r stor sl�ngs saker ut ur cachen.
+@c FIXME: Algoritm: tag f�rsta elementet i lru_list. Om dirty==FALSE och
+@c FIXME: ptr!=NULL och lock_cnt==0 s� frig�r ptr. Upprepa tills antalet noder
+@c FIXME: med ptr!=NULL och dirty==FALSE �r mindre �n antalet "rena" element man
+@c FIXME: vill ha inne i minnet. (Smutsiga element sl�ngs aldrig ut.)
+@c FIXME: 
+@c FIXME: 
+@c FIXME: LOCK_PERSON
+@c FIXME: 
+@c FIXME: �ka lock_cnt.
+@c FIXME: 
+@c FIXME: 
+@c FIXME: UNLOCK_PERSON
+@c FIXME: 
+@c FIXME: Minska lock_cnt.
+@c FIXME: 
+@c FIXME: 
+@c FIXME: PRE-SYNC
+@c FIXME: 
+@c FIXME: Utsparningen till fil sker i tre steg. F�rst sveper man �ver alla
+@c FIXME: Cache_noder. F�r alla som har dirty=TRUE g�r man f�ljande:
+@c FIXME: 
+@c FIXME:     if ( lock_cnt == 0 ) �
+@c FIXME:         snap_shot = ptr; (Pekartilldelning, ej kopiering av inneh�llet.) 
+@c FIXME:         ptr = NULL;
+@c FIXME:         Ta bort ptr ur lru-kedjan.
+@c FIXME:     � else �
+@c FIXME:         snap_shot = copy(ptr);
+@c FIXME:     �
+@c FIXME: 
+@c FIXME:     dirty = FALSE;
+@c FIXME: 
+@c FIXME: F�r _alla_ noder g�rs dessutom f�ljande:
+@c FIXME: 
+@c FIXME:    b_exists==exists;
+@c FIXME: 
+@c FIXME: 
+@c FIXME: SYNC
+@c FIXME: 
+@c FIXME: Steg tv� utf�rs en liten bit i taget. Till exempel s� skulle man kunna
+@c FIXME: spara en person efter varje atomiskt anrop, eller s�.
+@c FIXME: 
+@c FIXME: b_exists==FALSE?	   S�tt pos_b. Skriv "@@\n" till fil B.
+@c FIXME: �r snap_shot != NULL?	   S�tt pos_b. Skriv ut inneh�llet i snap_shot 
+@c FIXME:                            till fil B.
+@c FIXME: dirty==FALSE && ptr!=NULL  Skriv ut inneh�llet i ptr till fil B.
+@c FIXME: annars:			   Kopiera fr�n fil A till fil B. (Eftersom man
+@c FIXME:                            vet b�de var blocket b�rjar och slutar kan man
+@c FIXME:                            kopiera blocket utan att bry sig om vad som
+@c FIXME:                            st�r i det -> v�ldigt lite CPU g�r �t).
+@c FIXME: 
+@c FIXME: 
+@c FIXME: 
+@c FIXME: 
+@c FIXME: POST-SYNC
+@c FIXME: 
+@c FIXME: N�r alla Person:er har hanterats som i SYNC ovan �r det dags f�r det
+@c FIXME: tredje steget. D� g�r man igenom alla Cache_node:er och g�r f�ljande:
+@c FIXME: 
+@c FIXME:         pos = pos_b;
+@c FIXME:         file_b = FALSE;
+@c FIXME:         free(snap_shot);
+@c FIXME:         snap_shot = NULL;
+@c FIXME: 
+@c FIXME: Fil B som man f�rut hade �ppen f�r skrivning �ppnar man i st�llet f�r
+@c FIXME: l�sning som fil A.
+@c FIXME: 
+@c FIXME: 
+@c FIXME: 
+@c FIXME: 
+@c FIXME: ANM�RKNINGAR
+@c FIXME: 
+@c FIXME: Inneh�llet i snap_shot �r alltid "smutsigt" j�mf�rt med inneh�llet i
+@c FIXME: fil A. Det som snap_shot pekar p� finns aldrig med i lru-kedjan.
+@c FIXME: 
+
+
+
+@node Adding Configuration Parameters, Adding Asynchronous Messages, The Database, Hacking
+@comment  node-name,  next,  previous,  up
+@section Adding Configuration Parameters
+
+Make sure that you really understand what you want to configure. Think
+it over again. Find a good, descriptive name for it.
+
+Decide what values the parameter can be set to. Integers? Booleans?
+
+Document the parameter in @code{lyskomd.texi}.
+
+Add a field to @code{stuct kom_par} in @code{param.h}.
+
+Add it to @code{parameters[]} in @code{server-config.c}. See
+@code{conf-file.h} and maybe @code{conf-file.c} for information on this
+structure.
+
+Make sure that the parameter is used instead of any previous hard-coded
+value. Make sure that @code{dbck} can cope with it.
+
+
+@node Adding Asynchronous Messages, Adding a New Protocol Request, Adding Configuration Parameters, Hacking
+@comment  node-name,  next,  previous,  up
+@section Adding Asynchronous Messages
+
+@table @code
+
+@item async.h
+Add the message in @code{typedef enum @{ @} Async}. Make sure that
+@code{ay_dummy_last} is one more than any other message. If the message
+is to be sent by default, which is @i{not} recommended, place its number
+info @code{ASYNC_DEFAULT_MESSAGES}.
+
+@item prot-a-send-async.c
+@item prot-a-send-async.h
+Write a function that sends the message. This function is responsible
+for writing the message to a particular connection and for ensuring that
+the message is not sent to clients who do not want it. Make sure that
+the second argument to @code{async_header} really is the number of
+elements being sent. Arrays count as two elements: the item count and
+the elements.
+
+@item send-async.c
+@item send-async.h
+Write a function that sends the message to appropriate clients. This
+function is responsible for checking that async messages should be sent
+at all, for each client check if it allowed to see the message and
+ensure that the protocol specified by the connection is appropriate. The
+send function should either take a @code{struct connection *} as an
+argument and send the message to that connection, or loop over all
+connections. Most send functions take a connection pointer; the looping
+is dealt with elsewhere.
+
+@item Make sure that the message is sent in appropriate places.
+
+@item Document the message type in @code{Protocol-A.texi}.
+
+@end table
+
+@menu
+* Function Templates for prot-a-send-async.c::  
+* Function Templates for send-async.c::  
+@end menu
+
+
+@node Function Templates for prot-a-send-async.c, Function Templates for send-async.c, Adding Asynchronous Messages, Adding Asynchronous Messages
+@comment  node-name,  next,  previous,  up
+@subsection Function Templates for prot-a-send-async.c
+
+This is what a typical function in @code{prot-a-send-async.c} should
+look like. This function is responsible for checking that the client is
+accepting the message and writing the message itself to the connection. 
+
+@example
+void
+prot_a_async_@i{something}(Connection   *cptr,
+                           @i{parameters})
+@{
+    ASYNC_CHECK_ACCEPT(cptr, ay_@i{something});
+    async_header(cptr, @i{num_tokens}, ay_@i{something});
+    /* Output the body of the message */
+    async_trailer(cptr);
+@}
+@end example
+
+
+@node Function Templates for send-async.c,  , Function Templates for prot-a-send-async.c, Adding Asynchronous Messages
+@comment  node-name,  next,  previous,  up
+@subsection Function Templates for send-async.h
+
+This is what a typical function in @code{send-async.c} should look like.
+This function is responsible for sending the message to all connections
+that are appropriate, not sending it if the server is not supposed to
+send messages at all, and for checking that the protocol specified by
+the client is one the server knows.
+
+@example
+void async_@i{something}( @i{parameters} )
+@{
+    Connection *cptr;
+    Session_no i = 0;
+
+    if (!param.send_async_messages)
+	return;
+
+    while ((i = traverse_connections(i)) != 0)
+    @{
+	cptr = get_conn_by_number(i);
+
+	switch(cptr->protocol)
+	@{
+	case 0:
+            /* No protocol specified yet */
+	    break;
+	case 'A':
+            /* Check that connection is logged on. We might
+               want to check other things here too, such as
+               if the connection is allowed to see the message */
+	    if (cptr->username_valid == TRUE)
+		prot_a_async_@i{something}(cptr, @i{parameters});
+	    break;
+	default:
+	    restart_kom("async_@i{something}(): bad protocol.\n");
+	    break;
+	@}
+    @}
+@}
+@end example
+
+Template for a function that sends to a single connection:
+@example
+void async_@i{something}(struct connection *cptr,
+                         @i{parameters})
+@{
+    if (!param.send_async_messages)
+	return;
+
+    switch(cptr->protocol)
+    @{
+    case 0:
+        /* No protocol specified yet */
+	break;
+    case 'A':
+        /* Check that connection is logged on. We might
+           want to check other things here too, such as
+           if the connection is allowed to see the message */
+	if (cptr->username_valid == TRUE)
+	    prot_a_async_@i{something}(cptr, @i{parameters});
+	break;
+    default:
+	restart_kom("async_@i{something}(): bad protocol.\n");
+	break;
+    @}
+@}
+@end example
+
+
+@node Adding a New Protocol Request, Adding Aux-Item Types, Adding Asynchronous Messages, Hacking
+@comment  node-name,  next,  previous,  up
+@section Adding a New Protocol Request
+
+Before doing anything, think again. Make sure that the protocol request
+is needed, is in line with the rest of the protocol, behaves the way
+people want it to, and that everyone involved agrees that it is a good
+idea.
+
+@enumerate
+@item Document the request in @code{Protocol-A.texi}
+
+@item Declare the function in @code{include/services.h}
+
+@item Declare the function @i{last} in @code{server/fncdef.txt}. It
+should be given a call number one higher than the currently existing
+highest contiguous call number.
+
+@item If the function takes a pn input parameter of a new type, changes
+need to be made in several places. @xref{Adding New Input Types}.
+
+@item If the function takes too many parameters of type @code{num},
+@code{string} or @code{c_string}, the definition of @code{Connection} in 
+@code{server/connection.h} has to be changed.
+
+@item If the function has an output parameter of a new type, changes
+need to be made in several plaves. @xref{Adding New Result Types}.
+
+@item Write the function in a suitable place in the server directory.
+
+@item Write tests for the new function in
+@code{server/testsuite/lyskomd.0}. Write one file for testing the
+functionality. Write tests in @code{01.exp} (behavior when the client is 
+not logged on) and @code{03.exp} (normal behavior.)
+
+@item Run the testsuite to make sure nothing old has been broken.
+@end enumerate
+
+It is no longer necessary to update prot_a_is_legal_fnc since it is
+generated automatically.
+
+
+@menu
+* Adding New Input Types::      Procedure for adding input types.
+* Adding New Result Types::     Procedure for adding output types.
+* Modifying Output Types::      Procedure for modifying output types.
+@end menu
+
+
+@node Adding New Input Types, Adding New Result Types, Adding a New Protocol Request, Adding a New Protocol Request
+@comment  node-name,  next,  previous,  up
+@subsection Adding New Input Types
+
+Changes need to be made in the following files:
+
+@table @code
+@item Protocol-A.texi
+Document the new type.
+
+@item server/call-switch.awk
+The new type has to be added to the cascaded ifs that translate the type 
+name to code that points to the appropriate field in a
+@code{Connection} structure.
+
+@item server/prot-a-parse-arg-c.awk
+The new type has to be added to the cascaded ifs that create the
+argument list parser. 
+
+@item server/connections.h
+The definition of @code{Connection} must be extended with a field where
+the parse value can be stored. Don't even think about trying to reuse an 
+existing field. It's more trouble than it's worth.
+
+@item server/connection.c
+Free the contents of the field in @code{free_parsed()}.
+
+@item server/internal-connections.c
+Initialize the contents of the field in @code{init_connection()}.
+
+@end table
+
+
+
+@node Adding New Result Types, Modifying Output Types, Adding New Input Types, Adding a New Protocol Request
+@comment  node-name,  next,  previous,  up
+@subsection Adding New Result Types
+
+Changes need to be made in the following files:
+
+@table @code
+@item Protocol-A.texi
+Document the new type.
+
+@item server/prot-a.c
+Add a line in the @code{prot_a_reply} switch that calls the correct
+output function. 
+
+@item server/connections.h
+Add the type in @code{Res_type}and @code{Result_holder}. 
+
+@item server/prot-a-output.c
+@item server/prot-a-output.h
+Write a function that outputs the new type
+to a connection. Use the existing functions as templates.
+@end table
+
+
+@node Modifying Output Types,  , Adding New Result Types, Adding a New Protocol Request
+@comment  node-name,  next,  previous,  up
+@subsection Modifying Output Types
+
+When you modify an existing type you have to rename the old version of
+the type since it will still be used in existing calls. The convention
+hs previously been to rename @code{Something} to @code{Something_old},
+but the preferred method is to append an underscore and the protocol
+version in which the current version of the type was introduced. For
+example, if the type @code{Gazonk} was introduced in protocol version
+11, and a new version is to be introduced in protocol version 15, the
+current @code{Gazonk} structure is renamed to @code{Gazonk_11}.
+
+This is to avoid names like @code{Something_older},
+@code{Something_oldest} and @code{Something_Truly_Ancient}.
+
+
+Changes need to be made to the following files:
+
+@table @code
+@item Protocol-A.texi
+Document the new type in the appropriate section. Rename the existing
+type in the type documentation and in all calls that return it. Be
+thorough!
+
+@item fncdef.txt
+Rewrite all calls that use the modified type so they use the old version 
+of the type.
+
+@item prot-a.c
+Modify the current line in @code{prot_a_reply} for the existing version
+of the type, and add a new line for the new version of the type.
+
+@item connections.h
+Modify the existing entry in @code{Res_type} and @code{Result_holder},
+if necessary. This should only be necessary if the server uses both a
+new and old type internally, which is not recommended. Add new entries
+for the new version of the type.
+
+@item prot-a-output.h
+@item prot-a-output.c
+Rename the existing output routing according to the new name of the
+type. Write a new output routine for the new version of the type.
+
+@item memory.c
+If there are functions for the type in @code{memory.c}, make sure that
+your new type is initialized, cleared and copied in an appropriate
+manner.
+
+@end table
+
+If the type you modify is stored in the database, make sure it gets
+saved properly. @xref{Modifying Stored Types}.
+
+
+@node Adding Aux-Item Types, Modifying Stored Types, Adding a New Protocol Request, Hacking
+@comment  node-name,  next,  previous,  up
+@section Adding Aux-Item Types
+
+@enumerate
+@item Document the new type in Protocol-A.texi
+
+@item Write a definition of the new type in
+@code{run-support/aux-items.conf}.
+
+@item Write test cases for the new type in
+@code{server/testsuite/lyskomd.0/03.exp}.
+
+@item If the new type requires add, delete or undelete triggers that do
+not already exist, declare the trigger functions in @code{aux-items.c}
+and add them to the @code{aux_item_triggers} array in the same file.
+
+@item If the new type is so complex that is cannot be fully defined in
+@code{aux-items.conf}, then add it to the @code{compiled_aux_items}
+array in @code{aux-items.c}. Note that this functionality has not been
+tested until someone actually adds one of these beasts, so watch your
+step.
+
+@end enumerate
+
+
+@node Modifying Stored Types, Notes, Adding Aux-Item Types, Hacking
+@comment  node-name,  next,  previous,  up
+@section Modifying Stored Types
+
+If you want to modify an existing type that is stored in the database,
+think again. Can the job be done with aux-items instead? Is it really
+necessary?
+
+Be very, very careful when doing this. You have to make sure that the
+type as sent in old calls and async messages is not changed in any way.
+You have to make sure that the type can be stored to and read from the
+database.
+
+@enumerate
+@item Document the changes in Protocol-A.texi if the change is visible
+in the protocol.
+
+@item Bump the database version number by one for the next release of
+the server.
+
+@item Write a function in @file{ram-output.c} to output the new format.
+Update all old functions in @file{ram-output.c} that are database
+version dependent so that they can deal with the new database format.
+
+@item Write a function in @file{ram-parse.c} to read the new format.
+Update all old functions in @file{ram-parse.c} that are database version 
+dependent so that they can deal with the new database format.
+
+@item Set the default database format in @file{ram-parse.c} and
+@code{ram-output.c}. The variables to change are @code{input_format} and 
+@code{output_format}, respectively.
+
+@item Don't forget to update the functions in @file{memory.c}
+
+@end enumerate
+
+@menu
+* Template for ram-output.c::   
+* Template for ram-parse.c::    
+@end menu
+
+
+@node Template for ram-output.c, Template for ram-parse.c, Modifying Stored Types, Modifying Stored Types
+@comment  node-name,  next,  previous,  up
+@subsection Template for ram-output.c
+
+For types that can be output in several different formats, use the
+following templates for them. You have to be able to output in all
+formats, or @code{dbck} will be unable to convert between formats.
+
+@example
+static void
+foutput_@i{something}_0(FILE *fp, @i{something} *o)
+@{
+    /* Output version 0 of @i{something} */
+@}
+
+static void
+foutput_@i{something}_1(FILE *fp, @i{something} *o)
+@{
+    /* Output version 1 of @i{something} */
+@}
+
+static void
+foutput_info_2(FILE *fp, @i{something} *o)
+@{
+    /* Output version 2 of @i{something} */
+@}
+
+
+void foutput_@i{something}(FILE *fp, @i{something} *o)
+@{
+    switch(output_format)
+    @{
+    case 0:
+        foutput_@i{something}_0(fp, info);
+        break;
+    case 1:
+        foutput_@i{something}_1(fp, info);
+        break;
+    case 2:
+        foutput_@i{something}_2(fp, info);
+        break;
+    default:
+        restart_kom("unknown database format: %d", output_format);
+        break;
+    @}
+@}
+@end example
+
+Note that if two versions are the same, only write one functions. For
+example, if version 0 and version 1 are the same, only write an
+@code{foutput_@i{something}_0} function and call it from both case 0 and 
+case 1.
+
+@node Template for ram-parse.c,  , Template for ram-output.c, Modifying Stored Types
+@comment  node-name,  next,  previous,  up
+@subsection Template for ram-parse.c
+
+@example
+static Success
+fparse_@i{something}_0(FILE *fp, @i{something} *o)
+@{
+    /* Parse version 0 */
+    return OK;
+@}
+
+static Success
+fparse_@i{something}_1(FILE *fp, @i{something} *o)
+@{
+    /* Parse verson 1 */
+    return OK;
+@}
+
+static Success
+fparse_@i{something}_2(FILE *fp, @i{something} *o)
+@{
+    /* Parse verson 2 */
+    return OK;
+@}
+
+extern Success
+fparse_@i{something}(FILE *fp, @i{something} *o)
+@{
+    if ( fparse_long_errors != 0 )
+    @{
+	log("fparse_info(): fparse_long_errors == %d on entry. Reset.\n",
+	    fparse_long_errors);
+	fparse_long_errors = 0;
+    @}
+
+    switch (input_format)
+    @{
+    case 0:
+        return fparse_@i{something}_0(fp, o);
+        break;
+    case 1:
+        return fparse_@i{something}_1(fp, o);
+        break;
+    case 2:
+        return fparse_@i{something}_2(fp, o);
+        break;
+    default:
+        restart_kom("unknown input format: %d\n", input_format);
+        return FAILURE;
+        break;
+    @}
+@}
+@end example
+
+Note that if two versions are the same, only write one functions. For
+example, if version 0 and version 1 are the same, only write an
+@code{fparse_@i{something}_0} function and call it from both case 0 and 
+case 1.
+
+
+@node Notes, Debugging and Testing, Modifying Stored Types, Hacking
+@comment  node-name,  next,  previous,  up
+@section Hacking Notes
+
+@menu
+* Parsing Bit Fields::          How to parse bit fields properly.
+* Membership Notes::            How members and memberships are handled.
+* Linking Pairs of Aux Items::  How to link pairs of aux items.
+* Notes for fncdef.txt::        Format of the fncdef.txt file.
+* Traversing Connections::      How to traverse connections in lyskomd.
+@end menu
+
+
+@node Parsing Bit Fields, Membership Notes, Notes, Notes
+@comment  node-name,  next,  previous,  up
+@subsection Parsing Bit Fields
+
+The parser for a bit field parameter type should be very tolerant of the 
+length of the token. Anything from a single bit and up should be
+permitted. The parser should use default values for bits that are not
+provided and ignore extra bits.
+
+Here is a model function:
+
+@example
+void
+prot_a_parse_bitfield(Connection *client,
+                      Bitfield   *res)
+@{
+    String          token;
+    String_size     len;
+
+    token = prot_a_get_token(client);
+    len = s_strlen(token);
+    if (len <= 0)
+        longjmp(parse_env, ISC_PROTOCOL_ERR);
+
+    init_bitfield(res);
+    switch (len = s_strlen(token))
+    @{
+    default:
+    case 8: res->bit_8 = token.string[ 7 ];
+    case 7: res->bit_7 = token.string[ 6 ];
+    case 6: res->bit_6 = token.string[ 5 ];
+    case 5: res->bit_5 = token.string[ 4 ];
+    case 4: res->bit_4 = token.string[ 3 ];
+    case 3: res->bit_3 = token.string[ 2 ];
+    case 2: res->bit_2 = token.string[ 1 ];
+    case 1: res->bit_1 = token.string[ 0 ];
+    @}
+@}
+@end example
+
+The function gets the token, checks the sanity of the length, then
+initialized the result to its default values. Then it does a switch on
+all token lengths that are equal to or smaller than the number of bits
+the server knows about. The fall-through ensures that all bits in the
+token are read.
+
+
+@node Membership Notes, Linking Pairs of Aux Items, Parsing Bit Fields, Notes
+@comment  node-name,  next,  previous,  up
+@subsection Membership Notes
+
+The @code{position} field in the membership is @i{not} stored. It has to 
+be set every time a membership is requested for transmission to the
+client.
+
+
+
+@node Linking Pairs of Aux Items, Notes for fncdef.txt, Membership Notes, Notes
+@comment  node-name,  next,  previous,  up
+@subsection Linking Pairs of Aux Items
+
+Sometimes two aux items need to work in tandem. The first instance of
+this was the FAQ and FAQ-for-conference items. The FAQ item contains the 
+text number of a text that is a FAQ for a conference. The
+FAQ-for-conference item contains the conference for which a text is a
+FAQ. This is needed so that deletion of the text properly removes the
+aux-item on the conf (plus, it's nice to be able to see that a text is a 
+FAQ.)
+
+The @code{linked_item} field in the Aux_item structure is for linking
+items. The linking must be managed through the use of triggers. This
+field is not visible in the protocol. It is saved in the database. It is 
+not possible to have more than one link per item.
+
+Please remember the following points.
+
+@itemize @bullet
+
+@item The target of a link should have a link back. All links need to go 
+both ways.
+
+@item In the add trigger for one end, create the other end of the link
+and set the @code{linked_item} field in both items. Don't forget to mark 
+the objects at both ends as changed.
+
+@item Deletion and undeletion of the other side of the link will be
+managed automatically. You don't need delete and undelete triggers
+simply to destroy the other side of a link.
+
+@item Don't kill the server because one end is missing. It is possible
+for the administrator to remove an item manually. Log a message and
+continue working.
+
+@end itemize
+
+
+
+
+
+
+@node Notes for fncdef.txt, Traversing Connections, Linking Pairs of Aux Items, Notes
+@comment  node-name,  next,  previous,  up
+@subsection Notes for fncdef.txt
+
+The fncdef.txt file is used to define the RPC functions. Each line
+consists of the call number, the return type of the call, the parameters
+and the output types of the call.
+
+Some examples:
+
+@example
+    10 number  create_conf_old c_string (param.conf_name_len) conf_type
+    12 success lookup_name c_string (param.conf_name_len) : conf_list
+@end example
+
+The first line defines a call named @code{create_conf_old} that takes
+two arguments, a string that can only be as long as
+@code{param.conf_name_len} and a @code{conf_type}. It returns a number
+to the client. If the service call returns -1, the server will return an 
+error. The @code{create_conf_old} call has RPC number 10.
+
+The second line defines a call named @code{lookup_name} that takes a
+string argument that can be no longer than @code{param.conf_name_len},
+and returns a @code{conf_list}. The service call returns a
+@code{Success}. If it does not return @code{OK}, the server will return
+an error. The @code{lookup_name} call has RPC number 12.
+
+
+@subsubsection Scripts That Use fncdef.txt
+
+The following scripts operate on @code{fncdef.txt}. If you make
+modifications to the format of @code{fncdef.txt}, you have to update
+these scripts.
+
+@table @code
+@item call-switch.awk
+Generates @code{call-switch.incl}, which is included by
+@code{connections.c}
+
+@item com-h.awk
+Generates @code{com.h}, which is included by several files.
+
+@item fnc-def-init.awk
+Generates @code{fnc-def-init.incl}, which is included by
+@code{connections.c}.
+
+@item prot-a-is-legal-fnc.awk
+Generates @code{prot-a-is-legal-fnc.incl}, which is included by
+@code{prot-a.c}
+
+@item prot-a-parse-arg-c.awk
+@item prot-a-parse-arg-h.awk
+Generates @code{prot-a-parse-arg.c} and @code{prot-a-parse-arg.h}.
+@end table
+
+
+@node Traversing Connections,  , Notes for fncdef.txt, Notes
+@comment  node-name,  next,  previous,  up
+@subsection Traversing Connections
+
+Since session 0 is interpreted as the currently active session by
+get_conn_by_number it is important to be careful when traversing
+sessions. Code like this does not work since it will do one iteration
+through the loop with @code{sess} set to zero. This formerly caused
+@code{get_conn_by_number} to return @code{NULL}, but now causes it to
+return the session pointer for the current session.
+
+@example
+        for (sess = 0; (sess = traverse_connections(sess)) != 0; )
+        @{
+            cptr = get_conn_by_number(sess);
+            ...
+        @}
+@end example
+
+The canonical traversal code looks like this:
+
+@example
+        Session_no      session = 0;
+        while ((session = traverse_connections(session)) != 0)
+        @{
+            cptr = get_conn_by_number(session);
+            ...
+        @}
+@end example
+
+This code has @code{session} set to a session number before ever
+entering the loop.
+
+
+@node Debugging and Testing,  , Notes, Hacking
+@comment  node-name,  next,  previous,  up
+@section Debugging and Testing
+
+We're slowly adding support for debugging and testing lyskomd properly.
+
+@menu
+* The Test Suite::              The lyskomd regression test suite.
+* Configuration Options::       Debugging options for the configure script.
+* Coverage Testing::            How to do coverage testing with gcov.
+* Debug Calls::                 Special protocol A calls for testing.
+@end menu
+
+@node The Test Suite, Configuration Options, Debugging and Testing, Debugging and Testing
+@comment  node-name,  next,  previous,  up
+@subsection The Test Suite
+
+The lyskomd test suite is in src/server/testsuite. Please extend this
+with additional test cases every time you make modifications to the
+server. Run the test suite often to make sure that your changes did not
+break anything.
+
+The file config/prot-a.exp contains some support for protocol A. Don't
+use these functions in test cases. Use them to set up the inital
+database and for things tht have to be done, such as logins and enabling
+privileges, but that don't need to be tested. Also, don't count on all
+the code in prot-a.exp to be fully functional. Add new functions to this 
+file as you see fit.
+
+The basic structure of a test case is the following:
+
+@example
+source "config/prot-a.exp"
+read_versions
+
+lyskomd_start
+client_start 0
+talk_to client 0
+kom_connect "DejaGnu test suite"
+
+@i{The test cases}
+
+talk_to client 0
+kom_logout
+kom_login 5 [holl "gazonk"] 0
+kom_enable 255
+send "9999 44 0\n"
+simple_expect "=9999"
+
+client_death 0
+lyskomd_death
+@end example
+
+Use the existing test cases as templates.
+
+
+@node Configuration Options, Coverage Testing, The Test Suite, Debugging and Testing
+@comment  node-name,  next,  previous,  up
+@subsection Configuration Options
+
+There are several testing and debugging-related configuration options
+for lyskomd. Some of them also apply to libisc.
+
+@table @code
+@item --with-purify
+Build lyskomd with Purify. This currently does not work.
+
+@item --with-efence
+Build lyskomd with Electric Fence for checking buffer overruns. This
+option does work.
+
+@item --with-checker
+Build lyskomd with Gnu Checker for checking memory accesses, leaks, file 
+descriptors and all kinds of stuff. As of Checker version 0.99.6, Gnu
+Checker cannot deal with lyskomd. Once built, and this requires
+modifications to Checker (at least on Linux) it reports spurious errors.
+Still, the option is here for those who want to try it out.
+
+@item --with-gcov
+Build lyskomd with instrumentation for @code{gcov}. You have to use this 
+option if you want to run @code{gcov} on lyskomd. For @code{gcov} to be
+effective, you should turn off optimization as well.
+
+@item --with-optimization=@i{value}
+Build lyskomd with the specified level of optimization. Use either
+numeric values to select the level of optimization, or say
+@code{--with-optimization=no} or @code{--without-optimization} to turn
+optimization off. 
+
+@end table
+
+
+
+@node Coverage Testing, Debug Calls, Configuration Options, Debugging and Testing
+@comment  node-name,  next,  previous,  up
+@subsection Coverage Testing
+
+When you write new code, make sure that it is completely covered by the
+test suite. Run the lyskomd configure script with the
+@code{--with-gcov}, @code{--with-debug-calls} and
+@code{--without-optimization} flags to instrument the server for
+coverage testing with gcov.
+
+If you run configure without the @code{--without-optimization} option,
+the server will be compiled with optimizations on. This is fine, but the
+coverage data from gcov isn't completely reliable since parts of the
+program may have been optimized out of existance.
+
+Recompile everything, then run the test suite. Next do @code{gcov -f }
+@i{filename} to compute coverage information for the file @i{filename}.
+The resulting file @i{filename}@code{.gcov} shows which lines have been
+executed, and which haven't been run. Try to get 100% coverage.
+
+
+@node Debug Calls,  , Coverage Testing, Debugging and Testing
+@comment  node-name,  next,  previous,  up
+@subsection Debug Calls
+
+Run the configure script with @code{--with-debug-calls} to compile in
+support for debugging calls in the server. These calls are strictly for
+making testing easier (or possible.) They are not official, and they may 
+change at any time.
+
+@menu
+* memory-info::                 Get information from malloc              (1000)
+* set-marks::                   Set the number of marks on a text        (1001)
+* backdate-text::               Change the creation date of a text       (1002)
+@end menu
+
+@node memory-info, set-marks, Debug Calls, Debug Calls
+@comment  node-name,  next,  previous,  up
+@subsubsection memory-info (DEBUG) Experimential
+
+@findex memory-info
+@example
+        memory-info [1000] ( )
+                -> (( arena     :       INT32;
+                      ordblks   :       INT32;
+                      smblks    :       INT32;
+                      hblks     :       INT32;
+                      hblkhd    :       INT32;
+                      usmblks   :       INT32;
+                      fsmblks   :       INT32;
+                      uordblks  :       INT32;
+                      fordblks  :       INT32;
+                      keepcost  :       INT32; ));
+@end example
+
+This call returns the data returned by @code{mallinfo} in the server. 
+See the man page for @code{mallinfo} for explanations of the fields.
+
+@node set-marks, backdate-text, memory-info, Debug Calls
+@comment  node-name,  next,  previous,  up
+@subsubsection set-marks (DEBUG) Experimental
+
+@findex set-marks
+@example
+        set-marks [1001] (( text-no     :   Text_no;
+                            no-of-marks :   INT32; ))
+                -> ( );
+@end example
+
+Set the number of marks on text @code{text-no} to @code{no-of-marks},
+regardless of how many marks it really has. This call is useful for
+forcing the database into a state where the number of marks is incorrect 
+in some way. 
+
+
+@node backdate-text,  , set-marks, Debug Calls
+@comment  node-name,  next,  previous,  up
+@subsubsection backdate-text (DEBUG) Experimental
+
+@findex backdate-text
+@example
+        backdate-text [1002] (( text-no :   Text_no;
+                                seconds :   INT32; ))
+                -> ( );
+@end example
+
+Backdate a text in the server. Change the creation date of text
+@code{text-no} so it appears to have been created @code{seconds} earlier 
+than it was actually created. This can be used to test the garbage
+collector.
+
+
+
 @contents
 @bye
diff --git a/doc/lyskomdb.texi b/doc/lyskomdb.texi
index ba6ccb7b098a24820caa14557d78b45c281dec19..d7eb445f21012a6545d7270cf8bca4d491a4f984 100644
--- a/doc/lyskomdb.texi
+++ b/doc/lyskomdb.texi
@@ -1,5 +1,5 @@
 \input texinfo
-@c $Id: lyskomdb.texi,v 1.2 1999/04/03 21:58:09 ceder Exp $
+@c $Id: lyskomdb.texi,v 1.3 1999/05/18 13:06:22 byers Exp $
 @c %**start of header
 @setfilename lyskomdb.info
 @settitle "lyskomd Database Format Specification"
@@ -220,16 +220,13 @@ deleted         :       @BB{-C} @II{integer} @BB{NL}
 The integer in the conference, text and person records is the ID of the
 record. This implies that records can be in any order.
 
-@c FIXME: doesn't it store the first unused number?  There is probably a
-@c fence error here.  /ceder
-The @II{next-free-num} record is used to store the highest ID of any
-conference in the system. There may be several of these records in the
-database. 
+The @II{next-free-num} record is used to store the next available ID for
+conferences in the system. There may be several of these records in the
+database.
 
-@c FIXME: doesn't it store the first unused number?  There is probably a
-@c fence error here.  /ceder
-The @II{next-text-num} record is used to store the highest ID of any text 
-in the system. There may be several of these records in the database.
+The @II{next-text-num} record is used to store the next available ID for
+texts in the system. There may be several of these records in the
+database.
 
 A conference or text must have a number lower than the closest
 @II{next-free-num} or @II{next-text-num} preceding it.
diff --git a/src/include/kom-types.h b/src/include/kom-types.h
index 5a1c2d3f6947b25ed840e3f41949876d46eb723c..1c6027c466269e95c10d735c2ce2e19cdfce4777 100644
--- a/src/include/kom-types.h
+++ b/src/include/kom-types.h
@@ -1,5 +1,5 @@
 /*
- * $Id: kom-types.h,v 0.34 1999/05/12 13:24:27 byers Exp $
+ * $Id: kom-types.h,v 0.35 1999/05/18 13:06:26 byers Exp $
  * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -185,7 +185,7 @@ typedef enum {
     rec_time  = 7,	/* 7 Received at (time) */
     sent_by   = 8,	/* 8 Sent by (person) */
     sent_at   = 9,	/* 9 Sent at (time) */
-    bcc_recpt = 15	/* 15 BCC recipient (for kannedom) */
+    bcc_recpt = 15,	/* 15 BCC recipient (for kannedom) */
 #ifdef PROT_a
 	,
     x_person  = 11,	/* 11 External person id. (Global_name). */
@@ -193,6 +193,8 @@ typedef enum {
     x_text    = 13,	/* 13 External text. (Global_text). */
     x_system  = 14	/* 14 External system identification (System_id). */
 #endif
+
+    unknown_info = 4711 /* Internal use only. Unknown misc item encountered */
 } Info_type;
 
 #ifdef PROT_a
@@ -223,6 +225,7 @@ typedef	union {
 		Global_text	global_text;
 		System_id	system_id;
 #endif
+                Info_type       unknown_type;
 } Info_datum;
 
 
@@ -233,6 +236,12 @@ typedef	struct {
 } Misc_info;
 
 
+typedef struct {
+    unsigned short      no_of_misc;
+    Misc_info         * misc;
+} Misc_info_list;
+
+
 typedef struct {
     unsigned int        deleted : 1; /* This item has been deleted */
     unsigned int        inherit : 1; /* Copy to comments */
diff --git a/src/include/services.h b/src/include/services.h
index 46c0412afa3323d00c0c7741157e8fde8858b787..629ebc7fe0583b323ad67feee245409f8f30a05e 100644
--- a/src/include/services.h
+++ b/src/include/services.h
@@ -1,5 +1,5 @@
 /*
- * $Id: services.h,v 0.44 1999/05/12 13:24:28 byers Exp $
+ * $Id: services.h,v 0.45 1999/05/18 13:06:27 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -485,26 +485,22 @@ KOM_( mark_as_read (Conf_no		    conference,
 /* Returns 0 on error */
 extern  Text_no
 KOM_( create_text (const String		  message,
-		   unsigned short	  no_of_misc,
-		   CONST Misc_info	* misc,
+		   CONST Misc_info_list	* misc,
                    Aux_item_list        * aux ));
 
 extern Text_no
 KOM_( create_text_old (const String		  message,
-                       unsigned short	  no_of_misc,
-                       CONST Misc_info	* misc	     ));
+                       CONST Misc_info_list	* misc	     ));
 
 /* Returns 0 on error. This function is experimental. */
 extern  Text_no
 KOM_( create_anonymous_text (const String       message,
-			     unsigned short	no_of_misc,
-			     CONST Misc_info  * misc,
+			     CONST Misc_info_list  * misc,
                              Aux_item_list    *aux          ));
 
 extern  Text_no
 KOM_( create_anonymous_text_old (const String       message,
-                                 unsigned short	no_of_misc,
-                                 CONST Misc_info  * misc	     ));
+                                 CONST Misc_info_list  * misc	     ));
 
 extern Success
 KOM_( delete_text( Text_no text_no ));
diff --git a/src/server/admin.c b/src/server/admin.c
index c647437d9410be2e42e0aef27f138677e2848f3a..b04e396522d400b340e1c746ab7d7f8289ec29fa 100644
--- a/src/server/admin.c
+++ b/src/server/admin.c
@@ -1,5 +1,5 @@
 /*
- * $Id: admin.c,v 0.36 1999/05/16 21:45:00 ceder Exp $
+ * $Id: admin.c,v 0.37 1999/05/18 13:06:45 byers Exp $
  * Copyright (C) 1991, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -33,7 +33,7 @@
 #endif
 
 static const char *
-rcsid = "$Id: admin.c,v 0.36 1999/05/16 21:45:00 ceder Exp $";
+rcsid = "$Id: admin.c,v 0.37 1999/05/18 13:06:45 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -372,6 +372,21 @@ modify_server_info(Number_list      *items_to_delete,
                    Aux_item_list    *items_to_add)
 {
     CHK_LOGIN(FAILURE);
+
+    if (items_to_delete->length > param.max_delete_aux)
+    {
+        kom_errno = KOM_LONG_ARRAY;
+        err_stat = param.max_delete_aux;
+        return FAILURE;
+    }
+
+    if (items_to_add->length > param.max_add_aux)
+    {
+        kom_errno = KOM_LONG_ARRAY;
+        err_stat = param.max_add_aux;
+        return FAILURE;
+    }
+
     if ( !ENA(admin, 1) )
     {
         err_stat = 0;
diff --git a/src/server/aux-item-def-parse.y b/src/server/aux-item-def-parse.y
index 2516bcccaf6f6c73ede8cf04cbfef5c43283cea2..b761bde23811bc797e4f25fdb2b1e1d2f2472040 100644
--- a/src/server/aux-item-def-parse.y
+++ b/src/server/aux-item-def-parse.y
@@ -1,6 +1,6 @@
 %{
 /*
- * $Id: aux-item-def-parse.y,v 1.5 1999/05/12 13:24:55 byers Exp $
+ * $Id: aux-item-def-parse.y,v 1.6 1999/05/18 13:06:45 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -213,8 +213,9 @@ head        :       NUMBER ':' ID '(' targets ')'
             }
             |       NUMBER ':' ID '(' targets ')' DISABLED
             {
-                def.tag = 0;
+                def.tag = $1;
                 def.name = s_crea_c_str($3);
+                def.disabled = TRUE;
                 s_clear(&($3));
                 $3 = EMPTY_STRING;
                 yylval.str = EMPTY_STRING;
diff --git a/src/server/aux-items.c b/src/server/aux-items.c
index 57fdfe86a0a4c3cc67b254fc81d2eccf158ba501..de6924cca630cdcfd4bbffa72e2719b7a68089b5 100644
--- a/src/server/aux-items.c
+++ b/src/server/aux-items.c
@@ -1,5 +1,5 @@
 /*
- * $Id: aux-items.c,v 1.11 1999/05/16 21:45:15 ceder Exp $
+ * $Id: aux-items.c,v 1.12 1999/05/18 13:06:46 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -77,6 +77,7 @@ static Aux_item_definition compiled_aux_items[] =
 void aux_item_trigger_mark_text(Aux_item_trigger_data *);
 void aux_item_trigger_unmark_text(Aux_item_trigger_data *);
 void aux_item_trigger_mirror_faq(Aux_item_trigger_data *);
+void aux_item_trigger_link_item(Aux_item_trigger_data *data);
 
 
 /* Forward declarations of validators */
@@ -93,6 +94,7 @@ aux_item_triggers [] =
     { "mark-text", aux_item_trigger_mark_text },
     { "unmark-text", aux_item_trigger_unmark_text },
     { "link-faq", aux_item_trigger_mirror_faq },
+    { "link-item", aux_item_trigger_link_item },
     { NULL, NULL }
 };
 
@@ -115,6 +117,7 @@ Aux_item_definition empty_aux_item_definition =
     0,                      /* Tag */            
     { 0,0,0,0,0,0,0,0 },    /* Clear flags */    
     { 0,0,0,0,0,0,0,0 },    /* Set flags */      
+    0,                      /* Disabled */
     0,                      /* Author only */    
     0,                      /* Supervisor only */
     0,                      /* System only */
@@ -149,6 +152,7 @@ static Aux_item_definition simple_aux_item =
     0,                      /* Tag */            
     { 0,0,0,0,0,0,0,0 },    /* Clear flags */    
     { 0,0,0,0,0,0,0,0 },    /* Set flags */      
+    0,                      /* Disabled */
     0,                      /* Author only */    
     0,                      /* Supervisor only */
     0,                      /* System only */
@@ -304,6 +308,106 @@ find_aux_item_definition(Aux_item *item)
  * ======================================================================
  */
  
+
+/* TRIGGER THINGS */
+
+
+static void
+aux_item_fix_trigger_data(Aux_item_trigger_data *data)
+{
+    switch (data->object_type)
+    {
+    case TEXT_OBJECT_TYPE:
+        data->item = &((Text_stat *)data->object)->aux_item_list.items[data->item_index];
+        break;
+    case CONF_OBJECT_TYPE:
+        data->item = &((Conference *)data->object)->aux_item_list.items[data->item_index];
+        break;
+    case INFO_OBJECT_TYPE:
+        data->item = &((Info *)data->object)->aux_item_list.items[data->item_index];
+        break;
+
+    default:
+        break;
+    }
+}
+
+
+static void
+aux_item_call_add_triggers(Aux_item_definition *def,
+			   Object_type object_type,
+			   unsigned long item_index,
+			   unsigned long integer_argument,
+			   void     * pointer_argument,
+                           Aux_item * item)
+{
+    unsigned long i;
+    Aux_item_trigger_data data;
+    
+    data.action = AUX_ITEM_ADD_ACTION;
+    data.object_type = object_type;
+    data.item_index = item_index;
+    data.object_no = integer_argument;
+    data.object = pointer_argument;
+    data.item = item;
+
+    for (i = 0; i < def->num_add_triggers; i++)
+    {
+        (*(def->add_triggers[i]))(&data);
+        aux_item_fix_trigger_data(&data);
+    }
+}
+
+static void
+aux_item_call_delete_triggers(Aux_item_definition *def,
+                              Object_type object_type,
+                              unsigned long item_index,
+                              unsigned long integer_argument,
+                              void     * pointer_argument,
+                              Aux_item *item)
+{
+    unsigned long i;
+    Aux_item_trigger_data data;
+    
+    data.action = AUX_ITEM_DELETE_ACTION;
+    data.object_type = object_type;
+    data.item_index = item_index;
+    data.object_no = integer_argument;
+    data.object = pointer_argument;
+    data.item = item;
+
+    for (i = 0; i < def->num_delete_triggers; i++)
+    {
+        (*(def->delete_triggers[i]))(&data);
+    }
+}
+
+static void
+aux_item_call_undelete_triggers(Aux_item_definition *def,
+				Object_type object_type,
+				unsigned long item_index,
+				unsigned long integer_argument,
+				void     * pointer_argument,
+                                Aux_item * item)
+{
+    unsigned long i;
+    Aux_item_trigger_data data;
+    
+    data.action = AUX_ITEM_UNDELETE_ACTION;
+    data.object_type = object_type;
+    data.item_index = item_index;
+    data.object_no = integer_argument;
+    data.object = pointer_argument;
+    data.item = item;
+
+    for (i = 0; i < def->num_undelete_triggers; i++)
+    {
+        (*(def->undelete_triggers[i]))(&data);
+    }
+}
+
+
+
 /*
  * initialize_aux_items
  *
@@ -406,81 +510,306 @@ initialize_aux_items(char *aux_def_file)
 }
 
 
-/* TRIGGER THINGS */
-
 
-static void
-aux_item_call_add_triggers(Aux_item_definition *def,
-			   Object_type object_type,
-			   unsigned long item_index,
-			   unsigned long integer_argument,
-			   void     * pointer_argument,
-                           Aux_item * item)
+long
+find_aux_item_index(Aux_item_list *list, unsigned long aux_no)
 {
     unsigned long i;
-    Aux_item_trigger_data data;
+
+    for (i = 0; i < list->length; i++)
+    {
+        if (list->items[i].aux_no == aux_no)
+            return i;
+    }
+
+    return -1;
+}
+
+
+/* Find the aux item list containing the item that ITEM is linked to */
+
+static Aux_item_list *
+find_linked_aux_item_list(Aux_item *item)
+{
+    Text_stat       *text_stat;
+    Conference      *conf_stat;
     
-    data.action = AUX_ITEM_ADD_ACTION;
-    data.object_type = object_type;
-    data.item_index = item_index;
-    data.object_no = integer_argument;
-    data.object = pointer_argument;
-    data.item = item;
+    switch (item->linked_item.target_type)
+    {
+    case NO_OBJECT_TYPE:
+        return NULL;
 
-    for (i = 0; i < def->num_add_triggers; i++)
+    case TEXT_OBJECT_TYPE:
+        GET_T_STAT(text_stat, item->linked_item.target_object.text, NULL);
+        return &text_stat->aux_item_list;
+
+    case CONF_OBJECT_TYPE:
+        GET_C_STAT(conf_stat, item->linked_item.target_object.conf, NULL);
+        return &conf_stat->aux_item_list;
+
+    case INFO_OBJECT_TYPE:
+        return &kom_info.aux_item_list;
+
+    case PERS_OBJECT_TYPE:
+    default:
+        /* No lists in these items */
+        kom_log("find_linked_aux_item_list: Bad aux_item somewhere: link to person or other kind.");
+        return NULL;
+    }
+}
+
+/* Find the aux item that ITEM is linked to */
+
+static Aux_item *
+find_linked_aux_item(Aux_item *item)
+{
+    Aux_item_list       *target_list;
+
+    target_list = find_linked_aux_item_list(item);
+    if (target_list == NULL)
+        return NULL;
+
+    return find_aux_item(target_list, item->linked_item.target_item);
+}
+
+/* Mark the object linked to by an aux_item as changed */
+
+static void
+mark_linked_object_as_changed(Aux_item *item)
+{
+    Text_stat       *text_stat;
+    Conference      *conf_stat;
+
+    switch (item->linked_item.target_type)
     {
-        (*(def->add_triggers[i]))(&data);
+    case TEXT_OBJECT_TYPE:
+        VOID_GET_T_STAT(text_stat, item->linked_item.target_object.text);
+        mark_text_as_changed(item->linked_item.target_object.text);
+        break;
+
+    case CONF_OBJECT_TYPE:
+        VOID_GET_C_STAT(conf_stat, item->linked_item.target_object.conf);
+        mark_conference_as_changed(item->linked_item.target_object.conf);
+        break;
+
+    case INFO_OBJECT_TYPE:
+    case PERS_OBJECT_TYPE:
+    default:
+        /* Need no commit for these objects */
     }
 }
 
+
+
+
+/*
+ * Utility function for linking aux items. This function will take
+ * care of adding the appropriate item to the appropriate list.
+ *
+ * Note that this may cause aux-item lists to be realloced, so pointers
+ * into such lists may become invalid. Take particular care with the
+ * pointers in aux-item trigger data
+ *
+ * Call aux_item_fix_trigger_data if you need to fix the contents of
+ * trigger data after calling this function.
+ */
+
+
 static void
-aux_item_call_delete_triggers(Aux_item_definition *def,
-                              Object_type object_type,
-                              unsigned long item_index,
-                              unsigned long integer_argument,
-                              void     * pointer_argument,
-                              Aux_item *item)
+aux_item_link_items(Object_type     src_type,  /* Source object type */
+                    unsigned long   src_no,    /* Source object pointer */
+                    void           *src_ptr,   /* Source pointer */
+                    Aux_item       *src_item,  /* Source item */
+
+                    Object_type     dst_type,  /* Destination obj type */
+                    unsigned long   dst_no,    /* Destination obj pointer */
+                    void           *dst_ptr,   /* Destination pointer */
+                    Aux_item       *dst_item_data)
 {
-    unsigned long i;
-    Aux_item_trigger_data data;
-    
-    data.action = AUX_ITEM_DELETE_ACTION;
-    data.object_type = object_type;
-    data.item_index = item_index;
-    data.object_no = integer_argument;
-    data.object = pointer_argument;
-    data.item = item;
+    Aux_item_list       item_list;
 
-    for (i = 0; i < def->num_delete_triggers; i++)
+    /* Get a pointer to the destination object */
+
+    if (dst_ptr == NULL)
     {
-        (*(def->delete_triggers[i]))(&data);
+        switch (dst_type)
+        {
+        case TEXT_OBJECT_TYPE:
+            dst_ptr = cached_get_text_stat(dst_no);
+            break;
+        case CONF_OBJECT_TYPE:
+            dst_ptr = cached_get_conf_stat(dst_no);
+            break;
+        case INFO_OBJECT_TYPE:
+            dst_ptr = &kom_info;
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (dst_ptr == NULL || src_ptr == NULL)
+        return;
+
+
+    /* Set up the linking information in the destination item */
+
+    dst_item_data->linked_item.target_type = src_type;
+    dst_item_data->linked_item.target_item = src_item->aux_no;
+    switch (src_type)
+    {
+    case TEXT_OBJECT_TYPE: dst_item_data->linked_item.target_object.text = src_no; break;
+    case CONF_OBJECT_TYPE: dst_item_data->linked_item.target_object.conf = src_no; break;
+    case INFO_OBJECT_TYPE:
+    default:
+        dst_item_data->linked_item.target_object.text = 0;
     }
+
+
+    /* Set up the linking information in the source item */
+
+    src_item->linked_item.target_type = dst_type;
+    src_item->linked_item.target_item = 0;
+    switch (dst_type)
+    {
+    case TEXT_OBJECT_TYPE:
+        src_item->linked_item.target_object.text = dst_no;
+        src_item->linked_item.target_item = ((Text_stat *)dst_ptr)->highest_aux + 1;
+        break;
+    case CONF_OBJECT_TYPE:
+        src_item->linked_item.target_object.conf = dst_no;
+        src_item->linked_item.target_item = ((Conference *)dst_ptr)->highest_aux + 1;
+        break;
+    case INFO_OBJECT_TYPE:
+        src_item->linked_item.target_item = ((Info *)dst_ptr)->highest_aux_no + 1;
+        src_item->linked_item.target_object.text = 0;
+        src_item->linked_item.target_object.conf = 0;
+        break;
+    default:
+        src_item->linked_item.target_item = 0;
+        src_item->linked_item.target_object.text = 0;
+        src_item->linked_item.target_object.conf = 0;
+    }
+
+
+    /* Set up an item list to add */
+
+    item_list.length = 1;
+    item_list.items = dst_item_data;
+    prepare_aux_item_list(&item_list, 0);
+
+
+    /*
+     * Add the item and mark the destination as changed
+     *
+     * Note that these calls may cause the aux item list of the
+     * destination to move in memory due to calls to realloc.
+     */
+
+    switch (dst_type)
+    {
+    case TEXT_OBJECT_TYPE:
+        text_stat_add_aux_item_list((Text_stat *)dst_ptr,
+                                    (Text_no)dst_no, &item_list, 0);
+        mark_text_as_changed((Text_no)dst_no);
+        break;
+    case CONF_OBJECT_TYPE:
+        conf_stat_add_aux_item_list((Conference *)dst_ptr,
+                                    (Conf_no)dst_no, &item_list, 0);
+        mark_conference_as_changed((Conf_no)dst_no);
+        break;
+
+    case INFO_OBJECT_TYPE:
+        system_add_aux_item_list((Info *)dst_ptr, &item_list, 0);
+        break;
+
+    default:
+        break;
+    }
+
+    /*
+     * Set src_item to NULL since there is a chance that it is
+     * no longer valid (this happens when the source and destination
+     * objects are the same and reallocing the aux item list causes
+     *  it to move in memory
+     */
+
+    src_item = NULL;
+
+    /*
+     * Mark the source object as changed
+     */
+
+    mark_linked_object_as_changed(dst_item_data);
 }
 
+
+
+
 static void
-aux_item_call_undelete_triggers(Aux_item_definition *def,
-				Object_type object_type,
-				unsigned long item_index,
-				unsigned long integer_argument,
-				void     * pointer_argument,
-                                Aux_item * item)
+aux_item_list_add_items(Aux_item_list *add_to_list,
+                        Aux_item_list *items_to_add,
+                        Object_type    object_type,
+                        unsigned long  object_no,
+                        void          *object_ptr,
+                        unsigned long *highest_ptr,
+                        Pers_no        item_creator)
 {
-    unsigned long i;
-    Aux_item_trigger_data data;
-    
-    data.action = AUX_ITEM_UNDELETE_ACTION;
-    data.object_type = object_type;
-    data.item_index = item_index;
-    data.object_no = integer_argument;
-    data.object = pointer_argument;
-    data.item = item;
+    unsigned long       i;
+    unsigned long       highest_local;
+    unsigned long       start_index;
 
-    for (i = 0; i < def->num_undelete_triggers; i++)
+    if (items_to_add == NULL)
+        return;
+
+    /*
+     * Make local copies of variables we need in their original state
+     */
+
+    start_index = add_to_list->length;
+    highest_local = *highest_ptr;
+
+    /*
+     * Set up the target list so it looks like we've added
+     * items to it already. That way it is semi-safe to call
+     * this function recursively.
+     */
+
+    add_to_list->items = srealloc(add_to_list->items,
+                                  (add_to_list->length + items_to_add->length) *
+                                  sizeof(Aux_item));
+    add_to_list->length += items_to_add->length;
+    *highest_ptr = *highest_ptr + items_to_add->length;
+
+    for (i = 0; i < items_to_add->length; i++)
     {
-        (*(def->undelete_triggers[i]))(&data);
+        init_aux_item(&add_to_list->items[start_index + i]);
+    }
+
+    /*
+     * Now add the items and call the add triggers
+     */
+
+    for (i = 0; i < items_to_add->length; i++)
+    {
+        highest_local += 1;
+        copy_aux_item(&add_to_list->items[i + start_index],
+                      &items_to_add->items[i]);
+        add_to_list->items[i + start_index].aux_no  = highest_local;
+        add_to_list->items[i + start_index].creator = item_creator;
+        aux_item_call_add_triggers(
+            find_aux_item_definition(&items_to_add->items[i]),
+            object_type,
+            i + start_index,
+            object_no,
+            object_ptr,
+            &add_to_list->items[i + start_index]);
     }
 }
 
+
+
+
 /*
  * prepare_aux_item_list
  *
@@ -533,7 +862,6 @@ void prepare_aux_item(Aux_item *item,
 
     item->creator = creator;
     item->sent_at = current_time;
-    init_aux_item_link(&item->linked_item);
 }
 
 
@@ -630,7 +958,7 @@ static Bool aux_item_validate(Aux_item_validation_data validation_data)
 
         default:
             kom_log("BUG: unknown aux_item validator type");
-            break;
+
         }
     }
 
@@ -691,6 +1019,12 @@ aux_item_add_perm(Aux_item *item,
         return FALSE;
     }
 
+    if (def->disabled)
+    {
+        kom_errno = KOM_ILL_AUX;
+        return FALSE;
+    }
+
     switch (object_type)
     {
     case TEXT_OBJECT_TYPE: can_add_when = def->text_a; break;
@@ -830,7 +1164,7 @@ aux_inherit_items(Aux_item_list *target,
     Aux_item item;
     Aux_item_definition *def;
 
-    /* FIXME: Inheriting linked items is strange, but works. */
+    /* Inheriting linked items is strange, but works. */
 
     if (!target || !parent)
         return;
@@ -856,6 +1190,7 @@ aux_inherit_items(Aux_item_list *target,
                 continue;
 
             copy_aux_item(&item, &parent->items[i]);
+            init_aux_item_link(&item.linked_item);
             prepare_aux_item(&item, parent->items[i].creator, def);
             if (item.inherit_limit != 0)
                 item.inherit_limit -= 1;
@@ -976,97 +1311,6 @@ check_delete_aux_item_list(Number_list *items_to_delete,
     return OK;
 }
 
-
-
-long
-find_aux_item_index(Aux_item_list *list, unsigned long aux_no)
-{
-    unsigned long i;
-
-    for (i = 0; i < list->length; i++)
-    {
-        if (list->items[i].aux_no == aux_no)
-            return i;
-    }
-
-    return -1;
-}
-
-
-/* Find the aux item list containing the item that ITEM is linked to */
-
-static Aux_item_list *
-find_linked_aux_item_list(Aux_item *item)
-{
-    Text_stat       *text_stat;
-    Conference      *conf_stat;
-    
-    switch (item->linked_item.target_type)
-    {
-    case NO_OBJECT_TYPE:
-        return NULL;
-
-    case TEXT_OBJECT_TYPE:
-        GET_T_STAT(text_stat, item->linked_item.target_object.text, NULL);
-        return &text_stat->aux_item_list;
-
-    case CONF_OBJECT_TYPE:
-        GET_C_STAT(conf_stat, item->linked_item.target_object.conf, NULL);
-        return &conf_stat->aux_item_list;
-
-    case INFO_OBJECT_TYPE:
-        return &kom_info.aux_item_list;
-
-    case PERS_OBJECT_TYPE:
-    default:
-        /* No lists in these items */
-        kom_log("find_linked_aux_item_list: Bad aux_item somewhere: link to person or other kind.");
-        return NULL;
-    }
-}
-
-/* Find the aux item that ITEM is linked to */
-
-static Aux_item *
-find_linked_aux_item(Aux_item *item)
-{
-    Aux_item_list       *target_list;
-
-    target_list = find_linked_aux_item_list(item);
-    if (target_list == NULL)
-        return NULL;
-
-    return find_aux_item(target_list, item->linked_item.target_item);
-}
-
-/* Mark the object linked to by an aux_item as changed */
-
-static void
-mark_linked_object_as_changed(Aux_item *item)
-{
-    Text_stat       *text_stat;
-    Conference      *conf_stat;
-
-    switch (item->linked_item.target_type)
-    {
-    case TEXT_OBJECT_TYPE:
-        VOID_GET_T_STAT(text_stat, item->linked_item.target_object.text);
-        mark_text_as_changed(item->linked_item.target_object.text);
-        break;
-
-    case CONF_OBJECT_TYPE:
-        VOID_GET_C_STAT(conf_stat, item->linked_item.target_object.conf);
-        mark_conference_as_changed(item->linked_item.target_object.conf);
-        break;
-
-    case INFO_OBJECT_TYPE:
-    case PERS_OBJECT_TYPE:
-    default:
-        /* Need no commit for these objects */
-    }
-}
-
-
 /*
  * delete_aux_item_list
  *
@@ -1133,20 +1377,23 @@ delete_aux_item_list(Number_list *items_to_delete,
             {
             case CONF_OBJECT_TYPE:
                 linked_object_no = item->linked_item.target_object.conf;
-                linked_object = (void*)cached_get_text_stat(linked_object_no);
+                linked_object = (void*)cached_get_conf_stat(linked_object_no);
                 break;
             case TEXT_OBJECT_TYPE:
                 linked_object_no = item->linked_item.target_object.text;
-                linked_object = (void*)cached_get_conf_stat(linked_object_no);
+                linked_object = (void*)cached_get_text_stat(linked_object_no);
                 break;
             case INFO_OBJECT_TYPE:
                 linked_object_no = 0;
                 linked_object = NULL;
                 break;
             default:
-		restart_kom("delete_aux_item_list(): bad target type\n");
+		kom_log("delete_aux_item_list(): bad target type\n");
+                return;
             }
 
+            /* We only get here if the link type is known */
+
             delete_aux_item_list(&linked_delete,
                                  linked_item_list,
                                  item->linked_item.target_type,
@@ -1169,6 +1416,8 @@ undelete_aux_item_list(Number_list *items_to_undelete,
                        unsigned long object_no,
                        void *object)
 {
+    Kom_err         saved_kom_errno;
+    unsigned long   saved_err_stat;
     long            i;
     Aux_item       *item;
     Aux_item       *linked_item;
@@ -1179,6 +1428,9 @@ undelete_aux_item_list(Number_list *items_to_undelete,
     Number_list     linked_undelete;
     void           *linked_object;
     
+    saved_kom_errno = kom_errno;
+    saved_err_stat = err_stat;
+
     for (i = 0; i < items_to_undelete->length; i++)
     {
         if (items_to_undelete->data[i] == 0)
@@ -1220,20 +1472,25 @@ undelete_aux_item_list(Number_list *items_to_undelete,
             {
             case CONF_OBJECT_TYPE:
                 linked_object_no = item->linked_item.target_object.conf;
-                linked_object = (void*)cached_get_text_stat(linked_object_no);
+                linked_object = (void*)cached_get_conf_stat(linked_object_no);
                 break;
             case TEXT_OBJECT_TYPE:
                 linked_object_no = item->linked_item.target_object.text;
-                linked_object = (void*)cached_get_conf_stat(linked_object_no);
+                linked_object = (void*)cached_get_text_stat(linked_object_no);
                 break;
             case INFO_OBJECT_TYPE:
                 linked_object_no = 0;
                 linked_object = NULL;
                 break;
             default:
-		restart_kom("undelete_aux_item_list(): bad link type\n");
+		kom_log("undelete_aux_item_list(): bad link type\n");
+                kom_errno = saved_kom_errno;
+                err_stat = saved_err_stat;
+                return;
             }
 
+            /* We only get here if the link type is known */
+
             undelete_aux_item_list(&linked_undelete,
                                    linked_item_list,
                                    item->linked_item.target_type,
@@ -1241,6 +1498,9 @@ undelete_aux_item_list(Number_list *items_to_undelete,
                                    linked_object);
         }
     }
+
+    kom_errno = saved_kom_errno;
+    err_stat = saved_err_stat;
 }
 
 
@@ -1424,34 +1684,13 @@ void text_stat_add_aux_item_list(Text_stat *text_s,
                                  Aux_item_list *item_list,
                                  Pers_no item_creator)
 {
-    unsigned long i;
-
-    if (item_list == NULL)
-        return;
-
-    text_s->aux_item_list.items = srealloc(text_s->aux_item_list.items,
-                                           (text_s->aux_item_list.length +
-                                            item_list->length) *
-                                           sizeof(Aux_item));
-
-    for (i = 0; i < item_list->length; i++)
-    {
-        text_s->highest_aux += 1;
-        item_list->items[i].aux_no = text_s->highest_aux;
-        item_list->items[i].creator = item_creator;
-
-        copy_aux_item(
-            &text_s->aux_item_list.items[text_s->aux_item_list.length],
-            &item_list->items[i]);
-        text_s->aux_item_list.length += 1;
-        aux_item_call_add_triggers(
-            find_aux_item_definition(&item_list->items[i]),
-            TEXT_OBJECT_TYPE,
-            text_s->aux_item_list.length - 1,
-            text_no,
-            text_s,
-            &item_list->items[i]);
-    }
+    aux_item_list_add_items(&text_s->aux_item_list,
+                            item_list,
+                            TEXT_OBJECT_TYPE,
+                            text_no,
+                            text_s,
+                            &text_s->highest_aux,
+                            item_creator);
 }
 
 
@@ -1521,32 +1760,16 @@ conf_stat_add_aux_item_list(Conference    *conf,
                             Aux_item_list *item_list,
                             Pers_no        item_creator)
 {
-    unsigned long i;
+    aux_item_list_add_items(&conf->aux_item_list,
+                            item_list,
+                            CONF_OBJECT_TYPE,
+                            conf_no,
+                            conf,
+                            &conf->highest_aux,
+                            item_creator);
+}
 
-    if (item_list == NULL)
-        return;
 
-    conf->aux_item_list.items = srealloc(conf->aux_item_list.items,
-                                         (conf->aux_item_list.length +
-                                          item_list->length) *
-                                         sizeof(Aux_item));
-    for (i = 0; i < item_list->length; i++)
-    {
-        conf->highest_aux += 1;
-        item_list->items[i].aux_no = conf->highest_aux;
-        item_list->items[i].creator = item_creator;
-        copy_aux_item(&conf->aux_item_list.items[conf->aux_item_list.length],
-                      &item_list->items[i]);
-        conf->aux_item_list.length += 1;
-        aux_item_call_add_triggers(
-            find_aux_item_definition(&item_list->items[i]),
-            CONF_OBJECT_TYPE,
-            conf->aux_item_list.length - 1,
-            conf_no,
-            conf,
-            &item_list->items[i]);
-    }
-}
 
 Success system_check_add_aux_item_list(Info *info,
                                        Aux_item_list *list,
@@ -1599,32 +1822,13 @@ system_add_aux_item_list(Info    *info,
                          Aux_item_list *item_list,
                          Pers_no        item_creator)
 {
-    unsigned long i;
-
-    if (item_list == NULL)
-        return;
-
-    info->aux_item_list.items = srealloc(info->aux_item_list.items,
-                                         (info->aux_item_list.length +
-                                          item_list->length) *
-                                         sizeof(Aux_item));
-    for (i = 0; i < item_list->length; i++)
-    {
-        info->highest_aux_no += 1;
-        item_list->items[i].aux_no = info->highest_aux_no;
-        item_list->items[i].creator = item_creator;
-        copy_aux_item(&info->aux_item_list.items[info->aux_item_list.length],
-                      &item_list->items[i]);
-        info->aux_item_list.length += 1;
-
-        aux_item_call_add_triggers(
-            find_aux_item_definition(&item_list->items[i]),
-            INFO_OBJECT_TYPE,
-            info->aux_item_list.length - 1,
-            0,
-            info,
-            &item_list->items[i]);
-    }
+    aux_item_list_add_items(&info->aux_item_list,
+                            item_list,
+                            INFO_OBJECT_TYPE,
+                            0,
+                            info,
+                            &info->highest_aux_no,
+                            item_creator);
 }
 
 extern Success
@@ -1683,59 +1887,160 @@ void aux_item_trigger_unmark_text(Aux_item_trigger_data *data)
 
 void aux_item_trigger_mirror_faq(Aux_item_trigger_data *data)
 {
-    Conference      *conf_stat;
-    Conf_no          conf_no;
     Text_no          text_no;
-    Text_stat       *text_stat;
-    Aux_item_list    items;
     Aux_item         item_data;
     char             conf_no_string[40];
-    String_size      ill_char;
-    String_size      end_pos;
+    String_size      ill_char, end_pos;
+    String           str;
     
+
     if (data->object_type != CONF_OBJECT_TYPE || data->object == NULL)
         return;
 
-    init_aux_item(&item_data);
-    conf_stat = (Conference *)data->object;
-    conf_no = (Conf_no)data->object_no;
-    text_no = s_strtol(conf_stat->aux_item_list.items[data->item_index].data,
-                       &ill_char,
-                       10);
+    /* Get the object number of where we want to put the new item */
 
-    VOID_GET_T_STAT(text_stat, text_no);
+    text_no = s_strtol(data->item->data, &ill_char, 10);
 
-    sprintf(conf_no_string, "%-40lu", (unsigned long)conf_no);
+    /* Create the string for the new item */
+
+    sprintf(conf_no_string, "%-40lu", (unsigned long)data->object_no);
+    str = s_fcrea_str(conf_no_string);
+    end_pos = s_strchr(str, ' ', 0);
+    if (end_pos != -1)
+    {
+        s_strdel(&str, end_pos, s_strlen(str) - 1);
+    }
     
+
+    /* Fill in the new item  */
+
+    init_aux_item(&item_data);
     item_data.tag = 28;         /* Mirror of FAQ item */
-    item_data.data = s_fcrea_str(conf_no_string);
-    end_pos = s_strchr(item_data.data, ' ', 0);
-    if (end_pos != -1)
-        s_strdel(&item_data.data, end_pos, s_strlen(item_data.data) - 1);
+    item_data.data = str;
+
+
+    /* Create the link */
+
+    aux_item_link_items(data->object_type,
+                        data->object_no,
+                        data->object,
+                        data->item,
+
+                        TEXT_OBJECT_TYPE,
+                        text_no,
+                        NULL,
+                        &item_data
+                        );
+}
 
-    /* Set up the link from the text to the conference */
+
+/*
+ * Generic link trigger. This is primarily for testing.
+ *
+ * The item must contain three fields, separated with a space character.
+ * Field one is a character containing specifying the object type the
+ * other end of the link is supposed to be in. If it is 'C', the link is
+ * to a conference. If it is 'T', the link is to a text. If it is 'I',
+ * the link is to the system info.
+ *
+ * The second field is the item tag to use for the other end of the link.
+ * 
+ * The third field is the object id of the target object. For the
+ * system info it is ignored but must be present.
+ *
+ * Some examples:
+ *      "C 99 123": Link to an item of type 99 in conference 123
+ *      "I 92 9":   Link to an item of type 92 in the system info
+ *      "T 22 191": Link to an item of type 22 in text 191
+ *
+ * The created item will contain the same kind of information.
+ */
+
+void aux_item_trigger_link_item(Aux_item_trigger_data *data)
+{
+    char             object_no_string[100];
+    char            *tmp_str;
+    char             type_char;
+    Object_type      target_object_type;
+    unsigned long    target_item_tag, target_object_no;
+    int              nread;
+    Aux_item         item_data;
     
-    item_data.linked_item.target_type = CONF_OBJECT_TYPE;
-    item_data.linked_item.target_object.conf = conf_no;
-    item_data.linked_item.target_item = data->item->aux_no;
-   
-    items.length = 1;
-    items.items = &item_data;
+    init_aux_item(&item_data);
 
-    prepare_aux_item_list(&items, 0);
+    /* ----------------------------------------
+     * Find the data for the linked item
+     *
+     * The object type, object id and item tag
+     * are in the item the trigger is called
+     * for
+     *
+     * The string is given by the current item
+     */
 
-    text_stat_add_aux_item_list(text_stat, text_no, &items, 0);
-    mark_text_as_changed(text_no);
+    tmp_str = s_crea_c_str(data->item->data);
+    nread = sscanf(tmp_str,
+                   "%c %lu %lu",
+                   &type_char,
+                   &target_item_tag,
+                   &target_object_no);
+    sfree(tmp_str);
+    if (nread != 3)
+        return;
+
+    switch (type_char)
+    {
+    case 'T': target_object_type = TEXT_OBJECT_TYPE; break;
+    case 'C': target_object_type = CONF_OBJECT_TYPE; break;
+    case 'I': target_object_type = INFO_OBJECT_TYPE; break;
+    default: return;
+    }
+
+
+    /* Create the string for the linked item */
+
+    switch (data->object_type)
+    {
+    case TEXT_OBJECT_TYPE: type_char = 'T'; break;
+    case CONF_OBJECT_TYPE: type_char = 'C'; break;
+    case INFO_OBJECT_TYPE: type_char = 'I'; break;
+    default:               type_char = '?'; break;
+    }
+
+    sprintf(object_no_string, "%c %lu %lu",
+            type_char,
+            (unsigned long)data->item->tag,
+            (unsigned long)data->object_no);
 
-    /* Set up the link from the conference to the text */
 
-    data->item->linked_item.target_type = TEXT_OBJECT_TYPE;
-    data->item->linked_item.target_object.text = text_no;
-    data->item->linked_item.target_item = text_stat->highest_aux;
-    mark_conference_as_changed(conf_no);
+    /*
+     * Create the mirror item in item_data
+     *
+     * Item tag is found above
+     * Item data is found above
+     * Item link target item is the item-no of the current item
+     * Item link target object type is the object type in the trigger data
+     * Item link target object no is the object no in the trigger data
+     */
+
+    item_data.tag = target_item_tag;
+    item_data.data = s_fcrea_str(object_no_string);
+
+    aux_item_link_items(data->object_type,
+                        data->object_no,
+                        data->object,
+                        data->item,
+
+                        target_object_type,
+                        target_object_no,
+                        NULL,
+                        &item_data
+                        );
 }
 
 
+
+
 /*
  * Aux item validators
  */
diff --git a/src/server/aux-items.h b/src/server/aux-items.h
index 0a4ef7eb3001ae9e37f1ad7753eeb2af956f0f95..681778dd79b4605ba1ca2c5dcfbe959eeb32f0fd 100644
--- a/src/server/aux-items.h
+++ b/src/server/aux-items.h
@@ -1,5 +1,5 @@
 /*
- * $Id: aux-items.h,v 1.8 1999/05/16 21:45:25 ceder Exp $
+ * $Id: aux-items.h,v 1.9 1999/05/18 13:06:47 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -121,6 +121,7 @@ struct Aux_item_definition_s {
     unsigned long             tag;
     Aux_item_flags            clear_flags;
     Aux_item_flags            set_flags;
+    Bool                      disabled;
     Bool                      author_only;
     Bool                      supervisor_only;
     Bool                      system_only;
diff --git a/src/server/call-switch.awk b/src/server/call-switch.awk
index 214ab177f9f4f32c278203155aed3e39e8b763a5..ba04c9ef09aaafa4e900567ecf489e2a7123c4c4 100644
--- a/src/server/call-switch.awk
+++ b/src/server/call-switch.awk
@@ -1,5 +1,5 @@
 #
-# $Id: call-switch.awk,v 0.17 1999/05/12 13:25:00 byers Exp $
+# $Id: call-switch.awk,v 0.18 1999/05/18 13:06:48 byers Exp $
 # Copyright (C) 1991, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
 #
 # This file is part of the LysKOM server.
@@ -22,7 +22,7 @@
 #
 # Please mail bug reports to bug-lyskom@lysator.liu.se. 
 #
-# $Id: call-switch.awk,v 0.17 1999/05/12 13:25:00 byers Exp $
+# $Id: call-switch.awk,v 0.18 1999/05/18 13:06:48 byers Exp $
 BEGIN {
     printf("/* Don't edit this file - it is generated automatically");
     printf(" from\n   call-switch.awk and fncdef.txt */\n");
@@ -69,10 +69,10 @@ $1 != "#" && $1 != "" {
 	    printf("&client->membership_type");
 	else if ( $i == "c_local_text_no_p" )
 	    printf("client->c_local_text_no_p");
-	else if ( $i == "c_misc_info_p" )
-	    printf("client->c_misc_info_p");
         else if ( $i == "aux_item_list")
             printf("&client->aux_item_list");
+        else if ( $i == "misc_info_list")
+            printf("&client->misc_info_list");
 	else if ( $i == "time_date" )
 	    printf("&client->time");
         else if ( $i == "info" )
diff --git a/src/server/conference.c b/src/server/conference.c
index c73646d04d604b10e0125eeac06dc43ed854e790..89bfc5b609915a27a70ed14398ac18ae7d8e9a09 100644
--- a/src/server/conference.c
+++ b/src/server/conference.c
@@ -1,5 +1,5 @@
 /*
- * $Id: conference.c,v 0.47 1999/05/16 21:45:36 ceder Exp $
+ * $Id: conference.c,v 0.48 1999/05/18 13:06:49 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -35,7 +35,7 @@
 
 
 static const char *
-rcsid = "$Id: conference.c,v 0.47 1999/05/16 21:45:36 ceder Exp $";
+rcsid = "$Id: conference.c,v 0.48 1999/05/18 13:06:49 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -1348,6 +1348,21 @@ modify_conf_info(Conf_no        conf_no,
     Conference     *conf;
 
     CHK_LOGIN(FAILURE);
+    
+    if (items_to_delete->length > param.max_delete_aux)
+    {
+        kom_errno = KOM_LONG_ARRAY;
+        err_stat = param.max_delete_aux;
+        return FAILURE;
+    }
+
+    if (aux->length > param.max_add_aux)
+    {
+        kom_errno = KOM_LONG_ARRAY;
+        err_stat = param.max_add_aux;
+        return FAILURE;
+    }
+
     GET_C_STAT(conf, conf_no, FAILURE);
 
     /* Check if we may delete and add the items */
diff --git a/src/server/connections.c b/src/server/connections.c
index b0179a9221fba6668d27fea136ac5048b3f67111..6d7f4e57da1893d7e8c0810b076f610abcfc8d44 100644
--- a/src/server/connections.c
+++ b/src/server/connections.c
@@ -1,5 +1,5 @@
 /*
- * $Id: connections.c,v 0.59 1999/05/16 21:45:47 ceder Exp $
+ * $Id: connections.c,v 0.60 1999/05/18 13:06:50 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -36,7 +36,7 @@
 #endif
 
 static const char *
-rcsid = "$Id: connections.c,v 0.59 1999/05/16 21:45:47 ceder Exp $";
+rcsid = "$Id: connections.c,v 0.60 1999/05/18 13:06:50 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -294,8 +294,9 @@ free_parsed(Connection *client)
     s_clear(&client->c_string0);
     s_clear(&client->c_string1);
     client->string0 = EMPTY_STRING; /* So that no one frees it. */
-    sfree( client->c_misc_info_p );
-    client->c_misc_info_p = NULL;
+    sfree(client->misc_info_list.misc);
+    client->misc_info_list.misc = 0;
+    client->misc_info_list.no_of_misc = 0;
     s_clear(&client->aux_item.data);
     sfree( client->c_local_text_no_p);
     client->c_local_text_no_p = NULL;
@@ -305,6 +306,9 @@ free_parsed(Connection *client)
     client->array_parse_pos = 0;
     client->struct_parse_pos = 0;
     client->string_parse_pos = 0;
+    client->hunt_parse_pos = 0;
+    client->array_hunt_num = 0;
+    client->array_hunt_depth = 0;
     sfree(client->num_list.data);
     client->num_list.data = NULL;
     client->num_list.length = 0;
diff --git a/src/server/connections.h b/src/server/connections.h
index 6b806f0b21f2f72870fc232a5e3d5022635a450d..aca1a3675ec06d8be166aa97ed98fee4395150ff 100644
--- a/src/server/connections.h
+++ b/src/server/connections.h
@@ -1,5 +1,5 @@
 /*
- * $Id: connections.h,v 0.41 1999/05/12 13:25:05 byers Exp $
+ * $Id: connections.h,v 0.42 1999/05/18 13:06:51 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -23,7 +23,7 @@
  * Please mail bug reports to bug-lyskom@lysator.liu.se. 
  */
 /*
- * $Id: connections.h,v 0.41 1999/05/12 13:25:05 byers Exp $
+ * $Id: connections.h,v 0.42 1999/05/18 13:06:51 byers Exp $
  *
   * connections.h -- The top level of the communication packet.
   *
@@ -73,6 +73,10 @@ typedef struct connection {
     int			array_parse_index;
     int			struct_parse_pos;
     int			string_parse_pos;
+    int                 hunt_parse_pos;
+
+    int                 array_hunt_num;
+    int                 array_hunt_depth;
 
     int			ref_no;
     Call_header		function;       /* Function to call. */
@@ -92,7 +96,7 @@ typedef struct connection {
     String		c_string1;
     String		string0; /* This string is used for strings that
 				   * are freed by the routines in services.c */
-    Misc_info	       *c_misc_info_p;	/* Freead by free_parsed(). */
+    Misc_info_list      misc_info_list;
     Aux_item_list       aux_item_list;  /* Freed by free_parsed() */
     Aux_item            aux_item;       /* Freed by free_parsed() */
     Local_text_no      *c_local_text_no_p; /* Freead by free_parsed(). */
diff --git a/src/server/fncdef.txt b/src/server/fncdef.txt
index 471b4acc5b6290997cca788f3324ff1da3b286d1..ed6388e008b9c07c883bf0ad43d27fb0ed513785 100644
--- a/src/server/fncdef.txt
+++ b/src/server/fncdef.txt
@@ -1,5 +1,5 @@
 #
-# $Id: fncdef.txt,v 0.39 1999/05/12 13:25:09 byers Exp $
+# $Id: fncdef.txt,v 0.40 1999/05/18 13:06:52 byers Exp $
 # Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997
 # Lysator Academic Computer Association.
 #
@@ -23,7 +23,7 @@
 #
 # Please mail bug reports to bug-lyskom@lysator.liu.se. 
 #
-# $Id: fncdef.txt,v 0.39 1999/05/12 13:25:09 byers Exp $
+# $Id: fncdef.txt,v 0.40 1999/05/18 13:06:52 byers Exp $
 # 
 # This file is used to describe the functions in services.c. All
 # functions that are reachable from the clients are listed here, together
@@ -68,7 +68,7 @@
 25   success get_text            num num num : string
 26   success get_text_stat_old   num : text_stat_old
 27   success mark_as_read        num num c_local_text_no_p (param.mark_as_read_chunk)
-28   number create_text_old      c_string (param.text_len) num c_misc_info_p (param.max_crea_misc)
+28   number create_text_old      c_string (param.text_len) misc_info_list (param.max_crea_misc)
 29   success delete_text         num
 30   success add_recipient       num num num
 31   success sub_recipient       num num
@@ -105,7 +105,7 @@
 # Protocol version 3
 #
 58   success get_last_text       time_date : text_no
-59   number  create_anonymous_text_old   c_string (param.text_len) num c_misc_info_p (param.max_crea_misc)
+59   number  create_anonymous_text_old   c_string (param.text_len) misc_info_list (param.max_crea_misc)
 60   success find_next_text_no num       : text_no
 61   success find_previous_text_no num   : text_no
 #
@@ -153,8 +153,8 @@
 # Protocol version 10
 #
 85   success get_collate_table   : string
-86   number  create_text         c_string (param.text_len) num c_misc_info_p (param.max_crea_misc) aux_item_list (param.max_add_aux)
-87   number  create_anonymous_text   c_string (param.text_len) num c_misc_info_p (param.max_crea_misc) aux_item_list (param.max_add_aux)
+86   number  create_text         c_string (param.text_len) misc_info_list (param.max_crea_misc) aux_item_list (param.max_add_aux)
+87   number  create_anonymous_text   c_string (param.text_len) misc_info_list (param.max_crea_misc) aux_item_list (param.max_add_aux)
 88   number  create_conf         c_string (param.conf_name_len) conf_type aux_item_list (param.max_add_aux)
 89   number  create_person       c_string (param.conf_name_len) c_string (param.pwd_len) pers_flags aux_item_list (param.max_add_aux)
 90   success get_text_stat       num : text_stat
diff --git a/src/server/internal-connections.c b/src/server/internal-connections.c
index 1be0b48fd61032f3f57a7d0abd1c104dda564a86..f33c14e3ae4235762fcf8d374aaf04c59e229256 100644
--- a/src/server/internal-connections.c
+++ b/src/server/internal-connections.c
@@ -1,5 +1,5 @@
 /*
- * $Id: internal-connections.c,v 0.36 1999/05/16 21:45:59 ceder Exp $
+ * $Id: internal-connections.c,v 0.37 1999/05/18 13:06:53 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -35,7 +35,7 @@
 
 
 static const char *
-rcsid = "$Id: internal-connections.c,v 0.36 1999/05/16 21:45:59 ceder Exp $";
+rcsid = "$Id: internal-connections.c,v 0.37 1999/05/18 13:06:53 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -108,6 +108,9 @@ init_connection(Connection *conn)
     conn->array_parse_index = 0;
     conn->struct_parse_pos = 0;
     conn->string_parse_pos = 0;
+    conn->hunt_parse_pos = 0;
+    conn->array_hunt_num = 0;
+    conn->array_hunt_depth = 0;
     conn->ref_no = 0;
     conn->function = call_fnc_login_old;
     conn->num0 = 0;
@@ -117,7 +120,8 @@ init_connection(Connection *conn)
     conn->c_string0 = EMPTY_STRING;
     conn->c_string1 = EMPTY_STRING;
     conn->string0 = EMPTY_STRING;
-    conn->c_misc_info_p = NULL;
+    conn->misc_info_list.no_of_misc = 0;
+    conn->misc_info_list.misc = NULL;
     conn->aux_item.data = EMPTY_STRING;
     conn->aux_item_list.items = NULL;
     conn->aux_item_list.length = 0;
@@ -275,9 +279,11 @@ kill_client(Connection *cp)
 	kom_log("kill_client(): unexpected string remains.\n");
     }
 
-    if ( cp->c_misc_info_p != NULL || cp->c_local_text_no_p != NULL )
+    if ( cp->misc_info_list.misc != NULL || cp->c_local_text_no_p != NULL )
 	kom_log("kill_client(): unexpected remaining data.\n");
 
+    /* FIXME: Check for remaining data in aux-item structures */
+
     sfree(cp);
     --no_of_allocated_connections;
 }
diff --git a/src/server/membership.c b/src/server/membership.c
index 1e71b051f29e95b098cf517a2c15bc090b54bbf7..6f1edca47504b18d8a3393d6171e7544d45e4b4e 100644
--- a/src/server/membership.c
+++ b/src/server/membership.c
@@ -1,5 +1,5 @@
 /*
- * $Id: membership.c,v 0.43 1999/05/16 21:46:10 ceder Exp $
+ * $Id: membership.c,v 0.44 1999/05/18 13:06:54 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -38,7 +38,7 @@
 #define DEBUG_MARK_AS_READ
 
 static const char *
-rcsid = "$Id: membership.c,v 0.43 1999/05/16 21:46:10 ceder Exp $";
+rcsid = "$Id: membership.c,v 0.44 1999/05/18 13:06:54 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -337,6 +337,10 @@ add_rec_time(Conference * conf_c,
 	case sent_by:
 	case sent_at:
 	    break;
+
+        case unknown_info:
+        default:
+            restart_kom("ERROR: bogus misc_info type detected in text %lu\n", text_no);
 	}
     }
 
diff --git a/src/server/param.h b/src/server/param.h
index bfe2b862d51726a93f25f23e80a9aa885a6eea0b..85dda75ceecc619e99582c01b58b772b30058c01 100644
--- a/src/server/param.h
+++ b/src/server/param.h
@@ -1,5 +1,5 @@
 /*
- * $Id: param.h,v 1.25 1999/05/12 13:25:18 byers Exp $
+ * $Id: param.h,v 1.26 1999/05/18 13:06:54 byers Exp $
  * Copyright (C) 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -59,6 +59,7 @@ struct kom_par {
     char *nologin_file;
     char *lyskomd_path;
     char *savecore_path;
+    int y2k_compat;
     int timeout;
     int garbtimeout;
     int synctimeout;
diff --git a/src/server/prot-a-output.c b/src/server/prot-a-output.c
index fdc53f38b24a973f7069f6093b2cffd8d8315cf1..7a3b4ceaf6c2fb2d7a9f6f285c0dffed45d141c4 100644
--- a/src/server/prot-a-output.c
+++ b/src/server/prot-a-output.c
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a-output.c,v 0.44 1999/05/17 22:54:37 ceder Exp $
+ * $Id: prot-a-output.c,v 0.45 1999/05/18 13:06:55 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -35,7 +35,7 @@
 #endif
 
 static const char *
-rcsid = "$Id: prot-a-output.c,v 0.44 1999/05/17 22:54:37 ceder Exp $";
+rcsid = "$Id: prot-a-output.c,v 0.45 1999/05/18 13:06:55 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -759,7 +759,7 @@ prot_a_output_misc_info(Connection *fp,
     }
 }
 
-
+/*
 void
 prot_a_output_time(Connection *fp,
 		   time_t clk)
@@ -771,18 +771,54 @@ prot_a_output_time(Connection *fp,
     prot_a_output_ul(fp, t->tm_sec);
     prot_a_output_ul(fp, t->tm_min);
     prot_a_output_ul(fp, t->tm_hour);
+    prot_a_output_ul(fp, t->tm_mday);
+    prot_a_output_ul(fp, t->tm_mon);
+    prot_a_output_ul(fp, t->tm_year);
+    prot_a_output_ul(fp, t->tm_wday);
+    prot_a_output_ul(fp, t->tm_yday);
+    prot_a_output_ul(fp, t->tm_isdst);
+}
+*/
+
+void
+prot_a_output_time(Connection *fp,
+                       time_t clk)
+{
+    struct tm *t;
+
+    t = localtime( &clk );
 
     /* Please don't tell anyone that you saw this code.  It is fun,
-       mostly harmless, and it only affects a single day.  Don't spoil
-       the fun in advance!  */
-    if (t->tm_year == 100 && t->tm_mday == 1 && t->tm_mon == 0
-	&& t->tm_wday == 6 && t->tm_yday == 1)
+       mostly harmless, and it only affects as many days as the
+       server admin wants (default is two.)
+
+       Don't spoil the fun */
+
+    if (t->tm_year == 100 && t->tm_yday < param.y2k_compat)
     {
-	isc_puts(" 32 11 99 6 366", fp->isc_session);
-	prot_a_output_ul(fp, t->tm_isdst);
-	return;
+        t->tm_year -= 1;              /* Back to 1999 */
+        t->tm_mday = t->tm_yday + 31; /* December 31+yday */
+        t->tm_yday += 365;            /* yday includes all of 1999 */
+        t->tm_mon = 11;               /* Always december */
     }
 
+    prot_a_output_ul(fp, t->tm_sec);
+    prot_a_output_ul(fp, t->tm_min);
+    prot_a_output_ul(fp, t->tm_hour);
+/* =======                                                                */ 
+/*     / * Please don't tell anyone that you saw this code.  It is fun,   */ 
+/*        mostly harmless, and it only affects a single day.  Don't spoil */ 
+/*        the fun in advance!  * /                                        */ 
+/*                                                                        */ 
+/*     if (t->tm_year == 100 && t->tm_mday == 1 && t->tm_mon == 0         */ 
+/*         && t->tm_wday == 6 && t->tm_yday == 1)                         */ 
+/*     {                                                                  */ 
+/*         isc_puts(" 32 11 99 6 366", fp->isc_session);                  */ 
+/*         prot_a_output_ul(fp, t->tm_isdst);                             */ 
+/*         return;                                                        */ 
+/*     }                                                                  */ 
+/*                                                                        */ 
+/* >>>>>>> 0.44                                                           */ 
     prot_a_output_ul(fp, t->tm_mday);
     prot_a_output_ul(fp, t->tm_mon);
     prot_a_output_ul(fp, t->tm_year);
diff --git a/src/server/prot-a-parse-arg-c.awk b/src/server/prot-a-parse-arg-c.awk
index 062dd52c832ba019bf37a45339f6c6dd27e3b97e..a5e2827bc1e42b072ea5fe584c56d6dded190015 100644
--- a/src/server/prot-a-parse-arg-c.awk
+++ b/src/server/prot-a-parse-arg-c.awk
@@ -1,5 +1,5 @@
 #
-# $Id: prot-a-parse-arg-c.awk,v 0.22 1999/05/12 13:25:21 byers Exp $
+# $Id: prot-a-parse-arg-c.awk,v 0.23 1999/05/18 13:06:56 byers Exp $
 # Copyright (C) 1991, 1992, 1993, 1994, 1996  Lysator Academic Computer Association.
 #
 # This file is part of the LysKOM server.
@@ -22,7 +22,7 @@
 #
 # Please mail bug reports to bug-lyskom@lysator.liu.se. 
 #
-# $Id: prot-a-parse-arg-c.awk,v 0.22 1999/05/12 13:25:21 byers Exp $
+# $Id: prot-a-parse-arg-c.awk,v 0.23 1999/05/18 13:06:56 byers Exp $
 BEGIN {
     printf("/* Don't edit this file - it is generated automatically");
     printf(" from\n   prot-a-parse-arg-c.awk and fncdef.txt */\n\n");
@@ -139,9 +139,11 @@ $1 != "#" && $1 != "" {
 	    printf("\t    longjmp(parse_env, ISC_PROTOCOL_ERR);\n");
 	}
         else if ( $i == "aux_item" )
-          printf("\tprot_a_parse_aux_item_list(client, &client->aux_item);\n");
+          printf("\tprot_a_parse_aux_item(client, &client->aux_item);\n");
 	else if ( $i == "aux_item_list" )
           printf("\tprot_a_parse_aux_item_list(client, &client->aux_item_list, %s);\n", $(++i));
+        else if ( $i == "misc_info_list" )
+          printf("\tprot_a_parse_misc_info_list(client, &client->misc_info_list, %s);\n", $(++i));
 	else if ( $i == "time_date" )
 	    printf("\tprot_a_parse_time_date(client, &client->time);\n");
         else if ( $i == "info" )
diff --git a/src/server/prot-a-parse.c b/src/server/prot-a-parse.c
index 0e8b3e265530a8ba87b821c2bac3491ec8fa4bb6..c829811787845bf32ed4dea7a88da9d01f770d09 100644
--- a/src/server/prot-a-parse.c
+++ b/src/server/prot-a-parse.c
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a-parse.c,v 0.37 1999/05/12 13:25:22 byers Exp $
+ * $Id: prot-a-parse.c,v 0.38 1999/05/18 13:06:57 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -34,7 +34,7 @@
 #endif
 
 static const char *
-rcsid = "$Id: prot-a-parse.c,v 0.37 1999/05/12 13:25:22 byers Exp $";
+rcsid = "$Id: prot-a-parse.c,v 0.38 1999/05/18 13:06:57 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -69,6 +69,10 @@ USE(rcsid);
 
 BUGDECL;
 
+/* Forward declarations */
+
+static void prot_a_hunt_array_end(Connection *client);
+
 /*
  * Return next token from the input stream. Note that the String returned
  * by this call points into data that might be freed by the next call to
@@ -157,10 +161,15 @@ prot_a_parse_num_list(Connection *client,
 	    longjmp(parse_env, ISC_PROTOCOL_ERR);
 
 	if (res->length <= maxlen)
+        {
 	    res->data   = smalloc(sizeof(*res->data) * res->length);
+        }
 	else
 	{
-	    assert(res->data == NULL);
+            /* Parse one element more than the maximum to allow clients
+               of this function to detect the too-long array if they
+               want to */
+            res->data = smalloc(sizeof(*res->data) * (maxlen + 1));
 	}
 
 	client->array_parse_index = 0;
@@ -170,13 +179,24 @@ prot_a_parse_num_list(Connection *client,
 	while (client->array_parse_index < res->length)
 	{
 	    long tmp = prot_a_parse_long(client);
-	    if (res->data != NULL)
-		res->data[client->array_parse_index] = tmp;
-	    ++client->array_parse_index;
+
+            /* Enter the value into the array only if the
+               parse index is inside the allocated array */
+
+            if (client->array_parse_index < res->length &&
+                client->array_parse_index < (maxlen + 1))
+            {
+                res->data[client->array_parse_index] = tmp;
+            }
+            client->array_parse_index += 1;
 	}
 	client->array_parse_pos = 3;
 	/* Fall through */
     case 3:			/* Closing brace. */
+        /* Adjust the result length if we were parsing a long array */
+        res->length = min(maxlen+1, res->length);
+
+        /* Read the closing brace */
 	if ( parse_nonwhite_char(client) != '}' )
 	    longjmp(parse_env, ISC_PROTOCOL_ERR);
     default:
@@ -383,6 +403,9 @@ prot_a_parse_string(Connection  *client,
 	/* Fall through */
     case 2:
 	/* Was the string too long? If so, skip the truncated data. */
+        /* It looks like we're leaving one extra character in the
+           string here, which is necessary if we want clients of
+           this function to be able to detect long strings. */
 
 	client_len = result->len;
 	truncated_len = min(maxlen+1, client_len);
@@ -455,11 +478,12 @@ prot_a_parse_aux_item(Connection *client,
 extern void
 prot_a_parse_aux_item_list(Connection *client,
                            Aux_item_list *result,
-                           unsigned long maxlen)
+                           int maxlen)
 {
     static unsigned long err_cnt = 0;
     int i;
     long len;
+    Aux_item dummy_aux_item;
 
     switch (client->array_parse_pos)
     {
@@ -488,11 +512,17 @@ prot_a_parse_aux_item_list(Connection *client,
     case 1:
 	if ( parse_nonwhite_char(client) != '{' )
 	    longjmp(parse_env, ISC_PROTOCOL_ERR);
-	if ( result->length > maxlen )
-	    longjmp(parse_env, ISC_PROTOCOL_ERR);
 
-	result->items = smalloc(result->length * sizeof(Aux_item));
-        for (i = 0; i < result->length; i++)
+        if (result->length <= maxlen)
+        {
+            result->items = smalloc(result->length * sizeof(Aux_item));
+        }
+        else
+        {
+            result->items = smalloc((maxlen+1) * sizeof(Aux_item));
+        }
+        
+        for (i = 0; i < min(result->length, maxlen+1); i++)
         {
             result->items[i].data = EMPTY_STRING;
         }
@@ -501,12 +531,27 @@ prot_a_parse_aux_item_list(Connection *client,
     case 2:
 	while( client->array_parse_index < result->length )
 	{
-	    prot_a_parse_aux_item(client,
-                                  &result->items[client->array_parse_index]);
+            /* Enter a parsed aux item into the list only if we
+               have parsed less than the length of the list */
+            if (client->array_parse_index < result->length &&
+                client->array_parse_index <= maxlen)
+            {
+                prot_a_parse_aux_item(client,
+                                      &result->items[
+                                          client->array_parse_index]);
+            }
+            else
+            {
+                prot_a_parse_aux_item(client, &dummy_aux_item);
+            }
 	    client->array_parse_index += 1;
 	}
 	client->array_parse_pos = 3;
     case 3:
+        /* Adjust the length of the result to the length allocated */
+        result->length = min(result->length, maxlen+1);
+
+        /* Read the closing brace */
 	if ( parse_nonwhite_char(client) != '}' )
 	    longjmp(parse_env, ISC_PROTOCOL_ERR);
     default:
@@ -514,11 +559,105 @@ prot_a_parse_aux_item_list(Connection *client,
     }
 }
                                
+extern void
+prot_a_parse_misc_info_list(Connection *client,
+                            Misc_info_list  *result,
+                            int maxlen)
+{
+    static unsigned long err_cnt = 0;
+    int i;
+    long len;
+    Misc_info dummy_misc_info;
+
+    switch (client->array_parse_pos)
+    {
+    case 0:
+	if ((result->no_of_misc != 0 || result->misc != NULL) && err_cnt++ < 20)
+	{
+	    kom_log("WNG: prot_a_parse_aux_item_list(): len = %lu data = %lu\n",
+		(unsigned long)result->no_of_misc, (unsigned long)result->misc);
+	    result->no_of_misc = 0;
+	    result->misc = NULL;
+	    if (err_cnt == 20)
+		kom_log("The above warning is now turned off.");
+	}
+
+	len = prot_a_parse_long(client);
+        if (len < 0)
+        {
+	    isc_puts("%%Insane array size.\n", client->isc_session);
+	    isc_flush(client->isc_session);
+	    longjmp(parse_env, ISC_LOGOUT);
+        }
+        result->no_of_misc = len;
+	client->array_parse_pos = 1;
+        /* Fall through */
+
+    case 1:
+	if ( parse_nonwhite_char(client) != '{' )
+	    longjmp(parse_env, ISC_PROTOCOL_ERR);
+
+        if (result->no_of_misc <= maxlen)
+        {
+            result->misc = smalloc(result->no_of_misc * sizeof(Misc_info));
+        }
+        else
+        {
+            result->misc = smalloc((maxlen+1) * sizeof(Misc_info));
+        }
+        
+        for (i = 0; i < min(result->no_of_misc, maxlen+1); i++)
+        {
+            result->misc[i].type = unknown_info;
+        }
+	client->array_parse_index = 0;
+	client->array_parse_pos = 2;
+    case 2:
+	while( client->array_parse_index < result->no_of_misc )
+	{
+            /* Enter a parsed aux item into the list only if we
+               have parsed less than the no_of_misc of the list */
+            if (client->array_parse_index < result->no_of_misc &&
+                client->array_parse_index <= maxlen)
+            {
+                prot_a_parse_misc_info(client,
+                                      &result->misc[
+                                          client->array_parse_index]);
+                
+                /* If the most recently parsed item is an unknown, the
+                   misc-info parser will have skipped to the end of the
+                   array. Make allowances for this. */
+                if (result->misc[client->array_parse_index].type == unknown_info)
+                {
+                    result->no_of_misc = client->array_parse_index + 1;
+                }
+            }
+            else
+            {
+                prot_a_parse_misc_info(client, &dummy_misc_info);
+            }
+	    client->array_parse_index += 1;
+	}
+	client->array_parse_pos = 3;
+    case 3:
+        /* Adjust the no_of_misc of the result to the length allocated */
+        result->no_of_misc = min(result->no_of_misc, maxlen+1);
+
+        /* Read the closing brace */
+	if ( parse_nonwhite_char(client) != '}' )
+	    longjmp(parse_env, ISC_PROTOCOL_ERR);
+    default:
+	client->array_parse_pos = 0;
+    }
+}
+
 
 extern void
 prot_a_parse_misc_info(Connection *client,
 		       Misc_info      *result)
 {
+    struct tm tmp_time;
+
     switch ( client->struct_parse_pos )
     {
     case 0:
@@ -560,16 +699,32 @@ prot_a_parse_misc_info(Connection *client,
 	    break;
 
 	case comm_in:
+            result->datum.commented_in = prot_a_parse_long(client);
+            break;
+            
 	case footn_in:
+            result->datum.footnoted_in = prot_a_parse_long(client);
+            break;
+            
 	case rec_time:
+            prot_a_parse_time_date(client, &tmp_time);
+            result->datum.received_at = mktime(&tmp_time);
+            break;
+            
 	case sent_by:
+            result->datum.sender = prot_a_parse_long(client);
+            break;
+            
 	case sent_at:
-	    /* Fall through */
-	    
-#ifndef COMPILE_CHECKS
+            prot_a_parse_time_date(client, &tmp_time);
+            result->datum.sent_at = mktime(&tmp_time);
+            break;
+            
 	default:
-#endif
-	    longjmp(parse_env, ISC_PROTOCOL_ERR);
+            result->datum.unknown_type = result->type;
+            result->type = unknown_info;
+            client->array_hunt_depth = 1;
+            prot_a_hunt_array_end(client);
 	}
     default:
 	client->struct_parse_pos = 0;
@@ -768,3 +923,129 @@ prot_a_hunt_nl(Connection *client)
 	}
     }
 }
+
+/*
+ * Hunt for the end of an array. For this to work you need to set
+ * array_hunt_depth to the number of nested arrays you want to
+ * break out of (normally 1.) After this call the next token on
+ * the input stream from the client will be the closing brace of
+ * the array.
+ */
+
+static void
+prot_a_hunt_array_end(Connection *client)
+{
+    String_size number_end;
+    String_size len;
+
+    while (1) 
+    {
+	switch (client->hunt_parse_pos)
+	{
+	case 0:			/* whitspace/simple tokens */
+	    if ( client->first_to_parse >= s_strlen(client->unparsed) )
+		longjmp(parse_env, ISC_MSG_INCOMPLETE);
+
+	    switch(client->unparsed.string[client->first_to_parse])
+	    {
+	    case ' ':
+	    case '\r':
+	    case '\t':
+	    case '*':
+	    case '\n':
+		client->first_to_parse++;
+		break;
+	    case '{':
+                client->array_hunt_depth += 1;
+                client->first_to_parse++;
+                break;
+	    case '}':
+                client->array_hunt_depth -= 1;
+                if (client->array_hunt_depth <= 0)
+                {
+                    client->hunt_parse_pos = 0;
+                    return;
+                }
+                else
+                {
+                    client->first_to_parse++;
+                }
+                break;
+
+	    case '0': case '1': case '2': case '3': case '4':
+	    case '5': case '6': case '7': case '8': case '9':
+		/* Entering a number -- possibly a string. */
+		/* Don't increase first_to_parse. */
+		client->hunt_parse_pos = 1;
+		break;
+	    default:
+		longjmp(parse_env, ISC_PROTOCOL_ERR);
+	    }
+	    break;
+	case 1:			/* number/string */
+	    /* Entering a number.  The first char is known to be a digit.
+	       Parse the entire number at once. */
+	    len = client->unparsed.string[client->first_to_parse] - '0';
+	    for (number_end = client->first_to_parse + 1;
+		 number_end < s_strlen(client->unparsed);
+		 number_end++)
+	    {
+		if (client->unparsed.string[number_end] >= '0'
+		    && client->unparsed.string[number_end] <= '9')
+		{
+		    len = 10 * len + client->unparsed.string[number_end] - '0';
+		}
+		else
+		{
+		    /* The end of the number was reached. */
+		    break;
+		}
+	    }
+
+	    if (number_end == s_strlen(client->unparsed))
+		longjmp(parse_env, ISC_MSG_INCOMPLETE);
+
+	    if (client->unparsed.string[number_end] == 'H')
+	    {
+		/* We are entering a string.   Use num0 to store the
+		   lenght of the string to skip. */
+		client->array_hunt_num = len;
+		client->first_to_parse = number_end + 1;
+		client->hunt_parse_pos = 2;
+	    }
+	    else
+	    {
+		/* We have just skipped past a number that was not the
+		   start of a string. */
+		client->first_to_parse = number_end;
+		client->hunt_parse_pos = 0;
+	    }
+	    break;
+	case 2:			/* Skipping a string. */
+	    if (client->array_hunt_num == 0)
+	    {
+		/* The entire string has been skipped. */
+		client->hunt_parse_pos = 0;
+		break;
+	    }
+	    len = s_strlen(client->unparsed) - client->first_to_parse;
+	    if (client->array_hunt_num <= len)
+	    {
+		/* The entire string is present.  Skip it. */
+		client->first_to_parse += client->array_hunt_num;
+		client->hunt_parse_pos = 0;
+		break;
+	    }
+	    else
+	    {
+		/* Skip as much of the string as possible. */
+		client->array_hunt_num -= len;
+		client->first_to_parse = s_strlen(client->unparsed);
+		longjmp(parse_env, ISC_MSG_INCOMPLETE);
+	    }
+	    abort();            /* NOTREACHED */
+	default:
+            abort();
+	}
+    }
+}
diff --git a/src/server/prot-a-parse.h b/src/server/prot-a-parse.h
index a32e3cc07e8f71e7a587ade73525a496af274ce3..68275a8bc283c04749897d1c4115d211a56d99cc 100644
--- a/src/server/prot-a-parse.h
+++ b/src/server/prot-a-parse.h
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a-parse.h,v 0.16 1999/05/12 13:25:23 byers Exp $
+ * $Id: prot-a-parse.h,v 0.17 1999/05/18 13:06:58 byers Exp $
  * Copyright (C) 1991, 1992, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -23,7 +23,7 @@
  * Please mail bug reports to bug-lyskom@lysator.liu.se. 
  */
 /*
- * $Id: prot-a-parse.h,v 0.16 1999/05/12 13:25:23 byers Exp $
+ * $Id: prot-a-parse.h,v 0.17 1999/05/18 13:06:58 byers Exp $
  *
  */
 extern long
@@ -67,9 +67,13 @@ prot_a_parse_aux_item(Connection *client,
 extern void
 prot_a_parse_aux_item_list(Connection *client,
                            Aux_item_list *result,
-                           unsigned long maxlen);
+                           int maxlen);
 
 extern void
+prot_a_parse_misc_info_list(Connection *client,
+                            Misc_info_list  *result,
+                            int maxlen);
+extern void
 prot_a_parse_misc_info(Connection *client,
 		Misc_info      *result);
 
diff --git a/src/server/prot-a.c b/src/server/prot-a.c
index b00e5a31f9e48b3e59739a989c481e14ef3d517c..5630dcb97e4fc0e5dc37ba6f224e9cb0223f313b 100644
--- a/src/server/prot-a.c
+++ b/src/server/prot-a.c
@@ -1,5 +1,5 @@
 /*
- * $Id: prot-a.c,v 0.56 1999/04/28 22:13:14 ceder Exp $
+ * $Id: prot-a.c,v 0.57 1999/05/18 13:06:59 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -32,7 +32,7 @@
 #endif
 
 static const char *
-rcsid = "$Id: prot-a.c,v 0.56 1999/04/28 22:13:14 ceder Exp $";
+rcsid = "$Id: prot-a.c,v 0.57 1999/05/18 13:06:59 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -310,6 +310,9 @@ prot_a_init(Connection *conn)
     conn->array_parse_pos = 0;
     conn->struct_parse_pos = 0;
     conn->string_parse_pos = 0;
+    conn->hunt_parse_pos = 0;
+    conn->array_hunt_num = 0;
+    conn->array_hunt_depth = 0;
     conn->ref_no = 0;
     conn->function = call_fnc_login_old;
     conn->num0 = 0;
@@ -319,7 +322,8 @@ prot_a_init(Connection *conn)
     conn->c_string0 = EMPTY_STRING;
     conn->c_string1 = EMPTY_STRING;
     conn->string0 = EMPTY_STRING;
-    conn->c_misc_info_p = NULL;
+    conn->misc_info_list.misc = NULL;
+    conn->misc_info_list.no_of_misc = 0;
     conn->aux_item_list.items = NULL;
     conn->aux_item_list.length = 0;
     conn->c_local_text_no_p = NULL;
@@ -348,7 +352,11 @@ prot_a_destruct(Connection *conn)
     conn->aux_item_list.length = 0;
     sfree(conn->aux_item_list.items);
     conn->aux_item_list.items = NULL;
-    sfree(conn->c_misc_info_p);
+
+    conn->misc_info_list.no_of_misc = 0;
+    sfree(conn->misc_info_list.misc);
+    conn->misc_info_list.misc = NULL;
+
     sfree(conn->c_local_text_no_p);
 }
 
diff --git a/src/server/server-config.c b/src/server/server-config.c
index 57771b6d6caf8bf6c32d6f4a6c2f9712ed2749f7..f97c12c845822370ec7dff741bda396ea0f0ffa7 100644
--- a/src/server/server-config.c
+++ b/src/server/server-config.c
@@ -1,5 +1,5 @@
 /*
- * $Id: server-config.c,v 0.59 1999/05/12 13:25:31 byers Exp $
+ * $Id: server-config.c,v 0.60 1999/05/18 13:07:00 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -37,7 +37,7 @@
 #endif
 
 static const char *
-rcsid = "$Id: server-config.c,v 0.59 1999/05/12 13:25:31 byers Exp $";
+rcsid = "$Id: server-config.c,v 0.60 1999/05/18 13:07:00 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -149,6 +149,12 @@ static const struct parameter parameters[] = {
     {"Nologin file",
          assign_string,  0, 1, "/etc/nologin", &param.nologin_file},
 
+    /* Stuff */
+
+    { "Y2K Compatibility",
+         assign_int,    0, 1, "2", &param.y2k_compat },
+
+
     /* Performance tuning parameters (milliseconds) */
 
     {"Idle timeout",
diff --git a/src/server/session.c b/src/server/session.c
index e64151df0e8028bc3d403227e00c72bef323caf3..4d75f83904d9328bdae774a4a9950f4fab364381 100644
--- a/src/server/session.c
+++ b/src/server/session.c
@@ -1,5 +1,5 @@
 /*
- * $Id: session.c,v 0.46 1999/05/16 21:46:57 ceder Exp $
+ * $Id: session.c,v 0.47 1999/05/18 13:07:01 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -34,7 +34,7 @@
 #endif
 
 static const char *
-rcsid = "$Id: session.c,v 0.46 1999/05/16 21:46:57 ceder Exp $";
+rcsid = "$Id: session.c,v 0.47 1999/05/18 13:07:01 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -936,7 +936,11 @@ accept_async(Number_list *num_list)
      * Check agains maliciously long arrays
      */
     
-    if (num_list->data == NULL && num_list->length > 0)
+    /* FIXME: The following test only needs one branch depending on
+       FIXME: which implementation of prot_a_parse_num_list we go with. */
+
+    if (num_list->length > param.accept_async_len ||
+        (num_list->data == NULL && num_list->length > 0))
     {
         err_stat = 0;
         kom_errno = KOM_LONG_ARRAY;
diff --git a/src/server/testsuite/lyskomd.0/01.exp b/src/server/testsuite/lyskomd.0/01.exp
index fd645ecfd759038edaeec0e0824dea7e768e1d48..a3ee14cfa431fafb391ee04c1beb7eb665b9b86d 100644
--- a/src/server/testsuite/lyskomd.0/01.exp
+++ b/src/server/testsuite/lyskomd.0/01.exp
@@ -351,7 +351,7 @@ send "1113 95 0 { } 0 { }\n"
 simple_expect "%1113 6 0" "modify-system-info"
 # 96:query-predefined-aux-items
 send "1114 96\n"
-simple_expect "=1114 26 { 28 27 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 }" "query-predefined-aux-items"
+simple_expect "=1114 28 { 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 }" "query-predefined-aux-items"
 # 97:set-expire
 send "1115 97 1 76\n"
 simple_expect "%1115 6 0" "set-expire"
diff --git a/src/server/testsuite/lyskomd.0/03.exp b/src/server/testsuite/lyskomd.0/03.exp
index 106766eed91d62fae5debf5624258093fa814b1e..c16bd9e9388abc028cd20fb8593f600bd92aecf8 100644
--- a/src/server/testsuite/lyskomd.0/03.exp
+++ b/src/server/testsuite/lyskomd.0/03.exp
@@ -114,7 +114,7 @@ simple_expect "=1009"
 # exactly these aux-items.  It shouldn't be hard to fix the test suite
 # when more items are added.
 send "1010 96\n"
-simple_expect "=1010 26 { 28 27 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 }"
+simple_expect "=1010 28 { 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 }"
 
 send "1011 82\n"
 simple_expect "=1011"
@@ -1259,7 +1259,7 @@ simple_expect "=1345 $server_compat_version 1 2 3 4 0 1 { 1 9 5 $any_time 000000
 # test call 96 (query-predefined-aux-items)
 talk_to client 1
 send "1346 96\n"
-simple_expect "=1346 26 { 28 27 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 }"
+simple_expect "=1346 28 { 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 }"
 
 # test call 97 (set-expire)
 send "1347 97 10 7123123\n"
diff --git a/src/server/testsuite/lyskomd.0/aux-items-cov.exp b/src/server/testsuite/lyskomd.0/aux-items-cov.exp
index 80310cacad685790fab6732348ed519d38a9375a..cdc6f879afe6f61181dc27a4bb94572aa3d3fa0c 100644
--- a/src/server/testsuite/lyskomd.0/aux-items-cov.exp
+++ b/src/server/testsuite/lyskomd.0/aux-items-cov.exp
@@ -42,7 +42,10 @@ read_versions
 source "$srcdir/config/prot-a.exp"
 
 
-lyskomd_start "lyskomd.0/aux-items.cov"
+lyskomd_start "lyskomd.0/aux-items.cov" "\
+Max aux_items deleted per call: 10
+Max aux_items added per call: 10"
+
 
 client_start 0
 talk_to client 0
@@ -107,6 +110,9 @@ simple_expect "=4000"
 send "4001 95 0 { } 1 { 1004 00000000 0 [holl "999"] }\n"
 simple_expect "=4001"
 
+send "4002 94\n"
+simple_expect "=4002 $any_num $any_num $any_num $any_num $any_num $any_num 1 { 1 1004 5 $any_time 00000000 0 [holl "999"] }"
+
 # Attempt to create item with a broken validation regexp, twice
 
 send "5000 95 0 { } 1 { 1000 00000000 0 [holl "ABC"] }\n"
@@ -131,6 +137,276 @@ simple_expect "=5003"
 # FIXME: Call to aux_item_trigger_mark_text on item added to text?
 # FIXME: Call to aux_item_trigger_unmark_text on item added to text?
 
+# FIXME: Call to modify-X-info with a too-long delete list
+# FIXME: Call to modify-X-info with a too-long add list
+
+send "5100 92 1 11 { 1 2 3 4 5 6 7 8 9 10 11 } 0 { }\n"
+simple_expect "%5100 46 10"
+
+send "5101 92 1 0 { } 11 { 1 00000000 0 [holl "X"] 2 00000000 0 [holl "X"] 3 00000000 0 [holl "X"] 4 00000000 0 [holl "X"] 5 00000000 0 [holl "X"] 6 00000000 0 [holl "X"] 7 00000000 0 [holl "X"] 8 00000000 0 [holl "X"] 9 00000000 0 [holl "X"] 10 00000000 0 [holl "X"] 11 00000000 0 [holl "X"] }\n"
+simple_expect "%5101 46 10"
+
+send "5102 93 5 11 { 1 2 3 4 5 6 7 8 9 10 11 } 0 { }\n"
+simple_expect "%5102 46 10"
+
+send "5103 93 5 0 { } 11 { 1 00000000 0 [holl "X"] 2 00000000 0 [holl "X"] 3 00000000 0 [holl "X"] 4 00000000 0 [holl "X"] 5 00000000 0 [holl "X"] 6 00000000 0 [holl "X"] 7 00000000 0 [holl "X"] 8 00000000 0 [holl "X"] 9 00000000 0 [holl "X"] 10 00000000 0 [holl "X"] 11 00000000 0 [holl "X"] }\n"
+simple_expect "%5103 46 10"
+
+send "5104 95 11 { 1 2 3 4 5 6 7 8 9 10 11 } 0 { }\n"
+simple_expect "%5104 46 10"
+
+send "5105 95 0 { } 11 { 1 00000000 0 [holl "X"] 2 00000000 0 [holl "X"] 3 00000000 0 [holl "X"] 4 00000000 0 [holl "X"] 5 00000000 0 [holl "X"] 6 00000000 0 [holl "X"] 7 00000000 0 [holl "X"] 8 00000000 0 [holl "X"] 9 00000000 0 [holl "X"] 10 00000000 0 [holl "X"] 11 00000000 0 [holl "X"] }\n"
+simple_expect "%5105 46 10"
+
+
+
+# Test linking aux items
+
+# Create on text link to conf
+# Create on text link to info
+# Create on text link to text
+
+kom_login 5 "gazonk" 0
+send "5998 86 [holl "Testing"] 1 { 0 5 } 0 { }\n"
+simple_expect "=5998 4"
+
+send "5999 86 [holl "Jesting"] 1 { 0 5 } 0 { }\n"
+simple_expect "=5999 5"
+
+send "6000 92 4 0 { } 3 { 1006 00000000 0 [holl "T 1007 5"] 1006 00000000 0 [holl "C 1007 5"] 1006 00000000 0 [holl "I 1007 0"] }\n"
+simple_expect "=6000"
+
+send "6001 90 5\n"
+simple_expect "=6001 $any_time 5 0 7 0 2 { 0 5 6 3 } 1 { 1 1007 0 $any_time 00000000 0 [holl "T 1006 4"] }"
+
+send "6002 91 5\n"
+simple_expect "=6002 [holl "Administrat�r .f�r. LysKOM"] 10011000 $any_time $any_time 5 0 5 0 0 0 77 77 1 1 3 0 1 { 1 1007 0 $any_time 00000000 0 [holl "T 1006 4"] }"
+ 
+send "6003 94\n"
+simple_expect "=6003 $any_num $any_num $any_num $any_num $any_num $any_num 2 { 1 1004 5 $any_time 00000000 0 [holl "999"] 2 1007 0 $any_time 00000000 0 [holl "T 1006 4"] }"
+
+
+send "6100 88 [holl "C7"] 00000000 0 { }\n"
+simple_expect "=6100 7"
+
+send "6101 88 [holl "C8"] 00000000 0 { }\n"
+simple_expect "=6101 8"
+
+
+# Create on conf link to conf
+# Create on conf link to info
+# Create on conf link to text
+
+send "6102 93 7 0 { } 3 { 1006 00000000 0 [holl "T 1007 5"] 1006 00000000 0 [holl "C 1007 8"] 1006 00000000 0 [holl "I 1007 0"] }\n"
+simple_expect "=6102"
+
+send "6103 90 5\n"
+simple_expect "=6103 $any_time 5 0 7 0 2 { 0 5 6 3 } 2 { 1 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 2 1007 0 $any_time 00000000 0 [holl "C 1006 7"] }"
+
+send "6104 91 8\n"
+simple_expect "=6104 [holl "C8"] 00000000 $any_time $any_time 5 0 5 0 5 0 77 77 0 1 0 0 1 { 1 1007 0 $any_time 00000000 0 [holl "C 1006 7"] }"
+
+send "6105 94\n"
+simple_expect "=6105 $any_num $any_num $any_num $any_num $any_num $any_num 3 { 1 1004 5 $any_time 00000000 0 [holl "999"] 2 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 3 1007 0 $any_time 00000000 0 [holl "C 1006 7"] }"
+
+
+# Create on info link to conf
+# Create on info link to info
+# Create on info link to text
+
+kom_enable 255
+
+send "6106 95 0 { } 3 { 1006 00000000 0 [holl "T 1007 5"] 1006 00000000 0 [holl "C 1007 8"] 1006 00000000 0 [holl "I 1007 0"] }\n"
+simple_expect "=6106"
+
+send "6107 90 5\n"
+simple_expect "=6107 $any_time 5 0 7 0 2 { 0 5 6 3 } 3 { 1 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 2 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 3 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6108 91 8\n"
+simple_expect "=6108 [holl "C8"] 00000000 $any_time $any_time 5 0 5 0 5 0 77 77 0 1 0 0 2 { 1 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 2 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6109 94\n"
+simple_expect "=6109 $any_num $any_num $any_num $any_num $any_num $any_num 7 { 1 1004 5 $any_time 00000000 0 [holl "999"] 2 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 3 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 4 1006 5 $any_time 00000000 0 [holl "T 1007 5"] 5 1006 5 $any_time 00000000 0 [holl "C 1007 8"] 6 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 7 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+
+
+# Delete manually created text items
+
+send "6200 92 4 3 { 1 2 3 } 0 { }\n"
+simple_expect "=6200"
+
+send "6201 90 5\n"
+simple_expect "=6201 $any_time 5 0 7 0 2 { 0 5 6 3 } 2 { 2 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 3 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6202 91 5\n"
+simple_expect "=6202 [holl "Administrat�r .f�r. LysKOM"] 10011000 $any_time $any_time 5 0 5 0 0 0 77 77 1 1 3 0 0 \\*"
+ 
+send "6203 94\n"
+simple_expect "=6203 $any_num $any_num $any_num $any_num $any_num $any_num 6 { 1 1004 5 $any_time 00000000 0 [holl "999"] 3 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 4 1006 5 $any_time 00000000 0 [holl "T 1007 5"] 5 1006 5 $any_time 00000000 0 [holl "C 1007 8"] 6 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 7 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+
+# Delete manually created conf item
+
+send "6204 93 7 3 { 1 2 3 } 0 { }\n"
+simple_expect "=6204"
+
+send "6205 90 5\n"
+simple_expect "=6205 $any_time 5 0 7 0 2 { 0 5 6 3 } 1 { 3 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+ 
+send "6206 91 8\n"
+simple_expect "=6206 [holl "C8"] 00000000 $any_time $any_time 5 0 5 0 5 0 77 77 0 1 0 0 1 { 2 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6207 94\n"
+simple_expect "=6207 $any_num $any_num $any_num $any_num $any_num $any_num 5 { 1 1004 5 $any_time 00000000 0 [holl "999"] 4 1006 5 $any_time 00000000 0 [holl "T 1007 5"] 5 1006 5 $any_time 00000000 0 [holl "C 1007 8"] 6 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 7 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+
+# Delete manually created info item
+
+kom_enable 255
+
+send "6208 95 3 { 4 5 6 } 0 { }\n"
+simple_expect "=6208"
+
+send "6209 90 5\n"
+simple_expect "=6209 $any_time 5 0 7 0 2 { 0 5 6 3 } 0 \\*"
+
+send "6210 91 8\n"
+simple_expect "=6210 [holl "C8"] 00000000 $any_time $any_time 5 0 5 0 5 0 77 77 0 1 0 0 0 \\*"
+
+send "6211 94\n"
+simple_expect "=6211 $any_num $any_num $any_num $any_num $any_num $any_num 1 { 1 1004 5 $any_time 00000000 0 [holl "999"] }"
+
+
+# Delete auto created info item
+
+send "6212 92 4 0 { } 3 { 1006 00000000 0 [holl "T 1007 5"] 1006 00000000 0 [holl "C 1007 5"] 1006 00000000 0 [holl "I 1007 0"] }\n"
+simple_expect "=6212"
+
+send "6213 90 4\n"
+simple_expect "=6213 $any_time 5 0 7 0 2 { 0 5 6 2 } 3 { 4 1006 5 $any_time 00000000 0 [holl "T 1007 5"] 5 1006 5 $any_time 00000000 0 [holl "C 1007 5"] 6 1006 5 $any_time 00000000 0 [holl "I 1007 0"] }"
+
+
+send "6214 94\n"
+simple_expect "=6214 $any_num $any_num $any_num $any_num $any_num $any_num 2 { 1 1004 5 $any_time 00000000 0 [holl "999"] 8 1007 0 $any_time 00000000 0 [holl "T 1006 4"] }"
+
+send "6215 95 1 { 8 } 0 { }\n"
+simple_expect "=6215"
+
+send "6216 94\n"
+simple_expect "=6216 $any_num $any_num $any_num $any_num $any_num $any_num 1 { 1 1004 5 $any_time 00000000 0 [holl "999"] }"
+
+send "62160 90 4\n"
+simple_expect "=62160 $any_time 5 0 7 0 2 { 0 5 6 2 } 2 { 4 1006 5 $any_time 00000000 0 [holl "T 1007 5"] 5 1006 5 $any_time 00000000 0 [holl "C 1007 5"] }"
+
+
+# Delete auto created conf item
+
+send "6217 91 5\n"
+simple_expect "=6217 [holl "Administrat�r .f�r. LysKOM"] 10011000 $any_time $any_time 5 0 5 0 0 0 77 77 1 1 3 0 1 { 2 1007 0 $any_time 00000000 0 [holl "T 1006 4"] }"
+ 
+send "6218 93 5 1 { 2 } 0 { }\n"
+simple_expect "=6218"
+
+send "6219 91 5\n"
+simple_expect "=6219 [holl "Administrat�r .f�r. LysKOM"] 10011000 $any_time $any_time 5 0 5 0 0 0 77 77 1 1 3 0 0 \\*"
+ 
+send "6220 90 4\n"
+simple_expect "=6220 $any_time 5 0 7 0 2 { 0 5 6 2 } 1 { 4 1006 5 $any_time 00000000 0 [holl "T 1007 5"] }"
+
+
+# Delete auto created text item
+
+send "6221 90 5\n"
+simple_expect "=6221 $any_time 5 0 7 0 2 { 0 5 6 3 } 1 { 4 1007 0 $any_time 00000000 0 [holl "T 1006 4"] }"
+
+send "6222 92 5 1 { 4 } 0 { }\n"
+simple_expect "=6222"
+
+send "6223 90 5\n"
+simple_expect "=6223 $any_time 5 0 7 0 2 { 0 5 6 3 } 0 \\*"
+
+send "6224 90 4\n"
+simple_expect "=6224 $any_time 5 0 7 0 2 { 0 5 6 2 } 0 \\*"
+
+
+# Delete text with items linked to text, conf and info
+# Delete conf with items linked to text, conf and info
+
+# FIXME: Test cases here
+
+
+# Text with permanent item, items linked to conf, text, info
+# Conf with permanent item, items linked to conf, text, info
+# Info with permanent item, items linked to conf, text, info
+# Attempt to delete all (this should cover undelete functions)
+
+# Create the items (bracketed by non-linked items for additional testing)
+
+send "6300 92 4 0 { } 5 { 2000 00000000 0 [holl "A"] 1006 00000000 0 [holl "T 1007 4"] 1006 00000000 0 [holl "C 1007 7"] 1006 00000000 0 [holl "I 1007 0"] 1008 00000000 0 [holl "X"] }\n"
+simple_expect "=6300"
+
+send "6301 93 7 0 { } 5 { 2000 00000000 0 [holl "A"] 1006 00000000 0 [holl "T 1007 4"] 1006 00000000 0 [holl "C 1007 7"] 1006 00000000 0 [holl "I 1007 0"] 1008 00000000 0 [holl "X"] }\n"
+simple_expect "=6301"
+
+send "6302 95 0 { } 5 { 2000 00000000 0 [holl "A"] 1006 00000000 0 [holl "T 1007 4"] 1006 00000000 0 [holl "C 1007 7"] 1006 00000000 0 [holl "I 1007 0"]  1008 00000000 0 [holl "X"] }\n"
+simple_expect "=6302"
+
+
+# Check the original data
+
+send "6303 90 4\n"
+simple_expect "=6303 $any_time 5 0 7 0 2 { 0 5 6 2 } 8 { 7 2000 5 $any_time 00000000 0 [holl "A"] 8 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 9 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 10 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 11 1008 5 $any_time 00000000 0 [holl "X"] 12 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 13 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 14 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6304 91 7\n"
+simple_expect "=6304 [holl "C7"] 00000000 $any_time $any_time 5 0 5 0 5 0 77 77 0 1 0 0 8 { 4 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 5 2000 5 $any_time 00000000 0 [holl "A"] 6 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 7 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 8 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 9 1008 5 $any_time 00000000 0 [holl "X"] 10 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 11 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6305 94\n"
+simple_expect "=6305 $any_num $any_num $any_num $any_num $any_num $any_num 9 { 1 1004 5 $any_time 00000000 0 [holl "999"] 9 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 10 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 11 2000 5 $any_time 00000000 0 [holl "A"] 12 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 13 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 14 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 15 1008 5 $any_time 00000000 0 [holl "X"] 16 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+
+
+# Attempt to delete all items on the text
+
+send "6307 92 4 5 { 7 8 9 10 11 } 1 { 1009 00000000 0 [holl "X"] }\n"
+simple_expect "%6307 48 0"
+
+send "6308 90 4\n"
+simple_expect "=6308 $any_time 5 0 7 0 2 { 0 5 6 2 } 8 { 7 2000 5 $any_time 00000000 0 [holl "A"] 8 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 9 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 10 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 11 1008 5 $any_time 00000000 0 [holl "X"] 12 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 13 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 14 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6309 91 7\n"
+simple_expect "=6309 [holl "C7"] 00000000 $any_time $any_time 5 0 5 0 5 0 77 77 0 1 0 0 8 { 4 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 5 2000 5 $any_time 00000000 0 [holl "A"] 6 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 7 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 8 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 9 1008 5 $any_time 00000000 0 [holl "X"] 10 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 11 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6310 94\n"
+simple_expect "=6310 $any_num $any_num $any_num $any_num $any_num $any_num 9 { 1 1004 5 $any_time 00000000 0 [holl "999"] 9 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 10 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 11 2000 5 $any_time 00000000 0 [holl "A"] 12 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 13 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 14 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 15 1008 5 $any_time 00000000 0 [holl "X"] 16 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+# FIXME: Check all linked objects too
+
+send "6311 93 7 5 { 5 6 7 8 9 } 1 { 1009 00000000 0 [holl "X"] }\n"
+simple_expect "%6311 48 0"
+ 
+send "6312 90 4\n"
+simple_expect "=6312 $any_time 5 0 7 0 2 { 0 5 6 2 } 8 { 7 2000 5 $any_time 00000000 0 [holl "A"] 8 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 9 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 10 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 11 1008 5 $any_time 00000000 0 [holl "X"] 12 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 13 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 14 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6313 91 7\n"
+simple_expect "=6313 [holl "C7"] 00000000 $any_time $any_time 5 0 5 0 5 0 77 77 0 1 0 0 8 { 4 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 5 2000 5 $any_time 00000000 0 [holl "A"] 6 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 7 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 8 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 9 1008 5 $any_time 00000000 0 [holl "X"] 10 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 11 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6314 94\n"
+simple_expect "=6314 $any_num $any_num $any_num $any_num $any_num $any_num 9 { 1 1004 5 $any_time 00000000 0 [holl "999"] 9 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 10 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 11 2000 5 $any_time 00000000 0 [holl "A"] 12 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 13 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 14 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 15 1008 5 $any_time 00000000 0 [holl "X"] 16 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+
+send "6315 95 6 { 1 11 12 13 14 15 } 1 { 1009 00000000 0 [holl "X"] }\n"
+simple_expect "%6315 48 0"
+
+send "6316 90 4\n"
+simple_expect "=6316 $any_time 5 0 7 0 2 { 0 5 6 2 } 8 { 7 2000 5 $any_time 00000000 0 [holl "A"] 8 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 9 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 10 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 11 1008 5 $any_time 00000000 0 [holl "X"] 12 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 13 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 14 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6317 91 7\n"
+simple_expect "=6317 [holl "C7"] 00000000 $any_time $any_time 5 0 5 0 5 0 77 77 0 1 0 0 8 { 4 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 5 2000 5 $any_time 00000000 0 [holl "A"] 6 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 7 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 8 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 9 1008 5 $any_time 00000000 0 [holl "X"] 10 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 11 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+send "6318 94\n"
+simple_expect "=6318 $any_num $any_num $any_num $any_num $any_num $any_num 9 { 1 1004 5 $any_time 00000000 0 [holl "999"] 9 1007 0 $any_time 00000000 0 [holl "T 1006 4"] 10 1007 0 $any_time 00000000 0 [holl "C 1006 7"] 11 2000 5 $any_time 00000000 0 [holl "A"] 12 1006 5 $any_time 00000000 0 [holl "T 1007 4"] 13 1006 5 $any_time 00000000 0 [holl "C 1007 7"] 14 1006 5 $any_time 00000000 0 [holl "I 1007 0"] 15 1008 5 $any_time 00000000 0 [holl "X"] 16 1007 0 $any_time 00000000 0 [holl "I 1006 0"] }"
+
+
 
 # Finish
 
@@ -144,5 +420,5 @@ lyskomd_death
 
 # Try some broken config files
 
-lyskomd_fail_start "lyskomd.0/broken-aux-items.conf"
+# lyskomd_fail_start "lyskomd.0/broken-aux-items.conf"
 
diff --git a/src/server/testsuite/lyskomd.0/aux-items.cov b/src/server/testsuite/lyskomd.0/aux-items.cov
index 8a0bd29d9d200eb0f83926f21fc56de0b60c36e7..cd978407704cfb231ef9ba25a58c5210cb5c0944 100644
--- a/src/server/testsuite/lyskomd.0/aux-items.cov
+++ b/src/server/testsuite/lyskomd.0/aux-items.cov
@@ -12,11 +12,6 @@
     author-only = true;
 }
 
-# 1002 : invalid-trigger (any)
-# {
-#     add-trigger = fubar();
-# }
-
 1003 : mark-text (any)
 {
     add-trigger = mark-text();
@@ -31,3 +26,24 @@
 {
     system-only = true;
 }
+
+1006 : linking (any)
+{
+    add-trigger = link-item();
+}
+
+1007 : linking-target (any)
+{
+}
+
+1008 : nothing-special (any)
+{
+}
+
+1009 : cant-create (any) disabled
+{
+}
+
+2000 : nothing-special (any)
+{
+}
diff --git a/src/server/testsuite/lyskomd.0/prot-a-parse-cov.exp b/src/server/testsuite/lyskomd.0/prot-a-parse-cov.exp
index 0d26a3e4b1f941c7873f6bacc0f18db9e890acac..79b35373d41a764665dd37a26209b11000819e31 100644
--- a/src/server/testsuite/lyskomd.0/prot-a-parse-cov.exp
+++ b/src/server/testsuite/lyskomd.0/prot-a-parse-cov.exp
@@ -19,6 +19,7 @@ lyskomd_start "" "\
 Max password length: 8
 Max aux_items deleted per call: 1
 Max aux_items added per call: 1
+Max links per text: 4
 Max text length: 100
 "
 
@@ -172,23 +173,77 @@ client_start 0
 kom_connect [holl "DejaGnu Test Suite"]
 kom_accept_async "0 { }"
 
-# Try to send a long aux-item list
+# Try to send a long number list
+
+kom_login 5 "gazonk" 0
 
 send "1020 92 1 10 { 1 2 3 4 5 6 7 8 9 10 } 0 { }\n"
-simple_expect "%1020 6 0"
-setup_xfail "*"
-fail "Exceed max num_list length"
+simple_expect "%1020 46 1"
 
-send "1021 92 1 0 { } 2 { 1 00000000 0 [holl "A"] 2 00000000 0 [holl "B"] }\n"
-protocol_error
+send "1021 92 1 0 { } 3 { 1 00000000 0 [holl "A"] 2 00000000 0 [holl "B"] 3 00000000 0 [holl "C"] }\n"
+simple_expect "%1021 46 1"
+
+# Try to send a short delete list, add list and misc-info list
+
+send "1022 92 1 -1 { } 0 { }\n"
+simple_expect "%%Insane array size."
+client_death 0
+client_start 0
+talk_to client 0
+kom_connect "DejaGnu Test Lager"
+kom_accept_async "0 { }"
+
+send "1023 92 1 0 { } -1 { }\n"
+simple_expect "%%Insane array size."
+client_death 0
+client_start 0
+talk_to client 0
+kom_connect "DejaGnu Test Lager"
+kom_accept_async "0 { }"
+
+send "1024 86 [holl "TX"] -1 { } 0 { }\n"
+simple_expect "%%Insane array size."
+client_death 0
+client_start 0
+talk_to client 0
+kom_connect "DejaGnu Test Lager"
+kom_accept_async "0 { }"
+
+send "1025 86 [holl "TX"] 0 { } -1 { }\n"
+simple_expect "%%Insane array size."
+client_death 0
+client_start 0
+talk_to client 0
+kom_connect "DejaGnu Test Lager"
+kom_accept_async "0 { }"
 
+# Bad syntax for misc-info list
 
-# Send a misc-info list that contains an invalid item and a footn_to
-# (Yes, footn_to is untested in 00-06.exp!)
+send "1026 86 [holl "TX"] 1 2 0 { }\n"
+protocol_error
 
-send "1021 86 [holl "TX"] 2 { 4 10 999 999 } 0 { }\n"
+send "1027 86 [holl "TX"] 1 { 0 2 0 { }\n"
 protocol_error
 
+# Send a long misc-info list
+
+kom_login 5 "gazonk" 0
+send "1028 86 [holl "TX"] 6 { 0 1 0 2 0 3 0 4 0 9 0 10 } 0 { }\n"
+simple_expect "%1028 46 4"
+
+send "1029 86 [holl "TX"] 4 { 5 0 7 1 2 3 4 5 6 7 8 9 8 5 9 1 2 3 4 5 6 7 8 9 } 0 { }\n"
+simple_expect "%1029 25 0"
+
+
+
+
+# Send a misc-info list that contains an invalid item with complex data
+
+kom_login 5 "gazonk" 0
+
+send "1042 86 [holl "TX"] 1 { 999 999 3HABC 1 { 1 { } } } 0 { }\n"
+simple_expect "%1042 26 999"
+
 
 # Tests for prot_a_hunt_nl
 
diff --git a/src/server/testsuite/lyskomd.0/text-cov.exp b/src/server/testsuite/lyskomd.0/text-cov.exp
index bb6fd635356a9e0b7a663066e78e94d144b11b09..cae6b25052604a342a9ef538b84f33c4b4cc6dc6 100644
--- a/src/server/testsuite/lyskomd.0/text-cov.exp
+++ b/src/server/testsuite/lyskomd.0/text-cov.exp
@@ -199,6 +199,11 @@ simple_expect "=1207"
 send "1208 31 9 13\n"
 simple_expect "%1208 30 13"
 
+# Add a recipient with a bogus type
+
+send "1209 30 9 13 6\n"
+simple_expect "%1209 26 6"
+
 
 
 # Call create-text when we have no access to one of the recipients
@@ -527,9 +532,7 @@ simple_expect "%2603 47 0"
 # Attempt to crete a text with a comm-in item
 
 send "2604 86 [holl "T33 (oops)"] 2 { 0 10 3 32 } 0 { }\n"
-simple_expect "%% LysKOM protocol error."
-setup_xfail "*"
-fail "got protocol error instead of illegal-misc"
+simple_expect "%2604 25 1"
 
 
 # Attempt to recpt, cc, bcc a conference that does not exist
diff --git a/src/server/text.c b/src/server/text.c
index b18c01f3234c728d20a7adfbf20f75095278cf13..b0d93a80bef4cf3e92d82843b78ed207c77c3589 100644
--- a/src/server/text.c
+++ b/src/server/text.c
@@ -1,5 +1,5 @@
 /*
- * $Id: text.c,v 0.64 1999/05/16 21:47:36 ceder Exp $
+ * $Id: text.c,v 0.65 1999/05/18 13:07:02 byers Exp $
  * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  Lysator Academic Computer Association.
  *
  * This file is part of the LysKOM server.
@@ -34,7 +34,7 @@
 #endif
 
 static const char *
-rcsid = "$Id: text.c,v 0.64 1999/05/16 21:47:36 ceder Exp $";
+rcsid = "$Id: text.c,v 0.65 1999/05/18 13:07:02 byers Exp $";
 #include "rcs.h"
 USE(rcsid);
 
@@ -233,6 +233,7 @@ find_recipient(Conf_no	 conf_no,
 	    break;
 	    
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    restart_kom("find_recipient(): illegal misc_item\n");
 #endif
@@ -515,6 +516,7 @@ is_member_in_recpt(Person    *person,
 	    break;
 
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    kom_log("%s: is_member_in_recpt(): bad misc_item.\n", __FILE__);
 	    break;
@@ -593,6 +595,7 @@ do_delete_misc (u_short	  * no_of_misc,
 	    break;
 	    
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    restart_kom("do_delete_misc() - illegal misc");
 #endif
@@ -730,6 +733,7 @@ do_sub_recpt (Text_no	     text_no,
 	    break;
 	    
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    kom_log("%s: do_sub_recpt(): bad misc_item.\n", __FILE__);
 	    break;
@@ -903,10 +907,11 @@ sender(Text_stat * t_stat,
 	    break;		/* These may come before a sent_by. */
 
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
-	    kom_log("ERROR: sender(): Illegal misc_item found.\n");
-	    return 0;
+	    restart_kom("ERROR: sender(): Illegal misc_item found.\n");
 #endif
+
 	}
     }
     return 0;			/* No sender. */
@@ -966,6 +971,7 @@ is_sender(Text_stat * text_s,
 	    break;
 
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    restart_kom("is_sender(): Illegal misc_item found.\n");
 #endif
@@ -1016,6 +1022,7 @@ is_comm_sender(Text_stat * text_s,
 	    break;
 
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    restart_kom("is_comm_sender(): Illegal misc_item found.\n");
 #endif
@@ -1134,6 +1141,7 @@ skip_recp (Misc_info ** misc,
 	    ready = TRUE;
 	    break;
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    restart_kom("skip_recp() - illegal misc\n");
 #endif
@@ -1178,6 +1186,7 @@ recp_sent_by(Misc_info *misc, Misc_info *end,
             return FALSE;
 
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    restart_kom("recp_sent_by() - illegal misc\n");
 #endif
@@ -1314,6 +1323,7 @@ filter_secret_info(Text_stat *result,
 	    break;
 
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    restart_kom("filter_secret_info() - illegal misc_item!\n");    
 #endif
@@ -1657,6 +1667,7 @@ do_delete_text(Text_no    text_no,
 	case sent_at:
 	    restart_kom("do_delete_text(): Illegal misc-item syntax.\n");
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    restart_kom("do_delete_text(): Illegal misc-item.\n");
 #endif
@@ -1850,6 +1861,7 @@ check_double_subm (Misc_info	* misc,
 	    break;
 	    
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    kom_log("%s: check_double_subm(): bad misc_item.\n", __FILE__);
 	    break;
@@ -1894,6 +1906,7 @@ check_double_comm (Misc_info *misc,
 	    break;
 	    
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 	    kom_log("%s: check_double_subm(): bad misc_item.\n", __FILE__);
 	    break;
@@ -2098,6 +2111,11 @@ create_text_check_misc (u_short     * no_of_misc,
 	case loc_no:		/* Ignore loc_no */
 	    break;
 
+        case unknown_info:      /* Unrecognized info type */
+            err_stat = misc[i].datum.unknown_type;
+            kom_errno = KOM_ILLEGAL_INFO_TYPE;
+            return FAILURE;
+            
 	case comm_in:
 	case footn_in:
 	case rec_time:
@@ -2107,6 +2125,7 @@ create_text_check_misc (u_short     * no_of_misc,
 #ifndef COMPILE_CHECKS
  	default:
 #endif
+            err_stat = i;
 	    kom_errno = KOM_ILL_MISC;
 	    return FAILURE;
 	}
@@ -2236,6 +2255,7 @@ create_text_add_miscs(Text_no     new_text,
 	case sent_at:
 	    /* Fall through */
 #ifndef COMPILE_CHECKS
+        case unknown_info:
 	default:
 #endif
 	    restart_kom("create_text_add_misc() - illegal Info_type");
@@ -2414,13 +2434,13 @@ ok_to_create_next_text(void)
 
 extern Text_no
 create_text_old(const String message,
-                u_short no_of_misc,
-                Misc_info * misc)
+                Misc_info_list * misc_l)
 {
     Text_stat *t_stat;
     Text_no    text;
 
-    text = do_create_text(message, no_of_misc, misc, NULL, FALSE, &t_stat);
+    text = do_create_text(message, misc_l->no_of_misc,
+                          misc_l->misc, NULL, FALSE, &t_stat);
 
     if (text != 0)
     {
@@ -2435,14 +2455,14 @@ create_text_old(const String message,
 
 extern Text_no
 create_text(const String    message,
-            u_short         no_of_misc,
-            Misc_info     * misc,
+            Misc_info_list     * misc_l,
             Aux_item_list * aux)
 {
     Text_stat *t_stat;
     Text_no    text;
 
-    text = do_create_text(message, no_of_misc, misc, aux, FALSE, &t_stat);
+    text = do_create_text(message, misc_l->no_of_misc,
+                          misc_l->misc, aux, FALSE, &t_stat);
 
     if (text != 0)
     {
@@ -2465,14 +2485,14 @@ create_text(const String    message,
 
 extern Text_no
 create_anonymous_text(const String    message,
-                      u_short         no_of_misc,
-                      Misc_info     * misc,
+                      Misc_info_list* misc_l,
                       Aux_item_list * aux)
 {
     Text_no text;
     Text_stat * t_stat;
 
-    text = do_create_text(message, no_of_misc, misc, aux, TRUE, &t_stat);
+    text = do_create_text(message, misc_l->no_of_misc,
+                          misc_l->misc, aux, TRUE, &t_stat);
 
     if (text != 0)
     {
@@ -2485,13 +2505,13 @@ create_anonymous_text(const String    message,
 
 extern Text_no
 create_anonymous_text_old(const String  message,
-                          u_short       no_of_misc,
-                          Misc_info   * misc )
+                          Misc_info_list   * misc_l )
 {
     Text_no text;
     Text_stat * t_stat;
 
-    text = do_create_text(message, no_of_misc, misc, NULL, TRUE, &t_stat);
+    text = do_create_text(message, misc_l->no_of_misc,
+                          misc_l->misc, NULL, TRUE, &t_stat);
 
     if (text != 0)
     {
@@ -2520,6 +2540,13 @@ do_create_text(const String  message,
 
     CHK_LOGIN(0);
 
+    if (no_of_misc > param.max_crea_misc)
+    {
+        err_stat = param.max_crea_misc;
+        kom_errno = KOM_LONG_ARRAY;
+        return 0;
+    }
+
     /* Check the length of the text. */
 
     if ( s_strlen (message) > param.text_len )
@@ -2930,6 +2957,7 @@ add_recipient(	Text_no		text_no,
     case rec_time:
     case sent_by:
     case sent_at:
+    case unknown_info:
 	/* Fall through */
 #ifndef COMPILE_CHECKS
     default:
@@ -3352,6 +3380,21 @@ modify_text_info(Text_no        text,
     Text_stat       *text_s;
 
     CHK_LOGIN(FAILURE);
+
+    if (items_to_delete->length > param.max_delete_aux)
+    {
+        kom_errno = KOM_LONG_ARRAY;
+        err_stat = param.max_delete_aux;
+        return FAILURE;
+    }
+
+    if (aux->length > param.max_add_aux)
+    {
+        kom_errno = KOM_LONG_ARRAY;
+        err_stat = param.max_add_aux;
+        return FAILURE;
+    }
+
     GET_T_STAT(text_s, text, FAILURE);
 
     /* Check if we may delete and add the items */