[-]
[+]
|
Changed |
tentakel.spec
|
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/ChangeLog
^
|
@@ -1,1659 +1,1349 @@
-* Sat Jul 28 23:10:47 2007 +0000 stark
+2005-07-07 13:35 stark
- TODO: update some TODOs
+ * TODO: purge some TODOs that are implemented or will never be
+ implemented.
-* Sat Jul 28 22:52:49 2007 +0000 stark
+2005-07-07 13:33 stark
- tentakel.1: update copyright notice
+ * TODO: more
-* Sat Jul 28 22:52:47 2007 +0000 stark
+2005-07-07 13:32 stark
- get rid of RCS/SVN Ids
+ * ssh_running.py, tentakel.conf.example: include example for a
+ dynamic host group
-* Sat Jul 28 22:48:16 2007 +0000 stark
+2005-04-22 07:21 stark
- several changes
- - add execwrapper
- - remove svn2cl.xsl
- - better Makefile (and add execwrapper)
+ * tentakel.1, tentakel.1.html: newer date for the manual page
+2005-04-20 08:41 stark
+ * py/lekatnet/remote.py: Correct docstring
-* Fri Jul 27 21:51:37 2007 +0000 stark
+2005-04-20 08:28 stark
- Squashed commit of the following:
- commit 121f329a74c70326e9a84dd6deaed53df800dba2
- Author: Sebastian Stark <seb@biskalar.de>
- Date: Fri Jul 27 23:50:16 2007 +0200
+ * ChangeLog, tentakel.1, tentakel.1.html: Document host exclusion
- Add execwrapper.c
+2005-04-18 20:49 stark
- This program is a wrapper to help killing runaway ssh sessions.
- There are several cases where a program like ssh can hang forever
- so we need some portable and reliable way to kill it after
- a certain amount of time.
+ * tentakel.1, tentakel.1.html: document that dynamic host inclusion
+ scripts must return with exitcode 0
- Much thanks go to Andre Noll who wrote it.
+2005-04-18 20:31 stark
+ * py/lekatnet/config.py, tentakel.1, tentakel.1.html: allow absolute
+ pathnames in dynamic host inclusions
+2005-04-18 20:21 stark
-* Fri Jul 27 16:40:00 2007 +0000 stark
+ * py/lekatnet/config.py, py/lekatnet/plugins/__init__.py,
+ py/tentakel, tentakel.1, tentakel.1.html: Implement dynamic host
+ inclusion: A config group can contain !somefile statements where
+ somefile is the name of a script which outputs the actual
+ hostlist. Had to rename __user_dir and __user_plugin_dir to
+ _user_dir and _user_plugin_dir respectively.
- svn2cl.xsl not needed anymore
+2005-04-10 22:54 stark
-* Fri Jul 27 16:39:59 2007 +0000 stark
+ * py/setup.py: typo
- Makefile: change the way the ChangeLog file is being generated
- Use git-log to generate ChangeLog file. Depends on the par
- utility for nice formatting.
+2005-04-06 08:44 stark
- Make "changelog" a PHONY target
+ * py/setup.py: change my email address
+2005-04-02 16:18 stark
+ * ChangeLog: update
-* Fri Jul 27 14:42:33 2007 +0000 stark
+2005-04-02 16:17 stark
- TODO: C wrapper for ssh/rsh/etc.
+ * py/lekatnet/remote.py: do not hide KeyError exceptions when
+ instantiating a plugin
-* Fri Jul 27 14:26:38 2007 +0000 stark
+2005-04-02 11:37 stark
- one more TODO item
+ * Makefile, py/setup.py, py/tentakel: version 2.2.1
-* Sun Mar 25 12:50:36 2007 +0000 stark
+2005-04-02 11:31 stark
- fix error handling in case of inexistent group
+ * ChangeLog, Makefile, svn2cl.xsl: svn2cl generated ChangeLog. This
+ is not quite as nice as cvs2cl but it is sufficient to provide the
+ information needed in a ChangeLog.
-* Mon Mar 12 23:39:34 2007 +0000 stark
+2005-03-27 00:14 cran
- - update rsh.py to reflect stderr changes. Untested so far.
+ * py/lekatnet/config.py, py/lekatnet/remote.py: - support host
+ subtraction via '-host' syntax - groups can subtract hosts from
+ themselves or underlying groups - subgroups cannot subtract hosts
+ from groups above define SyntaxError exception, for future use by
+ the parser
-* Mon Mar 12 23:37:35 2007 +0000 stark
+2005-03-21 12:12 cran
- - Split stdout and stderr of the remote command.
- - Introduce the formatting character e to output stderr.
- - Update documentation accordingly
+ * TODO: update
- This is an amazingly small commit, only 11 lines of code needed to be changed!
+2005-03-20 15:54 cran
+ * README, tentakel.1, tentakel.1.html: minor documentation fixes
+2005-03-20 15:19 cran
+ * ChangeLog: update
-* Sun Mar 11 23:42:48 2007 +0000 stark
+2005-03-20 15:16 cran
- import statements go to the top of the file
+ * py/lekatnet/remote.py: In .run(), wait a bit for _stopEvent. Makes
+ thread joining much faster. taken from
+ http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65448
-* Sun Mar 11 23:36:26 2007 +0000 stark
+2005-03-18 08:36 cran
- comments about session timeout
+ * TODO, py/lekatnet/plugins/__init__.py: ignore missing user plugin
+ dir
-* Sun Mar 11 23:25:08 2007 +0000 stark
+2005-03-18 08:22 cran
- Integrate patch by Yves Jaeger. This makes it possible to pipe stuff into tentakel. Stdin will be multiplied and available on all remote hosts.
- It also removes the dependency on the commands module. Thanks, I did not like it anyway.
+ * ChangeLog: generate ChangeLog from cvs, more information.
- For now this commit breaks user plugins because of a little API change. There will be either a document describing how to upgrade or some workaround.
+2005-03-18 08:17 cran
+ * PLUGINS: oops. (%d -> %t)
-* Sun Mar 11 16:11:06 2007 +0000 stark
+2005-03-17 21:58 cran
- update to newer tpg version. Should make tentakel work with python2.5
+ * tentakel.1, tentakel.1.html: mention PLUGINS document in the
+ manual page
-* Sun Mar 11 16:04:50 2007 +0000 stark
+2005-03-17 21:55 cran
- revert ssh module to non-subprocess mode
+ * Makefile, PLUGINS, py/setup.py: Plugin documentation
-* Sun Mar 11 15:47:05 2007 +0000 stark
+2005-03-17 21:55 cran
- better error handling, e. g. for nonexistant group
+ * py/lekatnet/plugins/rsh.py, py/lekatnet/plugins/ssh.py: fix
+ imports
-* Sun Mar 4 21:30:26 2007 +0000 stark
+2005-03-17 20:51 cran
- Python 2.4 required from now on
+ * Makefile: include lekatnet/plugins/__init__.py in release tarball
-* Sun Mar 4 21:28:04 2007 +0000 stark
+2005-03-17 20:45 cran
- trying out the subprocess module
- returncode not yet working for some reason
+ * ChangeLog, py/lekatnet/remote.py: - update ChangeLog - remove unit
+ tests from remote.py. They do not work with plugins and bseides
+ this they're shit.
+2005-03-17 20:39 cran
+ * py/lekatnet/remote.py, py/tentakel: use config.__user_dir
-* Sun Mar 4 21:00:16 2007 +0000 stark
+2005-03-17 20:25 cran
- update
+ * py/lekatnet/config.py, py/lekatnet/plugins/__init__.py,
+ py/lekatnet/plugins/rsh.py, py/lekatnet/plugins/ssh.py,
+ py/lekatnet/remote.py, tentakel.1, tentakel.1.html: monster
+ commit, bring the plugin importer into an acceptable state. - do
+ not use execfile to source plugins, it's ugly. use "from plugins
+ import *" instead - put all importer logic in plugins/__init__.py
+ - mention plugins in the manual page - much better docstring for
+ remote.py, explain concepts
-* Sun Mar 4 20:56:08 2007 +0000 stark
+2005-03-17 01:57 cran
- update copyright notice
- 2007 is going to be a year of a new tentakel release.
+ * py/lekatnet/plugins/__init__.py: forgot to check this in
+2005-03-17 01:56 cran
+ * py/lekatnet/remote.py: make plugin imports a bit nicer - make the
+ plugin registry a private attribute - error when a plugin class
+ does not inherit from RemoteCommand - user plugins get loaded
+ last, so one can override standard methods
+2005-03-17 00:12 cran
-* Sun Jul 10 14:45:27 2005 +0000 stark
+ * py/lekatnet/plugins/rsh.py, py/lekatnet/plugins/ssh.py,
+ py/lekatnet/remote.py, py/setup.py: First shot at plugin loading -
+ move *RemoteCommand classes into plugin dir - make setup.py aware
+ of this directory/package - kind of ugly importer using execfile -
+ finds user plugins in $HOME/.tentakel/plugins/
- update
+2005-03-15 08:11 cran
-* Sun Jul 10 14:32:43 2005 +0000 stark
+ * py/lekatnet/config.py, py/lekatnet/error.py,
+ py/lekatnet/remote.py, py/lekatnet/shell.py, py/tentakel,
+ tentakel.1, tentakel.1.html: update copyright for 2005
- update
+2005-03-14 16:11 cran
-* Sun Jul 10 14:30:02 2005 +0000 stark
-
- better error handling during expansion of synamic hostlists
-
-* Sun Jul 10 13:35:54 2005 +0000 stark
-
- rcs id prop
-
-* Thu Jul 7 13:39:14 2005 +0000 stark
-
- update ChangeLog
-
-* Thu Jul 7 13:35:14 2005 +0000 stark
-
- purge some TODOs that are implemented or will never be implemented.
-
-* Thu Jul 7 13:33:12 2005 +0000 stark
-
- more
-
-* Thu Jul 7 13:32:21 2005 +0000 stark
-
- include example for a dynamic host group
-
-* Fri Apr 22 07:21:16 2005 +0000 stark
-
- newer date for the manual page
-
-* Wed Apr 20 08:41:06 2005 +0000 stark
-
- Correct docstring
-
-* Wed Apr 20 08:28:18 2005 +0000 stark
-
- Document host exclusion
-
-* Mon Apr 18 20:49:21 2005 +0000 stark
-
- document that dynamic host inclusion scripts must return with exitcode 0
-
-* Mon Apr 18 20:31:33 2005 +0000 stark
-
- allow absolute pathnames in dynamic host inclusions
-
-* Mon Apr 18 20:21:28 2005 +0000 stark
-
- Implement dynamic host inclusion: A config group can contain
- !somefile statements where somefile is the name of a script
- which outputs the actual hostlist.
-
- Had to rename __user_dir and __user_plugin_dir to _user_dir
- and _user_plugin_dir respectively.
-
-
-
-
-* Sun Apr 10 22:54:35 2005 +0000 stark
-
- typo
-
-* Wed Apr 6 08:44:57 2005 +0000 stark
-
- change my email address
-
-* Sat Apr 2 16:18:53 2005 +0000 stark
-
- update
-
-* Sat Apr 2 16:17:17 2005 +0000 stark
-
- do not hide KeyError exceptions when instantiating a plugin
-
-* Sat Apr 2 11:37:10 2005 +0000 stark
-
- version 2.2.1
-
-* Sat Apr 2 11:31:32 2005 +0000 stark
-
- svn2cl generated ChangeLog. This is not quite as nice as cvs2cl but
- it is sufficient to provide the information needed in a ChangeLog.
-
-
-
-* Sat Apr 2 11:13:43 2005 +0000 stark
-
- remove CVSROOT
-
-* Sun Mar 27 00:14:17 2005 +0000 cran
-
- - support host subtraction via '-host' syntax
- - groups can subtract hosts from themselves or underlying groups
- - subgroups cannot subtract hosts from groups above
-
- define SyntaxError exception, for future use by the parser
-
-
-
-* Mon Mar 21 12:12:24 2005 +0000 cran
-
- update
-
-* Sun Mar 20 15:54:26 2005 +0000 cran
-
- minor documentation fixes
-
-* Sun Mar 20 15:19:33 2005 +0000 cran
-
- update
-
-* Sun Mar 20 15:16:53 2005 +0000 cran
-
- In .run(), wait a bit for _stopEvent. Makes thread joining much faster.
- taken from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65448
-
-
-
-* Fri Mar 18 08:36:40 2005 +0000 cran
-
- ignore missing user plugin dir
-
-* Fri Mar 18 08:22:50 2005 +0000 cran
-
- generate ChangeLog from cvs, more information.
-
-* Fri Mar 18 08:17:33 2005 +0000 cran
-
- oops. (%d -> %t)
-
-* Thu Mar 17 21:58:18 2005 +0000 cran
-
- mention PLUGINS document in the manual page
-
-* Thu Mar 17 21:55:48 2005 +0000 cran
-
- Plugin documentation
-
-* Thu Mar 17 21:55:27 2005 +0000 cran
-
- fix imports
-
-* Thu Mar 17 20:51:01 2005 +0000 cran
-
- include lekatnet/plugins/__init__.py in release tarball
-
-* Thu Mar 17 20:45:55 2005 +0000 cran
-
- - update ChangeLog
- - remove unit tests from remote.py. They do not work with plugins
- and bseides this they're shit.
-
-
-
-* Thu Mar 17 20:39:14 2005 +0000 cran
-
- use config.__user_dir
-
-* Thu Mar 17 20:25:43 2005 +0000 cran
-
- monster commit, bring the plugin importer into an acceptable state.
- - do not use execfile to source plugins, it's ugly. use "from plugins import *" instead
- - put all importer logic in plugins/__init__.py
- - mention plugins in the manual page
- - much better docstring for remote.py, explain concepts
-
-
-
-* Thu Mar 17 01:57:49 2005 +0000 cran
-
- forgot to check this in
-
-* Thu Mar 17 01:56:39 2005 +0000 cran
-
- make plugin imports a bit nicer
- - make the plugin registry a private attribute
- - error when a plugin class does not inherit from RemoteCommand
- - user plugins get loaded last, so one can override standard methods
-
-
-
-* Thu Mar 17 00:12:56 2005 +0000 cran
-
- First shot at plugin loading
- - move *RemoteCommand classes into plugin dir
- - make setup.py aware of this directory/package
- - kind of ugly importer using execfile
- - finds user plugins in $HOME/.tentakel/plugins/
-
-
-
-* Tue Mar 15 08:11:47 2005 +0000 cran
-
- update copyright for 2005
-
-* Mon Mar 14 16:11:40 2005 +0000 cran
-
- - add some comments on RemoteCommand.slot to point out the problems
- - _maxparallel -> __maxparallel
-
- - only create the slot semaphore when needed and then only once (this was
+ * py/lekatnet/remote.py: - add some comments on RemoteCommand.slot
+ to point out the problems - _maxparallel -> __maxparallel - only
+ create the slot semaphore when needed and then only once (this was
a minor bug in the first version)
+2005-03-14 14:33 cran
+ * py/lekatnet/remote.py: Rework displayAll(). Now the RemoteCommand
+ class has an auxiliary queue holding references to objects that
+ have results pending. This way displayAll() can simply wait
+ (blocking) for the next result by calling the auxiliary queues
+ get() method. Makes displayAll() easier to understand and also a
+ bit faster. (speed is getting more and more an issue with
+ tentakel...) As a side effect this also fixes a silly bug that
+ allowed only one command to be executed during an interactive
+ tentakel session.
-* Mon Mar 14 14:33:45 2005 +0000 cran
-
- Rework displayAll().
- Now the RemoteCommand class has an auxiliary queue holding references to
- objects that have results pending. This way displayAll() can simply wait
- (blocking) for the next result by calling the auxiliary queues get() method.
-
- Makes displayAll() easier to understand and also a bit faster.
- (speed is getting more and more an issue with tentakel...)
-
- As a side effect this also fixes a silly bug that allowed only one command
- to be executed during an interactive tentakel session.
-
-
-
-* Sun Mar 13 18:57:09 2005 +0000 cran
-
- update
-
-* Sun Mar 13 18:50:53 2005 +0000 cran
-
- update
-
-* Sun Mar 13 18:46:40 2005 +0000 cran
-
- make clear that maxparallel is set to 0 by default
-
-* Sun Mar 13 18:43:42 2005 +0000 cran
-
- Add "maxparallel" parameter.
- This was surprisingly easy to implement by simply adding (and using) a
- BoundedSemaphore to the RemoteCommand class as a class attribute.
-
-
-
-* Sat Mar 5 22:11:58 2005 +0000 cran
-
- Add some pieces of plugin documentation
-
-* Sat Mar 5 22:04:41 2005 +0000 cran
-
- include plugin directory in release
-
-* Sat Mar 5 21:54:14 2005 +0000 cran
-
- Ignore readline import errors.
- This fixes compatibility with e. g. Solaris.
-
-
-
-* Sat Mar 5 21:23:27 2005 +0000 cran
-
- Set version to 2.2
- Put a notice in INSTALL to make people use packages in favor of a
- source install.
-
- Update ChangeLog (optimistically...)
-
-
-
-* Sat Mar 5 21:12:56 2005 +0000 cran
-
- Do not make RemoteCommands daemonic because one of the last changes
- made it necessary. Unfortunately I don't know why. Since tentakel seems
- to do fine without setDaemon(1) I don't care at the moment.
-
-
-
-* Wed Dec 29 13:07:55 2004 +0000 cran
-
- First shot at plugin infrastructure
-
-* Wed Dec 29 13:04:05 2004 +0000 cran
-
- cumulative check-in, cause I made many changes and forgot to check in
- afterwards...
-
- - better separation for the *RemoteCommand classes, commandQueue
- is now semi-private. Leads to easier client interface
-
- - fix bug that lead to many stale threads when changing the configuration
- interactively
-
- - RSHRemoteCommand can now determine the rsh return status
-
- - attempt to make thread handling better: output results immediately when
- they're ready (in the resultQueue). For that reason displayAll() sort
- of polls the resultQueue
-
- This commit might break things at first.
-
-
-
-* Sun Nov 21 11:32:45 2004 +0000 cran
-
- more
-
-* Wed Oct 6 21:28:47 2004 +0000 cran
-
- add a note about problems that may occur when an optional python-dev
- package is missing from the system. Noted by Marlon 10 months ago. :)
-
-
-
-* Mon Sep 27 00:41:00 2004 +0000 cran
-
- more elegant way to choose needed RemoteCommand derivate
-
-* Sun Sep 26 20:04:24 2004 +0000 cran
-
- change installation instructions regarding the python version that
- has to be 2.3 at least.
-
-
-
-* Sun Sep 26 20:01:06 2004 +0000 cran
-
- set release date for 2.1.3
-
-* Sun Sep 26 19:58:01 2004 +0000 cran
-
- Second part of the RemoteCommand overhaul
- - RemoteCommand is now a generic class, all remote command
- classes inherit from there
-
- - SSHRemoteCommand and RSHRemoteCommand are the first ones
-
- - introduce "rsh" method and "rsh_path" variable
-
- - update TODO
-
- - update manpage
-
- - update and reformat README
-
- - remove warning message about which config file is used that
- was there only for debugging reasons
-
- - IMPORTANT CHANGE: parameters for a specific hosts are now taken
- from it's nearest enclosing group and not from the top-level group.
- A simple change makes this possible: the ConfigBase.getGroupMembers()
- method now returns a list of tuples where each tuple contains a
- destination and a complete set of group config parameters
-
-
-
-* Sun Sep 26 13:28:09 2004 +0000 cran
-
- crank version number
-
-* Sun Sep 26 13:25:50 2004 +0000 cran
-
- First step of the RemoteCommand overhaul:
- The goal is to have a generic RemoteCommand class and one class for
- each remote methode that inherits from RemoteCommand.
-
- - Unify RemoteCommand __init__ parameters. This way the
- container object does not need to know about the remote
- method and its specific parameters. Instead the container
- has to supply the group specific parameters as a dictionary.
-
- - For this it is needed to be able to ask the ConfigBase class
- for a complete set of configuration directives for a specific
- group. You can do this with the getGroupParams() method now.
-
- - rename: ConfigBase.getExpandedGroup() -> ConfigBase.getGroupMembers()
-
- - rename: ConfigBase.getGroup() -> ConfigBase._getGroup()
-
- - update docstrings
-
- - update unit tests
-
-
-
-* Sun Sep 26 11:55:14 2004 +0000 cran
-
- typo
-
-* Sun Sep 26 11:52:34 2004 +0000 cran
-
- Introduce %t expansion:
- - add to format parser token list
- - RemoteCommand objects must now provide a duration
- - update documentation accordingly (fix typo in manpage as well: ommited -> omitted)
- - update ChangeLog
- - change default format to illustrate usage of %t
-
-
-
-* Sun Sep 26 11:41:21 2004 +0000 cran
-
- update
-
-* Sun Sep 26 10:24:58 2004 +0000 cran
-
- update, fix and add a lot of documentation
-
-* Sun Sep 26 09:54:30 2004 +0000 cran
-
- Forgot to remove TODO for previous commit
-
-* Sun Sep 26 09:51:20 2004 +0000 cran
-
- - make config.dump() and config.load() take a file object parameter
- and not a string containing the path.
- - use TemporaryFile or NamedTemporaryFile instead of mktemp.
-
- This limits backwards compatibility to python 2.3.
-
-
-
-* Sat Sep 25 13:23:09 2004 +0000 cran
-
- - update homepage URL
-
-* Sat Sep 25 13:21:56 2004 +0000 cran
-
- - update copyright notices (years)
- - change python default path to /usr/bin/python
-
-
-
-* Sat Sep 25 13:19:02 2004 +0000 cran
-
- typo: failure -> failures
- In case of a failure, this lead to a failure :)
-
-
-
-* Sun Jan 25 18:06:29 2004 +0000 cran
-
- don't use "from ... import *", instead, explicitely name the module name.
- This is much easier to read and debug.
-
-
-
-* Sun Jan 25 14:31:58 2004 +0000 cran
-
- - use new-style classes where possible
- - better format map handling:
- - better variable names
- - put %% in the default format map of the formatter class
- - make formatMap a property in the formatter class
- - use zip() instead of map(lambda...) to zero the default values in ConfigGroup
-
-
-
-* Sun Jan 25 14:21:18 2004 +0000 cran
-
- fix for braindead regression test (still braindead enough)
-
-* Sun Jan 18 13:47:34 2004 +0000 cran
-
- quite hard to do: reacting to programs that require terminal input
-
-* Sat Jan 17 18:58:29 2004 +0000 cran
-
- update
-
-* Sat Jan 17 18:54:19 2004 +0000 cran
-
- set version to 2.1.2
-
-* Sat Jan 17 18:50:46 2004 +0000 cran
-
- use english quoting style in warning and error messages
-
-* Sat Jan 17 18:35:03 2004 +0000 cran
-
- - (err nameclash in config.py fixed before)
- - first try config file that was specified on the command line
- and err out if it does not work
- - than try user config and site config and err out if they don't work
- - finally tell user that no config has been found
-
-
-
-* Sat Jan 17 18:13:21 2004 +0000 cran
-
- shift status 8 bits left to remove signal number
-
-* Sat Jan 17 18:12:21 2004 +0000 cran
-
- allow "-" in hostnames
-
-* Sun Jan 11 13:15:27 2004 +0000 cran
-
- - fix some regression tests
- - add one to test ugly syntax parsing
-
-
-
-* Sat Jan 10 23:34:02 2004 +0000 cran
-
- - put empty lines between groups in config dump
- - put clarifying comment into temporary config edit file
-
-
-
-* Sat Jan 10 22:44:29 2004 +0000 cran
-
- simple unit tests for RemoteCommand
-
-* Sat Jan 10 22:28:44 2004 +0000 cran
-
- introduce some unit tests (which were commited partially before)
- regression testing is triggered with "make regress" in the main directory
-
-
-
-* Sat Jan 10 21:48:07 2004 +0000 cran
-
- - remove bug from parser that zeroed out all global settings
- - sanitize getParam()
- - rework __doc__ for getParam()
- - remove superfluous variable in remote.py
-
-
-
-* Sat Jan 10 20:26:20 2004 +0000 cran
-
- set version to 2.1.1
-
-* Sat Jan 10 20:17:01 2004 +0000 cran
-
- - put default values in the PARAMS dictionary because it is more
- obvious
- - make comments a non-terminal in the config file grammar. Rather
- use tpg.Parser.extract() to cut them out. This should fix the
- problem where one could not use # in a parameter value
-
-
-
-* Tue Jan 6 12:12:25 2004 +0000 cran
-
- remove -x from ssh command
-
-* Tue Jan 6 12:10:45 2004 +0000 cran
-
- initialise keyword token from PARAMS
- this is some kind of hack since it involves setting the docstring
- with __doc__ = r"""......""" % ...
-
-
-
-* Mon Jan 5 21:27:36 2004 +0000 cran
-
- typo
-
-* Mon Jan 5 15:23:53 2004 +0000 cran
-
- fix getParam() to match expected behaviour
-
-* Mon Jan 5 14:51:24 2004 +0000 cran
-
- set release date
-
-* Mon Jan 5 14:45:04 2004 +0000 cran
-
- change config file example after recent changes
-
-* Mon Jan 5 14:39:03 2004 +0000 cran
-
- - put all config parameters into a global variable PARAMS
- - __str__ global parameters only if their value is non-empty
-
-
-
-* Sun Jan 4 23:36:49 2004 +0000 cran
-
- set version to 2.1
-
-* Sun Jan 4 23:34:54 2004 +0000 cran
-
- mention how parameters of sub-groups are treated
-
-* Sun Jan 4 23:33:56 2004 +0000 cran
-
- update
-
-* Sun Jan 4 23:33:39 2004 +0000 cran
-
- determine user globally, not in each group
-
-* Sun Jan 4 14:40:45 2004 +0000 cran
-
- change manual page after to reflect recent grammar changes
-
-* Sun Jan 4 14:40:05 2004 +0000 cran
-
- - restructure/simplify grammar
- - now all values (after =) have to be quoted with ""
- - all parameters may appear in a set statement, which makes them global
- - all parameters may appear in a group spec, which makes them local to this group
-
-
-
-* Sun Jan 4 12:59:43 2004 +0000 cran
-
- - introduce "set varname=value" directives in the configuration file
- - currently supported is ssh_path="/some/path/to/ssh"
- - new category in the config AST: "settings"
- - use self["settings"]["ssh_path"] from the config AST to set the ssh path
- - minor optimisations in the config file grammar (not ready yet)
-
-
-
-* Sun Jan 4 12:08:03 2004 +0000 cran
-
- update homepage address (now: http://tentakel.biskalar.de/)
-
-* Sun Jan 4 00:02:38 2004 +0000 cran
-
- add html version of manpage
-
-* Fri Jan 2 18:08:09 2004 +0000 cran
-
- more
-
-* Fri Jan 2 18:03:00 2004 +0000 cran
-
- make clear that host definitions do not need to be separated by newlines
-
-* Fri Jan 2 17:08:21 2004 +0000 cran
-
- announcement text for rel 2.0
-
-* Thu Jan 1 18:58:36 2004 +0000 cran
-
- 2.0 release
-
-* Thu Jan 1 18:46:09 2004 +0000 cran
-
- more
-
-* Thu Jan 1 18:35:18 2004 +0000 cran
-
- - remove redundant information
-
-* Thu Jan 1 18:34:18 2004 +0000 cran
-
- - more install hints
- - minor fixes
-
-
+2005-03-13 18:57 cran
-* Mon Dec 29 14:40:49 2003 +0000 cran
+ * TODO: update
- nicer postscript output
+2005-03-13 18:50 cran
-* Sun Dec 28 21:40:02 2003 +0000 cran
+ * TODO: update
- - don't use __str__ when a normal method makes more sense...
+2005-03-13 18:46 cran
-* Sun Dec 28 21:26:12 2003 +0000 cran
+ * tentakel.1, tentakel.1.html: make clear that maxparallel is set to
+ 0 by default
- - tentakel warnings and errors go to sys.stderr
- - indicate errors as such
+2005-03-13 18:43 cran
+ * ChangeLog, py/lekatnet/config.py, py/lekatnet/remote.py,
+ tentakel.1, tentakel.1.html, tentakel.conf.example: Add
+ "maxparallel" parameter. This was surprisingly easy to implement
+ by simply adding (and using) a BoundedSemaphore to the
+ RemoteCommand class as a class attribute.
+2005-03-05 22:11 cran
-* Sun Dec 28 21:22:23 2003 +0000 cran
+ * tentakel.1, tentakel.1.html: Add some pieces of plugin
+ documentation
- catch RuntimeError from possible loops in configuration files
+2005-03-05 22:04 cran
-* Sun Dec 28 20:40:27 2003 +0000 cran
+ * Makefile: include plugin directory in release
- modernize README
+2005-03-05 21:54 cran
-* Sun Dec 28 20:24:54 2003 +0000 cran
+ * py/lekatnet/shell.py: Ignore readline import errors. This fixes
+ compatibility with e. g. Solaris.
- - better formatting in a lot of places
- - document interactive mode
- - change suse7.3 example to myGroup
+2005-03-05 21:23 cran
+ * ChangeLog, INSTALL, Makefile, py/setup.py, py/tentakel: Set
+ version to 2.2 Put a notice in INSTALL to make people use packages
+ in favor of a source install. Update ChangeLog (optimistically...)
+2005-03-05 21:12 cran
-* Sun Dec 28 16:06:53 2003 +0000 cran
+ * py/lekatnet/remote.py: Do not make RemoteCommands daemonic because
+ one of the last changes made it necessary. Unfortunately I don't
+ know why. Since tentakel seems to do fine without setDaemon(1) I
+ don't care at the moment.
- update
+2004-12-29 13:07 cran
-* Sun Dec 28 15:39:49 2003 +0000 cran
+ * py/lekatnet/plugins, py/lekatnet/plugins/rsh.py,
+ py/lekatnet/plugins/ssh.py: First shot at plugin infrastructure
- update
+2004-12-29 13:04 cran
-* Sun Dec 28 15:22:32 2003 +0000 cran
+ * py/lekatnet/remote.py: cumulative check-in, cause I made many
+ changes and forgot to check in afterwards... - better separation
+ for the *RemoteCommand classes, commandQueue is now semi-private.
+ Leads to easier client interface - fix bug that lead to many stale
+ threads when changing the configuration interactively -
+ RSHRemoteCommand can now determine the rsh return status - attempt
+ to make thread handling better: output results immediately when
+ they're ready (in the resultQueue). For that reason displayAll()
+ sort of polls the resultQueue This commit might break things at
+ first.
- - make the manpage more exact
- - complete config file description
- - fix some issues with postscript output
+2004-11-21 11:32 cran
+ * TODO: more
+2004-10-06 21:28 cran
-* Sun Dec 28 12:22:13 2003 +0000 cran
+ * INSTALL: add a note about problems that may occur when an optional
+ python-dev package is missing from the system. Noted by Marlon 10
+ months ago. :)
- set version to 2.0
+2004-09-27 00:41 cran
-* Sun Dec 28 12:04:49 2003 +0000 cran
+ * py/lekatnet/remote.py: more elegant way to choose needed
+ RemoteCommand derivate
- done
+2004-09-26 20:04 cran
-* Sun Dec 28 12:04:06 2003 +0000 cran
+ * INSTALL: change installation instructions regarding the python
+ version that has to be 2.3 at least.
- - formats are now defined in the config file as groupspec parameters
- - formats are stored in the abstract syntax tree for each group
- - format is set in RemoteCollator.useConf()
- - update manpage and example config file accordingly
+2004-09-26 20:01 cran
+ * ChangeLog: set release date for 2.1.3
+2004-09-26 19:58 cran
-* Sat Dec 27 14:33:36 2003 +0000 cran
+ * ChangeLog, README, TODO, py/lekatnet/config.py,
+ py/lekatnet/remote.py, py/tentakel, tentakel.1, tentakel.1.html:
+ Second part of the RemoteCommand overhaul - RemoteCommand is now a
+ generic class, all remote command classes inherit from there -
+ SSHRemoteCommand and RSHRemoteCommand are the first ones -
+ introduce "rsh" method and "rsh_path" variable - update TODO -
+ update manpage - update and reformat README - remove warning
+ message about which config file is used that was there only for
+ debugging reasons - IMPORTANT CHANGE: parameters for a specific
+ hosts are now taken from it's nearest enclosing group and not from
+ the top-level group. A simple change makes this possible: the
+ ConfigBase.getGroupMembers() method now returns a list of tuples
+ where each tuple contains a destination and a complete set of
+ group config parameters
- some more TODOs
+2004-09-26 13:28 cran
-* Sat Dec 27 14:28:33 2003 +0000 cran
+ * Makefile, py/setup.py, py/tentakel: crank version number
- add TPG to the distribution
+2004-09-26 13:25 cran
-* Sat Dec 27 14:25:09 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/remote.py: First step of the
+ RemoteCommand overhaul: The goal is to have a generic
+ RemoteCommand class and one class for each remote methode that
+ inherits from RemoteCommand. - Unify RemoteCommand __init__
+ parameters. This way the container object does not need to know
+ about the remote method and its specific parameters. Instead the
+ container has to supply the group specific parameters as a
+ dictionary. - For this it is needed to be able to ask the
+ ConfigBase class for a complete set of configuration directives
+ for a specific group. You can do this with the getGroupParams()
+ method now. - rename: ConfigBase.getExpandedGroup() ->
+ ConfigBase.getGroupMembers() - rename: ConfigBase.getGroup() ->
+ ConfigBase._getGroup() - update docstrings - update unit tests
- add licenses
+2004-09-26 11:55 cran
-* Sat Dec 27 14:13:24 2003 +0000 cran
+ * tentakel.1, tentakel.1.html: typo
- Just give a warning on some errors instead of killing tentakel
+2004-09-26 11:52 cran
-* Sat Dec 27 13:55:35 2003 +0000 cran
+ * ChangeLog, py/lekatnet/config.py, py/lekatnet/remote.py,
+ tentakel.1, tentakel.1.html: Introduce %t expansion: - add to
+ format parser token list - RemoteCommand objects must now provide
+ a duration - update documentation accordingly (fix typo in manpage
+ as well: ommited -> omitted) - update ChangeLog - change default
+ format to illustrate usage of %t
- dont use the term "site shell"
+2004-09-26 11:41 cran
-* Sat Dec 27 13:53:03 2003 +0000 cran
+ * TODO: update
- move config file documentation into manpage
+2004-09-26 10:24 cran
-* Sat Dec 27 13:38:47 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/remote.py, py/tentakel: update,
+ fix and add a lot of documentation
- update
+2004-09-26 09:54 cran
-* Sat Dec 27 13:33:38 2003 +0000 cran
+ * py/lekatnet/config.py: Forgot to remove TODO for previous commit
- - if existant use $HOME/.tentakel/tentakel.conf instead of /etc/tentakel.conf
- - document this behaviour
+2004-09-26 09:51 cran
+ * py/lekatnet/config.py, py/tentakel: - make config.dump() and
+ config.load() take a file object parameter and not a string
+ containing the path. - use TemporaryFile or NamedTemporaryFile
+ instead of mktemp. This limits backwards compatibility to python
+ 2.3.
+2004-09-25 13:23 cran
-* Sat Dec 27 13:12:51 2003 +0000 cran
+ * py/setup.py: - update homepage URL
- - use TPG to parse formatstrings
- - use \n and \t for newline and tab
- - change manpage accordingly
+2004-09-25 13:21 cran
+ * py/lekatnet/config.py, py/lekatnet/error.py,
+ py/lekatnet/remote.py, py/lekatnet/shell.py, py/tentakel: - update
+ copyright notices (years) - change python default path to
+ /usr/bin/python
+2004-09-25 13:19 cran
-* Sat Dec 27 12:54:05 2003 +0000 cran
+ * py/lekatnet/remote.py: typo: failure -> failures In case of a
+ failure, this lead to a failure :)
- fix example
+2004-01-25 18:06 cran
-* Sat Dec 27 03:48:13 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/remote.py,
+ py/lekatnet/shell.py, py/tentakel: don't use "from ... import *",
+ instead, explicitely name the module name. This is much easier to
+ read and debug.
- rename -d parameter to -g
+2004-01-25 14:31 cran
-* Sat Dec 27 03:38:57 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/remote.py: - use new-style
+ classes where possible - better format map handling: - better
+ variable names - put %% in the default format map of the formatter
+ class - make formatMap a property in the formatter class - use
+ zip() instead of map(lambda...) to zero the default values in
+ ConfigGroup
- let the user decide which config file to use with the new -c parameter
+2004-01-25 14:21 cran
-* Sat Dec 27 03:22:50 2003 +0000 cran
+ * py/lekatnet/remote.py: fix for braindead regression test (still
+ braindead enough)
- crank beta version number
+2004-01-18 13:47 cran
-* Sat Dec 27 03:20:28 2003 +0000 cran
+ * TODO, py/lekatnet/config.py: quite hard to do: reacting to
+ programs that require terminal input
- - better syntax for the configuration file, see the grammar diff and example
+2004-01-17 18:58 cran
-* Fri Dec 26 23:59:38 2003 +0000 cran
+ * ChangeLog: update
- - import tpg into package lekatnet (maybe remove it later)
- - use tpg to generate a parser for the configuration file
- - simplify the abstract syntax tree in config.py much
+2004-01-17 18:54 cran
+ * Makefile, py/setup.py, py/tentakel: set version to 2.1.2
+2004-01-17 18:50 cran
-* Thu Dec 18 15:21:31 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/remote.py: use english quoting
+ style in warning and error messages
- more hints about installing tentakel
+2004-01-17 18:35 cran
-* Thu Dec 18 08:49:33 2003 +0000 cran
+ * py/tentakel: - (err nameclash in config.py fixed before) - first
+ try config file that was specified on the command line and err out
+ if it does not work - than try user config and site config and err
+ out if they don't work - finally tell user that no config has been
+ found
- document -v
+2004-01-17 18:13 cran
-* Wed Dec 17 22:38:03 2003 +0000 cran
+ * py/lekatnet/remote.py: shift status 8 bits left to remove signal
+ number
- - use tempfile module to get a temporary pathname for ConfigBase.edit()
- This is not really safe but acceptable for the time being.
- - get EDITOR or VISUAL from environment, fallback to vi
+2004-01-17 18:12 cran
+ * py/lekatnet/config.py: allow "-" in hostnames
+2004-01-11 13:15 cran
-* Wed Dec 17 22:11:39 2003 +0000 cran
+ * ChangeLog, py/lekatnet/config.py: - fix some regression tests -
+ add one to test ugly syntax parsing
- - move helptext for -h where it belongs, tentakel, not error.py
- - tentakel -v now outputs version information
+2004-01-10 23:34 cran
+ * py/lekatnet/config.py: - put empty lines between groups in config
+ dump - put clarifying comment into temporary config edit file
+2004-01-10 22:44 cran
-* Wed Dec 17 22:02:03 2003 +0000 cran
+ * Makefile, py/lekatnet/remote.py: simple unit tests for
+ RemoteCommand
- - if a the user value in tentakel.conf is set to "$user" then the
- effective uid of the tentakel process is used.
+2004-01-10 22:28 cran
+ * Makefile, py/lekatnet/config.py: introduce some unit tests (which
+ were commited partially before) regression testing is triggered
+ with "make regress" in the main directory
+2004-01-10 21:48 cran
-* Sun Dec 14 17:47:22 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/remote.py: - remove bug from
+ parser that zeroed out all global settings - sanitize getParam() -
+ rework __doc__ for getParam() - remove superfluous variable in
+ remote.py
- - respect PREFIX environment variable during installation
+2004-01-10 20:26 cran
-* Sun Dec 14 17:14:28 2003 +0000 cran
+ * ChangeLog, Makefile, py/setup.py, py/tentakel: set version to
+ 2.1.1
- - move modules into own package "letaknet"
- - use distutils for installation
- - adopt changes to INSTALL and Makefile
+2004-01-10 20:17 cran
+ * py/lekatnet/config.py, py/lekatnet/remote.py: - put default values
+ in the PARAMS dictionary because it is more obvious - make
+ comments a non-terminal in the config file grammar. Rather use
+ tpg.Parser.extract() to cut them out. This should fix the problem
+ where one could not use # in a parameter value
+2004-01-06 12:12 cran
-* Sat Dec 13 15:10:39 2003 +0000 cran
+ * py/lekatnet/remote.py: remove -x from ssh command
- - don't err when no groupname is specified on the command line,
- just use "default".
+2004-01-06 12:10 cran
+ * py/lekatnet/config.py: initialise keyword token from PARAMS this
+ is some kind of hack since it involves setting the docstring with
+ __doc__ = r"""......""" % ...
+2004-01-05 21:27 cran
-* Sat Dec 13 15:09:48 2003 +0000 cran
+ * tentakel.1, tentakel.1.html: typo
- - include temporary python files in clean target
+2004-01-05 15:23 cran
-* Sat Dec 13 14:59:13 2003 +0000 cran
+ * py/lekatnet/config.py: fix getParam() to match expected behaviour
- - Bring ChangeLog and documentation in sync with recent changes
- - rename old shell version to tentakel.old
+2004-01-05 14:51 cran
+ * ChangeLog: set release date
+2004-01-05 14:45 cran
-* Sat Dec 13 10:02:49 2003 +0000 cran
+ * tentakel.conf.example: change config file example after recent
+ changes
- This is not true
+2004-01-05 14:39 cran
-* Sat Dec 13 09:55:03 2003 +0000 cran
+ * py/lekatnet/config.py: - put all config parameters into a global
+ variable PARAMS - __str__ global parameters only if their value is
+ non-empty
- - put shell into own module
- - no globals are referenced anymore from the class body
+2004-01-04 23:36 cran
+ * Makefile, py/setup.py, py/tentakel: set version to 2.1
+2004-01-04 23:34 cran
-* Fri Dec 12 23:18:57 2003 +0000 cran
+ * tentakel.1, tentakel.1.html: mention how parameters of sub-groups
+ are treated
- - "listgroups" in interactive mode lists available groups
- - "use" in interactive mode sets current group and also changes the prompt
+2004-01-04 23:33 cran
+ * ChangeLog: update
+2004-01-04 23:33 cran
-* Fri Dec 12 21:58:12 2003 +0000 cran
+ * py/lekatnet/config.py: determine user globally, not in each group
- - sprinkle some TODOs
- - style: always newlines after docstrings
+2004-01-04 14:40 cran
+ * tentakel.1, tentakel.1.html: change manual page after to reflect
+ recent grammar changes
+2004-01-04 14:40 cran
-* Fri Dec 12 21:44:38 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/remote.py: -
+ restructure/simplify grammar - now all values (after =) have to be
+ quoted with "" - all parameters may appear in a set statement,
+ which makes them global - all parameters may appear in a group
+ spec, which makes them local to this group
- A *lot* of changes. too much to list all of them.
- - restructured a lot of objects
- - use cmd.Cmd for interactive mode
- - rename some variables
- - more useful docstrings
- - use __str__ for the ConfigItem-style objects. Not it's very easy
- to dump a config object back to a human readable file
+2004-01-04 12:59 cran
- Still lotsa bugs.
+ * py/lekatnet/config.py, py/lekatnet/remote.py: - introduce "set
+ varname=value" directives in the configuration file - currently
+ supported is ssh_path="/some/path/to/ssh" - new category in the
+ config AST: "settings" - use self["settings"]["ssh_path"] from the
+ config AST to set the ssh path - minor optimisations in the config
+ file grammar (not ready yet)
+2004-01-04 12:08 cran
+ * ChangeLog, README, tentakel.1, tentakel.1.html: update homepage
+ address (now: http://tentakel.biskalar.de/)
-* Mon Dec 8 14:37:07 2003 +0000 cran
+2004-01-04 00:02 cran
- First shot at a python version of tentakel.
- Not quite ready yet, but usable.
+ * Makefile, py/setup.py, tentakel.1.html: add html version of
+ manpage
+2004-01-02 18:08 cran
+ * TODO: more
-* Tue May 27 22:23:56 2003 +0000 imaginat
+2004-01-02 18:03 cran
- Provided a solution to the problem with the assert function. "set +e" is
- not supported by many shell, so Sebastians solution wasnt perfect. The
- ksh and the Unix V7 sh exits for the code "set -e; eval false || true",
- but it doesnt, when it's wrapped in ``. So I got rid of the set +e and
- used something similar to "if `eval false`" instead.
+ * tentakel.conf.example: make clear that host definitions do not
+ need to be separated by newlines
+2004-01-02 17:08 cran
+ * ANNOUNCE-2.0: announcement text for rel 2.0
-* Fri May 23 02:28:59 2003 +0000 cran
+2004-01-01 18:58 cran
- reflect recent changes and clarify a bit
+ * ChangeLog: 2.0 release
-* Fri May 23 02:22:44 2003 +0000 cran
+2004-01-01 18:46 cran
- Introduce -C option which can be used to restrict command execution
- to a specific number of hosts.
+ * TODO, tentakel.conf.example: more
+2004-01-01 18:35 cran
+ * Makefile: - remove redundant information
-* Fri May 23 02:13:51 2003 +0000 cran
+2004-01-01 18:34 cran
- make assert() actually work (never worked before)
+ * INSTALL: - more install hints - minor fixes
-* Thu May 22 10:42:33 2003 +0000 cran
+2003-12-29 14:40 cran
- o No default parameters, <method> and <user> for each host object now mandatory
- o Lists of lists
- o Clarify that nesting of lists is possible without limits
- o Update comments and syntax description accordingly
+ * tentakel.1: nicer postscript output
+2003-12-28 21:40 cran
+ * py/lekatnet/remote.py, py/lekatnet/shell.py: - don't use __str__
+ when a normal method makes more sense...
-* Tue May 20 12:41:50 2003 +0000 cran
+2003-12-28 21:26 cran
- Proposal for a general tentakel.conf file format.
- This is just an example .conf file, there is still no code that
- interprets it.
+ * py/lekatnet/error.py: - tentakel warnings and errors go to
+ sys.stderr - indicate errors as such
+2003-12-28 21:22 cran
+ * py/lekatnet/config.py: catch RuntimeError from possible loops in
+ configuration files
-* Mon May 19 17:27:32 2003 +0000 cran
+2003-12-28 20:40 cran
- bugfix release 0.3.1
+ * README: modernize README
-* Mon May 19 13:44:12 2003 +0000 imaginat
+2003-12-28 20:24 cran
- First draft on fixing that stupid dot error.
+ * tentakel.1: - better formatting in a lot of places - document
+ interactive mode - change suse7.3 example to myGroup
-* Sat Apr 19 16:16:57 2003 +0000 cran
+2003-12-28 16:06 cran
- o Rename INSTALLMAN->MANDIR and INSTALLBIN->BINDIR to avoid confusion.
- o Tell user that configure is not implemented yet.
+ * TODO: update
+2003-12-28 15:39 cran
+ * TODO: update
-* Sat Apr 19 15:25:54 2003 +0000 cran
+2003-12-28 15:22 cran
- First version of a Makefile. install.sh and mkrelease.sh are
- obsolete now.
+ * tentakel.1: - make the manpage more exact - complete config file
+ description - fix some issues with postscript output
- Update INSTALL to reflect changes in the installation process.
+2003-12-28 12:22 cran
+ * Makefile, py/setup.py, py/tentakel: set version to 2.0
+2003-12-28 12:04 cran
-* Fri Apr 18 11:12:17 2003 +0000 imaginat
+ * TODO: done
- Update list of necessary tools.
+2003-12-28 12:04 cran
-* Fri Apr 18 11:07:02 2003 +0000 imaginat
+ * py/lekatnet/config.py, py/lekatnet/remote.py,
+ py/lekatnet/shell.py, py/tentakel, tentakel.1,
+ tentakel.conf.example: - formats are now defined in the config
+ file as groupspec parameters - formats are stored in the abstract
+ syntax tree for each group - format is set in
+ RemoteCollator.useConf() - update manpage and example config file
+ accordingly
- Remove -f flag for rm command. (When something goes wrong, it should at
- least be reported, not silently ignored) Change the assertion for
- dprint back: It has to be invoked with exactly one argument.
+2003-12-27 14:33 cran
+ * TODO: some more TODOs
+2003-12-27 14:28 cran
-* Thu Apr 17 11:30:27 2003 +0000 cran
+ * Makefile, README: add TPG to the distribution
- use "rm -f" in *_destroy()
+2003-12-27 14:25 cran
-* Thu Apr 17 11:28:30 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/error.py,
+ py/lekatnet/remote.py, py/lekatnet/shell.py, py/tentakel: add
+ licenses
- document -d switch
+2003-12-27 14:13 cran
-* Thu Apr 17 11:27:01 2003 +0000 cran
+ * py/lekatnet/config.py, py/lekatnet/error.py,
+ py/lekatnet/remote.py: Just give a warning on some errors instead
+ of killing tentakel
- Match manpage SYNOPSIS in usage() output
+2003-12-27 13:55 cran
-* Thu Apr 17 11:25:54 2003 +0000 cran
+ * README, tentakel.1: dont use the term "site shell"
- remove stuff that is implemented
+2003-12-27 13:53 cran
-* Thu Apr 17 11:23:12 2003 +0000 cran
+ * tentakel.1, tentakel.conf.example: move config file documentation
+ into manpage
- release 0.3
+2003-12-27 13:38 cran
-* Thu Apr 17 11:18:51 2003 +0000 cran
+ * ChangeLog: update
- Documentation overhaul
- o remote return value in separator string
- o mention hardcoded /usr/bin/ssh in BUGS
+2003-12-27 13:33 cran
+ * py/tentakel, tentakel.1: - if existant use
+ $HOME/.tentakel/tentakel.conf instead of /etc/tentakel.conf -
+ document this behaviour
+2003-12-27 13:12 cran
-* Thu Apr 17 11:13:33 2003 +0000 cran
+ * py/lekatnet/remote.py, py/tentakel, tentakel.1: - use TPG to parse
+ formatstrings - use \n and \t for newline and tab - change manpage
+ accordingly
- o Temporarily fix possible loop in dprint()/assert()
- o Use "$*" in dprint argument instead of "$@"
+2003-12-27 12:54 cran
+ * tentakel.1: fix example
+2003-12-27 03:48 cran
-* Thu Apr 17 06:52:49 2003 +0000 cran
+ * README, py/tentakel, tentakel.1: rename -d parameter to -g
- set MYVER to 0.3
+2003-12-27 03:38 cran
-* Thu Apr 17 06:50:40 2003 +0000 cran
+ * py/tentakel, tentakel.1: let the user decide which config file to
+ use with the new -c parameter
- Don't put my email address in those files
+2003-12-27 03:22 cran
-* Thu Apr 17 06:49:41 2003 +0000 cran
+ * Makefile, py/setup.py, py/tentakel: crank beta version number
- restructure ChangeLog and reflect latest changes
+2003-12-27 03:20 cran
-* Thu Apr 17 06:45:57 2003 +0000 cran
+ * TODO, py/lekatnet/config.py, tentakel.conf.example: - better
+ syntax for the configuration file, see the grammar diff and
+ example
- Back out -s option. Setting (format)strings on the commandline
- is unneeded complexity and we don't really support it yet.
+2003-12-26 23:59 cran
- This feature may return once we have a working format string
- expansion facility.
+ * py/lekatnet/config.py, py/lekatnet/remote.py, py/lekatnet/tpg.py,
+ py/tentakel: - import tpg into package lekatnet (maybe remove it
+ later) - use tpg to generate a parser for the configuration file -
+ simplify the abstract syntax tree in config.py much
+2003-12-18 15:21 cran
+ * INSTALL: more hints about installing tentakel
-* Wed Apr 16 23:25:48 2003 +0000 imaginat
+2003-12-18 08:49 cran
- Take the ENVIRONMENT section out. The only entry there was about
- DEXECHOST, but that's not in use now, and similar functionality
- will be implemented in a more abstract way.
+ * tentakel.1: document -v
+2003-12-17 22:38 cran
+ * py/lekatnet/config.py: - use tempfile module to get a temporary
+ pathname for ConfigBase.edit() This is not really safe but
+ acceptable for the time being. - get EDITOR or VISUAL from
+ environment, fallback to vi
-* Wed Apr 16 23:17:42 2003 +0000 imaginat
+2003-12-17 22:11 cran
- Move the check for given commands from the execute function to the
- setup function.
+ * py/lekatnet/error.py, py/tentakel: - move helptext for -h where it
+ belongs, tentakel, not error.py - tentakel -v now outputs version
+ information
+2003-12-17 22:02 cran
+ * TODO, py/lekatnet/config.py, py/lekatnet/remote.py, py/tentakel: -
+ if a the user value in tentakel.conf is set to "$user" then the
+ effective uid of the tentakel process is used.
-* Wed Apr 16 22:45:14 2003 +0000 imaginat
+2003-12-14 17:47 cran
- Change the exit code setting to allow usage of set -e again.
+ * INSTALL, Makefile: - respect PREFIX environment variable during
+ installation
-* Wed Apr 16 16:03:38 2003 +0000 imaginat
+2003-12-14 17:14 cran
- Reporting of the local exit code works now. Unfortunately, for this to
- work, "set -e" has to be commented out.
+ * INSTALL, Makefile, py/config.py, py/error.py, py/lekatnet,
+ py/lekatnet/__init__.py, py/lekatnet/config.py,
+ py/lekatnet/error.py, py/lekatnet/remote.py, py/lekatnet/shell.py,
+ py/remote.py, py/setup.py, py/shell.py, py/tentakel,
+ py/tentakel.py: - move modules into own package "letaknet" - use
+ distutils for installation - adopt changes to INSTALL and Makefile
+2003-12-13 15:10 cran
+ * py/tentakel.py, tentakel.1: - don't err when no groupname is
+ specified on the command line, just use "default".
-* Wed Apr 16 14:14:38 2003 +0000 imaginat
+2003-12-13 15:09 cran
- Moved the wait command to the container call method.
+ * Makefile: - include temporary python files in clean target
-* Wed Apr 16 13:48:31 2003 +0000 imaginat
+2003-12-13 14:59 cran
- Corrected and inserted assertions. Corrected code that sets the local
- exit code.
+ * ChangeLog, README, TODO, hostlist.example, tentakel, tentakel.1,
+ tentakel.conf.example, tentakel.old: - Bring ChangeLog and
+ documentation in sync with recent changes - rename old shell
+ version to tentakel.old
+2003-12-13 10:02 cran
+ * py/shell.py: This is not true
-* Wed Apr 16 12:44:49 2003 +0000 imaginat
+2003-12-13 09:55 cran
- Rename temporary files to prefix tentakel. Separate remote stdout and stderr.
+ * py/shell.py, py/tentakel.py: - put shell into own module - no
+ globals are referenced anymore from the class body
-* Wed Apr 16 11:55:20 2003 +0000 cran
+2003-12-12 23:18 cran
- simplify usage() output
+ * py/tentakel.py: - "listgroups" in interactive mode lists available
+ groups - "use" in interactive mode sets current group and also
+ changes the prompt
-* Wed Apr 16 11:54:16 2003 +0000 cran
+2003-12-12 21:58 cran
- Introduce -s parameter that can be used to specify a custom
- separator string.
+ * py/config.py, py/error.py, py/remote.py, py/tentakel.py: -
+ sprinkle some TODOs - style: always newlines after docstrings
+2003-12-12 21:44 cran
+ * py/config.py, py/error.py, py/remote.py, py/tentakel.py: A *lot*
+ of changes. too much to list all of them. - restructured a lot of
+ objects - use cmd.Cmd for interactive mode - rename some variables
+ - more useful docstrings - use __str__ for the ConfigItem-style
+ objects. Not it's very easy to dump a config object back to a
+ human readable file Still lotsa bugs.
-* Wed Apr 16 08:51:22 2003 +0000 cran
+2003-12-08 14:37 cran
- Forgot a closing quote.
+ * py, py/config.py, py/error.py, py/remote.py, py/tentakel.py: First
+ shot at a python version of tentakel. Not quite ready yet, but
+ usable.
-* Wed Apr 16 08:48:12 2003 +0000 cran
+2003-05-27 22:23 imaginat
- We're beta now.
+ * tentakel: Provided a solution to the problem with the assert
+ function. "set +e" is not supported by many shell, so Sebastians
+ solution wasnt perfect. The ksh and the Unix V7 sh exits for the
+ code "set -e; eval false || true", but it doesnt, when it's
+ wrapped in ``. So I got rid of the set +e and used something
+ similar to "if `eval false`" instead.
-* Wed Apr 16 08:47:03 2003 +0000 cran
+2003-05-23 02:28 cran
- Remove lies about the need to quote the remote command in a whole.
- This was just a bug that has vanished in the meanwhile.
+ * TODO: reflect recent changes and clarify a bit
+2003-05-23 02:22 cran
+ * tentakel, tentakel.1: Introduce -C option which can be used to
+ restrict command execution to a specific number of hosts.
-* Wed Apr 16 08:43:16 2003 +0000 cran
+2003-05-23 02:13 cran
- o Rename flag -c to -l since -c will be used for the global config file.
- o Reflect this change in the documentation as well.
- o Rename FLAG_CONFIG to FLAG_HOSTLIST for the same reason.
+ * tentakel: make assert() actually work (never worked before)
+2003-05-22 10:42 cran
+ * tentakel.conf.example: o No default parameters, <method> and
+ <user> for each host object now mandatory o Lists of lists o
+ Clarify that nesting of lists is possible without limits o Update
+ comments and syntax description accordingly
-* Wed Apr 16 08:30:43 2003 +0000 cran
+2003-05-20 12:41 cran
- rename parse_config() to parse_hostlist() because we need
- this name for the function that will parse the global configfile
+ * tentakel.conf.example: Proposal for a general tentakel.conf file
+ format. This is just an example .conf file, there is still no code
+ that interprets it.
+2003-05-19 17:27 cran
+ * ChangeLog, Makefile, tentakel: bugfix release 0.3.1
-* Wed Apr 16 08:10:01 2003 +0000 cran
+2003-05-19 13:44 imaginat
- rename functions to match their meaning better:
- o callit() becomes distribute_command()
- o execute() becomes execute_command()
+ * tentakel: First draft on fixing that stupid dot error.
+2003-04-19 16:16 cran
+ * Makefile: o Rename INSTALLMAN->MANDIR and INSTALLBIN->BINDIR to
+ avoid confusion. o Tell user that configure is not implemented
+ yet.
-* Tue Apr 15 23:48:02 2003 +0000 imaginat
+2003-04-19 15:25 cran
- Add a class that takes over the repetitive calling of methods of the host
- objects. Restructure the callit function to make use of this class.
- Change make_host to use only one parameter by throwing the currently unused
- dexechost out. Change the class definition syntax slightly by omitting the
- semanticly misguiding {} in make_host.
+ * INSTALL, Makefile, install.sh, mkrelease.sh: First version of a
+ Makefile. install.sh and mkrelease.sh are obsolete now. Update
+ INSTALL to reflect changes in the installation process.
+2003-04-18 11:12 imaginat
+ * INSTALL: Update list of necessary tools.
-* Tue Apr 15 23:28:11 2003 +0000 imaginat
+2003-04-18 11:07 imaginat
- Due to the OO rewrite the DEXECHOST feature is not implemented at the
- moment. Note this in the ENVIRONMENT section.
+ * tentakel: Remove -f flag for rm command. (When something goes
+ wrong, it should at least be reported, not silently ignored)
+ Change the assertion for dprint back: It has to be invoked with
+ exactly one argument.
+2003-04-17 11:30 cran
+ * tentakel: use "rm -f" in *_destroy()
-* Mon Apr 14 21:58:05 2003 +0000 imaginat
+2003-04-17 11:28 cran
- The bourne shell doesnt support the unary negation operator !, that negates
- the return code of pipelines. Remove the only appearance.
+ * tentakel.1: document -d switch
+2003-04-17 11:27 cran
+ * tentakel: Match manpage SYNOPSIS in usage() output
-* Mon Apr 14 19:20:30 2003 +0000 imaginat
+2003-04-17 11:25 cran
- Introduce a first try on object oriented programming to tentakel.
- Rewrite the whole callit function to make use of the new object model
- for hosts.
+ * TODO: remove stuff that is implemented
+2003-04-17 11:23 cran
+ * ChangeLog: release 0.3
-* Mon Apr 14 13:48:13 2003 +0000 cran
+2003-04-17 11:18 cran
- more
+ * INSTALL, README, tentakel.1: Documentation overhaul o remote
+ return value in separator string o mention hardcoded /usr/bin/ssh
+ in BUGS
-* Mon Apr 14 13:45:22 2003 +0000 cran
+2003-04-17 11:13 cran
- Don't keep the users from being smart themselves.
+ * tentakel: o Temporarily fix possible loop in dprint()/assert() o
+ Use "$*" in dprint argument instead of "$@"
-* Sat Apr 12 00:33:25 2003 +0000 imaginat
+2003-04-17 06:52 cran
- Remove RSHFLAGS (those configuration will be taken over by configuration
- files) and DOWNHOSTS (which is obsolete).
+ * tentakel: set MYVER to 0.3
+2003-04-17 06:50 cran
+ * INSTALL, README: Don't put my email address in those files
-* Fri Apr 11 23:46:38 2003 +0000 imaginat
+2003-04-17 06:49 cran
- Some additional notes. Remove the entry about writing a manpage.
+ * ChangeLog: restructure ChangeLog and reflect latest changes
-* Fri Apr 11 22:27:38 2003 +0000 imaginat
+2003-04-17 06:45 cran
- Take the information about the now obsolete alive check out.
+ * tentakel, tentakel.1: Back out -s option. Setting (format)strings
+ on the commandline is unneeded complexity and we don't really
+ support it yet. This feature may return once we have a working
+ format string expansion facility.
-* Fri Apr 11 22:26:55 2003 +0000 imaginat
+2003-04-16 23:25 imaginat
- Update according to the changes in the code (take the aliveness check out).
+ * tentakel.1: Take the ENVIRONMENT section out. The only entry there
+ was about DEXECHOST, but that's not in use now, and similar
+ functionality will be implemented in a more abstract way.
-* Fri Apr 11 22:21:21 2003 +0000 imaginat
+2003-04-16 23:17 imaginat
- Take the test for aliveness of remote hosts out. As a result of that,
- the now useless flags -o and -a have also been removed. -q is the same
- as -a.
+ * tentakel: Move the check for given commands from the execute
+ function to the setup function.
+2003-04-16 22:45 imaginat
+ * tentakel: Change the exit code setting to allow usage of set -e
+ again.
-* Thu Apr 10 22:31:18 2003 +0000 cran
+2003-04-16 16:03 imaginat
- No more nmap. Instead, use ping to determine aliveness of hosts.
- Since some implementations of ping don't support setting an explicit
- timeout value we're bound to the default.
+ * tentakel: Reporting of the local exit code works now.
+ Unfortunately, for this to work, "set -e" has to be commented out.
- Comment two asserts that bugged me while I'm here.
+2003-04-16 14:14 imaginat
+ * tentakel: Moved the wait command to the container call method.
+2003-04-16 13:48 imaginat
-* Thu Apr 10 22:27:51 2003 +0000 imaginat
+ * tentakel: Corrected and inserted assertions. Corrected code that
+ sets the local exit code.
- Use correct quotation marks (mainly useful for postscript output).
+2003-04-16 12:44 imaginat
-* Thu Apr 10 18:18:55 2003 +0000 imaginat
+ * tentakel, tentakel.1: Rename temporary files to prefix tentakel.
+ Separate remote stdout and stderr.
- Introduce the function assert. Use it in some functions.
+2003-04-16 11:55 cran
-* Thu Apr 10 16:54:51 2003 +0000 imaginat
+ * tentakel: simplify usage() output
- Revision of the callit function, remove some non-bourne dependencies.
+2003-04-16 11:54 cran
-* Thu Apr 10 08:46:11 2003 +0000 cran
+ * tentakel, tentakel.1: Introduce -s parameter that can be used to
+ specify a custom separator string.
- more
+2003-04-16 08:51 cran
-* Thu Apr 10 08:42:36 2003 +0000 cran
+ * tentakel: Forgot a closing quote.
- further explanations for the DEXECHOST variable
+2003-04-16 08:48 cran
-* Thu Apr 10 08:27:37 2003 +0000 cran
+ * tentakel.1: We're beta now.
- proper license and RCS id
+2003-04-16 08:47 cran
-* Thu Apr 10 08:06:34 2003 +0000 cran
+ * README, tentakel: Remove lies about the need to quote the remote
+ command in a whole. This was just a bug that has vanished in the
+ meanwhile.
- document DEXECHOST variable in new section ENVIRONMENT
+2003-04-16 08:43 cran
-* Wed Apr 9 20:03:44 2003 +0000 imaginat
+ * README, tentakel, tentakel.1: o Rename flag -c to -l since -c will
+ be used for the global config file. o Reflect this change in the
+ documentation as well. o Rename FLAG_CONFIG to FLAG_HOSTLIST for
+ the same reason.
- Minor corrections / hacks: Ignorance of nmap's stderr, fix a missing "then",
- include the main program.
+2003-04-16 08:30 cran
+ * tentakel: rename parse_config() to parse_hostlist() because we
+ need this name for the function that will parse the global
+ configfile
+2003-04-16 08:10 cran
-* Wed Apr 9 19:50:57 2003 +0000 imaginat
+ * tentakel: rename functions to match their meaning better: o
+ callit() becomes distribute_command() o execute() becomes
+ execute_command()
- Introduce the setup function to evaluate the results of the command line
- parsing. Move the dprint function generation to the setup function.
- Introduce the function alive_echo. Moved the setting of the
- CFGFILE-variable from parse_config to setup.
+2003-04-15 23:48 imaginat
+ * tentakel: Add a class that takes over the repetitive calling of
+ methods of the host objects. Restructure the callit function to
+ make use of this class. Change make_host to use only one parameter
+ by throwing the currently unused dexechost out. Change the class
+ definition syntax slightly by omitting the semanticly misguiding
+ {} in make_host.
+2003-04-15 23:28 imaginat
-* Wed Apr 9 19:16:17 2003 +0000 imaginat
+ * tentakel.1: Due to the OO rewrite the DEXECHOST feature is not
+ implemented at the moment. Note this in the ENVIRONMENT section.
- Change parse_options to be just a parser, don't execute any code there.
- Removed FLAG_QUIET to conform to documentation to prohibit possible
- side effects. Removed command line option -h and added --version for
- displaying version information.
+2003-04-14 21:58 imaginat
+ * tentakel: The bourne shell doesnt support the unary negation
+ operator !, that negates the return code of pipelines. Remove the
+ only appearance.
+2003-04-14 19:20 imaginat
-* Wed Apr 9 18:58:51 2003 +0000 imaginat
+ * tentakel: Introduce a first try on object oriented programming to
+ tentakel. Rewrite the whole callit function to make use of the new
+ object model for hosts.
- Simplify the execute function
+2003-04-14 13:48 cran
-* Wed Apr 9 18:41:08 2003 +0000 imaginat
+ * TODO: more
- Split the huge code block at the end of the file into separate functions.
- Rename Version and Usage to version and usage, resp.
+2003-04-14 13:45 cran
+ * tentakel.1: Don't keep the users from being smart themselves.
+2003-04-12 00:33 imaginat
-* Wed Apr 9 18:34:25 2003 +0000 imaginat
+ * tentakel: Remove RSHFLAGS (those configuration will be taken over
+ by configuration files) and DOWNHOSTS (which is obsolete).
- Stripped some comments.
+2003-04-11 23:46 imaginat
-* Wed Apr 9 18:25:38 2003 +0000 imaginat
+ * TODO: Some additional notes. Remove the entry about writing a
+ manpage.
- Introduce a function to output the current version number and remove
- this from the Usage function
+2003-04-11 22:27 imaginat
+ * README: Take the information about the now obsolete alive check
+ out.
+2003-04-11 22:26 imaginat
-* Wed Apr 9 18:22:51 2003 +0000 imaginat
+ * tentakel.1: Update according to the changes in the code (take the
+ aliveness check out).
- Substitution of tabulator characters in the output of the Usage function
+2003-04-11 22:21 imaginat
-* Wed Apr 9 14:56:18 2003 +0000 imaginat
+ * tentakel: Take the test for aliveness of remote hosts out. As a
+ result of that, the now useless flags -o and -a have also been
+ removed. -q is the same as -a.
- Added quotes in the dprint function.
+2003-04-10 22:31 cran
-* Tue Apr 8 22:17:44 2003 +0000 imaginat
+ * INSTALL, README, tentakel, tentakel.1: No more nmap. Instead, use
+ ping to determine aliveness of hosts. Since some implementations
+ of ping don't support setting an explicit timeout value we're
+ bound to the default. Comment two asserts that bugged me while I'm
+ here.
- Replacement of "[" by "test" for better compatibility. Cleaner semanticss
- for the tests like -eq instead = for numbers.
+2003-04-10 22:27 imaginat
+ * tentakel.1: Use correct quotation marks (mainly useful for
+ postscript output).
+2003-04-10 18:18 imaginat
-* Tue Apr 8 22:05:56 2003 +0000 imaginat
+ * tentakel: Introduce the function assert. Use it in some functions.
- Added the "Reporting Bugs" section and my name to the author's list.
+2003-04-10 16:54 imaginat
-* Tue Apr 8 21:53:34 2003 +0000 imaginat
+ * tentakel: Revision of the callit function, remove some non-bourne
+ dependencies.
- Improved bourne compatibility. Dropped some uses of "$(())"- and
- "${}"-expansion that are not present in all bourne shells.
+2003-04-10 08:46 cran
+ * ChangeLog: more
+2003-04-10 08:42 cran
-* Tue Apr 8 13:54:22 2003 +0000 cran
+ * tentakel.1: further explanations for the DEXECHOST variable
- remove unnecessary comment
+2003-04-10 08:27 cran
-* Tue Apr 8 13:45:21 2003 +0000 imaginat
+ * tentakel.1: proper license and RCS id
- Changed the indentation to use 8 character wide columns globally.
+2003-04-10 08:06 cran
-* Tue Apr 8 13:22:57 2003 +0000 imaginat
+ * tentakel.1: document DEXECHOST variable in new section ENVIRONMENT
- Removed the unnecessary encapsulation of the nmap|grep pipe in the
- alive function.
+2003-04-09 20:03 imaginat
+ * tentakel: Minor corrections / hacks: Ignorance of nmap's stderr,
+ fix a missing "then", include the main program.
+2003-04-09 19:50 imaginat
-* Tue Apr 8 13:19:47 2003 +0000 imaginat
+ * tentakel: Introduce the setup function to evaluate the results of
+ the command line parsing. Move the dprint function generation to
+ the setup function. Introduce the function alive_echo. Moved the
+ setting of the CFGFILE-variable from parse_config to setup.
- Changed the semantics of the tempfile function. Error is now reported
- through the exit code from the mktemp process itself. The caller doesn't
- have to check if the created file name is "/dev/null" anymore.
+2003-04-09 19:16 imaginat
+ * tentakel: Change parse_options to be just a parser, don't execute
+ any code there. Removed FLAG_QUIET to conform to documentation to
+ prohibit possible side effects. Removed command line option -h and
+ added --version for displaying version information.
+2003-04-09 18:58 imaginat
-* Tue Apr 8 13:16:08 2003 +0000 imaginat
+ * tentakel: Simplify the execute function
- Changed the function err to exit by itself after showing the error.
- Adapted this behaviour to every places where the err function was
- used. Introduced the "warn" function to output warnings without
- exiting.
+2003-04-09 18:41 imaginat
+ * tentakel: Split the huge code block at the end of the file into
+ separate functions. Rename Version and Usage to version and usage,
+ resp.
+2003-04-09 18:34 imaginat
-* Tue Apr 8 13:01:33 2003 +0000 imaginat
+ * tentakel: Stripped some comments.
- Got rid of the "checksoft" function. It's still too early for such a functionality.
+2003-04-09 18:25 imaginat
-* Wed Apr 2 23:15:56 2003 +0000 cran
+ * tentakel: Introduce a function to output the current version
+ number and remove this from the Usage function
- more
+2003-04-09 18:22 imaginat
-* Wed Apr 2 23:14:09 2003 +0000 cran
+ * tentakel: Substitution of tabulator characters in the output of
+ the Usage function
- some new, some done, some changed
+2003-04-09 14:56 imaginat
-* Tue Apr 1 10:25:02 2003 +0000 cran
+ * tentakel: Added quotes in the dprint function.
- initialize FLAG_* with numbers, not strings.
+2003-04-08 22:17 imaginat
-* Tue Apr 1 10:07:21 2003 +0000 cran
+ * tentakel: Replacement of "[" by "test" for better compatibility.
+ Cleaner semanticss for the tests like -eq instead = for numbers.
- forgot one ~ -> $HOME
+2003-04-08 22:05 imaginat
-* Tue Apr 1 10:06:53 2003 +0000 cran
+ * tentakel.1: Added the "Reporting Bugs" section and my name to the
+ author's list.
- o use `` instead of $()
- o use $HOME instead of ~
- I hope this commit makes tentakel bourne shell compatible again.
+2003-04-08 21:53 imaginat
+ * tentakel: Improved bourne compatibility. Dropped some uses of
+ "$(())"- and "${}"-expansion that are not present in all bourne
+ shells.
+2003-04-08 13:54 cran
-* Sun Mar 30 16:51:08 2003 +0000 cran
+ * tentakel: remove unnecessary comment
- missing ,
+2003-04-08 13:45 imaginat
-* Sun Mar 30 16:42:30 2003 +0000 cran
+ * tentakel: Changed the indentation to use 8 character wide columns
+ globally.
- Remove -s option because it makes absolutely no sense.
- Return values should be handled in a better way.
+2003-04-08 13:22 imaginat
+ * tentakel: Removed the unnecessary encapsulation of the nmap|grep
+ pipe in the alive function.
+2003-04-08 13:19 imaginat
-* Sun Mar 30 16:36:58 2003 +0000 cran
+ * tentakel: Changed the semantics of the tempfile function. Error is
+ now reported through the exit code from the mktemp process itself.
+ The caller doesn't have to check if the created file name is
+ "/dev/null" anymore.
- sync -h output with manpage
+2003-04-08 13:16 imaginat
-* Sun Mar 30 15:36:46 2003 +0000 cran
+ * tentakel: Changed the function err to exit by itself after showing
+ the error. Adapted this behaviour to every places where the err
+ function was used. Introduced the "warn" function to output
+ warnings without exiting.
- installation helper
+2003-04-08 13:01 imaginat
-* Sun Mar 30 15:10:27 2003 +0000 cran
+ * tentakel: Got rid of the "checksoft" function. It's still too
+ early for such a functionality.
- User numbers, not strings, to express flags.
- Change [ parameters accordingly. (= -> -eq, != -> -ne)
+2003-04-02 23:15 cran
+ * ChangeLog: more
+2003-04-02 23:14 cran
-* Sun Mar 30 13:27:16 2003 +0000 cran
+ * TODO: some new, some done, some changed
- tentacle -> tentakel name change
+2003-04-01 10:25 cran
-* Sun Mar 30 13:24:00 2003 +0000 cran
+ * tentakel: initialize FLAG_* with numbers, not strings.
- send commit info to tentakel-commits@
+2003-04-01 10:07 cran
-* Sun Mar 30 13:23:11 2003 +0000 cran
+ * README: forgot one ~ -> $HOME
- put manpage into tarball
+2003-04-01 10:06 cran
-* Sat Mar 29 21:49:08 2003 +0000 cran
+ * INSTALL, tentakel, tentakel.1: o use `` instead of $() o use $HOME
+ instead of ~ I hope this commit makes tentakel bourne shell
+ compatible again.
- o manpage
- o rcs id
+2003-03-30 16:51 cran
+ * tentakel.1: missing ,
+2003-03-30 16:42 cran
-* Sat Mar 29 21:39:48 2003 +0000 cran
+ * tentakel, tentakel.1: Remove -s option because it makes absolutely
+ no sense. Return values should be handled in a better way.
- host list sorting functions
+2003-03-30 16:36 cran
-* Sat Mar 29 21:37:24 2003 +0000 cran
+ * tentakel: sync -h output with manpage
- enable syncmail for cran@
+2003-03-30 15:36 cran
-* Sat Mar 29 21:20:20 2003 +0000 cran
+ * ChangeLog, INSTALL, install.sh, mkrelease.sh: installation helper
- No logfile anymore. Instead, use dprint for debugging output.
- Debug output is enabled using the -d switch.
+2003-03-30 15:10 cran
+ * tentakel: User numbers, not strings, to express flags. Change [
+ parameters accordingly. (= -> -eq, != -> -ne)
+2003-03-30 13:27 cran
-* Wed Mar 26 17:39:18 2003 +0000 cran
+ * INSTALL, README, TODO, tentakel, tentakel.1: tentacle -> tentakel
+ name change
- o manpage mostly done
- o new todo: stdin/stdout handling
+2003-03-30 13:23 cran
+ * mkrelease.sh: put manpage into tarball
+2003-03-29 21:49 cran
-* Wed Mar 26 17:36:55 2003 +0000 cran
+ * ChangeLog: o manpage o rcs id
- some clarifications
+2003-03-29 21:39 cran
-* Wed Mar 26 17:29:40 2003 +0000 cran
+ * TODO: host list sorting functions
- unnecessary
+2003-03-29 21:20 cran
-* Wed Mar 26 14:08:26 2003 +0000 imaginat
+ * README, tentakel, tentakel.1: No logfile anymore. Instead, use
+ dprint for debugging output. Debug output is enabled using the -d
+ switch.
- Written the initial manpage.
+2003-03-26 17:39 cran
-* Wed Mar 26 14:05:53 2003 +0000 cran
+ * TODO: o manpage mostly done o new todo: stdin/stdout handling
- typo in example
+2003-03-26 17:36 cran
-* Wed Mar 26 14:04:38 2003 +0000 cran
+ * tentakel.1: some clarifications
- Some usage examples
+2003-03-26 17:29 cran
-* Wed Mar 26 13:56:13 2003 +0000 cran
+ * ChangeLog: unnecessary
- more
+2003-03-26 14:08 imaginat
-* Wed Mar 26 13:46:51 2003 +0000 cran
+ * tentakel.1: Written the initial manpage.
- add error handling function and use it where appropriate
+2003-03-26 14:05 cran
-* Wed Mar 26 13:39:45 2003 +0000 cran
+ * README: typo in example
- document a bit
+2003-03-26 14:04 cran
-* Wed Mar 26 13:11:22 2003 +0000 imaginat
+ * README: Some usage examples
- Corrected one of the spelling errors.
+2003-03-26 13:56 cran
-* Wed Mar 26 12:23:48 2003 +0000 cran
+ * TODO: more
- append yesterdays and todays changes
+2003-03-26 13:46 cran
-* Wed Mar 26 12:23:10 2003 +0000 cran
+ * tentakel: add error handling function and use it where appropriate
- more
+2003-03-26 13:39 cran
-* Wed Mar 26 12:19:05 2003 +0000 cran
+ * mkrelease.sh: document a bit
- o clarify install process
- o provide hostlist example
- o raise version number to 0.3-beta
+2003-03-26 13:11 imaginat
+ * INSTALL: Corrected one of the spelling errors.
+2003-03-26 12:23 cran
-* Wed Mar 26 12:09:23 2003 +0000 cran
+ * ChangeLog: append yesterdays and todays changes
- add (empty) ChangeLog
+2003-03-26 12:23 cran
-* Wed Mar 26 12:04:39 2003 +0000 cran
+ * TODO: more
- MUCH more information
+2003-03-26 12:19 cran
-* Wed Mar 26 12:04:21 2003 +0000 cran
+ * INSTALL, hostlist.example, mkrelease.sh, tentakel: o clarify
+ install process o provide hostlist example o raise version number
+ to 0.3-beta
- manpage
+2003-03-26 12:09 cran
-* Wed Mar 26 11:51:30 2003 +0000 cran
+ * ChangeLog, mkrelease.sh: add (empty) ChangeLog
- put TODO in release tarballs as well
+2003-03-26 12:04 cran
-* Tue Mar 25 12:09:39 2003 +0000 cran
+ * INSTALL, README: MUCH more information
- sprinkle some rcs ids
+2003-03-26 12:04 cran
-* Tue Mar 25 12:08:54 2003 +0000 cran
+ * TODO: manpage
- some todos
+2003-03-26 11:51 cran
-* Tue Mar 25 11:56:08 2003 +0000 cran
+ * mkrelease.sh: put TODO in release tarballs as well
- german -> english
+2003-03-25 12:09 cran
-* Tue Mar 25 10:25:10 2003 +0000 cran
+ * INSTALL, README: sprinkle some rcs ids
- make release script
+2003-03-25 12:08 cran
-* Tue Mar 25 09:36:28 2003 +0000 cran
+ * TODO: some todos
- Initial revision
+2003-03-25 11:56 cran
-* Thu Mar 20 18:16:18 2003 +0000 root
+ * tentakel: german -> english
- initial checkin
+2003-03-25 10:25 cran
-* Thu Mar 20 18:16:18 2003 +0000 root
+ * mkrelease.sh: make release script
- initial checkin
+2003-03-25 09:36 cran
-* Thu Mar 20 18:16:18 2003 +0000 (no author)
+ * ., INSTALL, README, tentakel: Initial revision
- New repository initialized by cvs2svn.
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/INSTALL
^
|
@@ -1,4 +1,7 @@
+$Id: INSTALL 278 2007-03-04 21:30:26Z stark $
+
+
Tentakel requires a working Python installation. The minimum Python
version required is 2.4.
Theoretically, tentakel should work on any platform that is supported by
@@ -42,11 +45,6 @@
In this case you will have to put this path to your PYTHONPATH
environment variable.
-By default the execwrapper.c program will be compiled. If you don't want
-this you have to change the Makefile accordingly. execwrapper is not
-needed for standard operation of tentakel, but can be very helpful in
-certain cases.
-
The tentakel commandline utility will install into $PREFIX/bin/tentakel.
If $PREFIX/bin is not contained in your PATH variable you will have to
append this directory in order to call tentakel without the need to type
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/Makefile
^
|
@@ -1,4 +1,6 @@
+# $Id: Makefile 256 2005-04-02 11:37:10Z stark $
+
RELEASEFILES= tentakel.1 \
tentakel.1.html \
INSTALL \
@@ -8,7 +10,6 @@
ChangeLog \
tentakel.conf.example \
Makefile \
- execwrapper.c \
py/setup.py \
py/tentakel \
py/lekatnet/__init__.py \
@@ -24,41 +25,33 @@
PYTHON?= python
PREFIX?= /usr/local
REL= tentakel-2.2.1
-CC?= cc
-CFLAGS?=
-all: build
+all: configure
configure:
cd py && $(PYTHON) setup.py config
-
-build: configure execwrapper
cd py && $(PYTHON) setup.py build
-htmldoc: tentakel.1
+htmldoc:
rm -f tentakel.1.html
groff -Thtml -man tentakel.1 > tentakel.1.html
changelog:
- git log --pretty=format:"* %cd %cn%n%n%s%n%b" \
- | grep -v "git-svn-id" \
- | sed 's/^\([^*]\)/ \1/' \
+ svn log --xml --verbose | \
+ xsltproc --stringparam strip-prefix trunk/tentakel svn2cl.xsl - \
>ChangeLog
-install: configure build
+install: configure
cd py && $(PYTHON) setup.py install --prefix=$(PREFIX)
-execwrapper: execwrapper.c
- $(CC) $(CFLAGS) -o execwrapper execwrapper.c
-
-release: build
+release:
rm -rf $(REL)
mkdir $(REL)
tar cf - $(RELEASEFILES) | ( cd $(REL) && tar xf - )
tar czf $(REL).tgz $(REL)
rm -rf $(REL)
-regress: build
+regress:
cd py/lekatnet && $(PYTHON) config.py
cd py/lekatnet && $(PYTHON) remote.py
@@ -66,7 +59,4 @@
rm -f *~
rm -f py/{,lekatnet/,lekatnet/plugins/}{*~,*.pyc,*.pyo}
rm -rf py/build
- rm -f execwrapper
rm -f $(REL).tgz
-
-.PHONY: changelog
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/README
^
|
@@ -1,3 +1,5 @@
+$Id: README 250 2005-03-20 15:54:26Z cran $
+
Tentakel is a program for executing the same command on many hosts in parallel
using various remote methods. It can make use of several sets of hosts that are
@@ -28,4 +30,3 @@
This software contains the Toy Parser Generator (tpg.py)
written by Christophe Delord.
-
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/TODO
^
|
@@ -1,6 +1,13 @@
+$Id: TODO 276 2007-03-04 21:00:16Z stark $
Lots of TODOs are directly written as comments in the source.
+* split stdout/stderr
+
+* use python2.4
+
+* really really check out python2.4s new subprocess module.
+
* more backends (not just ssh/rsh, what about telnet or other password
authorizing tools? what about ftp and similar non-remote-shell
environments?)
@@ -13,6 +20,8 @@
* Maybe merge user config into site config
+* more formatting expressions (stderr, ...)
+
* Do format expansion on command strings as well! What kind of
expressions could be useful?
@@ -41,34 +50,3 @@
taken from the environment and/or user-definable).
* Windows compatibility
-
-* Write regression test for execwrapper
-
-* Write regression test for dynamic host list generation
-
-* From Derek Scherger:
- 1. rename the "listgroups" command to simply "groups" to be consistent
- with "hosts" (good idea)
- 2. change both groups and hosts to list in sorted order (sent patch)
- 3. changed displayAll in remote.py to list output in sorted order (I'm
- not entirely sure about my "solution" here though. so have a closer
- look at this one.
- 4. Better error handling (to not kill program) (very good idea)
-
-* Color codes:
- * in format strings
- * depending on output from stderr
-
-* All configuration parameters should be available from the command line.
- It should be possible to specify an on-the-fly group at the command line.
- An example would be:
-
- tentakel -G node1,node2,node3 -o method=ssh -o format="..."
-
- If you select a group from the config file the -o option would override
- the values of the group definition.
-
-
-Resources:
-
- - http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/lekatnet/config.py
^
|
@@ -1,4 +1,6 @@
+# $Id: config.py 279 2007-03-11 15:47:05Z stark $
+#
# Copyright (c) 2002-2007 Sebastian Stark
#
# Redistribution and use in source and binary forms, with or without
@@ -59,7 +61,7 @@
'method': "ssh",
'maxparallel': "0",
'user': pwd.getpwuid(os.geteuid())[0],
- 'format': r"##### %d(stat: %s, dur(s): %t):\n%e%o\n"
+ 'format': r"### %d(stat: %s, dur(s): %t):\n%o\n"
}
METHODS = ['ssh', 'rsh']
@@ -314,7 +316,7 @@
val = self._getGroup(group)[param]
if val == '': return self["settings"][param]
else: return val
- except error.TNoSuchGroupError:
+ except KeyError:
return self["settings"][param]
def getGroupParams(self, groupName):
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/lekatnet/error.py
^
|
@@ -1,4 +1,6 @@
+# $Id: error.py 279 2007-03-11 15:47:05Z stark $
+#
# Copyright (c) 2002-2007 Sebastian Stark
#
# Redistribution and use in source and binary forms, with or without
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/lekatnet/plugins/rsh.py
^
|
@@ -1,4 +1,6 @@
+# $Id: rsh.py 275 2007-03-04 20:56:08Z stark $
+#
# Copyright (c) 2002-2007 Sebastian Stark
#
# Redistribution and use in source and binary forms, with or without
@@ -25,13 +27,14 @@
from lekatnet.remote import registerRemoteCommandPlugin
from lekatnet.remote import RemoteCommand
import time
+import commands
import random
import md5
class RSHRemoteCommand(RemoteCommand):
"RSH remote execution class"
- def __init__(self, destination, params, stdin):
+ def __init__(self, destination, params):
self.rshpath = params['rsh_path']
self.user = params['user']
RemoteCommand.__init__(self, destination, params)
@@ -40,8 +43,7 @@
def _rexec(self, command):
s = '%s -l %s %s "%s; echo %s \\$?"' % (self.rshpath, self.user, self.destination, command,self.delim)
t1 = time.time()
- _, output, err = self.getstatusoutput(s)
- ol = output.split('\n')
+ ol = commands.getoutput(s).split('\n')
for linenumber, line in enumerate(ol):
i = line.find(self.delim)
if i != -1:
@@ -49,6 +51,6 @@
ol.pop(linenumber)
break
self.duration = time.time() - t1
- return (int(status), '\n'.join(ol), err)
+ return (int(status), '\n'.join(ol))
registerRemoteCommandPlugin('rsh', RSHRemoteCommand)
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/lekatnet/plugins/ssh.py
^
|
@@ -1,4 +1,6 @@
+# $Id: ssh.py 282 2007-03-11 16:09:13Z stark $
+#
# Copyright (c) 2002-2007 Sebastian Stark
#
# Redistribution and use in source and binary forms, with or without
@@ -25,22 +27,24 @@
from lekatnet.remote import registerRemoteCommandPlugin
from lekatnet.remote import RemoteCommand
import time
+from subprocess import Popen, PIPE
class SSHRemoteCommand(RemoteCommand):
"SSH remote execution class"
- def __init__(self, destination, params, stdin):
+ def __init__(self, destination, params):
self.sshpath = params['ssh_path']
self.user = params['user']
- RemoteCommand.__init__(self, destination, params, stdin)
+ RemoteCommand.__init__(self, destination, params)
def _rexec(self, command):
- s = '%s %s@%s "%s"' % (self.sshpath, self.user, self.destination, command)
+ cmdstr = [self.sshpath, '%s@%s'%(self.user, self.destination), command]
t1 = time.time()
- status, output, err = self.getstatusoutput(s)
+ child = Popen(cmdstr, stdout=PIPE)
+ output = child.communicate()[0]
+ status = child.returncode
self.duration = time.time() - t1
# shift 8 bits right to strip signal number from status
- return (status >> 8, output, err)
+ return (status >> 8, output)
registerRemoteCommandPlugin('ssh', SSHRemoteCommand)
-
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/lekatnet/remote.py
^
|
@@ -1,4 +1,6 @@
+# $Id: remote.py 279 2007-03-11 15:47:05Z stark $
+#
# Copyright (c) 2002-2007 Sebastian Stark
#
# Redistribution and use in source and binary forms, with or without
@@ -40,19 +42,19 @@
import error
import sys
+import commands
import threading, Queue
import tpg
import time
import os
import config
-from popen2 import Popen3
class FormatString(tpg.Parser):
r"""
token escape : '\\[\\nt]' str ;
- token fmtchar : '%[%doest]' str ;
+ token fmtchar : '%[%dost]' str ;
token char : '.' str ;
START/e -> FORMAT/e ;
@@ -110,10 +112,9 @@
# have results ready
finishedObjects = Queue.Queue()
- def __init__(self, destination, params, stdin):
+ def __init__(self, destination, params):
threading.Thread.__init__(self)
self.duration = 0.0
- self.stdin = stdin
self.destination = destination
self._commandQueue = Queue.Queue()
self._resultQueue = Queue.Queue()
@@ -131,25 +132,6 @@
self.__class__.slot = threading.BoundedSemaphore(self.__maxparallel)
self.start()
- # Get the output from a shell command into a string.
- # Preserve the exit status; a trailing newline is stripped.
- # Assume the command will work with '{ ... ; } 2>&1' around it..
- # Returns a pair (sts, output)
- #
- def getstatusoutput(self, cmd):
- """Return (status, output) of executing cmd in a shell."""
- p = Popen3(cmd, capturestderr=True)
- p.tochild.write(self.stdin)
- p.tochild.close()
- err = p.childerr.read()
- p.childerr.close()
- text = p.fromchild.read()
- p.fromchild.close()
- sts = p.wait()
- if sts is None: sts = 0
- if text[-1:] == '\n': text = text[:-1]
- return sts, text, err
-
def execute(self, command):
"Execute a command in this thread"
self._commandQueue.put_nowait(command)
@@ -183,7 +165,7 @@
threading.Thread.join(self, self._commandTimeout)
-def remoteCommandFactory(destination, params, stdin):
+def remoteCommandFactory(destination, params):
"""Depending in the method, instantiate a corresponding
RemoteCommand derived object and return it"""
@@ -193,16 +175,16 @@
except KeyError:
error.err('Method not implemented: "%s"' % method)
else:
- return rc(destination, params, stdin)
+ return rc(destination, params)
class RemoteCollator(object):
"""This class is meant to hold RemoteCommand instances each
of which implements a specific way to execute a command on
a remote host"""
- def __init__(self, conf, groupName, stdin=''):
+ def __init__(self, conf, groupName):
self.clear()
- self.useConf(conf, groupName, stdin)
+ self.useConf(conf, groupName)
self.formatter = FormatString()
def clear(self):
@@ -215,7 +197,7 @@
pass
self.remoteobjects = []
- def useConf(self, conf, groupName, stdin):
+ def useConf(self, conf, groupName):
"""Load the specified group from configuration object conf
and add RemoteCommand objects for each contained host"""
save = self
@@ -227,7 +209,7 @@
raise
else:
for destination, params in groupMembers:
- self.add(remoteCommandFactory(destination, params, stdin))
+ self.add(remoteCommandFactory(destination, params))
self.format = conf.getParam("format", group=groupName)
def getDestinations(self):
@@ -272,12 +254,11 @@
while displayCount > 0:
obj = RemoteCommand.finishedObjects.get()
displayCount -= 1
- status, output, err = obj.getResult()
+ status, output = obj.getResult()
resultMap = {
r"%d": obj.destination,
r"%t": str(round(obj.duration, 2)),
r"%o": output,
- r"%e": err,
r"%s": str(status)
}
sys.stdout.write(self.expandFormat(resultMap))
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/lekatnet/shell.py
^
|
@@ -1,4 +1,6 @@
+# $Id: shell.py 275 2007-03-04 20:56:08Z stark $
+#
# Copyright (c) 2002-2007 Sebastian Stark
#
# Redistribution and use in source and binary forms, with or without
@@ -63,14 +65,14 @@
"conf: interactively edit current configuration"
self.conf.edit()
- self.dests.useConf(self.conf, self.groupName, stdin='')
+ self.dests.useConf(self.conf, self.groupName)
def do_use(self, rest):
"use <groupname>: use the specified group"
if rest:
self.groupName = rest
- self.dests.useConf(self.conf, self.groupName, stdin='')
+ self.dests.useConf(self.conf, self.groupName)
def do_listgroups(self, rest):
"listgroups: list available groups"
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/lekatnet/tpg.py
^
|
@@ -2,7 +2,7 @@
"""Toy Parser Generator is a lexical and syntactic parser generator
for Python. This generator was born from a simple statement: YACC
-is too complex to use in simple cases (calculators, configuration
+is to complex to use in simple cases (calculators, configuration
files, small programming languages, ...).
TPG can very simply write parsers that are usefull for most every
@@ -43,9 +43,9 @@
from __future__ import generators
-__tpgname__ = 'TPG'
-__version__ = '3.1.1'
-__date__ = '2006-10-07'
+__name__ = 'TPG'
+__version__ = '3.0.0'
+__date__ = '2003-11-11'
__description__ = "A Python parser generator"
__long_description__ = __doc__
__license__ = 'LGPL'
@@ -53,34 +53,27 @@
__email__ = 'christophe.delord@free.fr'
__url__ = 'http://christophe.delord.free.fr/en/tpg/'
-import parser
import re
-import sre_parse
import sys
-try:
- enumerate
-except NameError:
- enumerate = lambda seq: zip(xrange(sys.maxint), seq)
-
_id = lambda x: x
tab = " "*4
class Error(Exception):
- """ Error((line, column), msg)
+ """ Error((line, row), msg)
Error is the base class for TPG exceptions.
Attributes:
- line : line number from where the error has been raised
- column : column number from where the error has been raised
- msg : message associated to the error
+ line : line number from where the error has been raised
+ row : row number from where the error has been raised
+ msg : message associated to the error
"""
- def __init__(self, (line, column), msg):
- self.line, self.column = line, column
+ def __init__(self, (line, row), msg):
+ self.line, self.row = line, row
self.msg = msg
def __str__(self):
- return "%s at line %s, column %s: %s"%(self.__class__.__name__, self.line, self.column, self.msg)
+ return "%s at line %s, row %s: %s"%(self.__class__.__name__, self.line, self.row, self.msg)
class WrongToken(Error):
""" WrongToken()
@@ -91,31 +84,31 @@
Exception.__init__(self)
class LexicalError(Error):
- """ LexicalError((line, column), msg)
+ """ LexicalError((line, row), msg)
LexicalError is raised by lexers when a lexical error is encountered.
Attributes:
- line : line number from where the error has been raised
- column : column number from where the error has been raised
- msg : message associated to the error
+ line : line number from where the error has been raised
+ row : row number from where the error has been raised
+ msg : message associated to the error
"""
pass
class SyntacticError(Error):
- """ SyntacticError((line, column), msg)
+ """ SyntacticError((line, row), msg)
SyntacticError is raised by parsers when they fail.
Attributes:
- line : line number from where the error has been raised
- column : column number from where the error has been raised
- msg : message associated to the error
+ line : line number from where the error has been raised
+ row : row number from where the error has been raised
+ msg : message associated to the error
"""
pass
class SemanticError(Error):
- """ SemanticError(msg)
+ """ SemanticError((line, row), msg)
SemanticError is raised by user actions when an error is detected.
@@ -138,7 +131,7 @@
compile_options : options given to re.compile to compile regular expressions
"""
- word_re = re.compile(r"^\w+$")
+ word_re = re.compile(r"\w+")
def __init__(self, wb, compile_options):
if not wb:
@@ -181,7 +174,7 @@
last_token : last token reached in the input string
pos : position in the input string of the current token
line : line of the current token
- column : column of the current token
+ row : row of the current token
cur_token : current token
"""
@@ -258,11 +251,11 @@
"""
if token is None:
self.pos = 0
- self.line, self.column = 1, 1
+ self.line, self.row = 1, 1
self.cur_token = None
else:
self.pos = token.stop
- self.line, self.column = token.end_line, token.end_column
+ self.line, self.row = token.end_line, token.end_row
self.cur_token = token
def next(self):
@@ -276,7 +269,7 @@
prev_stop = self.cur_token.stop
while True:
if self.pos >= len(self.input):
- self.cur_token = EOFToken(self.line, self.column, self.pos, prev_stop)
+ self.cur_token = EOFToken(self.line, self.row, self.pos, prev_stop)
return self.cur_token
tok = self.token_re.match(self.input, self.pos)
if tok:
@@ -286,17 +279,17 @@
try:
value = value(text)
except WrongToken:
- raise LexicalError((self.line, self.column), "Lexical error in %s"%text)
+ raise LexicalError((self.line, self.row), "Lexical error in %s"%text)
start, stop = tok.span()
self.pos = stop
- tok_line, tok_column = self.line, self.column
+ tok_line, tok_row = self.line, self.row
if '\n' in text:
self.line += text.count('\n')
- self.column = len(text) - text.rfind('\n')
+ self.row = len(text) - text.rfind('\n')
else:
- self.column += len(text)
+ self.row += len(text)
if real_token:
- self.cur_token = Token(name, text, value, tok_line, tok_column, self.line, self.column, start, stop, prev_stop)
+ self.cur_token = Token(name, text, value, tok_line, tok_row, self.line, self.row, start, stop, prev_stop)
if self.pos > self.max_pos:
self.max_pos = self.pos
self.last_token = self.cur_token
@@ -308,21 +301,22 @@
err = self.input[self.pos:nl]
else:
err = self.input[self.pos:self.pos+w]
- raise LexicalError((self.line, self.column), "Lexical error near %s"%err)
+ raise LexicalError((self.line, self.row), "Lexical error near %s"%err)
def token(self):
""" return the current token
"""
return self.cur_token
- def extract(self, start, stop):
+ def __getitem__(self, item):
""" extract text from the input string
Parameters:
- start : token from which the extraction starts
- stop : token where the extraction stops
+ item : slice delimiting the text to extract
+ item.start is the token from which the extraction starts
+ item.stop is the token where the extraction stops
"""
- return self.input[start.start:stop.prev_stop]
+ return self.input[item.start.start:item.stop.prev_stop]
class Lexer(NamedGroupLexer):
r""" Lexer(word_bounded, compile_options)
@@ -344,7 +338,7 @@
last_token : last token reached in the input string
pos : position in the input string of the current token
line : line of the current token
- column : column of the current token
+ row : row of the current token
cur_token : current token
"""
@@ -412,7 +406,7 @@
prev_stop = self.cur_token.stop
while True:
if self.pos >= len(self.input):
- self.cur_token = EOFToken(self.line, self.column, self.pos, prev_stop)
+ self.cur_token = EOFToken(self.line, self.row, self.pos, prev_stop)
return self.cur_token
tok = None
text = ""
@@ -430,17 +424,17 @@
try:
value = value(text)
except WrongToken:
- raise LexicalError((self.line, self.column), "Lexical error in %s"%text)
+ raise LexicalError((self.line, self.row), "Lexical error in %s"%text)
start, stop = tok.span()
self.pos = stop
- tok_line, tok_column = self.line, self.column
+ tok_line, tok_row = self.line, self.row
if '\n' in text:
self.line += text.count('\n')
- self.column = len(text) - text.rfind('\n')
+ self.row = len(text) - text.rfind('\n')
else:
- self.column += len(text)
+ self.row += len(text)
if real_token:
- self.cur_token = Token(name, text, value, tok_line, tok_column, self.line, self.column, start, stop, prev_stop)
+ self.cur_token = Token(name, text, value, tok_line, tok_row, self.line, self.row, start, stop, prev_stop)
if self.pos > self.max_pos:
self.max_pos = self.pos
self.last_token = self.cur_token
@@ -452,7 +446,7 @@
err = self.input[self.pos:nl]
else:
err = self.input[self.pos:self.pos+w]
- raise LexicalError((self.line, self.column), "Lexical error near %s"%err)
+ raise LexicalError((self.line, self.row), "Lexical error near %s"%err)
class CacheNamedGroupLexer(NamedGroupLexer):
r""" CacheNamedGroupLexer(word_bounded, compile_options)
@@ -475,7 +469,7 @@
last_token : last token reached in the input string
pos : position in the input string of the current token
line : line of the current token
- column : column of the current token
+ row : row of the current token
cur_token : current token
"""
@@ -516,7 +510,7 @@
index = self.cur_token.index+1
token = self.cache[index]
self.pos = token.stop
- self.line, self.column = token.line, token.column
+ self.line, self.row = token.line, token.row
self.cur_token = token
if self.pos > self.max_pos:
self.max_pos = self.pos
@@ -546,7 +540,7 @@
last_token : last token reached in the input string
pos : position in the input string of the current token
line : line of the current token
- column : column of the current token
+ row : row of the current token
cur_token : current token
"""
@@ -586,7 +580,7 @@
index = self.cur_token.index+1
token = self.cache[index]
self.pos = token.stop
- self.line, self.column = token.line, token.column
+ self.line, self.row = token.line, token.row
self.cur_token = token
if self.pos > self.max_pos:
self.max_pos = self.pos
@@ -615,7 +609,7 @@
last_token : last token reached in the input string
pos : position in the input string of the current token
line : line of the current token
- column : column of the current token
+ row : row of the current token
cur_token : current token
"""
@@ -682,11 +676,11 @@
"""
if token is None:
self.pos = 0
- self.line, self.column = 1, 1
+ self.line, self.row = 1, 1
self.cur_token = SOFToken()
else:
self.pos = token.stop
- self.line, self.column = token.end_line, token.end_column
+ self.line, self.row = token.line, token.row
self.cur_token = token
self.eat_separators()
self.cur_token.next_start = self.pos
@@ -706,9 +700,9 @@
self.pos = stop
if '\n' in text:
self.line += text.count('\n')
- self.column = len(text) - text.rfind('\n')
+ self.row = len(text) - text.rfind('\n')
else:
- self.column += len(text)
+ self.row += len(text)
done = False
def eat(self, name):
@@ -727,13 +721,13 @@
text = self.input[start:stop]
value = value(text)
self.pos = stop
- tok_line, tok_column = self.line, self.column
+ tok_line, tok_row = self.line, self.row
if '\n' in text:
self.line += text.count('\n')
- self.column = len(text) - text.rfind('\n')
+ self.row = len(text) - text.rfind('\n')
else:
- self.column += len(text)
- self.cur_token = Token(name, text, value, tok_line, tok_column, self.line, self.column, start, stop, prev_stop)
+ self.row += len(text)
+ self.cur_token = Token(name, text, value, tok_line, tok_row, self.line, self.row, start, stop, prev_stop)
if self.pos > self.max_pos:
self.max_pos = self.pos
self.last_token = self.cur_token
@@ -746,53 +740,45 @@
"""
return self.cur_token
- def extract(self, start, stop):
+ def __getitem__(self, item):
""" extract text from the input string
Parameters:
- start : the token from which the extraction starts
- stop : the token where the extraction stops
+ item : slice delimiting the text to extract
+ item.start is the token from which the extraction starts
+ item.stop is the token where the extraction stops
"""
- start = start and start.next_start or 0
- stop = stop and stop.stop or -1
+ start = item.start and item.start.next_start or 0
+ stop = item.stop and item.stop.stop or -1
return self.input[start:stop]
class Token:
- """ Token(name, text, value, line, column, end_line, end_column, start, stop, prev_stop)
+ """ Token(name, text, value, line, row, end_line, end_row, start, stop, prev_stop)
Token object used by lexers
Attributes:
- name : name of the token
- text : text matched by the regular expression
- value : value computed from the text
- line : line of the token in the input string
- column : column of the token in the input string
- end_line : line of the end of the token
- end_column : column of the end of the token
- start : position of the start in the input string of the token
- stop : position of the end in the input string of the token
- prev_stop : position of the end of the previous token
+ name : name of the token
+ text : text matched by the regular expression
+ value : value computed from the text
+ line : line of the token in the input string
+ row : row of the token in the input string
+ end_line : line of the end of the token
+ end_row : row of the end of the token
+ start : position of the start in the input string of the token
+ stop : position of the end in the input string of the token
+ prev_stop : position of the end of the previous token
"""
- def __init__(self, name, text, value, line, column, end_line, end_column, start, stop, prev_stop):
+ def __init__(self, name, text, value, line, row, end_line, end_row, start, stop, prev_stop):
self.name = name
self.text = text
self.value = value
- self.line, self.column = line, column
- self.end_line, self.end_column = end_line, end_column
+ self.line, self.row = line, row
+ self.end_line, self.end_row = end_line, end_row
self.start, self.stop = start, stop
self.prev_stop = prev_stop
- #######################################################
- # row is deprecated : to be removed in a future version
- def warn_row(self): import warnings; warnings.warn("row is deprecated, please use column instead", category=DeprecationWarning)
- def get_row(self): self.warn_row(); return self.column
- def set_row(self): self.warn_row(); return self.column
- def del_row(self): self.warn_row(); del self.column
- row = property(fget=get_row, fset=set_row, fdel=del_row, doc="row")
- #######################################################
-
def match(self, name):
""" return True is the token name is the name of the expected token
@@ -802,29 +788,29 @@
return name == self.name
def __str__(self):
- return "line %s, column %s: %s %s %s"%(self.line, self.column, self.name, self.text, self.value)
+ return "line %s, row %s: %s %s %s"%(self.line, self.row, self.name, self.text, self.value)
class EOFToken(Token):
- """ EOFToken(line, column, pos, prev_stop)
+ """ EOFToken(line, row, pos, prev_stop)
Token for the end of file (end of the input string).
EOFToken is a Token object.
Attributes:
- name : name of the token
- text : text matched by the regular expression
- value : value computed from the text
- line : line of the token in the input string
- column : column of the token in the input string
- end_line : line of the end of the token
- end_column : column of the end of the token
- start : position of the start in the input string of the token
- stop : position of the end in the input string of the token
- prev_stop : position of the end of the previous token
+ name : name of the token
+ text : text matched by the regular expression
+ value : value computed from the text
+ line : line of the token in the input string
+ row : row of the token in the input string
+ end_line : line of the end of the token
+ end_row : row of the end of the token
+ start : position of the start in the input string of the token
+ stop : position of the end in the input string of the token
+ prev_stop : position of the end of the previous token
"""
- def __init__(self, line, column, pos, prev_stop):
- Token.__init__(self, "EOF", "EOF", None, line, column, line, column, pos, pos, prev_stop)
+ def __init__(self, line, row, pos, prev_stop):
+ Token.__init__(self, "EOF", "EOF", None, line, row, line, row, pos, pos, prev_stop)
class SOFToken(Token):
""" SOFToken()
@@ -833,30 +819,21 @@
SOFToken is a Token object.
Attributes:
- name : name of the token
- text : text matched by the regular expression
- value : value computed from the text
- line : line of the token in the input string
- column : column of the token in the input string
- end_line : line of the end of the token
- end_column : column of the end of the token
- start : position of the start in the input string of the token
- stop : position of the end in the input string of the token
- prev_stop : position of the end of the previous token
+ name : name of the token
+ text : text matched by the regular expression
+ value : value computed from the text
+ line : line of the token in the input string
+ row : row of the token in the input string
+ end_line : line of the end of the token
+ end_row : row of the end of the token
+ start : position of the start in the input string of the token
+ stop : position of the end in the input string of the token
+ prev_stop : position of the end of the previous token
"""
def __init__(self):
Token.__init__(self, "SOF", "SOF", None, 1, 1, 1, 1, 0, 0, 0)
-class Py:
- def __init__(self, level=0):
- frame = sys._getframe(1+level)
- self.globals = frame.f_globals
- self.locals = frame.f_locals
- def __getitem__(self, item):
- return eval(item%self, self.globals, self.locals)
-
-
class ParserMetaClass(type):
""" ParserMetaClass is the metaclass of Parser objects.
@@ -880,7 +857,7 @@
class Parser:
# Parser is the base class for parsers.
#
- # This class can not have a doc string otherwise it would be considered as a grammar.
+ # This class can not have a doc string since it would be considered as a grammar.
# The metaclass of this class is ParserMetaClass.
#
# Attributes:
@@ -895,7 +872,7 @@
def __init__(self):
""" Parser is the base class for parsers.
- This class can not have a doc string otherwise it would be considered as a grammar.
+ This class can not have a doc string since it would be considered as a grammar.
The metaclass of this class is ParserMetaClass.
Attributes:
@@ -960,11 +937,11 @@
except WrongToken:
if self.lexer.last_token is None:
last_token = ""
- line, column = 1, 1
+ line, row = 1, 1
else:
last_token = self.lexer.last_token.text
- line, column = self.lexer.last_token.line, self.lexer.last_token.column
- raise SyntacticError((line, column), "Syntax error near %s"%last_token)
+ line, row = self.lexer.last_token.line, self.lexer.last_token.row
+ raise SyntacticError((line, row), "Syntax error near %s"%last_token)
return value
def line(self, token=None):
@@ -979,30 +956,22 @@
return 1
return token.line
- def column(self, token=None):
- """ return the column number of a token
+ def row(self, token=None):
+ """ return the row number of a token
Parameters:
- token : token object. If None, the current token column is returned.
+ token : token object. If None, the current token row is returned.
"""
if token is None:
token =self.lexer.token()
if token is None:
- return 1
- return token.column
-
- #######################################################
- # row is deprecated : to be removed in a future version
- def row(self, token=None):
- import warnings
- warnings.warn("row is deprecated, please use column instead.", category=DeprecationWarning)
- return self.column(token)
- #######################################################
+ return 2
+ return token.row
def mark(self):
""" return the current token
- This can be used to get the line or column number of a token
+ This can be used to get the line or row number of a token
or to extract text between two tokens.
"""
return self.lexer.token()
@@ -1014,7 +983,7 @@
start : token object as returned by mark
stop : token object as returned by mark
"""
- return self.lexer.extract(start, stop)
+ return self.lexer[start:stop]
def check(self, cond):
""" check a condition and backtrack when it is False
@@ -1035,52 +1004,14 @@
raise SemanticError(msg)
class VerboseParser(Parser):
- # VerboseParser is the base class for debugging parsers.
- #
- # This class can not have a doc string otherwise it would be considered as a grammar.
- # The metaclass of this class is ParserMetaClass.
- # It extends the Parser class to log the activity of the lexer.
- #
- # Attributes:
- # lexer : lexer build from the grammar
- # verbose : level of information
- # 0 : no information
- # 1 : print tokens successfully matched
- # 2 : print tokens matched and not matched
- #
- # Methods added to the generated parsers:
- # init_lexer(self) : return a lexer object to scan the tokens defined by the grammar
- # <rule> : each rule is translated into a method with the same name
verbose = 1
def __init__(self):
- """ VerboseParser is the base class for debugging parsers.
-
- This class can not have a doc string otherwise it would be considered as a grammar.
- The metaclass of this class is ParserMetaClass.
- It extends the Parser class to log the activity of the lexer.
-
- Attributes:
- lexer : lexer build from the grammar
- verbose : level of information
- 0 : no information
- 1 : print tokens successfully matched
- 2 : print tokens matched and not matched
-
- Methods added to the generated parsers:
- init_lexer(self) : return a lexer object to scan the tokens defined by the grammar
- <rule> : each rule is translated into a method with the same name
- """
Parser.__init__(self)
self.eatcnt = 0
def eat(self, name):
- """ eat the current token if it matches the expected token
-
- Parameters:
- name : name of the expected token
- """
self.eatcnt += 1
token = self.lexer.token()
try:
@@ -1094,13 +1025,6 @@
raise
def eatCSL(self, name):
- """ eat the current token if it matches the expected token
-
- This method replaces eat for context sensitive lexers.
-
- Parameters:
- name : name of the expected token
- """
self.eatcnt += 1
try:
value = Parser.eatCSL(self, name)
@@ -1110,30 +1034,15 @@
return value
except WrongToken:
if self.verbose >= 2:
- token = Token("???", self.lexer.input[self.lexer.pos:self.lexer.pos+10].replace('\n', ' '), "???", self.lexer.line, self.lexer.column, self.lexer.line, self.lexer.column, self.lexer.pos, self.lexer.pos, self.lexer.pos)
+ token = Token("???", self.lexer.input[self.lexer.pos:self.lexer.pos+10].replace('\n', ' '), "???", self.lexer.line, self.lexer.row, self.lexer.line, self.lexer.row, self.lexer.pos, self.lexer.pos, self.lexer.pos)
print self.token_info(token, "!=", name)
raise
def parse(self, axiom, input, *args, **kws):
- """ parse a string starting from a given axiom
-
- Parameters:
- axiom : rule name where the parser starts
- input : input string to parse
- *args : argument list to pass to START
- **kws : argument dictionnary to pass to START
- """
self.axiom = axiom
return Parser.parse(self, axiom, input, *args, **kws)
def token_info(self, token, op, expected):
- """ return information about a token
-
- Parameters:
- token : token read by the lexer
- op : result of the comparison made by the lexer (== or !=)
- expected : name of the expected token
- """
eatcnt = self.eatcnt
callernames = []
stackdepth = 0
@@ -1143,16 +1052,14 @@
name = sys._getframe(stackdepth+1).f_code.co_name
if len(callernames) < 10:
callernames.insert(0, name)
- callernames = '.'.join(callernames)
- found = "(%d,%d) %s %s"%(token.line, token.column, token.name, token.text)
- return "[%3d][%2d]%s: %s %s %s"%(eatcnt, stackdepth, callernames, found, op, expected)
+ found = "(%d,%d) %s %s"%(token.line, token.row, token.name, token.text)
+ return "[%3d][%2d]%s: %s %s %s"%(eatcnt, stackdepth, '.'.join(callernames), found, op, expected)
blank_line_re = re.compile("^\s*$")
indent_re = re.compile("^\s*")
+# This class contains some TPG classes to make the parsers usable inside and outside the tpg module
class tpg:
- """ This class contains some TPG classes to make the parsers usable inside and outside the tpg module
- """
NamedGroupLexer = NamedGroupLexer
Lexer = Lexer
CacheNamedGroupLexer = CacheNamedGroupLexer
@@ -1165,43 +1072,14 @@
class TPGParser(tpg.Parser):
__grammar__ = r"""
- # This class parses TPG grammar
- # and generate the Python source and compiled code for the parser
-
set lexer = NamedGroupLexer
- set lexer_verbose
separator spaces '\s+' ;
- separator comment '\#.*' ;
+ separator comment '#.*' ;
- token string '''
- "{3} [^"\\]*
- (?: (?: \\. | "(?!"") )
- [^"\\]*
- )*
- "{3}
- | " [^"\\\n]*
- (?: \\. [^"\\\n]* )*
- "
- | '{3} [^'\\]*
- (?: (?: \\. | '(?!'') )
- [^'\\]*
- )*
- '{3}
- | ' [^'\\\n]*
- (?: \\. [^'\\\n]* )*
- '
- ''' ;
-
- token code '''
- \{\{
- ( \}? [^\}]+ )*
- \}\}
- | \$ [^\$\n]* \$
- | \$ .*\n
- ( [ \t]* \$ .*\n )*
- ''' $ self.Code
- token ident '\w+' ;
+ token string "\"(\\.|[^\"\\]+)*\"|'(\\.|[^'\\]+)*'" ;
+ token code "\{\{(\}?[^\}]+)*\}\}|\$[^\$\n]*\$|\$.*\n([ \t]*\$.*\n)*" $ self.Code
+ token ident "\w+" ;
token lcbra '\{' ;
token rcbra '\}' ;
token star2 '\*\*' ;
@@ -1233,7 +1111,7 @@
| 'token' $ token_type = self.DefToken
)
ident/name ':'?
- @t string/expr $ self.re_check(expr, t)
+ string/expr
( PY_EXPR/code ';'?
| ';' $ code = None
)
@@ -1247,26 +1125,24 @@
RULE/$self.Rule(head, body)$ -> HEAD/head '->' OR_EXPR/body ';' ;
- #HEAD/$self.Symbol(name, args, ret)$ -> ident/name OPT_ARGS/args RET/ret ;
- HEAD/$self.Symbol(name, args, ret)$ -> ident/name OPT_ARGS/args RET<$self.PY_Ident(name)$>/ret ;
+ HEAD/$self.Symbol(name, args, ret)$ -> ident/name OPT_ARGS/args RET/ret ;
OR_EXPR/$self.balance(or_expr)$ ->
AND_EXPR/a $ or_expr = [a]
- ( check $ not or_expr[-1].empty() $
- '\|' AND_EXPR/a $ or_expr.append(a)
- )*
+ ( '\|' AND_EXPR/a $ or_expr.append(a)
+ )*
;
AND_EXPR/$and_expr$ ->
$ and_expr = self.And()
( ATOM_EXPR/a REP<a>/a $ and_expr.append(a)
- )*
+ )* $ if len(and_expr) == 1: and_expr = and_expr[0]
;
ATOM_EXPR/a ->
SYMBOL/a
| INLINE_TOKEN/a
- | @t code/a $ self.code_check(a, t)
+ | code/a
| '\(' OR_EXPR/a '\)'
| 'check' PY_EXPR/cond $ a = self.Check(cond)
| 'error' PY_EXPR/msg $ a = self.Error(msg)
@@ -1286,13 +1162,9 @@
)?
;
- #SYMBOL/$self.Symbol(name, args, ret)$ -> ident/name OPT_ARGS/args RET/ret ;
- SYMBOL/$self.Symbol(name, args, ret)$ -> ident/name OPT_ARGS/args RET<$self.PY_Ident(name)$>/ret ;
+ SYMBOL/$self.Symbol(name, args, ret)$ -> ident/name OPT_ARGS/args RET/ret ;
- INLINE_TOKEN/$self.InlineToken(expr, ret)$ ->
- @t string/expr $ self.re_check(expr, t)
- RET/ret
- ;
+ INLINE_TOKEN/$self.InlineToken(expr, ret)$ -> string/expr RET/ret ;
OPT_ARGS/args -> ARGS/args | $ args = self.Args() $ ;
@@ -1313,8 +1185,7 @@
| '\*\*' ident/name $ a = self.PY_KeywordArgumentList(name)
;
- #RET/ret -> '/' PY_EXPR/ret | $ ret = None $ ;
- RET<ret=None>/ret -> ( '/' PY_EXPR/ret )? ;
+ RET/ret -> '/' PY_EXPR/ret | $ ret = None $ ;
PY_EXPR/expr ->
ident/name $ expr = self.PY_Ident(name)
@@ -1325,7 +1196,7 @@
"""
def init_lexer(self):
- lexer = tpg.NamedGroupLexer(True, tpg.re.VERBOSE)
+ lexer = tpg.NamedGroupLexer(True, 0)
lexer.def_token('_tok_1', r'set')
lexer.def_token('_tok_2', r'=')
lexer.def_token('_tok_3', r'separator')
@@ -1346,34 +1217,10 @@
lexer.def_token('_tok_18', r'>')
lexer.def_token('_tok_19', r'/')
lexer.def_separator('spaces', r'\s+')
- lexer.def_separator('comment', r'\#.*')
- lexer.def_token('string', r'''
- "{3} [^"\\]*
- (?: (?: \\. | "(?!"") )
- [^"\\]*
- )*
- "{3}
- | " [^"\\\n]*
- (?: \\. [^"\\\n]* )*
- "
- | '{3} [^'\\]*
- (?: (?: \\. | '(?!'') )
- [^'\\]*
- )*
- '{3}
- | ' [^'\\\n]*
- (?: \\. [^'\\\n]* )*
- '
- ''')
- lexer.def_token('code', r'''
- \{\{
- ( \}? [^\}]+ )*
- \}\}
- | \$ [^\$\n]* \$
- | \$ .*\n
- ( [ \t]* \$ .*\n )*
- ''', self.Code)
- lexer.def_token('ident', r'\w+')
+ lexer.def_separator('comment', r'#.*')
+ lexer.def_token('string', r"\"(\\.|[^\"\\]+)*\"|'(\\.|[^'\\]+)*'")
+ lexer.def_token('code', r"\{\{(\}?[^\}]+)*\}\}|\$[^\$\n]*\$|\$.*\n([ \t]*\$.*\n)*", self.Code)
+ lexer.def_token('ident', r"\w+")
lexer.def_token('lcbra', r'\{')
lexer.def_token('rcbra', r'\}')
lexer.def_token('star2', r'\*\*')
@@ -1437,9 +1284,7 @@
self.eat('_tok_5') # ':'
except tpg.WrongToken:
self.lexer.back(_p2)
- t = self.mark()
expr = self.eat('string')
- self.re_check(expr, t)
_p3 = self.lexer.token()
try:
code = self.PY_EXPR()
@@ -1479,7 +1324,7 @@
r""" HEAD -> ident OPT_ARGS RET """
name = self.eat('ident')
args = self.OPT_ARGS()
- ret = self.RET(self.PY_Ident(name))
+ ret = self.RET()
return self.Symbol(name, args, ret)
def OR_EXPR(self, ):
@@ -1489,7 +1334,6 @@
while True:
_p1 = self.lexer.token()
try:
- self.check(not or_expr[-1].empty())
self.eat('_tok_8') # '\|'
a = self.AND_EXPR()
or_expr.append(a)
@@ -1510,6 +1354,7 @@
except tpg.WrongToken:
self.lexer.back(_p1)
break
+ if len(and_expr) == 1: and_expr = and_expr[0]
return and_expr
def ATOM_EXPR(self, ):
@@ -1524,9 +1369,7 @@
a = self.INLINE_TOKEN()
except tpg.WrongToken:
self.lexer.back(_p1)
- t = self.mark()
a = self.eat('code')
- self.code_check(a, t)
except tpg.WrongToken:
self.lexer.back(_p1)
try:
@@ -1600,14 +1443,12 @@
r""" SYMBOL -> ident OPT_ARGS RET """
name = self.eat('ident')
args = self.OPT_ARGS()
- ret = self.RET(self.PY_Ident(name))
+ ret = self.RET()
return self.Symbol(name, args, ret)
def INLINE_TOKEN(self, ):
r""" INLINE_TOKEN -> string RET """
- t = self.mark()
expr = self.eat('string')
- self.re_check(expr, t)
ret = self.RET()
return self.InlineToken(expr, ret)
@@ -1674,14 +1515,15 @@
a = self.PY_KeywordArgumentList(name)
return a
- def RET(self, ret=None):
- r""" RET -> ('/' PY_EXPR)? """
+ def RET(self, ):
+ r""" RET -> '/' PY_EXPR | """
_p1 = self.lexer.token()
try:
self.eat('_tok_19') # '/'
ret = self.PY_EXPR()
except tpg.WrongToken:
self.lexer.back(_p1)
+ ret = None
return ret
def PY_EXPR(self, ):
@@ -1712,19 +1554,6 @@
else:
self.env = {}
- def re_check(self, expr, tok):
- try:
- sre_parse.parse(eval('r'+expr))
- except Exception, e:
- raise LexicalError((tok.line, tok.column), "Invalid regular expression: %s (%s)"%(expr, e))
-
- def code_check(self, code, tok):
- try:
- parser.suite(code.code)
- except Exception, e:
- erroneous_code = "\n".join([ "%2d: %s"%(i+1, l) for (i, l) in enumerate(code.code.splitlines()) ])
- raise LexicalError((tok.line, tok.column), "Invalid Python code (%s): \n%s"%(e, erroneous_code))
-
class Options:
option_dict = {
# Option name Accepted values Default value
@@ -1771,15 +1600,7 @@
]
return "+".join([ "tpg.re.%s"%opt for opt in options if opt ]) or 0
- class Empty:
- def empty(self):
- return True
-
- class NotEmpty:
- def empty(self):
- return False
-
- class Code(NotEmpty):
+ class Code:
def __init__(self, code):
if code.startswith('$'):
if code.endswith('$'):
@@ -1866,12 +1687,11 @@
return self.head.name, [
self.head.gen_def(),
tab + 'r""" %s -> %s """'%(self.head.gen_doc(self), self.body.gen_doc(self)),
- self.head.gen_init_ret(tab),
self.body.gen_code(tab, counters, None),
self.head.gen_ret(tab),
]
- class Symbol(NotEmpty):
+ class Symbol:
def __init__(self, name, args, ret):
self.name = name
self.args = args
@@ -1885,8 +1705,6 @@
raise SemanticError("Token %s can not have arguments"%self.name)
def gen_def(self):
return "def %s(self, %s):"%(self.name, self.args.gen_code())
- def gen_init_ret(self, indent):
- return self.ret.gen_code() == self.name and indent + "%s = None"%(self.name) or ()
def gen_ret(self, indent):
return self.ret and indent + "return %s"%self.ret.gen_code() or ()
def gen_code(self, indent, counters, pos):
@@ -1903,7 +1721,7 @@
def gen_doc(self, parent):
return self.name
- class InlineToken(NotEmpty):
+ class InlineToken:
def __init__(self, expr, ret):
self.expr = expr
self.ret = ret
@@ -1953,11 +1771,6 @@
return "**%s"%self.name
class And(list):
- def empty(self):
- for a in self:
- if not a.empty():
- return False
- return True
def get_inline_tokens(self):
for a in self:
for token in a.get_inline_tokens():
@@ -1978,7 +1791,7 @@
docs.append(doc)
return " ".join(docs)
- class Or(NotEmpty):
+ class Or:
def __init__(self, a, b):
self.a = a
self.b = b
@@ -2013,7 +1826,7 @@
m = len(xs)//2
return self.Or(self.balance(xs[:m]), self.balance(xs[m:]))
- class Rep(NotEmpty):
+ class Rep:
def __init__(self, a, min, max):
self.a = a
self.min = min
@@ -2101,7 +1914,7 @@
rep = "{%s,%s}"%(min, max)
return "%s%s"%(doc, rep)
- class Check(NotEmpty):
+ class Check:
def __init__(self, cond):
self.cond = cond
def get_inline_tokens(self):
@@ -2114,7 +1927,7 @@
def gen_code(self, indent, counters, pos):
return indent + "self.check(%s)"%self.cond.gen_code()
- class Error(NotEmpty):
+ class Error:
def __init__(self, msg):
self.msg = msg
def get_inline_tokens(self):
@@ -2127,7 +1940,7 @@
def gen_code(self, indent, counters, pos):
return indent + "self.error(%s)"%self.msg.gen_code()
- class Mark(NotEmpty):
+ class Mark:
def __init__(self, mark):
self.mark = mark
def get_inline_tokens(self):
@@ -2154,9 +1967,17 @@
def make_code(self, attribute, *source):
source = "".join(self.flatten_nl(*source))
- local_namespace = {}
- exec source in self.env, local_namespace
- code = local_namespace[attribute]
+ try:
+ old_code = self.env[attribute]
+ except KeyError:
+ old_code_exists = False
+ else:
+ old_code_exists = True
+ exec source in self.env
+ code = self.env[attribute]
+ del self.env[attribute]
+ if old_code_exists:
+ self.env[attribute] = old_code
return attribute, source, code
def gen(self, options, tokens, rules):
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/setup.py
^
|
@@ -1,4 +1,6 @@
+# $Id: setup.py 260 2005-04-10 22:54:35Z stark $
+
from distutils.core import setup
setup(
|
[-]
[+]
|
Added |
tentakel-2.2.1.tar.gz/py/setup.py.orig
^
|
@@ -0,0 +1,26 @@
+
+# $Id: setup.py 260 2005-04-10 22:54:35Z stark $
+
+from distutils.core import setup
+
+setup(
+ name = "tentakel",
+ version = "2.2.1",
+ description = "distributed command execution",
+ url = "http://tentakel.biskalar.de/",
+ author = "Sebastian Stark, Marlon Berlin",
+ author_email = "tentakel@biskalar.de, imaginat@users.sourceforge.net",
+ maintainer = "Sebastian Stark",
+ maintainer_email = "tentakel@biskalar.de",
+ license = "BSD",
+ platforms = "All that support threading",
+
+ packages = ["lekatnet", "lekatnet.plugins"],
+ scripts = ["tentakel"],
+ data_files = [ ("share/man/man1", ["../tentakel.1"]),
+ ("share/doc/tentakel-2.2", ["../tentakel.conf.example",
+ "../README",
+ "../TODO",
+ "../PLUGINS",
+ "../tentakel.1.html"]) ]
+)
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/py/tentakel
^
|
@@ -1,5 +1,7 @@
#!/usr/bin/python
+# $Id: tentakel 275 2007-03-04 20:56:08Z stark $
+#
# Copyright (c) 2002-2007 Sebastian Stark
#
# Redistribution and use in source and binary forms, with or without
@@ -109,12 +111,7 @@
# batch mode: execute command
if command:
- if sys.stdin.isatty():
- stdin = ''
- else:
- stdin = sys.stdin.read()
- sys.stdin.close()
- dests = remote.RemoteCollator(conf, groupName, stdin)
+ dests = remote.RemoteCollator(conf, groupName)
dests.execAll(command)
dests.displayAll()
else:
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/ssh_running.py
^
|
@@ -1,5 +1,7 @@
#!/usr/bin/env python2.4
#
+# $Id: ssh_running.py 278 2007-03-04 21:30:26Z stark $
+#
# Dynamic tentakel hostlist. Return all hosts from GROUP that have
# sshd running on port 22.
#
|
[-]
[+]
|
Added |
tentakel-2.2.1.tar.gz/svn2cl.xsl
^
|
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+
+ svn2cl.xsl - xslt stylesheet for converting svn log to a normal
+ changelog
+
+ This file is based on several implementations of this conversion
+ that I was not completely happy with and some other common
+ xslt constructs found on the web.
+
+ Copyright (C) 2004 Arthur de Jong.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<!--
+ TODO
+ - make external lookups of author names possible
+ - find a place for revision numbers
+ - mark deleted files as such
+ - combine paths
+ - make stripping of characters nicer
+-->
+
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/1999/xhtml">
+
+ <xsl:output
+ method="text"
+ encoding="iso-8859-15"
+ media-type="text/plain"
+ omit-xml-declaration="yes"
+ standalone="yes"
+ indent="no" />
+
+ <xsl:strip-space elements="*" />
+
+ <!-- the prefix of pathnames to strip -->
+ <xsl:param name="strip-prefix" select="'/'" />
+
+ <!-- format one entry from the log -->
+ <xsl:template match="logentry">
+ <!-- date -->
+ <xsl:apply-templates select="date" />
+ <!-- two spaces -->
+ <xsl:text> </xsl:text>
+ <!-- author's name -->
+ <xsl:apply-templates select="author" />
+ <!-- two newlines -->
+ <xsl:text>
+
+</xsl:text>
+ <!-- the log message -->
+ <xsl:apply-templates select="msg" />
+ <!-- another two newlines -->
+ <xsl:text>
+
+</xsl:text>
+ </xsl:template>
+
+ <!-- format date -->
+ <xsl:template match="date">
+ <xsl:variable name="date" select="normalize-space(.)" />
+ <xsl:value-of select="substring($date,1,10)" />
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="substring($date,12,5)" />
+ </xsl:template>
+
+ <!-- format author -->
+ <xsl:template match="author">
+ <xsl:value-of select="normalize-space(.)" />
+ </xsl:template>
+
+ <!-- format log message -->
+ <xsl:template match="msg">
+ <!-- first line is indented (other indents are done in wrap template) -->
+ <xsl:text> * </xsl:text>
+ <!-- get paths string -->
+ <xsl:variable name="paths">
+ <xsl:apply-templates select="../paths" />
+ </xsl:variable>
+ <!-- print the paths and message nicely wrapped -->
+ <xsl:call-template name="wrap">
+ <xsl:with-param name="txt" select="concat($paths,': ',normalize-space(.))" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- present paths nice -->
+ <xsl:template match="paths">
+ <xsl:for-each select="path">
+ <xsl:sort select="normalize-space(.)" data-type="text" />
+ <xsl:if test="not(position()=1)">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ <xsl:variable name="p1" select="normalize-space(.)" />
+ <xsl:variable name="p2">
+ <xsl:choose>
+ <xsl:when test="starts-with($p1,'/')">
+ <xsl:value-of select="substring($p1,2)" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$p1" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="p3">
+ <xsl:choose>
+ <xsl:when test="starts-with($p2,$strip-prefix)">
+ <xsl:value-of select="substring($p2,1+string-length($strip-prefix))" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$p2" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="p4">
+ <xsl:choose>
+ <xsl:when test="starts-with($p3,'/')">
+ <xsl:value-of select="substring($p3,2)" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$p3" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$p4 = ''">
+ <xsl:value-of select="'.'" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$p4" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+
+ <!-- string-wrapping template -->
+ <xsl:template name="wrap">
+ <xsl:param name="txt" />
+ <xsl:variable name="linelen" select="67" />
+ <xsl:choose>
+ <xsl:when test="(string-length($txt) < $linelen) or not(contains($txt,' '))">
+ <!-- this is easy, nothing to do -->
+ <xsl:value-of select="$txt" />
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- find the first line -->
+ <xsl:variable name="tmp" select="substring($txt,1,$linelen)" />
+ <xsl:variable name="line">
+ <xsl:choose>
+ <xsl:when test="contains($tmp,' ')">
+ <xsl:call-template name="find-line">
+ <xsl:with-param name="txt" select="$tmp" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($txt,' ')" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- print line and newline -->
+ <xsl:value-of select="$line" />
+ <xsl:text>
+ </xsl:text>
+ <!-- wrap the rest of the text -->
+ <xsl:call-template name="wrap">
+ <xsl:with-param name="txt" select="normalize-space(substring($txt,string-length($line)+1))" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- template to trim line to contain space as last char -->
+ <xsl:template name="find-line">
+ <xsl:param name="txt" />
+ <xsl:choose>
+ <xsl:when test="substring($txt,string-length($txt),1) = ' '">
+ <xsl:value-of select="normalize-space($txt)" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="find-line">
+ <xsl:with-param name="txt" select="substring($txt,1,string-length($txt)-1)" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/tentakel.1
^
|
@@ -1,5 +1,7 @@
.\"
-.\" Copyright (c) 2002-2007 Sebastian Stark
+.\" $Id: tentakel.1 266 2005-04-22 07:21:16Z stark $
+.\"
+.\" Copyright (c) 2002, 2003, 2004, 2005 Sebastian Stark
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -22,7 +24,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.fam P
-.TH TENTAKEL 1 "2007 March 13"
+.TH TENTAKEL 1 "2005 April 22"
.SH NAME
tentakel \- distributed command execution
.SH SYNOPSIS
@@ -156,10 +158,7 @@
expanded to the name of the destination (ip or hostname).
.TP
.B o
-expanded to the standard output of the remote command.
-.TP
-.B e
-expanded to the standard error of the remote command.
+expanded to the output of the remote command.
.TP
.B s
expanded to the exit status of the remote command.
@@ -169,7 +168,7 @@
This includes the time for network overhead etc.
.LP
.RE
-The default format is \f(CR"### %d(stat: %s, dur(s): %t):\\n%e%o\\n"\fP.
+The default format is \f(CR"### %d(stat: %s, dur(s): %t):\\n%o\\n"\fP.
.RE
.TP
.B maxparallel
@@ -332,7 +331,7 @@
.BR uptime (1)
command on all hosts defined in group
.I myGroup.
-The output of each host is printed according
+The whole output (even stderr) of each host is printed according
to the format string.
.SH FILES
.PD 0
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/tentakel.1.html
^
|
@@ -1,5 +1,5 @@
<!-- Creator : groff version 1.18.1 -->
-<!-- CreationDate: Tue Mar 13 00:34:42 2007 -->
+<!-- CreationDate: Fri Apr 22 09:24:39 2005 -->
<html>
<head>
<meta name="generator" content="groff -Thtml, see www.gnu.org">
@@ -372,20 +372,7 @@
<td width="8%"></td>
<td width="55%">
-<p>expanded to the standard output of the remote
-command.</p>
-</td>
-<tr valign="top" align="left">
-<td width="32%"></td>
-<td width="2%">
-
-<p><b>e</b></p>
-</td>
-<td width="8%"></td>
-<td width="55%">
-
-<p>expanded to the standard error of the remote
-command.</p>
+<p>expanded to the output of the remote command.</p>
</td>
<tr valign="top" align="left">
<td width="32%"></td>
@@ -419,7 +406,7 @@
<td width="20%"></td>
<td width="79%">
<p>The default format is <tt>"### %d(stat: %s, dur(s):
-%t):\n%e%o\n"</tt>.</p></td>
+%t):\n%o\n"</tt>.</p></td>
</table>
<!-- INDENTATION -->
<table width="100%" border=0 rules="none" frame="void"
@@ -767,11 +754,11 @@
cols="4" cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
-<td width="7%">
+<td width="5%">
<p><b>conf</b></p>
</td>
-<td width="2%"></td>
+<td width="4%"></td>
<td width="77%">
<p>Change the current configuration interactively. The
@@ -784,11 +771,11 @@
</td>
<tr valign="top" align="left">
<td width="11%"></td>
-<td width="7%">
+<td width="5%">
<p><b>quit</b></p>
</td>
-<td width="2%"></td>
+<td width="4%"></td>
<td width="77%">
<p>Exit tentakel. The same can be done by pressing
@@ -817,8 +804,9 @@
<p><tt>$ tentakel -g myGroup uptime</tt></p>
<!-- INDENTATION -->
<p>This command executes the <b>uptime</b>(1) command on all
-hosts defined in group <i>myGroup.</i> The output of each
-host is printed according to the format string.</p>
+hosts defined in group <i>myGroup.</i> The whole output
+(even stderr) of each host is printed according to the
+format string.</p>
</td>
</table>
<a name="FILES"></a>
|
[-]
[+]
|
Changed |
tentakel-2.2.1.tar.gz/tentakel.conf.example
^
|
@@ -1,3 +1,5 @@
+# $Id: tentakel.conf.example 267 2005-07-07 13:32:21Z stark $
+
# Example configuration file for tentakel
# first section: global parameters
|
|
Added |
tentakel-2.2.1.tgz.orig
^
|
[-]
[+]
|
Deleted |
tentakel-2.2.1.tgz/CREDITS
^
|
@@ -1,13 +0,0 @@
-Marlon Berlin
-Christoph Marquardt
-Kevin Glueck
-Taylor Dondich
-Munish Chopra
-Antoine Ginies
-Dag Wieers
-Chris Bainbridge
-Mason J. Katz
-Pascal Bleser
-Damon P. Cortesi
-Yves Jaeger
-Andre Noll
|
[-]
[+]
|
Deleted |
tentakel-2.2.1.tgz/execwrapper.c
^
|
@@ -1,141 +0,0 @@
-/*
-Copyright (c) 2007 Andre Noll
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ANDRE NOLL
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/select.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-
-static int signal_pipe[2];
-
-static int tv_diff(const struct timeval *b, const struct timeval *a, struct timeval *diff)
-{
- int ret = 1;
-
- if ((b->tv_sec < a->tv_sec) ||
- ((b->tv_sec == a->tv_sec) && (b->tv_usec < a->tv_usec))) {
- const struct timeval *tmp = a;
- a = b;
- b = tmp;
- ret = -1;
- }
- if (!diff)
- return ret;
- diff->tv_sec = b->tv_sec - a->tv_sec;
- if (b->tv_usec < a->tv_usec) {
- diff->tv_sec--;
- diff->tv_usec = 1000 * 1000 - a->tv_usec + b->tv_usec;
- } else
- diff->tv_usec = b->tv_usec - a->tv_usec;
- return ret;
-}
-
-static void signal_handler(int s)
-{
- write(signal_pipe[1], &s, sizeof(int));
-}
-
-
-void signal_init_or_die(void)
-{
- if (pipe(signal_pipe))
- exit(EXIT_FAILURE);
- if (signal(SIGCHLD, &signal_handler) == SIG_ERR)
- exit(EXIT_FAILURE);
-}
-
-static int reap_child(pid_t child_pid)
-{
- int status;
- pid_t pid;
-
- do
- pid = waitpid(child_pid, &status, 0);
- while (pid == -1 && errno == EINTR);
- if (pid <= 0) /* oops, that should never happen */
- return EXIT_FAILURE;
- if (WIFEXITED(status))
- printf("child %i exited. Exit status: %i\n", (int)pid,
- WEXITSTATUS(status));
- else if (WIFSIGNALED(status))
- printf("child %i was killed by signal %i\n", (int)pid,
- WTERMSIG(status));
- else
- printf("child %i terminated abormally\n", (int)pid);
- return pid;
-}
-
-
-int main(int argc, char **argv)
-{
- int ret, err, expired = 0;
- pid_t pid;
- struct timeval start, timeout = {.tv_sec = 0}, tv;
-
- if (argc < 3)
- exit(EXIT_FAILURE);
- timeout.tv_sec = atoi(argv[1]);
- argv[1] = strdup(argv[2]);
- pid = fork();
- if (pid < 0)
- exit(EXIT_FAILURE);
- signal_init_or_die();
- if (!pid) {
- close(signal_pipe[0]);
- close(signal_pipe[1]);
- execvp(argv[1], argv + 2);
- _exit(EXIT_FAILURE);
- }
- free(argv[1]);
- gettimeofday(&start, NULL);
- tv = timeout;
- do {
- fd_set rfds;
- struct timeval diff, now;
-
- FD_ZERO(&rfds);
- FD_SET(signal_pipe[0], &rfds);
- ret = select(signal_pipe[0] + 1, &rfds, NULL, NULL, &tv);
- err = errno;
- gettimeofday(&now, NULL);
- tv_diff(&start, &now, &diff);
- if (tv_diff(&diff, &timeout, &tv) > 0)
- expired = 1;
- } while ((!ret && !expired) || (ret < 0 && err == EINTR));
- if (ret <= 0)
- kill(pid, SIGINT);
- ret = reap_child(pid);
- close(signal_pipe[0]);
- close(signal_pipe[1]);
- return ret;
-}
|