Great Circle Associates Majordomo-Workers
(March 1994)
 

Indexed By Date: [Previous] [Next] Indexed By Thread: [Previous] [Next]

Subject: Majordomo 2.0 requirement/design spec, comments
From: "John P. Rouillard" <rouilj @ terminus . cs . umb . edu>
Date: Fri, 04 Mar 1994 16:01:01 -0500
To: majordomo-workers @ greatcircle . com


R. Gary Cutbill responded with some comments on the original draft of
the majordomo spec. I think his points are valid, but I think that my
comments are more valid 8-). If you are planning on commenting on the
majordomo spec, you may want to look at this message as well to see if
you agree with Gary or not. I have seen some of thes sugestions
(e.g. decoupling help messages from majordomo into seperate files that
majordomo serves up) made by other people. If you agree with Gary and
think my reasoning is faulty (which it probably is), then please tell
me. That's what the majordom-workers list is for anyway. Lets see if
we can get a flurry of activity together for the next week or two, and
get 1.90 our the door and a running start on 2.0.

------- Forwarded Message

To: "R. Gary Cutbill" <rgary@x.org>
Subject: Re: A Christmas Present (Majordomo 2.0 requirement/design spec) 
Date: Sat, 12 Feb 1994 00:35:21 -0500
From: "John P. Rouillard" <rouilj@terminus.cs.umb.edu>


In message <9402111926.AB06030@expo.x.org>, "R. Gary Cutbill" writes:
> ask for this.  Some of what I say here I truly believe, and some I will
> say for the sake of playing Devil's advocate.  With that veil in place to
> defend any philosophical blunders I may make :-), here goes:

No problem. I did ask for your opinions.

> >   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.)
> A valuable idea particularly since so much is being done to provide
> hooks to the user for customization.  I would suggest that this facility
> should be kept fairly simple and only allow users to set the value of
> variables during parsing. (as opposed to offering function calls, etc.)
> I would implement this with a table driven scheme.  I imagine that
> the table would have the folling fields: switchname, min # of args,  
> max # of args, variable to store arguments in.  If a switch took zero
> arguments, then it's variable would be set to a true value.  If we make
> it a requirement that switch names always begin with a '-', the command
> line parse would be able to do some face validity checking of arguments.

Actually I was going to make it even simpler than that. A &newopt("t:)
function would just add "t:" to the list of valid arguments that are
given to getopt. It would be up to the code to validate the argument
when it runs. By default a specification of "t:" will set the variable
$main'opt_t to the value that is picked up from the command line. It
would return an error if the t argument didn't have an
argument. Getopts is documented in the Camel perl book or the online
perl library. It works pretty much like any ther getopt routine. I was
actually thinking about using one of the better getopt replacements,
(maybe ngetopts) but the basic functionality is the same.

> ( I suppose one could convince me that a 'validity function' in the table
> would be good idea too.  The purpose of the function would be to check to
> see that arguments gathered for a switch were OK, or to return an error.)

Since the command line arguments are set by the majordomo installer
and not the list manager, I wasn't planning on putting in validating
functions etc, because I don't consider the command line arguments a
possible source of security breaches. On the other hand the arguments
in the config file could be a security problem if the are evalled
(e.g. suppose `cat /etc/passwd | mail rouilj@cs.umb.edu` were some how
evalled within the context of majordomo (regexps use eval as do a
couple of other functions)). That is why the validate functions
exist. If I can convince myself that the validate functions eliminate "bad
things", then I don't have to do as much security checking inside the
code that implements the functions themselves.

Do I sound on the mark here? Is there a possible security problem with
command line arguments set up by the majordomo installer?

> >   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.

This section is before the dispatch loop, so I am not quite sure how
your comments below apply to this code.

> >   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.:  
			[descriptions elided]
> > 		2) add a (new) main command E.G.
> > 		3) add a post command E.G.
> > 
> >      	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 set of error codes must have the following:
> > 
> > 		1) OK: All is ok (maybe (OK_NO_ACTION and OK_ACTION
> > 		2) OK_STOP: All is ok, but don't call more pre_commands, or
> > 		2) ERROR_STOP: Fatal error, don't call more pre_commands, or 
> > 		3) ERROR: Error, but continue processing with other pre and
> > 		4) ERROR_ABORT: Abort processing of any more commands
 		[ omitted text in descriptions]
> > 
> > 	There should be some way to specify a required order for
> > 	application of commands. By way of a contrived example:
	 [omited text]
> The above sections seem like too much work to me, and seems like it offers
> redundant functionality. I would rather see this done by just making the
> dispatch function table driven.  If a user wanted to implement some kind of
> pre-command or post-command for an existing mjd command, they could just
> write a wrapper function that performs the necessary steps (including
> calling the existing function), and modify the dispatch table.

The dispatch is table driven internally, its just that the addin
writer doesn't see it. If you or I were the only one writing addins,
then you are correct the above is overkill. The extra generality I
think is needed because I may have 30 or so addins all written by
different people. I want to be able to plunk them into an include
directory, have majordomo read them, and have all of them work
together just fine. (Well, this is my dream at any rate.) If I
implemented what you suggested, each of the 30 modules would have to
implement changes in the dispatch function, and would have to make
sure that every one of the previous modifications to the dispatch
function was called.  Off the top of my head, I suppose it might be
possible to recursively handle the setup, creating a call stack rather
than a loop of calls e.g.

	unsub_function	      	replaces and calls

	do_unsubscribe		nothing
	add_default_group	do_unsubscribe
	do_unsubscribe*		add_default_group

add_default_group would replace do_unsubscribe as the unsub_function,
and would call do_unsubscribe (or some other function if it
likes). do_unsubscribe* would replace add_default_group as the
unsub_function, and would call add_default_group.  Where the call
sequence of do_unsubscribe* looks like:

sub do_unsubscribe_star ( 
	@parts = @_;
	< do some pre processing code to @>
	<call the function we replaced in the unsub_function,
	 I have no clue how to get this to work. Maybe a registration
	 function to add do_unsubscribe_star would return the old function
	 that could be kept in a package local variable, or the
	 majordomo eval loop could specify the cascade function
	 to be called here.> 

	&$export{"CASCADE_do_unsubscribe_star"}(@parts)
	<do some post-processing code>
)

I like this better than the explicit pre/post model except for one
problem.  Every function would have to be able to interpret and handle
all possible error codes from the cascade function. If we add more
error codes to short circuit evaluation (say one to call do_command
immediately by passing all pre-command code) then all of the addin
functions would have to be modified to support this new
code. Sigh. Now that I think of it, an error in one of these functions
could trash the entire call chain, where an error in one of the loop
functions just trashes that function. Do you have some other mechanism
in mind for pulling this off?

In any case, the way I see the pre-functions is as a formal mechanism
for adding functions to modify the user provided command to the form
that majordomo wants. If you want to do something entirely different,
you can override the base function by returning the appropriate value
from your pre function, but I think total overrides will be
unlikely. I mean your -l [the -l mods will be in 1.90. This allows the
specification of a listname for majordomo so it can sit at the
-request address] mods could be done with:

  &newgetopt("-l:");
  &precommand(get, provide_default_group)
  &precommand(subscribe, provide_default_group)
   ...

I have abbreviated the args to precommand for clarity. Where
provide_default_group would just put the default group into the @parts
array, and hand it off to do_get or whatever. Effectively I have made
the dispatch loop table driven with an arbitrary amount of code that
is executed before parsing the user request, and an arbitrary amount
of code that is executed after the parsing is done. I think that you
would discover that you would have to end up implementing essentially
the same sort of mechanism that I am proposing to handle the general
case.

> New commands would be implemented in the same manner.

Yes, there will be a function to add new commands to the command table.

> The key reason I prefer just using the table driven method is that
> it strikes me as easier to use (as well as easier to implement).
> All of the pre- and post- registration stuff seems as semantically
> difficult as writing perl, and it adds a layer of needed
> knowledge. Since the user is going to have to know perl either way,
> why not just the basic facilities of the language to deal with
> flow-control types and error handling issues.

Hopefully the user will not need to know perl if somebody has already
written an addin that does the function that is needed. All they have
to do is plunk the appropriate addin into the include directory, and
viola they have the added functionality, help for the functionality
etc.

> I think that the list of error codes should still be usable to report back
> to the dispatcher the results of a command.

Do you think the cases, of "returned ok, no change done", and
"returned ok change done" have to be differentiated?
 
> If the dispatch code was changed to include a dispatch_one_line function,
> then the approve command could use the same functionality as the main 
> dispatch loop and it ought to be pretty painless.  (it also allows for
> a single table to drive both pieces.

That is exactly what I was thinking. I would duplicate the pre,
command and post loop inside the approve command for those commands
that are supposed to be "approvable". One problem though what happens
with the following request sent to bblisa-request with the -l
<listname> patch?

	approve fooble subscribe rouilj@cs.umb.edu

There is no listname there yet to approve against. I would hope that
the add_default_group code would modify the above to:

	approve fooble subscribe bblisa rouilj@cs.umb.edu

so that approve could check fooble against bblisa, the chop the
approve fooble off the command and reiterate the subscribe arguments
through the pre-subscribe, do_subscribe, post_subscribe loop.

> I would change the help command so that it reads two files, one which is 
> the default help text, and one which is user supplied that describes any
> custom functionality.

Hmm, I was planning on having the default help text be built into
majordomo. The user supplied help text would be incorporated into the
addin module in the help function.

> >     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 rely
> > 	to. 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.
> >
> I'm not sure why this is useful. Is it because some machines have trouble
> executing a reply because of its size?

While some replies are too large to fit through gateways (especially
if you are retrieving lots of info files), it was meant more to handle
the problem of hiding the existence of the majordomo command, or
hiding certain command responses. It turns out (I did a limited
version of the change on majordomo) that it is a win on machines with
limited core memory. The perl process will be almost totally done
before sendmail starts up. Thus you only need enough core to run perl
or sendmail successfully rather than perl and sendmail. The way the
code is currently set up. it looks like sendmail and perl get into a
swapping war on machines with limited core. The space needed for data
is the same regardless of whether perl or sendmail is buffering it,
but with a deferred reply, you don't have any sendmail executable code
(and its requisite swapping) occurring while the perl code is running.

> > Some mechanism should be added to allow a help message that
> > includes the administrative commands. Maybe approve password help
> > listname could be overloaded.

> Actually, it seems like it would be nice if help took keywords to
> retrieve specific help about a whole variety of commands, by sending
> a file to the user.  I would have a 'help' directory which contains
> a set of files that have the same names as commands. "help subscribe"
> would then send the file 'help/subscribe' to a user.  In
> this way, help really just becomes a specialized version of
> 'do_get'.

True, it would act line a "get help command_file", but I think having
a separate help tree that has to be updated at the same time as the
code to implement a command may be a lose. I can easily see the old
help text being left in the tree by mistake.

> Of course there would need to be some reasonable default
> for user that only said 'help'. (perhaps it should provide a brief
> description, and then perform the equivalent of a 'do_index' on the
> help directory.

That is what the description in the command adding functions did. It
provided a one (or two) liner that could be put out in an abbreviated
default help message. This help message would also be marked to show
the commands that have additional help available.

> If you're worried about preventing users from seeing help files for
> administrative commands, those could be protected by a special file
> suffix, or by putting them in a special (hidden?)  directory.

I am not really worried about them seeing the help files, as much as I
am worried about cluttering the default help screen with
administrative commands.


> I'm interested in your reactions. I' ve tried to offer ideas that
> simplify the implementation, while still allowing for the same
> functionality.

You seem to have followed the same line of reasoning that Alan and I
did (well they do say that great minds think alike). We came to the
conclusion that we needed a more formal hook mechanism to support
multiple addins from multiple people in a manner where they wouldn't
keep colliding every time they turned around. The problem is that I
have come up with a somewhat complicated mechanism, but I think moving
the complications to the supplied majordomo code rather than having it
solved by add-hoc means for all of the different addins is a win
overall.

I like the simplicity of the single table dispatch function and doing
away with the explicit pre/post processing, but I can't see how the
mechanism would stand up to some changes (primarily return codes)
without modification of the addin modules. Also, it kind of makes me
queasy to think of addin code trying to interpret and act on the the
return codes without complete information. Do you have another
implementation in mind that will solve this problem? I think that I
have covered all the bases implementing the functionality as a
recursive function and a loop iteration, but I may have missed a
paradigm 8-).

> I'm willing to work on this stuff as I have time.

Great.

				-- John
John Rouillard

Special Projects Volunteer	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.

------- End of Forwarded Message


Indexed By Date Previous: Majordomo 2.0 final spec review.
From: "John P. Rouillard" <rouilj@terminus.cs.umb.edu>
Next: Majordomo 1.90 beta 1 released.
From: "John P. Rouillard" <rouilj@terminus.cs.umb.edu>
Indexed By Thread Previous: Majordomo 2.0 final spec review.
From: "John P. Rouillard" <rouilj@terminus.cs.umb.edu>
Next: Majordomo 1.90 beta 1 released.
From: "John P. Rouillard" <rouilj@terminus.cs.umb.edu>

Google
 
Search Internet Search www.greatcircle.com