[Nut-upsdev] [PATCH 09/36] first cut at fixing the insanity of using perl and python scripts to parse C sources and generate new header files

Greg A. Woods woods at planix.com
Thu Mar 8 23:21:20 UTC 2012


From: "Greg A. Woods" <woods at planix.com>

nut-scanner currently compiles using two header files which are built
from information in some of the C sources of various drivers.  This is
kinda bogus, but worst of all was how these headers were generated.

I've entirely deprecated the Python script that parsed drivers/*-mib.c
files to generate tools/nut-scanner/nutscan-snmp.h.  That header is now
generated by a magic new option to the snmp-ups driver itself.  This is
a temporary solution as it is not friendly to cross-compilation.
Ultimately the *-mib.c files, and the table they are linked together
with, should be moved to common code which both the driver and
nut-scanner can link directly with.

The generation of tools/nut-scanner/nutscan-usb.h has been moved into
the tools/nut-scanner/Makefile.am for now and made to run only when one
of the drivers/*_usb.c files changes (which depends on use of GNU Make),
though it too should be entirely eliminated as above.
---
 drivers/snmp-ups.c            |   47 +++++++++++++++++++++++++++++++++
 drivers/snmp-ups.h            |    1 +
 tools/Makefile.am             |   58 +++--------------------------------------
 tools/nut-scanner/.gitignore  |    5 ++--
 tools/nut-scanner/Makefile.am |   38 ++++++++++++++++++++++++---
 tools/nut-usbinfo.pl          |   12 ++++-----
 6 files changed, 95 insertions(+), 66 deletions(-)

diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c
index 3722d34..12eff77 100644
--- a/drivers/snmp-ups.c
+++ b/drivers/snmp-ups.c
@@ -89,6 +89,7 @@ const char *mibname;
 const char *mibvers;
 
 static void disable_transfer_oids(void);
+static void dump_nutscanner_snmp(void);
 
 #define DRIVER_NAME	"Generic SNMP UPS driver"
 #define DRIVER_VERSION		"0.66"
@@ -248,6 +249,7 @@ void upsdrv_makevartable(void)
 		"Set the authentication protocol (MD5 or SHA) used for authenticated SNMPv3 messages (default=MD5)");
 	addvar(VAR_VALUE, SU_VAR_PRIVPROT,
 		"Set the privacy protocol (DES or AES) used for encrypted SNMPv3 messages (default=DES)");
+	addvar(VAR_FLAG, SU_VAR_MAGIC, "Run the secret magic header dumper");
 }
 
 void upsdrv_initups(void)
@@ -259,6 +261,11 @@ void upsdrv_initups(void)
 
 	upsdebugx(1, "SNMP UPS driver : entering upsdrv_initups()");
 
+	if (testvar(SU_VAR_MAGIC)) {
+		dump_nutscanner_snmp();
+		exit(0);
+	}
+
 	/* Retrieve user's parameters */
 	mibs = testvar(SU_VAR_MIBS) ? getval(SU_VAR_MIBS) : "auto";
 
@@ -1667,8 +1674,48 @@ void su_shutdown_ups(void)
 	}
 }
 
+static void dump_nutscanner_snmp()
+{
+	int i;
+
+	printf("/*\n");
+	printf(" * nutscan-snmp.h\n");
+	printf(" *\n");
+	printf(" * WARNING!!!  This file was automatically generated by snmp-ups!\n");
+	printf(" */\n");
+	printf("\n");
+	printf("#ifndef DEVSCAN_SNMP_H\n");
+	printf("#define DEVSCAN_SNMP_H\n");
+	printf("\n");
+	printf("typedef struct {\n");
+	printf("\tchar   *oid;\n");
+	printf("\tchar   *mib;\n");
+	printf("\tchar   *sysoid;\n");
+	printf("} snmp_device_id_t;\n");
+	printf("\n");
+	printf("/* SNMP IDs device table */\n");
+	printf("static snmp_device_id_t snmp_device_table[] = {\n");
+
+	/* Now, iterate on mib2nut definitions */
+	for (i = 0; mib2nut[i] != NULL; i++) {
+		printf("\t{ \"%s\", \"%s\", %s%s%s},\n",
+		       mib2nut[i]->oid_auto_check,
+		       mib2nut[i]->mib_name,
+		       mib2nut[i]->sysOID ? "\"" : "",
+		       mib2nut[i]->sysOID ? mib2nut[i]->sysOID : "NULL",
+		       mib2nut[i]->sysOID ? "\"" : "");
+	}
+
+	printf("\t/* Terminating entry */\n");
+	printf("\t{ NULL, NULL, NULL}\n");
+	printf("};\n" );
+	printf("#endif /* DEVSCAN_SNMP_H */\n");
+}
+
+
 /* FIXME: the below functions can be removed since these were for loading
  * the mib2nut information from a file instead of the .h definitions... */
+/* XXX maybe that's not a good idea -- it would be nice to have data-driven MIB info again! */
 /* return 1 if usable, 0 if not */
 static int parse_mibconf_args(int numargs, char **arg)
 {
diff --git a/drivers/snmp-ups.h b/drivers/snmp-ups.h
index 60fcc5d..802da9e 100644
--- a/drivers/snmp-ups.h
+++ b/drivers/snmp-ups.h
@@ -179,6 +179,7 @@ typedef struct {
 #define SU_VAR_PRIVPASSWD	"privPassword"
 #define SU_VAR_AUTHPROT		"authProtocol"
 #define SU_VAR_PRIVPROT		"privProtocol"
+#define SU_VAR_MAGIC		"magic"
 
 
 #define SU_INFOSIZE		128
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 88ee285..4f6ae38 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,51 +1,13 @@
 # TODO: remove redundancies!
 
-# XXX this does not work with Automake!!!
-#
-# In fact the very concept is entirely antithetical to Automake.
-#
-# SUBDIRS are explicitly a listing of all the directories that make
-# must recurse into BEFORE processing the current directory.
-#
-# These python scripts must be moved into a sub-directory, and _only_
-# executed IFF they need to be, and all the nut-scanner sources need
-# to be moved out of a sub-directory into this directory.
-#
-# Force build in ./ before nut-scanner, to have nutscan-{usb,snmp}.h
-# built before going into the nut-scanner sub-directory
-#
-#SUBDIRS = . nut-scanner
 SUBDIRS = nut-scanner
 
 EXTRA_DIST = nut-usbinfo.pl nut-hclinfo.py device-recorder.sh svn2cl.authors nut-snmpinfo.py
 
-all: nut-scanner-deps 
-
-# XXX these rules are all bogus!  They cause un-named target files to
-# always be rebuilt!  None of that is ever the right way to use make,
-# and especially not Automake.  Explicit filenames and their exact
-# dependencies need to be properly listed.
-
-nut-scanner-deps:
-	@if python -c 1; then \
-		echo "Regenerating the SNMP helper files."; \
-		$(top_srcdir)/tools/nut-snmpinfo.py; \
-	else \
-		echo "----------------------------------------------------------------------"; \
-		echo "Warning: Python is not available."; \
-		echo "Skipping the SNMP helper files regeneration."; \
-		echo "----------------------------------------------------------------------"; \
-	fi
-
-	@if perl -e 1; then \
-		echo "Regenerating the USB helper files."; \
-		$(top_srcdir)/tools/nut-usbinfo.pl; \
-	else \
-		echo "----------------------------------------------------------------------"; \
-		echo "Warning: Perl is not available."; \
-		echo "Skipping the USB helper files regeneration."; \
-		echo "----------------------------------------------------------------------"; \
-	fi
+# XXX this rules is bogus!  It causes un-named target files to always
+# be rebuilt!  That is never the right way to use make, and especially
+# not Automake.  Explicit filenames and their exact dependencies need
+# to be properly listed.
 
 website:
 	@if python -c "import json,simplejson,lxml"; then \
@@ -60,20 +22,8 @@ website:
 	fi
 
 # call the USB info script upon "make dist", and if Perl is present
-# call the SNMP info script upon "make dist", and if Python is present
-# and call both for building nut-scanner
 # also generate HCL data files
 dist-hook:
-	@if python -c 1; then \
-		echo "Regenerating the SNMP helper files."; \
-		$(distdir)/nut-snmpinfo.py; \
-	else \
-		echo "----------------------------------------------------------------------"; \
-		echo "Warning: Python is not available."; \
-		echo "Skipping the SNMP helper files regeneration."; \
-		echo "----------------------------------------------------------------------"; \
-	fi
-
 	@if perl -e 1; then \
 		echo "Regenerating the USB helper files."; \
 		$(distdir)/nut-usbinfo.pl; \
diff --git a/tools/nut-scanner/.gitignore b/tools/nut-scanner/.gitignore
index a7d477c..c849817 100644
--- a/tools/nut-scanner/.gitignore
+++ b/tools/nut-scanner/.gitignore
@@ -1,11 +1,12 @@
-/*.o
 /*.la
 /*.lo
+/*.o
 /.deps
+/.libs
 /Makefile
 /Makefile.in
 /nut-scanner
 /nutscan-snmp.h
 /nutscan-usb.h
 /test-nutscan
-/.libs
+/ups.conf
diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am
index d4066d2..a734fdc 100644
--- a/tools/nut-scanner/Makefile.am
+++ b/tools/nut-scanner/Makefile.am
@@ -1,7 +1,38 @@
 BUILT_SOURCES = nutscan-usb.h nutscan-snmp.h
 
-nutscan-usb.h nutscan-snmp.h:
-	cd ..; $(MAKE) $(AM_MAKEFLAGS) nut-scanner-deps
+# This may be problematical -- hosts without perl but with USB do exist
+#
+# There must be a better way -- perhaps similar to how nutscan-snmp.h
+# is now created...
+#
+nutscan-usb.h: $(top_srcdir)/drivers/*_usb.c
+	@if perl -e 1; then \
+		echo "Regenerating the USB helper files."; \
+		$(top_srcdir)/tools/nut-usbinfo.pl; \
+	else \
+		echo "----------------------------------------------------------------------"; \
+		echo "Warning: Perl is not available."; \
+		echo "Skipping the USB helper files generation."; \
+		echo "Assuming WITH_USB is not going to be defined at build time."; \
+		echo "----------------------------------------------------------------------"; \
+	fi
+
+# XXX note this will not work for cross-compiles!
+#
+# (see the old ../nut-snmpinfo.py as a hint to how this header could
+# be cross-built -- consider rewriting this toool to link directly
+# with the ../drivers/*-mib.o files, and some new module that would
+# contain the mib2nut table, so that this header is not needed)
+#
+nutscan-snmp.h: ups.conf
+	@NUT_CONFPATH=. ../../drivers/snmp-ups -a nut-scanner -x magic | sed 1d > $(@).tmp
+	@cmp -s $(@).tmp $(@) > /dev/null 2>&1 || mv $(@).tmp $(@)
+	@rm -f $(@).tmp
+
+ups.conf:
+	@echo "[nut-scanner]" > $@
+	@echo "	driver = snmp-ups" >> $@
+	@echo "	port = 127.0.0.1" >> $@
 
 # Only build nut-scanner, and its library, if libltdl was found (required!)
 if WITH_LIBLTDL
@@ -47,5 +78,4 @@ else
  dist_noinst_HEADERS += nut-scan.h nutscan-device.h nutscan-ip.h nutscan-init.h
 endif
 
-CLEANFILES = nutscan-usb.h nutscan-snmp.h
-
+CLEANFILES = nutscan-usb.h nutscan-snmp.h ups.conf
diff --git a/tools/nut-usbinfo.pl b/tools/nut-usbinfo.pl
index 7833086..bd74bf8 100755
--- a/tools/nut-usbinfo.pl
+++ b/tools/nut-usbinfo.pl
@@ -25,26 +25,26 @@ use File::Find;
 use strict;
 
 # path to scan for USB_DEVICE pattern
-my $scanPath="../drivers";
+my $scanPath="../../drivers";
 
 # HAL output file
-my $outputHAL="../scripts/hal/ups-nut-device.fdi.in";
+my $outputHAL="../../scripts/hal/ups-nut-device.fdi.in";
 
 # Hotplug output file
-my $outputHotplug="../scripts/hotplug/libhid.usermap";
+my $outputHotplug="../../scripts/hotplug/libhid.usermap";
 
 # udev output file
-my $outputUdev="../scripts/udev/nut-usbups.rules.in";
+my $outputUdev="../../scripts/udev/nut-usbups.rules.in";
 
 # UPower output file
-my $outputUPower="../scripts/upower/95-upower-hid.rules";
+my $outputUPower="../../scripts/upower/95-upower-hid.rules";
 # tmp output, to allow generating the ENV{UPOWER_VENDOR} header list
 my $tmpOutputUPower;
 # mfr header flag
 my $upowerMfrHeaderDone = 0;
 
 # NUT device scanner - C header
-my $outputDevScanner = "./nut-scanner/nutscan-usb.h";
+my $outputDevScanner = "./nutscan-usb.h";
 
 my $GPL_header = "\
  *  Copyright (C) 2011 - Arnaud Quette <arnaud.quette\@free.fr>\
-- 
1.7.9.2




More information about the Nut-upsdev mailing list