Here is the redesign document that has been talked about on this
list. As you can see it is over 1 year since it was last revised. By
next week I hope to have a current plans for 1.94 written for the
list.
=== start doc
This is a second pass at the design doc. The changes from the first
pass are highlighted with |'s in the left margin. If you haven't read
it before please read and comment on it now. The comment period will
be until Monday 3/21/94. If I don't hear from you, I will feel
justified in scrapping any requests for additions to the spec after
the comment period. I have to start coding some time.
As before:
***'s mark items that (I think) can be handled independently.
***
There should exist a mechanism to extend the list of acceptable
command line parameters to getopts. (This could be used to add
a -l command line option that specified a listname so that
majordomo can be used at the -request address for a mailing
list.)
|***
|
| The command line collector in majordomo will be extended to allow
| commands lines to be continued with a '\' as the last
| non-whitespace character on the line.
|
| The command line collector will be extended to allow whitespace to
| be escaped using "\ ". This would permit embedded spaces to be
| used in majordomo commands. E.G.
|
| get bblisa this\ is\ a\ file
|*** (Done for the most part)
| A configuration file system will be added to majordomo. The
| system should be extensible and usable by any part of
| majordomo including:
|
| majordomo proper
| resend
| digest
| archive programs
|
| Any configuration file that is required should be able to be
| handled using the config file mechanism.
***
Before and after the dispatch portion of the code (where the
do_<command> functions are called), the user will be able to
provide functions to be run. These functions can be used to
provide access control etc for majordomo.
There should be a function that will register these pre and post
functions.
The interface to the pre/post dispatch functions should be well
defined. Access to global variables in majordomo (e.g.
$reply_to) should be through some agreed upon mechanism (e.g.
copying the variable reply_to to $export{"reply_to"}) for use
by the pre/post routines. This allows the internal variable
names etc of majordomo to change without trashing the pre/post
dispatch environments.
***
Replace the main dispatching case (like) statement that calls
do_<function> with a loop that allows 1 or more functions to
be called before the main function. The loop will also allow 1
or more functions to be called after the main function is
called. This main loop will be table driven so that additional
command can be added.
Functions will be provided to
1) add a pre command E.G.:
add_pre(function_name (e.g. pre_add), majordomo_command);
2) add a (new) main command E.G.
add_do(function_name (e.g. do_subscribe),
majordomo_command (e.g. add),
type (admin|user), approvable (yes/no)
description);
3) add a post command E.G.
add_post(function_name (e.g. post_add), majordomo_command);
The command to register a new main command will require a
description of the command. This description will be provided
to the user as part of the help command. This new command will
be flagged as a non-standard command in the help
documentation.
There will have to be a distinction between "user" and
"administrative" commands, so that admin commands aren't put
into the user help message.
Also there will be an entry that states that the command can
be the object of an approve command, and what password should
be used.
The interface to the pre/post commands should be well defined. Access
to global variables in majordomo (e.g. $reply_to) should be
through some agreed upon mechanism (e.g. copying the variable
reply_to to $export{"reply_to"}) for use by the pre/post routines.
This allows the internal variable names etc of majordomo to change
without trashing the pre/post command environments. This idea
should be extended to all interactions that the pre/post commands
have with the enclosing majordomo environment. One variable
that should be supplied is the name of the current majordomo
command being processed. This allows a generic pre_function to
be used to do something like add a <listname> etc.
Two calling paradigms have been suggested:
$error = &pre_command(*parts)
and
($error, @parts) = &pre_command(@parts)
where parts is the array that is passed into do_command.
The first is more efficient and the return type is a single
value, but means that the programmer will have to understand
glob types, and how to manipulate them. The second mechanism
is simpler for perl novices, but the return value from the
routine will have to be a composite of error code and the
massaged parts array.
| The second method described above will be used.
The set of error codes must have the following:
| 1) OK: All is ok. The cases OK_NO_ACTION and OK_ACTION
| will be differentiated.
2) OK_STOP: All is ok, but don't call more pre_commands, or
do_command (i.e. the pre_command handled
the entire request).
| 3) ERROR_STOP: Fatal error, don't call more pre_commands, or
| do_command (pre command reported error).
| Process the next command in the message.
4) ERROR: Error, but continue processing with other pre and
do_commands (the later commands report the
error)
5) ERROR_ABORT: Abort processing of any more commands
(i.e. exit majordomo through normal exit
| code). No additional commands are processed,
| but any reply procedures are executed.
| One item that will be needed is a way for the pre routine to
| "approve" an item to be acted on by a later majordomo command.
| (e.g. this would allow people from a certain site to subscribe
| to a closed list as though it was open).
|***
| The loading code can be developed separately from the code that
| handles the pre-routine interface.
There should be some way to specify a required order for
application of commands. By way of a contrived example:
You have 2 modules:
1) one of which handles a listserv
"unsubscribe *" (unsubscribe from all
lists on the server) request.
2) The other allows putting majordomo at the
-request address, and adds the
listname to any commands that need it. If
it is the bblisa-request list, it checks
parts[0] to see if it is bblisa, if not
it puts bblisa in parts[0]. If the request
is approve, the parts[2] element is used in place
of parts[0].
I get a "unsubscribe *" request to the bblisa-request
mailing list.
application order result
for pre_
1 then 2 Everthing works fine. Module 1
recognized the * command, and
unsubscribes from the list,
and returns, OK_STOP. 2 never
gets called.
2 then 1 Boom. 2 checks to see if * is
the same as bblisa, (it
isn't) so it adds bblisa.
Module 1 sees the command
"unsubscribe bblisa *"
doesn't recognize it as
"unsubscribe *", and returns.
The main loop calls
do_unsubscribe.
do_unsubscribe, finding no
email address '*' reports an
error.
Granted, the user screwed up by posting an 'unsubscribe *' to
a list-request address, but hey I said the example was
contrived.
Maybe this problem could be handled by structuring the loading
algorithm. A simple hack like naming the files:
mj_at_-request-3.pl
mh_search_archives-99.pl
restrict_access.pl
rationalize_reply_to.pl
listserv_unsubscribe-2.pl
global_list_database.pl
Loading the files according to the numbers following the
final - produces the order:
listserv_unsubscribe-2.pl
mj_at_-request-3.pl
mh_search_archives-99.pl
restrict_access/rationalize/global
(what ever order you want, since an
order was not specified)
and the pre-commands would be loaded/applied in the same
order. This doesn't require any real perl hacking ability on
the part of the majordomo maintainer. Hey, if it works for
SVR4 it can't be all bad right 8-) 8-) 8-)?
| The above naming method will be used, but the numbers will be
| placed before the name of the file, separated by a -. E.G.
| 99-mh_search_archives.pl. The names should be less than 14
| characters in length.
|
| Before loading a module the name of the module file will be
| stored in a variable ($main'addin_fn) for use by the addin.
|*** The approve command can be developed independently.
The approve command will have to be rewritten to be table driven
just like the main dispatch loop so that new commands can use
the approve functionality.
|***
|
| Each major program will set a marker variable during startup
|before loading any addins.
|
| $main'program_name = 'mj_majordomo';
|
|This permits a single directory for addins so that the addins can be
|used by resend and digest in the future. Each addin will be in two parts:
|
| <define all keywords for the config file>
|
| if ( $main'program_name = mj_majordomo) ) { # or mj_resend, mj_digest
| return 1;
| }
|
| <various add command for majordomo and the definitions of their
| respective subroutines>
|
|This allows majordomo to load all of the addin files so that it can
|properly deal with errors in the config files, without having majordomo
|read and define all of the (potentially meaningless) subroutines that
|are needed for another command in the package.
|
|The prefix "mj_" is reserved for use by programs that are distributed
|and maintained by the maintainer(s) of majordomo. The following values
|are also reserved:
|
| mj_majordomo: The majordomo command
| mj_resend: The resend command
| mj_digest: The digest command written by Brent, originally
| distributed seperately.
| mj_archive: The archive command written by Brent, originally
| distributed separately.
***
The REPLY filehandle will be replaced with a command
&add_reply(text). There will also be a command called
&send_reply that takes the first line of the reply, and strips
that line and uses its contents as the address to send the
| reply to. For any given command (i.e. once through the
| pre-command, command, post-command loop) the &add_reply text
| will add text to a reply array available to the command
| functions. After the post_command(s) have been executed, the
| reply array will be copied onto the end of the reply buffer
| that will ultimately be used by &send_reply. This
| segmentation allows post commands to easily determine how
| much text is being sent out, and allows the post commands to
| modify the text for the reply without having to scan and parse
| the entire reply buffer.
There will have to be commands to iterate over the reply
buffer since the reply buffer may be in an @array, or may be
on external disk for those machines that have limited memory.
| There should also be a hook that gets run before the reply is
| actually sent. This could be used to split messages that will
| have problems being delivered due to size into smaller
| messages.
***
Some mechanism should be added to allow a help message that
includes the administrative commands. Maybe
approve password help listname
could be overloaded.
| Also the help command should take arguments. If an argument is given
| to a help command the function &help_<argument> will be
| called. The majordomo command "help" will be equivalent to the
| majordomo command "help default", and will call &help_default.
| This allows more extensive help pages for more complex
| commands such as archive searching commands etc to be
| requested without overwhelming a user with unnecessary
| information. I see no reason a "help admin" command couldn't
| be added to describe the admin commands.
End of spec. The rest of my ramblings about how this will change the
world as we know it, and probably end hunger haven't changed since the
first go around.
=== end doc
-- John
John Rouillard
Senior Systems Administrator IDD Information Services
rouilj@dstar.iddis.com Waltham, MA (617) 890-7227 x337
(617) 487-3937 (Direct)
Senior Systems Consultant (SERL Project) University of Massachusetts at Boston
rouilj@cs.umb.edu (preferred) Boston, MA, (617) 287-6480
===============================================================================
My employers don't acknowledge my existence much less my opinions.
|
|