[SCM] UNNAMED PROJECT branch, master, updated. debian/6.1.1c-1-35-ged85064

Picca Frédéric-Emmanuel picca at synchrotron-soleil.fr
Sat Mar 13 13:44:14 UTC 2010


The following commit has been merged in the master branch:
commit ed850647d0469ce21e2c1548ec1354493154615a
Author: Picca Frédéric-Emmanuel <picca at synchrotron-soleil.fr>
Date:   Sat Mar 13 14:20:28 2010 +0100

    * work in progress with tango_admin

diff --git a/debian/changelog b/debian/changelog
index d5de690..f0e0a0e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,6 +5,7 @@ tango (7.1.1~dfsg-1) unstable; urgency=low
   * update to debian-policy 3.8.3 (nothing to do)
   * switch to the 3.0 (quilt) source format
   * starter install the right device in the database during installation.
+  * add the tango_admin program from the CVS upstream
 
  -- Picca Frédéric-Emmanuel <picca at synchrotron-soleil.fr>  Tue, 01 Dec 2009 15:59:16 +0100
 
diff --git a/debian/control b/debian/control
index d6fd63b..d5901e3 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,13 @@ Source: tango
 Section: science
 Priority: extra
 Maintainer: Picca Frédéric-Emmanuel <picca at synchrotron-soleil.fr>
-Build-Depends: debhelper (>= 7.0.50), po-debconf, autotools-dev, doxygen, libcos4-dev, libmysqlclient-dev
+Build-Depends: debhelper (>= 7.0.50),
+	       po-debconf,
+	       autotools-dev,
+	       autoconf-archive,
+	       doxygen,
+	       libcos4-dev,
+	       libmysqlclient-dev
 Standards-Version: 3.8.3
 Homepage: http://www.tango-controls.org
 Vcs-Git: git://git.debian.org/git/debian-science/packages/tango.git
@@ -11,7 +17,8 @@ Vcs-Browser: http://git.debian.org/?p=debian-science/packages/tango.git
 Package: liblog4tango4
 Section: libs
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
+Depends: ${shlibs:Depends},
+	 ${misc:Depends}
 Description: logging for TANGO - shared library
  Log for TANGO is a library of C++ classes for flexible logging to files,
  syslog and other destinations. It is modeled after the Log for
@@ -24,7 +31,8 @@ Description: logging for TANGO - shared library
 Package: liblog4tango4-dev
 Section: libdevel
 Architecture: any
-Depends: liblog4tango4 (= ${binary:Version}), ${misc:Depends}
+Depends: liblog4tango4 (= ${binary:Version}),
+	 ${misc:Depends}
 Description: logging for TANGO - development library
  Log for TANGO is a library of C++ classes for flexible logging to files,
  syslog and other destinations. It is modeled after the Log for
@@ -37,7 +45,8 @@ Package: liblog4tango4-dbg
 Section: debug
 Architecture: any
 Priority: extra
-Depends: liblog4tango4 (= ${binary:Version}), ${misc:Depends}
+Depends: liblog4tango4 (= ${binary:Version}),
+	 ${misc:Depends}
 Description: logging for TANGO - debug library
  Log for TANGO is a library of C++ classes for flexible logging to files,
  syslog and other destinations. It is modeled after the Log for
@@ -61,7 +70,9 @@ Description: logging for TANGO - documentation
 Package: libtango7
 Section: libs
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
+Depends: ${shlibs:Depends},
+	 ${misc:Depends},
+	 tango-common
 Description: TANGO distributed control system - shared library
  TANGO is an object-oriented distributed control system using CORBA. In
  TANGO all objects are representations of devices, which can be on the
@@ -82,7 +93,8 @@ Description: TANGO distributed control system - shared library
 Package: libtango7-dev
 Section: libdevel
 Architecture: any
-Depends: libtango7 (= ${binary:Version}), ${misc:Depends}
+Depends: libtango7 (= ${binary:Version}),
+	 ${misc:Depends}
 Description: TANGO distributed control system - development library
  TANGO is an object-oriented distributed control system using CORBA. In
  TANGO all objects are representations of devices, which can be on the
@@ -104,7 +116,8 @@ Package: libtango7-dbg
 Section: debug
 Architecture: any
 Priority: extra
-Depends: libtango7 (= ${binary:Version}), ${misc:Depends}
+Depends: libtango7 (= ${binary:Version}),
+	 ${misc:Depends}
 Description: TANGO distributed control system - debug library
  TANGO is an object-oriented distributed control system using CORBA. In
  TANGO all objects are representations of devices, which can be on the
@@ -145,8 +158,10 @@ Description: TANGO distributed control system - documentation
 
 Package: tango-common
 Section: net
-Architecture: all
-Depends: ${misc:Depends}, adduser
+Architecture: any
+Depends: ${shlibs:Depends},
+	 ${misc:Depends},
+	 adduser
 Description: TANGO distributed control system - common files
  This package provides shared files for the TANGO distributed control
  system, and sets up the required infrastructure.
@@ -154,7 +169,10 @@ Description: TANGO distributed control system - common files
 Package: tango-db
 Section: net
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6), tango-common, dbconfig-common
+Depends: ${shlibs:Depends},
+	 ${misc:Depends},
+	 lsb-base (>= 3.0-6),
+	 dbconfig-common
 Description: TANGO distributed control system - database server
  TANGO is an object oriented distributed control system. It allows
  communication between TANGO device processes running on the same
@@ -167,8 +185,10 @@ Description: TANGO distributed control system - database server
 Package: tango-starter
 Section: net
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6),
-	 tango-common, dbconfig-common, omninotify
+Depends: ${shlibs:Depends},
+	 ${misc:Depends},
+	 lsb-base (>= 3.0-6),
+	 omninotify
 Description: TANGO distributed control system - control server
  TANGO is an object oriented distributed control system. It allows
  communication between TANGO device processes running on the same
@@ -182,7 +202,10 @@ Description: TANGO distributed control system - control server
 Package: tango-accesscontrol
 Section: net
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6), tango-common, tango-starter
+Depends: ${shlibs:Depends},
+	 ${misc:Depends},
+	 lsb-base (>= 3.0-6),
+	 tango-starter
 Description:  TANGO distributed control system - accesscontrol server
  TANGO is an object oriented distributed control system. It allows
  communication between TANGO device processes running on the same
@@ -197,7 +220,9 @@ Description:  TANGO distributed control system - accesscontrol server
 Package: tango-test
 Section: net
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, tango-common, tango-starter
+Depends: ${shlibs:Depends},
+	 ${misc:Depends},
+	 tango-starter
 Description:  TANGO distributed control system - test device
  TANGO is an object oriented distributed control system. It allows
  communication between TANGO device processes running on the same
@@ -209,9 +234,10 @@ Description:  TANGO distributed control system - test device
  attribute types, and can be used for testing the installation.
 
 Package: tango-test-dbg
-Section: net
+Section: debug
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, tango-common, tango-starter
+Depends: tango-test (= ${binary:Version}),
+	 ${misc:Depends}
 Description:  TANGO distributed control system - test device
  TANGO is an object oriented distributed control system. It allows
  communication between TANGO device processes running on the same
diff --git a/debian/patches/features/fix-tangotest-string-image b/debian/patches/debian/notify_daemon
similarity index 65%
copy from debian/patches/features/fix-tangotest-string-image
copy to debian/patches/debian/notify_daemon
index 67564bb..9ada366 100644
--- a/debian/patches/features/fix-tangotest-string-image
+++ b/debian/patches/debian/notify_daemon
@@ -26,14 +26,29 @@ Forwarded: <no|not-needed|url proving that it has been forwarded>
 Reviewed-By: <name and email of someone who approved the patch>
 Last-Update: <YYYY-MM-DD>
 
---- tango-7.1.1~dfsg.orig/cppserver/tangotest/TangoTest.cpp
-+++ tango-7.1.1~dfsg/cppserver/tangotest/TangoTest.cpp
-@@ -1081,7 +1081,7 @@ void TangoTest::write_string_image(Tango
-   {
-     for (i = 0; i < dimXStringImage; i++)
-     {
--      str_index = i + j * dimYStringImage;
-+      str_index = i + j * dimXStringImage;
-       CORBA::string_free(attr_string_image_read[str_index]);
-       attr_string_image_read[str_index] = CORBA::string_dup(p[str_index]);
-     }
+--- tango-7.1.1~dfsg.orig/scripts/notify_daemon.in
++++ tango-7.1.1~dfsg/scripts/notify_daemon.in
+@@ -16,8 +16,6 @@ SunOS)  KILLALL=pkill
+ esac
+ 
+ 
+-BIN_DIR=@prefix@/bin
+-
+ ulimit -s 2048
+ 
+ #------------------------------------------------------------
+@@ -35,12 +33,12 @@ fi
+ 
+ echo "TANGO_HOST=$TANGO_HOST"
+ echo "Starting notifd....."
+-$BIN_DIR/notifd -n  -DDeadFilterInterval=300  1>/dev/null 2>/tmp/notifd.err &
++notifd -n  -DDeadFilterInterval=300  1>/dev/null 2>/tmp/notifd.err &
+ 
+ 
+ #---- Sleep a bit before write IOR in database
+ sleep 3
+-$BIN_DIR/notifd2db
++notifd2db
+ 
+ echo "ulimit has been set to:"
+ ulimit -s
diff --git a/debian/patches/debian/starter b/debian/patches/debian/starter
new file mode 100644
index 0000000..b4e0497
--- /dev/null
+++ b/debian/patches/debian/starter
@@ -0,0 +1,49 @@
+Description: Upstream changes introduced in version 7.1.1~dfsg-1
+ This patch has been created by dpkg-source during the package build.
+ Here's the last changelog entry, hopefully it gives details on why
+ those changes were made:
+ .
+ tango (7.1.1~dfsg-1) unstable; urgency=low
+ .
+   * remove the "." from the DsStarterPath
+   * use the right notifd2db path
+ .
+ The person named in the Author field signed this changelog entry.
+Author: Picca Frédéric-Emmanuel <picca at synchrotron-soleil.fr>
+
+---
+The information above should follow the Patch Tagging Guidelines, please
+checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
+are templates for supplementary fields that you might want to add:
+
+Origin: <vendor|upstream|other>, <url of original patch>
+Bug: <url in upstream bugtracker>
+Bug-Debian: http://bugs.debian.org/<bugnumber>
+Forwarded: <no|not-needed|url proving that it has been forwarded>
+Reviewed-By: <name and email of someone who approved the patch>
+Last-Update: <YYYY-MM-DD>
+
+--- tango-7.1.1~dfsg.orig/cppserver/starter/Starter.cpp
++++ tango-7.1.1~dfsg/cppserver/starter/Starter.cpp
+@@ -629,9 +629,7 @@ void Starter::get_device_property()
+ 	//-------------------------------------------------------------
+ 	if (dev_prop[0].is_empty())
+ 		cout << "WARNING : startDsPath NOT defined !!!!" << endl;
+-	if (startDsPath.size()==0)
+-		startDsPath.push_back(".");
+-	else
++	if (startDsPath.size()!=0)
+ 	for (unsigned int i=0 ; i<startDsPath.size() ; i++)
+ 		INFO_STREAM << "startDsPath[" << i << "] = " << startDsPath[i] << endl;
+ 	INFO_STREAM << "WaitForDriverStartup = " << waitForDriverStartup << " seconds" << endl;
+--- tango-7.1.1~dfsg.orig/cppserver/starter/Starter.h
++++ tango-7.1.1~dfsg/cppserver/starter/Starter.h
+@@ -157,7 +157,7 @@
+  //-----------------------------------------------
+ #define PING_TIMEOUT			3	//	seconds
+ #define	TIME_BETWEEN_STARTUPS	500	//	Milli seconds
+-#define NOTIFY_DAEMON_SCRIPT	"notify_daemon"
++#define NOTIFY_DAEMON_SCRIPT	"/usr/lib/tango/notify_daemon"
+ 
+ //	Used onlyduring the Cpp Api bug fixing on 
+ //	specAtt->get_max_x() method.
diff --git a/debian/patches/debian/starter-mysql.in.diff b/debian/patches/debian/starter-mysql.in.diff
deleted file mode 100644
index 7e43542..0000000
--- a/debian/patches/debian/starter-mysql.in.diff
+++ /dev/null
@@ -1,56 +0,0 @@
-Description: Upstream changes introduced in version 7.1.1~dfsg-1
- This patch has been created by dpkg-source during the package build.
- Here's the last changelog entry, hopefully it gives details on why
- those changes were made:
- .
- tango (7.1.1~dfsg-1) UNRELEASED; urgency=low
- .
-   * Imported Upstream version 7.1.1~dfsg
-   * add the dversionmangle in the watch file
-   * update to debian-policy 3.8.3 (nothing to do)
-   * switch to the 3.0 (quilt) source format
- .
- The person named in the Author field signed this changelog entry.
-Author: Picca Frédéric-Emmanuel <picca at synchrotron-soleil.fr>
-
----
-The information above should follow the Patch Tagging Guidelines, please
-checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
-are templates for supplementary fields that you might want to add:
-
-Origin: <vendor|upstream|other>, <url of original patch>
-Bug: <url in upstream bugtracker>
-Bug-Debian: http://bugs.debian.org/<bugnumber>
-Forwarded: <no|not-needed|url proving that it has been forwarded>
-Reviewed-By: <name and email of someone who approved the patch>
-Last-Update: <YYYY-MM-DD>
-
---- /dev/null
-+++ tango-7.1.1~dfsg/cppserver/starter/mysql.in
-@@ -0,0 +1,26 @@
-+#
-+# Create entry for starter device server in device table
-+#
-+
-+INSERT INTO device VALUES ('tango/admin/_hostname_',NULL,'tango','admin','_hostname_', 'nada','nada','nada','Starter/_hostname_','nada','Starter','nada','nada','nada','nada');
-+INSERT INTO device VALUES ('dserver/Starter/_hostname_',NULL,'dserver','Starter','_hostname_','nada','nada','nada','Starter/_hostname_','nada','DServer','nada','nada','nada','nada');
-+
-+#
-+# Set the device property
-+#
-+
-+INSERT INTO property_device VALUES ('tango/admin/_hostname_', 'tango', 'admin', '_hostname_', 'polled_attr', 1, 'notifdstate', NULL, NULL, NULL);
-+INSERT INTO property_device VALUES ('tango/admin/_hostname_', 'tango', 'admin', '_hostname_', 'polled_attr', 2, '1000', NULL, NULL, NULL);
-+INSERT INTO property_device VALUES ('tango/admin/_hostname_', 'tango', 'admin', '_hostname_', 'polled_attr', 3, 'servers', NULL, NULL, NULL);
-+INSERT INTO property_device VALUES ('tango/admin/_hostname_', 'tango', 'admin', '_hostname_', 'polled_attr', 4, '1000', NULL, NULL, NULL);
-+INSERT INTO property_device VALUES ('tango/admin/_hostname_', 'tango', 'admin', '_hostname_', 'polled_attr', 5, 'state', NULL, NULL, NULL);
-+INSERT INTO property_device VALUES ('tango/admin/_hostname_', 'tango', 'admin', '_hostname_', 'polled_attr', 6, '1000', NULL, NULL, NULL);
-+
-+#
-+# Set the class property:
-+#
-+
-+INSERT INTO property_class VALUES ('Starter','AllowedAccessCmd',1,'DevReadLog',NULL,NULL,NULL);
-+INSERT INTO property_class VALUES ('Starter','AllowedAccessCmd',2,'DevStart',NULL,NULL,NULL);
-+INSERT INTO property_class VALUES ('Starter','AllowedAccessCmd',3,'DevGetRunningServers',NULL,NULL,NULL);
-+INSERT INTO property_class VALUES ('Starter','AllowedAccessCmd',4,'DevGetStopServers',NULL,NULL,NULL);
diff --git a/debian/patches/debian/tango-admin b/debian/patches/debian/tango-admin
new file mode 100644
index 0000000..51d6d5e
--- /dev/null
+++ b/debian/patches/debian/tango-admin
@@ -0,0 +1,2330 @@
+Description: Upstream changes introduced in version 7.1.1~dfsg-1
+ This patch has been created by dpkg-source during the package build.
+ Here's the last changelog entry, hopefully it gives details on why
+ those changes were made:
+ .
+ tango (7.1.1~dfsg-1) unstable; urgency=low
+ .
+   * Imported Upstream version 7.1.1~dfsg
+   * add the dversionmangle in the watch file
+   * update to debian-policy 3.8.3 (nothing to do)
+   * switch to the 3.0 (quilt) source format
+   * starter install the right device in the database during installation.
+ .
+ The person named in the Author field signed this changelog entry.
+Author: Picca Frédéric-Emmanuel <picca at synchrotron-soleil.fr>
+
+---
+The information above should follow the Patch Tagging Guidelines, please
+checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
+are templates for supplementary fields that you might want to add:
+
+Origin: <vendor|upstream|other>, <url of original patch>
+Bug: <url in upstream bugtracker>
+Bug-Debian: http://bugs.debian.org/<bugnumber>
+Forwarded: <no|not-needed|url proving that it has been forwarded>
+Reviewed-By: <name and email of someone who approved the patch>
+Last-Update: <YYYY-MM-DD>
+
+--- /dev/null
++++ tango-7.1.1~dfsg/utils/tango_admin/tango_admin.cpp
+@@ -0,0 +1,839 @@
++static const char *RcsId = "$Id: tango_admin.cpp,v 1.1 2010/03/12 12:34:36 taurel Exp $";
++
++//+============================================================================
++//
++// file :               tango_admin.cpp
++//
++// description :        C++ source code for the tango_admin utility
++//						This utility is a Tango database command line interface
++//						Obviously, not all the database features are interfaced
++//						by this tool. Only the features needed for the Debian
++//						packaging have been implemented. This means:
++//						- ping the database server
++//						- check if a device is defined in DB
++//						- check if a server is defined in DB
++//						- create a server in DB
++//						- delete a server from the DB
++//						- create a property in DB
++//						- delete a property from DB
++//
++// project :            TANGO
++//
++// author(s) :          E.Taurel
++//
++// Copyright (C) :      2004,2005,2006,2007,2008,2009,2010
++//						European Synchrotron Radiation Facility
++//                      BP 220, Grenoble 38043
++//                      FRANCE
++//
++// This file is part of Tango.
++//
++// Tango is free software: you can redistribute it and/or modify
++// it under the terms of the GNU Lesser General Public License as published by
++// the Free Software Foundation, either version 3 of the License, or
++// (at your option) any later version.
++// 
++// Tango is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU Lesser General Public License for more details.
++// 
++// You should have received a copy of the GNU Lesser General Public License
++// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
++//
++// $Revision: 1.1 $
++//
++//-============================================================================
++
++#include <iostream>
++#include <anyoption.h>
++#include <tango.h>
++
++using namespace std;
++
++int ping_database();
++int check_device(char *);
++int add_server(char *,char *,char *);
++void list2vect(string &,vector<string> &);
++int check_server(char *);
++int delete_server(char *,bool);
++int add_property(char *,char *,char *);
++int delete_property(char *,char *);
++
++
++int main(int argc,char *argv[])
++{
++	AnyOption *opt = new AnyOption();
++
++//
++// Add usage menu
++//
++
++	opt->addUsage("Usage: " );
++ 	opt->addUsage(" --help  		Prints this help " );
++	opt->addUsage(" --ping-database	Ping database " );
++	opt->addUsage(" --check-device <dev>    Check if the device is defined in DB");
++ 	opt->addUsage(" --add-server <exec/inst> <class> <dev list (comma separated)>   Add a server in DB" );
++ 	opt->addUsage(" --delete-server <exec/inst> [--with-properties]   Delete a server from DB" );
++	opt->addUsage(" --check-server <exec/inst>   Check if a device server is defined in DB");
++ 	opt->addUsage(" --add-property <dev> <prop_name> <prop_value (comma separated for array)>    Add a device property in DB" );
++	opt->addUsage(" --delete-property <dev> <prop_name>   Delete a device property from DB ");
++
++
++//
++// Define the command line options
++//
++
++	opt->setFlag("help",'h');
++ 	opt->setFlag("ping-database",'c');
++	opt->setOption("add-server");
++	opt->setOption("delete-server");
++	opt->setFlag("with-properties");
++	opt->setOption("add-property");
++	opt->setOption("delete-property");
++	opt->setOption("check-device");
++	opt->setOption("check-server");
++
++//
++// Process cmd line
++//
++
++	opt->processCommandArgs( argc, argv );
++
++	if (!opt->hasOptions())
++	{
++		opt->printUsage();
++		delete opt;
++		return 0;
++	}
++
++//
++// --help option
++//
++
++	if (opt->getFlag("help") || opt->getFlag('h'))
++	{
++		opt->printUsage();
++		delete opt;
++		return 0;
++	}
++
++//
++// --ping-database option
++//
++
++	if (opt->getFlag("ping-database") == true)
++	{
++		if (opt->getValue("add-server") != NULL ||
++			opt->getValue("delete-server") != NULL ||
++		    opt->getValue("add-property") != NULL ||
++		    opt->getValue("delete-property") != NULL ||
++			opt->getValue("check-device") != NULL ||
++			opt->getValue("check-server") != NULL ||
++		    opt->getFlag("with-properties") == true)
++			cout << "Can't mix option --check-database with other option(s)" << endl;
++
++		if (argc != 2)
++		{
++			cout << "Bad argument number for option --check-database" << endl;
++			opt->printUsage();
++			delete opt;
++			return 0;
++		}
++
++		cout << "Check database" << endl;
++		int ret;
++		ret = ping_database();
++
++		delete opt;
++		return ret;
++	}
++
++//
++// --check-device option
++//
++
++
++	else if (opt->getValue("check-device") != NULL)
++	{
++		if (opt->getValue("delete-server") != NULL ||
++		    opt->getValue("add-property") != NULL ||
++		    opt->getValue("delete-property") != NULL ||
++			opt->getValue("add-server") != NULL ||
++			opt->getValue("check-server") != NULL ||
++		    opt->getFlag("with-properties") == true)
++			cout << "Can't mix option --add-server with other option(s)" << endl;
++		else
++		{
++			if (argc != 3)
++			{
++				cout << "Bad argument number for option --check_device" << endl;
++				opt->printUsage();
++				delete opt;
++				return 0;
++			}
++
++			int ret;
++			ret = check_device(opt->getValue("check-device"));
++
++			delete opt;
++			return ret;
++		}
++	}
++
++//
++// --add-server option
++//
++
++
++	else if (opt->getValue("add-server") != NULL)
++	{
++		if (opt->getValue("delete-server") != NULL ||
++		    opt->getValue("add-property") != NULL ||
++		    opt->getValue("delete-property") != NULL ||
++			opt->getValue("check-device") != NULL ||
++			opt->getValue("check-server") != NULL ||
++		    opt->getFlag("with-properties") == true)
++			cout << "Can't mix option --add-server with other option(s)" << endl;
++		else
++		{
++			if (argc != 5)
++			{
++				cout << "Bad argument number for option --add-server" << endl;
++				opt->printUsage();
++				delete opt;
++				return 0;
++			}
++
++			int ret;
++			ret = add_server(opt->getValue("add-server"),opt->getArgv(0),opt->getArgv(1));
++
++			delete opt;
++			return ret;
++		}
++	}
++
++//
++// --check-server option
++//
++
++
++	else if (opt->getValue("check-server") != NULL)
++	{
++		if (opt->getValue("delete-server") != NULL ||
++		    opt->getValue("add-property") != NULL ||
++		    opt->getValue("delete-property") != NULL ||
++			opt->getValue("add-server") != NULL ||
++			opt->getValue("check-device") != NULL ||
++		    opt->getFlag("with-properties") == true)
++			cout << "Can't mix option --check-server with other option(s)" << endl;
++		else
++		{
++			if (argc != 3)
++			{
++				cout << "Bad argument number for option --check_server" << endl;
++				opt->printUsage();
++				delete opt;
++				return 0;
++			}
++
++			int ret;
++			ret = check_server(opt->getValue("check-server"));
++
++			delete opt;
++			return ret;
++		}
++	}
++
++//
++// --delete-server option
++//
++
++	else if (opt->getValue("delete-server") != NULL)
++	{
++		if (opt->getValue("add-server") != NULL ||
++		    opt->getValue("add-property") != NULL ||
++			opt->getValue("check-server") != NULL ||
++			opt->getValue("check-device") != NULL ||
++		    opt->getValue("delete-property") != NULL)
++			cout << "Can't mix option --delete-server with other option(s)" << endl;
++		else
++		{
++			if ((argc < 3 || argc > 4) ||
++				(argc == 3 && strcmp(argv[2],"--with-properties") == 0) ||
++				(strcmp(opt->getValue("delete-server"),"--with-properties") == 0))
++			{
++				cout << "Bad option delete-server usage" << endl;
++				opt->printUsage();
++				delete opt;
++				return 0;
++			}
++
++			int ret;
++			if (opt->getFlag("with-properties") == true)
++				ret = delete_server(opt->getValue("delete-server"),true);
++			else
++				ret = delete_server(opt->getValue("delete-server"),false);
++
++			delete opt;
++			return ret;
++		}
++	}
++
++//
++// --add-property option
++//
++
++	else if (opt->getValue("add-property") != NULL)
++	{
++		if (opt->getValue("delete-server") != NULL ||
++		    opt->getValue("delete-property") != NULL ||
++			opt->getValue("add-server") != NULL ||
++			opt->getValue("check-device") != NULL ||
++			opt->getValue("check-server") != NULL ||
++		    opt->getFlag("with-properties") == true ||
++			opt->getFlag("ping-database") == true)
++			cout << "Can't mix option --add-property with other option(s)" << endl;
++		else
++		{
++			if (argc != 5)
++			{
++				cout << "Bag argument number for option --add-property" << endl;
++				opt->printUsage();
++				delete opt;
++				return 0;
++			}
++
++			int ret;
++			ret = add_property(opt->getValue("add-property"),opt->getArgv(0),opt->getArgv(1));
++
++			delete opt;
++			return ret;
++		}
++	}
++
++//
++// --delete-property option
++//
++
++	else if (opt->getValue("delete-property") != NULL)
++	{
++		if (opt->getValue("delete-server") != NULL ||
++		    opt->getValue("add-property") != NULL ||
++			opt->getValue("add-server") != NULL ||
++			opt->getValue("check-device") != NULL ||
++			opt->getValue("check-server") != NULL ||
++		    opt->getFlag("with-properties") == true ||
++			opt->getFlag("ping-database") == true)
++			cout << "Can't mix option --delete-property with other option(s)" << endl;
++		else
++		{
++			if (argc != 4)
++			{
++				cout << "Bag argument number for option --add-property" << endl;
++				opt->printUsage();
++				delete opt;
++				return 0;
++			}
++
++			int ret;
++			ret = delete_property(opt->getValue("delete-property"),opt->getArgv(0));
++
++			delete opt;
++			return ret;
++		}
++	}
++//
++// Unknown choice
++//
++
++	else
++	{
++		cout << "Wrong usage" << endl;
++		opt->printUsage();
++	}
++
++	delete opt;
++}
++
++//+-------------------------------------------------------------------------
++//
++// method : 		ping_database
++// 
++// description : 	This function connect to the database and executes
++//					one of its command in order to check the database
++//					connectivity
++//
++// The function returns 0 is everything is fine. Otherwise, it returns -1
++//
++//--------------------------------------------------------------------------
++
++int ping_database()
++{
++	int ret = 0;
++
++	try
++	{
++		Tango::Database db;
++
++		string db_info;
++		db_info = db.get_info();
++	}
++	catch (Tango::DevFailed &e)
++	{
++		ret = -1;
++	}
++	return ret;	
++}
++
++//+-------------------------------------------------------------------------
++//
++// method : 		check_device
++// 
++// description : 	This function checks if a device is defined in the DB
++//
++// argument : in : 	- name : The device name
++//
++// The function returns 0 is the device is defined. Otherwise, it returns -1
++//
++//--------------------------------------------------------------------------
++
++int check_device(char *name)
++{
++	int ret = 0;
++
++	try
++	{
++		Tango::Database db;
++
++		string d_name(name);
++		Tango::DbDevImportInfo dii = db.import_device(d_name);
++	}
++	catch (Tango::DevFailed &e)
++	{
++		ret = -1;
++	}
++	return ret;	
++}
++
++//+-------------------------------------------------------------------------
++//
++// method : 		add_server
++// 
++// description : 	This function adds a server definition in the DB
++//
++// argument : in : 	- d_name : The device server name (exec/inst)
++//					- c_name : The class name
++//					- d_list : The device list
++//
++// The function returns 0 is everything is fine. Otherwise, it returns -1
++//
++//--------------------------------------------------------------------------
++
++int add_server(char *d_name,char *c_name,char *d_list)
++{
++	int ret = 0;
++
++//
++// Check ds name syntax
++//
++
++	string ds_name(d_name);
++	string::size_type pos;
++
++	pos = ds_name.find('/');
++	if ((count(ds_name.begin(),ds_name.end(),'/') != 1) || pos == 0 || pos == (ds_name.size() - 1))
++	{
++		cout << "Wrong syntax for ds name" << endl;
++		ret = -1;
++		return ret;
++	}
++
++//
++// Check class name syntax
++//
++
++	string class_name(c_name);
++	if (count(class_name.begin(),class_name.end(),'/') != 0)
++	{
++		cout << "Wrong syntax for class name" << endl;
++		ret = -1;
++		return ret;
++	}
++
++//
++// Check device list and device syntax
++//
++
++	string dev_list(d_list);
++	vector<string> dev_names;
++
++	list2vect(dev_list,dev_names);
++
++	for (unsigned int loop = 0;loop < dev_names.size();++loop)
++	{
++		if (count(dev_names[loop].begin(),dev_names[loop].end(),'/') != 2)
++		{
++			cout << "Wrong syntax for device " << dev_names[loop] << endl;
++			ret = -1;
++			return ret;
++		}
++
++		string::size_type pos1,pos2;
++		pos1 = dev_names[loop].find('/');
++		pos2 = dev_names[loop].rfind('/');
++
++		if (pos1 == 0 || pos2 == dev_names[loop].length() - 1 || pos2 == pos1 + 1)
++		{
++			cout << "Wrong syntax for device " << dev_names[loop] << endl;
++			ret = -1;
++			return ret;
++		}
++	}
++
++//
++// Create server in DB
++// Dont forget to add the admin device
++//
++
++	try
++	{
++		Tango::Database db;
++
++		Tango::DbDevInfos ddi;
++		Tango::DbDevInfo tmp_dbi;
++
++		for (unsigned int loop = 0;loop < dev_names.size();++loop)
++		{
++			tmp_dbi.name = dev_names[loop];
++			tmp_dbi._class = class_name;
++			tmp_dbi.server = ds_name;
++			ddi.push_back(tmp_dbi);
++		}
++		tmp_dbi.name = "dserver/" + ds_name;
++		tmp_dbi._class = "DServer";
++		tmp_dbi.server = ds_name;
++
++		ddi.push_back(tmp_dbi);
++
++		db.add_server(ds_name,ddi);
++	}
++	catch (Tango::DevFailed &e)
++	{
++		ret = -1;
++	}
++	return ret;
++}
++
++//+-------------------------------------------------------------------------
++//
++// method : 		check_server
++// 
++// description : 	This function checks if a device server is defined in the DB
++//
++// argument : in : 	- d_name : The device server name
++//
++// The function returns 0 is the device is defined. Otherwise, it returns -1
++//
++//--------------------------------------------------------------------------
++
++int check_server(char *d_name)
++{
++	int ret = 0;
++
++	string dev_name = "dserver/";
++	string ds_name = d_name;
++
++	dev_name = dev_name + ds_name;
++
++	ret = check_device((char *)dev_name.c_str());
++
++	return ret;
++}
++
++//+-------------------------------------------------------------------------
++//
++// method : 		delete_server
++// 
++// description : 	This function deletes a device server from the DB
++//
++// argument : in : 	- d_name : The device server name
++//					- with_res : If true, also delte device properties
++//
++// The function returns 0 is everything is fine. Otherwise, it returns -1
++//
++//--------------------------------------------------------------------------
++
++int delete_server(char *d_name,bool with_res)
++{
++	int ret = 0;
++
++	string ds_name(d_name);
++
++//
++// Check device server name syntax
++//
++
++	string::size_type pos;
++	pos = ds_name.find('/');
++
++	if (pos == 0 || pos == ds_name.size() - 1 ||
++		count(ds_name.begin(),ds_name.end(),'/') != 1)
++	{
++		ret = -1;
++		return ret;
++	}
++
++	ret = check_server(d_name);
++	if (ret != 0)
++		return ret;
++
++
++	try
++	{
++
++		Tango::Database db;
++
++//
++// If we need to remove prop
++//
++
++		if (with_res == true)
++		{
++
++//
++//	First get the ds class list
++//
++
++			Tango::DbDatum db_res = db.get_device_class_list(ds_name);
++			vector<string> dev_list;
++			db_res >> dev_list;
++
++//
++// Get device property name for each device
++//
++
++			for (unsigned int loop = 0;loop < dev_list.size();++loop)
++			{
++				vector<string> prop_list;
++
++				db.get_device_property_list(dev_list[loop],"*",prop_list);
++
++//
++// Delete all device properties
++//
++
++				if (prop_list.size() != 0)
++				{
++					Tango::DbData dbd;
++					
++					for (unsigned int ctr = 0;ctr < prop_list.size();++ctr)
++						dbd.push_back(Tango::DbDatum(prop_list[ctr]));
++
++					db.delete_device_property(dev_list[loop],dbd);
++				}
++
++				++loop;
++			}				
++
++		}
++
++//
++// Delete device server from db
++//
++
++
++		db.delete_server(ds_name);
++	}
++	catch (Tango::DevFailed &e)
++	{
++		ret = -1;
++	}
++
++	return ret;
++}
++
++//+-------------------------------------------------------------------------
++//
++// method : 		add_property
++// 
++// description : 	This function adds a device property in the DB
++//
++// argument : in : 	- d_name : The device name 
++//					- p_name : The property name
++//					- p_val : The property value
++//
++// The function returns 0 is everything is fine. Otherwise, it returns -1
++//
++//--------------------------------------------------------------------------
++
++int add_property(char *d_name,char *p_name,char *p_val)
++{
++	int ret = 0;
++
++//
++// Check dev name syntax
++//
++
++	string dev_name(d_name);
++	string::size_type pos1,pos2;
++
++	pos1 = dev_name.find('/');
++	pos2 = dev_name.rfind('/');
++
++	if ((count(dev_name.begin(),dev_name.end(),'/') != 2) || 
++		pos1 == 0 || pos2 == (dev_name.size() - 1) || pos2 == pos1 + 1)
++	{
++		cout << "Wrong syntax for device name" << endl;
++		ret = -1;
++		return ret;
++	}
++
++//
++// Check if the device is defined
++//
++
++	if (check_device(d_name) != 0)
++		return -1;
++
++//
++// Convert prop value(s) into a vector
++//
++
++	string prop_val(p_val);
++	vector<string> prop_val_list;
++
++	list2vect(prop_val,prop_val_list);
++
++//
++// Create server in DB
++// Dont forget to add the admin device
++//
++
++	try
++	{
++		Tango::Database db;
++
++		Tango::DbData dbd;
++		Tango::DbDatum db_s(p_name);
++		
++		db_s << prop_val_list;
++		dbd.push_back(db_s);
++
++		db.put_device_property(dev_name,dbd);
++	}
++	catch (Tango::DevFailed &e)
++	{
++		ret = -1;
++	}
++	return ret;
++}
++
++//+-------------------------------------------------------------------------
++//
++// method : 		delete_property
++// 
++// description : 	This function deletes a device property from the DB
++//
++// argument : in : 	- d_name : The device name 
++//					- p_name : The property name
++//
++// The function returns 0 is everything is fine. Otherwise, it returns -1
++//
++//--------------------------------------------------------------------------
++
++int delete_property(char *d_name,char *p_name)
++{
++	int ret = 0;
++
++//
++// Check dev name syntax
++//
++
++	string dev_name(d_name);
++	string::size_type pos1,pos2;
++
++	pos1 = dev_name.find('/');
++	pos2 = dev_name.rfind('/');
++
++	if ((count(dev_name.begin(),dev_name.end(),'/') != 2) || 
++		pos1 == 0 || pos2 == (dev_name.size() - 1) || pos2 == pos1 + 1)
++	{
++		cout << "Wrong syntax for device name" << endl;
++		ret = -1;
++		return ret;
++	}
++
++//
++// Check if the device is defined
++//
++
++	if (check_device(d_name) != 0)
++		return -1;
++
++//
++// Create server in DB
++// Dont forget to add the admin device
++//
++
++	try
++	{
++		Tango::Database db;
++
++		Tango::DbData dbd;
++		dbd.push_back(Tango::DbDatum(p_name));
++
++		db.delete_device_property(dev_name,dbd);
++	}
++	catch (Tango::DevFailed &e)
++	{
++		ret = -1;
++	}
++	return ret;
++}
++
++//+-------------------------------------------------------------------------
++//
++// method : 		list2vect
++// 
++// description : 	This function converts a comma separated
++//					device list into a vector of strings with one
++//					element for each device
++//
++// argument : in : 	- dev_list : The device list
++//					- dev_names : The device vector
++//
++//--------------------------------------------------------------------------
++
++void list2vect(string &dev_list,vector<string> &dev_names)
++{
++	string::size_type beg,end;
++
++	bool end_loop = false;
++	beg = 0;
++
++	while (end_loop == false)
++	{
++		end = dev_list.find(',',beg);
++		if (end == beg)
++		{
++			++beg;
++			continue;
++		}
++
++		if (end == string::npos)
++		{
++			end = dev_list.length();
++			end_loop = true;
++		}
++
++		string one_dev;
++		one_dev = dev_list.substr(beg,end - beg);
++		dev_names.push_back(one_dev);
++
++		beg = end + 1;
++		if (beg == dev_list.size())
++			end_loop = true;
++	}
++}
++
+--- /dev/null
++++ tango-7.1.1~dfsg/utils/tango_admin/anyoption.h
+@@ -0,0 +1,295 @@
++//
++// anyoption.h -	include file for command line options management
++//
++// 
++// Copyright (C) :      2004,2005,2006,2007,2008,2009,2010
++//						European Synchrotron Radiation Facility
++//                      BP 220, Grenoble 38043
++//                      FRANCE
++//
++// This file is part of Tango.
++//
++// Tango is free software: you can redistribute it and/or modify
++// it under the terms of the GNU Lesser General Public License as published by
++// the Free Software Foundation, either version 3 of the License, or
++// (at your option) any later version.
++// 
++// Tango is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU Lesser General Public License for more details.
++// 
++// You should have received a copy of the GNU Lesser General Public License
++// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
++
++#ifndef _ANYOPTION_H
++#define _ANYOPTION_H
++
++#include <iostream>
++#include <fstream>
++#include <stdlib.h>
++#include <string.h>
++
++#define COMMON_OPT 	1
++#define COMMAND_OPT 	2
++#define FILE_OPT 	3
++#define COMMON_FLAG 	4
++#define COMMAND_FLAG 	5
++#define FILE_FLAG 	6
++
++#define COMMAND_OPTION_TYPE  	1
++#define COMMAND_FLAG_TYPE 	2
++#define FILE_OPTION_TYPE  	3
++#define FILE_FLAG_TYPE 		4 
++#define UNKNOWN_TYPE 		5
++
++#define DEFAULT_MAXOPTS 	10
++#define MAX_LONG_PREFIX_LENGTH 	2
++
++#define DEFAULT_MAXUSAGE	3
++#define DEFAULT_MAXHELP         10	
++
++#define TRUE_FLAG "true" 
++
++using namespace std;
++
++class AnyOption 
++{
++
++public: /* the public interface */
++	AnyOption();
++	AnyOption(int maxoptions ); 
++	AnyOption(int maxoptions , int maxcharoptions); 
++	~AnyOption();
++
++	/* 
++         * following set methods specifies the  
++	 * special characters and delimiters 
++	 * if not set traditional defaults will be used
++         */
++
++	void setCommandPrefixChar( char _prefix );   /* '-' in "-w" */
++	void setCommandLongPrefix( char *_prefix );  /* '--' in "--width" */
++	void setFileCommentChar( char _comment );    /* '#' in shellscripts */
++	void setFileDelimiterChar( char _delimiter );/* ':' in "width : 100" */
++
++	/* 
++	 * provide the input for the options
++         * like argv[] for commndline and the 
++         * option file name  to use;
++	 */
++
++	void useCommandArgs( int _argc, char **_argv );
++	void useFiileName( const char *_filename );
++
++	/* 
++         * turn off the POSIX style options 
++         * this means anything starting with a '-' or "--"
++         * will be considered a valid option 
++         * which alo means you cannot add a bunch of 
++         * POIX options chars together like "-lr"  for "-l -r"
++         * 
++         */
++
++	void noPOSIX();
++
++	/*
++         * prints warning verbose if you set anything wrong 
++         */
++	void setVerbose();
++
++
++	/* 
++         * there are two types of options  
++         *
++         * Option - has an associated value ( -w 100 )
++         * Flag  - no value, just a boolean flag  ( -nogui )
++         * 
++	 * the options can be either a string ( GNU style )
++         * or a character ( traditional POSIX style ) 
++         * or both ( --width, -w )
++         *
++         * the options can be common to the commandline and 
++         * the optionfile, or can belong only to either of 
++         * commandline and optionfile
++         *
++         * following set methods, handle all the aboove 
++	 * cases of options.
++         */
++
++	/* options comman to command line and option file */
++	void setOption( const char *opt_string );
++	void setOption( char  opt_char );
++	void setOption( const char *opt_string , char opt_char );
++	void setFlag( const char *opt_string );
++	void setFlag( char  opt_char );
++	void setFlag( const char *opt_string , char opt_char );
++
++	/* options read from commandline only */
++	void setCommandOption( const char *opt_string );
++	void setCommandOption( char  opt_char );
++	void setCommandOption( const char *opt_string , char opt_char );
++	void setCommandFlag( const char *opt_string );
++	void setCommandFlag( char  opt_char );
++	void setCommandFlag( const char *opt_string , char opt_char );
++
++	/* options read from an option file only  */
++	void setFileOption( const char *opt_string );
++	void setFileOption( char  opt_char );
++	void setFileOption( const char *opt_string , char opt_char );
++	void setFileFlag( const char *opt_string );
++	void setFileFlag( char  opt_char );
++	void setFileFlag( const char *opt_string , char opt_char );
++
++	/*
++         * process the options, registerd using 
++         * useCommandArgs() and useFileName();
++         */
++	void processOptions();  
++	void processCommandArgs();
++	void processCommandArgs( int max_args );
++	bool processFile();
++
++	/*
++         * process the specified options 
++         */
++	void processCommandArgs( int _argc, char **_argv );
++	void processCommandArgs( int _argc, char **_argv, int max_args );
++	bool processFile( const char *_filename );
++	
++	/*
++         * get the value of the options 
++	 * will return NULL if no value is set 
++         */
++	char *getValue( const char *_option );
++	bool  getFlag( const char *_option );
++	char *getValue( char _optchar );
++	bool  getFlag( char _optchar );
++
++	/*
++	 * Print Usage
++	 */
++	void printUsage();
++	void printAutoUsage();
++	void addUsage( const char *line );
++	void printHelp();
++        /* print auto usage printing for unknown options or flag */
++	void autoUsagePrint(bool flag);
++	
++	/* 
++         * get the argument count and arguments sans the options
++         */
++	int   getArgc();
++	char* getArgv( int index );
++	bool  hasOptions();
++
++private: /* the hidden data structure */
++	int argc;		/* commandline arg count  */
++	char **argv;  		/* commndline args */
++	const char* filename; 	/* the option file */
++	char* appname; 	/* the application name from argv[0] */
++
++	int *new_argv; 		/* arguments sans options (index to argv) */
++	int new_argc;   	/* argument count sans the options */
++	int max_legal_args; 	/* ignore extra arguments */
++
++
++	/* option strings storage + indexing */
++	int max_options; 	/* maximum number of options */
++	const char **options; 	/* storage */
++	int *optiontype; 	/* type - common, command, file */
++	int *optionindex;	/* index into value storage */
++	int option_counter; 	/* counter for added options  */
++
++	/* option chars storage + indexing */
++	int max_char_options; 	/* maximum number options */
++	char *optionchars; 	/*  storage */
++	int *optchartype; 	/* type - common, command, file */
++	int *optcharindex; 	/* index into value storage */
++	int optchar_counter; 	/* counter for added options  */
++
++	/* values */
++	char **values; 		/* common value storage */
++	int g_value_counter; 	/* globally updated value index LAME! */
++
++	/* help and usage */
++	const char **usage; 	/* usage */
++	int max_usage_lines;	/* max usage lines reseverd */
++	int usage_lines;	/* number of usage lines */
++
++	bool command_set;	/* if argc/argv were provided */
++	bool file_set;		/* if a filename was provided */
++	bool mem_allocated;     /* if memory allocated in init() */
++	bool posix_style; 	/* enables to turn off POSIX style options */
++	bool verbose;		/* silent|verbose */
++	bool print_usage;	/* usage verbose */
++	bool print_help;	/* help verbose */
++	
++	char opt_prefix_char;		/*  '-' in "-w" */
++	char long_opt_prefix[MAX_LONG_PREFIX_LENGTH]; /* '--' in "--width" */
++	char file_delimiter_char;	/* ':' in width : 100 */
++	char file_comment_char;		/*  '#' in "#this is a comment" */
++	char equalsign;
++	char comment;
++	char delimiter;
++	char endofline;
++	char whitespace;
++	char nullterminate;
++
++	bool set;   //was static member
++	bool once;  //was static member
++	
++	bool hasoptions;
++	bool autousage;
++
++private: /* the hidden utils */
++	void init();	
++	void init(int maxopt, int maxcharopt );	
++	bool alloc();
++	void cleanup();
++	bool valueStoreOK();
++
++	/* grow storage arrays as required */
++	bool doubleOptStorage();
++	bool doubleCharStorage();
++	bool doubleUsageStorage();
++
++	bool setValue( const char *option , char *value );
++	bool setFlagOn( const char *option );
++	bool setValue( char optchar , char *value);
++	bool setFlagOn( char optchar );
++
++	void addOption( const char* option , int type );
++	void addOption( char optchar , int type );
++	void addOptionError( const char *opt);
++	void addOptionError( char opt);
++	bool findFlag( char* value );
++	void addUsageError( const char *line );
++	bool CommandSet();
++	bool FileSet();
++	bool POSIX();
++
++	char parsePOSIX( char* arg );
++	int parseGNU( char *arg );
++	bool matchChar( char c );
++	int matchOpt( char *opt );
++
++	/* dot file methods */
++	char *readFile();
++	char *readFile( const char* fname );
++	bool consumeFile( char *buffer );
++	void processLine( char *theline, int length );
++	char *chomp( char *str );
++	void valuePairs( char *type, char *value ); 
++	void justValue( char *value );
++
++	void printVerbose( const char *msg );
++	void printVerbose( char *msg );
++	void printVerbose( char ch );
++	void printVerbose( );
++
++
++};
++
++#endif /* ! _ANYOPTION_H */
++
+--- /dev/null
++++ tango-7.1.1~dfsg/utils/tango_admin/anyoption.cpp
+@@ -0,0 +1,1159 @@
++static const char *RcsId = "$Id: anyoption.cpp,v 1.1 2010/03/12 12:34:36 taurel Exp $";
++
++//+============================================================================
++//
++// file :               anyoption.cpp
++//
++// description :        C++ source code for the AnyOption
++//						class. This class is used to manage the command line
++//						line arguments. This code comes from the
++//						http://www.hackorama.com/anyoption.
++//
++// project :            TANGO
++//
++// author(s) :          Kishan Thomas (E.Taurel)
++//
++// Copyright (C) :      2004,2005,2006,2007,2008,2009,2010
++//						European Synchrotron Radiation Facility
++//                      BP 220, Grenoble 38043
++//                      FRANCE
++//
++// This code (and the associated include file) comes from the following
++// web page: http://www.hackorama.com/anyoption/
++//
++// It is available there without any licensing informations.
++//
++// This file is part of Tango.
++//
++// Tango is free software: you can redistribute it and/or modify
++// it under the terms of the GNU Lesser General Public License as published by
++// the Free Software Foundation, either version 3 of the License, or
++// (at your option) any later version.
++// 
++// Tango is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU Lesser General Public License for more details.
++// 
++// You should have received a copy of the GNU Lesser General Public License
++// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
++//
++// $Revision: 1.1 $
++//
++//-============================================================================
++
++
++#include "anyoption.h"
++
++AnyOption::AnyOption()
++{
++	init();
++}
++
++AnyOption::AnyOption(int maxopt)
++{
++	init( maxopt , maxopt );
++}
++
++AnyOption::AnyOption(int maxopt, int maxcharopt)
++{
++	init( maxopt , maxcharopt );
++}
++
++AnyOption::~AnyOption()
++{
++	if( mem_allocated )
++		cleanup();
++}
++
++void
++AnyOption::init()
++{
++	init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS );
++}
++
++void
++AnyOption::init(int maxopt, int maxcharopt )
++{
++
++	max_options 	= maxopt;
++	max_char_options = maxcharopt;
++	max_usage_lines	= DEFAULT_MAXUSAGE;
++	usage_lines	= 0 ;
++	argc 		= 0;
++	argv 		= NULL;
++	posix_style	= true;
++	verbose 	= false;
++	filename 	= NULL;
++	appname 	= NULL;	
++	option_counter 	= 0;
++	optchar_counter	= 0;
++	new_argv 	= NULL;
++	new_argc 	= 0 ;
++	max_legal_args 	= 0 ;
++	command_set 	= false;
++	file_set 	= false;
++	values 		= NULL;	
++	g_value_counter = 0;
++	mem_allocated 	= false;
++	command_set 	= false;
++	file_set	= false;
++	opt_prefix_char     = '-';
++	file_delimiter_char = ':';
++	file_comment_char   = '#';
++	equalsign 	= '=';
++	comment       = '#' ;
++	delimiter     = ':' ;
++	endofline     = '\n';
++	whitespace    = ' ' ;
++	nullterminate = '\0';
++	set = false;
++	once = true;
++	hasoptions = false;
++	autousage = false;
++
++	::strcpy( long_opt_prefix , "--" );
++
++	if( alloc() == false ){
++		cout << endl << "OPTIONS ERROR : Failed allocating memory" ;
++		cout << endl ;
++		cout << "Exiting." << endl ;
++		exit (0);
++	}
++}
++
++bool
++AnyOption::alloc()
++{
++	int i = 0 ;
++	int size = 0 ;
++
++	if( mem_allocated )
++		return true;
++
++	size = (max_options+1) * sizeof(const char*);
++	options = (const char**)malloc( size );	
++	optiontype = (int*) malloc( (max_options+1)*sizeof(int) );	
++	optionindex = (int*) malloc( (max_options+1)*sizeof(int) );	
++	if( options == NULL || optiontype == NULL || optionindex == NULL )
++		return false;
++	else
++		mem_allocated  = true;
++	for( i = 0 ; i < max_options ; i++ ){
++		options[i] = NULL;
++		optiontype[i] = 0 ;
++		optionindex[i] = -1 ;
++	}
++	optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) );
++	optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) );	
++	optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) );	
++	if( optionchars == NULL || 
++            optchartype == NULL || 
++            optcharindex == NULL )
++        {
++		mem_allocated = false;
++		return false;
++	}
++	for( i = 0 ; i < max_char_options ; i++ ){
++		optionchars[i] = '0';
++		optchartype[i] = 0 ;
++		optcharindex[i] = -1 ;
++	}
++
++	size = (max_usage_lines+1) * sizeof(const char*) ;
++	usage = (const char**) malloc( size );
++
++	if( usage == NULL  ){
++		mem_allocated = false;
++		return false;
++	}
++	for( i = 0 ; i < max_usage_lines ; i++ )
++		usage[i] = NULL;
++
++	return true;
++}
++
++bool
++AnyOption::doubleOptStorage()
++{
++	options = (const char**)realloc( options,  
++			((2*max_options)+1) * sizeof( const char*) );
++	optiontype = (int*) realloc(  optiontype ,  
++			((2 * max_options)+1)* sizeof(int) );	
++	optionindex = (int*) realloc(  optionindex,  
++			((2 * max_options)+1) * sizeof(int) );	
++	if( options == NULL || optiontype == NULL || optionindex == NULL )
++		return false;
++	/* init new storage */
++	for( int i = max_options ; i < 2*max_options ; i++ ){
++		options[i] = NULL;
++		optiontype[i] = 0 ;
++		optionindex[i] = -1 ;
++	}
++	max_options = 2 * max_options ;
++	return true;
++}
++
++bool
++AnyOption::doubleCharStorage()
++{
++	optionchars = (char*) realloc( optionchars,  
++			((2*max_char_options)+1)*sizeof(char) );
++	optchartype = (int*) realloc( optchartype,  
++			((2*max_char_options)+1)*sizeof(int) );	
++	optcharindex = (int*) realloc( optcharindex,  
++			((2*max_char_options)+1)*sizeof(int) );	
++	if( optionchars == NULL || 
++	    optchartype == NULL || 
++	    optcharindex == NULL )
++		return false;
++	/* init new storage */
++	for( int i = max_char_options ; i < 2*max_char_options ; i++ ){
++		optionchars[i] = '0';
++		optchartype[i] = 0 ;
++		optcharindex[i] = -1 ;
++	}
++	max_char_options = 2 * max_char_options;	
++	return true;
++}
++
++bool
++AnyOption::doubleUsageStorage()
++{
++	usage = (const char**)realloc( usage,  
++			((2*max_usage_lines)+1) * sizeof( const char*) );
++	if ( usage == NULL )
++		return false;
++	for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ )
++		usage[i] = NULL;
++	max_usage_lines = 2 * max_usage_lines ;
++	return true;
++
++}
++
++
++void
++AnyOption::cleanup()
++{
++	free (options);
++	free (optiontype);
++	free (optionindex);	
++	free (optionchars);
++	free (optchartype);
++	free (optcharindex);
++	free (usage);
++	if( values != NULL )
++		free (values);
++	if( new_argv != NULL )
++		free (new_argv);
++}
++
++void
++AnyOption::setCommandPrefixChar( char _prefix )
++{
++	opt_prefix_char = _prefix;
++}
++
++void
++AnyOption::setCommandLongPrefix( char *_prefix )
++{
++	if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){
++		*( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0'; 
++	}
++
++	strcpy (long_opt_prefix,  _prefix);
++}
++
++void
++AnyOption::setFileCommentChar( char _comment )
++{
++	file_delimiter_char = _comment;
++}
++
++
++void
++AnyOption::setFileDelimiterChar( char _delimiter )
++{
++	file_comment_char = _delimiter ;
++}
++
++bool
++AnyOption::CommandSet()
++{
++	return( command_set );
++}
++
++bool
++AnyOption::FileSet()
++{
++	return( file_set );
++}
++
++void
++AnyOption::noPOSIX()
++{
++	posix_style = false;
++}
++
++bool
++AnyOption::POSIX()
++{
++	return posix_style;
++}
++
++
++void
++AnyOption::setVerbose()
++{
++	verbose = true ;
++}
++
++void
++AnyOption::printVerbose()
++{
++	if( verbose )
++		cout << endl  ;
++}
++void
++AnyOption::printVerbose( const char *msg )
++{
++	if( verbose )
++		cout << msg  ;
++}
++
++void
++AnyOption::printVerbose( char *msg )
++{
++	if( verbose )
++		cout << msg  ;
++}
++
++void
++AnyOption::printVerbose( char ch )
++{
++	if( verbose )
++		cout << ch ;
++}
++
++bool
++AnyOption::hasOptions()
++{
++	return hasoptions;
++}
++
++void
++AnyOption::autoUsagePrint(bool _autousage)
++{
++	autousage = _autousage;
++}
++
++void
++AnyOption::useCommandArgs( int _argc, char **_argv )
++{
++	argc = _argc;
++	argv = _argv;
++	command_set = true;
++	appname = argv[0];
++	if(argc > 1) hasoptions = true;
++}
++
++void
++AnyOption::useFiileName( const char *_filename )
++{
++	filename = _filename;
++	file_set = true;
++}
++
++/*
++ * set methods for options 
++ */
++
++void
++AnyOption::setCommandOption( const char *opt )
++{
++	addOption( opt , COMMAND_OPT );
++	g_value_counter++;
++}
++
++void
++AnyOption::setCommandOption( char opt )
++{
++	addOption( opt , COMMAND_OPT );
++	g_value_counter++;
++}
++
++void
++AnyOption::setCommandOption( const char *opt , char optchar )
++{
++	addOption( opt , COMMAND_OPT );
++	addOption( optchar , COMMAND_OPT );
++	g_value_counter++;
++}
++
++void
++AnyOption::setCommandFlag( const char *opt )
++{
++	addOption( opt , COMMAND_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::setCommandFlag( char opt )
++{
++	addOption( opt , COMMAND_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::setCommandFlag( const char *opt , char optchar )
++{
++	addOption( opt , COMMAND_FLAG );
++	addOption( optchar , COMMAND_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFileOption( const char *opt )
++{
++	addOption( opt , FILE_OPT );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFileOption( char opt )
++{
++	addOption( opt , FILE_OPT );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFileOption( const char *opt , char optchar )
++{
++	addOption( opt , FILE_OPT );
++	addOption( optchar, FILE_OPT  );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFileFlag( const char *opt )
++{
++	addOption( opt , FILE_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFileFlag( char opt )
++{
++	addOption( opt , FILE_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFileFlag( const char *opt , char optchar )
++{
++	addOption( opt , FILE_FLAG );
++	addOption( optchar , FILE_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::setOption( const char *opt )
++{
++	addOption( opt , COMMON_OPT );
++	g_value_counter++;
++}
++
++void
++AnyOption::setOption( char opt )
++{
++	addOption( opt , COMMON_OPT );
++	g_value_counter++;
++}
++
++void
++AnyOption::setOption( const char *opt , char optchar )
++{
++	addOption( opt , COMMON_OPT );
++	addOption( optchar , COMMON_OPT );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFlag( const char *opt )
++{
++	addOption( opt , COMMON_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFlag( const char opt )
++{
++	addOption( opt , COMMON_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::setFlag( const char *opt , char optchar )
++{
++	addOption( opt , COMMON_FLAG );
++	addOption( optchar , COMMON_FLAG );
++	g_value_counter++;
++}
++
++void
++AnyOption::addOption( const char *opt, int type )
++{
++	if( option_counter >= max_options ){
++		if( doubleOptStorage() == false ){
++			addOptionError( opt );
++			return;
++		}
++	}
++	options[ option_counter ] = opt ;
++	optiontype[ option_counter ] =  type ;
++	optionindex[ option_counter ] = g_value_counter; 
++	option_counter++;
++}
++
++void
++AnyOption::addOption( char opt, int type )
++{
++	if( !POSIX() ){
++		printVerbose("Ignoring the option character \"");
++		printVerbose(  opt );
++		printVerbose( "\" ( POSIX options are turned off )" );
++		printVerbose();
++		return;
++	}
++
++
++	if( optchar_counter >= max_char_options ){
++		if( doubleCharStorage() == false ){
++			addOptionError( opt );
++			return;
++		}
++	}
++	optionchars[ optchar_counter ] =  opt ;
++	optchartype[ optchar_counter ] =  type ;
++	optcharindex[ optchar_counter ] = g_value_counter; 
++	optchar_counter++;
++}
++
++void
++AnyOption::addOptionError( const char *opt )
++{
++	cout << endl ;
++	cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
++	cout << "While adding the option : \""<< opt << "\"" << endl;
++	cout << "Exiting." << endl ;
++	cout << endl ;
++	exit(0);
++}
++
++void
++AnyOption::addOptionError( char opt )
++{
++	cout << endl ;
++	cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
++	cout << "While adding the option: \""<< opt << "\"" << endl;
++	cout << "Exiting." << endl ;
++	cout << endl ;
++	exit(0);
++}
++
++void
++AnyOption::processOptions()
++{
++	if( ! valueStoreOK() )
++		return;
++}
++
++void 
++AnyOption::processCommandArgs(int max_args)
++{
++	max_legal_args = max_args;
++	processCommandArgs();
++}
++ 
++void
++AnyOption::processCommandArgs( int _argc, char **_argv, int max_args )
++{
++	max_legal_args = max_args;
++	processCommandArgs(  _argc, _argv );
++}
++
++void
++AnyOption::processCommandArgs( int _argc, char **_argv )
++{
++	useCommandArgs( _argc, _argv );
++	processCommandArgs();
++}
++
++void
++AnyOption::processCommandArgs()
++{
++   	if( ! ( valueStoreOK() && CommandSet() )  )
++	   return;
++	   
++	if( max_legal_args == 0 )
++		max_legal_args = argc;
++	new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) );
++	for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */
++		if(  argv[i][0] == long_opt_prefix[0] && 
++                     argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */
++			int match_at = parseGNU( argv[i]+2 ); /* skip -- */
++			if( match_at >= 0 && i < argc-1 ) /* found match */
++				setValue( options[match_at] , argv[++i] );
++		}else if(  argv[i][0] ==  opt_prefix_char ) { /* POSIX char */
++			if( POSIX() ){ 
++				char ch =  parsePOSIX( argv[i]+1 );/* skip - */ 
++				if( ch != '0' && i < argc-1 ) /* matching char */
++					setValue( ch ,  argv[++i] );
++			} else { /* treat it as GNU option with a - */
++				int match_at = parseGNU( argv[i]+1 ); /* skip - */
++				if( match_at >= 0 && i < argc-1 ) /* found match */
++					setValue( options[match_at] , argv[++i] );
++			}
++		}else { /* not option but an argument keep index */
++			if( new_argc < max_legal_args ){
++                                new_argv[ new_argc ] = i ;
++                                new_argc++;
++                        }else{ /* ignore extra arguments */
++                                printVerbose( "Ignoring extra argument: " );
++				printVerbose( argv[i] );
++				printVerbose( );
++				printAutoUsage();
++                        }
++			printVerbose( "Unknown command argument option : " );
++			printVerbose( argv[i] );
++			printVerbose( );
++			printAutoUsage();
++		}
++	}
++}
++
++char 
++AnyOption::parsePOSIX( char* arg )
++{
++
++	for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ 
++		char ch = arg[i] ;
++		if( matchChar(ch) ) { /* keep matching flags till an option */
++			/*if last char argv[++i] is the value */
++			if( i == strlen(arg)-1 ){ 
++				return ch;
++			}else{/* else the rest of arg is the value */
++				i++; /* skip any '=' and ' ' */
++				while( arg[i] == whitespace 
++			    		|| arg[i] == equalsign )
++					i++;	
++				setValue( ch , arg+i );
++				return '0';
++			}
++		}
++	}
++	printVerbose( "Unknown command argument option : " );
++	printVerbose( arg );
++	printVerbose( );
++	printAutoUsage();
++	return '0';
++}
++
++int
++AnyOption::parseGNU( char *arg )
++{
++	int split_at = 0;
++	/* if has a '=' sign get value */
++	for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
++		if(arg[i] ==  equalsign ){
++			split_at = i ; /* store index */
++			i = strlen(arg); /* get out of loop */
++		}
++	}
++	if( split_at > 0 ){ /* it is an option value pair */
++		char* tmp = (char*) malloc(  (split_at+1)*sizeof(char) );
++		for( int i = 0 ; i < split_at ; i++ )
++			tmp[i] = arg[i];
++		tmp[split_at] = '\0';
++
++		if ( matchOpt( tmp ) >= 0 ){
++			setValue( options[matchOpt(tmp)] , arg+split_at+1 );
++			free (tmp);
++		}else{
++			printVerbose( "Unknown command argument option : " );
++			printVerbose( arg );
++			printVerbose( );
++			printAutoUsage();
++			free (tmp);
++			return -1;
++		}
++	}else{ /* regular options with no '=' sign  */
++		return  matchOpt(arg);
++	}
++	return -1;
++}
++
++
++int 
++AnyOption::matchOpt( char *opt )
++{
++	for( int i = 0 ; i < option_counter ; i++ ){
++		if( strcmp( options[i], opt ) == 0 ){
++			if( optiontype[i] ==  COMMON_OPT ||
++			    optiontype[i] ==  COMMAND_OPT )	
++			{ /* found option return index */
++				return i;
++			}else if( optiontype[i] == COMMON_FLAG ||
++			       optiontype[i] == COMMAND_FLAG )
++			{ /* found flag, set it */ 
++				setFlagOn( opt );
++				return -1;
++			}
++		}
++	}
++	printVerbose( "Unknown command argument option : " );
++	printVerbose( opt  ) ;
++	printVerbose( );
++	printAutoUsage();
++	return  -1;	
++}
++bool
++AnyOption::matchChar( char c )
++{
++	for( int i = 0 ; i < optchar_counter ; i++ ){
++		if( optionchars[i] == c ) { /* found match */
++			if(optchartype[i] == COMMON_OPT ||
++			     optchartype[i] == COMMAND_OPT )
++			{ /* an option store and stop scanning */
++				return true;	
++			}else if( optchartype[i] == COMMON_FLAG || 
++				  optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */
++				setFlagOn( c );
++				return false;
++			}
++		}
++	}
++	printVerbose( "Unknown command argument option : " );
++	printVerbose( c ) ;
++	printVerbose( );
++	printAutoUsage();
++	return false;
++}
++
++bool
++AnyOption::valueStoreOK( )
++{
++	int size= 0;
++	if( !set ){
++		if( g_value_counter > 0 ){
++			size = g_value_counter * sizeof(char*);
++			values = (char**)malloc( size );	
++			for( int i = 0 ; i < g_value_counter ; i++)
++				values[i] = NULL;
++			set = true;
++		}
++	}
++	return  set;
++}
++
++/*
++ * public get methods 
++ */
++char*
++AnyOption::getValue( const char *option )
++{
++	if( !valueStoreOK() )
++		return NULL;
++
++	for( int i = 0 ; i < option_counter ; i++ ){
++		if( strcmp( options[i], option ) == 0 )
++			return values[ optionindex[i] ];
++	}
++	return NULL;
++}
++
++bool
++AnyOption::getFlag( const char *option )
++{
++	if( !valueStoreOK() )
++		return false;
++	for( int i = 0 ; i < option_counter ; i++ ){
++		if( strcmp( options[i], option ) == 0 )
++			return findFlag( values[ optionindex[i] ] );
++	}
++	return false;
++}
++
++char*
++AnyOption::getValue( char option )
++{
++	if( !valueStoreOK() )
++		return NULL;
++	for( int i = 0 ; i < optchar_counter ; i++ ){
++		if( optionchars[i] == option )
++			return values[ optcharindex[i] ];
++	}
++	return NULL;
++}
++
++bool
++AnyOption::getFlag( char option )
++{
++	if( !valueStoreOK() )
++		return false;
++	for( int i = 0 ; i < optchar_counter ; i++ ){
++		if( optionchars[i] == option )
++			return findFlag( values[ optcharindex[i] ] ) ;
++	}
++	return false;
++}
++
++bool
++AnyOption::findFlag( char* val )
++{
++	if( val == NULL )
++		return false;
++
++	if( strcmp( TRUE_FLAG , val ) == 0 )
++		return true;
++
++	return false;
++}
++
++/*
++ * private set methods 
++ */
++bool
++AnyOption::setValue( const char *option , char *value )
++{
++	if( !valueStoreOK() )
++		return false;
++        for( int i = 0 ; i < option_counter ; i++ ){
++                if( strcmp( options[i], option ) == 0 ){
++                        values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
++                        strcpy( values[ optionindex[i] ], value );
++			return true;
++		}
++        }
++        return false;
++}
++
++bool
++AnyOption::setFlagOn( const char *option )
++{
++	if( !valueStoreOK() )
++		return false;
++        for( int i = 0 ; i < option_counter ; i++ ){
++                if( strcmp( options[i], option ) == 0 ){
++                        values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
++                        strcpy( values[ optionindex[i] ]  ,  TRUE_FLAG );
++			return true;
++		}
++        }
++        return false;
++}
++
++bool
++AnyOption::setValue( char option , char *value )
++{
++	if( !valueStoreOK() )
++		return false;
++        for( int i = 0 ; i < optchar_counter ; i++ ){
++                if( optionchars[i] == option ){
++                        values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
++                        strcpy( values[ optcharindex[i] ],  value );
++			return true;
++		}
++        }
++        return false;
++}
++
++bool
++AnyOption::setFlagOn( char option )
++{
++	if( !valueStoreOK() )
++		return false;
++        for( int i = 0 ; i < optchar_counter ; i++ ){
++                if( optionchars[i] == option ){
++                        values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
++			strcpy( values[ optcharindex[i] ] , TRUE_FLAG );
++			return true;
++		}
++        }
++        return false;
++}
++
++
++int
++AnyOption::getArgc( )
++{
++	return new_argc;
++}
++
++char* 
++AnyOption::getArgv( int index )
++{
++	if( index < new_argc ){
++		return ( argv[ new_argv[ index ] ] );
++	}
++	return NULL;
++}
++
++/* dotfile sub routines */
++
++bool
++AnyOption::processFile()
++{
++	if( ! (valueStoreOK() && FileSet())  )
++		return false;
++	return  ( consumeFile(readFile()) );
++}
++
++bool
++AnyOption::processFile( const char *filename )
++{
++	useFiileName(filename );
++	return ( processFile() );
++}
++
++char*
++AnyOption::readFile()
++{
++	return ( readFile(filename) );
++}
++
++/*
++ * read the file contents to a character buffer 
++ */
++
++char*
++AnyOption::readFile( const char* fname )
++{
++        int length;
++        char *buffer;
++        ifstream is;
++        is.open ( fname , ifstream::in );
++        if( ! is.good() ){
++                is.close();
++                return NULL;
++        }
++        is.seekg (0, ios::end);
++        length = is.tellg();
++        is.seekg (0, ios::beg);
++        buffer = (char*) malloc(length*sizeof(char));
++        is.read (buffer,length);
++        is.close();
++        return buffer;
++}
++
++/*
++ * scans a char* buffer for lines that does not 
++ * start with the specified comment character.
++ */
++bool
++AnyOption::consumeFile( char *buffer )
++{
++
++        if( buffer == NULL ) 
++		return false;
++
++       	char *cursor = buffer;/* preserve the ptr */
++       	char *pline = NULL ;
++       	int linelength = 0;
++       	bool newline = true;
++       	for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){
++       	if( *cursor == endofline ) { /* end of line */
++          	if( pline != NULL ) /* valid line */
++               		processLine( pline, linelength );
++                 	pline = NULL;
++                 	newline = true;
++           	}else if( newline ){ /* start of line */
++                 	newline = false;
++              		if( (*cursor != comment ) ){ /* not a comment */
++		    		pline = cursor ;
++                    		linelength = 0 ;
++                	}
++             	}
++            	cursor++; /* keep moving */
++            	linelength++;
++       	}
++     	free (buffer);
++	return true;
++}
++
++
++/*
++ *  find a valid type value pair separated by a delimiter 
++ *  character and pass it to valuePairs()
++ *  any line which is not valid will be considered a value
++ *  and will get passed on to justValue()
++ *
++ *  assuming delimiter is ':' the behaviour will be,
++ *
++ *  width:10    - valid pair valuePairs( width, 10 );
++ *  width : 10  - valid pair valuepairs( width, 10 );
++ *
++ *  ::::        - not valid 
++ *  width       - not valid
++ *  :10         - not valid 
++ *  width:      - not valid  
++ *  ::          - not valid 
++ *  :           - not valid 
++ *  
++ */
++
++void
++AnyOption::processLine( char *theline, int length  )
++{
++        bool found = false;
++        char *pline = (char*) malloc( (length+1)*sizeof(char) );
++        for( int i = 0 ; i < length ; i ++ )
++                pline[i]= *(theline++);
++        pline[length] = nullterminate;
++        char *cursor = pline ; /* preserve the ptr */
++        if( *cursor == delimiter || *(cursor+length-1) == delimiter ){
++                justValue( pline );/* line with start/end delimiter */
++        }else{
++                for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */
++                        if( *cursor == delimiter ){
++                                *(cursor-1) = nullterminate; /* two strings */
++                                found = true;
++                                valuePairs( pline , cursor+1 );
++                        }
++                        cursor++;
++                }
++                cursor++;
++                if( !found ) /* not a pair */
++                        justValue( pline );
++        }
++        free (pline);
++}
++
++/*
++ * removes trailing and preceeding whitespaces from a string
++ */
++char*
++AnyOption::chomp( char *str )
++{
++        while( *str == whitespace )
++                str++;
++        char *end = str+strlen(str)-1;
++        while( *end == whitespace )
++                end--;
++        *(end+1) = nullterminate;
++        return str;
++}
++
++void
++AnyOption::valuePairs( char *type, char *value )
++{
++	if ( strlen(chomp(type)) == 1  ){ /* this is a char option */
++		for( int i = 0 ; i < optchar_counter ; i++ ){
++			if(  optionchars[i] == type[0]  ){ /* match */
++				if( optchartype[i] == COMMON_OPT ||
++				    optchartype[i] == FILE_OPT )
++				{
++			 		setValue( type[0] , chomp(value) );
++			 		return;
++				}
++			}
++		}
++	}	
++	/* if no char options matched */
++	for( int i = 0 ; i < option_counter ; i++ ){
++		if( strcmp( options[i], type ) == 0 ){ /* match */
++			if( optiontype[i] == COMMON_OPT ||
++			    optiontype[i] == FILE_OPT )
++			{
++		 		setValue( type , chomp(value) );
++		 		return;
++			}
++		}
++	}
++        printVerbose( "Unknown option in resourcefile : " );
++	printVerbose( type );
++	printVerbose( );
++}
++
++void
++AnyOption::justValue( char *type )
++{
++
++	if ( strlen(chomp(type)) == 1  ){ /* this is a char option */
++		for( int i = 0 ; i < optchar_counter ; i++ ){
++			if(  optionchars[i] == type[0]  ){ /* match */
++				if( optchartype[i] == COMMON_FLAG ||
++				    optchartype[i] == FILE_FLAG )
++				{
++			 		setFlagOn( type[0] );
++			 		return;
++				}
++			}
++		}
++	}	
++	/* if no char options matched */
++	for( int i = 0 ; i < option_counter ; i++ ){
++		if( strcmp( options[i], type ) == 0 ){ /* match */
++			if( optiontype[i] == COMMON_FLAG ||
++			    optiontype[i] == FILE_FLAG )
++			{
++		 		setFlagOn( type );
++		 		return;
++			}
++		}
++	}
++        printVerbose( "Unknown option in resourcefile : " );
++	printVerbose( type  );
++	printVerbose( );
++}
++
++/*
++ * usage and help 
++ */
++
++
++void
++AnyOption::printAutoUsage()
++{
++	if( autousage ) printUsage();
++}
++
++void
++AnyOption::printUsage()
++{
++	
++	if( once ) {
++		once = false ;
++		cout << endl ;
++		for( int i = 0 ; i < usage_lines ; i++ )
++			cout << usage[i] << endl ;	
++		cout << endl ;
++	}
++}
++	
++	
++void
++AnyOption::addUsage( const char *line )
++{
++	if( usage_lines >= max_usage_lines ){
++		if( doubleUsageStorage() == false ){
++			addUsageError( line );
++			exit(1);
++		}
++	}
++	usage[ usage_lines ] = line ;	
++	usage_lines++;
++}
++
++void
++AnyOption::addUsageError( const char *line )
++{
++	cout << endl ;
++	cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
++	cout << "While adding the usage/help  : \""<< line << "\"" << endl;
++	cout << "Exiting." << endl ;
++	cout << endl ;
++	exit(0);
++
++}
++
diff --git a/debian/patches/features/fix-tangotest-string-image b/debian/patches/features/tango-admin-pkg
similarity index 54%
copy from debian/patches/features/fix-tangotest-string-image
copy to debian/patches/features/tango-admin-pkg
index 67564bb..452b3cb 100644
--- a/debian/patches/features/fix-tangotest-string-image
+++ b/debian/patches/features/tango-admin-pkg
@@ -26,14 +26,38 @@ Forwarded: <no|not-needed|url proving that it has been forwarded>
 Reviewed-By: <name and email of someone who approved the patch>
 Last-Update: <YYYY-MM-DD>
 
---- tango-7.1.1~dfsg.orig/cppserver/tangotest/TangoTest.cpp
-+++ tango-7.1.1~dfsg/cppserver/tangotest/TangoTest.cpp
-@@ -1081,7 +1081,7 @@ void TangoTest::write_string_image(Tango
-   {
-     for (i = 0; i < dimXStringImage; i++)
-     {
--      str_index = i + j * dimYStringImage;
-+      str_index = i + j * dimXStringImage;
-       CORBA::string_free(attr_string_image_read[str_index]);
-       attr_string_image_read[str_index] = CORBA::string_dup(p[str_index]);
-     }
+--- tango-7.1.1~dfsg.orig/configure.in
++++ tango-7.1.1~dfsg/configure.in
+@@ -413,6 +413,7 @@ AC_OUTPUT(Makefile
+ 	  cppserver/tangoaccesscontrol/Makefile
+ 	  utils/Makefile
+ 	  utils/notifd2db/Makefile
++	  utils/tango_admin/Makefile
+ 	  scripts/Makefile
+ 	  scripts/jive
+ 	  scripts/logviewer
+--- tango-7.1.1~dfsg.orig/utils/Makefile.am
++++ tango-7.1.1~dfsg/utils/Makefile.am
+@@ -1,2 +1,2 @@
+ 
+-SUBDIRS = notifd2db 
++SUBDIRS = notifd2db tango_admin
+--- /dev/null
++++ tango-7.1.1~dfsg/utils/tango_admin/Makefile.am
+@@ -0,0 +1,16 @@
++INCLUDES = -I$(top_srcdir)/lib/cpp/client \
++	   -I$(top_srcdir)/lib/cpp/server $(ORB_INCLUDE_PREFIX) \
++           -I$(top_srcdir)/lib/cpp/log4tango/include \
++           -I$(top_builddir)/lib/cpp/log4tango/include
++
++LDADD = -L$(top_builddir)/lib/cpp/server -ltango \
++        -L$(top_builddir)/lib/cpp/log4tango/src -llog4tango
++
++bin_PROGRAMS=tango_admin
++
++tango_admin_SOURCES=\
++	tango_admin.cpp \
++	anyoption.cpp \
++	anyoption.h
++
++
diff --git a/debian/patches/series b/debian/patches/series
index 69e56ff..cc35b89 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,5 +1,8 @@
 debian/fix_database_scripts.diff -p1
 debian/my.cnf.in.diff -p1
-debian/starter-mysql.in.diff -p1
+debian/starter -p1
+debian/tango-admin -p1
+debian/notify_daemon -p1
 features/fix_libtango_compilation.diff -p1
 features/fix-tangotest-string-image -p1
+features/tango-admin-pkg -p1
diff --git a/debian/rules b/debian/rules
index 59a377d..1ca1c59 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,34 +1,44 @@
 #!/usr/bin/make -f
 
+BUILDROOT=build
+
+get-orig-source:
+	uscan --verbose --force-download
+
 override_dh_auto_configure:
-	dh_auto_configure -- --with-omni=/usr --disable-dbcreate --disable-java
+	mkdir -p "$(CURDIR)/$(BUILDROOT)"
+	for f in "$(CURDIR)"/*; do cp -arf "$$f" "$(CURDIR)/$(BUILDROOT)/"; done
+	cd "$(CURDIR)/$(BUILDROOT)" && autoreconf -fi -I m4
+	cd "$(CURDIR)/$(BUILDROOT)" && dh_auto_configure -- --with-omni=/usr --disable-dbcreate --disable-java
+
+override_dh_auto_clean:
+	rm -rf "$(CURDIR)/$(BUILDROOT)"
 
-override_dh_clean:
-	rm -f config.log
-	rm -f ac_config.h
-	rm -f ac_config.h.old
-	dh_clean
+override_dh_auto_build:
+	cd "$(CURDIR)/$(BUILDROOT)" && dh_auto_build
+
+override_dh_auto_install:
+	cd "$(CURDIR)/$(BUILDROOT)" && dh_auto_install --destdir="$(CURDIR)/debian/tmp/"
 
 override_dh_auto_install:
 	# install dbconfig-common scripts
 	install -d debian/tmp/usr/share/dbconfig-common/data/tango-db/install
-	install -p -m 644 cppserver/database/create_db.sql debian/tmp/usr/share/dbconfig-common/data/tango-db/install/mysql
+	install -p -m 644 $(CURDIR)/$(BUILDROOT)/cppserver/database/create_db.sql debian/tmp/usr/share/dbconfig-common/data/tango-db/install/mysql
 	# install scripts used during the configuration
 	install -d debian/tmp/usr/share/tango-db
-	install -p -m 644 cppserver/database/create_db_tables.sql debian/tmp/usr/share/tango-db/create_db_tables.sql
-	install -p -m 644 cppserver/database/stored_proc.sql debian/tmp/usr/share/tango-db/stored_proc.sql
-	install -p -m 600 cppserver/database/my.cnf debian/tmp/usr/share/tango-db/my.cnf
-	# template for the starter installation
-	install -d debian/tmp/usr/share/tango-starter
-	install -p -m 600 cppserver/starter/mysql.in debian/tmp/usr/share/tango-starter/mysql.in
-	dh_auto_install
+	install -p -m 644 $(CURDIR)/$(BUILDROOT)/cppserver/database/create_db_tables.sql debian/tmp/usr/share/tango-db/create_db_tables.sql
+	install -p -m 644 $(CURDIR)/$(BUILDROOT)/cppserver/database/stored_proc.sql debian/tmp/usr/share/tango-db/stored_proc.sql
+	install -p -m 600 $(CURDIR)/$(BUILDROOT)/cppserver/database/my.cnf debian/tmp/usr/share/tango-db/my.cnf
+	cd "$(CURDIR)/$(BUILDROOT)" && dh_auto_install --destdir="$(CURDIR)/debian/tmp/"
 
 override_dh_strip:
 	dh_strip -plibtango7 --dbg-package=libtango7-dbg
 	dh_strip -pliblog4tango4 --dbg-package=liblog4tango4-dbg
 	dh_strip -ptango-test --dbg-package=tango-test-dbg
-	dh_strip -a -Nlibtango7 -Nliblog4tango4 -Ntango-starter
+	dh_strip -a -Nlibtango7 -Nliblog4tango4 -Ntango-test
 
 %:
 	dh $@
 
+.PHONY: get-orig-source
+
diff --git a/debian/tango-accesscontrol.init.d b/debian/tango-accesscontrol.init.d
index 843c1a2..f02bf51 100644
--- a/debian/tango-accesscontrol.init.d
+++ b/debian/tango-accesscontrol.init.d
@@ -64,7 +64,7 @@ do_stop()
 	#   1 if daemon was already stopped
 	#   2 if daemon could not be stopped
 	#   other if a failure occurred
-	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON
+	start-stop-daemon --stop --quiet --retry=TERM/5/KILL/5 --pidfile $PIDFILE --exec $DAEMON
 	RETVAL="$?"
 	[ "$RETVAL" = 2 ] && return 2
 	# Wait for children to finish too if this is a daemon that forks
@@ -73,7 +73,7 @@ do_stop()
 	# that waits for the process to drop all resources that could be
 	# needed by services started subsequently.  A last resort is to
 	# sleep for some time.
-	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	start-stop-daemon --stop --quiet --oknodo --retry=0/5/KILL/5 --exec $DAEMON
 	[ "$?" = 2 ] && return 2
 	# Many daemons don't delete their pidfiles when they exit.
 	rm -f $PIDFILE
diff --git a/debian/tango-common.install b/debian/tango-common.install
new file mode 100644
index 0000000..6c6d3ee
--- /dev/null
+++ b/debian/tango-common.install
@@ -0,0 +1 @@
+usr/bin/tango_admin usr/lib/tango
\ No newline at end of file
diff --git a/debian/tango-starter.config b/debian/tango-starter.config
deleted file mode 100644
index 95d1f1e..0000000
--- a/debian/tango-starter.config
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-# config maintainer script for foo-mysql
-
-set -e
-
-# source debconf stuff
-. /usr/share/debconf/confmodule
-
-# source dbconfig-common shell library, and call the hook function
-if [ -f /usr/share/dbconfig-common/dpkg/config.mysql ]; then
-  dbc_dbname="tango"
-  dbc_dbuser="tango"
-  . /usr/share/dbconfig-common/dpkg/config.mysql 
-  dbc_go tango-starter $@
-fi
diff --git a/debian/tango-starter.init.d b/debian/tango-starter.init.d
index c5a5fde..96b5003 100644
--- a/debian/tango-starter.init.d
+++ b/debian/tango-starter.init.d
@@ -14,7 +14,7 @@
 
 # Author: Picca Frédéric-Emmanuel <picca at synchrotron-soleil.fr>
 
-PATH=/sbin:/usr/sbin:/bin:/usr/bin
+PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/lib/tango
 DESC="Tango Control System - starter"
 NAME=tango-starter
 NAME_REAL=Starter
@@ -42,7 +42,13 @@ do_start()
 	# Return
 	#   0 if daemon has been started
 	#   1 if daemon was already running
-	#   2 if daemon could not be started
+        #   2 if daemon could not be started
+
+        # first check for a running tango-database and
+        tango_admin --ping-database || return 2
+        #register the tango-starter if necessary
+	tango_admin --check-device tango/admin/`hostname` || tango_admin --add-server Starter/`hostname` Starter tango/admin/`hostname` || return 2
+
 	start-stop-daemon --start --quiet --chuid tango:tango --background \
 	    --make-pidfile --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
 	    || return 1
diff --git a/debian/tango-starter.install b/debian/tango-starter.install
index d31e28a..c344bec 100644
--- a/debian/tango-starter.install
+++ b/debian/tango-starter.install
@@ -1,3 +1,3 @@
 usr/bin/Starter usr/lib/tango
-usr/share/tango-starter
-usr/bin/notify_daemon usr/lib/tango
\ No newline at end of file
+usr/bin/notify_daemon usr/lib/tango
+usr/bin/notifd2db usr/lib/tango
\ No newline at end of file
diff --git a/debian/tango-starter.postinst b/debian/tango-starter.postinst
deleted file mode 100644
index 3a76b58..0000000
--- a/debian/tango-starter.postinst
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-set -e
-
-#first generate the right template for dbconfig-common
-mkdir -p /usr/share/dbconfig-common/data/tango-starter/install
-hostname | xargs -I HOSTNAME sed -e 's/\_hostname\_/HOSTNAME/g' /usr/share/tango-starter/mysql.in > /usr/share/dbconfig-common/data/tango-starter/install/mysql
-
-. /usr/share/debconf/confmodule
-. /usr/share/dbconfig-common/dpkg/postinst.mysql
-
-dbc_go tango-starter $@
-
-#DEBHELPER#
diff --git a/debian/tango-starter.postrm b/debian/tango-starter.postrm
deleted file mode 100644
index 2516102..0000000
--- a/debian/tango-starter.postrm
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-set -e
-
-if [ -f /usr/share/debconf/confmodule ]; then
-  . /usr/share/debconf/confmodule
-fi
-if [ -f /usr/share/dbconfig-common/dpkg/postrm.mysql ]; then
-  . /usr/share/dbconfig-common/dpkg/postrm.mysql
-  dbc_go tango-starter $@
-fi
-
-if [ "$1" = "purge" ]; then
-  rm -f /usr/share/dbconfig-common/data/tango-starter/install/mysql
-fi
-
-#DEBHELPER#
diff --git a/debian/tango-starter.prerm b/debian/tango-starter.prerm
deleted file mode 100644
index a570aed..0000000
--- a/debian/tango-starter.prerm
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-set -e
-
-. /usr/share/debconf/confmodule
-. /usr/share/dbconfig-common/dpkg/prerm.mysql 
-dbc_go tango-starter $@
-
-#DEBHELPER#

-- 
UNNAMED PROJECT



More information about the debian-science-commits mailing list