[augeas-devel] 2009 Lens Fiesta! (inetd.conf edition)

Matthew Palmer matt at anchor.net.au
Thu Aug 13 01:33:42 UTC 2009


On Tue, Aug 04, 2009 at 11:00:40PM +0000, David Lutterkort wrote:
> On Sat, 2009-08-01 at 12:44 +1000, Matthew Palmer wrote:
> > I surprised even myself at the speed which this lens was produced -- it
> > worked fine pretty much straight off the bat, too.
> 
> Who ever said writing lenses was hard ? ;)

Probably me, before I got my head around the syntax.  It really is
mind-meltingly weird.  I can't see how you'd do something this powerful any
other way, but I can't fault people who look at lenses and say "you know
what, I think I've got to go feed my cat".

> > Parses inetd.conf for awesome happiness.
> 
> Same question as about the syslinux lens: are you willing to relicense
> under the LGPLv2+ to avoid headaches for some distributors who get
> scared when they see GPLv2 files in a supposedly LGPLv2+ library.

Yep, that's OK, despite my derision at people incapable of comprehending
simple licences.  If Microsoft can handle the GPL, I think everyone else
needs to get over themselves.  <grin>

Relicenced version attached.

- Matt
-------------- next part --------------
(* inetd.conf lens definition for Augeas
   Auther: Matt Palmer <mpalmer at hezmatt.org>

   Copyright (C) 2009 Matt Palmer, All Rights Reserved

   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License version 2.1 as
   published by the Free Software Foundation.
               
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
   Public License for more details.
                       
   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http://www.gnu.org/licenses/>.

This lens parses /etc/inetd.conf.  The current format is based on the
syntax documented in the inetd manpage shipped with Debian's openbsd-inetd
package version 0.20080125-2.  Apologies if your inetd.conf doesn't follow
the same format.

Each top-level entry will have a key being that of the service name (the
first column in the service definition, which is the name or number of the
port that the service should listen on).  The attributes for the service all
sit under that.  In regular Augeas style, the order of the attributes
matter, and attempts to set things in a different order will fail miserably. 
The defined attribute names (and the order in which they must appear) are as
follows (with mandatory parameters indicated by [*]):

address -- a sequence of IP addresses or hostnames on which this service
	should listen.

socket[*] -- The type of the socket that will be created (either stream or
	dgram, although the lens doesn't constrain the possibilities here)

protocol[*] -- The socket protocol.  I believe that the usual possibilities
	are "tcp", "udp", or "unix", but no restriction is made on what you
	can actually put here.

sndbuf -- Specify a non-default size for the send buffer of the connection.

rcvbuf -- Specify a non-default size for the receive buffer of the connection.

wait[*] -- Whether to wait for new connections ("wait"), or just terminate
	immediately ("nowait").

max -- The maximum number of times that a service can be invoked in one minute.

user[*] -- The user to run the service as.

group -- A group to set the running service to, rather than the primary
	group of the previously specified user.

command[*] -- What program to run.

arguments -- A sequence of arguments to pass to the command.

In addition to this straightforward tree, inetd has the ability to set
"default" listen addresses; this is a little used feature which nonetheless
comes in handy sometimes.  The key for entries of this type is "#address"
(to prevent collision with any real services that might one day be called
"address"), and the subtree should be a sequence of addresses.  "*" can
always be used to return the default behaviour of listening on INADDR_ANY.

*)

module Inetd =
	autoload xfm

	(***************************
	 * PRIMITIVES
	 ***************************)

	(* Store whitespace *)
	let wsp = del /[ \t]+/ " "
	let sep = del /[ \t]+/ "	"
	let owsp(t:string) = del /[ \t]*/ t
	
	(* It's the end of the line as we know it... doo, doo, dooooo *)
	let eol = Util.eol
	
	(* In the beginning, the earth was without form, and void *)
	let empty = Util.empty
	
	let comment = Util.comment
	
	let del_str = Util.del_str
	
	let address = [ seq "addrseq" . store /[a-zA-Z0-9\.-]+/ ]
	let address_list = ( counter "addrseq" . (address . del_str ",")* . address )
	
	let argument = [ seq "argseq" . store /[^ \t\n]+/ ]
	let argument_list = ( counter "argseq" . (argument . wsp)* . argument )

	(***************************
	 * ELEMENTS
	 ***************************)
	
	let service = ( [label "address" . address_list . del_str ":" ]? . key /[^ \t\n\/:#]+/ )
	
	let socket = [ label "socket" . store /[^ \t\n#]+/ ]
	
	let protocol = ( [ label "protocol" . store /[^ \t\n,#]+/ ]
	                 . [ del_str "," . key /sndbuf/ . del_str "=" . store /[^ \t\n,]+/ ]?
	                 . [ del_str "," . key /rcvbuf/ . del_str "=" . store /[^ \t\n,]+/ ]?
	               )
	
	let wait = ( [ label "wait" . store /(wait|nowait)/ ]
	             . [ del_str "." . label "max" . store /[0-9]+/ ]?
	           )
	
	let usergroup = ( [ label "user" . store /[^ \t\n:\.]+/ ]
	                  . [ del /[:\.]/ ":" . label "group" . store /[^ \t\n:\.]+/ ]?
	                )
	
	let command = ( [ label "command" . store /[^ \t\n]+/ ]
	                . (wsp . argument_list)?
	              )

	(***************************
	 * SERVICE LINES
	 ***************************)
	
	let service_line = [ service
	                     . sep
	                     . socket
	                     . sep
	                     . protocol
	                     . sep
	                     . wait
	                     . sep
	                     . usergroup
	                     . sep
	                     . command
	                     . eol
	                   ]

	(***************************
	 * DEFAULT LISTEN ADDRESSES
	 ***************************)
	
	let default_listen_address = [ label "#address"
	                               . address_list
	                               . del_str ":"
	                               . eol
	                             ]
	
	(***********************
	 * LENS / FILTER
	 ***********************)

	let lns = (comment|empty|service_line|default_listen_address)*
	
	let filter = (incl "/etc/inetd.conf")
	             . Util.stdexcl

	let xfm = transform lns filter
-------------- next part --------------
module Test_inetd =

	(* The standard "parse a bucket of text" test *)
(*	let conf = "# Blah di blah comment

simplesrv	stream	tcp	nowait	fred	/usr/bin/simplesrv
arguserve	dgram	udp	wait	mary	/usr/bin/usenet		foo bar wombat

1234		stream	tcp	nowait	fred	/usr/bin/numbersrv

127.0.0.1:addrsrv	stream	tcp	nowait	fred	/usr/bin/addrsrv
127.0.0.1,10.0.0.1:multiaddrsrv	stream tcp nowait fred /usr/bin/multiaddrsrv
faff.fred.com:
127.0.0.1,faff.fred.com:
*:

sndbufsrv	stream	tcp,sndbuf=12k	nowait	fred	/usr/bin/sndbufsrv
rcvbufsrv	stream	tcp,rcvbuf=24k	nowait	fred	/usr/bin/rcvbufsrv
allbufsrv	stream	tcp,sndbuf=1m,rcvbuf=24k	nowait	fred /usr/bin/allbufsrv

dotgroupsrv	stream	tcp	nowait	fred.wilma	/usr/bin/dotgroupsrv
colongroupsrv	stream	tcp	nowait	fred:wilma	/usr/bin/colongroupsrv

maxsrv		stream	tcp	nowait.20	fred	/usr/bin/maxsrv
"

	test Inetd.lns get conf =
		{ "#comment" = "Blah di blah comment" }
		{}
		{ "simplesrv"
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "command" = "/usr/bin/simplesrv" }
		}
		{ "arguserve"
			{ "socket" = "dgram" }
			{ "protocol" = "udp" }
			{ "wait" = "wait" }
			{ "user" = "mary" }
			{ "command" = "/usr/bin/usenet" }
			{ "arguments"
				{ "1" = "foo" }
				{ "2" = "bar" }
				{ "3" = "wombat" }
			}
		}
		{}
		{ "1234"
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "command" = "/usr/bin/numbersrv" }
		}
		{}
		{ "addrsrv"
			{ "address"
				{ "1" = "127.0.0.1" }
			}
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "command" = "/usr/bin/addrsrv" }
		}
		{ "multiaddrsrv"
			{ "address"
				{ "1" = "127.0.0.1" }
				{ "2" = "10.0.0.1" }
			}
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "command" = "/usr/bin/multiaddrsrv" }
		}
		{ "#address"
			{ "1" = "faff.fred.com" }
		}
		{ "#address"
			{ "1" = "127.0.0.1" }
			{ "2" = "faff.fred.com" }
		}
		{ "#address"
			{ "1" = "*" }
		}
		{}
		{ "sndbufsrv"
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "sndbuf" = "12k" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "command" = "/usr/bin/sndbufsrv" }
		}
		{ "rcvbufsrv"
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "rcvbuf" = "24k" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "command" = "/usr/bin/rcvbufsrv" }
		}
		{ "allbufsrv"
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "sndbuf" = "1m" }
			{ "rcvbuf" = "24k" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "command" = "/usr/bin/allbufsrv" }
		}
		{}
		{ "dotgroupsrv"
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "group" = "wilma" }
			{ "command" = "/usr/bin/dotgroupsrv" }
		}
		{ "colongroupsrv"
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "wait" = "nowait" }
			{ "user" = "fred" }
			{ "group" = "wilma" }
			{ "command" = "/usr/bin/colongroupsrv" }
		}
		{}
		{ "maxsrv"
			{ "socket" = "stream" }
			{ "protocol" = "tcp" }
			{ "wait" = "nowait" }
			{ "max" = "20" }
			{ "user" = "fred" }
			{ "command" = "/usr/bin/maxsrv" }
		}


*)
(**************************************************************************)

	(* Test new file creation *)
	
	test Inetd.lns put "" after
		set "/faffsrv/socket" "stream";
		set "/faffsrv/protocol" "tcp";
		set "/faffsrv/wait" "nowait";
		set "/faffsrv/user" "george";
		set "/faffsrv/command" "/sbin/faffsrv"
	= "faffsrv	stream	tcp	nowait	george	/sbin/faffsrv
"


More information about the augeas-devel mailing list